Beispiel #1
0
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;

}
Beispiel #2
0
void *network(void *args){
	int len=-1, send=0, n;
	char buffer[BUF_SIZE] = {0,};
	char* http_header; 
	//my new variable
	int point_url1=0, point_url2=0,pathname_len=-1,pathname_type_point1=0,pathname_type_point2=0;
	int status_code=0,content_type=0, content_length=0, out_fd=-1;
	struct stat st;
	char input_url[MAXLINE], pathname[MAXLINE];
	char pathname_type[5];
	char default_msg[] = "loading failed", default_pathname[]="index.html";

	int connfd = *( (int *)args );
	pthread_detach(pthread_self());
	free(args);
	
	char *home_dir=getenv("HOME_DIR");
	// read client request into buffer until there is '\r\n\r\n'
	do {
		n = read(connfd, buffer + send, 1024);
		send += n;
		if (buffer[send-4] == '\r' && buffer[send-3] == '\n' &&
		buffer[send-2] == '\r' && buffer[send-1] == '\n')
			break;
	} while (send <= 1024);
/////////////////////////////doing client request below///////////////////////////
	//separate path from request
	if( (point_url1 = myfindchar(buffer, 0, ' ')) ){
		point_url2 = myfindchar(buffer, point_url1, ' ');
		mystrncpy(input_url, (buffer+point_url1+1), (point_url2-point_url1-1));
	}
	if (!home_dir)
	{
		mystrcpy(pathname, input_url);
	}
	else{
		mystrcpy(pathname, home_dir);
		mystrcat(pathname, input_url);
	}
	//find content_type of pathname
	if( (input_url[0]=='/') && (input_url[1]=='\0') ){
		mystrcat(pathname, default_pathname);
	}
	
//	pathname_len = mystrlen(pathname);
	while(pathname[++pathname_len]);
	pathname_type_point1 = (myfindchar2(pathname, pathname_len, '.'));
	pathname_type_point2 = (myfindchar2(pathname, pathname_len, '/'));
	if( pathname_type_point1 > pathname_type_point2) {	//Normal position
		mystrcpy(pathname_type, (pathname + pathname_type_point1 + 1) );
		content_type = myfindtype(pathname_type);
		if( content_type == TYPE_UNKNOWN){
			status_code = ERR_NOT_ALLOWED;
			content_length = 14;	
		}	
		else{
		//find status_code of pathname
		if( (out_fd = open(pathname, O_RDONLY) ) < 0){		//error status
			//if(errno == ENOENT){
				status_code = (ERR_NO_FILE);
			//}
			if(errno == EACCES){
				status_code = (ERR_NOT_ALLOWED);
			}
			content_type = TYPE_UNKNOWN;
			content_length = 14;	//content_length of pathname in error status
							
		}
		//find content_length of pathname in normal status
		else{		//normal status
			status_code = (NO_ERR);
			stat(pathname, &st);	
			content_length = st.st_size;
			if( content_type == TYPE_UNKNOWN){
				status_code = ERR_NOT_ALLOWED;
				content_length = 14;
			}
		}
		
		}
	}
	else{
		content_type = TYPE_UNKNOWN;
		status_code = ERR_NOT_ALLOWED;
		content_length = 14;	
	}		

///////////////////////////////// sending <HTTP body>:////////////////////////
/////////////////////////////////////NORMAL///////////////////////////////
		http_header = make_http_header(status_code, content_type, content_length);	
		while(http_header[++len]); // length of http_header	
		send = 0;
		do {
			send += write(connfd, http_header + send, len - send);
		} while (send < len); // until write is done
		if((status_code == NO_ERR) && (content_type != TYPE_UNKNOWN ) ){	//"Normal"
			while( (n= read(out_fd, buffer, BUF_SIZE) ) >0){
				send =0;
				do{
					send += write(connfd, buffer+send, n-send);
				}while(send<n);
			}
		}
//////////////////////////////////////loading failed/////////////////////////
		else{		// "loading failed"
			send = 0;
			do {
				send += write(connfd, default_msg + send, content_length - send);
			} while (send < content_length);
		}
/////////////////////////////update_data/////////////////////////////////
	free(http_header);
	close(out_fd);
	close(connfd);
	return 0;
}
Beispiel #3
0
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;

}