Subversion Repositories NedoOS

Rev

Rev 2368 | Blame | Compare with Previous | Last modification | View Log | Download

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <oscalls.h>
  5. #include <osfs.h>
  6. #include <intrz80.h>
  7. #include <../common/terminal.c>
  8. #include <tcp.h>
  9. /////////////
  10. #define true 1
  11. #define false 0
  12.  
  13. unsigned int RBR_THR = 0xf8ef;
  14. unsigned int IER = 0xf9ef;
  15. unsigned int IIR_FCR = 0xfaef;
  16. unsigned int LCR = 0xfbef;
  17. unsigned int MCR = 0xfcef;
  18. unsigned int LSR = 0xfdef;
  19. unsigned int MSR = 0xfeef;
  20. unsigned int SR = 0xffef;
  21. unsigned int divider = 1;
  22. unsigned int comType = 0;
  23. unsigned int espType = 32;
  24. unsigned int espRetry = 5;
  25. unsigned long factor, timerok;
  26.  
  27. unsigned char picture[15000];
  28. unsigned char netbuf[5000];
  29. unsigned char curPath[128];
  30.  
  31. unsigned char minRating[] = "0000000000";
  32. struct fileStruct
  33. {
  34.   long picId;
  35.   unsigned int picYear;
  36.   unsigned long totalAmount;
  37.   unsigned int httpErr;
  38.   unsigned int extStatus;
  39.   unsigned char picRating[8];
  40.   unsigned char picName[256];
  41.   unsigned char picType[64];
  42.   unsigned char authorIds[64];
  43.   unsigned char authorTitle[64];
  44.   unsigned char authorRealName[64];
  45.   unsigned char afn[128];
  46.   unsigned char pfn[128];
  47.   unsigned char fileName[128];
  48. } curFileStruct;
  49.  
  50. struct window
  51. {
  52.   unsigned char x;
  53.   unsigned char y;
  54.   unsigned char w;
  55.   unsigned char h;
  56.   unsigned char text;
  57.   unsigned char back;
  58.   unsigned char tittle[80];
  59. } curWin;
  60.  
  61. struct sockaddr_in dnsaddress;
  62. struct sockaddr_in targetadr;
  63. struct readstructure readStruct;
  64.  
  65. unsigned char ver[] = "4.6";
  66. const unsigned char sendOk[] = "SEND OK";
  67. const unsigned char gotWiFi[] = "WIFI GOT IP";
  68. unsigned char buffer[] = "0000000000";
  69. unsigned char userAgent[] = " HTTP/1.1\r\nHost: zxart.ee\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE5.01; NedoOS; GetPic)\r\n\r\n\0";
  70. unsigned char zxart[] = "zxart.ee";
  71. unsigned char keypress, verbose, randomPic, slideShow, netDriver;
  72.  
  73. unsigned long contLen;
  74. unsigned long count = 0;
  75. unsigned int headlng;
  76. unsigned int slideShowTime = 0;
  77. unsigned int loaded;
  78.  
  79. unsigned char crlf[2] = {13, 10};
  80. unsigned char cmd[512];
  81. unsigned char link[512];
  82. unsigned char fileIdChar[10];
  83.  
  84. void clearStatus(void)
  85. {
  86. }
  87. /*
  88. void writeLog(const char *logline, char *place)
  89. {
  90.   FILE *LogFile;
  91.   unsigned long fileSize;
  92.   unsigned char toLog[512];
  93.  
  94.   LogFile = OS_OPENHANDLE("m:/getpic.log", 0x80);
  95.   if (((int)LogFile) & 0xff)
  96.   {
  97.     LogFile = OS_CREATEHANDLE("m:/getpic.log", 0x80);
  98.     OS_CLOSEHANDLE(LogFile);
  99.     LogFile = OS_OPENHANDLE("m:/getpic.log", 0x80);
  100.   }
  101.  
  102.   fileSize = OS_GETFILESIZE(LogFile);
  103.   OS_SEEKHANDLE(LogFile, fileSize);
  104.  
  105.   sprintf(toLog, "%6lu : %s : %s\r\n", time(), place, logline);
  106.   OS_WRITEHANDLE(toLog, LogFile, strlen(toLog));
  107.   OS_CLOSEHANDLE(LogFile);
  108. }
  109. */
  110. void emptyKeys(void)
  111. {
  112.   unsigned char loop = 0, key;
  113.   do
  114.   {
  115.     key = OS_GETKEY();
  116.     if (loop > 64)
  117.     {
  118.       break;
  119.     }
  120.     loop++;
  121.   } while (key != 0);
  122. }
  123.  
  124. void waitKey(void)
  125. {
  126.   do
  127.   {
  128.     YIELD();
  129.   } while (OS_GETKEY() == 0);
  130. }
  131.  
  132. unsigned char delayLongKey(unsigned long counter)
  133. {
  134.   unsigned long start, finish, key;
  135.   counter = counter / 20;
  136.   if (counter < 1)
  137.   {
  138.     counter = 1;
  139.   }
  140.   start = time();
  141.   finish = start + counter;
  142.  
  143.   while (start < finish)
  144.   {
  145.     start = time();
  146.     key = OS_GETKEY();
  147.     if (key != 0)
  148.     {
  149.       return key;
  150.     }
  151.     YIELD();
  152.   }
  153.   return 32;
  154. }
  155.  
  156. void spaces(unsigned char number)
  157. {
  158.   while (number > 0)
  159.   {
  160.     putchar(' ');
  161.     number--;
  162.   }
  163. }
  164. void quit(void)
  165. {
  166.   OS_CLS(0);
  167.   OS_SETGFX(-1);
  168.   exit(0);
  169. }
  170. /*
  171. void infoBox(struct window w, const char *message)
  172. {
  173.   unsigned char wcount, tempx, tittleStart;
  174.  
  175.   w.h++;
  176.   OS_SETXY(w.x, w.y - 1);
  177.   BDBOX(w.x, w.y, w.w + 1, w.h, w.back, 32);
  178.   OS_SETXY(w.x, w.y);
  179.   OS_SETCOLOR(w.text);
  180.   putchar(201);
  181.   for (wcount = 0; wcount < w.w; wcount++)
  182.   {
  183.     putchar(205);
  184.   }
  185.   putchar(187);
  186.   OS_SETXY(w.x, w.y + w.h);
  187.   putchar(200);
  188.   for (wcount = 0; wcount < w.w; wcount++)
  189.   {
  190.     putchar(205);
  191.   }
  192.   putchar(188);
  193.  
  194.   tempx = w.x + w.w + 1;
  195.   for (wcount = 1; wcount < w.h; wcount++)
  196.   {
  197.     OS_SETXY(w.x, w.y + wcount);
  198.     putchar(186);
  199.     OS_SETXY(tempx, w.y + wcount);
  200.     putchar(186);
  201.   }
  202.   tittleStart = w.x + (w.w / 2) - (strlen(w.tittle) / 2);
  203.   OS_SETXY(tittleStart, w.y);
  204.   printf("[%s]", w.tittle);
  205.  
  206.   OS_SETXY(w.x + 1, w.y + 1);
  207.   OS_SETCOLOR(w.back);
  208.   tittleStart = w.x + (w.w / 2) - (strlen(message) / 2);
  209.   OS_SETXY(tittleStart, w.y + 1);
  210.   printf("%s", message);
  211. }
  212. */
  213. void printHelp(void)
  214. {
  215.   OS_SETCOLOR(67);
  216.   printf("   GETPIC [%s] zxart.ee picture viewer for nedoNET\n\r", ver);
  217.   OS_SETCOLOR(6);
  218.   printf("-------------------------------------------------------\n\r");
  219.   printf(" Управление:\n\r");
  220.   printf(" 'ESC' - выход из программы;\n\r");
  221.   printf(" '<-' или 'B' к последним картинкам;\n\r");
  222.   printf(" '->' или 'Пробел' к более старым картинкам\n\r");
  223.   printf(" 'J' Прыжок на  указанную по счету картинку\n\r");
  224.   printf(" 'I' Просмотр экрана информации о картинках\n\r");
  225.   printf(" 'S' Сохранить картинку на диск в текущую папку\n\r");
  226.   printf(" 'V' не выводить информацию об авторах\n\r");
  227.   printf(" 'R' переход в режим  случайная картинка с рейтингом 4+\n\r");
  228.   printf(" 'A' переход в режим  слайд-шоу\n\r");
  229.   printf(" 'D' Переключение режима ZXNETUSB/ESP-COM\n\r");
  230.   printf(" 'T' Продолжительность одного слайда в int-ах \n\r");
  231.   printf(" 'M' Минимальный рейтинг для случайного воспроизведения. \n\r");
  232.   printf(" 'H' Данная справочная информация\n\r");
  233.   printf("-----------------Нажмите любую кнопку------------------\n\r");
  234.   printf("[Build:%s  %s]",__DATE__, __TIME__);
  235.   OS_SETCOLOR(70);
  236.   keypress = getchar();
  237.   OS_CLS(0);
  238. }
  239.  
  240. void delay(unsigned long counter)
  241. {
  242.   unsigned long start, finish;
  243.   counter = counter / 20;
  244.   if (counter < 1)
  245.   {
  246.     counter = 1;
  247.   }
  248.   start = time();
  249.   finish = start + counter;
  250.  
  251.   while (start < finish)
  252.   {
  253.     start = time();
  254.   }
  255. }
  256.  
  257. ///////////////////////////
  258. #include <../common/esp-com.c>
  259. #include <../common/network.c>
  260. //////////////////////////
  261.  
  262. int testOperation2(const char *process, int socket)
  263. {
  264.   if (socket < 0)
  265.   {
  266.     printf("%s: [ERROR:", process);
  267.     errorPrint(-socket);
  268.     printf("]\r\n");
  269.     YIELD();
  270.     return -socket;
  271.   }
  272.   return 1;
  273. }
  274.  
  275. int cutHeader(unsigned int todo)
  276. {
  277.   unsigned char *count1;
  278.  
  279.   curFileStruct.httpErr = httpError();
  280.   if (curFileStruct.httpErr != 200)
  281.   {
  282.     clearStatus();
  283.  
  284.     // writeLog("HTTP error ", "cutHeader      ");
  285.     // writeLog(netbuf, "cutHeader      ");
  286.     // writeLog("---+++---", "cutHeader      ");
  287.  
  288.     printf("HTTP response:[%u]\r\n", curFileStruct.httpErr);
  289.     puts(netbuf);
  290.     puts("---+++---");
  291.     waitKey();
  292.     return 0;
  293.   }
  294.   count1 = strstr(netbuf, "Content-Length:");
  295.   if (count1 == NULL)
  296.   {
  297.     clearStatus();
  298.     printf("contLen not found");
  299.     contLen = 0;
  300.     curFileStruct.httpErr = 999; // bad kostil
  301.     return 0;
  302.   }
  303.   contLen = atol(count1 + 15);
  304.   // printf("Content-Length: %lu \n\r", contLen);
  305.  
  306.   count1 = strstr(netbuf, "\r\n\r\n");
  307.   if (count1 == NULL)
  308.   {
  309.     clearStatus();
  310.     printf("end of header not found\r\n");
  311.   }
  312.   else
  313.   {
  314.     headlng = ((unsigned int)count1 - (unsigned int)netbuf + 4);
  315.     // printf("header %u bytes\r\n", headlng);
  316.   }
  317.   return todo - headlng;
  318. }
  319.  
  320. char *str_replace(char *dst, int num, const char *str, const char *orig, const char *rep)
  321. {
  322.   const char *ptr;
  323.   size_t len1 = strlen(orig);
  324.   size_t len2 = strlen(rep);
  325.   char *tmp = dst;
  326.  
  327.   num -= 1;
  328.   while ((ptr = strstr(str, orig)) != NULL)
  329.   {
  330.     num -= (ptr - str) + len2;
  331.     if (num < 1)
  332.       break;
  333.  
  334.     strncpy(dst, str, (size_t)(ptr - str));
  335.     dst += ptr - str;
  336.     strncpy(dst, rep, len2);
  337.     dst += len2;
  338.     str = ptr + len1;
  339.   }
  340.  
  341.   for (; (*dst = *str) && (num > 0); --num)
  342.   {
  343.     ++dst;
  344.     ++str;
  345.   }
  346.   return tmp;
  347. }
  348.  
  349. char fillPictureEsp(void)
  350. {
  351.   unsigned char sizeLink;
  352.   unsigned long downloaded;
  353.   unsigned char countl;
  354.   unsigned int todo;
  355.   const unsigned char *count1;
  356.   unsigned char firstPacket;
  357.   unsigned int byte;
  358.   strcpy(link, netbuf);
  359.   sizeLink = strlen(link);
  360.   do
  361.   {
  362.     sendcommand("AT+CIPSTART=\"TCP\",\"zxart.ee\",80");
  363.     getAnswer3(); // CONNECT or ERROR or link is not valid
  364.     count1 = strstr(netbuf, "CONNECT");
  365.   } while (count1 == NULL);
  366.  
  367.   getAnswer3();                                   // OK
  368.   sprintf(netbuf, "AT+CIPSEND=%u", sizeLink + 2); // second CRLF in send command
  369.   sendcommand(netbuf);
  370.   getAnswer3();
  371.   do
  372.   {
  373.  
  374.     byte = uartReadBlock();
  375.     if (byte > 255)
  376.     {
  377.       // writeLog("uartReadBlock(); receiving timeout [1]", "fillPictureEsp ");
  378.       return false;
  379.     }
  380.  
  381.     // putchar(byte);
  382.   } while (byte != '>');
  383.   sendcommand(link);
  384.   countl = 0;
  385.   do
  386.   {
  387.     byte = uartReadBlock();
  388.     if (byte > 255)
  389.     {
  390.       // writeLog("uartReadBlock(); receiving timeout [2]", "fillPictureEsp ");
  391.       return false;
  392.     }
  393.  
  394.     if (byte == sendOk[countl])
  395.     {
  396.       countl++;
  397.     }
  398.     else
  399.     {
  400.       countl = 0;
  401.     }
  402.   } while (countl < strlen(sendOk));
  403.   // writeLog("sendOk - OK", "fillPictureEsp ");
  404.   byte = uartReadBlock(); // CR
  405.   if (byte > 255)
  406.   {
  407.     // writeLog("uartReadBlock(); receiving timeout  [3]", "fillPictureEsp ");
  408.     return false;
  409.   }
  410.   byte = uartReadBlock(); // LF
  411.   if (byte > 255)
  412.   {
  413.     // writeLog("uartReadBlock(); receiving timeout  [4]", "fillPictureEsp ");
  414.     return false;
  415.   }
  416.   downloaded = 0;
  417.   firstPacket = true;
  418.   do
  419.   {
  420.     headlng = 0;
  421.     todo = recvHead();
  422.  
  423.     if (!getdataEsp(todo))
  424.     {
  425.       OS_CLS(0);
  426.       printf("[getdataEsp] Downloading timeout. Exit![%lu]\r\n", count);
  427.       waitKey();
  428.       exit(0);
  429.     }
  430.  
  431.     if (firstPacket)
  432.     {
  433.       todo = cutHeader(todo);
  434.       firstPacket = false;
  435.       if (curFileStruct.httpErr != 200)
  436.       {
  437.         sendcommand("AT+CIPCLOSE");
  438.         uartFlush(200);
  439.         return false;
  440.       }
  441.     }
  442.  
  443.     if (downloaded + todo > sizeof(picture))
  444.     {
  445.       printf("dataBuffer overrun... %u reached \n\r", downloaded + todo);
  446.       return false;
  447.     }
  448.     memcpy(picture + downloaded, netbuf + headlng, todo);
  449.     downloaded = downloaded + todo;
  450.   } while (downloaded < contLen);
  451.   sendcommand("AT+CIPCLOSE");
  452.   getAnswer3(); // CLOSED or ERROR
  453.   count1 = strstr(netbuf, "CLOSED");
  454.   if (count1 != NULL)
  455.   {
  456.     getAnswer3(); // OK
  457.   }
  458.   // writeLog("Data downloaded", "fillPictureEsp ");
  459.   return true;
  460. }
  461.  
  462. char fillPictureNet(void)
  463. {
  464.   int todo;
  465.   unsigned int downloaded = 0;
  466.   unsigned char firstPacket;
  467.   char socket, retry;
  468.   picture[0] = 0;
  469.   retry = 3;
  470.   socket = OpenSock(AF_INET, SOCK_STREAM);
  471.   if (testOperation2("OS_NETSOCKET", socket) != 1)
  472.   {
  473.     getchar();
  474.     quit();
  475.   }
  476.   todo = netConnect(socket, retry);
  477.   if (testOperation2("OS_NETCONNECT", todo) != 1)
  478.   {
  479.     getchar();
  480.     quit();
  481.   }
  482.   todo = tcpSend(socket, (unsigned int)&netbuf, strlen(netbuf), retry);
  483.   if (testOperation2("OS_WIZNETWRITE", todo) != 1)
  484.   {
  485.     getchar();
  486.     quit();
  487.   }
  488.   firstPacket = true;
  489.   do
  490.   {
  491.     headlng = 0;
  492.     todo = tcpRead(socket, retry);
  493.     testOperation("OS_WIZNETREAD", todo); // Quit if too many retries
  494.  
  495.     if (firstPacket)
  496.     {
  497.       todo = cutHeader(todo);
  498.       firstPacket = false;
  499.       if (curFileStruct.httpErr != 200)
  500.       {
  501.         netShutDown(socket, 0);
  502.         return false;
  503.       }
  504.     }
  505.  
  506.     if (downloaded + todo > sizeof(picture))
  507.     {
  508.       printf("dataBuffer overrun... %u reached \n\r", downloaded + todo);
  509.       return false;
  510.     }
  511.     memcpy(picture + downloaded, netbuf + headlng, todo);
  512.     downloaded = downloaded + todo;
  513.   } while (downloaded != contLen);
  514.  
  515.   netShutDown(socket, 0);
  516.   picture[downloaded + 1] = 0;
  517.   return true;
  518. }
  519.  
  520. void nameRepair(unsigned char *pfn, unsigned int tfnSize)
  521. {
  522.  
  523.   str_replace(pfn, tfnSize, pfn, "\\", "_");
  524.   str_replace(pfn, tfnSize, pfn, "/", "_");
  525.   str_replace(pfn, tfnSize, pfn, ":", "_");
  526.   str_replace(pfn, tfnSize, pfn, "*", "_");
  527.   str_replace(pfn, tfnSize, pfn, "?", "_");
  528.   str_replace(pfn, tfnSize, pfn, "<", "_");
  529.   str_replace(pfn, tfnSize, pfn, ">", "_");
  530.   str_replace(pfn, tfnSize, pfn, "|", "_");
  531.   str_replace(pfn, tfnSize, pfn, " ", "_");
  532.   str_replace(pfn, tfnSize, pfn, "&#039;", "'");
  533.   str_replace(pfn, tfnSize, pfn, "&amp;", "&");
  534.   str_replace(pfn, tfnSize, pfn, "&quot;", "'");
  535.   str_replace(pfn, tfnSize, pfn, "&gt;", ")");
  536.   str_replace(pfn, tfnSize, pfn, "&lt;", "(");
  537.   str_replace(pfn, tfnSize, pfn, "\"", "'");
  538. }
  539.  
  540. void stringRepair(unsigned char *pfn, unsigned int tSize)
  541. {
  542.   str_replace(pfn, tSize, pfn, "&#039;", "'");
  543.   str_replace(pfn, tSize, pfn, "&amp;", "&");
  544.   str_replace(pfn, tSize, pfn, "&gt;", ">");
  545.   str_replace(pfn, tSize, pfn, "&lt;", "<");
  546.   str_replace(pfn, tSize, pfn, "&quot;", "\"");
  547.   str_replace(pfn, tSize, pfn, "\\/", "/");
  548. }
  549.  
  550. void ncReplace(void)
  551. {
  552.   unsigned char len;
  553.   for (len = 0; len < strlen(curFileStruct.afn); len++)
  554.   {
  555.     if ((curFileStruct.afn[len] < ' ') || (curFileStruct.afn[len] > 0xf1) || (curFileStruct.afn[len] > 0xb0 && curFileStruct.afn[len] < 0xdf))
  556.     {
  557.       curFileStruct.afn[len] = '_';
  558.     }
  559.   }
  560.  
  561.   for (len = 0; len < strlen(curFileStruct.pfn); len++)
  562.   {
  563.     if ((curFileStruct.pfn[len] < ' ') || (curFileStruct.pfn[len] > 0xef) || (curFileStruct.pfn[len] > 0xb0 && curFileStruct.pfn[len] < 0xdf))
  564.     {
  565.       curFileStruct.pfn[len] = '_';
  566.     }
  567.   }
  568. }
  569.  
  570. unsigned char savePic(unsigned long fileId)
  571. {
  572.   FILE *fp2;
  573.   unsigned char afnSize, tfnSize;
  574.  
  575.   afnSize = sizeof(curFileStruct.afn) - 1;
  576.   tfnSize = sizeof(curFileStruct.pfn) - 1;
  577.  
  578.   strcpy(curFileStruct.afn, curFileStruct.authorTitle);
  579.   nameRepair(curFileStruct.afn, afnSize);
  580.  
  581.   strcpy(curFileStruct.pfn, curFileStruct.picName);
  582.   nameRepair(curFileStruct.pfn, tfnSize);
  583.  
  584.   ncReplace();
  585.  
  586.   sprintf(curFileStruct.fileName, "%s-%s-%ld.scr", curFileStruct.afn, curFileStruct.pfn, fileId);
  587.   if (strlen(curFileStruct.fileName) > 62)
  588.   {
  589.     sprintf(fileIdChar, "-%ld", fileId);
  590.     str_replace(curFileStruct.fileName, sizeof(curFileStruct.fileName) - 1, curFileStruct.fileName, fileIdChar, "");
  591.     curFileStruct.fileName[50] = '\0';
  592.     strcat(curFileStruct.fileName, fileIdChar);
  593.     strcat(curFileStruct.fileName, ".scr");
  594.   }
  595.   OS_SETSYSDRV();
  596.   OS_MKDIR("../downloads");        // Create if not exist
  597.   OS_MKDIR("../downloads/getpic"); // Create if not exist
  598.   OS_CHDIR("../downloads/getpic");
  599.   fp2 = OS_CREATEHANDLE(curFileStruct.fileName, 0x80);
  600.   if (((int)fp2) & 0xff)
  601.   {
  602.     printf("%s creating error\r\n", curFileStruct.fileName);
  603.     getchar();
  604.     quit();
  605.   }
  606.   OS_WRITEHANDLE(picture, fp2, 6912);
  607.   OS_CLOSEHANDLE(fp2);
  608.   return 0;
  609. }
  610.  
  611. int pos(unsigned char *s, unsigned char *c, unsigned int n, unsigned int startPos)
  612. {
  613.   unsigned int i, j;
  614.   unsigned int lenC, lenS;
  615.  
  616.   for (lenC = 0; c[lenC]; lenC++)
  617.     ;
  618.   for (lenS = 0; s[lenS]; lenS++)
  619.     ;
  620.  
  621.   for (i = startPos; i <= lenS - lenC; i++)
  622.   {
  623.     for (j = 0; s[i + j] == c[j]; j++)
  624.       ;
  625.  
  626.     if (j - lenC == 1 && i == lenS - lenC && !(n - 1))
  627.       return i;
  628.     if (j == lenC)
  629.       if (n - 1)
  630.         n--;
  631.       else
  632.         return i;
  633.   }
  634.   return -1;
  635. }
  636.  
  637. const char *parseJson(unsigned char *property)
  638. {
  639.   unsigned int w, lng, lngp1, findEnd, listPos;
  640.   unsigned char terminator;
  641.   int n;
  642.   // n = -1;
  643.   //  netbuf[0] = '\0';
  644.   n = pos(picture, property, 1, 0);
  645.   if (n == -1)
  646.   {
  647.     strcpy(netbuf, "-");
  648.     // printf("Property %s not found", property);
  649.     return netbuf;
  650.   }
  651.   lng = n - 1 + strlen(property);
  652.   if (picture[lng] == ':')
  653.   {
  654.     terminator = 0;
  655.   }
  656.   if (picture[lng] == '\"')
  657.   {
  658.     terminator = '\"';
  659.   }
  660.   if (picture[lng] == '[')
  661.   {
  662.     terminator = ']';
  663.   }
  664.  
  665.   findEnd = 1;
  666.   lngp1 = lng + 1;
  667.  
  668.   while (42)
  669.   {
  670.  
  671.     if ((picture[lngp1 + findEnd] == ','))
  672.     {
  673.       if (terminator == 0)
  674.       {
  675.         break;
  676.       }
  677.       if ((picture[lng + findEnd] == terminator))
  678.       {
  679.         findEnd--;
  680.         break;
  681.       }
  682.     }
  683.     findEnd++;
  684.   }
  685.   listPos = 0;
  686.   for (w = lngp1; w < findEnd + lngp1; w++)
  687.   {
  688.     netbuf[listPos] = picture[w];
  689.     listPos++;
  690.   }
  691.   netbuf[listPos] = 0;
  692.   return netbuf;
  693. }
  694.  
  695. void convert866(void)
  696. {
  697.   unsigned int lng, targetPos, w, q = 0;
  698.   unsigned char bufferl[8], one, two;
  699.   unsigned int decVal;
  700.   lng = strlen(netbuf);
  701.   targetPos = lng + 1;
  702.  
  703.   while (q < lng)
  704.   {
  705.     one = netbuf[q];
  706.     two = netbuf[q + 1];
  707.     if (one == 92 && two == 117)
  708.     {
  709.       q = q + 2;
  710.       for (w = 0; w < 4; w++)
  711.       {
  712.         bufferl[w] = netbuf[q + w];
  713.       }
  714.       q = q + 4;
  715.       bufferl[4] = '\0';
  716.       decVal = (unsigned int)strtol(bufferl, NULL, 16);
  717.  
  718.       if (decVal < 1088)
  719.       {
  720.         decVal = decVal - 912;
  721.       }
  722.       if (decVal > 1087)
  723.       {
  724.         decVal = decVal - 864;
  725.       }
  726.       if (decVal == 1025)
  727.       {
  728.         decVal = 240;
  729.       }
  730.       if (decVal == 1105)
  731.       {
  732.         decVal = 241;
  733.       }
  734.  
  735.       netbuf[targetPos] = decVal;
  736.     }
  737.     else
  738.     {
  739.       netbuf[targetPos] = netbuf[q];
  740.       q++;
  741.     }
  742.     targetPos++;
  743.   }
  744.   netbuf[targetPos] = 0;
  745.  
  746.   for (w = lng + 1; w < targetPos + 1; w++)
  747.   {
  748.     netbuf[w - lng - 1] = netbuf[w];
  749.   }
  750. }
  751.  
  752. long processJson(unsigned long startPos, unsigned char limit, unsigned char queryNum)
  753. {
  754.   unsigned int tSize;
  755.   const unsigned char *count1;
  756.   unsigned char result;
  757.   switch (queryNum)
  758.   {
  759.   case 0:
  760.     sprintf(netbuf, "GET /api/export:zxPicture/filter:zxPictureType=standard/limit:%u/start:%lu/order:date,desc%s", limit, startPos, userAgent);
  761.     break;
  762.   case 1:
  763.     sprintf(netbuf, "GET /api/types:zxPicture/export:zxPicture/language:eng/start:0/limit:1/order:rand/filter:zxPictureMinRating=%s;zxPictureType=standard%s", minRating, userAgent);
  764.     break;
  765.   case 99: // GET /jsonElementData/elementId:182798
  766.     sprintf(netbuf, "GET /jsonElementData/elementId:%lu%s", startPos, userAgent);
  767.     break;
  768.   }
  769.  
  770.   switch (netDriver)
  771.   {
  772.   case 0:
  773.     result = fillPictureNet();
  774.     break;
  775.   case 1:
  776.     result = fillPictureEsp();
  777.     break;
  778.   }
  779.  
  780.   if (!result)
  781.   {
  782.     return -1;
  783.   }
  784.  
  785.   count1 = strstr(picture, "responseStatus\":\"success");
  786.   if (count1 == NULL)
  787.   {
  788.     OS_CLS(0);
  789.     OS_SETCOLOR(66);
  790.     puts("Picture[]:");
  791.     puts(picture);
  792.     puts("---------------");
  793.     printf("PROCESS JSON: [ERROR: Bad responseStatus.] [Query:%u][Pic:%lu]\r\n", queryNum, startPos);
  794.     YIELD();
  795.     getchar();
  796.     return -1;
  797.   }
  798.  
  799.   count1 = strstr(picture, "\"id\":");
  800.   if (count1 == NULL)
  801.   {
  802.     parseJson("\"totalAmount\":");
  803.  
  804.     if (atol(netbuf) == 0)
  805.     {
  806.       return -3;
  807.     }
  808.  
  809.     if (netbuf[0] != '-')
  810.     {
  811.       return -4;
  812.     }
  813.     OS_CLS(0);
  814.     OS_SETCOLOR(66);
  815.     puts("Picture[]:");
  816.     puts(picture);
  817.     puts("---------------");
  818.     printf("PROCESS JSON: [ERROR: ID not found.] [Query:%u][Pic:%lu]\r\n", queryNum, startPos);
  819.     YIELD();
  820.     return -2;
  821.   }
  822.   netbuf[0] = 0;
  823.  
  824.   switch (queryNum)
  825.   {
  826.   case 0:
  827.   case 1:
  828.     parseJson("\"id\":");
  829.     curFileStruct.picId = atol(netbuf);
  830.     parseJson(",\"title\":\"");
  831.     convert866();
  832.     strcpy(curFileStruct.picName, netbuf);
  833.     tSize = sizeof(curFileStruct.picName);
  834.     stringRepair(curFileStruct.picName, tSize);
  835.  
  836.     parseJson(",\"type\":\"");
  837.     strcpy(curFileStruct.picType, netbuf);
  838.     parseJson("\"rating\":\"");
  839.     strcpy(curFileStruct.picRating, netbuf);
  840.     parseJson("\"year\":\"");
  841.     curFileStruct.picYear = atoi(netbuf);
  842.     parseJson("\"totalAmount\":");
  843.     curFileStruct.totalAmount = atol(netbuf);
  844.     parseJson("\"authorIds\":[");
  845.     strcpy(curFileStruct.authorIds, netbuf);
  846.     break;
  847.   case 99: // Author info
  848.     parseJson(",\"title\":\"");
  849.     convert866();
  850.     strcpy(curFileStruct.authorTitle, netbuf);
  851.     parseJson(",\"realName\":\"");
  852.     convert866();
  853.     strcpy(curFileStruct.authorRealName, netbuf);
  854.     break;
  855.   }
  856.   return curFileStruct.picId;
  857. }
  858.  
  859. void printData(void)
  860. {
  861.   OS_SETCOLOR(70);
  862.   printf(" #: ");
  863.   OS_SETCOLOR(71);
  864.   printf("%lu", count);
  865.   OS_SETCOLOR(70);
  866.   printf(" ID: ");
  867.   OS_SETCOLOR(71);
  868.   printf("%lu ", curFileStruct.picId);
  869.   OS_SETCOLOR(70);
  870.   printf(" Total Pics: ");
  871.   OS_SETCOLOR(71);
  872.   printf("%lu\r\n", curFileStruct.totalAmount);
  873.   OS_SETCOLOR(70);
  874.   printf(" Author: ");
  875.   OS_SETCOLOR(69);
  876.   printf("%s\r\n", curFileStruct.authorTitle);
  877.   OS_SETCOLOR(70);
  878.   printf(" TITLE: ");
  879.   OS_SETCOLOR(67);
  880.   printf("%s\r\n", curFileStruct.picName);
  881.   OS_SETCOLOR(70);
  882.   printf(" RATING: ");
  883.   OS_SETCOLOR(71);
  884.   printf("%s", curFileStruct.picRating);
  885.   OS_SETCOLOR(70);
  886.   printf(" YEAR: ");
  887.   OS_SETCOLOR(71);
  888.   printf("%u\r\n", curFileStruct.picYear);
  889.   OS_SETCOLOR(70);
  890.   printf(" AuthorsIDs ");
  891.   OS_SETCOLOR(71);
  892.   printf("%s", curFileStruct.authorIds);
  893.   OS_SETCOLOR(70);
  894.   printf(" Real name: ");
  895.   OS_SETCOLOR(71);
  896.   printf("%s\r\n", curFileStruct.authorRealName);
  897.   OS_SETCOLOR(69);
  898.   printf("\r\n");
  899.   printf("\r\n");
  900.  
  901.   OS_SETCOLOR(70);
  902.  
  903.   OS_SETCOLOR(70);
  904.   printf(" Query: ");
  905.   OS_SETCOLOR(71);
  906.   if (randomPic)
  907.   {
  908.     printf("Random pic with %s+ rating\r\n", minRating);
  909.   }
  910.   else
  911.   {
  912.     puts("Sequental from newest");
  913.   }
  914.   OS_SETCOLOR(70);
  915.   printf(" Mode : ");
  916.   OS_SETCOLOR(71);
  917.  
  918.   if (slideShow)
  919.   {
  920.     printf("Slide-show, %u ints \r\n", slideShowTime);
  921.   }
  922.   else
  923.   {
  924.     puts("Manual show");
  925.   }
  926.  
  927.   // YIELD();
  928. }
  929.  
  930. unsigned char inputBox(struct window w, const char *prefilled)
  931. {
  932.   unsigned char wcount, tempx, tittleStart;
  933.   unsigned char byte, counter;
  934.   w.h++;
  935.   OS_SETXY(w.x, w.y - 1);
  936.   BDBOX(w.x, w.y, w.w + 1, w.h, w.back, 32);
  937.   OS_SETXY(w.x, w.y);
  938.   OS_SETCOLOR(w.text);
  939.   putchar(201);
  940.   for (wcount = 0; wcount < w.w; wcount++)
  941.   {
  942.     putchar(205);
  943.   }
  944.   putchar(187);
  945.   OS_SETXY(w.x, w.y + w.h);
  946.   putchar(200);
  947.   for (wcount = 0; wcount < w.w; wcount++)
  948.   {
  949.     putchar(205);
  950.   }
  951.   putchar(188);
  952.  
  953.   tempx = w.x + w.w + 1;
  954.   for (wcount = 1; wcount < w.h; wcount++)
  955.   {
  956.     OS_SETXY(w.x, w.y + wcount);
  957.     putchar(186);
  958.     OS_SETXY(tempx, w.y + wcount);
  959.     putchar(186);
  960.   }
  961.   tittleStart = w.x + (w.w / 2) - (strlen(w.tittle) / 2);
  962.   OS_SETXY(tittleStart, w.y);
  963.   printf("[%s]", w.tittle);
  964.   OS_SETXY(w.x + 1, w.y + 1);
  965.   OS_SETCOLOR(w.back);
  966.   putchar(219);
  967.  
  968.   cmd[0] = 0;
  969.  
  970.   counter = strlen(prefilled);
  971.   if (counter != 0)
  972.   {
  973.     strcpy(cmd, prefilled);
  974.     goto skipKeys;
  975.   }
  976.  
  977.   do
  978.   {
  979.     byte = OS_GETKEY();
  980.     if (byte != 0)
  981.     {
  982.       switch (byte)
  983.       {
  984.       case 0x08:
  985.         if (counter > 0)
  986.         {
  987.           counter--;
  988.           cmd[counter] = 0;
  989.         }
  990.         break;
  991.       case 0x0d:
  992.  
  993.         if (counter == 0)
  994.         {
  995.           return false;
  996.         }
  997.         else
  998.         {
  999.           return true;
  1000.         }
  1001.  
  1002.       case 31:
  1003.         break;
  1004.       case 250:
  1005.         break;
  1006.       case 249:
  1007.         break;
  1008.       case 248:
  1009.         break;
  1010.       case 251: // Right
  1011.         break;
  1012.       case 252: // Del
  1013.         OS_SETXY(w.x + 1, w.y + 1);
  1014.         spaces(counter + 1);
  1015.         cmd[0] = 0;
  1016.         counter = 0;
  1017.         break;
  1018.       case 27:
  1019.         cmd[0] = 0;
  1020.         return false;
  1021.       default:
  1022.         if (counter < w.w - 1)
  1023.         {
  1024.           cmd[counter] = byte;
  1025.           counter++;
  1026.           cmd[counter] = 0;
  1027.         }
  1028.         break;
  1029.       }
  1030.     skipKeys:
  1031.       OS_SETXY(w.x + 1, w.y + 1);
  1032.       printf("%s", cmd);
  1033.       putchar(219);
  1034.       if (byte == 0x08)
  1035.       {
  1036.         putchar(' ');
  1037.       }
  1038.     }
  1039.     YIELD();
  1040.   } while (42);
  1041.   return false;
  1042. }
  1043.  
  1044. void safeKeys(unsigned char keypress)
  1045. {
  1046.   switch (keypress)
  1047.   {
  1048.   case 27:
  1049.     OS_SETCOLOR(70);
  1050.     printf("Good bye...\r\n");
  1051.     delayLong(500);
  1052.     quit();
  1053.     break;
  1054.   case 'j':
  1055.   case 'J':
  1056.     curWin.w = 13;
  1057.     curWin.x = 80 / 2 - curWin.w / 2 - 2;
  1058.     curWin.y = 11;
  1059.     curWin.h = 1;
  1060.     curWin.text = 103;
  1061.     curWin.back = 103;
  1062.     strcpy(curWin.tittle, "# of pic:");
  1063.     if (inputBox(curWin, ""))
  1064.     {
  1065.       sscanf(cmd, "%lu", &count);
  1066.       if (count > curFileStruct.totalAmount - 1)
  1067.       {
  1068.         count = curFileStruct.totalAmount - 1;
  1069.       }
  1070.     }
  1071.     break;
  1072.   case 't':
  1073.   case 'T':
  1074.     curWin.w = 20;
  1075.     curWin.x = 80 / 2 - curWin.w / 2 - 2;
  1076.     curWin.y = 11;
  1077.     curWin.h = 1;
  1078.     curWin.text = 103;
  1079.     curWin.back = 103;
  1080.     strcpy(curWin.tittle, "Slide time(ints)");
  1081.     if (inputBox(curWin, ""))
  1082.     {
  1083.       sscanf(cmd, "%u", &slideShowTime);
  1084.       if (slideShowTime == 0)
  1085.       {
  1086.         slideShowTime = 1;
  1087.       }
  1088.       OS_CLS(0);
  1089.       OS_SETCOLOR(70);
  1090.       printf("Slide duration set to %u ints.", slideShowTime);
  1091.       delayLong(500);
  1092.     }
  1093.     break;
  1094.   case 'v':
  1095.   case 'V':
  1096.     verbose = !verbose;
  1097.  
  1098.     if (verbose == 0)
  1099.     {
  1100.       BOX(1, 1, 80, 25, 40, ' ');
  1101.       AT(1, 1);
  1102.     }
  1103.     break;
  1104.   case 'h':
  1105.   case 'H':
  1106.     printHelp();
  1107.     break;
  1108.   case 'r':
  1109.   case 'R':
  1110.     randomPic = !randomPic;
  1111.     OS_SETCOLOR(70);
  1112.     if (verbose == 1)
  1113.     {
  1114.       if (randomPic == 1)
  1115.       {
  1116.         printf("    Random mode enabled...\r\n");
  1117.         count = 0;
  1118.         delayLong(500);
  1119.       }
  1120.       else
  1121.       {
  1122.         printf("    Sequental mode enabled...\r\n");
  1123.         count = 0;
  1124.         delayLong(500);
  1125.       }
  1126.     }
  1127.     break;
  1128.   case 'a':
  1129.   case 'A':
  1130.     slideShow = !slideShow;
  1131.     OS_SETCOLOR(70);
  1132.     if (slideShow == 1)
  1133.     {
  1134.       if (verbose == 1)
  1135.         printf("    SlideShow mode enabled...\r\n\r\n");
  1136.       slideShowTime = 150;
  1137.       delayLong(500);
  1138.     }
  1139.     else
  1140.     {
  1141.       if (verbose == 1)
  1142.         printf("    Manual mode enabled...\r\n\r\n");
  1143.       slideShowTime = 0;
  1144.       delayLong(500);
  1145.     }
  1146.     break;
  1147.   case 'd':
  1148.   case 'D':
  1149.     netDriver = !netDriver;
  1150.     OS_SETCOLOR(70);
  1151.     if (netDriver == 1)
  1152.     {
  1153.       printf("    ESP-COM mode enabled...\r\n");
  1154.       loadEspConfig();
  1155.       uart_init(divider);
  1156.       espReBoot();
  1157.       printf("    ESP-COM inited...\r\n");
  1158.       delayLong(500);
  1159.     }
  1160.     else
  1161.     {
  1162.       if (verbose == 1)
  1163.         printf("    NedoNET mode enabled...");
  1164.       delayLong(500);
  1165.     }
  1166.     break;
  1167.   case 'm':
  1168.   case 'M':
  1169.     curWin.w = 22;
  1170.     curWin.x = 80 / 2 - curWin.w / 2 - 2;
  1171.     curWin.y = 1;
  1172.     curWin.h = 1;
  1173.     curWin.text = 103;
  1174.     curWin.back = 103;
  1175.     strcpy(curWin.tittle, "Минимальная оценка:");
  1176.  
  1177.     if (inputBox(curWin, ""))
  1178.     {
  1179.       char counter;
  1180.       for (counter = 0; counter < strlen(cmd); counter++)
  1181.       {
  1182.         if ((((cmd[counter] < '0') || (cmd[counter] > '9'))) && cmd[counter] != '.')
  1183.         {
  1184.           counter = 0;
  1185.           break;
  1186.         }
  1187.       }
  1188.       if (counter != 0)
  1189.       {
  1190.         strncpy(minRating, cmd, 5);
  1191.         count = 0;
  1192.       }
  1193.     }
  1194.   default:
  1195.     break;
  1196.   }
  1197. }
  1198.  
  1199. char readParamFromIni(void)
  1200. {
  1201.   FILE *fpini;
  1202.   unsigned char *count1;
  1203.   const char currentNetwork[] = "currentNetwork";
  1204.   unsigned char curNet = 0;
  1205.  
  1206.   OS_GETPATH((unsigned int)&curPath);
  1207.   OS_SETSYSDRV();
  1208.   OS_CHDIR("/");
  1209.   OS_CHDIR("ini");
  1210.  
  1211.   fpini = OS_OPENHANDLE("network.ini", 0x80);
  1212.   if (((int)fpini) & 0xff)
  1213.   {
  1214.     clearStatus();
  1215.     printf("network.ini not found.\r\n");
  1216.     getchar();
  1217.     return false;
  1218.   }
  1219.  
  1220.   OS_READHANDLE(netbuf, fpini, sizeof(netbuf) - 1);
  1221.   OS_CLOSEHANDLE(fpini);
  1222.  
  1223.   count1 = strstr(netbuf, currentNetwork);
  1224.   if (count1 != NULL)
  1225.   {
  1226.     sscanf(count1 + strlen(currentNetwork) + 1, "%u", &curNet);
  1227.   }
  1228.  
  1229.   OS_CHDIR(curPath);
  1230.   return curNet;
  1231. }
  1232.  
  1233. void init(void)
  1234. {
  1235.   OS_SETSYSDRV();
  1236.   OS_MKDIR("../downloads");        // Create if not exist
  1237.   OS_MKDIR("../downloads/getpic"); // Create if not exist
  1238.   OS_CHDIR("../downloads/getpic");
  1239.  
  1240.   count = 0;
  1241.   verbose = 1;
  1242.   randomPic = 0;
  1243.   slideShow = 0;
  1244.   strcpy(minRating, "4.0");
  1245.  
  1246.   targetadr.family = AF_INET;
  1247.   targetadr.porth = 00;
  1248.   targetadr.portl = 80;
  1249.   targetadr.b1 = 217; // D9
  1250.   targetadr.b2 = 146; // 92
  1251.   targetadr.b3 = 69;  // 45
  1252.   targetadr.b4 = 13;  // 0D
  1253.  
  1254.   netDriver = readParamFromIni();
  1255.  
  1256.   if (netDriver == 0)
  1257.   {
  1258.     get_dns();
  1259.     clearStatus();
  1260.     dnsResolve("zxart.ee");
  1261.   }
  1262.  
  1263.   if (netDriver == 1)
  1264.   {
  1265.     loadEspConfig();
  1266.     uart_init(divider);
  1267.     espReBoot();
  1268.     OS_CLS(0);
  1269.   }
  1270. }
  1271.  
  1272. unsigned char viewScreen6912c(unsigned int bufAdr)
  1273. {
  1274.   unsigned char key;
  1275.   OS_SETBORDER(0);
  1276.   OS_SETGFX(0x83);
  1277.   SETPG32KHIGH(OS_GETSCR0() >> 8);
  1278.   memcpy((unsigned char *)(0xc000), (unsigned char *)(bufAdr), 6912);
  1279.  
  1280.   if (slideShowTime != 0)
  1281.   {
  1282.     key = delayLongKey(slideShowTime * 20);
  1283.   }
  1284.   else
  1285.   {
  1286.     key = getchar();
  1287.   }
  1288.   OS_SETGFX(0x86);
  1289.   return key;
  1290. }
  1291.  
  1292. C_task main(void)
  1293. {
  1294.   long iddqd, idkfa;
  1295.   char result;
  1296.  
  1297.   OS_HIDEFROMPARENT();
  1298.   OS_SETGFX(0x86);
  1299.   OS_CLS(0);
  1300.  
  1301.   init();
  1302.  
  1303.   printHelp();
  1304.   safeKeys(keypress);
  1305.  
  1306. start:
  1307.   keypress = 0;
  1308.   switch (randomPic)
  1309.   {
  1310.   case 0:
  1311.  
  1312.     iddqd = processJson(count, 1, 0);
  1313.     break;
  1314.   case 1:
  1315.     iddqd = processJson(0, 1, 1);
  1316.     break;
  1317.   }
  1318.  
  1319.   OS_SETCOLOR(70);
  1320.  
  1321.   switch (iddqd)
  1322.   {
  1323.   case -3: // return 0 pictures
  1324.     strcpy(minRating, "1.0");
  1325.     printf("[%u]No picture is returned in query. Minimal rating is set to %s\r\n", curFileStruct.httpErr, minRating);
  1326.     delayLong(500);
  1327.     goto start;
  1328.   case -4: // return xxxx picture, but empty body.
  1329.     printf("[%u]Empty body is returned. Next picture, please.(%ld)...\r\n", curFileStruct.httpErr, iddqd);
  1330.     delayLong(500);
  1331.     count++;
  1332.     goto start;
  1333.   case -1: // return HTTP error != 200
  1334.     printf("[%u]Error getting pic info. Next picture, please(%ld)...\r\n", curFileStruct.httpErr, iddqd);
  1335.     count++;
  1336.     delayLong(500);
  1337.     goto start;
  1338.   }
  1339.  
  1340.   if (verbose == 1)
  1341.   {
  1342.     idkfa = processJson(atol(curFileStruct.authorIds), 0, 99);
  1343.     if (idkfa < 0)
  1344.     {
  1345.       printf("[%u]Error can't parse authorIds(%s). Next picture, please...\r\n", curFileStruct.httpErr, curFileStruct.authorIds);
  1346.       count++;
  1347.       delayLong(500);
  1348.       goto start;
  1349.     }
  1350.   }
  1351.   if (strcmp(curFileStruct.picType, "standard") != 0)
  1352.   {
  1353.     printf("[%u]Error format '%s' not supported. Next picture, please.\n\r", curFileStruct.httpErr, curFileStruct.picType);
  1354.     delayLong(500);
  1355.     count++;
  1356.     goto start;
  1357.   }
  1358.   sprintf(netbuf, "GET /file/id:%ld%s", iddqd, userAgent);
  1359.   switch (netDriver)
  1360.   {
  1361.   case 0:
  1362.     result = fillPictureNet();
  1363.     break;
  1364.   case 1:
  1365.     result = fillPictureEsp();
  1366.     break;
  1367.   }
  1368.  
  1369.   if (!result) // return HTTP error != 200
  1370.   {
  1371.     printf("[%u]Error getting pic. Next picture, please...\r\n", curFileStruct.httpErr);
  1372.     count++;
  1373.     delayLong(500);
  1374.     goto start;
  1375.   }
  1376.  
  1377. review:
  1378.   OS_CLS(0);
  1379.   YIELD();
  1380.   // keypress = viewScreen6912((unsigned int)&picture, slideShowTime);
  1381.   keypress = viewScreen6912c((unsigned int)&picture);
  1382.   emptyKeys();
  1383.  
  1384.   ////// Keys only for pictures
  1385.   if (keypress == 's' || keypress == 'S')
  1386.   {
  1387.     savePic(iddqd);
  1388.     printf("%s saved.", curFileStruct.fileName);
  1389.     delayLong(500);
  1390.     count++;
  1391.   }
  1392.  
  1393.   if (keypress == 248 || keypress == 'b' || keypress == 'B')
  1394.   {
  1395.     if (count > 0)
  1396.     {
  1397.       count--;
  1398.     }
  1399.   }
  1400.   if (keypress == 251 || keypress == 32)
  1401.   {
  1402.     count++;
  1403.     goto start;
  1404.   }
  1405.   if (keypress == 'i' || keypress == 'I')
  1406.   {
  1407.     printData();
  1408.     while (OS_GETKEY() == 0)
  1409.     {
  1410.     }
  1411.     goto review;
  1412.   }
  1413.   safeKeys(keypress);
  1414.   goto start;
  1415. }
  1416.