⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 httpdav.c

📁 站点映像程序
💻 C
📖 第 1 页 / 共 5 页
字号:
		break;	    case 1: /* we got us a response! */		DEBUG( DEBUG_HTTP, "Wait got data.\n" );		http_expect_works = 1; /* it works - use it again */		break;	    case 0: 		/* Timed out - i.e. Expect: ignored. There is a danger		 * here that the server DOES respect the Expect: header,		 * but was going SO slowly that it didn't get time to		 * respond within HTTP_EXPECT_TIMEOUT.		 * TODO: while sending the body, check to see if the		 * server has sent anything back - if it HAS, then		 * stop sending - this is a spec compliance SHOULD */		DEBUG( DEBUG_HTTP, "Wait timed out.\n" );		http_expect_works = -1; /* don't try that again */		/* and give them the body */		if( http_req_sendbody( req ) != PROTO_OK )		    HTTP_FATAL_ERROR( "Could not send body.\n" );		break;	    }	} else if( req->body != http_body_none ) {#ifdef USE_BROKEN_PROPFIND	    if( is_propfind ) {		char *pfbuf;		DEBUG( DEBUG_HTTP, "Broken PROPFIND handler...\n" );		pfbuf = malloc( strlen(request) + req->body_size + 1 );		memset( pfbuf, 0, strlen(request) + req->body_size + 1 );		strcpy( pfbuf, request );		strcat( pfbuf, req->body_buffer );		DEBUG( DEBUG_HTTP, "Sending PROPFIND request...\n" );		if( send_string( http_sock, pfbuf ) < 0 ) {		    HTTP_FATAL_ERROR( "Could not send request.\n" );		}		DEBUG( DEBUG_HTTP, "Sending newline.\n" );		if( send_line( http_sock, "" ) < 0 ) {		    HTTP_FATAL_ERROR( "Could not send newline.\n" );		}		free( pfbuf );	    } else {		#endif /* USE_BROKEN_PROPFIND */	    /* Just chuck the file down the socket */	    DEBUG( DEBUG_HTTP, "Sending body...\n" );	    if( http_req_sendbody( req ) == PROTO_ERROR )		HTTP_FATAL_ERROR( "Could not send body.\n" );	    /* FIXME: This. Should it be here? */	    DEBUG( DEBUG_HTTP, "Sending newline.\n" );	    if( send_line( http_sock, "" ) < 0 ) {		HTTP_FATAL_ERROR( "Could not send newline.\n" );	    }	    DEBUG( DEBUG_HTTP, "Body sent.\n" );#ifdef USE_BROKEN_PROPFIND	    }#endif /* USE_BROKEN_PROPFIND */	}		/* Now, we have either:	 *   - Sent the header and body, or	 *   - Sent the header incl. Expect: line, and got some response.	 * In any case, we get the status line of the response.	 */		/* HTTP/1.1 says we MUST be able to accept any number of	 * 100 (Continue) responses prior to the normal response.	 * So loop while we get them.	 */		do {	    if( read_line( http_sock, buffer, BUFSIZ ) < 0 ) {		dead_connection = true;		HTTP_FATAL_ERROR( "Could not read status line.\n" );	    }	    	    DEBUG( DEBUG_HTTP, "[Status Line] < %s", buffer );	    	    /* Got the status line - parse it */	    if( http_parse_status( req, buffer ) == PROTO_ERROR )		HTTP_FATAL_ERROR( "Could not parse status line.\n" );	    if( req->class == 1 ) {		DEBUG( DEBUG_HTTP, "Got 1xx-class.\n" );		/* Skip any headers, we don't need them */		do {		    if( read_line( http_sock, buffer, BUFSIZ ) < 0 )			HTTP_FATAL_ERROR( "Could not read header.\n" );		    DEBUG( DEBUG_HTTP, "[Ignored header] < %s", buffer );		} while( strcmp( buffer, EOL ) != 0 );			if( using_expect && (req->status == 100) ) {		    /* We are using Expect: 100, and we got a 100-continue 		     * return code... send the request body */		    DEBUG( DEBUG_HTTP, "Got continue... sending body now.\n" );		    if( http_req_sendbody( req ) != PROTO_OK )			HTTP_FATAL_ERROR( "Could not send body.\n" );		    DEBUG( DEBUG_HTTP, "Body sent.\n" );		}	    }	} while( req->class == 1 );		/* We've got the real status line... now get the headers */		req->resp_length = -1;	req->resp_te = http_te_unknown;	close_connection = false;		/* Now read the rest of the header... up to the next blank line */	while( read_line( http_sock, buffer, BUFSIZ ) > 0 ) {	    char extra[BUFSIZ], *pnt;	    DEBUG( DEBUG_HTTP, "[Header:%d] < %s", strlen(buffer), buffer );	    if( strcmp( buffer, EOL ) == 0 ) {		DEBUG( DEBUG_HTTP, "CRLF: End of headers.\n" );		break;	    }	    while(true) {		/* Collect any extra lines into buffer */		ret = sock_recv( http_sock, extra, 1, MSG_PEEK);		if( ret <= 0 ) {		    HTTP_FATAL_ERROR( "Couldn't peek at next line.\n" );		}		if( extra[0] != ' ' && extra[0] != '\t' ) {		    /* No more headers */		    break;		}		ret = read_line( http_sock, extra, BUFSIZ );		if( ret == -2 ) {		    /* No newline within BUFSIZ bytes. This is a 		     * loooong header. */		    DEBUG( DEBUG_HTTP, 			   "Header line longer than buffer, skipped.\n" );		    break;		} else if( ret <= 0 ) { 		    HTTP_FATAL_ERROR( "Couldn't read next header line.\n" );		} else {		    DEBUG( DEBUG_HTTP, "[Cont:%d] < %s", strlen(extra), extra);		}		/* Append a space to the end of the last header, in		 * place of the CRLF. */		pnt = strchr( buffer, '\r' );		pnt[0] = ' '; pnt[1] = '\0';		/* Skip leading whitespace off next line */		for( pnt = extra; *pnt!='\0' && 			 ( *pnt == ' ' || *pnt =='\t' ); pnt++ ) /*oneliner*/;		DEBUG( DEBUG_HTTP, "[Continued] < %s", pnt );		if( strlen(buffer) + strlen(pnt) >= BUFSIZ ) {		    DEBUG( DEBUG_HTTP, "Exceeded header buffer space.\n" );		    /* Note, we don't break out of the loop here, cos		     * we need to collect all the continued lines */		} else {		    strcat( buffer, pnt );		}	    }	    /* Now parse the header line. This is all a bit noddy. */	    pnt = strchr( buffer, ':' );	    if( pnt != NULL ) {		char *name, *value, *part;		/* Null-term name at the : */		*pnt = '\0';		name = buffer;		/* Strip leading whitespace from the value */				for( value = pnt+1; *value!='\0' && *value==' '; value++ )		    /* nullop */;		if( (part = strchr( value, '\r' )) != NULL ) 		    *part = '\0';		if( (part = strchr( value, '\n' )) != NULL ) 		    *part = '\0';		DEBUG( DEBUG_HTTP, "Header Name: [%s], Value: [%s]\n",		       name, value );		if( strcasecmp( name, "Content-Length" ) == 0 ) {		    /* TODO: 2068 says we MUST notify the user if this		     * is not a real number. */		    req->resp_length = atoi( value );		} else if( strcasecmp( name, "Transfer-Encoding" ) == 0 ) {		    if( strcasecmp( value, "chunked" ) == 0 ) {			req->resp_te = http_te_chunked;		    } else {			req->resp_te = http_te_unknown;		    }		} else if( strcasecmp( name, "Connection" ) == 0 ) {		    if( strcasecmp( value, "close" ) == 0 ) {			close_connection = true;		    }		} else if( strcasecmp( name, "WWW-Authenticate" ) == 0 ) {		    /* Parse the authentication challenge */		    http_can_authenticate = 			http_auth_challenge( &http_server_auth, value );		} else if( strcasecmp( name, "Authentication-Info" ) == 0 ) {		    /* Remember on the authentication reponse */		    authinfo = strdup( value );		} else if( req->hdrs_callback != NULL ) {		    (*req->hdrs_callback)( name, value );		}	    }	}	/* Body length calculation, bit icky.	 * Here, we set:	 * length==-1 if we DO NOT know the exact body length	 * length>=0 if we DO know the body length.	 *	 * RFC2068, section 4.3: 	 * NO body is returned if the method is HEAD, or the resp status	 * is 204 or 304	 */	if( (strcmp( req->method, "HEAD" ) == 0 ) ||	    req->status==204 ||	    req->status==304 ) {	    req->resp_length = 0;	} else {	    /* RFC2068, section 4.4: if we have a transfer encoding	     * and a content-length, then ignore the content-length. */	    if( (req->resp_length>-1) && 		(req->resp_te!=http_te_unknown) ) {		req->resp_length = -1;	    }	}	/* The caller only wants the body if this request	 * was 2xx class. */	/* FIXME: Let the caller decide when they want it*/	wants_body = (req->class == 2);	if( req->resp_length != 0 ) {	    /* Now, read the body */	    int readlen;	    req->resp_left = req->resp_length;	    req->resp_chunk_left = 0;	    do {		/* Read a block */		readlen = http_response_read( req, buffer, BUFSIZ );		DEBUG( DEBUG_HTTP, "Read %d bytes.\n", readlen );		if( readlen > -1 ) {		    /* What to do with the body block */		    if( req->body_callback && wants_body ) 			(*req->body_callback)( req->body_callback_userdata,					       buffer, readlen );		    http_auth_response_body( &http_server_auth, 					     buffer, readlen );		}	    } while( readlen > 0 );	    if( readlen < 0 ) {		HTTP_FATAL_ERROR( "Block read error.\n" );	    } else if( (readlen == 0) && (req->resp_te == http_te_chunked) ) {		char *pnt;		/* Read till CRLF - skip trailing headers */		do {		    if( read_line( http_sock, buffer, BUFSIZ ) < 0 ) {			/* It broke */			HTTP_FATAL_ERROR( "Could not read trailer.\n" );		    }		    DEBUG( DEBUG_HTTP, "[Chunk trailer] %s", buffer );		    /* Now parse the header line. */		    pnt = strchr( buffer, ':' );		    if( pnt != NULL ) {			char *name, *value, *part;			/* Null-term name at the : */			*pnt = '\0';			name = buffer;			/* Strip leading whitespace from the value */ 			for( value = pnt+1; 			     *value!='\0' && *value==' '; value++ )			    /* nullop */;			if( (part = strchr( value, '\r' )) != NULL ) 			    *part = '\0';			if( (part = strchr( value, '\n' )) != NULL ) 			    *part = '\0';			DEBUG( DEBUG_HTTP, "Header Name: [%s], Value: [%s]\n",			       name, value );			if( strcasecmp( name, "Authentication-Info" ) == 0 ) {			    /* Save the authinfo value */			    if( authinfo == NULL ) {				authinfo = strdup( value );			    } else {				DEBUG( DEBUG_HTTP, "Recieved TWO auth-info headers... ignoring second.\n" );			    }			}		    }		} while( strcmp( buffer, EOL ) != 0 );	    }	}	/* Now, if we are doing authentication, check the	 * server's credentials. */	if( http_can_authenticate && (authinfo != NULL) ) {	    if( http_auth_verify_response( &http_server_auth, authinfo ) ) {		ret = PROTO_OK;		DEBUG( DEBUG_HTTP, "Response authenticated okay.\n" );	    } else {		DEBUG( DEBUG_HTTP, "Reponse authenticated as invalid.\n" );		ret = PROTO_ERROR;		sprintf( http_error,"Server was not authenticated correctly.");	    }	} else {	    ret = PROTO_OK;	}	DOFREE( authinfo );    http_request_finish_proc:	/* Now, do we close the connection? */	if( close_connection ) {	    DEBUG( DEBUG_HTTP, "Forced connection close.\n" );	    http_close( );	} else if( http_conn_limit ) {	    DEBUG( DEBUG_HTTP, "Limited connection close.\n" );	    http_close( );	}	        	/* Now, do that all *again* if it didn't work.	 * Otherwise, give up */    } while( (dead_connection && (++con_attempt<4)) || ((++attempt<3) && http_can_authenticate && (req->status == 401) ));    DEBUG( DEBUG_HTTP, "Req ends, status %d class %dxx, status line:\n%s\n", 	   req->status, req->class, http_error );    return ret;}/* Simple HTTP put.  * local is the local filename. Remote is the destination URI (URI?) * Make it proper. * Returns: *   PROTO_FILE if no local file *   PROTO_ERROR if something general goes wrong *   PROTO_OK if it all works fine */int http_put( const char *local, const char *remote, const bool ascii ) {    http_req_t req;    int ret;        http_request_init( &req, "PUT", remote );    /* joe: ANSI C says the "b" will be ignored by platforms which     * should ignore it... but, we'll play safe: */#if defined (__EMX__) || defined(__CYGWIN__)    req.body_file = fopen( local, "rb" );#else    req.body_file = fopen( local, "r" );#endif    if( req.body_file == NULL ) {	strcpy( http_error, "Could not open file." );	ret = PROTO_FILE;    } else {	req.body = http_body_file;		ret = http_request( &req );	fclose( req.body_file );		if( ret == PROTO_OK && req.class != 2 )	    ret = PROTO_ERROR;    }    http_request_end( &req );    return ret;}int http_get_fd;bool http_get_working;size_t http_get_total, http_get_progress;void http_get_callback( void *user, const char *buffer, const size_t len ) {    if( !http_get_working ) return;    DEBUG( DEBUG_HTTP, "Got progress: %d out of %d\n", len, http_get_total );    if( send_data( http_get_fd, buffer, len ) < 0 ) {	http_get_working = false;    } else {	http_get_progress += len;	fe_transfer_progress( http_get_progress, http_get_total );     }}int http_get( const char *local, const char *remote, const int remotesize,	      const bool ascii ) {    http_req_t req;    int ret;#if defined (__EMX__) || defined (__CYGWIN__)    /* We have to set O_BINARY, thus need open(). Otherwise it should be       equivalent to creat(). */    http_get_fd = open( local, O_WRONLY|O_TRUNC|O_CREAT|O_BINARY, 0644 );#else    http_get_fd = creat( local, 0644 );#endif    if( http_get_fd < 0 ) {	snprintf( http_error, BUFSIZ, "Could not open local file: %s", 		  strerror( errno ) );	return PROTO_ERROR;    }    http_request_init( &req, "GET", remote );    req.body_callback = http_get_callback;    http_get_working = true;    http_get_progress = 0;    http_get_total = remotesize;    DEBUG( DEBUG_HTTP, "Total remote size: %d\n", remotesize );    ret = http_request( &req );        if( close( http_get_fd ) < 0 ) {	snprintf( http_error, BUFSIZ, "Error closing local file: %s",		  strerror( errno ) );	ret = PROTO_ERROR;    } else if( ret == PROTO_OK && req.class != 2 ) {	ret = PROTO_ERROR;    }    http_request_end( &req );    return ret;}/* Perform the file operations */int dav_move( const char *from, const char *to ) {    http_req_t req;    int ret;    http_request_init( &req, "MOVE", from );    strcat( req.headers, "Destination: http://" );    http_strcat_hostname( &http_server_host, req.headers );    strcat( req.headers, to );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -