📄 webserver.c
字号:
* caller (doesn't even have to be malloc()d .)
* alias_content: the xml doc; this is allocated by the caller; and
* freed by the web server
* alias_content_length: length of alias body in bytes
* last_modified: time when the contents of alias were last
* changed (local time)
*
* Description: Replaces current alias with the given alias. To remove
* the current alias, set alias_name to NULL.
*
* Returns:
* 0 - OK
* UPNP_E_OUTOF_MEMORY: note: alias_content is not freed here
************************************************************************/
int
web_server_set_alias( IN const char *alias_name,
IN const char *alias_content,
IN size_t alias_content_length,
IN time_t last_modified )
{
int ret_code;
struct xml_alias_t alias;
#ifdef _ALIASDOC
alias_release( &gAliasDoc );
#endif
if( alias_name == NULL ) {
// don't serve aliased doc anymore
return 0;
}
assert( alias_content != NULL );
membuffer_init( &alias.doc );
membuffer_init( &alias.name );
alias.ct = NULL;
do {
// insert leading /, if missing
if( *alias_name != '/' ) {
if( membuffer_assign_str( &alias.name, "/" ) != 0 ) {
break; // error; out of mem
}
}
ret_code = membuffer_append_str( &alias.name, alias_name );
if( ret_code != 0 ) {
break; // error
}
if( ( alias.ct = ( int * )malloc( sizeof( int ) ) ) == NULL ) {
break; // error
}
*alias.ct = 1;
membuffer_attach( &alias.doc, ( char * )alias_content,
alias_content_length );
alias.last_modified = last_modified;
// save in module var
ithread_mutex_lock( &gWebMutex );
#ifdef _ALIASDOC
gAliasDoc = alias;
#else
memcpy( &(gAliasDict[numAliasDictEntries]), &alias, sizeof( struct xml_alias_t ) );
numAliasDictEntries++;
#endif
ithread_mutex_unlock( &gWebMutex );
return 0;
} while( FALSE );
// error handler
// free temp alias
membuffer_destroy( &alias.name );
membuffer_destroy( &alias.doc );
free( alias.ct );
return UPNP_E_OUTOF_MEMORY;
}
/************************************************************************
* Function: web_server_init
*
* Parameters:
* none
*
* Description: Initilialize the different documents. Initialize the
* memory for root directory for web server. Call to initialize global
* XML document. Sets bWebServerState to WEB_SERVER_ENABLED
*
* Returns:
* 0 - OK
* UPNP_E_OUTOF_MEMORY: note: alias_content is not freed here
************************************************************************/
int
web_server_init( void )
{
int ret_code;
if( bWebServerState == WEB_SERVER_DISABLED ) {
media_list_init( ); // decode media list
membuffer_init( &gDocumentRootDir );
glob_alias_init( );
pVirtualDirList = NULL;
ret_code = ithread_mutex_init( &gWebMutex, NULL );
if( ret_code == -1 ) {
return UPNP_E_OUTOF_MEMORY;
}
bWebServerState = WEB_SERVER_ENABLED;
}
return 0;
}
/************************************************************************
* Function: web_server_destroy
*
* Parameters:
* none
*
* Description: Release memory allocated for the global web server root
* directory and the global XML document
* Resets the flag bWebServerState to WEB_SERVER_DISABLED
*
* Returns:
* void
************************************************************************/
void
web_server_destroy( void )
{
int ret;
if( bWebServerState == WEB_SERVER_ENABLED ) {
membuffer_destroy( &gDocumentRootDir );
#ifdef _ALIASDOC
alias_release( &gAliasDoc );
ithread_mutex_lock( &gWebMutex );
memset( &gAliasDoc, 0, sizeof( struct xml_alias_t ) );
ithread_mutex_unlock( &gWebMutex );
#endif
ret = ithread_mutex_destroy( &gWebMutex );
assert( ret == 0 );
bWebServerState = WEB_SERVER_DISABLED;
}
}
/************************************************************************
* Function: get_file_info
*
* Parameters:
* IN const char* filename ; Filename having the description document
* OUT struct File_Info * info ; File information object having file
* attributes such as filelength, when was
* the file last modified, whether a file
* or a directory and whether the file or
* directory is readable.
*
* Description: Release memory allocated for the global web server root
* directory and the global XML document
* Resets the flag bWebServerState to WEB_SERVER_DISABLED
*
* Returns:
* int
************************************************************************/
static int
get_file_info( IN const char *filename,
OUT struct File_Info *info )
{
int code;
struct stat s;
FILE *fp;
int rc = 0;
info->content_type = NULL;
code = stat( filename, &s );
if( code == -1 ) {
return -1;
}
#ifndef _WIN32
if( S_ISDIR( s.st_mode ) ) {
#else
if( S_IFDIR & s.st_mode ) {
#endif
info->is_directory = TRUE;
#ifndef _WIN32
} else if( S_ISREG( s.st_mode ) ) {
#else
} else if( S_IFREG & s.st_mode ) {
#endif
info->is_directory = FALSE;
} else {
return -1;
}
// check readable
fp = fopen( filename, "r" );
info->is_readable = ( fp != NULL );
if( fp ) {
fclose( fp );
}
info->file_length = s.st_size;
info->last_modified = s.st_mtime;
rc = get_content_type( filename, &info->content_type );
DBGONLY( UpnpPrintf( UPNP_INFO, HTTP, __FILE__, __LINE__,
"file info: %s, length: %d, last_mod=%s readable=%d\n",
filename, info->file_length,
asctime( gmtime( &info->last_modified ) ),
info->is_readable ); )
return rc;
}
/************************************************************************
* Function: web_server_set_root_dir
*
* Parameters:
* IN const char* root_dir ; String having the root directory for the
* document
*
* Description: Assign the path specfied by the IN const char* root_dir
* parameter to the global Document root directory. Also check for
* path names ending in '/'
*
* Returns:
* int
************************************************************************/
int
web_server_set_root_dir( IN const char *root_dir )
{
int index;
int ret;
ret = membuffer_assign_str( &gDocumentRootDir, root_dir );
if( ret != 0 ) {
return ret;
}
// remove trailing '/', if any
if( gDocumentRootDir.length > 0 ) {
index = gDocumentRootDir.length - 1; // last char
if( gDocumentRootDir.buf[index] == '/' ) {
membuffer_delete( &gDocumentRootDir, index, 1 );
}
}
return 0;
}
#ifndef _ALIASDOC
/************************************************************************
* Function: getAliasFromDict(
*
* Parameters:
* IN const char* request_file ; request file passed in to be compared with
* OUT struct xml_alias_t* alias ; xml alias object which has a file name
* stored
* OUT struct File_Info * info ; File information object which will be
* filled up if the file comparison succeeds
*
* Description: Compare the files names between the one on the XML alias
* the one passed in as the input parameter. If equal extract file
* information
*
* Returns:
* TRUE - On Success
* FALSE if request is not an alias
************************************************************************/
static xboolean
getAliasFromDict(IN const char *request_file,
OUT struct xml_alias_t *alias,
OUT struct File_Info *info )
{
int i;
// traverse dictionary looking for the alias
ithread_mutex_lock( &gWebMutex );
for (i = 0; i < numAliasDictEntries; i++) {
if (strcmp(gAliasDict[i].name.buf, request_file) == 0) {
memcpy( alias, &(gAliasDict[i]), sizeof( struct xml_alias_t ) );
(*(alias->ct))++;
// fill up info
info->file_length = alias->doc.length;
info->is_readable = TRUE;
info->is_directory = FALSE;
info->last_modified = alias->last_modified;
ithread_mutex_unlock( &gWebMutex );
return TRUE;
}
}
ithread_mutex_unlock( &gWebMutex );
return FALSE;
}
#endif
/************************************************************************
* Function: get_alias
*
* Parameters:
* IN const char* request_file ; request file passed in to be compared with
* OUT struct xml_alias_t* alias ; xml alias object which has a file name
* stored
* OUT struct File_Info * info ; File information object which will be
* filled up if the file comparison
* succeeds
*
* Description: Compare the files names between the one on the XML alias
* the one passed in as the input parameter. If equal extract file
* information
*
* Returns:
* TRUE - On Success
* FALSE if request is not an alias
************************************************************************/
static XINLINE xboolean
get_alias( IN const char *request_file,
OUT struct xml_alias_t *alias,
OUT struct File_Info *info )
{
int cmp;
cmp = strcmp( alias->name.buf, request_file );
if( cmp == 0 ) {
// fill up info
info->file_length = alias->doc.length;
info->is_readable = TRUE;
info->is_directory = FALSE;
info->last_modified = alias->last_modified;
}
return cmp == 0;
}
/************************************************************************
* Function: isFileInVirtualDir
*
* Parameters:
* IN char *filePath ; directory path to be tested for virtual directory
*
* Description: Compares filePath with paths from the list of virtual
* directory lists
*
* Returns:
* BOOLEAN
************************************************************************/
int
isFileInVirtualDir( IN char *filePath )
{
virtualDirList *pCurVirtualDir;
int webDirLen;
pCurVirtualDir = pVirtualDirList;
while( pCurVirtualDir != NULL ) {
webDirLen = strlen( pCurVirtualDir->dirName );
if( pCurVirtualDir->dirName[webDirLen - 1] == '/' ) {
if( strncmp( pCurVirtualDir->dirName, filePath, webDirLen ) ==
0 )
return TRUE;
} else {
if( ( strncmp( pCurVirtualDir->dirName, filePath, webDirLen )
== 0 ) && ( filePath[webDirLen] == '/' ) )
return TRUE;
}
pCurVirtualDir = pCurVirtualDir->next;
}
return FALSE;
}
/************************************************************************
* Function: ToUpperCase
*
* Parameters:
* INOUT char * Str ; Input string to be converted
*
* Description: Converts input string to upper case
*
* Returns:
* int
************************************************************************/
int
ToUpperCase( char *Str )
{
int i;
for( i = 0; i < ( int )strlen( Str ); i++ )
Str[i] = toupper( Str[i] );
return 1;
}
/************************************************************************
* Function: StrStr
*
* Parameters:
* IN char * S1 ; Input string
* IN char * S2 ; Input sub-string
*
* Description: Finds a substring from a string
*
* Returns:
* char * ptr - pointer to the first occurence of S2 in S1
************************************************************************/
char *
StrStr( char *S1,
char *S2 )
{
char *Str1,
*Str2;
char *Ptr,
*Ret;
int Pos;
Str1 = ( char * )malloc( strlen( S1 ) + 2 );
Str2 = ( char * )malloc( strlen( S2 ) + 2 );
if( !Str1 || !Str2 )
return NULL;
strcpy( Str1, S1 );
strcpy( Str2, S2 );
ToUpperCase( Str1 );
ToUpperCase( Str2 );
Ptr = strstr( Str1, Str2 );
if( Ptr == NULL )
return NULL;
Pos = Ptr - Str1;
Ret = S1 + Pos;
free( Str1 );
free( Str2 );
return Ret;
}
/************************************************************************
* Function: StrTok
*
* Parameters:
* IN char ** Src ; String containing the token
* IN char * del ; Set of delimiter characters
*
* Description: Finds next token in a string
*
* Returns:
* char * ptr - pointer to the first occurence of S2 in S1
************************************************************************/
char *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -