int http_transfer(UrlResource *rsrc) { FILE *out = NULL; Url *u = NULL; Url *proxy_url = NULL; Url *redir_u = NULL; char *request = NULL; char *raw_header = NULL; HttpHeader *header = NULL; char *len_string = NULL; char *new_location = NULL; char buf[BUFSIZE]; int sock = 0; ssize_t bytes_read = 0; int retval = 0; int i; /* make sure we haven't recursed too much */ if( redirect_count > REDIRECT_MAX ) { report(ERR, "redirection max count exceeded " "(looping redirect?)"); redirect_count = 0; return 0; } /* make sure everything's initialized to something useful */ u = rsrc->url; if( ! *(u->host) ) { report(ERR, "no host specified"); return 0; } /* fill in proxyness */ if( !rsrc->proxy ) { rsrc->proxy = get_proxy("HTTP_PROXY"); } if( !rsrc->outfile ) { if( u->file ) rsrc->outfile = strdup(u->file); else rsrc->outfile = strdup("index.html"); } if( !u->path ) u->path = strdup("/"); if( !u->file ) u->file = strdup(""); /* funny looking */ if( !u->port ) u->port = 80; rsrc->options |= default_opts; /* send the request to either the proxy or the remote host */ if( rsrc->proxy ) { proxy_url = url_new(); url_init(proxy_url, rsrc->proxy); if( !proxy_url->port ) proxy_url->port = 80; if( !proxy_url->host ) { report(ERR, "bad proxy `%s'", rsrc->proxy); return 0; } if( proxy_url->username ) rsrc->proxy_username = strdup(proxy_url->username); if( proxy_url->password ) rsrc->proxy_password = strdup(proxy_url->password); /* Prompt for proxy password if not specified */ if( proxy_url->username && !proxy_url->password ) { char *prompt = NULL; prompt = strconcat("Password for proxy ", proxy_url->username, "@", proxy_url->host, ": ", NULL); proxy_url->password = strdup(getpass(prompt)); free(prompt); } if( ! (sock = tcp_connect(proxy_url->host, proxy_url->port)) ) return 0; u->path = strdup(""); u->file = strdup(u->full_url); request = get_request(rsrc); write(sock, request, strlen(request)); } else /* no proxy */ { if( ! (sock = tcp_connect(u->host, u->port)) ) return 0; request = get_request(rsrc); write(sock, request, strlen(request)); } out = open_outfile(rsrc); if( !out ) { report(ERR, "opening %s: %s", rsrc->outfile, strerror(errno)); return 0; } /* check to see if it returned a HTTP 1.x response */ memset(buf, '\0', 5); bytes_read = read(sock, buf, 8); if( bytes_read == 0 ) { close(sock); return 0; } if( ! (buf[0] == 'H' && buf[1] == 'T' && buf[2] == 'T' && buf[3] == 'P') ) { if ((rsrc->options & OPT_RESUME) && rsrc->outfile_offset) { report(WARN, "server does not support resume, " "try again" " with -n (no resume)"); retval = 0; goto cleanup; } write(fileno(out), buf, bytes_read); } else { /* skip the header */ buf[bytes_read] = '\0'; raw_header = get_raw_header(sock); raw_header = strconcat(buf, raw_header, NULL); header = make_http_header(raw_header); if (rsrc->options & OPT_VERBOSE) { fwrite(raw_header, 1, strlen(raw_header), stderr); } /* check for redirects */ new_location = get_header_value("location", header); if (raw_header[9] == '3' && new_location ) { redir_u = url_new(); /* make sure we still send user/password along */ redir_u->username = safe_strdup(u->username); redir_u->password = safe_strdup(u->password); url_init(redir_u, new_location); rsrc->url = redir_u; redirect_count++; retval = transfer(rsrc); goto cleanup; } if (raw_header[9] == '4' || raw_header[9] == '5') { for(i = 0; raw_header[i] && raw_header[i] != '\n'; i++); raw_header[i] = '\0'; report(ERR, "HTTP error from server: %s", raw_header); retval = 0; goto cleanup; } len_string = get_header_value("content-length", header); if (len_string) rsrc->outfile_size = (off_t )atoi(len_string); if (get_header_value("content-range", header)) rsrc->outfile_size += rsrc->outfile_offset; if( (!rsrc->outfile_size) && (rsrc->options & OPT_RESUME) && !(rsrc->options & OPT_NORESUME) && rsrc->outfile_offset ) { report(WARN, "unable to determine remote file size, try again" " with -n (no resume)"); retval = 0; goto cleanup; } } if( ! dump_data(rsrc, sock, out) ) retval = 0; else retval = 1; cleanup: free_http_header(header); close(sock); fclose(out); return retval; }
int http_transfer(UrlResource *rsrc, libnet_callback notify) { FILE *out = NULL; Url *u = NULL; Url *proxy_url = NULL; Url *redir_u = NULL; char *request = NULL; //char *raw_header = NULL; HttpHeader *header = NULL; //char *len_string = NULL; //char *new_location = NULL; char *tmp_string = NULL; //char buf[BUFSIZE]; int sock = -1; ssize_t bytes_read = 0; int msg_code = 0; int retval = 0; int i; char *buf = MALLOC(BUFSIZE); if (!buf) { LIBNET_DEBUG("No enough memory!\n"); return 0; } /* make sure we haven't recursed too much */ if ( redirect_count > REDIRECT_MAX ) { LIBNET_DEBUG("redirection max count exceeded (looping redirect?)"); redirect_count = 0; msg_code = -NET_ERR_CONNECT_FAILED; goto cleanup; } /* make sure everything's initialized to something useful */ u = rsrc->url; if ( !u->host ) { LIBNET_DEBUG("no host specified"); msg_code = -NET_ERR_CONNECT_FAILED; goto cleanup; } /* fill in proxyness */ if ( !rsrc->proxy ) { rsrc->proxy = get_proxy("HTTP_PROXY"); } if (( NULL == rsrc->outfile ) && (NULL == rsrc->buffer)) { if ( u->file ) rsrc->outfile = strdup(u->file); else rsrc->outfile = strdup("index.html"); } if ( !u->path ) u->path = strdup("/"); if ( !u->file ) u->file = strdup(""); /* funny looking */ if ( !u->port ) u->port = 80; rsrc->options |= default_opts; /* send the request to either the proxy or the remote host */ if ( rsrc->proxy ) { proxy_url = url_new(); url_init(proxy_url, rsrc->proxy); if ( !proxy_url->port ) proxy_url->port = 80; if ( !proxy_url->host ) { LIBNET_DEBUG( "bad proxy `%s'", rsrc->proxy); msg_code = -NET_ERR_CONNECT_FAILED; goto cleanup; } if ( proxy_url->username ) rsrc->proxy_username = strdup(proxy_url->username); if ( proxy_url->password ) rsrc->proxy_password = strdup(proxy_url->password); #ifdef LIB_W5300 sock = w5300_tcp_connect(proxy_url->host, proxy_url->port, rsrc->srcip, rsrc->srcport); #else sock = util_tcp_connect(proxy_url->host, proxy_url->port); #endif if (sock < 0) { msg_code = -NET_ERR_CONNECT_FAILED; goto cleanup; } safe_free(u->path); safe_free(u->file); u->path = strdup(""); u->file = strdup(u->full_url); request = get_request(rsrc); LIBNET_DEBUG("sending request:\n%s", request); S_WRITE(sock, request, STRLEN(request)); FREE(request); } else /* no proxy */ { #ifdef LIB_W5300 sock = w5300_tcp_connect(u->host, u->port, rsrc->srcip, rsrc->srcport); #else sock = util_tcp_connect(u->host, u->port); #endif if (sock < 0) { msg_code = -NET_ERR_CONNECT_FAILED; goto cleanup; } request = get_request(rsrc); LIBNET_DEBUG("sending request:\n%s", request); S_WRITE(sock, request, STRLEN(request)); FREE(request); } if (rsrc->outfile) { if ((get_file_size(rsrc->outfile) > 0) && (rsrc->options & OPT_RESUME)) out = fopen(rsrc->outfile, "rb+"); else out = fopen(rsrc->outfile, "wb"); if ( !out ) { LIBNET_DEBUG( "opening %s: %s", rsrc->outfile, ""); msg_code = -NET_ERR_FILE_SAVE_ERROR; goto cleanup; } } /* check to see if it returned a HTTP 1.x response */ MEMSET(buf, '\0', 5); #ifdef LIB_W5300 bytes_read = S_READ(sock, buf, BUFSIZE); buf[bytes_read] = '\0'; LIBNET_DEBUG("receive respond:(%d)\n%s", bytes_read, buf); #else bytes_read = S_READ(sock, buf, 8); #endif if ( bytes_read <= 0 ) { msg_code = -NET_ERR_HTTP_SERVER_ERROR; goto cleanup; } if ( ! (buf[0] == 'H' && buf[1] == 'T' && buf[2] == 'T' && buf[3] == 'P') ) { if((rsrc->options & OPT_RESUME) && rsrc->outfile_offset) { LIBNET_DEBUG("server does not support resume!"); msg_code = -NET_ERR_OPERATION_NOT_PERMIT; goto cleanup; } //fwrite(buf, bytes_read, 1,out); } else { /* skip the header */ #ifdef LIB_W5300 buf[bytes_read] = '\0'; #else char *raw_header1 = NULL; buf[bytes_read] = '\0'; raw_header1 = get_raw_header(sock); strconcat2(buf, raw_header1, NULL); FREE(raw_header1); LIBNET_DEBUG("receive respond:(%d)\n%s", bytes_read, buf); #endif header = make_http_header(buf); /* check for redirects */ tmp_string = get_header_value("location", header); if (buf[9] == '3' && tmp_string ) { #if 1 //diable redirec function redir_u = url_new(); /* make sure we still send user/password along */ redir_u->username = safe_strdup(u->username); redir_u->password = safe_strdup(u->password); url_init(redir_u, tmp_string); rsrc->url = redir_u; redirect_count++; //retval = transfer(rsrc, notify); transfer((UINT32)rsrc, (UINT32)notify); rsrc->url =u; redirect_count--; if(redirect_count<0) redirect_count=0; if (redir_u) { url_destroy(redir_u); FREE(redir_u); } #endif FREE(tmp_string); tmp_string = NULL; //msg_code = -NET_ERR_OPERATION_NOT_PERMIT;//we can support redirect now, remove this line. goto cleanup; } if (tmp_string) { FREE(tmp_string); tmp_string = NULL; } if (buf[9] == '4' || buf[9] == '5') { for (i = 0; buf[i] && buf[i] != '\n'; i++); buf[i] = '\0'; LIBNET_DEBUG("HTTP error from server: %s\n", buf); if( buf[9] == '4' && buf[10] == '0' && buf[11] == '4') msg_code = -NET_ERR_FILE_NOT_FOUND; else msg_code = -NET_ERR_HTTP_SERVER_ERROR; goto cleanup; } tmp_string = get_header_value("content-length", header); if (tmp_string) { rsrc->outfile_size = (off_t )ATOI(tmp_string); FREE(tmp_string); tmp_string = NULL; if(rsrc->use_pecache ==0) { if ((rsrc->buffer) && (rsrc->buffer_len < rsrc->outfile_size)) { LIBNET_DEBUG("the buffer length less than the file fize (%d < %d)\n", rsrc->buffer, (int)rsrc->outfile_size); msg_code = -NET_ERR_FILE_SAVE_ERROR; goto cleanup; } } } tmp_string = get_header_value("content-range", header); if (tmp_string) { FREE(tmp_string); tmp_string = NULL; rsrc->outfile_size += rsrc->outfile_offset; } if ((!rsrc->outfile_size) && (rsrc->options & OPT_RESUME) && !(rsrc->options & OPT_NORESUME) && rsrc->outfile_offset ) { LIBNET_DEBUG("unable to determine remote file size"); msg_code = -NET_ERR_FILE_SAVE_ERROR; goto cleanup; } } if(rsrc->use_pecache ==0) retval = dump_data(rsrc, sock, out, notify); else retval = dump_data_to_pecache(rsrc, sock, out, notify); cleanup: free_http_header(header); //if (raw_header) // FREE(raw_header); if (proxy_url) { url_destroy(proxy_url); FREE(proxy_url); } if (sock >= 0) { S_CLOSE(sock); } if (out) fclose(out); if (buf) { FREE(buf); } #ifndef WIN32 if (rsrc->outfile) fs_sync(rsrc->outfile); #endif if (msg_code < 0 && rsrc->running) { notify(NET_MSG_DOWNLOAD_FINISH, (UINT32)msg_code); libnet_abort_url_read(TRUE);//to break url_open while loop //retval!=1 means transfer fail } return retval; }