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

📄 webserver.c

📁 电驴下载工具eMule0.47aVeryCD的源代码,可作分析测试也可用于P2P软件的开发研究.
💻 C
📖 第 1 页 / 共 4 页
字号:
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2003 Intel Corporation 
// All rights reserved. 
//
// Redistribution and use in source and binary forms, with or without 
// modification, are permitted provided that the following conditions are met: 
//
// * Redistributions of source code must retain the above copyright notice, 
// this list of conditions and the following disclaimer. 
// * Redistributions in binary form must reproduce the above copyright notice, 
// this list of conditions and the following disclaimer in the documentation 
// and/or other materials provided with the distribution. 
// * Neither name of Intel Corporation nor the names of its contributors 
// may be used to endorse or promote products derived from this software 
// without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR 
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////

/************************************************************************
* Purpose: This file defines the Web Server and has functions to carry out 
* operations of the Web Server.										
************************************************************************/

#include <assert.h>
#include "util.h"
#include "strintmap.h"
#include "membuffer.h"
#include "httpparser.h"
#include "httpreadwrite.h"
#include "statcodes.h"
#include "webserver.h"
#include "upnp.h"
#include "config.h"
#include "upnpapi.h"

#ifndef _WIN32
#include <unistd.h>
#endif
#include <sys/stat.h>
#include "ithread.h"
#include "unixutil.h"

/*
   Response Types 
 */
enum resp_type { RESP_FILEDOC, RESP_XMLDOC, RESP_HEADERS, RESP_WEBDOC,
        RESP_POST };

// mapping of file extension to content-type of document
struct document_type_t {
    const char *file_ext;
    const char *content_type;
    const char *content_subtype;
};

struct xml_alias_t {
    membuffer name;             // name of DOC from root; e.g.: /foo/bar/mydesc.xml
    membuffer doc;              // the XML document contents
    time_t last_modified;
    int *ct;
};

static const char *gMediaTypes[] = {
    NULL,                       // 0
    "audio",                    // 1
    "video",                    // 2
    "image",                    // 3
    "application",              // 4
    "text"                      // 5
};

/*
   Defines 
 */

// index into 'gMediaTypes'
#define AUDIO_STR		"\1"
#define VIDEO_STR		"\2"
#define IMAGE_STR		"\3"
#define APPLICATION_STR "\4"
#define TEXT_STR		"\5"

// int index
#define APPLICATION_INDEX	4
#define TEXT_INDEX			5

// general
#define NUM_MEDIA_TYPES 69
#define NUM_HTTP_HEADER_NAMES 33

// sorted by file extension; must have 'NUM_MEDIA_TYPES' extensions
static const char *gEncodedMediaTypes =
    "aif\0" AUDIO_STR "aiff\0"
    "aifc\0" AUDIO_STR "aiff\0"
    "aiff\0" AUDIO_STR "aiff\0"
    "asf\0" VIDEO_STR "x-ms-asf\0"
    "asx\0" VIDEO_STR "x-ms-asf\0"
    "au\0" AUDIO_STR "basic\0"
    "avi\0" VIDEO_STR "msvideo\0"
    "bmp\0" IMAGE_STR "bmp\0"
    "dcr\0" APPLICATION_STR "x-director\0"
    "dib\0" IMAGE_STR "bmp\0"
    "dir\0" APPLICATION_STR "x-director\0"
    "dxr\0" APPLICATION_STR "x-director\0"
    "gif\0" IMAGE_STR "gif\0"
    "hta\0" TEXT_STR "hta\0"
    "htm\0" TEXT_STR "html\0"
    "html\0" TEXT_STR "html\0"
    "jar\0" APPLICATION_STR "java-archive\0"
    "jfif\0" IMAGE_STR "pjpeg\0"
    "jpe\0" IMAGE_STR "jpeg\0"
    "jpeg\0" IMAGE_STR "jpeg\0"
    "jpg\0" IMAGE_STR "jpeg\0"
    "js\0" APPLICATION_STR "x-javascript\0"
    "kar\0" AUDIO_STR "midi\0"
    "m3u\0" AUDIO_STR "mpegurl\0"
    "mid\0" AUDIO_STR "midi\0"
    "midi\0" AUDIO_STR "midi\0"
    "mov\0" VIDEO_STR "quicktime\0"
    "mp2v\0" VIDEO_STR "x-mpeg2\0"
    "mp3\0" AUDIO_STR "mpeg\0"
    "mpe\0" VIDEO_STR "mpeg\0"
    "mpeg\0" VIDEO_STR "mpeg\0"
    "mpg\0" VIDEO_STR "mpeg\0"
    "mpv\0" VIDEO_STR "mpeg\0"
    "mpv2\0" VIDEO_STR "x-mpeg2\0"
    "pdf\0" APPLICATION_STR "pdf\0"
    "pjp\0" IMAGE_STR "jpeg\0"
    "pjpeg\0" IMAGE_STR "jpeg\0"
    "plg\0" TEXT_STR "html\0"
    "pls\0" AUDIO_STR "scpls\0"
    "png\0" IMAGE_STR "png\0"
    "qt\0" VIDEO_STR "quicktime\0"
    "ram\0" AUDIO_STR "x-pn-realaudio\0"
    "rmi\0" AUDIO_STR "mid\0"
    "rmm\0" AUDIO_STR "x-pn-realaudio\0"
    "rtf\0" APPLICATION_STR "rtf\0"
    "shtml\0" TEXT_STR "html\0"
    "smf\0" AUDIO_STR "midi\0"
    "snd\0" AUDIO_STR "basic\0"
    "spl\0" APPLICATION_STR "futuresplash\0"
    "ssm\0" APPLICATION_STR "streamingmedia\0"
    "swf\0" APPLICATION_STR "x-shockwave-flash\0"
    "tar\0" APPLICATION_STR "tar\0"
    "tcl\0" APPLICATION_STR "x-tcl\0"
    "text\0" TEXT_STR "plain\0"
    "tif\0" IMAGE_STR "tiff\0"
    "tiff\0" IMAGE_STR "tiff\0"
    "txt\0" TEXT_STR "plain\0"
    "ulw\0" AUDIO_STR "basic\0"
    "wav\0" AUDIO_STR "wav\0"
    "wax\0" AUDIO_STR "x-ms-wax\0"
    "wm\0" VIDEO_STR "x-ms-wm\0"
    "wma\0" AUDIO_STR "x-ms-wma\0"
    "wmv\0" VIDEO_STR "x-ms-wmv\0"
    "wvx\0" VIDEO_STR "x-ms-wvx\0"
    "xbm\0" IMAGE_STR "x-xbitmap\0"
    "xml\0" TEXT_STR "xml\0"
    "xsl\0" TEXT_STR "xml\0"
    "z\0" APPLICATION_STR "x-compress\0"
    "zip\0" APPLICATION_STR "zip\0" "\0";
    // *** end ***

/***********************************************************************/
/*
   module variables - Globals, static and externs                      
 */

/***********************************************************************/
static struct document_type_t gMediaTypeList[NUM_MEDIA_TYPES];
membuffer gDocumentRootDir;     // a local dir which serves as webserver root
#ifdef _ALIASDOC
static struct xml_alias_t gAliasDoc;    // XML document
#else _ALIASDOC
// need a dictionary of these things
#define NUM_ALIASES 10
static struct xml_alias_t gAliasDict[NUM_ALIASES];
static int numAliasDictEntries = 0;
#endif
static ithread_mutex_t gWebMutex;
extern str_int_entry Http_Header_Names[NUM_HTTP_HEADER_NAMES];

/************************************************************************
* Function: has_xml_content_type										
*																		
* Parameters:															
*	none																
*																		
* Description: decodes list and stores it in gMediaTypeList				
*																		
* Returns:																
*	 void																
************************************************************************/
static XINLINE void
media_list_init( void )
{
    int i;
    const char *s = gEncodedMediaTypes;
    struct document_type_t *doc_type;

    for( i = 0; *s != '\0'; i++ ) {
        doc_type = &gMediaTypeList[i];

        doc_type->file_ext = s;

        s += strlen( s ) + 1;   // point to type
        doc_type->content_type = gMediaTypes[( int )*s];    // set cont-type

        s++;                    // point to subtype
        doc_type->content_subtype = s;

        s += strlen( s ) + 1;   // next entry
    }
    assert( i == NUM_MEDIA_TYPES );
}

/************************************************************************
* Function: has_xml_content_type										
*																		
* Parameters:															
*	IN const char* extension ; 											
*	OUT const char** con_type,											
*	OUT const char** con_subtype										
*																		
* Description: Based on the extension, returns the content type and 	
*	content subtype														
*																		
* Returns:																
*	 0 on success;														
*	-1 on error															
************************************************************************/
static XINLINE int
search_extension( IN const char *extension,
                  OUT const char **con_type,
                  OUT const char **con_subtype )
{
    int top,
      mid,
      bot;
    int cmp;

    top = 0;
    bot = NUM_MEDIA_TYPES - 1;

    while( top <= bot ) {
        mid = ( top + bot ) / 2;
#ifndef _WIN32
        cmp = strcasecmp( extension, gMediaTypeList[mid].file_ext );
#else
        cmp = _stricmp( extension, gMediaTypeList[mid].file_ext );
#endif

        if( cmp > 0 ) {
            top = mid + 1;      // look below mid
        } else if( cmp < 0 ) {
            bot = mid - 1;      // look above mid
        } else                  // cmp == 0
        {
            *con_type = gMediaTypeList[mid].content_type;
            *con_subtype = gMediaTypeList[mid].content_subtype;
            return 0;
        }
    }

    return -1;
}

/************************************************************************
* Function: get_content_type											
*																		
* Parameters:															
*	IN const char* filename,											
*	OUT DOMString* content_type											
*																		
* Description: Based on the extension, clones an XML string based on	
*	type and content subtype. If content type and sub type are not		
*	found, unknown types are used										
*																		
* Returns:																
*	 0 - On Sucess														
*	 UPNP_E_OUTOF_MEMORY - on memory allocation failures				
************************************************************************/
XINLINE int
get_content_type( IN const char *filename,
                  OUT DOMString * content_type )
{
    const char *extension;
    const char *type,
     *subtype;
    xboolean ctype_found = FALSE;
    char *temp = NULL;
    int length = 0;

    ( *content_type ) = NULL;

    // get ext
    extension = strrchr( filename, '.' );
    if( extension != NULL ) {
        if( search_extension( extension + 1, &type, &subtype ) == 0 ) {
            ctype_found = TRUE;
        }
    }

    if( !ctype_found ) {
        // unknown content type
        type = gMediaTypes[APPLICATION_INDEX];
        subtype = "octet-stream";
    }

    length = strlen( type ) + strlen( "/" ) + strlen( subtype ) + 1;
    temp = ( char * )malloc( length );

    if( !temp ) {
        return UPNP_E_OUTOF_MEMORY;
    }

    sprintf( temp, "%s/%s", type, subtype );
    ( *content_type ) = ixmlCloneDOMString( temp );

    free( temp );

    if( !content_type ) {
        return UPNP_E_OUTOF_MEMORY;
    }

    return 0;
}

/************************************************************************
* Function: glob_alias_init												
*																		
* Parameters:															
*	none																
*																		
* Description: Initialize the global XML document. Allocate buffers		
*	for the XML document												
*																		
* Returns:																
*	 void																
************************************************************************/
static XINLINE void
glob_alias_init( void )
{
#ifndef _ALIASDOC    
    int i;
    struct xml_alias_t *alias = 0;
#else
    struct xml_alias_t *alias = &gAliasDoc;

#endif

#ifndef _ALIASDOC  
    for (i = 0; i < NUM_ALIASES; i++ ) {
	alias = &(gAliasDict[i]);
#endif

	membuffer_init( &alias->doc );
	membuffer_init( &alias->name );
	alias->ct = NULL;
	alias->last_modified = 0;
#ifndef _ALIASDOC    
    }
#endif
}

/************************************************************************
* Function: is_valid_alias												
*																		
* Parameters:															
*	IN const struct xml_alias_t* alias ; XML alias object				
*																		
* Description: Check for the validity of the XML object buffer													
*																		
* Returns:																
*	 BOOLEAN															
************************************************************************/
static XINLINE xboolean
is_valid_alias( IN const struct xml_alias_t *alias )
{
    return alias->doc.buf != NULL;
}
#ifdef _ALIASDOC
/************************************************************************
* Function: alias_grab													
*																		
* Parameters:															
*	OUT struct xml_alias_t* alias ; XML alias object										
*																		
* Description: Copy the contents of the global XML document into the	
*	local OUT parameter																							
*																		
* Returns:																
*	 void																
************************************************************************/
static void
alias_grab( OUT struct xml_alias_t *alias )
{
    ithread_mutex_lock( &gWebMutex );

    assert( is_valid_alias( &gAliasDoc ) );

    memcpy( alias, &gAliasDoc, sizeof( struct xml_alias_t ) );
    *alias->ct = *alias->ct + 1;

    ithread_mutex_unlock( &gWebMutex );
}
#endif
/************************************************************************
* Function: alias_release												
*																		
* Parameters:															
*	IN struct xml_alias_t* alias ; XML alias object										
*																		
* Description: Release the XML document referred to by the IN parameter 
*	Free the allocated buffers associated with this object				
*																		
* Returns:																
*	void																
************************************************************************/
static void
alias_release( IN struct xml_alias_t *alias )
{
    ithread_mutex_lock( &gWebMutex );

    // ignore invalid alias
    if( !is_valid_alias( alias ) ) {
        ithread_mutex_unlock( &gWebMutex );
        return;
    }

    assert( alias->ct > 0 );

    *alias->ct = *alias->ct - 1;
    if( *alias->ct <= 0 ) {
        membuffer_destroy( &alias->doc );
        membuffer_destroy( &alias->name );
        free( alias->ct );
    }
    ithread_mutex_unlock( &gWebMutex );
}

/************************************************************************
* Function: web_server_set_alias										
*																		
* Parameters:															
*	alias_name: webserver name of alias; created by caller and freed by 

⌨️ 快捷键说明

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