/* ------------------------------------------------------------ */ /* 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 #include #include #include #include #if HTS_WIN #else #include #endif #ifndef _WIN32 #include #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", "" }, { "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 : / */ 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: test:::.. ztest:::.. */ 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, "\r\n"); StringStrcat(&output, ""); } else if (format == -2) { StringStrcat(&output, StringBuff(&tmpbuff)); StringStrcat(&output, "\">"); StringStrcat(&output, StringBuff(&tmpbuff)); StringStrcat(&output, ""); } 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(iGetProfileInt("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)]=='\\') && (rlenrol=((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]); } }