diff options
Diffstat (limited to 'src/htsserver.c')
-rw-r--r-- | src/htsserver.c | 1814 |
1 files changed, 1814 insertions, 0 deletions
diff --git a/src/htsserver.c b/src/htsserver.c new file mode 100644 index 0000000..0408976 --- /dev/null +++ b/src/htsserver.c @@ -0,0 +1,1814 @@ +/* ------------------------------------------------------------ */ +/* +HTTrack Website Copier, Offline Browser for Windows and Unix +Copyright (C) Xavier Roche and other contributors + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +Important notes: + +- We hereby ask people using this source NOT to use it in purpose of grabbing +emails addresses, or collecting any other private information on persons. +This would disgrace our work, and spoil the many hours we spent on it. + + +Please visit our Website: http://www.httrack.com +*/ + + +/* ------------------------------------------------------------ */ +/* File: Mini-server */ +/* Author: Xavier Roche */ +/* ------------------------------------------------------------ */ + + +/* specific definitions */ +/* specific definitions */ +#include "htsbase.h" +#include "htsnet.h" +#include "htslib.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <fcntl.h> +#if HTS_WIN +#else +#include <arpa/inet.h> +#endif +#ifndef _WIN32 +#include <signal.h> +#endif +/* END specific definitions */ + +/* définitions globales */ +#include "htsglobal.h" + +/* htslib */ +/*#include "htslib.h"*/ + +/* HTTrack Website Copier Library */ +#include "httrack-library.h" + +/* Language files */ +#include "htsinthash.h" +int NewLangStrSz=1024; +inthash NewLangStr=NULL; +int NewLangStrKeysSz=1024; +inthash NewLangStrKeys=NULL; +int NewLangListSz=1024; +inthash NewLangList=NULL; +/* Language files */ + + +#include "htsserver.h" + +char* gethomedir(void); +int commandRunning = 0; +int commandEndRequested = 0; +int commandEnd = 0; +int commandReturn = 0; +char* commandReturnMsg = NULL; +char* commandReturnCmdl = NULL; +int commandReturnSet = 0; + +/* Extern */ +extern void webhttrack_main(char* cmd); +extern void webhttrack_lock(int lock); + +static int is_image(char* file) { + return ( (strstr(file, ".gif") != NULL) ); +} +static int is_text(char* file) { + return ( (strstr(file, ".txt") != NULL) ); +} +static int is_html(char* file) { + return ( (strstr(file, ".htm") != NULL) ); +} + +static void sig_brpipe( int code ) { + /* ignore */ +} + + +// URL Link catcher + +// 0- Init the URL catcher with standard port + +// smallserver_init(&port,&return_host); +T_SOC smallserver_init_std(int* port_prox,char* adr_prox) { + T_SOC soc; + int try_to_listen_to[]={8080,8081,8082,8083,8084,8085,8086,8087,8088,8089, + 32000,32001,32002,32003,32004,32005,32006,32007,32008,32009, + 42000,42001,42002,42003,42004,42005,42006,42007,42008,42009, + 0,-1}; + int i=0; + do { + soc=smallserver_init(&try_to_listen_to[i],adr_prox); + *port_prox=try_to_listen_to[i]; + i++; + } while( (soc == INVALID_SOCKET) && (try_to_listen_to[i]>=0)); + return soc; +} + + +// 1- Init the URL catcher + +// smallserver_init(&port,&return_host); +T_SOC smallserver_init(int* port,char* adr) { + T_SOC soc = INVALID_SOCKET; + char h_loc[256+2]; + + commandRunning = + commandEnd = + commandReturn = + commandReturnSet = + commandEndRequested = 0; + if (commandReturnMsg) + free(commandReturnMsg); + commandReturnMsg = NULL; + if (commandReturnCmdl) + free(commandReturnCmdl); + commandReturnCmdl = NULL; + + if (gethostname(h_loc,256)==0) { // host name + SOCaddr server; + int server_size=sizeof(server); + /*t_hostent* hp_loc; + t_fullhostent buffer;*/ + + // effacer structure + memset(&server, 0, sizeof(server)); + + /*if ( (hp_loc=vxgethostbyname(h_loc, &buffer)) )*/ { // notre host + + // copie adresse + // NO (bind all) + // SOCaddr_copyaddr(server, server_size, hp_loc->h_addr_list[0], hp_loc->h_length); + + SOCaddr_initany(server, server_size); + if ( (soc=socket(SOCaddr_sinfamily(server), SOCK_STREAM, 0)) != INVALID_SOCKET) { + SOCaddr_initport(server, *port); + if ( bind(soc,(struct sockaddr*) &server, server_size) == 0 ) { + /*int len; + SOCaddr server2; + len=sizeof(server2);*/ + // effacer structure + /*memset(&server2, 0, sizeof(server2)); + if (getsockname(soc,(struct sockaddr*) &server2,&len) == 0) { + *port=ntohs(SOCaddr_sinport(server)); // récupérer port*/ + if (listen(soc,10)>=0) { // au pif le 10 + // SOCaddr_inetntoa(adr, 128, server2, len); + strcpy(adr, h_loc); + } else { +#ifdef _WIN32 + closesocket(soc); +#else + close(soc); +#endif + soc=INVALID_SOCKET; + } + + + /*} else { +#ifdef _WIN32 + closesocket(soc); +#else + close(soc); +#endif + soc=INVALID_SOCKET; + }*/ + + + } else { +#ifdef _WIN32 + closesocket(soc); +#else + close(soc); +#endif + soc=INVALID_SOCKET; + } + } + } + } + return soc; +} + +// 2 - Wait for URL + +static int recv_bl(T_SOC soc, void* buffer, size_t len, int timeout) { + if (check_readinput_t(soc, timeout)) { + int n = 1; + size_t size = len; + size_t offs = 0; + while(n > 0 && size > 0) { + n = recv(soc, ((char*)buffer) + offs, (int) size, 0); + if (n > 0) { + offs += n; + size -= n; + } + } + return (int)offs; + } + return -1; +} + + +// smallserver +// returns 0 if error +// url: buffer where URL must be stored - or ip:port in case of failure +// data: 32Kb + +typedef struct { + char* name; + int value; +} initIntElt; +typedef struct { + char* name; + char* value; +} initStrElt; + +int smallserver_setkey(char* key, char* value) { + return inthash_write(NewLangList, key, (unsigned long int)strdup(value)); +} +int smallserver_setkeyint(char* key, LLint value) { + char tmp[256]; + sprintf(tmp, LLintP, value); + return inthash_write(NewLangList, key, (unsigned long int)strdup(tmp)); +} +int smallserver_setkeyarr(char* key, int id, char* key2, char* value) { + char tmp[256]; + sprintf(tmp, "%s%d%s", key, id, key2); + return inthash_write(NewLangList, tmp, (unsigned long int)strdup(value)); +} + +#define SET_ERROR(err) do { \ + inthash_write(NewLangList, "error", (unsigned long int)strdup(err)); \ + error_redirect = "/server/error.html"; \ +} while(0) + +int smallserver(T_SOC soc,char* url,char* method,char* data, char* path) { + int timeout=30; + int retour=0; + int willexit=0; + int buffer_size = 32768; + char* buffer = (char*)malloc(buffer_size); + String headers = STRING_EMPTY; + String output = STRING_EMPTY; + String tmpbuff = STRING_EMPTY; + String fspath = STRING_EMPTY; + + /* Load strings */ + htslang_init(); + if (!htslang_load(NULL, path)) { + fprintf(stderr, "unable to find lang.def and/or lang/ strings in %s\n", path); + return 0; + } + LANG_T(path, 0); + + /* Init various values */ + { + char pth[1024]; + char* initOn[] = { "parseall", "Cache", "ka", + "cookies", "parsejava", "testall", "updhack", "index", NULL }; + initIntElt initInt[] = { + { "filter", 4 }, + { "travel", 2 }, + { "travel2", 1 }, + { "travel3", 1 }, + /* */ + { "connexion", 4 }, + /* */ + { "maxrate", 25000 }, + /* */ + { "build", 1 }, + /* */ + { "checktype", 2}, + { "robots", 3 }, + + { NULL, 0 } + }; + initStrElt initStr[] = { + { "user", "Mozilla/4.5 (compatible; HTTrack 3.0x; Windows 98)" }, + { "footer", "<!-- Mirrored from %s%s by HTTrack Website Copier/3.x [XR&CO'2002], %s -->" }, + { "url2", "+*.png +*.gif +*.jpg +*.css +*.js -ad.doubleclick.net/*" }, + { NULL, NULL } + }; + int i = 0; + for(i = 0 ; initInt[i].name ; i++) { + char tmp[32]; + sprintf(tmp, "%d", initInt[i].value); + inthash_write(NewLangList, initInt[i].name, (unsigned long int)strdup(tmp)); + } + for(i = 0 ; initOn[i] ; i++) { + inthash_write(NewLangList, initOn[i], (unsigned long int)strdup("1")); /* "on" */ + } + for(i = 0 ; initStr[i].name ; i++) { + inthash_write(NewLangList, initStr[i].name, (unsigned long int)strdup(initStr[i].value)); + } + strcpybuff(pth, gethomedir()); + strcatbuff(pth, "/websites"); + inthash_write(NewLangList, "path", (unsigned long int)strdup(pth)); + } + + /* Lock */ + webhttrack_lock(1); + + // connexion (accept) + while(!willexit && buffer != NULL && soc != INVALID_SOCKET) { + char line1[1024]; + char line[8192]; + char line2[1024]; + T_SOC soc_c; + struct sockaddr dummyaddr; + int dummylen = sizeof(struct sockaddr); + LLint length = 0; + char* error_redirect = NULL; + + line[0] = '\0'; + buffer[0] = '\0'; + StringClear(&headers); + StringClear(&output); + StringClear(&tmpbuff); + StringClear(&fspath); + StringStrcat(&headers, ""); + StringStrcat(&output, ""); + StringStrcat(&tmpbuff, ""); + StringStrcat(&fspath, ""); + memset(&dummyaddr, 0, sizeof(dummyaddr)); + + /* UnLock */ + webhttrack_lock(0); + + /* sigpipe */ +#ifndef _WIN32 + signal( SIGPIPE , sig_brpipe ); +#endif + + /* Accept */ + while ( (soc_c = accept(soc, &dummyaddr, &dummylen)) == INVALID_SOCKET); + + /* Lock */ + webhttrack_lock(1); + + if(linputsoc_t(soc_c, line1, sizeof(line1) - 2, timeout) > 0) { + int meth = 0; + if (strfield(line1, "get ")) { + meth = 1; + } else if (strfield(line1, "post ")) { + meth = 2; + } else if (strfield(line1, "head ")) { /* yes, we can do that */ + meth = 10; + } else { +#ifdef _DEBUG + // assert(FALSE); +#endif + } + if (meth) { + /* Flush headers */ + length = buffer_size - 2; + while(linputsoc_t(soc_c, line, sizeof(line) - 2, timeout) > 0) { + int p; + if ((p=strfield(line,"Content-length:"))!=0) { + sscanf(line+p, LLintP, &(length)); + } + else if ((p=strfield(line,"Accept-language:"))!=0) { + char tmp[32]; + char* s = line + p; + /*int l;*/ + while(*s == ' ') s++; + tmp[0] = '\0'; + strncatbuff(tmp, s, 2); + /*l = LANG_SEARCH(path, tmp);*/ + } + } + if (meth == 2) { + int sz = 0; + if (length > buffer_size - 2) { + length = buffer_size - 2; + } + if (length > 0 && (sz=recv_bl(soc_c, buffer, (int)length, timeout)) < 0) { + meth = 0; + } else { + buffer[sz] = '\0'; + } + } + } + + /* Generated variables */ + if (commandEnd && !commandReturnSet) { + commandReturnSet = 1; + if (commandReturn) { + char tmp[32]; + sprintf(tmp, "%d", commandReturn); + inthash_write(NewLangList, "commandReturn", (unsigned long int)strdup(tmp)); + inthash_write(NewLangList, "commandReturnMsg", (unsigned long int)commandReturnMsg); + inthash_write(NewLangList, "commandReturnCmdl", (unsigned long int)commandReturnCmdl); + } else { + inthash_write(NewLangList, "commandReturn", (unsigned long int)NULL); + inthash_write(NewLangList, "commandReturnMsg", (unsigned long int)NULL); + inthash_write(NewLangList, "commandReturnCmdl", (unsigned long int)NULL); + } + } + + /* SID check */ + { + unsigned long int adr = 0; + if (inthash_readptr(NewLangList, "_sid", (long int *)&adr)) { + if (inthash_write(NewLangList, "sid", (unsigned long int)strdup((char*)adr))) { + } + } + } + + /* check variables */ + if (meth && buffer[0]) { + char* s = buffer; + char *e, *f; + strcatbuff(buffer, "&"); + while( s && (e = strchr(s, '=')) && (f = strchr(s, '&')) ) { + char* ua; + int len; + String sua = STRING_EMPTY; + *e = *f = '\0'; + ua = e + 1; + if (strfield2(ua, "on")) /* hack : "on" == 1 */ + ua = "1"; + len = strlen(ua); + unescapehttp(ua, &sua); + inthash_write(NewLangList, s, (unsigned long int)StringAcquire(&sua)); + s = f + 1; + } + } + + + /* Error check */ + { + unsigned long int adr = 0; + unsigned long int adr2 = 0; + if (inthash_readptr(NewLangList, "sid", (long int *)&adr)) { + if (inthash_readptr(NewLangList, "_sid", (long int *)&adr2)) { + if (strcmp((char*)adr, (char*)adr2) != 0) { + meth = 0; + } + } + } + } + + /* Check variables (internal) */ + if (meth) { + int doLoad=0; + unsigned long int adr = 0; + if (inthash_readptr(NewLangList, "lang", (long int *)&adr)) { + int n = 0; + if (sscanf((char*)adr, "%d", &n) == 1 && n - 1 != LANG_T(path, -1)) { + LANG_T(path, n - 1); + } + } + + /* Load existing project settings */ + if (inthash_readptr(NewLangList, "loadprojname", (long int *)&adr)) { + char* pname = (char*) adr; + if (*pname) { + inthash_write(NewLangList, "projname", (unsigned long int)strdup(pname)); + } + inthash_write(NewLangList, "loadprojname", (unsigned long int)NULL); + doLoad=1; + } + + /* path : <path>/<project> */ + if (!commandRunning) { + unsigned long int adrw = 0, adrpath = 0, adrprojname = 0; + if (inthash_readptr(NewLangList, "path", (long int *)&adrpath) + && inthash_readptr(NewLangList, "projname", (long int *)&adrprojname)) { + StringClear(&fspath); + StringStrcat(&fspath, (char*)adrpath); + StringStrcat(&fspath, "/"); + StringStrcat(&fspath, (char*)adrprojname); + } + } + + /* Load existing project settings */ + if (doLoad) { + FILE* fp; + StringStrcat(&fspath, "/hts-cache/winprofile.ini"); + fp = fopen(StringBuff(&fspath), "rb"); + if (fp) { + /* Read file */ + while(!feof(fp)) { + char* str = line; + char* pos; + if (!linput(fp, line, sizeof(line) - 2)) { + *str = '\0'; + } + pos=strchr(line, '='); + if (pos) { + String escline = STRING_EMPTY; + *pos++='\0'; + if (pos[0] == '0' && pos[1] == '\0') + *pos = '\0'; /* 0 => empty */ + unescapeini(pos, &escline); + inthash_write(NewLangList, line, (unsigned long int)StringAcquire(&escline)); + } + } + + fclose(fp); + } + } + + } + + /* Execute command */ + { + unsigned long int adr = 0; + int p = 0; + if (inthash_readptr(NewLangList, "command", (long int *)&adr)) { + if (strcmp((char*)adr, "cancel") == 0) { + if (commandRunning) { + if (!commandEndRequested) { + commandEndRequested=1; + hts_request_stop(0); + } else { + hts_request_stop(1); /* note: the force flag does not have anyeffect yet */ + commandEndRequested=2; /* will break the loop() callback */ + } + } + } else if ((p=strfield((char*)adr, "cancel-file="))) { + if (commandRunning) { + hts_cancel_file((char*)adr + p); + } + } else if (strcmp((char*)adr, "cancel-parsing") == 0) { + if (commandRunning) { + hts_cancel_parsing(); + } + } else if ((p=strfield((char*)adr, "pause="))) { + if (commandRunning) { + hts_setpause(1); + } + } else if ((p=strfield((char*)adr, "unpause"))) { + if (commandRunning) { + hts_setpause(0); + } + } else if (strcmp((char*)adr, "abort") == 0) { + if (commandRunning) { + hts_request_stop(1); + commandEndRequested=2; /* will break the loop() callback */ + } + } else if ((p=strfield((char*)adr, "add-url="))) { + if (commandRunning) { + char* ptraddr[2]; + ptraddr[0] = (char*)adr + p; + ptraddr[1] = NULL; + hts_addurl(ptraddr); + } + } else if ((p=strfield((char*)adr, "httrack"))) { + if (!commandRunning) { + unsigned long int adrcd = 0; + if (inthash_readptr(NewLangList, "command_do", (long int *)&adrcd)) { + unsigned long int adrw = 0, adrpath = 0, adrprojname = 0; + if (inthash_readptr(NewLangList, "winprofile", (long int *)&adrw)) { + StringClear(&tmpbuff); + StringStrcat(&tmpbuff, StringBuff(&fspath)); + StringStrcat(&tmpbuff, "/hts-cache/"); + + /* Create minimal directory structure */ + if (!structcheck(StringBuff(&tmpbuff))) { + FILE* fp; + StringStrcat(&tmpbuff, "winprofile.ini"); + fp = fopen(StringBuff(&tmpbuff), "wb"); + if (fp != NULL) { + int count = (int) strlen((char*)adrw); + if ((int)fwrite((void*)adrw, 1, count, fp) == count) { + + /* Wipe the doit.log file, useless here (all options are replicated) and + even a bit annoying (duplicate/ghost options) + The behaviour is exactly the same as in WinHTTrack + */ + StringClear(&tmpbuff); + StringStrcat(&tmpbuff, StringBuff(&fspath)); + StringStrcat(&tmpbuff, "/hts-cache/doit.log"); + remove(StringBuff(&tmpbuff)); + + /* + RUN THE SERVER + */ + if (strcmp((char*)adrcd, "start") == 0) { + webhttrack_main((char*)adr + p); + } else { + commandRunning = 0; + commandEnd = 1; + } + } else { + char tmp[1024]; + sprintf(tmp, "Unable to write %d bytes in the the init file %s", count, StringBuff(&fspath)); + SET_ERROR(tmp); + } + fclose(fp); + } else { + char tmp[1024]; + sprintf(tmp, "Unable to create the init file %s", StringBuff(&fspath)); + SET_ERROR(tmp); + } + } else { + char tmp[1024]; + sprintf(tmp, "Unable to create the directory structure in %s", StringBuff(&fspath)); + SET_ERROR(tmp); + } + + } else { + SET_ERROR("Internal server error: unable to fetch project name or path"); + } + } + } + } else if (strcmp((char*)adr, "quit") == 0) { + willexit=1; + } + inthash_write(NewLangList, "command", (unsigned long int)NULL); + } + } + + /* Response */ + if (meth) { + int virtualpath = 0; + char* pos; + char* url = strchr(line1, ' '); + if (url && *++url == '/' && (pos = strchr(url, ' ')) && !(*pos = '\0') ) { + char fsfile[1024]; + char* file; + FILE* fp; + char* qpos; + + /* get the URL */ + if (error_redirect == NULL) { + if ( (qpos = strchr(url, '?')) ) { + *qpos = '\0'; + } + fsfile[0] = '\0'; + if (strcmp(url, "/") == 0) { + file = "/server/index.html"; + meth = 2; + } else { + file = url; + } + } else { + file = error_redirect; + meth = 2; + } + + if (strncmp(file, "/website/", 9) == 0) { + virtualpath = 1; + } + + if (commandRunning) { + if (!is_image(file)) { + file = "/server/refresh.html"; + } + } else if (commandEnd && !virtualpath && !willexit) { + if (!is_image(file)) { + file = "/server/finished.html"; + } + } + + if (strlen(path) + strlen(file) + 32 < sizeof(fsfile)) { + if (strncmp(file, "/website/", 9) != 0) { + sprintf(fsfile, "%shtml%s", path, file); + } else { + unsigned long int adr = 0; + if (inthash_readptr(NewLangList, "projpath", (long int *)&adr)) { + sprintf(fsfile, "%s%s", (char*)adr, file + 9); + } + } + } + + if (fsfile[0] && strstr(file, "..") == NULL && (fp = fopen(fsfile, "rb"))) { + char ok[] = "HTTP/1.0 200 OK\r\n" + "Connection: close\r\n" + "Server: httrack-small-server\r\n" + "Content-type: text/html\r\n" + "Cache-Control: no-cache, must-revalidate, private\r\n" + "Pragma: no-cache\r\n" + ; + char ok_img[] = "HTTP/1.0 200 OK\r\n" + "Connection: close\r\n" + "Server: httrack small server\r\n" + "Content-type: image/gif\r\n" + ; + char ok_text[] = "HTTP/1.0 200 OK\r\n" + "Connection: close\r\n" + "Server: httrack small server\r\n" + "Content-type: text/plain\r\n" + ; + + /* register current page */ + inthash_write(NewLangList, "thisfile", (unsigned long int)strdup(file)); + + /* Force GET for the last request */ + if (meth == 2 && willexit) { + meth = 1; + } + + /* posted data are redirected to get protocol */ + if (meth == 2) { + char redir[] = "HTTP/1.0 302 Redirect\r\n" + "Connection: close\r\n" + "Server: httrack-small-server\r\n"; + unsigned long int adr = 0; + char* newfile = file; + if (inthash_readptr(NewLangList, "redirect", (long int *)&adr) && adr != 0) { + char* newadr = (char*)adr; + if (*newadr) { + newfile = newadr; + } + } + StringMemcat(&headers, redir, strlen(redir)); + { + char tmp[256]; + if (strlen(file) < sizeof(tmp) - 32) { + sprintf(tmp, "Location: %s\r\n", newfile); + StringMemcat(&headers, tmp, strlen(tmp)); + } + } + inthash_write(NewLangList, "redirect", (unsigned long int)NULL); + } + else if (is_html(file)) { + int outputmode = 0; + StringMemcat(&headers, ok, sizeof(ok) - 1); + while(!feof(fp)) { + char* str = line; + int prevlen = StringLength(&output); + int nocr = 0; + if (!linput(fp, line, sizeof(line) - 2)) { + *str = '\0'; + } + if (*str && str[strlen(str) - 1] == '\\') { + nocr = 1; + str[strlen(str) - 1] = '\0'; + } + while(*str) { + char* pos; + int n; + if (*str == '$' && *++str == '{' && (pos = strchr(++str, '}')) && (n = (pos - str) ) && n < 1024 ) { + char name_[1024 + 2]; + char* name = name_; + char* langstr = NULL; + int p; + int format = 0; + int listDefault = 0; + name[0] = '\0'; + strncatbuff(name, str, n); + if (strncmp(name, "/*", 2) == 0) { + /* comments */ + } + else if (( p = strfield(name, "html:"))) { + name += p; + format = 1; + } + else if (( p = strfield(name, "list:"))) { + name += p; + format = 2; + } + else if (( p = strfield(name, "liststr:"))) { + name += p; + format = -2; + } + else if (( p = strfield(name, "file-exists:"))) { + char* pos2; + name += p; + format = 0; + pos2 = strchr(name, ':'); + langstr = ""; + if (pos2 != NULL) { + *pos2 = '\0'; + if (strstr(name, "..") == NULL) { + if (fexist(fconcat(path, name))) { + langstr = pos2 + 1; + } + } + } + } + else if (( p = strfield(name, "do:"))) { + char* pos2; + name += p; + format = 1; + pos2 = strchr(name, ':'); + langstr = ""; + if (pos2 != NULL) { + *pos2 = '\0'; + pos2++; + } else { + pos2=""; + } + if (strcmp(name, "output-mode") == 0) { + if (strcmp(pos2, "html") == 0) { + outputmode = 1; + } else if (strcmp(pos2, "inifile") == 0) { + outputmode = 2; + } else if (strcmp(pos2, "html-urlescaped") == 0) { + outputmode = 3; + } else { + outputmode = 0; + } + } else if (strcmp(name, "if-file-exists") == 0) { + if (strstr(pos2, "..") == NULL) { + if (!fexist(fconcat(path, pos2))) { + outputmode = -1; + } + } + } else if (strcmp(name, "if-project-file-exists") == 0) { + if (strstr(pos2, "..") == NULL) { + if (!fexist(fconcat(StringBuff(&fspath), pos2))) { + outputmode = -1; + } + } + } else if (strcmp(name, "if-file-do-not-exists") == 0) { + if (strstr(pos2, "..") == NULL) { + if (fexist(fconcat(path, pos2))) { + outputmode = -1; + } + } + } else if (strcmp(name, "if-not-empty") == 0) { + unsigned long int adr = 0; + if (!inthash_readptr(NewLangList, pos2, (long int *)&adr) || *((char*)adr) == 0 ) { + outputmode = -1; + } + } else if (strcmp(name, "if-empty") == 0) { + unsigned long int adr = 0; + if (inthash_readptr(NewLangList, pos2, (long int *)&adr) && *((char*)adr) != 0 ) { + outputmode = -1; + } + } else if (strcmp(name, "end-if") == 0) { + outputmode = 0; + } else if (strcmp(name, "loadhash") == 0) { + unsigned long int adr = 0; + if (inthash_readptr(NewLangList, "path", (long int *)&adr)) { + char* rpath = (char*) adr; + find_handle h; + if (rpath[0]) { + if (rpath[strlen(rpath)-1]=='/') { + rpath[strlen(rpath)-1]='\0'; /* note: patching stored (inhash) value */ + } + } + h = hts_findfirst(rpath); + if (h) { + struct topindex_chain * chain=NULL; + struct topindex_chain * startchain=NULL; + StringClear(&tmpbuff); + do { + if (hts_findisdir(h)) { + char iname[HTS_URLMAXSIZE*2]; + strcpybuff(iname,rpath); + strcatbuff(iname,"/"); + strcatbuff(iname,hts_findgetname(h)); + strcatbuff(iname,"/hts-cache/winprofile.ini"); + if (fexist(iname)) { + if (StringLength(&tmpbuff) > 0) { + StringStrcat(&tmpbuff, "\r\n"); + } + StringStrcat(&tmpbuff, hts_findgetname(h)); + } + + } + } while(hts_findnext(h)); + hts_findclose(h); + inthash_write(NewLangList, "winprofile", (unsigned long int)StringAcquire(&tmpbuff)); + } + } + } else if (strcmp(name, "copy") == 0) { + if (*pos2) { + char* pos3 = strchr(pos2, ':'); + if ( pos3 && *(pos3 + 1) ) { + unsigned long int adr = 0; + *pos3++ = '\0'; + if (inthash_readptr(NewLangList, pos2, (long int *)&adr)) { + inthash_write(NewLangList, pos3, (unsigned long int)strdup((char*)adr)); + inthash_write(NewLangList, pos2, (unsigned long int)NULL); + } + } + } + } else if (strcmp(name, "set") == 0) { + if (*pos2) { + char* pos3 = strchr(pos2, ':'); + if ( pos3 ) { + *pos3++ = '\0'; + inthash_write(NewLangList, pos2, (unsigned long int)strdup(pos3)); + } else { + inthash_write(NewLangList, pos2, (unsigned long int)NULL); + } + } + } + } + /* + test:<if exist> + test:<if ==0>:<if ==1>:<if == 2>.. + ztest:<if == 0 || !exist>:<if == 1>:<if == 2>.. + */ + else if ( ( p = strfield(name, "test:")) || ( p = strfield(name, "ztest:")) ) { + unsigned long int adr = 0; + char* pos2; + int ztest = (name[0] == 'z'); + langstr = ""; + name += p; + pos2 = strchr(name, ':'); + if (pos2 != NULL) { + *pos2 = '\0'; + if (inthash_readptr(NewLangList, name, (long int *)&adr) || ztest) { + char* newadr = (char*)adr; + if (!newadr) + newadr = ""; + if (*newadr || ztest) { + int npos = 0; + name = pos2 + 1; + format = 4; + if (strchr(name, ':') == NULL) { + npos = 0; /* first is good if only one : */ + format = 0; + } else { + if (sscanf(newadr, "%d", &npos) != 1) { + if (strfield(newadr, "on")) { + npos = 1; + } else { + npos = 0; /* first one will be ok */ + format = 0; + } + } + } + while( *name && *name != '}' && npos >= 0) { + int end=0; + char* fpos = strchr(name, ':'); + int n2; + if (fpos == NULL) { + fpos = name + strlen(name); + end=1; + } + n2 = (int) (fpos - name); + if (npos == 0) { + langstr = name; + *fpos='\0'; + } else if (end) { + npos=0; + } + name += n2 + 1; + npos--; + } + } + } + } + } + else if (( p = strfield(name, "listid:"))) { + char* pos2; + name += p; + format = 2; + pos2 = strchr(name, ':'); + if (pos2) { + char dname[32]; + int n2 = (int) (pos2 - name); + if (n2 > 0 && n2 < sizeof(dname) - 2) { + unsigned long int adr = 0; + dname[0] = '\0'; + strncatbuff(dname, name, n2); + if (inthash_readptr(NewLangList, dname, (long int *)&adr)) { + int n = 0; + if (sscanf((char*)adr, "%d", &n) == 1) { + listDefault = n; + } + } + name += n2 + 1; + } + } + } + else if (( p = strfield(name, "checked:"))) { + name += p; + format = 3; + } + if (langstr == NULL) { + if (strfield2(name, "#iso")) { + langstr = line2; + langstr[0] = '\0'; + LANG_LIST(path, langstr); + assertf(strlen(langstr) < sizeof(line2) - 2); + } else { + langstr = LANGSEL(name); + if (langstr == NULL || *langstr == '\0') { + unsigned long int adr = 0; + if (inthash_readptr(NewLangList, name, (long int *)&adr)) { + char* newadr = (char*)adr; + langstr = newadr; + } + } + } + } + if (langstr && outputmode != -1) { + switch(format) { + case 0: + { + char* a = langstr; + while(*a) { + if (a[0] == '\\' && isxdigit(a[1]) && isxdigit(a[2])) { + int n; + char c; + if (sscanf(a+1, "%x", &n) == 1) { + c = (char)n; + StringMemcat(&output, &c, 1); + } + a += 2; + } else if (outputmode && a[0] == '<') { + StringStrcat(&output, "<"); + } else if (outputmode && a[0] == '>') { + StringStrcat(&output, ">"); + } else if (outputmode && a[0] == '&') { + StringStrcat(&output, "&"); + } else if (outputmode == 3 && a[0] == ' ') { + StringStrcat(&output, "%20"); + } else if (outputmode >= 2 && ((unsigned char)a[0]) < 32) { + char tmp[32]; + sprintf(tmp, "%%%02x", (unsigned char)a[0]); + StringStrcat(&output, tmp); + } else if (outputmode == 2 && a[0] == '%') { + StringStrcat(&output, "%%"); + } else if (outputmode == 3 && a[0] == '%') { + StringStrcat(&output, "%25"); + } else { + StringMemcat(&output, a, 1); + } + a++; + } + } + break; + case 3: + if (*langstr) { + StringStrcat(&output, "checked"); + } + break; + default: + if (*langstr) { + int id=1; + char* fstr = langstr; + StringClear(&tmpbuff); + if (format == 2) { + StringStrcat(&output, "<option value=1>"); + } else if (format == -2) { + StringStrcat(&output, "<option value=\""); + } + while(*fstr) { + switch(*fstr) { + case 13: break; + case 10: + if (format == 1) { + StringStrcat(&output, StringBuff(&tmpbuff)); + StringStrcat(&output, "<br>\r\n"); + } else if (format == -2) { + StringStrcat(&output, StringBuff(&tmpbuff)); + StringStrcat(&output, "\">"); + StringStrcat(&output, StringBuff(&tmpbuff)); + StringStrcat(&output, "</option>\r\n"); + StringStrcat(&output, "<option value=\""); + } else { + char tmp[32]; + sprintf(tmp, "%d", ++id); + StringStrcat(&output, StringBuff(&tmpbuff)); + StringStrcat(&output, "</option>\r\n"); + StringStrcat(&output, "<option value="); + StringStrcat(&output, tmp); + if (listDefault == id) { + StringStrcat(&output, " selected"); + } + StringStrcat(&output, ">"); + } + StringClear(&tmpbuff); + break; + case '<': + StringStrcat(&tmpbuff, "<"); + break; + case '>': + StringStrcat(&tmpbuff, ">"); + break; + case '&': + StringStrcat(&tmpbuff, "&"); + break; + default: + StringMemcat(&tmpbuff, fstr, 1); + break; + } + fstr++; + } + if (format == 2) { + StringStrcat(&output, StringBuff(&tmpbuff)); + StringStrcat(&output, "</option>"); + } else if (format == -2) { + StringStrcat(&output, StringBuff(&tmpbuff)); + StringStrcat(&output, "\">"); + StringStrcat(&output, StringBuff(&tmpbuff)); + StringStrcat(&output, "</option>"); + } else { + StringStrcat(&output, StringBuff(&tmpbuff)); + } + StringClear(&tmpbuff); + } + } + } + str = pos; + } else { + if (outputmode != -1) { + StringMemcat(&output, str, 1); + } + } + str++; + } + if (!nocr && prevlen != StringLength(&output)) { + StringStrcat(&output, "\r\n"); + } + } +#ifdef _DEBUG + { + int len = (int)strlen((char*)StringBuff(&output)); + assert(len == (int)StringLength(&output)); + } +#endif + } else if (is_text(file)) { + StringMemcat(&headers, ok_text, sizeof(ok_text) - 1); + while(!feof(fp)) { + int n = fread(line, 1, sizeof(line) - 2, fp); + if (n > 0) { + StringMemcat(&output, line, n); + } + } + } else { + StringMemcat(&headers, ok_img, sizeof(ok_img) - 1); + while(!feof(fp)) { + int n = fread(line, 1, sizeof(line) - 2, fp); + if (n > 0) { + StringMemcat(&output, line, n); + } + } + } + fclose(fp); + } else { + char error_hdr[] = "HTTP/1.0 404 Not Found\r\n" + "Server: httrack small server\r\n" + "Content-type: text/html\r\n"; + char error[] = + "Page not found.\r\n"; + StringStrcat(&headers, error_hdr); + StringStrcat(&output, error); + //assert(file == NULL); + } + } + } else { +#ifdef _DEBUG + char error_hdr[] = "HTTP/1.0 500 Server Error\r\n" + "Server: httrack small server\r\n" + "Content-type: text/html\r\n"; + char error[] = + "Server error.\r\n"; + StringStrcat(&headers, error_hdr); + StringStrcat(&output, error); +#endif + } + { + char tmp[256]; + sprintf(tmp, "Content-length: %d\r\n", (int) StringLength(&output)); + StringStrcat(&headers, tmp); + } + StringStrcat(&headers, "\r\n"); + if ( + (send(soc_c, StringBuff(&headers), StringLength(&headers), 0) != StringLength(&headers)) + || + ( (meth == 1) && (send(soc_c, StringBuff(&output), StringLength(&output), 0) != StringLength(&output)) ) + ) { +#ifdef _DEBUG + //assert(FALSE); +#endif + } + } else { +#ifdef _DEBUG + // assert(FALSE); +#endif + } + + /* Shutdown (FIN) and wait until confirmed */ + { + char c; +#ifdef _WIN32 + shutdown(soc_c, SD_SEND); +#else + shutdown(soc_c, 1); +#endif + /* This is necessary as IE sometimes (!) sends an additional CRLF after POST data */ + while(recv(soc_c, ((char*)&c), 1, 0) > 0); + } + +#if HTS_WIN + closesocket(soc_c); +#else + close(soc_c); +#endif + } + + if (soc != INVALID_SOCKET) { +#ifdef _WIN32 + closesocket(soc); +#else + close(soc); +#endif + } + + StringFree(&headers); + StringFree(&output); + StringFree(&tmpbuff); + StringFree(&fspath); + + if (buffer) + free(buffer); + + if (commandReturnMsg) + free(commandReturnMsg); + commandReturnMsg = NULL; + if (commandReturnCmdl) + free(commandReturnCmdl); + commandReturnCmdl = NULL; + + /* Unlock */ + webhttrack_lock(0); + + return retour; +} + + + +/* Language files */ + + +int htslang_init() { + if (NewLangList==NULL) { + int i = 0; + NewLangList=inthash_new(NewLangListSz); + if (NewLangList==NULL) { + abortLog("Error in lang.h: not enough memory"); + } else { + inthash_value_is_malloc(NewLangList,1); + } + } + return 1; +} + +int htslang_uninit() { + if (NewLangList!=NULL) { + inthash_delete(&NewLangList); + } + return 1; +} + +int htslang_load(char* limit_to, char* path) { + char* hashname; + // + int selected_lang=LANG_T(path, -1); + // + if (!limit_to) { + LANG_DELETE(); + NewLangStr=inthash_new(NewLangStrSz); + NewLangStrKeys=inthash_new(NewLangStrKeysSz); + if ((NewLangStr==NULL) || (NewLangStrKeys==NULL)) { + abortLog("Error in lang.h: not enough memory"); + } else { + inthash_value_is_malloc(NewLangStr,1); + inthash_value_is_malloc(NewLangStrKeys,1); + } + } + + /* Load master file (list of keys and internal keys) */ + if (!limit_to) { + char* mname = "lang.def"; + FILE* fp=fopen(fconcat(path, mname),"rb"); + if (fp) { + char intkey[8192]; + char key[8192]; + while(!feof(fp)) { + linput_cpp(fp,intkey,8000); + linput_cpp(fp,key,8000); + if (strnotempty(intkey) && strnotempty(key)) { + char* test=LANGINTKEY(key); + + /* Increment for multiple definitions */ + if (strnotempty(test)) { + int increment=0; + int pos=strlen(key); + do { + increment++; + sprintf(key+pos,"%d",increment); + test=LANGINTKEY(key); + } while (strnotempty(test)); + } + + if (!strnotempty(test)) { // éviter doublons + // conv_printf(key,key); + int len; + char* buff; + len=strlen(intkey); + buff=(char*)malloc(len+2); + if (buff) { + strcpybuff(buff,intkey); + inthash_add(NewLangStrKeys,key,(long int)(char*)buff); + } + } + } // if + } // while + fclose(fp); + } else { + return 0; + } + } + + /* Language Name? */ + { + char name[256]; + sprintf(name,"LANGUAGE_%d",selected_lang+1); + hashname=LANGINTKEY(name); + } + + /* Get only language name */ + if (limit_to) { + if (hashname) + strcpybuff(limit_to, hashname); + else + strcpybuff(limit_to, "???"); + return 0; + } + + /* Error */ + if (!hashname) + return 0; + + /* Load specific language file */ + { + int loops; + // 2nd loop: load undefined strings + for(loops=0;loops<2;loops++) { + FILE* fp; + char lbasename[1024]; + { + char name[256]; + sprintf(name,"LANGUAGE_%d",(loops==0)?(selected_lang+1):1); + hashname=LANGINTKEY(name); + } + sprintf(lbasename, "lang/%s.txt",hashname); + fp=fopen(fconcat(path, lbasename), "rb"); + if (fp) { + char extkey[8192]; + char value[8192]; + while(!feof(fp)) { + linput_cpp(fp,extkey,8000); + linput_cpp(fp,value,8000); + if (strnotempty(extkey) && strnotempty(value)) { + int len; + char* buff; + char* intkey; + + intkey=LANGINTKEY(extkey); + + if (strnotempty(intkey)) { + + /* Increment for multiple definitions */ + { + char* test=LANGSEL(intkey); + if (strnotempty(test)) { + if (loops == 0) { + int increment=0; + int pos=strlen(extkey); + do { + increment++; + sprintf(extkey+pos,"%d",increment); + intkey=LANGINTKEY(extkey); + if (strnotempty(intkey)) + test=LANGSEL(intkey); + else + test=""; + } while (strnotempty(test)); + } else + intkey=""; + } else { + if (loops > 0) { + //err_msg += intkey; + //err_msg += " "; + } + } + } + + /* Add key */ + if (strnotempty(intkey)) { + len=strlen(value); + buff=(char*)malloc(len+2); + if (buff) { + conv_printf(value,buff); + inthash_add(NewLangStr,intkey,(long int)(char*)buff); + } + } + + } + } // if + } // while + fclose(fp); + } else { + return 0; + } + } + } + + // Control limit_to + if (limit_to) + limit_to[0]='\0'; + + return 1; +} + +/* NOTE : also contains the "webhttrack" hack */ +void conv_printf(char* from,char* to) { + int i=0,j=0,len; + len=strlen(from); + while(i<len) { + switch(from[i]) { + case '\\': + i++; + switch(from[i]) { + case 'a': to[j]='\a'; break; + case 'b': to[j]='\b'; break; + case 'f': to[j]='\f'; break; + case 'n': to[j]='\n'; break; + case 'r': to[j]='\r'; break; + case 't': to[j]='\t'; break; + case 'v': to[j]='\v'; break; + case '\'': to[j]='\''; break; + case '\"': to[j]='\"'; break; + case '\\': to[j]='\\'; break; + case '?': to[j]='\?'; break; + default: to[j]=from[i]; break; + } + break; + default: + to[j]=from[i]; + break; + } + i++; + j++; + } + to[j++]='\0'; + /* Dirty hack */ + { + char * a = to; + while((a = strstr(a, "WinHTTrack"))) { + a[0] = 'W'; + a[1] = 'e'; + a[2] = 'b'; + a++; + } + } +} + +void LANG_DELETE() { + inthash_delete(&NewLangStr); + inthash_delete(&NewLangStrKeys); +} + +// sélection de la langue +void LANG_INIT(char* path) { + //CWinApp* pApp = AfxGetApp(); + //if (pApp) { + int test = 0; /* pApp->GetProfileInt("Language","IntId",0); */ + LANG_T(path, 0 /*pApp->GetProfileInt("Language","IntId",0)*/ ); + //} +} + +int LANG_T(char* path, int l) { + if (l>=0) { + QLANG_T(l); + htslang_load(NULL, path); + } + return QLANG_T(-1); // 0=default (english) +} + +int LANG_SEARCH(char* path, char* iso) { + char lang_str[1024]; + int i = 0; + int curr_lng=LANG_T(path, -1); + int found = 0; + unsigned long int adr = 0; + do { + QLANG_T(i); + strcpybuff(lang_str,"LANGUAGE_ISO"); + htslang_load(lang_str, path); + if (strfield(iso, lang_str)) { + found = i; + } + i++; + } while(strlen(lang_str) > 0); + QLANG_T(curr_lng); + return found; +} + +int LANG_LIST(char* path, char* buffer) { + char lang_str[1024]; + int i = 0; + int curr_lng=LANG_T(path, -1); + int found = 0; + buffer[0] = '\0'; + do { + QLANG_T(i); + strcpybuff(lang_str, "LANGUAGE_NAME"); + htslang_load(lang_str, path); + if (strlen(lang_str) > 0) { + if (buffer[0]) + strcatbuff(buffer, "\n"); + strcatbuff(buffer, lang_str); + } + i++; + } while(strlen(lang_str) > 0); + QLANG_T(curr_lng); + return i; +} + +int QLANG_T(int l) { + static int lng=0; + if (l>=0) { + lng=l; + } + return lng; // 0=default (english) +} + +char* LANGSEL(char* name) { + unsigned long int adr = 0; + if (NewLangStr) + if (!inthash_read(NewLangStr,name,(long int *)&adr)) + adr=0; + if (adr) { + return (char*)adr; + } + return ""; +} + +char* LANGINTKEY(char* name) { + unsigned long int adr=0; + if (NewLangStrKeys) + if (!inthash_read(NewLangStrKeys,name,(long int *)&adr)) + adr=0; + if (adr) { + return (char*)adr; + } + return ""; +} + +char* gethomedir(void) { + char* home = getenv( "HOME" ); + if (home) + return home; + else + return "."; +} + +int linput_cpp(FILE* fp,char* s,int max) { + int rlen=0; + s[0]='\0'; + do { + int ret; + if (rlen>0) + if (s[rlen-1]=='\\') + s[--rlen]='\0'; // couper \ final + // lire ligne + ret=linput_trim(fp,s+rlen,max-rlen); + if (ret>0) + rlen+=ret; + } while((s[max(rlen-1,0)]=='\\') && (rlen<max)); + return rlen; +} + +// copy of concat +typedef struct { + char buff[16][HTS_URLMAXSIZE*2*2]; + int rol; +} concat_strc; +char* concat(const char* a,const char* b) { + static concat_strc* strc = NULL; + if (strc == NULL) { + strc = (concat_strc*) calloc(16, sizeof(concat_strc)); + } + strc->rol=((strc->rol+1)%16); // roving pointer + strcpybuff(strc->buff[strc->rol],a); + if (b) strcatbuff(strc->buff[strc->rol],b); + return strc->buff[strc->rol]; +} +#ifdef _WIN32 +char* __fconv(char* a) { + int i; + for(i=0;i<(int) strlen(a);i++) + if (a[i]=='/') // convertir + a[i]='\\'; + return a; +} +char* fconcat(char* a,char* b) { + return __fconv(concat(a,b)); +} +char* fconv(char* a) { + return __fconv(concat(a,"")); +} +#endif + +/* *** Various functions *** */ + + +int fexist(char* s) { + struct stat st; + memset(&st, 0, sizeof(st)); + if (stat(s, &st) == 0) { + if (S_ISREG(st.st_mode)) { + return 1; + } + } + return 0; +} + +int linput(FILE* fp,char* s,int max) { + int c; + int j=0; + do { + c=fgetc(fp); + if (c!=EOF) { + switch(c) { + case 13: break; // sauter CR + case 10: c=-1; break; + case 0: case 9: case 12: break; // sauter ces caractères + default: s[j++]=(char) c; break; + } + } + } while((c!=-1) && (c!=EOF) && (j<(max-1))); + s[j]='\0'; + return j; +} + +int linput_trim(FILE* fp,char* s,int max) { + int rlen=0; + char* ls=(char*) malloct(max+2); + s[0]='\0'; + if (ls) { + char* a; + // lire ligne + rlen=linput(fp,ls,max); + if (rlen) { + // sauter espaces et tabs en fin + while( (rlen>0) && is_realspace(ls[max(rlen-1,0)]) ) + ls[--rlen]='\0'; + // sauter espaces en début + a=ls; + while((rlen>0) && ((*a==' ') || (*a=='\t'))) { + a++; + rlen--; + } + if (rlen>0) { + memcpy(s,a,rlen); // can copy \0 chars + s[rlen]='\0'; + } + } + // + freet(ls); + } + return rlen; +} + +int linputsoc(T_SOC soc, char* s, int max) { + int c; + int j=0; + do { + unsigned char ch; + if (recv(soc, &ch, 1, 0) == 1) { + c = ch; + } else { + c = EOF; + } + if (c!=EOF) { + switch(c) { + case 13: break; // sauter CR + case 10: c=-1; break; + case 9: case 12: break; // sauter ces caractères + default: s[j++]=(char) c; break; + } + } + } while((c!=-1) && (c!=EOF) && (j<(max-1))); + s[j]='\0'; + return j; +} + +int linputsoc_t(T_SOC soc, char* s, int max, int timeout) { + if (check_readinput_t(soc, timeout)) { + return linputsoc(soc, s, max); + } + return -1; +} + +// check if data is available +int check_readinput(htsblk* r) { + if (r->soc != INVALID_SOCKET) { + fd_set fds; // poll structures + struct timeval tv; // structure for select + FD_ZERO(&fds); + FD_SET(r->soc,&fds); + tv.tv_sec=0; + tv.tv_usec=0; + select(r->soc + 1,&fds,NULL,NULL,&tv); + if (FD_ISSET(r->soc,&fds)) + return 1; + else + return 0; + } else + return 0; +} + +// check if data is available +int check_readinput_t(T_SOC soc, int timeout) { + if (soc != INVALID_SOCKET) { + fd_set fds; // poll structures + struct timeval tv; // structure for select + FD_ZERO(&fds); + FD_SET(soc,&fds); + tv.tv_sec=timeout; + tv.tv_usec=0; + select(soc + 1,&fds,NULL,NULL,&tv); + if (FD_ISSET(soc,&fds)) + return 1; + else + return 0; + } else + return 0; +} + +int strfield(const char* f,const char* s) { + int r=0; + while (streql(*f,*s) && ((*f)!=0) && ((*s)!=0)) { f++; s++; r++; } + if (*s==0) + return r; + else + return 0; +} + +int ehexh(char c) { + if ((c>='0') && (c<='9')) return c-'0'; + if ((c>='a') && (c<='f')) c-=('a'-'A'); + if ((c>='A') && (c<='F')) return (c-'A'+10); + return 0; +} + +int ehex(char* s) { + return 16*ehexh(*s)+ehexh(*(s+1)); +} + +void unescapehttp(char* s, String* tempo) { + int i; + for (i=0;i<(int) strlen(s);i++) { + if (s[i]=='%' && s[i+1]=='%') { + i++; + StringAddchar(tempo, '%'); + } else if (s[i]=='%') { + char hc; + i++; + hc = (char) ehex(s+i); + StringAddchar(tempo, (char) hc); + i++; // sauter 2 caractères finalement + } + else if (s[i]=='+') { + StringAddchar(tempo, ' '); + } + else + StringAddchar(tempo, s[i]); + } +} + +/* same, except + */ +void unescapeini(char* s, String* tempo) { + int i; + char lastc=0; + for (i=0;i<(int) strlen(s);i++) { + if (s[i]=='%' && s[i+1]=='%') { + i++; + StringAddchar(tempo, lastc = '%'); + } else if (s[i]=='%') { + char hc; + i++; + hc = (char) ehex(s+i); + if (!is_retorsep(hc) || !is_retorsep(lastc)) { + StringAddchar(tempo, lastc = (char) hc); + } + i++; // sauter 2 caractères finalement + } + else + StringAddchar(tempo, lastc = s[i]); + } +} + |