/****************************************************************************** Return the content-range in bytes, as returned by the server, if this is Content-range header, -1 otherwise. ******************************************************************************/ long long hgetrange(const char *hdr) { const int l = 14; /* strlen("content-range:"). */ long long len; if (strncasecmp(hdr, "content-range:", l)) return -1; hdr += (l + hskip_lws(hdr + l)); if (!*hdr) return -1; /* Nutscape proxy server sends content-length without "bytes" specifier, which is a breach of HTTP/1.1 draft. But heck, I must support it... */ if (!strncasecmp(hdr, "bytes", 5)) { hdr += 5; hdr += hskip_lws(hdr); if (!*hdr) return -1; } if (!isdigit(*hdr)) return -1; for (len = 0; isdigit(*hdr); hdr++) len = 10 * len + (*hdr - '0'); proz_debug("range %s range %lld",*hdr,len); return len; }
/****************************************************************************** Return the content length of the document body, if this is Content-length header, -1 otherwise. ******************************************************************************/ long long hgetlen(const char *hdr) { const int l = 15; /* strlen("content-length:"). */ long long len; if (strncasecmp(hdr, "content-length:", l)) return -1; hdr += (l + hskip_lws(hdr + l)); if (!*hdr) return -1; if (!isdigit(*hdr)) return -1; for (len = 0; isdigit(*hdr); hdr++) len = 10 * len + (*hdr - '0'); proz_debug("contenlen %s contentlen %lld",*hdr,len); return len; }
int open_new_dl_win (urlinfo * url_data, boolean ftpsearch) { dl_win = new DL_Window (url_data); dl_win->dl_start (rt.num_connections, ftpsearch); proz_debug ("calling the callback function..."); //need a timer here... while (dl_win->status != DL_DONE && dl_win->status != DL_IDLING && dl_win->status != DL_ABORTED) { delay_ms (700); //wait before checking the status again... dl_win->my_cb (); } return((dl_win->status==DL_DONE) ? 1:-1); // delete (dl_win); }
/* Sets the default config */ void set_defaults() { struct stat st; char cwd[PATH_MAX]; /* * Zero the structure which holds the config data */ memset(&rt, 0, sizeof(rt)); if (getcwd(cwd, sizeof(cwd)) == NULL){ proz_debug("Failed to get the current working directory"); strcpy(cwd, "."); } if (rt.home_dir != 0) free(rt.home_dir); rt.home_dir = strdup(libprozrtinfo.home_dir); /*TODO what to do if the homedir is NULL */ if (rt.config_dir != 0) free(rt.config_dir); rt.config_dir = (char *) malloc(PATH_MAX); snprintf(rt.config_dir, PATH_MAX, "%s/%s", rt.home_dir, PRZCONFDIR); /* Make the ~/.prozilla directory if necessary */ if (stat(rt.config_dir, &st) == -1){ /*error has hapenned */ if (errno == ENOENT){ /*Create the dir then */ if (mkdir(rt.config_dir, S_IRWXU) != 0){ perror(_("unable to create the directory to store the config info in")); exit(0); } } else perror(_("Error while stating the config info directory")); } /*Output the file to the directory , cwd by default */ if (rt.output_dir != 0) free(rt.output_dir); rt.output_dir = strdup(cwd); if (rt.dl_dir != 0) free(rt.dl_dir); rt.dl_dir = strdup(cwd); if (rt.logfile_dir != 0) free(rt.logfile_dir); rt.logfile_dir = strdup(rt.config_dir); /* * The default no of connections and maximum redirections allowed */ rt.num_connections = 4; rt.max_redirections = 10; /* Uses PASV by default */ rt.ftp_use_pasv = libprozrtinfo.ftp_use_pasv; /* * The force option, off by default when enabled * cause Prozilla not to prompt the user about overwriting existent * files etc.. */ rt.force_mode = FALSE; /* * .netrc options */ rt.use_netrc = TRUE; /* * The max number of trys and the delay between each */ rt.max_attempts = 0; /* TODO : It is currently unlimited */ rt.retry_delay = 15; /* delay in seconds */ /*Default is to not log any debug info */ rt.debug_mode = FALSE; rt.quiet_mode = TRUE; rt.libdebug_mode = TRUE; rt.ftp_search = FALSE; rt.min_search_size=128; rt.max_simul_pings = 5; rt.max_ping_wait = 8; rt.ftps_mirror_req_n = 40; rt.max_bps_per_dl = 0; /* 0= No throttling */ if (rt.http_proxy != 0) free(rt.http_proxy); rt.http_proxy = (proxy_info *) malloc(sizeof(proxy_info)); rt.http_proxy->username = strdup(""); rt.http_proxy->passwd = strdup(""); rt.http_proxy->type = HTTPPROXY; proz_parse_url("localhost:3128", &rt.http_proxy->proxy_url, 0); rt.use_http_proxy = FALSE; if (rt.ftp_proxy != 0) free(rt.ftp_proxy); rt.ftp_proxy = (proxy_info *) malloc(sizeof(proxy_info)); rt.ftp_proxy->username = strdup(""); rt.ftp_proxy->passwd = strdup(""); rt.ftp_proxy->type = HTTPPROXY; proz_parse_url("localhost:3128", &rt.ftp_proxy->proxy_url, 0); rt.use_ftp_proxy = FALSE; rt.http_no_cache = FALSE; rt.timeout.tv_sec = 90; rt.timeout.tv_usec = 0; rt.ftpsearch_server_id = 1; /*Set the values necessary for libprozilla */ rt.display_mode = DISP_STDOUT; set_runtime_values(); return; }
uerr_t ftp_parse(ftpparse *fp,char *buf,int len) { char *cp; char *token; char *ptr; char *date; int i; fp->filename = 0; fp->namelen = 0; // fp->flagtrycwd = 0; // fp->flagtryretr = 0; //fp->sizetype = FTPPARSE_SIZE_UNKNOWN; fp->filesize = 0; // fp->mtimetype = FTPPARSE_MTIME_UNKNOWN; fp->mtime = 0; // fp->idtype = FTPPARSE_ID_UNKNOWN; fp->id = 0; // fp->idlen = 0; proz_debug("FTP LIST to be parsed is %s", cp=strdup(buf)); free(cp); if (len < 2) /* an empty name in EPLF, with no info, could be 2 chars */ return FTPPARSENOTEXIST; switch(*buf) { case 'b': case 'c': case 'd': case 'l': case 'p': case 's': case '-': /* UNIX-style listing, without inum and without blocks */ /* "-rw-r--r-- 1 root other 531 Jan 29 03:26 README" */ /* "dr-xr-xr-x 2 root other 512 Apr 8 1994 etc" */ /* "dr-xr-xr-x 2 root 512 Apr 8 1994 etc" */ /* "lrwxrwxrwx 1 root other 7 Jan 25 00:17 bin -> usr/bin" */ /* Also produced by Microsoft's FTP servers for Windows: */ /* "---------- 1 owner group 1803128 Jul 10 10:18 ls-lR.Z" */ /* "d--------- 1 owner group 0 May 9 19:45 Softlib" */ /* Also WFTPD for MSDOS: */ /* "-rwxrwxrwx 1 noone nogroup 322 Aug 19 1996 message.ftp" */ /* Also NetWare: */ /* "d [R----F--] supervisor 512 Jan 16 18:53 login" */ /* "- [R----F--] rhesus 214059 Oct 20 15:27 cx.exe" */ /* Also NetPresenz for the Mac: */ /* "-------r-- 326 1391972 1392298 Nov 22 1995 MegaPhone.sit" */ /* "drwxrwxr-x folder 2 May 10 1996 network" */ if (*buf == 'd') fp->filetype = DIRECTORY; if (*buf == '-') fp->filetype = DIRECTORY; if (*buf == 'l') fp->filetype = SYMBOLIC_LINK; ptr=cp=strdup(buf); for (i=0;i<4;i++) { //add checking token= get_nextfield(&cp); if(token == NULL) //failed to parse return FTPPARSEFAIL; } /* ** This field can either be group or size. We find out by looking at the ** next field. If this is a non-digit then this field is the size. */ while (*cp && isspace((int) *cp)) cp++; if (isdigit((int) *cp)) { token = get_nextfield(&cp); while (*cp && isspace((int) *cp)) cp++; } //if it is a filename fp->filesize=strtol(token,NULL,10); proz_debug("FTP file size is %ld", fp->filesize); while (*cp && isspace((int) *cp)) cp++; assert(cp+12<ptr+len); date = cp; cp += 12; *cp++ = '\0'; fp->date_str = strdup(date); proz_debug("LIST date is %s", fp->date_str); return FTPPARSEOK; default: return FTPPARSEFAIL; } }
uerr_t tcp_ping(ping_t * ping_data) { int status, noblock, flags; extern int h_errno; struct timeval start_time; struct timeval end_time; char ping_buf[TCP_PING_PACKSIZE]; int bytes_read; struct addrinfo hints, *res=NULL; char szPort[10]; int error; assert(ping_data->host); memset(&hints, 0, sizeof(hints)); memset(szPort, 0, sizeof(szPort)); snprintf(szPort, sizeof(szPort), "%d", ping_data->port); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(ping_data->host, szPort, &hints, &res); if (error) { return ping_data->err = HOSTERR; } if ((ping_data->sock = socket(res->ai_family, res->ai_socktype, IPPROTO_TCP)) < 1) { free(res); return ping_data->err = CONSOCKERR; } /* Experimental. */ flags = fcntl(ping_data->sock, F_GETFL, 0); if (flags != -1) noblock = fcntl(ping_data->sock, F_SETFL, flags | O_NONBLOCK); else noblock = -1; /* get start time */ gettimeofday(&start_time, 0); status = connect(ping_data->sock, res->ai_addr, res->ai_addrlen); if ((status == -1) && (noblock != -1) && (errno == EINPROGRESS)) { fd_set writefd; FD_ZERO(&writefd); FD_SET(ping_data->sock, &writefd); status = select((ping_data->sock + 1), NULL, &writefd, NULL, &ping_data->timeout); /* Do we need to retry if the err is EINTR? */ if (status > 0) { socklen_t arglen = sizeof(int); if (getsockopt (ping_data->sock, SOL_SOCKET, SO_ERROR, &status, &arglen) < 0) status = errno; if (status != 0) errno = status, status = -1; if (errno == EINPROGRESS) errno = ETIMEDOUT; } else if (status == 0) errno = ETIMEDOUT, status = -1; } if (status < 0) { close_sock(&ping_data->sock); if (errno == ECONNREFUSED) { free(res); return ping_data->err = CONREFUSED; } else if (errno == ETIMEDOUT) { free(res); return ping_data->err = PINGTIMEOUT; } else { free(res); return ping_data->err = CONERROR; } } else { flags = fcntl(ping_data->sock, F_GETFL, 0); if (flags != -1) fcntl(ping_data->sock, F_SETFL, flags & ~O_NONBLOCK); } /* setsockopt(*sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&opt, (int) sizeof(opt)); */ free(res); /*So far so good connection established */ bytes_read = krecv(ping_data->sock, ping_buf, TCP_PING_PACKSIZE, 0, &ping_data->timeout); close_sock(&ping_data->sock); proz_debug("bytes read = %d", bytes_read); if (bytes_read == -1) { if (errno == ETIMEDOUT) return ping_data->err = PINGTIMEOUT; else return ping_data->err = READERR; } if (bytes_read == 0 || bytes_read < TCP_PING_PACKSIZE) return ping_data->err = READERR; /* the end time */ gettimeofday(&end_time, 0); proz_timeval_subtract(&ping_data->ping_time, &end_time, &start_time); /* standard_ping_milli_secs =(int)((((float)ping_data->ping_time.tv_usec/1000)+(((float)ping_data->ping_time.tv_sec)*1000))*3/(float)bytes_read); ping_data->ping_time.tv_sec=standard_ping_milli_secs/1000; ping_data->ping_time.tv_usec=standard_ping_milli_secs%1000; */ return ping_data->err = PINGOK; }
void mass_ping(ftps_request_t * request) { int i, j, k = 0, num_iter, num_left, simul_pings; pthread_t *ping_threads; ping_t *ping_requests; simul_pings = request->max_simul_pings; pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); ping_threads = (pthread_t *) kmalloc(sizeof(pthread_t) * simul_pings); ping_requests = kmalloc(sizeof(ping_t) * request->num_mirrors); num_iter = request->num_mirrors / simul_pings; num_left = request->num_mirrors % simul_pings; proz_debug("Max simul pings=%d", simul_pings); proz_debug("request->num_mirrors=%d", request->num_mirrors); pthread_mutex_lock(&request->access_mutex); request->mass_ping_running = TRUE; pthread_mutex_unlock(&request->access_mutex); k = 0; for (i = 0; i < num_iter; i++) { for (j = 0; j < simul_pings; j++) { ping_t ping_request; memset(ping_requests + k, 0, sizeof(ping_request)); /*FIXME */ ping_requests[k].timeout.tv_sec = request->ping_timeout.tv_sec; ping_requests[k].timeout.tv_usec = request->ping_timeout.tv_usec; ping_requests[k].host = strdup(request->mirrors[k].server_name); ping_requests[k].port = 21; if (pthread_create(&ping_threads[j], NULL, (void *) &tcp_ping, (void *) (ping_requests + k)) != 0) proz_die("Error: Not enough system resources" "to create thread!\n"); k++; } k -= simul_pings; for (j = 0; j < simul_pings; j++) { /*Wait till the end of each thread. */ pthread_join(ping_threads[j], NULL); if (ping_requests[k].err == PINGOK) { pthread_mutex_lock(&request->access_mutex); request->mirrors[k].milli_secs = (ping_requests[k].ping_time.tv_sec * 1000) + (ping_requests[k].ping_time.tv_usec / 1000); request->mirrors[k].status = RESPONSEOK; pthread_mutex_unlock(&request->access_mutex); } else { pthread_mutex_lock(&request->access_mutex); request->mirrors[k].status = NORESPONSE; pthread_mutex_unlock(&request->access_mutex); } k++; } } for (j = 0; j < num_left; j++) { ping_t ping_request; memset(ping_requests + k, 0, sizeof(ping_request)); /*FIXME */ ping_requests[k].timeout.tv_sec = request->ping_timeout.tv_sec; ping_requests[k].timeout.tv_usec = 0; ping_requests[k].host = strdup(request->mirrors[k].server_name); ping_requests[k].port = 21; if (pthread_create(&ping_threads[j], NULL, (void *) &tcp_ping, (void *) (&ping_requests[k])) != 0) proz_die("Error: Not enough system resources" "to create thread!\n"); k++; } k -= num_left; for (j = 0; j < num_left; j++) { /*Wait till the end of each thread. */ pthread_join(ping_threads[j], NULL); /*Wait till the end of each thread. */ pthread_join(ping_threads[j], NULL); if (ping_requests[k].err == PINGOK) { pthread_mutex_lock(&request->access_mutex); request->mirrors[k].milli_secs = (ping_requests[k].ping_time.tv_sec * 1000) + (ping_requests[k].ping_time.tv_usec / 1000); request->mirrors[k].status = RESPONSEOK; pthread_mutex_unlock(&request->access_mutex); } else { pthread_mutex_lock(&request->access_mutex); request->mirrors[k].status = NORESPONSE; pthread_mutex_unlock(&request->access_mutex); } k++; } proz_debug("mass_ping complete."); pthread_mutex_lock(&request->access_mutex); request->mass_ping_running = FALSE; pthread_mutex_unlock(&request->access_mutex); }
int proz_log_read_logfile(logfile * lf, download_t * download, boolean load_con_info) { char buffer[PATH_MAX]; FILE *fp = NULL; int i; /* * Compute the name of the logfile */ snprintf(buffer, PATH_MAX, "%s/%s%s.log", download->log_dir, download->u.file, DEFAULT_FILE_EXT); if (!(fp = fopen(buffer, "rb"))) { /* * fixme add the error displaing to the main function */ download_show_message(download, _("Error opening file %s for reading: %s"), buffer, strerror(errno)); return -1; } if (fread(lf, 1, sizeof(logfile), fp) != sizeof(logfile)) { fclose(fp); return -1; } lf->url = kmalloc(lf->url_len + 1); if (fread(lf->url, 1, lf->url_len, fp) != lf->url_len) { fclose(fp); return -1; } lf->url[lf->url_len] = 0; if (load_con_info == TRUE) { for (i = 0; i < lf->num_connections; i++) { proz_debug("value before= %d", download->pconnections[i]->local_startpos); if (fread (&download->pconnections[i]->local_startpos, 1, sizeof(download->pconnections[i]->local_startpos), fp) != sizeof(download->pconnections[i]->local_startpos)) { download_show_message(download, _("Error reading from file %s: %s"), buffer, strerror(errno)); fclose(fp); return -1; } proz_debug("value after= %d", download->pconnections[i]->local_startpos); proz_debug("orig_remote_startpos before= %d", download->pconnections[i]->orig_remote_startpos); if (fread (&download->pconnections[i]->orig_remote_startpos, 1, sizeof(download->pconnections[i]->orig_remote_startpos), fp) != sizeof(download->pconnections[i]->orig_remote_startpos)) { download_show_message(download, _("Error reading from file %s: %s"), buffer, strerror(errno)); fclose(fp); return -1; } proz_debug("orig_remote_startpos after= %d", download->pconnections[i]->orig_remote_startpos); proz_debug("remote_edndpos before= %d", download->pconnections[i]->remote_endpos); if (fread (&download->pconnections[i]->remote_endpos, 1, sizeof(download->pconnections[i]->remote_endpos), fp) != sizeof(download->pconnections[i]->remote_endpos)) { download_show_message(download, _("Error reading from file %s: %s"), buffer, strerror(errno)); fclose(fp); return -1; } proz_debug("remote_endpos after= %d", download->pconnections[i]->remote_endpos); proz_debug("remote_bytes_received before= %d", download->pconnections[i]->remote_bytes_received); if (fread (&download->pconnections[i]->remote_bytes_received, 1, sizeof(download->pconnections[i]->remote_bytes_received), fp) != sizeof(download->pconnections[i]->remote_bytes_received)) { download_show_message(download, _("Error reading from file %s: %s"), buffer, strerror(errno)); fclose(fp); return -1; } proz_debug("remote_bytes_received after= %d", download->pconnections[i]->remote_bytes_received); } } fclose(fp); return 1; }
int main (int argc, char **argv) { int c; int ret; proz_init (argc, argv); //init libprozilla set_defaults (); //set some reasonable defaults load_prefs (); //load values from the config file while ((c = getopt_long (argc, argv, "?hvrfk:1Lt:VgsP:", long_opts, NULL)) != EOF) { switch (c) { case 'L': license (); exit (0); case 'h': help (); exit (0); case 'V': version (); exit (0); case 'r': rt.resume_mode = RESUME; break; case 'f': rt.force_mode = TRUE; break; case 'k': if (setargval (optarg, &rt.num_connections) != 1) { /* * The call failed due to a invalid arg */ printf (_("Error: Invalid arguments for the -k option\n" "Please type proz --help for help\n")); exit (0); } if (rt.num_connections == 0) { printf (_("Hey! How can I download anything with 0 (Zero)" " connections!?\n" "Please type proz --help for help\n")); exit (0); } break; case 't': if (setargval (optarg, &rt.max_attempts) != 1) { /* * The call failed due to a invalid arg */ printf (_("Error: Invalid arguments for the -t or --tries option(s)\n" "Please type proz --help for help\n")); exit (0); } break; case 'n': /* * Don't use ~/.netrc" */ rt.use_netrc = FALSE; break; case 'P': /* * Save the downloaded file to DIR */ rt.output_dir = kstrdup (optarg); break; case '?': help (); exit (0); break; case '1': rt.num_connections = 1; break; case 'g': /* * TODO solve this soon */ printf ("Error: GTK interface is not supported in " "the development version currently\n"); exit (0); break; case 129: /* * lets use PORT as the default then */ rt.ftp_use_pasv = FALSE; break; case 130: /* * retry-delay option */ if (setargval (optarg, &rt.retry_delay) != 1) { /* * The call failed due to a invalid arg */ printf (_("Error: Invalid arguments for the --retry-delay option\n" "Please type proz --help for help\n")); exit (0); } break; case 131: /*--timout option */ if (setargval (optarg, &rt.itimeout) != 1) { /* * The call failed due to a invalid arg */ printf (_("Error: Invalid arguments for the --timeout option\n" "Please type proz --help for help\n")); exit (0); } break; case 132: /* --no-getch option */ rt.dont_prompt = TRUE; break; case 133: /* --debug option */ rt.debug_mode = TRUE; rt.libdebug_mode=TRUE; break; case 'v': /* --verbose option */ rt.quiet_mode = FALSE; break; case 's': /* --ftpsearch option */ rt.ftp_search = TRUE; break; case 135: /* --no-search option */ rt.ftp_search = FALSE; break; case 136: /* --pt option */ if (setargval (optarg, &rt.max_ping_wait) != 1) { /* * The call failed due to a invalid arg */ printf (_("Error: Invalid arguments for the --pt option\n" "Please type proz --help for help\n")); exit (0); } if (rt.max_ping_wait == 0) { printf (_("Hey! Does waiting for a server response for Zero(0)" " seconds make and sense to you!?\n" "Please type proz --help for help\n")); exit (0); } break; case 137: /* --pao option */ if (setargval (optarg, &rt.max_simul_pings) != 1) { /* * The call failed due to a invalid arg */ printf (_("Error: Invalid arguments for the --pao option\n" "Please type proz --help for help\n")); exit (0); } if (rt.max_simul_pings == 0) { printf (_("Hey you! Will pinging Zero(0) servers at once" " achive anything for me!?\n" "Please type proz --help for help\n")); exit (0); } break; case 138: /* --max-ftp-servers option */ if (setargval (optarg, &rt.ftps_mirror_req_n) != 1) { /* * The call failed due to a invalid arg */ printf (_("Error: Invalid arguments for the --pao option\n" "Please type proz --help for help\n")); exit (0); } if (rt.ftps_mirror_req_n == 0) { printf (_("Hey! Will requesting Zero(0) servers at once" "from the ftpearch achive anything!?\n" "Please type proz --help for help\n")); exit (0); } break; case 139: /* --max-bps */ if (setlongargval (optarg, &rt.max_bps_per_dl) != 1) { /* * The call failed due to a invalid arg */ printf (_("Error: Invalid arguments for the --max-bps option\n" "Please type proz --help for help\n")); exit (0); } break; case 140: rt.display_mode = DISP_STDOUT; break; case 141: /* --min-size */ if (setlongargval (optarg, &rt.min_search_size) != 1) { /* * The call failed due to a invalid arg */ printf (_("Error: Invalid arguments for the --min-size option\n" "Please type proz --help for help\n")); exit (0); } break; case 142: /* --ftpsid */ if (setargval (optarg, &rt.ftpsearch_server_id) != 1) { /* * The call failed due to a invalid arg */ printf (_("Error: Invalid arguments for the --ftpsid option\n" "Please type proz --help for help\n")); exit (0); } if (rt.ftpsearch_server_id < 0 || rt.ftpsearch_server_id >1) { printf (_("The available servers are (0) filesearching.com and (1) ftpsearch.elmundo.es\n" "Please type proz --help for help\n")); exit (0); } break; default: printf (_("Error: Invalid option\n")); exit (0); } } set_runtime_values (); //tell libprozilla about any changed settings if (optind == argc) { help (); } else { /* Gettext stuff */ setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); /*delete the ~/.prozilla/debug.log file if present at the start of each run */ proz_debug_delete_log (); if (rt.display_mode == DISP_CURSES) initCurses(); /* we will now see whether the user has specfied any urls in the command line and add them */ for (int i = optind; i < argc; i++) { uerr_t err; urlinfo *url_data; url_data = (urlinfo *) malloc (sizeof (urlinfo)); memset (url_data, 0, sizeof (urlinfo)); //parses and validates the command-line parm err = proz_parse_url (argv[i], url_data, 0); if (err != URLOK) { PrintMessage (_ ("%s does not seem to be a valid URL"), argv[optind]); proz_debug ("%s does not seem to be a valid URL", argv[optind]); exit (0); } PrintMessage("Starting....."); //In to %s\n",url_data->host); // start the download ret=open_new_dl_win (url_data, rt.ftp_search); /*If the download failed the return -1 */ if(ret==-1) { free(url_data); delete(dl_win); shutdown(); return -1; } delete(dl_win); free (url_data); } } shutdown(); }
uerr_t ftp_get_url_info_from_http_proxy(connection_t * connection) { uerr_t err; int remote_port_len; char *user, *passwd, *www_auth = NULL, *proxy_auth = NULL, *pragma_no_cache = NULL; char *request, *remote_port; netrc_entry *netrc_ent; memset(&connection->hs, 0, sizeof(connection->hs)); err = connect_to_server(&connection->data_sock, connection->ftp_proxy->proxy_url.host, connection->ftp_proxy->proxy_url.port, &connection->xfer_timeout); if (err != NOCONERROR) { connection_show_message(connection, _("Error connecting to %s"), connection->ftp_proxy->proxy_url.host); return err; } user = connection->u.user; passwd = connection->u.passwd; /* Use .netrc if asked to do so. */ if (connection->use_netrc == TRUE) { netrc_ent = search_netrc(libprozrtinfo.netrc_list, connection->u.host); if (netrc_ent != NULL) { user = netrc_ent->account; passwd = netrc_ent->password; } } user = user ? user : ""; passwd = passwd ? passwd : ""; if (strlen(user) || strlen(passwd)) { /* Construct the necessary header. */ www_auth = get_basic_auth_str(user, passwd, "Authorization"); proz_debug(_("Authenticating as user %s password %s"), user, passwd); proz_debug(_("Authentification string=%s"), www_auth); } else www_auth = 0; if (strlen(connection->ftp_proxy->username) || strlen(connection->ftp_proxy->passwd)) proxy_auth = get_basic_auth_str(connection->ftp_proxy->username, connection->ftp_proxy->passwd, "Proxy-Authorization"); remote_port = (char *) alloca(64); remote_port_len = sprintf(remote_port, ":%d", connection->u.port); if (http_use_proxy(connection) && (connection->http_no_cache || connection->attempts > 0)) { pragma_no_cache = (char *) alloca(21); sprintf(pragma_no_cache, "Pragma: no-cache\r\n"); } /*Referrer TAG should not be needed in FTP through HTTP proxy..right */ request = (char *) alloca(strlen(connection->u.url) + strlen(connection->user_agent) + strlen(connection->u.host) + remote_port_len + (www_auth ? strlen(www_auth) : 0) + (proxy_auth ? strlen(proxy_auth) : 0) + 64 + (pragma_no_cache ? strlen(pragma_no_cache) : 0)); sprintf(request, "GET %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s%s\r\nAccept: */*\r\n%s%s%s\r\n", connection->u.url, connection->user_agent, connection->u.host, remote_port, www_auth ? www_auth : "", proxy_auth ? proxy_auth : "", pragma_no_cache ? pragma_no_cache : ""); proz_debug("HTTP request = %s", request); err = http_fetch_headers(connection, &connection->hs, request); close_sock(&connection->data_sock); /*Convert the error code to the equivalent FTP one if possible */ if (err == HOK) { connection->main_file_size = connection->hs.contlen; if (connection->hs.accept_ranges == 1) connection->resume_support = TRUE; else if (connection->hs.accept_ranges == -1) connection->resume_support = FALSE; return FTPOK; } if (err == HAUTHREQ) return FTPLOGREFUSED; else if (err == HTTPNSFOD) return FTPNSFOD; /* connection->file_type = REGULAR_FILE; */ return FTPERR; }
/****************************************************************************** ... ******************************************************************************/ uerr_t proz_http_get_url_info(connection_t * connection) { uerr_t err; int remote_port_len; char *user, *passwd, *www_auth = NULL, *proxy_auth = NULL, *referer = NULL, *location = NULL, *pragma_no_cache = NULL; char *request, *remote_port; netrc_entry *netrc_ent; memset(&connection->hs, 0, sizeof(connection->hs)); if (http_use_proxy(connection)) { connection_show_message(connection, _("Connecting to %s"), connection->http_proxy->proxy_url.host); err = connect_to_server(&connection->data_sock, connection->http_proxy->proxy_url.host, connection->http_proxy->proxy_url.port, &connection->xfer_timeout); if (err != NOCONERROR) { connection_show_message(connection, _("Error connecting to %s"), connection->http_proxy->proxy_url.host); return err; } } else { connection_show_message(connection, _("Connecting to %s"), connection->u.host); err = connect_to_server(&connection->data_sock, connection->u.host, connection->u.port, &connection->xfer_timeout); if (err != NOCONERROR) { connection_show_message(connection, _("Error connecting to %s"), connection->u.host); return err; } } user = connection->u.user; passwd = connection->u.passwd; /* Use .netrc if asked to do so. */ if (connection->use_netrc == TRUE) { netrc_ent = search_netrc(libprozrtinfo.netrc_list, connection->u.host); if (netrc_ent != NULL) { user = netrc_ent->account; passwd = netrc_ent->password; } } user = user ? user : ""; passwd = passwd ? passwd : ""; if (strlen(user) || strlen(passwd)) { /* Construct the necessary header. */ www_auth = get_basic_auth_str(user, passwd, "Authorization"); proz_debug(_("Authenticating as user %s password %s"), user, passwd); proz_debug(_("Authentification string=%s"), www_auth); } else www_auth = 0; if (http_use_proxy(connection)) { if (strlen(connection->http_proxy->username) || strlen(connection->http_proxy->passwd)) proxy_auth = get_basic_auth_str(connection->http_proxy->username, connection->http_proxy->passwd, "Proxy-Authorization"); } if (connection->u.port == 80) { remote_port = NULL; remote_port_len = 0; } else { remote_port = (char *) alloca(64); remote_port_len = sprintf(remote_port, ":%d", connection->u.port); } if (connection->u.referer) { referer = (char *) alloca(13 + strlen(connection->u.referer)); sprintf(referer, "Referer: %s\r\n", connection->u.referer); } /* If we go through a proxy the request for the URL is different */ if (http_use_proxy(connection)) { location = (char *) alloca(strlen(connection->u.url) + 1); strcpy(location, connection->u.url); } else { location = (char *) alloca(strlen(connection->u.path) + 1); strcpy(location, connection->u.path); } /*Use no-cache directive for proxy servers? */ if (http_use_proxy(connection) && (connection->http_no_cache || connection->attempts > 0)) { pragma_no_cache = (char *) alloca(21); sprintf(pragma_no_cache, "Pragma: no-cache\r\n"); } request = (char *) alloca(strlen(location) + strlen(connection->user_agent) + strlen(connection->u.host) + remote_port_len + (referer ? strlen(referer) : 0) + (www_auth ? strlen(www_auth) : 0) + (proxy_auth ? strlen(proxy_auth) : 0) + 64 + (pragma_no_cache ? strlen(pragma_no_cache) : 0)); sprintf(request, "GET %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s%s\r\nAccept: */*\r\n%s%s%s%s\r\n", location, connection->user_agent, connection->u.host, remote_port ? remote_port : "", referer ? referer : "", www_auth ? www_auth : "", proxy_auth ? proxy_auth : "", pragma_no_cache ? pragma_no_cache : ""); proz_debug("HTTP request = %s", request); connection_show_message(connection, _("Sending HTTP request")); err = http_fetch_headers(connection, &connection->hs, request); close_sock(&connection->data_sock); if (err == HOK) { connection->main_file_size = connection->hs.contlen; if (connection->hs.accept_ranges == 1) connection->resume_support = TRUE; else if (connection->hs.accept_ranges == -1) connection->resume_support = FALSE; } connection->file_type = REGULAR_FILE; return err; }
/****************************************************************************** ... ******************************************************************************/ uerr_t http_fetch_headers(connection_t * connection, http_stat_t * hs, char *command) { uerr_t err; int num_written, hcount, statcode, all_length; long long contlen, contrange; char *hdr, *type, *all_headers; const char *error; hs->len = 0L; hs->contlen = -1; hs->accept_ranges = -1; hs->res = -1; hs->newloc = NULL; hs->remote_time = NULL; hs->error = NULL; num_written = ksend(connection->data_sock, command, strlen(command), 0, &connection->xfer_timeout); if (num_written != strlen(command)) { proz_debug(_("Failed writing HTTP request")); return WRITEERR; } all_headers = NULL; all_length = 0; contlen = contrange = -1; statcode = -1; type = NULL; /* Header-fetching loop. */ hcount = 0; for (;;) { ++hcount; /* Get the header. */ err = fetch_next_header(connection->data_sock, &hdr, &connection->xfer_timeout); proz_debug(_("Header = %s"), hdr); if (err == HEOF) { proz_debug(_("End of file while parsing headers")); kfree(hdr); if (type) kfree(type); if (all_headers) kfree(all_headers); return HEOF; } else if (err == HERR) { proz_debug(_("Read error in headers")); kfree(hdr); if (type) kfree(type); if (all_headers) kfree(all_headers); return HERR; } /* Exit on empty header. */ if (!*hdr) { kfree(hdr); break; } /* Check for errors documented in the first header. */ if (hcount == 1) { statcode = hparsestatline(hdr, &error); hs->statcode = statcode; /* Store the descriptive response. */ if (statcode == -1) /* Malformed request. */ hs->error = kstrdup(_("UNKNOWN")); else if (!*error) hs->error = kstrdup(_("(no description)")); else hs->error = kstrdup(error); } if (contlen == -1) { contlen = hgetlen(hdr); hs->contlen = contlen; } /* If the server specified a new location then lets store it. */ if (!hs->newloc) hs->newloc = hgetlocation(hdr); if (!hs->remote_time) hs->remote_time = hgetmodified(hdr); if (hs->accept_ranges == -1) hs->accept_ranges = hgetaccept_ranges(hdr); if (!hs->newloc) hs->newloc = hgetlocation(hdr); kfree(hdr); } if (H_20X(statcode)) return HOK; if (H_REDIRECTED(statcode) || statcode == HTTP_MULTIPLE_CHOICES) { /* RFC2068 says that in case of the 300 (multiple choices) response, the server can output a preferred URL through `Location' header; otherwise, the request should be treated like GET. So, if the location is set, it will be a redirection; otherwise, just proceed normally. */ if (statcode == HTTP_MULTIPLE_CHOICES && !hs->newloc) return HOK; else { if (all_headers) kfree(all_headers); if (type) kfree(type); return NEWLOCATION; } } if (statcode == HTTP_UNAUTHORIZED) return HAUTHREQ; if (statcode == HTTP_NOT_FOUND) return HTTPNSFOD; if (statcode == HTTP_INTERNAL) return INTERNALSERVERR; if (statcode == HTTP_NOT_IMPLEMENTED) return UNKNOWNREQ; if (statcode == HTTP_BAD_GATEWAY) return BADGATEWAY; if (statcode == HTTP_UNAVAILABLE) return SERVICEUNAVAIL; if (statcode == HTTP_GATEWAY_TIMEOUT) return GATEWAYTIMEOUT; return HERR; }