{"id":1495,"date":"2025-01-13T04:46:05","date_gmt":"2025-01-13T04:46:05","guid":{"rendered":"https:\/\/infonaujiena.lt\/index.php\/2025\/01\/13\/pamirstos-technologijos-cgi-techplanet\/"},"modified":"2025-01-13T04:46:05","modified_gmt":"2025-01-13T04:46:05","slug":"pamirstos-technologijos-cgi-techplanet","status":"publish","type":"post","link":"https:\/\/infonaujiena.lt\/index.php\/2025\/01\/13\/pamirstos-technologijos-cgi-techplanet\/","title":{"rendered":"Pamir\u0161tos technologijos: CGI | TechPlanet"},"content":{"rendered":"<p> <br \/>\n<\/p>\n<div id=\"\">\n<p>\u012ekv\u0117ptas komentar\u0173: \u017emon\u0117s turi tvirt\u0105 ry\u0161\u012f tarp Perl kaip kalbos ir CGI kaip technologijos, naudotos pirmosiomis interneto dienomis.<\/p>\n<p>Tai logi\u0161ka: tuo metu Perl buvo viena i\u0161 nedaugelio pla\u010diai paplitusi\u0173 scenarij\u0173 kalb\u0173 ir, \u017einoma, CGI scenarijus buvo patogiau ra\u0161yti Perl, o ne, pavyzd\u017eiui, apvalkalu. Ta\u010diau tai nerei\u0161kia, kad vienas buvo prikaltas prie kito.<\/p>\n<p>Apskritai, technologija buvo savaip gera: \u012fdieg\u0117te \u017einiatinklio server\u012f (da\u017eniausiai Apache), sukonfig\u016bravote katalog\u0105, i\u0161 kurio buvo galima vykdyti scenarijus, ir gal\u0117jote paleisti visk\u0105, k\u0105 norite.<\/p>\n<p>Skirtingai nuo v\u0117lesni\u0173 sud\u0117ting\u0173 \u017einiatinklio sistem\u0173, tai tiesiogine prasme paleido program\u0105 serveryje, lygiai taip pat, kaip paleistum\u0117te j\u0105 per terminal\u0105 ar konsol\u0119. Viskas, kas buvo perduota programai per HTTP, buvo gauta per STDIN, o viskas, kas programos i\u0161vestis \u012f STDOUT, buvo i\u0161si\u0173sta \u012f kliento nar\u0161ykl\u0119.<\/p>\n<p>I\u0161 esm\u0117s tai buvo \u012fprasta neinteraktyvi konsolin\u0117 programa, grynas REST API \u2013 serveris visada paleid\u017eia program\u0105 nuo nulio, o programa veikia su tuo, kas jai buvo duota.<\/p>\n<p>Neigiamas dalykas buvo tas, kad programos paleidimas visada u\u017etrukdavo, ypa\u010d jei ji buvo para\u0161yta scenarij\u0173 kalba, kuriai reikalingas vertimas. Vienkartin\u0117ms u\u017eklausoms tai nebuvo svarbu, ta\u010diau kai programa paleid\u017eiama per 0,5 sekund\u0117s ir turite 100 u\u017eklaus\u0173 per sekund\u0119, viskas pradeda \u0161iek tiek l\u0117t\u0117ti.<\/p>\n<p>\u0160tai kod\u0117l v\u0117liau buvo pristatytas FastCGI, kur programa buvo \u201ei\u0161 anksto paleista\u201c ir lauk\u0117 duomen\u0173, o galiausiai per\u0117jome prie integruot\u0173 serveri\u0173 su keli\u0173 gij\u0173 tinkle.<\/p>\n<p>Dabar parodysiu, kaip tai galima naudoti \u0161iandien:<\/p>\n<p>Kaip jau min\u0117jau ankstesniame straipsnyje, suk\u016briau \u201euniversalios prieigos blok\u0105\u201c: vienos plok\u0161t\u0117s kompiuter\u012f su mar\u0161ruto parinkimo tarpiniu serveriu, kuris atskiria avis nuo o\u017ek\u0173, muses nuo kotlet\u0173 ir ligonius nuo sveik\u0173j\u0173.<\/p>\n<p>Ta\u010diau, kaip ir bet kuri\u0105 program\u0105, visas \u0161ias funkcijas gali reik\u0117ti paleisti i\u0161 naujo. Negana to, nam\u0173 internetas i\u0161 prigimties yra nestabilus \u2013 ant laid\u0173 u\u017evirsta medis, ekskavatorius i\u0161kasa ka\u017ek\u0105 ne taip ir staiga nustoja krauti ka\u010di\u0173 nuotraukos. Turite suprasti, kas atsitiko.<\/p>\n<p>\u017dinoma, visada galite \u012fvesti SSH, \u012fvesti kelias komandas konsol\u0117je ir su\u017einoti, bet ar galime tai padaryti lengviau? Ra\u0161yti atskir\u0105 \u017einiatinklio sistem\u0105, kad b\u016bt\u0173 galima visk\u0105 patikrinti, atrodo per daug.<\/p>\n<p>Taigi, u\u017eduotis:<\/p>\n<ul>\n<li>Fone veikia kelios programos.<\/li>\n<li>Yra b\u016bd\u0173, kaip patikrinti, ar programa veikia, ar \u201epakabinta\u201c.<\/li>\n<li>Turime sukurti paprast\u0105 tinklalap\u012f su dabartine b\u016bsena ir galimybe i\u0161 naujo paleisti programas.<\/li>\n<li>Kadangi tai yra giliai vietiniame tinkle, leidimo nereikia, ta\u010diau niekas netur\u0117t\u0173 nieko sulau\u017eyti grem\u0117zdi\u0161komis rankomis.<\/li>\n<\/ul>\n<p>\u0160iame serveryje \u012fdiegiame \u201eApache\u201c (\u201eNginx\u201c negali susidoroti su paprastu CGI be \u0161okin\u0117jimo).<\/p>\n<pre><code class=\"language-bash\">apt install apache2\n<\/code><\/pre>\n<p>Po \u012fdiegimo viskas veikia \u201ei\u0161 d\u0117\u017eut\u0117s\u201c, ta\u010diau turime \u012fjungti CGI modul\u012f, kuris pagal numatytuosius nustatymus yra i\u0161jungtas:<\/p>\n<pre><code class=\"language-bash\">cd \/etc\/apache2\/mods-enabled\nln -s ..\/mods-available\/cgi.load .\n\/etc\/init.d\/apache2 restart\n<\/code><\/pre>\n<p>Atlikta. Pagal numatytuosius nustatymus CGI scenarijai tur\u0117t\u0173 b\u016bti <code>\/usr\/lib\/cgi-bin\/<\/code>ir pasiekiama per \u017einiatinkl\u012f kaip <code>\/cgi-bin\/*.cgi<\/code>. \u017dinoma, tai galima pakeisti, ypa\u010d jei jus vargina pasen\u0119s \u201ecgi-bin\u201c, bet dabar to nepamatysime. Ir, \u017einoma, \u0161is katalogas i\u0161 prad\u017ei\u0173 tu\u0161\u010dias.<\/p>\n<p>Sukuriame pirm\u0105j\u012f fail\u0105, <code>env.cgi<\/code>:<\/p>\n<pre><code class=\"language-bash\">#!\/bin\/sh\n\necho \"Content-Type: text\/html\"\necho \"\"\n\necho \"&lt;pre&gt;\"\nenv\necho \"&lt;\/pre&gt;\"\n\nid\nchmod 755 env.cgi\n<\/code><\/pre>\n<p>Prie serverio pasiekiame per nar\u0161ykl\u0119:<\/p>\n<pre><code>http:\/\/xx.xx.xx.xx\/cgi-bin\/env.cgi\n<\/code><\/pre>\n<p>I\u0161vestis:<\/p>\n<pre><code>GATEWAY_INTERFACE=CGI\/1.1\nREMOTE_ADDR=XX.XX.XX.XX\nQUERY_STRING=\nHTTP_USER_AGENT=Mozilla\/5.0 (X11; Linux x86_64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/129.0.0.0 Safari\/537.36\nDOCUMENT_ROOT=\/var\/www\/html\nREMOTE_PORT=40472\nHTTP_UPGRADE_INSECURE_REQUESTS=1\nHTTP_ACCEPT=text\/html,application\/xhtml+xml,application\/xml;q=0.9,image\/avif,image\/webp,image\/apng,*\/*;q=0.8,application\/signed-exchange;v=b3;q=0.7\nSERVER_SIGNATURE=\nApache\/2.4.62 (Debian) Server at 10.1.0.4 Port 80\n\n....\n\nuid=33(www-data) gid=33(www-data) groups=33(www-data)\n<\/code><\/pre>\n<p>Joki\u0173 sud\u0117ting\u0173 program\u0173, nauj\u0173 ar sen\u0173 kalb\u0173, strukt\u016br\u0173, nieko \u2013 tik paprastas apvalkalo scenarijus.<\/p>\n<p>\u010cia yra \u012fdomios eilut\u0117s <code>QUERY_STRING=<\/code> ir apatin\u0117 eilut\u0117 <code>uid=33(www-data) gid=33(www-data) groups=33(www-data)<\/code>.<\/p>\n<p>The <code>QUERY_STRING=<\/code> yra eilut\u0117, kuri bus \u012fvesta adresu po scenarijaus pavadinimo:<\/p>\n<pre><code>http:\/\/XX.XX.XX.XX\/cgi-bin\/env.cgi?blablabla -&gt; QUERY_STRING=blablabla\n<\/code><\/pre>\n<p>Idealiu atveju tai tur\u0117t\u0173 b\u016bti URL u\u017ekoduoti GET parametrai, ta\u010diau prakti\u0161kai nesvarbu, kokia eilut\u0117 yra, jei ji nepa\u017eeid\u017eia simboli\u0173 konvencij\u0173. Tokiu atveju galime nusi\u0173sti vien\u0105 eilut\u0119, nurodant, su kokia programa m\u016bs\u0173 scenarijus tur\u0117t\u0173 veikti.<\/p>\n<p>Apatin\u0117 eilut\u0117, rezultatas <code>id<\/code> komanda rodo, kad \u017einiatinklio serveris veikia pagal <code>www-data<\/code> naudotojas.<\/p>\n<p>Nor\u0117dami patikrinti internet\u0105 ir \u012fvairias tarpinio serverio parinktis, galime naudoti standart\u0105 <code>curl<\/code>:<\/p>\n<p>Tiesiogin\u0117 u\u017eklausa suteiks mums i\u0161orin\u012f IP:<\/p>\n<pre><code class=\"language-bash\">curl http:\/\/v4v6.ipv6-test.com\/api\/myip.php --silent\n<\/code><\/pre>\n<p>U\u017eklausa per SOCKS5 tarpin\u012f server\u012f suteiks mums i\u0161orin\u012f IP, matom\u0105 per tarpin\u012f server\u012f, ir taip pat patikrins tarpinio serverio funkcionalum\u0105:<\/p>\n<pre><code class=\"language-bash\">curl -x socks5h:\/\/127.0.0.1:1080 http:\/\/v4v6.ipv6-test.com\/api\/myip.php --silent\n<\/code><\/pre>\n<p>Kiti pana\u0161\u016bs.<\/p>\n<p>Gal\u0117tume atlikti visas patikras vienu scenarijumi ir gr\u0105\u017einti rezultatus JSON formatu, ta\u010diau kai kurios u\u017eklausos gali u\u017etrukti ilgai, o scenarijus j\u0173 vis\u0173 laukt\u0173. Tai n\u0117ra labai patogu, tod\u0117l scenarijus bus vienas, bet k\u0105 jis patikrins, priklausys nuo u\u017eklausos parametro.<\/p>\n<p>Taigi, mes gauname scenarij\u0173 <code>check_one.cgi<\/code>:<\/p>\n<pre><code class=\"language-bash\">#!\/bin\/sh\nq=$QUERY_STRING\n# remove everything else\nunset $(env | cut -d= -f1)\n\nPATH=\/usr\/local\/sbin:\/usr\/local\/bin:\/usr\/sbin:\/usr\/bin:\/sbin:\/bin; export PATH\n\n# mandatory header\necho \"Content-Type: application\/json\"\necho \"\"\n\n# add \"x\" to the parameter to avoid empty strings\nif ( \"x$q\" = \"xxray\" ) ; then\n\n    # here we request the server's response, it will give us the IP address\n\tINETIP=$( curl http:\/\/v4v6.ipv6-test.com\/api\/myip.php --silent )\n\tPROXYIP=$( curl -x socks5h:\/\/127.0.0.1:1080 http:\/\/v4v6.ipv6-test.com\/api\/myip.php --silent )\n\n\techo \"{\\\"extip\\\":\\\"${INETIP}\\\",\\\"proxyip\\\":\\\"${PROXYIP}\\\"}\"\n\nelif ( \"x$q\" = \"xi2p\" ) ; then\n\n    X=1\n    # here and below - the fact of the response is important, so only headers and error code\n\tcurl -x socks5h:\/\/127.0.0.1:4447 http:\/\/flibusta.i2p -I --silent -o \/dev\/null\n\tif ( $? -ne 0 ) ; then\n\t\tX=0\n\tfi\n\techo \"{\\\"i2p\\\":${X}}\";\n\nelif ( \"x$q\" = \"xnodpi\" ) ; then\n\n    X=1\n\tcurl -x socks5h:\/\/127.0.0.1:1081 https:\/\/jnn-pa.googleapis.com -I --silent -o \/dev\/null\n\tif ( $? -ne 0 ) ; then\n\t\tX=0\n\tfi\n\techo \"{\\\"nodpi\\\":${X}}\";\n\nelif ( \"x$q\" = \"xproxy\" ) ; then\n\t\n    X=1\n\tcurl -x socks5h:\/\/127.0.0.1:6007 http:\/\/v4v6.ipv6-test.com\/api\/myip.php -I --silent -o \/dev\/null\n\tif ( $? -ne 0 ) ; then\n\t\tX=0\n\tfi\n\techo \"{\\\"proxy\\\":${X}}\";\n\nelse\n    # to not forget what options are available\n\techo \"{\\\"options\\\":(\\\"proxy\\\",\\\"xray\\\",\\\"i2p\\\",\\\"nodpi\\\")}\"\nfi\n<\/code><\/pre>\n<p>Dabar, nurod\u0119 tam tikras parinktis, galime gauti atsakym\u0105, ar konkretus mar\u0161rutas veikia, ar ne.<\/p>\n<p>Paslaugas i\u0161 naujo paleisti galima taip: Kadangi \u017einiatinklio serveris veikia pagal <code>www-data<\/code> vartotojas, jis neturi teisi\u0173 i\u0161 naujo paleisti visko, ko norime, ir mes jai t\u0173 teisi\u0173 nesuteiksime. Vietoj to, mes vykdysime paslaugas specialiai pagal j\u0105 ir taip, kad jos pa\u010dios paleist\u0173si i\u0161 naujo. Mes kuriame tipinius scenarijus, tokius kaip:<\/p>\n<pre><code class=\"language-bash\">#!\/bin\/sh\n#\nexec &gt; \/dev\/null\nexec 2&gt;&amp;1\n\ncd \/tmp\n\nwhile ( 1 ) ; do\n  \/usr\/local\/etc\/xray\/xray -c \/usr\/local\/etc\/xray\/config.json\ndone\n<\/code><\/pre>\n<p>The <code>xray<\/code> programa nepaleid\u017eiama fone, taigi, jei procesas u\u017emu\u0161tas arba mir\u0161ta savaime, begalinis scenarijaus ciklas j\u012f paleis i\u0161 naujo. Taip apsisaugome nuo netik\u0117t\u0173 gedim\u0173, o pakibimo atveju u\u017etenka u\u017emu\u0161ti pakibimo proces\u0105 \u2013 tam u\u017etenka teisi\u0173.<\/p>\n<p>Tas pats pasakytina ir apie kitus procesus.<\/p>\n<p>Dabar turime prad\u0117ti procesus. Tam patogu naudoti <code>\/etc\/rc.local<\/code> scenarijus (\u0161iuo atveju jis veikia; jei ne, prid\u0117kite j\u012f kur nors kitur, pvz <code>\/etc\/init.d<\/code>):<\/p>\n<pre><code class=\"language-bash\">su www-data -s \/bin\/sh -c 'setsid \/usr\/local\/bin\/start_xray &amp;'\n<\/code><\/pre>\n<p>The <code>-s \/bin\/sh<\/code> parametras reikalingas, nes <code>www-data<\/code> vartotojas neturi savo apvalkalo (\u017er <code>vipw<\/code>). The <code>-c<\/code> parametras paleid\u017eia komand\u0105, \u0161iuo atveju <code>setsid<\/code>kuris paleid\u017eia paleisties scenarij\u0173 (\u0161iek tiek perteklin\u012f) kaip demon\u0105.<\/p>\n<p>Kiti pana\u0161\u016bs. I\u0161 naujo paleidus kompiuter\u012f, paleid\u017eiami paleidimo scenarijai, kurie paleid\u017eia programas, kurios dabar veikia pagal vartotoj\u0105, o joms sugedus ar \u017euvus, jos automati\u0161kai paleid\u017eiamos i\u0161 naujo.<\/p>\n<p>Vienintelis niuansas su <code>i2pd<\/code> yra tai, kad jis ie\u0161ko konfig\u016bracij\u0173 pagrindiniame kataloge <code>~\/.i2pd<\/code>o \u0161iam vartotojui tai yra <code>\/var\/www<\/code> katalogas (dar kart\u0105 \u017er <code>vipw<\/code>), tod\u0117l nustatymai tur\u0117t\u0173 b\u016bti ten ir tur\u0117t\u0173 b\u016bti ra\u0161ymo teis\u0117s \u012f konfig\u016bracijos katalog\u0105.<\/p>\n<p>Dabar ra\u0161ome \u017eudiko scenarij\u0173:<\/p>\n<pre><code class=\"language-bash\">#!\/bin\/sh\nq=$QUERY_STRING\n# remove everything else\nunset $(env | cut -d= -f1)\n\nPATH=\/usr\/local\/sbin:\/usr\/local\/bin:\/usr\/sbin:\/usr\/bin:\/sbin:\/bin; export PATH\n\necho \"Content-Type: text\/html\"\necho \"\"\n\npid=\n\nif ( \"x$q\" = \"xxray\" ) ; then\n\t\n  pid=$(ps ax| grep -v grep | grep 'xray\/xray' | awk '{ print $1 }')\n\n  if ( -n \"$pid\" ) ; then\n\t  echo $pid\n    kill $pid\n    sleep 3\n  fi\n\nelif ( \"x$q\" = \"xi2p\" ) ; then\n\n  pid=$(ps ax| grep -v grep | grep '\/i2pd' | awk '{ print $1 }')\n\n  if ( -n \"$pid\" ) ; then\n\t  echo $pid\n    kill $pid\n    sleep 3\n  fi\n\nelif ( \"x$q\" = \"xnodpi\" ) ; then\n\n  pid=$(ps ax| grep -v grep | grep '\/ciadpi' | awk '{ print $1 }')\n\n  if ( -n \"$pid\" ) ; then\n\t  echo $pid\n    kill $pid\n    sleep 3\n  fi\n\nelse\n\techo \"{\\\"options\\\":(\\\"xray\\\",\\\"i2p\\\",\\\"nodpi\\\")}\"\nfi\n<\/code><\/pre>\n<p><code>ps ax<\/code>  pateikia proces\u0173 s\u0105ra\u0161\u0105, pirmasis <code>grep<\/code> pa\u0161alina <code>grep<\/code> pati i\u0161 i\u0161vesties, antra <code>grep<\/code> ie\u0161ko norimos programos, <code>awk<\/code> i\u0161traukia PID, <code>kill<\/code> u\u017emu\u0161a j\u012f ir <code>sleep<\/code> \u0161iek tiek laukia, kol procesas baigsis.<\/p>\n<p>Apskritai tai beveik viskas. Dabar sukurkime puslap\u012f:<\/p>\n<pre><code class=\"language-html\">&lt;!DOCTYPE html PUBLIC \"-\/\/W3C\/\/DTD XHTML 1.0 Transitional\/\/EN\" \"http:\/\/www.w3.org\/TR\/xhtml1\/DTD\/xhtml1-transitional.dtd\"&gt;\n&lt;html xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"&gt;\n  &lt;head&gt;\n    &lt;meta http-equiv=\"Content-Type\" content=\"text\/html; charset=UTF-8\" \/&gt;\n    &lt;title&gt;HTML gate&lt;\/title&gt;\n\n&lt;style type=\"text\/css\"&gt;\n  body, html {\n    margin: 0;\n    padding: 0;\n    font-family: Arial, sans-serif;\n    height: 100%;\n  }\n  .placeholder {\n    display:inline-block;\n    width:10em;\n  }\n  .txt_error {\n    color:#ff0000;\n    font-weight:bold;\n  }\n  .txt_ok {\n    color:#00ff00;\n    font-weight:bold;\n  }\n  .hero {\n    height: 100vh;\n    background-image: url('bg-image.jpeg');\n    background-color: black;\n    background-position: center;\n    background-repeat: no-repeat;\n    background-size:cover;\n    color: white;\n    box-sizing: border-box;\n  }\n  #status {\n    padding:2em;\n  }\n  #buttons {\n    display:flex;\n    align-items: center;\n    justify-content: center;\n    gap: 5em;\n    padding-top: 300px;\n  }\n  #buttons button, #check {\n    padding: 15px 35px;\n    font-size: 20px;\n    border: solid 3px #ff8b00;\n    background: #00003370;\n    color: #ffc800;\n    border-radius: 10px;\n    cursor:pointer;\n  }\n  .disabled {\n    color:#736e5f!important;\n    border: solid 3px #736e5f!important;\n    cursor:not-allowed!important;\n  }\n\n&lt;\/style&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n\n  &lt;div class=\"hero\" id=\"head\"&gt;\n\n   &lt;div id=\"status\"&gt;\n\t  &lt;table&gt;\n\t\t  &lt;tr&gt;\n\t\t\t  &lt;td&gt;External IP&lt;\/td&gt;\n\t\t\t  &lt;td&gt;&lt;span id=\"extip\" class=\"placeholder\"&gt;&lt;span class=\"loading\"&gt;...&lt;\/span&gt;&lt;\/span&gt;&lt;\/td&gt;\n\t\t  &lt;\/tr&gt;\n\t\t  &lt;tr&gt;\n\t\t\t  &lt;td&gt;Proxy IP&lt;\/td&gt;\n\t\t\t  &lt;td&gt;&lt;span id=\"proxyip\" class=\"placeholder\"&gt;&lt;span class=\"loading\"&gt;...&lt;\/span&gt;&lt;\/span&gt;&lt;\/td&gt;\n\t\t  &lt;\/tr&gt;\n\t\t  &lt;tr&gt;\n\t\t\t  &lt;td&gt;I2P network&lt;\/td&gt;\n\t\t\t  &lt;td&gt;&lt;span id=\"i2p\" class=\"placeholder\"&gt;&lt;span class=\"loading\"&gt;...&lt;\/span&gt;&lt;\/span&gt;&lt;\/td&gt;\n\t\t  &lt;\/tr&gt;\n\t\t  &lt;tr&gt;\n\t\t\t  &lt;td&gt;Proxy&lt;\/td&gt;\n\t\t\t  &lt;td&gt;&lt;span id=\"proxy\" class=\"placeholder\"&gt;&lt;span class=\"loading\"&gt;...&lt;\/span&gt;&lt;\/span&gt;&lt;\/td&gt;\n\t\t  &lt;\/tr&gt;\n\t\t  &lt;tr&gt;\n\t\t\t  &lt;td&gt;NoDPI&lt;\/td&gt;\n\t\t\t  &lt;td&gt;&lt;span id=\"nodpi\" class=\"placeholder\"&gt;&lt;span class=\"loading\"&gt;...&lt;\/span&gt;&lt;\/span&gt;&lt;\/td&gt;\n\t\t  &lt;\/tr&gt;\n\t  &lt;\/table&gt;\n    &lt;button onclick=\"check()\" id=\"check\"&gt;Check&lt;\/button&gt;\n   &lt;\/div&gt;\n   &lt;div id=\"buttons\"&gt;\n    &lt;button onclick=\"kill(this,'xray')\"&gt;Restart Xray&lt;\/button&gt;\n    &lt;button onclick=\"kill(this,'i2p')\"&gt;Restart i2p&lt;\/button&gt;\n    &lt;button onclick=\"kill(this,'nodpi')\"&gt;Restart NoDPI&lt;\/button&gt;\n   &lt;\/div&gt;\n  &lt;\/div&gt;\n  &lt;script&gt;\n    function kill(ctl,id){\n      console.log(ctl, id);\n      ctl.disabled=true;\n      ctl.classList.add('disabled');\n      fetch('\/cgi-bin\/kill_one.cgi?'+id)\n        .then(response =&gt; {\n          if (!response.ok) {\n            throw new Error(`HTTP error! status: ${response.status}`);\n          }\n          return response.json();\n        })\n        .then(data =&gt; {\n          window.setTimeout(check,10000);\n          ctl.disabled=false;\n          ctl.classList.remove('disabled');\n          check();\n        })\n        .catch(error =&gt; {\n          console.error('Error fetching data:', error);\n          ctl.disabled=false;\n          ctl.classList.remove('disabled');\n        });\n    }\n\n    function check(){\n      const urls = (\n        'xray',\n        'i2p',\n        'proxy',\n        'nodpi'\n      );\n\n      const labels = document.querySelectorAll('.placeholder');\n      labels.forEach(item =&gt; {\n        item.innerHTML = '&lt;span class=\"loading\"&gt;...&lt;\/span&gt;';\n      });\n\n      urls.forEach(url =&gt; {\n        fetch('\/cgi-bin\/check_one.cgi?'+url)\n          .then(response =&gt; {\n            if (!response.ok) {\n              throw new Error(`HTTP error! status: ${response.status}`);\n            }\n            return response.json();\n          })\n          .then(data =&gt; {\n            Object.entries(data).forEach(((key, value)) =&gt; {\n              const element = document.getElementById(key);\n              if (element) {\n                if(value == 1){\n                  element.classList.remove('txt_error');\n                  element.classList.add('txt_ok');\n                  element.textContent=\"OK\";\n                }else if(value == 0){\n                  element.classList.add('txt_error');\n                  element.classList.remove('txt_ok');\n                  element.textContent=\"ERROR\";\n                }else{\n                  element.classList.remove('txt_error');\n                  element.classList.add('txt_ok');\n                  element.textContent = value;\n                }\n              }\n            });\n          })\n          .catch(error =&gt; {\n            console.error('Error fetching data:', error);\n        });\n      });\n    }\n\n    check();\n    &lt;\/script&gt;\n  &lt;\/body&gt;\n&lt;\/html&gt;\n<\/code><\/pre>\n<p>Rezultatas:<br \/>\n<\/p>\n<p>tiek. Grynas administratoriaus darbas, apvalkalas ir \u0161iek tiek<\/p>\n<\/p><\/div>\n<p>Jei tekste radote klaid\u0105, si\u0173skite prane\u0161im\u0105 autoriui pa\u017eym\u0117dami klaid\u0105 ir paspausdami Ctrl-Enter.<\/p>\n<p><br \/>\n<br \/><a href=\"https:\/\/techplanet.today\/post\/forgotten-technologies-cgi\">Source link <\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u012ekv\u0117ptas komentar\u0173: \u017emon\u0117s turi tvirt\u0105 ry\u0161\u012f tarp Perl kaip kalbos ir CGI kaip technologijos, naudotos pirmosiomis interneto dienomis. Tai logi\u0161ka: tuo metu Perl buvo viena i\u0161 nedaugelio pla\u010diai paplitusi\u0173 scenarij\u0173 kalb\u0173 ir, \u017einoma, CGI scenarijus buvo patogiau ra\u0161yti Perl, o ne, pavyzd\u017eiui, apvalkalu. Ta\u010diau tai nerei\u0161kia, kad vienas buvo prikaltas prie kito. Apskritai, technologija buvo [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1496,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[3],"tags":[2910,2908,2909,2317],"class_list":["post-1495","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technologijos","tag-cgi","tag-pamirstos","tag-technologijos","tag-techplanet"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/infonaujiena.lt\/index.php\/wp-json\/wp\/v2\/posts\/1495","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/infonaujiena.lt\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/infonaujiena.lt\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/infonaujiena.lt\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/infonaujiena.lt\/index.php\/wp-json\/wp\/v2\/comments?post=1495"}],"version-history":[{"count":0,"href":"https:\/\/infonaujiena.lt\/index.php\/wp-json\/wp\/v2\/posts\/1495\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/infonaujiena.lt\/index.php\/wp-json\/wp\/v2\/media\/1496"}],"wp:attachment":[{"href":"https:\/\/infonaujiena.lt\/index.php\/wp-json\/wp\/v2\/media?parent=1495"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/infonaujiena.lt\/index.php\/wp-json\/wp\/v2\/categories?post=1495"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/infonaujiena.lt\/index.php\/wp-json\/wp\/v2\/tags?post=1495"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}