From 25adbdabb47499fe641c7bd9595024ff82667058 Mon Sep 17 00:00:00 2001 From: Xavier Roche Date: Mon, 19 Mar 2012 12:51:31 +0000 Subject: httrack 3.30.1 --- src/htsparse.c | 4164 ++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 2875 insertions(+), 1289 deletions(-) (limited to 'src/htsparse.c') diff --git a/src/htsparse.c b/src/htsparse.c index b012a8d..3d35252 100644 --- a/src/htsparse.c +++ b/src/htsparse.c @@ -30,641 +30,1040 @@ Please visit our Website: http://www.httrack.com /* ------------------------------------------------------------ */ -/* File: Main source */ -/* DIRECT INCLUDE TO httrack.c */ +/* File: htsparse.c parser */ +/* html/javascript/css parser */ +/* and other parser routines */ /* Author: Xavier Roche */ /* ------------------------------------------------------------ */ -#if HTS_ANALYSTE -if (hts_htmlcheck(r.adr,(int)r.size,urladr,urlfil)) { -#endif - FILE* fp=NULL; // fichier écrit localement - char* adr=r.adr; // pointeur (on parcourt) - char* lastsaved; // adresse du dernier octet sauvé + 1 - if ( (opt.debug>1) && (opt.log!=NULL) ) { - fspc(opt.log,"debug"); fprintf(opt.log,"scan file.."LF); test_flush; - } +#include +#include +#include +#include +#include +#include - // Indexing! -#if HTS_MAKE_KEYWORD_INDEX - if (opt.kindex) { - if (index_keyword(r.adr,r.size,r.contenttype,savename,opt.path_html)) { - if ( (opt.debug>1) && (opt.log!=NULL) ) { - fspc(opt.log,"debug"); fprintf(opt.log,"indexing file..done"LF); test_flush; - } - } else { - if ( (opt.debug>1) && (opt.log!=NULL) ) { - fspc(opt.log,"debug"); fprintf(opt.log,"indexing file..error!"LF); test_flush; - } - } +/* File defs */ +#include "htscore.h" + +/* specific definitions */ +#include "htsbase.h" +#include "htsnet.h" +#include "htsbauth.h" +#include "htsmd5.h" +#include "htsindex.h" + +/* external modules */ +#include "htsmodules.h" + +// htswrap_add +#include "htswrap.h" + +// parser +#include "htsparse.h" + + +// specific defines +#define urladr (liens[ptr]->adr) +#define urlfil (liens[ptr]->fil) +#define savename (liens[ptr]->sav) +#define parenturladr (liens[liens[ptr]->precedent]->adr) +#define parenturlfil (liens[liens[ptr]->precedent]->fil) +#define parentsavename (liens[liens[ptr]->precedent]->sav) +#define relativeurladr ((!parent_relative)?urladr:parenturladr) +#define relativeurlfil ((!parent_relative)?urlfil:parenturlfil) +#define relativesavename ((!parent_relative)?savename:parentsavename) + +#define test_flush if (opt->flush) { if (opt->log) { fflush(opt->log); } if (opt->errlog) { fflush(opt->errlog); } } + +// does nothing +#define XH_uninit do {} while(0) + +// version optimisée, qui permet de ne pas toucher aux html non modifiés (update) +#define REALLOC_SIZE 8192 +#define HT_ADD_CHK(A) if (((int) (A)+ht_len+1) >= ht_size) { \ + ht_size=(A)+ht_len+REALLOC_SIZE; \ + ht_buff=(char*) realloct(ht_buff,ht_size); \ + if (ht_buff==NULL) { \ + printf("PANIC! : Not enough memory [%d]\n",__LINE__); \ + XH_uninit; \ + abortLogFmt("not enough memory for current html document in HT_ADD_CHK : realloct(%d) failed" _ ht_size); \ + exit(1); \ + } \ + } \ + ht_len+=A; +#define HT_ADD_ADR \ + if ((opt->getmode & 1) && (ptr>0)) { \ + int i=((int) (adr - lastsaved)),j=ht_len; HT_ADD_CHK(i) \ + memcpy(ht_buff+j, lastsaved, i); \ + ht_buff[j+i]='\0'; \ + lastsaved=adr; \ } +#define HT_ADD(A) \ + if ((opt->getmode & 1) && (ptr>0)) { \ + int i=strlen(A),j=ht_len; \ + if (i) { \ + HT_ADD_CHK(i) \ + memcpy(ht_buff+j, A, i); \ + ht_buff[j+i]='\0'; \ + } } +#define HT_ADD_START \ + int ht_size=(int)(r->size*5)/4+REALLOC_SIZE; \ + int ht_len=0; \ + char* ht_buff=NULL; \ + if ((opt->getmode & 1) && (ptr>0)) { \ + ht_buff=(char*) malloct(ht_size); \ + if (ht_buff==NULL) { \ + printf("PANIC! : Not enough memory [%d]\n",__LINE__); \ + XH_uninit; \ + abortLogFmt("not enough memory for current html document in HT_ADD_START : malloct(%d) failed" _ ht_size); \ + exit(1); \ + } \ + ht_buff[0]='\0'; \ + } +#define HT_ADD_END { \ + int ok=0;\ + if (ht_buff) { \ + INTsys file_len=(INTsys) strlen(ht_buff);\ + char digest[32+2];\ + digest[0]='\0';\ + domd5mem(ht_buff,file_len,digest,1);\ + if (fsize(fconv(savename))==file_len) { \ + int mlen;\ + char* mbuff;\ + cache_readdata(cache,"//[HTML-MD5]//",savename,&mbuff,&mlen);\ + if (mlen) mbuff[mlen]='\0';\ + if ((mlen == 32) && (strcmp(((mbuff!=NULL)?mbuff:""),digest)==0)) {\ + ok=1;\ + if ( (opt->debug>1) && (opt->log!=NULL) ) {\ + fspc(opt->log,"debug"); fprintf(opt->log,"File not re-written (md5): %s"LF,savename);\ + test_flush;\ + }\ + } else {\ + ok=0;\ + } \ + }\ + if (!ok) { \ + fp=filecreate(savename); \ + if (fp) { \ + if (file_len>0) {\ + if ((INTsys)fwrite(ht_buff,1,file_len,fp) != file_len) { \ + int fcheck;\ + if ((fcheck=check_fatal_io_errno())) {\ + opt->state.exit_xh=-1;\ + }\ + if (opt->errlog) { \ + fspc(opt->errlog,"error"); fprintf(opt->errlog,"Unable to write HTML file %s: %s"LF, savename, strerror(errno));\ + if (fcheck) {\ + fspc(opt->errlog,"error");\ + fprintf(opt->errlog,"* * Fatal write error, giving up"LF);\ + }\ + test_flush;\ + }\ + }\ + }\ + fclose(fp); fp=NULL; \ + if (strnotempty(r->lastmodified)) \ + set_filetime_rfc822(savename,r->lastmodified); \ + } else {\ + int fcheck;\ + if ((fcheck=check_fatal_io_errno())) {\ + opt->state.exit_xh=-1;\ + }\ + if (opt->errlog) { \ + fspc(opt->errlog,"error");\ + fprintf(opt->errlog,"Unable to save file %s : %s"LF, savename, strerror(errno));\ + if (fcheck) {\ + fspc(opt->errlog,"error");\ + fprintf(opt->errlog,"* * Fatal write error, giving up"LF);\ + }\ + test_flush;\ + }\ + }\ + } else {\ + filenote(savename,NULL); \ + }\ + if (cache->ndx)\ + cache_writedata(cache->ndx,cache->dat,"//[HTML-MD5]//",savename,digest,(int)strlen(digest));\ + } \ + freet(ht_buff); ht_buff=NULL; \ + } +#define HT_ADD_FOP + +// COPY IN HTSCORE.C +#define HT_INDEX_END do { \ +if (!makeindex_done) { \ +if (makeindex_fp) { \ + char tempo[1024]; \ + if (makeindex_links == 1) { \ + sprintf(tempo,""CRLF,makeindex_firstlink); \ + } else \ + tempo[0]='\0'; \ + fprintf(makeindex_fp,template_footer, \ + "", \ + tempo \ + ); \ + fflush(makeindex_fp); \ + fclose(makeindex_fp); /* à ne pas oublier sinon on passe une nuit blanche */ \ + makeindex_fp=NULL; \ + usercommand(opt,0,NULL,fconcat(opt->path_html,"index.html"),"primary","primary"); \ +} \ +} \ +makeindex_done=1; /* ok c'est fait */ \ +} while(0) + +// Enregistrement d'un lien: +// on calcule la taille nécessaire: taille des 3 chaînes à stocker (taille forcée paire, plus 2 octets de sécurité) +// puis on vérifie qu'on a assez de marge dans le buffer - sinon on en réalloue un autre +// enfin on écrit à l'adresse courante du buffer, qu'on incrémente. on décrémente la taille dispo d'autant ensuite +// codebase: si non nul et si .class stockee on le note pour chemin primaire pour classes +// FA,FS: former_adr et former_fil, lien original +#if HTS_HASH +#define liens_record_sav_len(A) +#else +#define liens_record_sav_len(A) (A)->sav_len=strlen((A)->sav) #endif - // Now, parsing - if ((opt.getmode & 1) && (ptr>0)) { // récupérer les html sur disque - // créer le fichier html local - HT_ADD_FOP; // écrire peu à peu le fichier - } - - if (!error) { - int detect_title=0; // détection du title - // - char* in_media=NULL; // in other media type (real media and so..) - int intag=0; // on est dans un tag - int incomment=0; // dans un " - ); - - } else makeindex_done=-1; // fait, erreur - } + base[0]='\0'; // effacer base-href + lastsaved=adr; + do { + int p=0; + int valid_p=0; // force to take p even if == 0 + int ending_p='\0'; // ending quote? + int archivetag_p=0; // avoid multiple-archives with commas + INSCRIPT inscript_state_pos_prev=inscript_state_pos; + error=0; + + /* Hack to avoid NULL char problems with C syntax */ + /* Yes, some bogus HTML pages can embed null chars + and therefore can not be properly handled if this hack is not done + */ + if ( ! (*adr) ) { + if ( ((int) (adr - r->adr)) < r->size) + *adr=' '; + } + + + + /* + index.html built here + */ + // Construction index.html (sommaire) + // Avant de tester les a href, + // Ici on teste si l'on doit construire l'index vers le(s) site(s) miroir(s) + if (!makeindex_done) { // autoriation d'écrire un index + if (!detect_title) { + if (opt->depth == liens[ptr]->depth) { // on note toujours les premiers liens + if (!in_media) { + if (opt->makeindex && (ptr>0)) { + if (opt->getmode & 1) { // autorisation d'écrire + p=strfield(adr,"title"); + if (p) { + if (*(adr-1)=='/') p=0; // /title + } else { + if (strfield(adr,"/html")) + p=-1; // noter, mais sans titre + else if (strfield(adr,"body")) + p=-1; // noter, mais sans titre + else if ( ((int) (adr - r->adr) ) >= (r->size-1) ) + p=-1; // noter, mais sans titre + else if ( (int) (adr - r->adr) >= r->size - 2) // we got to hurry + p=-1; // xxc xxc xxc + } + } else + p=0; - if (makeindex_fp!=NULL) { - char tempo[HTS_URLMAXSIZE*2]; - char s[HTS_URLMAXSIZE*2]; - char* a=NULL; - char* b=NULL; - s[0]='\0'; - if (p>0) { - a=strchr(adr,'>'); - if (a!=NULL) { - a++; - while(is_space(*a)) a++; // sauter espaces & co - b=strchr(a,'<'); // prochain tag - } + if (p) { // ok center + if (makeindex_fp==NULL) { + verif_backblue(opt,opt->path_html); // générer gif + makeindex_fp=filecreate(fconcat(opt->path_html,"index.html")); + if (makeindex_fp!=NULL) { + + // Header + fprintf(makeindex_fp,template_header, + "" + ); + + } else makeindex_done=-1; // fait, erreur } - if (lienrelatif(tempo,liens[ptr]->sav,concat(opt.path_html,"index.html"))==0) { - detect_title=1; // ok détecté pour cette page! - makeindex_links++; // un de plus - strcpy(makeindex_firstlink,tempo); - // - if ((b==a) || (a==NULL) || (b==NULL)) { // pas de titre - strcpy(s,tempo); - } else if ((b-a)<256) { - b--; - while(is_space(*b)) b--; - strncpy(s,a,b-a+1); - *(s+(b-a)+1)='\0'; + + if (makeindex_fp!=NULL) { + char tempo[HTS_URLMAXSIZE*2]; + char s[HTS_URLMAXSIZE*2]; + char* a=NULL; + char* b=NULL; + s[0]='\0'; + if (p>0) { + a=strchr(adr,'>'); + if (a!=NULL) { + a++; + while(is_space(*a)) a++; // sauter espaces & co + b=strchr(a,'<'); // prochain tag + } } + if (lienrelatif(tempo,liens[ptr]->sav,concat(opt->path_html,"index.html"))==0) { + detect_title=1; // ok détecté pour cette page! + makeindex_links++; // un de plus + strcpybuff(makeindex_firstlink,tempo); + // - // Body - fprintf(makeindex_fp,template_body, - tempo, - s - ); + /* Hack */ + if (opt->mimehtml) { + strcpybuff(makeindex_firstlink, "cid:primary/primary"); + } + if ((b==a) || (a==NULL) || (b==NULL)) { // pas de titre + strcpybuff(s,tempo); + } else if ((b-a)<256) { + b--; + while(is_space(*b)) b--; + strncpy(s,a,b-a+1); + *(s+(b-a)+1)='\0'; + } + + // Body + fprintf(makeindex_fp,template_body, + tempo, + s + ); + + } } } } } + + } else if (liens[ptr]->depthdepth) { // on a sauté level1+1 et level1 + HT_INDEX_END; } - - } else if (liens[ptr]->depthmakeindex) + } + // FIN Construction index.html (sommaire) + /* + end -- index.html built here + */ - if (opt.getmode & 1) { // sauver html - p=strfield(adr,""); - // if (p==0) p=strfield(adr,"getmode & 1) { // sauver html + p=strfield(adr,""); + // if (p==0) p=strfield(adr,"adr,'\r')) eol="\r\n"; - time_gmt_rfc822(gmttime); - strcat(tempo,eol); - sprintf(tempo+strlen(tempo),opt.footer,jump_identification(urladr),urlfil,gmttime,"","","","","","","",""); - strcat(tempo,eol); - //fwrite(tempo,1,strlen(tempo),fp); - HT_ADD(tempo); - } - } - } - - // éliminer les is used somewhere else.. darn those browsers are dirty - */ - if (!strstr(adr,"-->")) { + } else if (!incomment) { + intag=0; //inquote=0; + + // entrée dans du javascript? + // on parse ICI car il se peut qu'on ait eu a parser les src=.. dedans + //if (!inscript) { // sinon on est dans un obj.write(".. + if ((intag_start_valid) && + ( + check_tag(intag_start,"script") + || + check_tag(intag_start,"style") + ) + ) { + char* a=intag_start; // < + // ** while(is_realspace(*(--a))); + if (*a=='<') { // sûr que c'est un tag? + if (check_tag(intag_start,"script")) + inscript_name="script"; + else + inscript_name="style"; + inscript=1; + inscript_state_pos=INSCRIPT_START; + intag=1; // because après