/* Pseudo-key (lien_url structure) hash function */ static inthash_keys key_adrfil_hashes_generic(void *arg, const char *value_, const int former) { hash_struct *const hash = (hash_struct*) arg; const lien_url*const lien = (lien_url*) value_; const char *const adr = !former ? lien->adr : lien->former_adr; const char *const fil = !former ? lien->fil : lien->former_fil; const char *const adr_norm = adr != NULL ? ( hash->normalized ? jump_normalized(adr) : jump_identification(adr) ) : NULL; // copy address assertf(adr_norm != NULL); strcpy(hash->normfil, adr_norm); // copy link assertf(fil != NULL); if (hash->normalized) { fil_normalized(fil, &hash->normfil[strlen(hash->normfil)]); } else { strcpy(&hash->normfil[strlen(hash->normfil)], fil); } // hash return inthash_hash_value(hash->normfil); }
/* Pseudo-key (lien_url structure) comparison function */ static int key_adrfil_equals_generic(void *arg, const char *a_, const char *b_, const int former) { hash_struct *const hash = (hash_struct*) arg; const int normalized = hash->normalized; const lien_url*const a = (lien_url*) a_; const lien_url*const b = (lien_url*) b_; const char *const a_adr = !former ? a->adr : a->former_adr; const char *const b_adr = !former ? b->adr : b->former_adr; const char *const a_fil = !former ? a->fil : a->former_fil; const char *const b_fil = !former ? b->fil : b->former_fil; const char *ja; const char *jb; // safety assertf(a_adr != NULL); assertf(b_adr != NULL); assertf(a_fil != NULL); assertf(b_fil != NULL); // skip scheme and authentication to the domain (possibly without www.) ja = normalized ? jump_normalized(a_adr) : jump_identification(a_adr); jb = normalized ? jump_normalized(b_adr) : jump_identification(b_adr); assertf(ja != NULL); assertf(jb != NULL); if (strcasecmp(ja, jb) != 0) { return 0; } // now compare pathes if (normalized) { fil_normalized(a_fil, hash->normfil); fil_normalized(b_fil, hash->normfil2); return strcmp(hash->normfil, hash->normfil2) == 0; } else { return strcmp(a_fil, b_fil) == 0; } }
void COptionTab10::Onproxyconfigure() { CProxyId proxy; char adr[256]; CString s; GetDlgItemText(IDC_portprox,s); proxy.m_proxport=s; GetDlgItemText(IDC_prox,s); strcpybuff(adr,s); proxy.m_proxadr=jump_identification(adr); if (jump_identification(adr)!=adr) { char user_pass[256]; user_pass[0]='\0'; char* a; size_t nsize = (size_t) ( ( jump_identification(adr) - adr ) - 1 ); strncatbuff(user_pass,adr,nsize); a=strchr(user_pass,':'); if (a) *a='\0'; else a=user_pass+strlen(user_pass); proxy.m_proxlogin=user_pass; proxy.m_proxpass=a+1; } if (proxy.DoModal() == IDOK) { if (proxy.m_proxlogin.GetLength()==0) { SetDlgItemTextCP(this, IDC_prox,proxy.m_proxadr); m_ctl_pwdhide.SetCheck(0); OnPwdhide(); } else { SetDlgItemTextCP(this, IDC_prox,proxy.m_proxlogin+":"+proxy.m_proxpass+"@"+proxy.m_proxadr); m_ctl_pwdhide.SetCheck(1); OnPwdhide(); } SetDlgItemTextCP(this, IDC_portprox,proxy.m_proxport); } }
char *bauth_prefix(char *prefix, char *adr, char *fil) { char *a; strcpybuff(prefix, jump_identification(adr)); strcatbuff(prefix, fil); a = strchr(prefix, '?'); if (a) *a = '\0'; if (strchr(prefix, '/')) { a = prefix + strlen(prefix) - 1; while(*a != '/') a--; *(a + 1) = '\0'; } return prefix; }
// forme à partir d'un lien et du contexte (origin_fil et origin_adr d'où il est tiré) adr et fil // [adr et fil sont des buffers de 1ko] // 0 : ok // -1 : erreur // -2 : protocole non supporté (ftp) int ident_url_relatif(const char *lien,const char* origin_adr,const char* origin_fil,char* adr,char* fil) { int ok=0; int scheme=0; adr[0]='\0'; fil[0]='\0'; //effacer buffers // lien non vide! if (strnotempty(lien)==0) return -1; // erreur! // Scheme? { const char* a=lien; while (isalpha((unsigned char)*a)) a++; if (*a == ':') scheme=1; } // filtrer les parazites (mailto & cie) // scheme+authority (//) if ( (strfield(lien,"http://")) // scheme+// || (strfield(lien,"file://")) // scheme+// || (strncmp(lien,"//",2)==0) // // sans scheme (-> default) ) { if (ident_url_absolute(lien,adr,fil)==-1) { ok=-1; // erreur URL } } else if (strfield(lien,"ftp://")) { // Note: ftp:foobar.gif is not valid if (ftp_available()) { // ftp supporté if (ident_url_absolute(lien,adr,fil)==-1) { ok=-1; // erreur URL } } else { ok=-2; // non supporté } #if HTS_USEMMS } else if (strfield(lien,"mms://")) { if (ident_url_absolute(lien,adr,fil)==-1) { ok=-1; // erreur URL } #endif #if HTS_USEOPENSSL } else if (strfield(lien,"https://")) { if (SSL_is_available) { // Note: ftp:foobar.gif is not valid if (ident_url_absolute(lien,adr,fil)==-1) { ok=-1; // erreur URL } } else { ok=-1; } #endif } else if ((scheme) && ( (!strfield(lien,"http:")) && (!strfield(lien,"https:")) && (!strfield(lien,"ftp:")) #if HTS_USEMMS && (!strfield(lien,"mms:")) #endif )) { ok=-1; // unknown scheme } else { // c'est un lien relatif // On forme l'URL complète à partie de l'url actuelle // et du chemin actuel si besoin est. // copier adresse if (((int) strlen(origin_adr)<HTS_URLMAXSIZE) && ((int) strlen(origin_fil)<HTS_URLMAXSIZE) && ((int) strlen(lien)<HTS_URLMAXSIZE)) { /* patch scheme if necessary */ if (strfield(lien,"http:")) { lien+=5; strcpybuff(adr, jump_protocol(origin_adr)); // même adresse ; protocole vide (http) } else if (strfield(lien,"https:")) { lien+=6; strcpybuff(adr, "https://"); // même adresse forcée en https strcatbuff(adr, jump_protocol(origin_adr)); } else if (strfield(lien,"ftp:")) { lien+=4; strcpybuff(adr, "ftp://"); // même adresse forcée en ftp strcatbuff(adr, jump_protocol(origin_adr)); #if HTS_USEMMS } else if (strfield(lien,"mms:")) { lien+=4; strcpybuff(adr, "mms://"); // même adresse forcée en ftp strcatbuff(adr, jump_protocol(origin_adr)); #endif } else { strcpybuff(adr,origin_adr); // même adresse ; et même éventuel protocole } if (*lien!='/') { // sinon c'est un lien absolu if (*lien == '\0') { strcpybuff(fil,origin_fil); } else if (*lien == '?') { // example: a href="?page=2" char* a; strcpybuff(fil,origin_fil); a=strchr(fil,'?'); if (a) *a='\0'; strcatbuff(fil,lien); } else { const char *a=strchr(origin_fil,'?'); if (a == NULL) a=origin_fil+strlen(origin_fil); while((*a!='/') && ( a > origin_fil) ) a--; if (*a=='/') { // ok on a un '/' if ( (((int) (a - origin_fil))+1+strlen(lien)) < HTS_URLMAXSIZE) { // copier chemin strncpy(fil,origin_fil,((int) (a - origin_fil))+1); *(fil + ((int) (a - origin_fil))+1)='\0'; // copier chemin relatif if (((int) strlen(fil)+(int) strlen(lien)) < HTS_URLMAXSIZE) { strcatbuff(fil,lien + ((*lien=='/')?1:0) ); // simplifier url pour les ../ fil_simplifie(fil); } else ok=-1; // erreur } else { // erreur ok=-1; // erreur URL } } else { // erreur ok=-1; // erreur URL } } } else { // chemin absolu // copier chemin directement strcatbuff(fil,lien); fil_simplifie(fil); } // *lien!='/' } else ok=-1; } // test news: etc. // case insensitive pour adresse { char *a=jump_identification(adr); while(*a) { if ((*a>='A') && (*a<='Z')) *a+='a'-'A'; a++; } } return ok; }
// GESTION DES TABLES DE HACHAGE // Méthode à 2 clés (adr+fil), 2e cle facultative // hash[no_enregistrement][pos]->hash est un index dans le tableau général liens // #define HTS_HASH_SIZE 8191 (premier si possible!) // type: numero enregistrement - 0 est case insensitive (sav) 1 (adr+fil) 2 (former_adr+former_fil) // recherche dans la table selon nom1,nom2 et le no d'enregistrement // retour: position ou -1 si non trouvé int hash_read(const hash_struct* hash,char* nom1,char* nom2,int type,int normalized) { char BIGSTK normfil_[HTS_URLMAXSIZE*2]; char catbuff[CATBUFF_SIZE]; char* normfil; char* normadr; unsigned int cle; int pos; // calculer la clé de recherche, non modulée if (type) cle = hash_cle(nom1,nom2); else cle = hash_cle(convtolower(catbuff,nom1),nom2); // case insensitive // la position se calcule en modulant pos = (int) (cle%HTS_HASH_SIZE); // entrée trouvée? if (hash->hash[type][pos] >= 0) { // un ou plusieurs enregistrement(s) avec une telle clé existe.. // tester table de raccourcis (hash) // pos est maintenant la position recherchée dans liens pos = hash->hash[type][pos]; while (pos>=0) { // parcourir la chaine switch (type) { case 0: // sav if (strfield2(nom1,hash->liens[pos]->sav)) { // case insensitive #if DEBUG_HASH==2 printf("hash: found shortcut at %d\n",pos); #endif return pos; } break; case 1: // adr+fil { if (!normalized) normfil=hash->liens[pos]->fil; else normfil=fil_normalized(hash->liens[pos]->fil,normfil_); if (!normalized) normadr = jump_identification(hash->liens[pos]->adr); else normadr = jump_normalized(hash->liens[pos]->adr); if ((strfield2(nom1,normadr)!=0) && (strcmp(nom2,normfil)==0)) { #if DEBUG_HASH==2 printf("hash: found shortcut at %d\n",pos); #endif return pos; } } break; case 2: // former_adr+former_fil { if (hash->liens[pos]->former_adr) { if (!normalized) normfil=hash->liens[pos]->former_fil; else normfil=fil_normalized(hash->liens[pos]->former_fil,normfil_); if (!normalized) normadr = jump_identification(hash->liens[pos]->former_adr); else normadr = jump_normalized(hash->liens[pos]->former_adr); if ((strfield2(nom1,normadr)!=0) && (strcmp(nom2,normfil)==0)) { #if DEBUG_HASH==2 printf("hash: found shortcut at %d\n",pos); #endif return pos; } } } break; } // calculer prochaine position dans la chaine { int old=pos; pos=hash->liens[pos]->hash_next[type]; // sinon prochain dans la chaine if (old==pos) pos=-1; // erreur de bouclage (ne devrait pas arriver) } } // Ok va falloir chercher alors.. /*pos=hash->max_lien; // commencer à max_lien switch (type) { case 0: // sav while(pos>=0) { if (hash->liens[pos]->hash_sav == cle ) { if (strcmp(nom1,hash->liens[pos]->sav)==0) { hash->hash[type][(int) (cle%HTS_HASH_SIZE)] = pos; // noter plus récent dans shortcut table #if DEBUG_HASH==2 printf("hash: found long search at %d\n",pos); #endif return pos; } } pos--; } break; case 1: // adr+fil while(pos>=0) { if (hash->liens[pos]->hash_adrfil == cle ) { if ((strcmp(nom1,hash->liens[pos]->adr)==0) && (strcmp(nom2,hash->liens[pos]->fil)==0)) { hash->hash[type][(int) (cle%HTS_HASH_SIZE)] = pos; // noter plus récent dans shortcut table #if DEBUG_HASH==2 printf("hash: found long search at %d\n",pos); #endif return pos; } } pos--; } break; case 2: // former_adr+former_fil while(pos>=0) { if (hash->liens[pos]->hash_fadrfil == cle ) { if (hash->liens[pos]->former_adr) if ((strcmp(nom1,hash->liens[pos]->former_adr)==0) && (strcmp(nom2,hash->liens[pos]->former_fil)==0)) { hash->hash[type][(int) (cle%HTS_HASH_SIZE)] = pos; // noter plus récent dans shortcut table #if DEBUG_HASH==2 printf("hash: found long search at %d\n",pos); #endif return pos; } } pos--; } }*/ #if DEBUG_HASH==1 printf("hash: not found after test %s%s\n",nom1,nom2); #endif return -1; // non trouvé } else { #if DEBUG_HASH==2 printf("hash: not found %s%s\n",nom1,nom2); #endif return -1; // non trouvé : clé non entrée (même une fois) } }
// enregistrement lien lpos dans les 3 tables hash1..3 void hash_write(hash_struct* hash,int lpos,int normalized) { char BIGSTK normfil_[HTS_URLMAXSIZE*2]; char catbuff[CATBUFF_SIZE]; char* normfil; unsigned int cle; int pos; int* ptr; // if (hash->liens[lpos]) { // on sait jamais.. hash->max_lien = max(hash->max_lien,lpos); #if DEBUG_HASH hashnumber=hash->max_lien; #endif // élément actuel sur -1 (fin de chaine) hash->liens[lpos]->hash_next[0]=hash->liens[lpos]->hash_next[1]=hash->liens[lpos]->hash_next[2]=-1; // cle = hash_cle(convtolower(catbuff,hash->liens[lpos]->sav),""); // CASE INSENSITIVE pos = (int) (cle%HTS_HASH_SIZE); ptr = hash_calc_chaine(hash,0,pos); // calculer adresse chaine *ptr = lpos; // noter dernier enregistré #if DEBUG_HASH==3 printf("[%d",pos); #endif // if (!normalized) normfil=hash->liens[lpos]->fil; else normfil=fil_normalized(hash->liens[lpos]->fil,normfil_); if (!normalized) cle = hash_cle(jump_identification(hash->liens[lpos]->adr),normfil); else cle = hash_cle(jump_normalized(hash->liens[lpos]->adr),normfil); pos = (int) (cle%HTS_HASH_SIZE); ptr = hash_calc_chaine(hash,1,pos); // calculer adresse chaine *ptr = lpos; // noter dernier enregistré #if DEBUG_HASH==3 printf(",%d",pos); #endif // if (hash->liens[lpos]->former_adr) { // former_adr existe? if (!normalized) normfil=hash->liens[lpos]->former_fil; else normfil=fil_normalized(hash->liens[lpos]->former_fil,normfil_); if (!normalized) cle = hash_cle(jump_identification(hash->liens[lpos]->former_adr),normfil); else cle = hash_cle(jump_normalized(hash->liens[lpos]->former_adr),normfil); pos = (int) (cle%HTS_HASH_SIZE); ptr = hash_calc_chaine(hash,2,pos); // calculer adresse chaine *ptr = lpos; // noter dernier enregistré #if DEBUG_HASH==3 printf(",%d",pos); #endif } #if DEBUG_HASH==3 printf("] "); fflush(stdout); #endif } #if DEBUT_HASH else { printf("* hash_write=0!!\n"); abortLogFmt("unexpected error in hash_write (pos=%d)" _ pos); exit(1); } #endif // }
void help_wizard(httrackp* opt) { char* urls = (char*) malloct(HTS_URLMAXSIZE*2); char* mainpath = (char*) malloct(256); char* projname = (char*) malloct(256); char* stropt = (char*) malloct(2048); // options char* stropt2 = (char*) malloct(2048); // options longues char* strwild = (char*) malloct(2048); // wildcards char* cmd = (char*) malloct(4096); char* str = (char*) malloct(256); char** argv = (char**) malloct(256 * sizeof(char*)); // char* a; // if (urls == NULL || mainpath == NULL || projname == NULL || stropt == NULL || stropt2 == NULL || strwild == NULL || cmd == NULL || str == NULL || argv == NULL) { fprintf(stderr, "* memory exhausted in %s, line %d\n", __FILE__, __LINE__); return; } urls[0] = mainpath[0] = projname[0] = stropt[0] = stropt2[0] = strwild[0] = cmd[0] = str[0] = '\0'; // strcpybuff(stropt,"-"); mainpath[0]=projname[0]=stropt2[0]=strwild[0]='\0'; // printf("\n"); printf("Welcome to HTTrack Website Copier (Offline Browser) "HTTRACK_VERSION"%s\n", hts_get_version_info(opt)); printf("Copyright (C) Xavier Roche and other contributors\n"); #ifdef _WIN32 printf("Note: You are running the commandline version,\n"); printf("run 'WinHTTrack.exe' to get the GUI version.\n"); #endif #ifdef HTTRACK_AFF_WARNING printf("NOTE: "HTTRACK_AFF_WARNING"\n"); #endif #ifdef HTS_PLATFORM_NAME #if USE_BEGINTHREAD printf("[compiled: "HTS_PLATFORM_NAME" - MT]\n"); #else printf("[compiled: "HTS_PLATFORM_NAME"]\n"); #endif #endif printf("To see the option list, enter a blank line or try httrack --help\n"); // // Project name while(strnotempty(projname)==0) { printf("\n"); printf("Enter project name :"); fflush(stdout); linput(stdin,projname,250); if (strnotempty(projname)==0) help("httrack",1); } // // Path if (strnotempty(hts_gethome())) printf("\nBase path (return=%s/websites/) :",hts_gethome()); else printf("\nBase path (return=current directory) :"); linput(stdin,str,250); if (!strnotempty(str)) { strcatbuff(str,hts_gethome()); strcatbuff(str,"/websites/"); } if (strnotempty(str)) if ((str[strlen(str)-1]!='/') && (str[strlen(str)-1]!='\\')) strcatbuff(str,"/"); strcatbuff(stropt2,"-O \""); strcatbuff(stropt2,str); strcatbuff(stropt2,projname); strcatbuff(stropt2,"\" "); // Créer si ce n'est fait un index.html 1er niveau make_empty_index(str); // printf("\n"); printf("Enter URLs (separated by commas or blank spaces) :"); fflush(stdout); linput(stdin,urls,250); if (strnotempty(urls)) { while( (a=strchr(urls,',')) ) *a=' '; while( (a=strchr(urls,'\t')) ) *a=' '; // Action printf("\nAction:\n"); switch(help_query("Mirror Web Site(s)|Mirror Web Site(s) with Wizard|Just Get Files Indicated|Mirror ALL links in URLs (Multiple Mirror)|Test Links In URLs (Bookmark Test)|Update/Continue a Mirror",1)) { case 1: break; case 2: strcatbuff(stropt,"W"); break; case 3: strcatbuff(stropt2,"--get "); break; case 4: strcatbuff(stropt2,"--mirrorlinks "); break; case 5: strcatbuff(stropt2,"--testlinks "); break; case 6: strcatbuff(stropt2,"--update "); break; case 0: return; break; } // Proxy printf("\nProxy (return=none) :"); linput(stdin,str,250); if (strnotempty(str)) { while( (a=strchr(str,' ')) ) *a=':'; // port if (!strchr(jump_identification(str),':')) { char str2[256]; printf("\nProxy port (return=8080) :"); linput(stdin,str2,250); strcatbuff(str,":"); if (strnotempty(str2)==0) strcatbuff(str,"8080"); else strcatbuff(str,str2); } strcatbuff(stropt2,"-P "); strcatbuff(stropt2,str); strcatbuff(stropt2," "); } // Display strcatbuff(stropt2," -%v "); // Wildcards printf("\nYou can define wildcards, like: -*.gif +www.*.com/*.zip -*img_*.zip\n"); printf("Wildcards (return=none) :"); linput(stdin,strwild,250); // Options do { printf("\nYou can define additional options, such as recurse level (-r<number>), separed by blank spaces\n"); printf("To see the option list, type help\n"); printf("Additional options (return=none) :"); linput(stdin,str,250); if (strfield2(str,"help")) { help("httrack",2); } else if (strnotempty(str)) { strcatbuff(stropt2,str); strcatbuff(stropt2," "); } } while(strfield2(str,"help")); { int argc=1; int g=0; int i=0; // printf("\n"); if (strlen(stropt)==1) stropt[0]='\0'; // aucune sprintf(cmd,"%s %s %s %s",urls,stropt,stropt2,strwild); printf("---> Wizard command line: httrack %s\n\n",cmd); printf("Ready to launch the mirror? (Y/n) :"); fflush(stdout); linput(stdin,str,250); if (strnotempty(str)) { if (!((str[0]=='y') || (str[0]=='Y'))) return ; } printf("\n"); // couper en morceaux argv[0]="winhttrack"; argv[1]=cmd; argc++; while(cmd[i]) { if(cmd[i]=='\"') g=!g; if(cmd[i]==' '){ if(!g){ cmd[i]='\0'; argv[argc++]=cmd+i+1; } } i++; } hts_main(argc,argv); } //} else { // help("httrack",1); } /* Free buffers */ freet(urls); freet(mainpath); freet(projname); freet(stropt); freet(stropt2); freet(strwild); freet(cmd); freet(str); }
// la véritable fonction une fois lancées les routines thread/fork int run_launch_ftp(FTPDownloadStruct * pStruct) { lien_back *back = pStruct->pBack; httrackp *opt = pStruct->pOpt; char user[256] = "anonymous"; char pass[256] = "user@"; char line_retr[2048]; int port = 21; #if FTP_PASV int port_pasv = 0; #endif char BIGSTK adr_ip[1024]; char *adr, *real_adr; char *ftp_filename = ""; int timeout = 300; // timeout int timeout_onfly = 8; // attente réponse supplémentaire int transfer_list = 0; // directory int rest_understood = 0; // rest command understood t_fullhostent fullhostent_buffer; // buffer pour resolver // T_SOC soc_ctl = INVALID_SOCKET; T_SOC soc_servdat = INVALID_SOCKET; T_SOC soc_dat = INVALID_SOCKET; // SOCaddr server_data; int server_data_size = sizeof(server_data); // line_retr[0] = adr_ip[0] = '\0'; timeout = 300; // effacer strcpybuff(back->r.msg, ""); back->r.statuscode = 0; back->r.size = 0; // récupérer user et pass si présents, et sauter user:id@ dans adr real_adr = strchr(back->url_adr, ':'); if (real_adr) real_adr++; else real_adr = back->url_adr; while(*real_adr == '/') real_adr++; // sauter / if ((adr = jump_identification(real_adr)) != real_adr) { // user int i = -1; pass[0] = '\0'; do { i++; user[i] = real_adr[i]; } while((real_adr[i] != ':') && (real_adr[i])); user[i] = '\0'; if (real_adr[i] == ':') { // pass int j = -1; i++; // oui on saute aussi le : do { j++; pass[j] = real_adr[i + j]; } while(((&real_adr[i + j + 1]) < adr) && (real_adr[i + j])); pass[j] = '\0'; } } // Calculer RETR <nom> { char *a; #if 0 a = back->url_fil + strlen(back->url_fil) - 1; while((a > back->url_fil) && (*a != '/')) a--; if (*a != '/') { a = NULL; } #else a = back->url_fil; #endif if (a != NULL && *a != '\0') { #if 0 a++; // sauter / #endif ftp_filename = a; if (strnotempty(a)) { char catbuff[CATBUFF_SIZE]; char *ua = unescape_http(catbuff, a); int len_a = (int) strlen(ua); if (len_a > 0 && ua[len_a - 1] == '/') { /* obviously a directory listing */ transfer_list = 1; snprintf(line_retr, sizeof(line_retr), "LIST -A %s", ua); } else if ((strchr(ua, ' ')) || (strchr(ua, '\"')) || (strchr(ua, '\'')) ) { snprintf(line_retr, sizeof(line_retr), "RETR \"%s\"", ua); } else { /* Regular one */ snprintf(line_retr, sizeof(line_retr), "RETR %s", ua); } } else { transfer_list = 1; snprintf(line_retr, sizeof(line_retr), "LIST -A"); } } else { strcpybuff(back->r.msg, "Unexpected PORT error"); // back->status=STATUS_FTP_READY; // fini back->r.statuscode = STATUSCODE_INVALID; } } #if FTP_DEBUG printf("Connecting to %s...\n", adr); #endif // connexion { SOCaddr server; int server_size = sizeof(server); t_hostent *hp; char *a; char _adr[256]; const char *error = "unknown error"; _adr[0] = '\0'; //T_SOC soc_ctl; // effacer structure memset(&server, 0, sizeof(server)); // port a = strchr(adr, ':'); // port if (a) { sscanf(a + 1, "%d", &port); strncatbuff(_adr, adr, (int) (a - adr)); } else strcpybuff(_adr, adr); // récupérer adresse résolue strcpybuff(back->info, "host name"); hp = hts_gethostbyname2(opt, _adr, &fullhostent_buffer, &error); if (hp == NULL) { snprintf(back->r.msg, sizeof(back->r.msg), "Unable to get server's address: %s", error); // back->status=STATUS_FTP_READY; // fini back->r.statuscode = STATUSCODE_NON_FATAL; _HALT_FTP return 0; } _CHECK_HALT_FTP; // copie adresse SOCaddr_copyaddr(server, server_size, hp->h_addr_list[0], hp->h_length); // copie adresse pour cnx data SOCaddr_copyaddr(server_data, server_data_size, hp->h_addr_list[0], hp->h_length); // memcpy(&server.sin_addr, hp->h_addr, hp->h_length); // créer ("attachement") une socket (point d'accès) internet,en flot soc_ctl = (T_SOC) socket(SOCaddr_sinfamily(server), SOCK_STREAM, 0); if (soc_ctl == INVALID_SOCKET) { strcpybuff(back->r.msg, "Unable to create a socket"); // back->status=STATUS_FTP_READY; // fini back->r.statuscode = STATUSCODE_INVALID; _HALT_FTP return 0; }
// tester taille int hts_testlinksize(httrackp* opt, char* adr,char* fil, LLint size) { int jok=0; if (size>=0) { char BIGSTK l[HTS_URLMAXSIZE*2]; char BIGSTK lfull[HTS_URLMAXSIZE*2]; if (size>=0) { LLint sz=size; int size_flag=0; // former URL complète du lien actuel strcpybuff(l,jump_identification(adr)); if (*fil!='/') strcatbuff(l,"/"); strcatbuff(l,fil); // if (!link_has_authority(adr)) strcpybuff(lfull,"http://"); else lfull[0]='\0'; strcatbuff(lfull,adr); if (*fil!='/') strcatbuff(l,"/"); strcatbuff(lfull,fil); // filters, 0=sait pas 1=ok -1=interdit { int jokDepth1=0,jokDepth2=0; int jok1=0,jok2=0; LLint sz1=size,sz2=size; int size_flag1=0,size_flag2=0; jok1 = fa_strjoker(/*url*/0, *opt->filters.filters,*opt->filters.filptr,lfull,&sz1,&size_flag1,&jokDepth1); jok2 = fa_strjoker(/*url*/0, *opt->filters.filters,*opt->filters.filptr,l, &sz2,&size_flag2,&jokDepth2); if (jok2 == 0) { // #2 doesn't know jok = jok1; // then, use #1 sz = sz1; size_flag = size_flag1; } else if (jok1 == 0) { // #1 doesn't know jok = jok2; // then, use #2 sz = sz2; size_flag = size_flag2; } else if (jokDepth1 >= jokDepth2) { // #1 matching rule is "after" #2, then it is prioritary jok = jok1; sz = sz1; size_flag = size_flag1; } else { // #2 matching rule is "after" #1, then it is prioritary jok = jok2; sz = sz2; size_flag = size_flag2; } } // log if (jok==1) { if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"File confirmed (size test): %s%s ("LLintP")"LF,adr,fil,(LLint)(size)); } } else if (jok==-1) { if (size_flag) { /* interdit à cause de la taille */ if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"File cancelled due to its size: %s%s ("LLintP", limit: "LLintP")"LF,adr,fil,(LLint)(size),(LLint)(sz)); } } else { jok=1; } } } } return jok; }
static int hts_acceptlink_(httrackp* opt, int ptr,int lien_tot,lien_url** liens, char* adr,char* fil, char* tag, char* attribute, int* set_prio_to, int* just_test_it) { int forbidden_url=-1; int meme_adresse; int embedded_triggered = 0; #define _FILTERS (*opt->filters.filters) #define _FILTERS_PTR (opt->filters.filptr) #define _ROBOTS ((robots_wizard*)opt->robotsptr) int may_set_prio_to=0; // -------------------- PHASE 0 -------------------- /* Infos */ if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"wizard test begins: %s%s"LF,adr,fil); test_flush; } /* Already exists? Then, we know that we knew that this link had to be known */ if (adr[0] != '\0' && fil[0] != '\0' && opt->hash != NULL && hash_read(opt->hash, adr, fil, 1, opt->urlhack) >= 0 ) { return 0; /* Yokai */ } // -------------------- PRELUDE OF PHASE 3-BIS -------------------- /* Built-in known tags (<img src=..>, ..) */ if (forbidden_url != 0 && opt->nearlink && tag != NULL && attribute != NULL) { int i; for(i = 0 ; hts_detect_embed[i].tag != NULL ; i++) { if (cmp_token(tag, hts_detect_embed[i].tag) && cmp_token(attribute, hts_detect_embed[i].attr) ) { embedded_triggered = 1; break; } } } // -------------------- PHASE 1 -------------------- /* Doit-on traiter les non html? */ if ((opt->getmode & 2)==0) { // non on ne doit pas if (!ishtml(opt,fil)) { // non il ne faut pas //adr[0]='\0'; // ne pas traiter ce lien, pas traiter forbidden_url=1; // interdire récupération du lien if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"non-html file ignored at %s : %s"LF,adr,fil); test_flush; } } } /* Niveau 1: ne pas parser suivant! */ if (ptr>0) { if ( ( liens[ptr]->depth <= 0 ) || ( liens[ptr]->depth <= 1 && !embedded_triggered ) ) { forbidden_url=1; // interdire récupération du lien if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"file from too far level ignored at %s : %s"LF,adr,fil); test_flush; } } } /* en cas d'échec en phase 1, retour immédiat! */ if (forbidden_url == 1) { return forbidden_url; } // -------------------- PHASE 2 -------------------- // ------------------------------------------------------ // doit-on traiter ce lien?.. vérifier droits de déplacement meme_adresse=strfield2(adr,urladr); if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); if (meme_adresse) fprintf(opt->log,"Compare addresses: %s=%s"LF,adr,urladr); else fprintf(opt->log,"Compare addresses: %s!=%s"LF,adr,urladr); test_flush; } if (meme_adresse) { // même adresse { // tester interdiction de descendre // MODIFIE : en cas de remontée puis de redescente, il se pouvait qu'on ne puisse pas atteindre certains fichiers // problème: si un fichier est virtuellement accessible via une page mais dont le lien est sur une autre *uniquement*.. char BIGSTK tempo[HTS_URLMAXSIZE*2]; char BIGSTK tempo2[HTS_URLMAXSIZE*2]; tempo[0] = tempo2[0] = '\0'; // note (up/down): on calcule à partir du lien primaire, ET du lien précédent. // ex: si on descend 2 fois on peut remonter 1 fois if (lienrelatif(tempo,fil,liens[liens[ptr]->premier]->fil)==0) { if (lienrelatif(tempo2,fil,liens[ptr]->fil)==0) { if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"build relative links to test: %s %s (with %s and %s)"LF,tempo,tempo2,liens[liens[ptr]->premier]->fil,liens[ptr]->fil); test_flush; } // si vient de primary, ne pas tester lienrelatif avec (car host "différent") /*if (liens[liens[ptr]->premier] == 0) { // vient de primary } */ // NEW: finalement OK, sauf pour les moved repérés par link_import // PROBLEME : annulé a cause d'un lien éventuel isolé accepté..qui entrainerait un miroir // (test même niveau (NOUVEAU à cause de certains problèmes de filtres non intégrés)) // NEW if ( (tempo[0] != '\0' && tempo[1] != '\0' && strchr(tempo+1,'/') == 0) || (tempo2[0] != '\0' && tempo2[1] != '\0' && strchr(tempo2+1,'/') == 0) ) { if (!liens[ptr]->link_import) { // ne résulte pas d'un 'moved' forbidden_url=0; if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"same level link authorized: %s%s"LF,adr,fil); test_flush; } } } // down if ( (strncmp(tempo,"../",3)) || (strncmp(tempo2,"../",3))) { // pas montée sinon ne nbous concerne pas int test1,test2; if (!strncmp(tempo,"../",3)) test1=0; else test1 = (strchr(tempo +((*tempo =='/')?1:0),'/')!=NULL); if (!strncmp(tempo2,"../",3)) test2=0; else test2 = (strchr(tempo2+((*tempo2=='/')?1:0),'/')!=NULL); if ( (test1) && (test2) ) { // on ne peut que descendre if ((opt->seeker & 1)==0) { // interdiction de descendre forbidden_url=1; if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"lower link canceled: %s%s"LF,adr,fil); test_flush; } } else { // autorisé à priori - NEW if (!liens[ptr]->link_import) { // ne résulte pas d'un 'moved' forbidden_url=0; if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"lower link authorized: %s%s"LF,adr,fil); test_flush; } } } } else if ( (test1) || (test2) ) { // on peut descendre pour accéder au lien if ((opt->seeker & 1)!=0) { // on peut descendre - NEW if (!liens[ptr]->link_import) { // ne résulte pas d'un 'moved' forbidden_url=0; if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"lower link authorized: %s%s"LF,adr,fil); test_flush; } } } } } // up if ( (!strncmp(tempo,"../",3)) && (!strncmp(tempo2,"../",3)) ) { // impossible sans monter if ((opt->seeker & 2)==0) { // interdiction de monter forbidden_url=1; if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"upper link canceled: %s%s"LF,adr,fil); test_flush; } } else { // autorisé à monter - NEW if (!liens[ptr]->link_import) { // ne résulte pas d'un 'moved' forbidden_url=0; if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"upper link authorized: %s%s"LF,adr,fil); test_flush; } } } } else if ( (!strncmp(tempo,"../",3)) || (!strncmp(tempo2,"../",3)) ) { // Possible en montant if ((opt->seeker & 2)!=0) { // autorisé à monter - NEW if (!liens[ptr]->link_import) { // ne résulte pas d'un 'moved' forbidden_url=0; if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"upper link authorized: %s%s"LF,adr,fil); test_flush; } } } // sinon autorisé en descente } } else { if (opt->log) { fprintf(opt->log,"Error building relative link %s and %s"LF,fil,liens[ptr]->fil); test_flush; } } } else { if (opt->log) { fprintf(opt->log,"Error building relative link %s and %s"LF,fil,liens[liens[ptr]->premier]->fil); test_flush; } } } // tester interdiction de descendre? { // tester interdiction de monter char BIGSTK tempo[HTS_URLMAXSIZE*2]; char BIGSTK tempo2[HTS_URLMAXSIZE*2]; if (lienrelatif(tempo,fil,liens[liens[ptr]->premier]->fil)==0) { if (lienrelatif(tempo2,fil,liens[ptr]->fil)==0) { } else { if (opt->log) { fprintf(opt->log,"Error building relative link %s and %s"LF,fil,liens[ptr]->fil); test_flush; } } } else { if (opt->log) { fprintf(opt->log,"Error building relative link %s and %s"LF,fil,liens[liens[ptr]->premier]->fil); test_flush; } } } // fin tester interdiction de monter } else { // adresse différente, sortir? //if (!opt->wizard) { // mode non wizard // doit-on traiter ce lien?.. vérifier droits de sortie switch((opt->travel & 255)) { case 0: if (!opt->wizard) // mode non wizard forbidden_url=1; break; // interdicton de sortir au dela de l'adresse case 1: { // sortie sur le même dom.xxx size_t i = strlen(adr)-1; size_t j = strlen(urladr)-1; while( (i>0) && (adr[i]!='.')) i--; while( (j>0) && (urladr[j]!='.')) j--; i--; j--; while( (i>0) && (adr[i]!='.')) i--; while( (j>0) && (urladr[j]!='.')) j--; if ((i>0) && (j>0)) { if (!strfield2(adr+i,urladr+j)) { // != if (!opt->wizard) { // mode non wizard //printf("refused: %s\n",adr); forbidden_url=1; // pas même domaine if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"foreign domain link canceled: %s%s"LF,adr,fil); test_flush; } } } else { if (opt->wizard) { // mode wizard forbidden_url=0; // même domaine if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"same domain link authorized: %s%s"LF,adr,fil); test_flush; } } } } else forbidden_url=1; } break; case 2: { // sortie sur le même .xxx size_t i = strlen(adr)-1; size_t j = strlen(urladr)-1; while( (i>0) && (adr[i]!='.')) i--; while( (j>0) && (urladr[j]!='.')) j--; if ((i>0) && (j>0)) { if (!strfield2(adr+i,urladr+j)) { // !- if (!opt->wizard) { // mode non wizard //printf("refused: %s\n",adr); forbidden_url=1; // pas même .xx if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"foreign location link canceled: %s%s"LF,adr,fil); test_flush; } } } else { if (opt->wizard) { // mode wizard forbidden_url=0; // même domaine if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"same location link authorized: %s%s"LF,adr,fil); test_flush; } } } } else forbidden_url=1; } break; case 7: // everywhere!! if (opt->wizard) { // mode wizard forbidden_url=0; break; } } // switch // ANCIENNE POS -- récupérer les liens à côtés d'un lien (nearlink) } // fin test adresse identique/différente // -------------------- PHASE 3 -------------------- // récupérer les liens à côtés d'un lien (nearlink) (nvelle pos) if (forbidden_url != 0 && opt->nearlink) { if (!ishtml(opt,fil)) { // non html //printf("ok %s%s\n",ad,fil); forbidden_url=0; // autoriser may_set_prio_to=1+1; // set prio to 1 (parse but skip urls) if near is the winner if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"near link authorized: %s%s"LF,adr,fil); test_flush; } } } // -------------------- PHASE 3-BIS -------------------- /* Built-in known tags (<img src=..>, ..) */ if (forbidden_url != 0 && embedded_triggered) { forbidden_url=0; // autoriser may_set_prio_to=1+1; // set prio to 1 (parse but skip urls) if near is the winner if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"near link authorized (friendly tag): %s%s"LF,adr,fil); test_flush; } } // -------------------- PHASE 4 -------------------- // ------------------------------------------------------ // Si wizard, il se peut qu'on autorise ou qu'on interdise // un lien spécial avant même de tester sa position, sa hiérarchie etc. // peut court-circuiter le forbidden_url précédent if (opt->wizard) { // le wizard entre en action.. // int question=1; // poser une question int force_mirror=0; // pour mirror links int filters_answer=0; // décision prise par les filtres char BIGSTK l[HTS_URLMAXSIZE*2]; char BIGSTK lfull[HTS_URLMAXSIZE*2]; if (forbidden_url!=-1) question=0; // pas de question, résolu // former URL complète du lien actuel strcpybuff(l,jump_identification(adr)); if (*fil!='/') strcatbuff(l,"/"); strcatbuff(l,fil); // full version (http://foo:[email protected]/bar.html) if (!link_has_authority(adr)) strcpybuff(lfull,"http://"); else lfull[0]='\0'; strcatbuff(lfull,adr); if (*fil!='/') strcatbuff(lfull,"/"); strcatbuff(lfull,fil); // tester filters (URLs autorisées ou interdites explicitement) // si lien primaire on saute le joker, on est pas lémur if (ptr==0) { // lien primaire, autoriser question=1; // la question sera résolue automatiquement forbidden_url=0; may_set_prio_to=0; // clear may-set flag } else { // eternal depth first // vérifier récursivité extérieure if (opt->extdepth>0) { if ( /*question && */ (ptr>0) && (!force_mirror)) { // well, this is kinda a hak // we don't want to mirror EVERYTHING, and we have to decide where to stop // there is no way yet to tag "external" links, and therefore links that are // "weak" (authorized depth < external depth) are just not considered for external // hack if (liens[ptr]->depth > opt->extdepth) { // *set_prio_to = opt->extdepth + 1; *set_prio_to = 1 + (opt->extdepth); may_set_prio_to=0; // clear may-set flag forbidden_url=0; // autorisé question=0; // résolution auto if ((opt->debug>1) && (opt->log!=NULL)) { if (question) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"(wizard) ambiguous link accepted (external depth): link %s at %s%s"LF,l,urladr,urlfil); } else { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"(wizard) forced to accept link (external depth): link %s at %s%s"LF,l,urladr,urlfil); } test_flush; } } } } // filters { int jok; char* mdepth=""; // filters, 0=sait pas 1=ok -1=interdit { int jokDepth1=0,jokDepth2=0; int jok1=0,jok2=0; jok1 = fa_strjoker(/*url*/0, _FILTERS,*_FILTERS_PTR,lfull,NULL,NULL,&jokDepth1); jok2 = fa_strjoker(/*url*/0, _FILTERS,*_FILTERS_PTR,l, NULL,NULL,&jokDepth2); if (jok2 == 0) { // #2 doesn't know jok = jok1; // then, use #1 mdepth = _FILTERS[jokDepth1]; } else if (jok1 == 0) { // #1 doesn't know jok = jok2; // then, use #2 mdepth = _FILTERS[jokDepth2]; } else if (jokDepth1 >= jokDepth2) { // #1 matching rule is "after" #2, then it is prioritary jok = jok1; mdepth = _FILTERS[jokDepth1]; } else { // #2 matching rule is "after" #1, then it is prioritary jok = jok2; mdepth = _FILTERS[jokDepth2]; } } if (jok == 1) { // autorisé filters_answer=1; // décision prise par les filtres question=0; // ne pas poser de question, autorisé forbidden_url=0; // URL autorisée may_set_prio_to=0; // clear may-set flag if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"(wizard) explicit authorized (%s) link: link %s at %s%s"LF,mdepth,l,urladr,urlfil); test_flush; } } else if (jok == -1) { // forbidden filters_answer=1; // décision prise par les filtres question=0; // ne pas poser de question: forbidden_url=1; // URL interdite if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"(wizard) explicit forbidden (%s) link: link %s at %s%s"LF,mdepth,l,urladr,urlfil); test_flush; } } // sinon on touche à rien } } // vérifier mode mirror links if (question) { if (opt->mirror_first_page) { // mode mirror links if (liens[ptr]->precedent==0) { // parent=primary! forbidden_url=0; // autorisé may_set_prio_to=0; // clear may-set flag question=1; // résolution auto force_mirror=5; // mirror (5) if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"(wizard) explicit mirror link: link %s at %s%s"LF,l,urladr,urlfil); test_flush; } } } } // on doit poser la question.. peut on la poser? // (oui je sais quel preuve de délicatesse, merci merci) if ((question) && (ptr>0) && (!force_mirror)) { if (opt->wizard==2) { // éliminer tous les liens non répertoriés comme autorisés (ou inconnus) question=0; forbidden_url=1; if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"(wizard) ambiguous forbidden link: link %s at %s%s"LF,l,urladr,urlfil); test_flush; } } } // vérifier robots.txt if (opt->robots) { int r = checkrobots(_ROBOTS,adr,fil); if (r == -1) { // interdiction #if DEBUG_ROBOTS printf("robots.txt forbidden: %s%s\n",adr,fil); #endif // question résolue, par les filtres, et mode robot non strict if ((!question) && (filters_answer) && (opt->robots == 1) && (forbidden_url!=1)) { r=0; // annuler interdiction des robots if (!forbidden_url) { if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"Warning link followed against robots.txt: link %s at %s%s"LF,l,adr,fil); test_flush; } } } if (r == -1) { // interdire forbidden_url=1; question=0; if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"(robots.txt) forbidden link: link %s at %s%s"LF,l,adr,fil); test_flush; } } } } if (!question) { if ((opt->debug>1) && (opt->log!=NULL)) { if (!forbidden_url) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"(wizard) shared foreign domain link: link %s at %s%s"LF,l,urladr,urlfil); } else { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"(wizard) cancelled foreign domain link: link %s at %s%s"LF,l,urladr,urlfil); } test_flush; } #if BDEBUG==3 printf("at %s in %s, wizard says: url %s ",urladr,urlfil,l); if (forbidden_url) printf("cancelled"); else printf(">SHARED<"); printf("\n"); #endif } /* en cas de question, ou lien primaire (enregistrer autorisations) */ if (question || (ptr==0)) { const char* s; int n=0; // si primaire (plus bas) alors ... if ((ptr!=0) && (force_mirror==0)) { char BIGSTK tempo[HTS_URLMAXSIZE*2]; tempo[0]='\0'; strcatbuff(tempo,adr); strcatbuff(tempo,fil); s = RUN_CALLBACK1(opt, query3, tempo); if (strnotempty(s)==0) // entrée n=0; else if (isdigit((unsigned char)*s)) sscanf(s,"%d",&n); else { switch(*s) { case '*': n=-1; break; case '!': n=-999; { /*char *a; int i; a=copie_de_adr-128; if (a<r.adr) a=r.adr; for(i=0;i<256;i++) { if (a==copie_de_adr) printf("\nHERE:\n"); printf("%c",*a++); } printf("\n\n"); */ } break; default: n=-999; printf("What did you say?\n"); break; } } io_flush; } else { // lien primaire: autoriser répertoire entier if (!force_mirror) { if ((opt->seeker & 1)==0) { // interdiction de descendre n=7; } else { n=5; // autoriser miroir répertoires descendants (lien primaire) } } else // forcer valeur (sub-wizard) n=force_mirror; } /* sanity check - reallocate filters HERE */ if ((*_FILTERS_PTR) + 1 >= opt->maxfilter) { opt->maxfilter += HTS_FILTERSINC; if (filters_init(&_FILTERS, opt->maxfilter, HTS_FILTERSINC) == 0) { printf("PANIC! : Too many filters : >%d [%d]\n", (*_FILTERS_PTR),__LINE__); fflush(stdout); if (opt->log) { fprintf(opt->log,LF"Too many filters, giving up..(>%d)"LF, (*_FILTERS_PTR) ); fprintf(opt->log,"To avoid that: use #F option for more filters (example: -#F5000)"LF); test_flush; } assertf("too many filters - giving up" == NULL); // wild.. } } // here we have enough room for a new filter if necessary switch(n) { case -1: // sauter tout le reste forbidden_url=1; opt->wizard=2; // sauter tout le reste break; case 0: // interdire les mêmes liens: adr/fil forbidden_url=1; HT_INSERT_FILTERS0; // insérer en 0 strcpybuff(_FILTERS[0],"-"); strcatbuff(_FILTERS[0],jump_identification(adr)); if (*fil!='/') strcatbuff(_FILTERS[0],"/"); strcatbuff(_FILTERS[0],fil); break; case 1: // éliminer répertoire entier et sous rép: adr/path/ * forbidden_url=1; { size_t i = strlen(fil)-1; while((fil[i]!='/') && (i>0)) i--; if (fil[i]=='/') { HT_INSERT_FILTERS0; // insérer en 0 strcpybuff(_FILTERS[0],"-"); strcatbuff(_FILTERS[0],jump_identification(adr)); if (*fil!='/') strcatbuff(_FILTERS[0],"/"); strncatbuff(_FILTERS[0] ,fil,i); if (_FILTERS[0][strlen(_FILTERS[0])-1]!='/') strcatbuff(_FILTERS[0],"/"); strcatbuff(_FILTERS[0],"*"); } } // ** ... break; case 2: // adresse adr* forbidden_url=1; HT_INSERT_FILTERS0; // insérer en 0 strcpybuff(_FILTERS[0],"-"); strcatbuff(_FILTERS[0],jump_identification(adr)); strcatbuff(_FILTERS[0],"*"); break; case 3: // ** A FAIRE forbidden_url=1; /* { int i=strlen(adr)-1; while((adr[i]!='/') && (i>0)) i--; if (i>0) { } }*/ break; // case 4: // same link // PAS BESOIN!! /*HT_INSERT_FILTERS0; // insérer en 0 strcpybuff(_FILTERS[0],"+"); strcatbuff(_FILTERS[0],adr); if (*fil!='/') strcatbuff(_FILTERS[0],"/"); strcatbuff(_FILTERS[0],fil);*/ // étant donné le renversement wizard/primary filter (les primary autorisent up/down ET interdisent) // il faut éviter d'un lien isolé effectue un miroir total.. *set_prio_to = 0+1; // niveau de récursion=0 (pas de miroir) break; case 5: // autoriser répertoire entier et fils if ((opt->seeker & 2)==0) { // interdiction de monter size_t i = strlen(fil)-1; while((fil[i]!='/') && (i>0)) i--; if (fil[i]=='/') { HT_INSERT_FILTERS0; // insérer en 0 strcpybuff(_FILTERS[0],"+"); strcatbuff(_FILTERS[0],jump_identification(adr)); if (*fil!='/') strcatbuff(_FILTERS[0],"/"); strncatbuff(_FILTERS[0],fil,i+1); strcatbuff(_FILTERS[0],"*"); } } else { // autoriser domaine alors!! HT_INSERT_FILTERS0; // insérer en 0 strcpybuff(filters[filptr],"+"); strcpybuff(_FILTERS[0],"+"); strcatbuff(_FILTERS[0],jump_identification(adr)); strcatbuff(_FILTERS[0],"*"); } break; case 6: // same domain HT_INSERT_FILTERS0; // insérer en 0 strcpybuff(filters[filptr],"+"); strcpybuff(_FILTERS[0],"+"); strcatbuff(_FILTERS[0],jump_identification(adr)); strcatbuff(_FILTERS[0],"*"); break; // case 7: // autoriser ce répertoire { size_t i = strlen(fil)-1; while((fil[i]!='/') && (i>0)) i--; if (fil[i]=='/') { HT_INSERT_FILTERS0; // insérer en 0 strcpybuff(_FILTERS[0],"+"); strcatbuff(_FILTERS[0],jump_identification(adr)); if (*fil!='/') strcatbuff(_FILTERS[0],"/"); strncatbuff(_FILTERS[0],fil,i+1); strcatbuff(_FILTERS[0],"*[file]"); } } break; case 50: // on fait rien break; } // switch } // test du wizard sur l'url } // fin du test wizard.. // -------------------- PHASE 5 -------------------- // lien non autorisé, peut-on juste le tester? if (just_test_it) { if (forbidden_url==1) { if (opt->travel&256) { // tester tout de même if (strfield(adr,"ftp://")==0 #if HTS_USEMMS && strfield(adr,"mms://")==0 #endif ) { // PAS ftp! forbidden_url=1; // oui oui toujours interdit (note: sert à rien car ==1 mais c pour comprendre) *just_test_it=1; // mais on teste if ((opt->debug>1) && (opt->log!=NULL)) { HTS_LOG(opt,LOG_DEBUG); fprintf(opt->log,"Testing link %s%s"LF,adr,fil); } } } } //adr[0]='\0'; // cancel } // -------------------- FINAL PHASE -------------------- // Test if the "Near" test won if (may_set_prio_to && forbidden_url == 0) { *set_prio_to = may_set_prio_to; } return forbidden_url; #undef _FILTERS #undef _FILTERS_PTR #undef _ROBOTS }
// forme à partir d'un lien et du contexte (origin_fil et origin_adr d'où il est tiré) adr et fil // [adr et fil sont des buffers de 1ko] // 0 : ok // -1 : erreur // -2 : protocole non supporté (ftp) int ident_url_relatif(const char *lien, const char *origin_adr, const char *origin_fil, lien_adrfil* const adrfil) { int ok = 0; int scheme = 0; assertf(adrfil != NULL); adrfil->adr[0] = '\0'; adrfil->fil[0] = '\0'; //effacer buffers // lien non vide! if (strnotempty(lien) == 0) return -1; // erreur! // Scheme? { const char *a = lien; while(isalpha((unsigned char) *a)) a++; if (*a == ':') scheme = 1; } // filtrer les parazites (mailto & cie) // scheme+authority (//) if ((strfield(lien, "http://")) // scheme+// || (strfield(lien, "file://")) // scheme+// || (strncmp(lien, "//", 2) == 0) // // sans scheme (-> default) ) { if (ident_url_absolute(lien, adrfil) == -1) { ok = -1; // erreur URL } } else if (strfield(lien, "ftp://")) { // Note: ftp:foobar.gif is not valid if (ftp_available()) { // ftp supporté if (ident_url_absolute(lien, adrfil) == -1) { ok = -1; // erreur URL } } else { ok = -2; // non supporté } #if HTS_USEOPENSSL } else if (strfield(lien, "https://")) { // Note: ftp:foobar.gif is not valid if (ident_url_absolute(lien, adrfil) == -1) { ok = -1; // erreur URL } #endif } else if ((scheme) && ((!strfield(lien, "http:")) && (!strfield(lien, "https:")) && (!strfield(lien, "ftp:")) )) { ok = -1; // unknown scheme } else { // c'est un lien relatif // On forme l'URL complète à partie de l'url actuelle // et du chemin actuel si besoin est. // sanity check if (origin_adr == NULL || origin_fil == NULL || *origin_adr == '\0' || *origin_fil == '\0') { return -1; } // copier adresse if (((int) strlen(origin_adr) < HTS_URLMAXSIZE) && ((int) strlen(origin_fil) < HTS_URLMAXSIZE) && ((int) strlen(lien) < HTS_URLMAXSIZE)) { /* patch scheme if necessary */ if (strfield(lien, "http:")) { lien += 5; strcpybuff(adrfil->adr, jump_protocol_const(origin_adr)); // même adresse ; protocole vide (http) } else if (strfield(lien, "https:")) { lien += 6; strcpybuff(adrfil->adr, "https://"); // même adresse forcée en https strcatbuff(adrfil->adr, jump_protocol_const(origin_adr)); } else if (strfield(lien, "ftp:")) { lien += 4; strcpybuff(adrfil->adr, "ftp://"); // même adresse forcée en ftp strcatbuff(adrfil->adr, jump_protocol_const(origin_adr)); } else { strcpybuff(adrfil->adr, origin_adr); // même adresse ; et même éventuel protocole } if (*lien != '/') { // sinon c'est un lien absolu if (*lien == '\0') { strcpybuff(adrfil->fil, origin_fil); } else if (*lien == '?') { // example: a href="?page=2" char *a; strcpybuff(adrfil->fil, origin_fil); a = strchr(adrfil->fil, '?'); if (a) *a = '\0'; strcatbuff(adrfil->fil, lien); } else { const char *a = strchr(origin_fil, '?'); if (a == NULL) a = origin_fil + strlen(origin_fil); while((*a != '/') && (a > origin_fil)) a--; if (*a == '/') { // ok on a un '/' if ((((int) (a - origin_fil)) + 1 + strlen(lien)) < HTS_URLMAXSIZE) { // copier chemin strncpy(adrfil->fil, origin_fil, ((int) (a - origin_fil)) + 1); *(adrfil->fil + ((int) (a - origin_fil)) + 1) = '\0'; // copier chemin relatif if (((int) strlen(adrfil->fil) + (int) strlen(lien)) < HTS_URLMAXSIZE) { strcatbuff(adrfil->fil, lien + ((*lien == '/') ? 1 : 0)); // simplifier url pour les ../ fil_simplifie(adrfil->fil); } else ok = -1; // erreur } else { // erreur ok = -1; // erreur URL } } else { // erreur ok = -1; // erreur URL } } } else { // chemin absolu // copier chemin directement strcatbuff(adrfil->fil, lien); fil_simplifie(adrfil->fil); } // *lien!='/' } else ok = -1; } // test news: etc. // case insensitive pour adresse { char *a = jump_identification(adrfil->adr); while(*a) { if ((*a >= 'A') && (*a <= 'Z')) *a += 'a' - 'A'; a++; } } // IDNA / RFC 3492 (Punycode) handling for HTTP(s) if (!link_has_authority(adrfil->adr) || strfield(adrfil->adr, "https:")) { char *const a = jump_identification(adrfil->adr); // Non-ASCII characters (theorically forbidden, but browsers are lenient) if (!hts_isStringAscii(a, strlen(a))) { char *const idna = hts_convertStringUTF8ToIDNA(a, strlen(a)); if (idna != NULL) { if (strlen(idna) < HTS_URLMAXSIZE) { strcpybuff(a, idna); } free(idna); } } } return ok; }