/* ------------------------------------------------------------ */ /* HTTrack Website Copier, Offline Browser for Windows and Unix Copyright (C) 1998-2013 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 3 of the License, or (at your option) 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, see . 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 */ /* Bypass internal definition protection */ #define HTS_INTERNAL_BYTECODE #include "htsbase.h" #undef HTS_INTERNAL_BYTECODE #include "htsnet.h" #include "htslib.h" #include #include #include #include #include #ifdef _WIN32 #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 */ /* Bypass internal definition protection */ #define HTS_INTERNAL_BYTECODE #include "htsinthash.h" #undef HTS_INTERNAL_BYTECODE 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; httrackp *global_opt = NULL; /* Extern */ extern void webhttrack_main(char *cmd); extern void webhttrack_lock(void); extern void webhttrack_release(void); 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 */ } HTS_UNUSED static int check_readinput_t(T_SOC soc, int timeout); HTS_UNUSED static int recv_bl(T_SOC soc, void *buffer, size_t len, int timeout); HTS_UNUSED static int linputsoc(T_SOC soc, char *s, int max); HTS_UNUSED static int check_readinput(htsblk * r); HTS_UNUSED static int linputsoc_t(T_SOC soc, char *s, int max, int timeout); HTS_UNUSED static int linput(FILE * fp, char *s, int max); /* Language files */ HTS_UNUSED static int htslang_load(char *limit_to, char *apppath); HTS_UNUSED static void conv_printf(char *from, char *to); HTS_UNUSED static void LANG_DELETE(void); HTS_UNUSED static void LANG_INIT(char *path); HTS_UNUSED static int LANG_T(char *path, int l); HTS_UNUSED static int QLANG_T(int l); HTS_UNUSED static char *LANGSEL(char *name); HTS_UNUSED static char *LANGINTKEY(char *name); HTS_UNUSED static int LANG_SEARCH(char *path, char *iso); HTS_UNUSED static int LANG_LIST(char *path, char *buffer); // 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, int defaultPort) { T_SOC soc; if (defaultPort <= 0) { int try_to_listen_to[] = { 8080, 8081, 8082, 8083, 8084, 8085, 8086, 8087, 8088, 8089, 32000, 32001, 32002, 32003, 32004, 32006, 32006, 32007, 32008, 32009, 42000, 42001, 42002, 42003, 42004, 42006, 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)); } else { soc = smallserver_init(&defaultPort, adr_prox); *port_prox = defaultPort; } return soc; } // 1- Init the URL catcher // get hostname. return 1 upon success. static int gethost(const char *hostname, SOCaddr * server, size_t server_size) { if (hostname != NULL && *hostname != '\0') { #if HTS_INET6==0 /* ipV4 resolver */ t_hostent *hp = gethostbyname(hostname); if (hp != NULL) { if (hp->h_length) { SOCaddr_copyaddr(*server, server_size, hp->h_addr_list[0], hp->h_length); return 1; } } #else /* ipV6 resolver */ struct addrinfo *res = NULL; struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; if (getaddrinfo(hostname, NULL, &hints, &res) == 0) { if (res) { if ((res->ai_addr) && (res->ai_addrlen)) { SOCaddr_copyaddr(*server, server_size, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); return 1; } } } if (res) { freeaddrinfo(res); } #endif } return 0; } static int my_getlocalhost(char *h_loc, size_t size) { SOCaddr addr; strcpy(h_loc, "localhost"); if (gethost(h_loc, &addr, sizeof(addr)) == 1) { return 0; } // come on ... else { strcpy(h_loc, "127.0.0.1"); return 0; } } // get local hostname; falls back to "localhost" in case of error // always returns 0 static int my_gethostname(char *h_loc, size_t size) { h_loc[0] = '\0'; if (gethostname(h_loc, (int) size) == 0) { // host name SOCaddr addr; if (gethost(h_loc, &addr, sizeof(addr)) == 1) { return 0; } else { return my_getlocalhost(h_loc, size); } } else { return my_getlocalhost(h_loc, size); } return 0; } // 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 (my_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)) ) */ { // 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 = (T_SOC) socket(SOCaddr_sinfamily(server), SOCK_STREAM, 0)) != INVALID_SOCKET) { SOCaddr_initport(server, *port); if (bind(soc, (struct sockaddr *) &server, server_size) == 0) { /*SOClen 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 // check if data is available // 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; #define SET_ERROR(err) do { \ inthash_write(NewLangList, "error", (intptr_t)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 tmpbuff2 = STRING_EMPTY; String fspath = STRING_EMPTY; char catbuff[CATBUFF_SIZE]; /* 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", "urlhack", "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 +*.jpeg +*.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, (intptr_t) strdup(tmp)); } for(i = 0; initOn[i]; i++) { inthash_write(NewLangList, initOn[i], (intptr_t) strdup("1")); /* "on" */ } for(i = 0; initStr[i].name; i++) { inthash_write(NewLangList, initStr[i].name, (intptr_t) strdup(initStr[i].value)); } strcpybuff(pth, gethomedir()); strcatbuff(pth, "/websites"); inthash_write(NewLangList, "path", (intptr_t) strdup(pth)); } /* Lock */ webhttrack_lock(); // connexion (accept) while(!willexit && buffer != NULL && soc != INVALID_SOCKET) { char line1[1024]; char line[8192]; char line2[1024]; T_SOC soc_c; LLint length = 0; char *error_redirect = NULL; line[0] = '\0'; buffer[0] = '\0'; StringClear(headers); StringClear(output); StringClear(tmpbuff); StringClear(tmpbuff2); StringClear(fspath); StringCat(headers, ""); StringCat(output, ""); StringCat(tmpbuff, ""); StringCat(tmpbuff2, ""); StringCat(fspath, ""); /* UnLock */ webhttrack_release(); /* sigpipe */ #ifndef _WIN32 signal(SIGPIPE, sig_brpipe); #endif /* Accept */ while((soc_c = (T_SOC) accept(soc, NULL, NULL)) == INVALID_SOCKET) ; /* Lock */ webhttrack_lock(); 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", (intptr_t) strdup(tmp)); inthash_write(NewLangList, "commandReturnMsg", (intptr_t) commandReturnMsg); inthash_write(NewLangList, "commandReturnCmdl", (intptr_t) commandReturnCmdl); } else { inthash_write(NewLangList, "commandReturn", (intptr_t) NULL); inthash_write(NewLangList, "commandReturnMsg", (intptr_t) NULL); inthash_write(NewLangList, "commandReturnCmdl", (intptr_t) NULL); } } /* SID check */ { intptr_t adr = 0; if (inthash_readptr(NewLangList, "_sid", &adr)) { if (inthash_write (NewLangList, "sid", (intptr_t) 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; String sua = STRING_EMPTY; *e = *f = '\0'; ua = e + 1; if (strfield2(ua, "on")) /* hack : "on" == 1 */ ua = "1"; unescapehttp(ua, &sua); inthash_write(NewLangList, s, (intptr_t) StringAcquire(&sua)); s = f + 1; } } /* Error check */ { intptr_t adr = 0; intptr_t adr2 = 0; if (inthash_readptr(NewLangList, "sid", &adr)) { if (inthash_readptr(NewLangList, "_sid", &adr2)) { if (strcmp((char *) adr, (char *) adr2) != 0) { meth = 0; } } } } /* Check variables (internal) */ if (meth) { int doLoad = 0; intptr_t adr = 0; if (inthash_readptr(NewLangList, "lang", &adr)) { int n = 0; if (sscanf((char *) adr, "%d", &n) == 1 && n > 0 && n - 1 != LANG_T(path, -1)) { LANG_T(path, n - 1); /* make a backup, because the GUI will override it */ inthash_write(NewLangList, "lang_", (intptr_t) strdup((char *) adr)); } } /* Load existing project settings */ if (inthash_readptr(NewLangList, "loadprojname", &adr)) { char *pname = (char *) adr; if (*pname) { inthash_write(NewLangList, "projname", (intptr_t) strdup(pname)); } inthash_write(NewLangList, "loadprojname", (intptr_t) NULL); doLoad = 1; } else if (inthash_readptr(NewLangList, "loadprojcateg", &adr)) { char *pname = (char *) adr; if (*pname) { inthash_write(NewLangList, "projcateg", (intptr_t) strdup(pname)); } inthash_write(NewLangList, "loadprojcateg", (intptr_t) NULL); } /* intial configuration */ { if (!inthash_read(NewLangList, "conf_file_loaded", NULL)) { inthash_write(NewLangList, "conf_file_loaded", (intptr_t) strdup("true")); doLoad = 2; } } /* path : / */ if (!commandRunning) { intptr_t adrpath = 0, adrprojname = 0; if (inthash_readptr(NewLangList, "path", &adrpath) && inthash_readptr(NewLangList, "projname", &adrprojname)) { StringClear(fspath); StringCat(fspath, (char *) adrpath); StringCat(fspath, "/"); StringCat(fspath, (char *) adrprojname); } } /* Load existing project settings */ if (doLoad) { FILE *fp; if (doLoad == 1) { StringCat(fspath, "/hts-cache/winprofile.ini"); } else if (doLoad == 2) { StringCopy(fspath, gethomedir()); #ifdef _WIN32 StringCat(fspath, "/httrack.ini"); #else StringCat(fspath, "/.httrack.ini"); #endif } 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, (intptr_t) StringAcquire(&escline)); } } fclose(fp); } } } /* Execute command */ { intptr_t adr = 0; int p = 0; if (inthash_readptr(NewLangList, "command", &adr)) { if (strcmp((char *) adr, "cancel") == 0) { if (commandRunning) { if (!commandEndRequested) { commandEndRequested = 1; hts_request_stop(global_opt, 0); } else { hts_request_stop(global_opt, 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_push(global_opt, (char *) adr + p); } } else if (strcmp((char *) adr, "cancel-parsing") == 0) { if (commandRunning) { hts_cancel_parsing(global_opt); } } else if ((p = strfield((char *) adr, "pause="))) { if (commandRunning) { hts_setpause(global_opt, 1); } } else if ((p = strfield((char *) adr, "unpause"))) { if (commandRunning) { hts_setpause(global_opt, 0); } } else if (strcmp((char *) adr, "abort") == 0) { if (commandRunning) { hts_request_stop(global_opt, 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(global_opt, ptraddr); } } else if ((p = strfield((char *) adr, "httrack"))) { if (!commandRunning) { intptr_t adrcd = 0; if (inthash_readptr(NewLangList, "command_do", &adrcd)) { intptr_t adrw = 0; if (inthash_readptr(NewLangList, "winprofile", &adrw)) { /* User general profile */ intptr_t adruserprofile = 0; if (inthash_readptr (NewLangList, "userprofile", &adruserprofile) && adruserprofile != 0) { int count = (int) strlen((char *) adruserprofile); if (count > 0) { FILE *fp; StringClear(tmpbuff); StringCopy(tmpbuff, gethomedir()); #ifdef _WIN32 StringCat(tmpbuff, "/httrack.ini"); #else StringCat(tmpbuff, "/.httrack.ini"); #endif fp = fopen(StringBuff(tmpbuff), "wb"); if (fp != NULL) { (void) ((int) fwrite((void *) adruserprofile, 1, count, fp)); fclose(fp); } } } /* Profile */ StringClear(tmpbuff); StringCat(tmpbuff, StringBuff(fspath)); StringCat(tmpbuff, "/hts-cache/"); /* Create minimal directory structure */ if (!structcheck(StringBuff(tmpbuff))) { FILE *fp; StringCat(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); StringCat(tmpbuff, StringBuff(fspath)); StringCat(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", (intptr_t) 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 { intptr_t adr = 0; if (inthash_readptr(NewLangList, "projpath", &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", (intptr_t) 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"; intptr_t adr = 0; char *newfile = file; if (inthash_readptr(NewLangList, "redirect", &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", (intptr_t) NULL); } else if (is_html(file)) { int outputmode = 0; StringMemcat(headers, ok, sizeof(ok) - 1); while(!feof(fp)) { char *str = line; int prevlen = (int) 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; size_t 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(catbuff, 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(catbuff, path, pos2))) { outputmode = -1; } } } else if (strcmp(name, "if-project-file-exists") == 0) { if (strstr(pos2, "..") == NULL) { if (!fexist (fconcat(catbuff, StringBuff(fspath), pos2))) { outputmode = -1; } } } else if (strcmp(name, "if-file-do-not-exists") == 0) { if (strstr(pos2, "..") == NULL) { if (fexist(fconcat(catbuff, path, pos2))) { outputmode = -1; } } } else if (strcmp(name, "if-not-empty") == 0) { intptr_t adr = 0; if (!inthash_readptr(NewLangList, pos2, &adr) || *((char *) adr) == 0) { outputmode = -1; } } else if (strcmp(name, "if-empty") == 0) { intptr_t adr = 0; if (inthash_readptr(NewLangList, pos2, &adr) && *((char *) adr) != 0) { outputmode = -1; } } else if (strcmp(name, "end-if") == 0) { outputmode = 0; } else if (strcmp(name, "loadhash") == 0) { intptr_t adr = 0; if (inthash_readptr(NewLangList, "path", &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 */ } } { const char *profiles = hts_getcategories(rpath, 0); const char *categ = hts_getcategories(rpath, 1); inthash_write(NewLangList, "winprofile", (intptr_t) profiles); inthash_write(NewLangList, "wincateg", (intptr_t) categ); } } } else if (strcmp(name, "copy") == 0) { if (*pos2) { char *pos3 = strchr(pos2, ':'); if (pos3 && *(pos3 + 1)) { intptr_t adr = 0; *pos3++ = '\0'; if (inthash_readptr(NewLangList, pos2, &adr)) { inthash_write(NewLangList, pos3, (intptr_t) strdup((char *) adr)); inthash_write(NewLangList, pos2, (intptr_t) NULL); } } } } else if (strcmp(name, "set") == 0) { if (*pos2) { char *pos3 = strchr(pos2, ':'); if (pos3) { *pos3++ = '\0'; inthash_write(NewLangList, pos2, (intptr_t) strdup(pos3)); } else { inthash_write(NewLangList, pos2, (intptr_t) NULL); } } } } /* test: test:::.. ztest:::.. */ else if ((p = strfield(name, "test:")) || (p = strfield(name, "ztest:"))) { intptr_t 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, &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) { intptr_t adr = 0; dname[0] = '\0'; strncatbuff(dname, name, n2); if (inthash_readptr(NewLangList, dname, &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') { intptr_t adr = 0; if (inthash_readptr(NewLangList, name, &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] == '<') { StringCat(output, "<"); } else if (outputmode && a[0] == '>') { StringCat(output, ">"); } else if (outputmode && a[0] == '&') { StringCat(output, "&"); } else if (outputmode == 3 && a[0] == ' ') { StringCat(output, "%20"); } else if (outputmode >= 2 && ((unsigned char) a[0]) < 32) { char tmp[32]; sprintf(tmp, "%%%02x", (unsigned char) a[0]); StringCat(output, tmp); } else if (outputmode == 2 && a[0] == '%') { StringCat(output, "%%"); } else if (outputmode == 3 && a[0] == '%') { StringCat(output, "%25"); } else { StringMemcat(output, a, 1); } a++; } } break; case 3: if (*langstr) { StringCat(output, "checked"); } break; default: if (*langstr) { int id = 1; char *fstr = langstr; StringClear(tmpbuff); if (format == 2) { StringCat(output, "\r\n"); StringCat(output, ""); } else if (format == -2) { StringCat(output, StringBuff(tmpbuff)); StringCat(output, "\">"); StringCat(output, StringBuff(tmpbuff)); StringCat(output, ""); } else { StringCat(output, StringBuff(tmpbuff)); } StringClear(tmpbuff); } } } str = pos; } else { if (outputmode != -1) { StringMemcat(output, str, 1); } } str++; } if (!nocr && prevlen != StringLength(output)) { StringCat(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 = (int) 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 = (int) 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"; StringCat(headers, error_hdr); StringCat(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"; StringCat(headers, error_hdr); StringCat(output, error); #endif } { char tmp[256]; sprintf(tmp, "Content-length: %d\r\n", (int) StringLength(output)); StringCat(headers, tmp); } StringCat(headers, "\r\n"); if ((send(soc_c, StringBuff(headers), (int) StringLength(headers), 0) != StringLength(headers)) || ((meth == 1) && (send(soc_c, StringBuff(output), (int) 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) ; } #ifdef _WIN32 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(tmpbuff2); StringFree(fspath); if (buffer) free(buffer); if (commandReturnMsg) free(commandReturnMsg); commandReturnMsg = NULL; if (commandReturnCmdl) free(commandReturnCmdl); commandReturnCmdl = NULL; /* Unlock */ webhttrack_release(); return retour; } /* Language files */ int htslang_init(void) { if (NewLangList == NULL) { NewLangList = inthash_new(0); if (NewLangList == NULL) { abortLog("Error in lang.h: not enough memory"); } else { inthash_value_is_malloc(NewLangList, 1); } } return 1; } int htslang_uninit(void) { if (NewLangList != NULL) { inthash_delete(&NewLangList); } return 1; } int smallserver_setkey(char *key, char *value) { return inthash_write(NewLangList, key, (intptr_t) strdup(value)); } int smallserver_setkeyint(char *key, LLint value) { char tmp[256]; sprintf(tmp, LLintP, value); return inthash_write(NewLangList, key, (intptr_t) 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, (intptr_t) strdup(value)); } static int htslang_load(char *limit_to, char *path) { char *hashname; char catbuff[CATBUFF_SIZE]; // int selected_lang = LANG_T(path, -1); // if (!limit_to) { LANG_DELETE(); NewLangStr = inthash_new(0); NewLangStrKeys = inthash_new(0); 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(catbuff, 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; size_t 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 = (int) strlen(intkey); buff = (char *) malloc(len + 2); if (buff) { strcpybuff(buff, intkey); inthash_add(NewLangStrKeys, key, (intptr_t) 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(catbuff, 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; size_t 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 = (int) strlen(value); buff = (char *) malloc(len + 2); if (buff) { conv_printf(value, buff); inthash_add(NewLangStr, intkey, (intptr_t) 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 */ static void conv_printf(char *from, char *to) { int i = 0, j = 0, len; len = (int) 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++; } } } static void LANG_DELETE(void) { inthash_delete(&NewLangStr); inthash_delete(&NewLangStrKeys); } // sélection de la langue static void LANG_INIT(char *path) { //CWinApp* pApp = AfxGetApp(); //if (pApp) { /* pApp->GetProfileInt("Language","IntId",0); */ LANG_T(path, 0 /*pApp->GetProfileInt("Language","IntId",0) */ ); //} } static int LANG_T(char *path, int l) { if (l >= 0) { QLANG_T(l); htslang_load(NULL, path); } return QLANG_T(-1); // 0=default (english) } static int LANG_SEARCH(char *path, char *iso) { char lang_str[1024]; int i = 0; int curr_lng = LANG_T(path, -1); int found = 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; } static int LANG_LIST(char *path, char *buffer) { char lang_str[1024]; int i = 0; int curr_lng = LANG_T(path, -1); 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; } static int QLANG_T(int l) { static int lng = 0; if (l >= 0) { lng = l; } return lng; // 0=default (english) } static char *LANGSEL(char *name) { intptr_t adr = 0; if (NewLangStr) if (!inthash_read(NewLangStr, name, &adr)) adr = 0; if (adr) { return (char *) adr; } return ""; } static char *LANGINTKEY(char *name) { intptr_t adr = 0; if (NewLangStrKeys) if (!inthash_read(NewLangStrKeys, name, &adr)) adr = 0; if (adr) { return (char *) adr; } return ""; } /* *** Various functions *** */ 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; } // check if data is available static 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; } /*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; }*/ /* same, except + */