/* ------------------------------------------------------------ */ /* 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 3 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. Please visit our Website: http://www.httrack.com */ /* ------------------------------------------------------------ */ /* File: ProxyTrack, httrack cache-based proxy */ /* Author: Xavier Roche */ /* ------------------------------------------------------------ */ #ifndef WEBHTTRACK_PROXYTRACK #define WEBHTTRACK_PROXYTRACK /* Version */ #define PROXYTRACK_VERSION "0.5" /* Store manager */ #include "../minizip/mztools.h" #include "store.h" #include #ifndef HTS_DO_NOT_USE_FTIME #ifdef _WIN32 #include #else #include #endif #include #else #include #endif #ifndef _WIN32 #include #endif /* generic */ int proxytrack_main(char* proxyAddr, int proxyPort, char* icpAddr, int icpPort, PT_Indexes index); /* Spaces: CR,LF,TAB,FF */ #define is_space(c) ( ((c)==' ') || ((c)=='\"') || ((c)==10) || ((c)==13) || ((c)==9) || ((c)==12) || ((c)==11) || ((c)=='\'') ) #define is_realspace(c) ( ((c)==' ') || ((c)==10) || ((c)==13) || ((c)==9) || ((c)==12) || ((c)==11) ) #define is_taborspace(c) ( ((c)==' ') || ((c)==9) ) #define is_quote(c) ( ((c)=='\"') || ((c)=='\'') ) #define is_retorsep(c) ( ((c)==10) || ((c)==13) || ((c)==9) ) /* Static definitions */ #define _ , #define CRITICAL_(msg, file, line) do { \ fprintf(stderr, "* critical: "); \ fprintf(stderr, msg); \ fprintf(stderr, " at %s:%d\n", file, line); \ fflush(stderr); \ } while(0) #define CRITICAL(msg) do { \ fprintf(stderr, "* critical: "); \ fprintf(stderr, msg); \ fprintf(stderr, " at %s:%d\n", __FILE__, __LINE__); \ fflush(stderr); \ } while(0) #define WARNING(msg) do { \ fprintf(stderr, "* warning: "); \ fprintf(stderr, msg); \ fprintf(stderr, "\n"); \ fflush(stderr); \ } while(0) #define LOG(msg) do { \ fprintf(stderr, "* log: "); \ fprintf(stderr, msg); \ fprintf(stderr, "\n"); \ fflush(stderr); \ } while(0) #if defined(_DEBUG) || defined(DEBUG) #define DEBUG(msg) do { \ fprintf(stderr, "* debug: "); \ fprintf(stderr, msg); \ fprintf(stderr, "\n"); \ fflush(stderr); \ } while(0) #else #define DEBUG_(msg, file, line) do { } while(0) #define DEBUG(msg) do { } while(0) #endif /* Header for generated pages */ #define PROXYTRACK_COMMENT_HEADER \ "\r\n" \ "\r\n" /* See IE "feature" (MSKB Q294807) */ #define DISABLE_IE_FRIENDLY_HTTP_ERROR_MESSAGES \ "\r\n" \ "\r\n" \ "\r\n" \ "\r\n" \ "\r\n" \ "\r\n" \ "\r\n" \ "\r\n" \ "\r\n" \ "\r\n" \ "\r\n" \ "\r\n" static char* gethomedir(void) { char* home = getenv( "HOME" ); if (home) return home; else return "."; } static 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; } static int link_has_authority(const char* lien) { const char* a=lien; if (isalpha((const unsigned char)*a)) { // Skip scheme? while (isalpha((const unsigned char)*a)) a++; if (*a == ':') a++; else return 0; } if (strncmp(a,"//",2) == 0) return 1; return 0; } static const char* jump_protocol(const char* source) { int p; // scheme // "Comparisons of scheme names MUST be case-insensitive" (RFC2616) if ((p = strfield(source,"http:"))) source+=p; else if ((p = strfield(source,"ftp:"))) source+=p; else if ((p = strfield(source,"https:"))) source+=p; else if ((p = strfield(source,"file:"))) source+=p; else if ((p = strfield(source,"mms:"))) source+=p; // net_path if (strncmp(source,"//",2)==0) source+=2; return source; } static const char* strrchr_limit(const char* s, char c, const char* limit) { if (limit == NULL) { char* p = strrchr(s, c); return p?(p+1):NULL; } else { char *a=NULL, *p; for(;;) { p=strchr((a)?a:s, c); if ((p >= limit) || (p == NULL)) return a; a=p+1; } } } static const char* jump_protocol_and_auth(const char* source) { const char *a,*trytofind; if (strcmp(source, "file://") == 0) return source; a = jump_protocol(source); trytofind = strrchr_limit(a, '@', strchr(a,'/')); return (trytofind != NULL)?trytofind:a; } #ifndef min #define min(a,b) ((a)>(b)?(b):(a)) #endif #ifndef max #define max(a,b) ((a)>(b)?(a):(b)) #endif static int linput_trim(FILE* fp,char* s,int max) { int rlen=0; char* ls=(char*) malloc(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'; } } // free(ls); } return rlen; } #ifndef S_ISREG #define S_ISREG(m) ((m) & _S_IFREG) #endif static 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; } /* convertir une chaine en temps */ static void set_lowcase(char* s) { int i; for(i=0;i<(int) strlen(s);i++) if ((s[i]>='A') && (s[i]<='Z')) s[i]+=('a'-'A'); } static struct tm* convert_time_rfc822(struct tm *result,const char* s) { char months[]="jan feb mar apr may jun jul aug sep oct nov dec"; char str[256]; char* a; /* */ int result_mm=-1; int result_dd=-1; int result_n1=-1; int result_n2=-1; int result_n3=-1; int result_n4=-1; /* */ if ((int) strlen(s) > 200) return NULL; strcpy(str,s); set_lowcase(str); /* éliminer :,- */ while( (a=strchr(str,'-')) ) *a=' '; while( (a=strchr(str,':')) ) *a=' '; while( (a=strchr(str,',')) ) *a=' '; /* tokeniser */ a=str; while(*a) { char *first, *last; char tok[256]; /* découper mot */ while(*a==' ') a++; /* sauter espaces */ first=a; while((*a) && (*a!=' ')) a++; last=a; tok[0]='\0'; if (first!=last) { char* pos; strncat(tok,first,(int) (last - first)); /* analyser */ if ( (pos=strstr(months,tok)) ) { /* month always in letters */ result_mm=((int) (pos - months))/4; } else { int number; if (sscanf(tok,"%d",&number) == 1) { /* number token */ if (result_dd<0) /* day always first number */ result_dd=number; else if (result_n1<0) result_n1=number; else if (result_n2<0) result_n2=number; else if (result_n3<0) result_n3=number; else if (result_n4<0) result_n4=number; } /* sinon, bruit de fond(+1GMT for exampel) */ } } } if ((result_n1>=0) && (result_mm>=0) && (result_dd>=0) && (result_n2>=0) && (result_n3>=0) && (result_n4>=0)) { if (result_n4>=1000) { /* Sun Nov 6 08:49:37 1994 */ result->tm_year=result_n4-1900; result->tm_hour=result_n1; result->tm_min=result_n2; result->tm_sec=max(result_n3,0); } else { /* Sun, 06 Nov 1994 08:49:37 GMT or Sunday, 06-Nov-94 08:49:37 GMT */ result->tm_hour=result_n2; result->tm_min=result_n3; result->tm_sec=max(result_n4,0); if (result_n1<=50) /* 00 means 2000 */ result->tm_year=result_n1+100; else if (result_n1<1000) /* 99 means 1999 */ result->tm_year=result_n1; else /* 2000 */ result->tm_year=result_n1-1900; } result->tm_isdst=0; /* assume GMT */ result->tm_yday=-1; /* don't know */ result->tm_wday=-1; /* don't know */ result->tm_mon=result_mm; result->tm_mday=result_dd; return result; } return NULL; } static struct tm PT_GetTime(time_t t) { struct tm tmbuf; #ifdef _WIN32 struct tm * tm = gmtime(&t); #else struct tm * tm = gmtime_r(&t, &tmbuf); #endif if (tm != NULL) return *tm; else { memset(&tmbuf, 0, sizeof(tmbuf)); return tmbuf; } } static int set_filetime(const char* file, struct tm* tm_time) { struct utimbuf tim; #ifndef HTS_DO_NOT_USE_FTIME struct timeb B; memset(&B, 0, sizeof(B)); B.timezone=0; ftime( &B ); tim.actime = tim.modtime = mktime(tm_time) - B.timezone*60; #else // bogus time (GMT/local).. tim.actime=tim.modtime=mktime(tm_time); #endif return utime(file, &tim); } static int set_filetime_time_t(const char* file, time_t t) { if (t != (time_t) 0 && t != (time_t) -1) { struct tm tm = PT_GetTime(t); return set_filetime(file, &tm); } return -1; } static int set_filetime_rfc822(const char* file, const char* date) { struct tm buffer; struct tm* tm_s = convert_time_rfc822(&buffer,date); if (tm_s) { return set_filetime(file,tm_s); } else return -1; } #endif