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

📄 webserver.c

📁 电驴下载工具eMule0.47aVeryCD的源代码,可作分析测试也可用于P2P软件的开发研究.
💻 C
📖 第 1 页 / 共 4 页
字号:
StrTok( char **Src,
        char *Del )
{
    char *TmpPtr,
     *RetPtr;

    if( *Src != NULL ) {
        RetPtr = *Src;
        TmpPtr = strstr( *Src, Del );
        if( TmpPtr != NULL ) {
            *TmpPtr = '\0';
            *Src = TmpPtr + strlen( Del );
        } else
            *Src = NULL;

        return RetPtr;
    }

    return NULL;
}

/************************************************************************
* Function: GetNextRange												
*																		
* Parameters:															
*	IN char ** SrcRangeStr ; string containing the token / range										
*	OUT int * FirstByte ;	 gets the first byte of the token												
*	OUT int * LastByte	; gets the last byte of the token												
*																		
* Description: Returns a range of integers from a sring					
*																		
* Returns: int	;
*	always returns 1;				
************************************************************************/
int
GetNextRange( char **SrcRangeStr,
              int *FirstByte,
              int *LastByte )
{
    char *Ptr,
     *Tok;
    int i,
      F = -1,
      L = -1;
    int Is_Suffix_byte_Range = 1;

    if( *SrcRangeStr == NULL )
        return -1;

    Tok = StrTok( SrcRangeStr, "," );

    if( ( Ptr = strstr( Tok, "-" ) ) == NULL )
        return -1;
    *Ptr = ' ';
    sscanf( Tok, "%d%d", &F, &L );

    if( F == -1 || L == -1 ) {
        *Ptr = '-';
        for( i = 0; i < ( int )strlen( Tok ); i++ ) {
            if( Tok[i] == '-' ) {
                break;
            } else if( isdigit( Tok[i] ) ) {
                Is_Suffix_byte_Range = 0;
                break;
            }

        }

        if( Is_Suffix_byte_Range ) {
            *FirstByte = L;
            *LastByte = F;
            return 1;
        }
    }

    *FirstByte = F;
    *LastByte = L;
    return 1;

}

/************************************************************************
* Function: CreateHTTPRangeResponseHeader								
*																		
* Parameters:															
*	char * ByteRangeSpecifier ; String containing the range 	
*	long FileLength ; Length of the file													
*	OUT struct SendInstruction * Instr ; SendInstruction object	where the 
*										range operations will be stored
*																		
* Description: Fills in the Offset, read size and contents to send out	
*	as an HTTP Range Response											
*																		
* Returns:																
*	HTTP_BAD_REQUEST													
*	UPNP_E_OUTOF_MEMORY													
*	HTTP_REQUEST_RANGE_NOT_SATISFIABLE									
*	HTTP_OK																
************************************************************************/
int
CreateHTTPRangeResponseHeader( char *ByteRangeSpecifier,
                               long FileLength,
                               OUT struct SendInstruction *Instr )
{

    int FirstByte,
      LastByte;
    char *RangeInput,
     *Ptr;

    Instr->IsRangeActive = 1;
    Instr->ReadSendSize = FileLength;

    if( !ByteRangeSpecifier )
        return HTTP_BAD_REQUEST;

    RangeInput = malloc( strlen( ByteRangeSpecifier ) + 1 );
    if( !RangeInput )
        return UPNP_E_OUTOF_MEMORY;
    strcpy( RangeInput, ByteRangeSpecifier );

    //CONTENT-RANGE: bytes 222-3333/4000  HTTP_PARTIAL_CONTENT
    if( StrStr( RangeInput, "bytes" ) == NULL ||
        ( Ptr = StrStr( RangeInput, "=" ) ) == NULL ) {
        free( RangeInput );
        Instr->IsRangeActive = 0;
        return HTTP_BAD_REQUEST;
    }
    //Jump =
    Ptr = Ptr + 1;

    if( FileLength < 0 ) {
        free( RangeInput );
        return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
    }

    if( GetNextRange( &Ptr, &FirstByte, &LastByte ) != -1 ) {

        if( FileLength < FirstByte ) {
            free( RangeInput );
            return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
        }

        if( FirstByte >= 0 && LastByte >= 0 && LastByte >= FirstByte ) {
            if( LastByte >= FileLength )
                LastByte = FileLength - 1;

            Instr->RangeOffset = FirstByte;
            Instr->ReadSendSize = LastByte - FirstByte + 1;
            sprintf( Instr->RangeHeader, "CONTENT-RANGE: bytes %d-%d/%ld\r\n", FirstByte, LastByte, FileLength );   //Data between two range.
        } else if( FirstByte >= 0 && LastByte == -1
                   && FirstByte < FileLength ) {
            Instr->RangeOffset = FirstByte;
            Instr->ReadSendSize = FileLength - FirstByte;
            sprintf( Instr->RangeHeader,
                     "CONTENT-RANGE: bytes %d-%ld/%ld\r\n", FirstByte,
                     FileLength - 1, FileLength );
        } else if( FirstByte == -1 && LastByte > 0 ) {
            if( LastByte >= FileLength ) {
                Instr->RangeOffset = 0;
                Instr->ReadSendSize = FileLength;
                sprintf( Instr->RangeHeader,
                         "CONTENT-RANGE: bytes 0-%ld/%ld\r\n",
                         FileLength - 1, FileLength );
            } else {
                Instr->RangeOffset = FileLength - LastByte;
                Instr->ReadSendSize = LastByte;
                sprintf( Instr->RangeHeader,
                         "CONTENT-RANGE: bytes %ld-%ld/%ld\r\n",
                         FileLength - LastByte + 1, FileLength,
                         FileLength );
            }
        } else {
            free( RangeInput );
            return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
        }
    } else {
        free( RangeInput );
        return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
    }

    free( RangeInput );
    return HTTP_OK;
}

/************************************************************************
* Function: CheckOtherHTTPHeaders										
*																		
* Parameters:															
*	IN http_message_t * Req ;  HTTP Request message
*	OUT struct SendInstruction * RespInstr ; Send Instruction object to 
*							data for the response
*	int FileSize ;	Size of the file containing the request document
*																		
* Description: Get header id from the request parameter and take		
*	appropriate action based on the ids.								
*	as an HTTP Range Response											
*																		
* Returns:																
*	HTTP_BAD_REQUEST													
*	UPNP_E_OUTOF_MEMORY													
*	HTTP_REQUEST_RANGE_NOT_SATISFIABLE									
*	HTTP_OK																
************************************************************************/
int
CheckOtherHTTPHeaders( IN http_message_t * Req,
                       OUT struct SendInstruction *RespInstr,
                       int FileSize )
{
    http_header_t *header;
    ListNode *node;

    //NNS: dlist_node* node;
    int index,
      RetCode = HTTP_OK;
    char *TmpBuf;

    TmpBuf = ( char * )malloc( LINE_SIZE );
    if( !TmpBuf )
        return UPNP_E_OUTOF_MEMORY;

    node = ListHead( &Req->headers );

    while( node != NULL ) {
        header = ( http_header_t * ) node->item;

        // find header type.
        index = map_str_to_int( ( const char * )header->name.buf,
                                header->name.length, Http_Header_Names,
                                NUM_HTTP_HEADER_NAMES, FALSE );

        if( header->value.length >= LINE_SIZE ) {
            free( TmpBuf );
            TmpBuf = ( char * )malloc( header->value.length + 1 );
            if( !TmpBuf )
                return UPNP_E_OUTOF_MEMORY;
        }

        memcpy( TmpBuf, header->value.buf, header->value.length );
        TmpBuf[header->value.length] = '\0';
        if( index >= 0 )
            switch ( Http_Header_Names[index].id ) {
                case HDR_TE:   //Request
                    {
                        RespInstr->IsChunkActive = 1;

                        if( strlen( TmpBuf ) > strlen( "gzip" ) ) {
                            if( StrStr( TmpBuf, "trailers" ) != NULL ) {    //means client will accept trailer
                                RespInstr->IsTrailers = 1;
                            }
                        }
                    }
                    break;

                case HDR_CONTENT_LENGTH:
                    {
                        RespInstr->RecvWriteSize = atoi( TmpBuf );
                        break;
                    }

                case HDR_RANGE:
                    if( ( RetCode = CreateHTTPRangeResponseHeader( TmpBuf,
                                                                   FileSize,
                                                                   RespInstr ) )
                        != HTTP_OK ) {
                        free( TmpBuf );
                        return RetCode;
                    }
                    break;
                default:
                    /*
                       TODO 
                     */
                    /*
                       header.value is the value. 
                     */
                    /*
                       case HDR_CONTENT_TYPE: //return 1;
                       case HDR_CONTENT_LANGUAGE://return 1;
                       case HDR_LOCATION: //return 1;
                       case HDR_CONTENT_LOCATION://return 1;
                       case HDR_ACCEPT: //return 1;
                       case HDR_ACCEPT_CHARSET://return 1;
                       case HDR_ACCEPT_LANGUAGE://return 1;
                       case HDR_USER_AGENT: break;//return 1;
                     */

                    //Header check for encoding 
                    /*
                       case HDR_ACCEPT_RANGE: //Server capability.
                       case HDR_CONTENT_RANGE://Response.
                       case HDR_IF_RANGE:
                     */

                    //Header check for encoding 
                    /*
                       case HDR_ACCEPT_ENCODING:
                       if(StrStr(TmpBuf, "identity"))
                       {
                       break;
                       }
                       else return -1;
                       case HDR_CONTENT_ENCODING:
                       case HDR_TRANSFER_ENCODING: //Response
                     */
                    break;
            }

        node = ListNext( &Req->headers, node );

    }

    free( TmpBuf );
    return RetCode;
}

/************************************************************************
* Function: process_request												
*																		
* Parameters:															
*	IN http_message_t *req ; HTTP Request message												
*	OUT enum resp_type *rtype ; Tpye of response											
*	OUT membuffer *headers ; 												
*	OUT membuffer *filename ; Get filename from request document
*	OUT struct xml_alias_t *alias ; Xml alias document from the 
*									request document,										
*	OUT struct SendInstruction * RespInstr ; Send Instruction object 
*					where the response is set up.										
*																		
* Description: Processes the request and returns the result in the OUT	
*	parameters															
*																		
* Returns:																
*	HTTP_BAD_REQUEST													
*	UPNP_E_OUTOF_MEMORY													
*	HTTP_REQUEST_RANGE_NOT_SATISFIABLE									
*	HTTP_OK																
************************************************************************/
static int
process_request( IN http_message_t * req,
                 OUT enum resp_type *rtype,
                 OUT membuffer * headers,
                 OUT membuffer * filename,
                 OUT struct xml_alias_t *alias,
                 OUT struct SendInstruction *RespInstr )
{
    int code;
    int err_code;

    //membuffer content_type;
    char *request_doc;
    struct File_Info finfo;
    xboolean using_alias;
    xboolean using_virtual_dir;
    uri_type *url;
    char *temp_str;
    int resp_major,
      resp_minor;
    xboolean alias_grabbed;
    int dummy;
    struct UpnpVirtualDirCallbacks *pVirtualDirCallback;

    print_http_headers( req );

    url = &req->uri;
    assert( req->method == HTTPMETHOD_GET ||
            req->method == HTTPMETHOD_HEAD
            || req->method == HTTPMETHOD_POST
            || req->method == HTTPMETHOD_SIMPLEGET );

    // init
    request_doc = NULL;
    finfo.content_type = NULL;
    //membuffer_init( &content_type );
    alias_grabbed = FALSE;
    err_code = HTTP_INTERNAL_SERVER_ERROR;  // default error
    using_virtual_dir = FALSE;
    using_alias = FALSE;

    http_CalcResponseVersion( req->major_version, req->minor_version,
                              &resp_major, &resp_minor );

    //
    // remove dots
    //
    request_doc = malloc( url->pathquery.size + 1 );
    if( request_doc == NULL ) {
        goto error_handler;     // out of mem
    }
    memcpy( request_doc, url->pathquery.buff, url->pathquery.size );
    request_doc[url->pathquery.size] = '\0';
    dummy = url->pathquery.size;
    remove_escaped_chars( request_doc, &dummy );
    code = remove_dots( request_doc, url->pathquery.size );
    if( code != 0 ) {
        err_code = HTTP_FORBIDDEN;
        goto error_handler;
    }

    if( *request_doc != '/' ) {
        // no slash
        err_code = HTTP_BAD_REQUEST;
        goto error_handler;
    }


    if( isFileInVirtualDir( request_doc ) ) {
        using_virtual_dir = TRUE;
        RespInstr->IsVirtualFile = 1;
        if( membuffer_assign_str( filename, request_doc ) != 0 ) {
            goto error_handler;
        }

    } else {
        //
        // try using alias
        //
#ifdef _ALIASDOC
        if( is_valid_alias( &gAliasDoc ) ) {
            alias_grab( alias );
            alias_grabbed = TRUE;

            using_alias = get_alias( request_doc, alias, &finfo );
#else
            using_alias = getAliasFromDict( request_doc, alias, &finfo );
#endif
            if( using_alias == TRUE ) {
		alias_grabbed = TRUE;
                finfo.content_type = ixmlCloneDOMString( "text/xml" );

                if( finfo.content_type == NULL ) {
                    goto error_handler;
                }
            }
#ifdef _ALIASDOC
        }
#endif
    }

    if( using_virtual_dir ) {
        if( req->method != HTTPMETHOD_POST ) {
            // get file info
            pVirtualDirCallback = &virtualDirCallback;
            if( pVirtualDirCallback->get_info( filename->buf, &finfo ) !=
                0 ) {
                err_code = HTTP_NOT_FOUND;
                goto error_handler;
            }
            // try index.html if req is a dir
            if( finfo.is_directory ) {
                if( filename->buf[filename->length - 1] == '/' ) {
                    temp_str = "index.html";
                } else {
                    temp_str = "/index.html";
                }
                if( membuffer_append_str( filename, temp_str ) != 0 ) {
                    goto error_handler;
                }
                // get info

⌨️ 快捷键说明

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