diff options
Diffstat (limited to 'httpserver/http-readmsg.cc')
-rw-r--r-- | httpserver/http-readmsg.cc | 1014 |
1 files changed, 1014 insertions, 0 deletions
diff --git a/httpserver/http-readmsg.cc b/httpserver/http-readmsg.cc new file mode 100644 index 0000000..da88274 --- /dev/null +++ b/httpserver/http-readmsg.cc @@ -0,0 +1,1014 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +#include "mymalloc/mymalloc.h" +/*------------------------------------------------------------------------*/ +/* http-readmsg.c - generic HTTP-Message functions: */ +/* Reading and parsing of HTTP-Messages. */ +/*------------------------------------------------------------------------*/ +/* Comments: */ +/* - Status: */ +/* - Missing symbolic constant BUFFBLOCK_SIZE. */ +/* - To check: All Buffers free()ed? Also in error cases? */ +/* - ParseReqLine()/ParseRespLine() use static buffers, but */ +/* they are protected against overwriting. */ +/*------------------------------------------------------------------------*/ + + +#include "defs.h" +#include "protos.h" +#include "server.h" +#include "http-defs.h" +#include "http.h" + + +/****** http-readmsg/ReadHeader ********************************************** +* +* NAME +* ReadHeader -- Read a HTTP message header from a socket. +* +* SYNOPSIS +* char *ReadHeader( int SockFD, size_t *size ); +* +* FUNCTION +* This function reads from the socket descriptor "SockFD" until it +* detects an empty line (two <CR><LF> sequences in a row). Every read +* character is stored in a buffer, which is dynamically allocated. +* If the empty line is detected, it returns a pointer to the buffer +* and the variable "*size" contains the buffersize. +* +* INPUTS +* SockFD - The socket descriptor to read from. +* size - A pointer to a variable which may hold the size of the buffer +* which contains the message header. +* +* RESULT +* A pointer a buffer with the HTTP message header. +* +* NOTES +* The function checks for errors returned by the "read()" system call. +* Other problems ("out-of-band" data, socket errors) are not checked. +* +****************************************************************************** +* +*/ + +int ReadHeader( int SockFD, char **Buffer, size_t *BuffSize ) +{ + size_t BuffBlock = 1024; + size_t minbuff = 2; + size_t nread = 0; + size_t sumread = 0; + char *Ptr; + int check_eol = 0; + int error = FALSE; + int elapsed = 0; + + for(;;) + { + if( *BuffSize - sumread < minbuff ) + { + *BuffSize += BuffBlock; + *Buffer = (char*)realloc( *Buffer, *BuffSize ); + if( *Buffer == NULL ) + { + ErrorMsg( E_SYS, ERROR, "ERROR: ReadHeader(): malloc() failed." ); + error = TRUE; + break; + } + bzero( *Buffer, *BuffSize ); + } + + Ptr = *Buffer + sumread; + nread = read( SockFD, Ptr, 1 ); + if( nread == 1 ) + { + elapsed = 0; /* Clear timeout counter */ + sumread++; + if( *Ptr == '\n' ) /* Check for two consecutive "\r\n" */ + { + if( check_eol == 1 ) + break; /* if found => End-Of-Header */ + else + check_eol = 1; + } + else if( *Ptr != '\r' ) + check_eol = 0; + } + else if( nread == 0 ) + { + if( elapsed >= 30 ) + { + ErrorMsg( E_PRIV, ERROR, "ERROR: ReadHeader() timed out." ); + error = TRUE; + break; + } + sleep(1); + elapsed++; + } + else + { + if( errno != EAGAIN ) + { + ErrorMsg( E_SYS, ERROR, "ERROR: ReadHeader(): read() failed." ); + error = TRUE; + break; + } + else + { + sleep( elapsed ); + if( elapsed >= 30 ) + { + ErrorMsg( E_PRIV, ERROR, "ERROR: ReadHeader() timed out." ); + error = TRUE; + break; + } + sleep(1); + elapsed++; + } + } + } + if( error == TRUE ) + { + if( *Buffer != NULL ) + free( *Buffer ); + *Buffer = NULL; + *BuffSize = 0; + return( RI_READ_ERROR ); + } + else + return( RI_READ_OK ); +} + + +/****** http-readmsg/ReadBody ************************************************ +* +* NAME +* ReadBody -- Read a HTTP message body from a socket. +* +* SYNOPSIS +* char *ReadBody( int SockFD, size_t BuffSize ); +* +* FUNCTION +* This functions reads the HTTP message body with the size "BuffSize" +* from the socket "SockFD". A buffer for the message body is allocated +* within this function and a pointer to this buffer is returned. +* +* INPUTS +* SockFD - The socket descriptor to read from. +* BuffSize - The size of the message body. +* +* RESULT +* A pointer to the buffer which contains the message body. +* +* NOTES +* The function checks for errors returned by the "read()" system call. +* Other problems ("out-of-band" data, socket errors) are not checked. +* +****************************************************************************** +* +*/ + +char *ReadBody( int SockFD, size_t BuffSize ) +{ + int nread = 0; + char *Buffer = NULL; + + if( ( Buffer = (char*)mymalloc( BuffSize + 1 ) ) == NULL ) + { + ErrorMsg( E_SYS, ERROR, "ERROR: malloc error for HTTP-Body buffer." ); + return( Buffer ); + } + bzero( Buffer, BuffSize + 1); + nread = ReadN( SockFD, Buffer, BuffSize ); + if( nread < 0 ) + { + ErrorMsg( E_SYS, ERROR, "ERROR: ReadBody(): read() failed." ); + free( Buffer ); + Buffer = NULL; + return( Buffer ); + } + else if( nread < BuffSize ) + { + ErrorMsg( E_PRIV, WARN, "WARN: MessageBody not of expected size." ); + } + return( Buffer ); +} + + +/****** http-readmsg/ParseReqHeader ****************************************** +* +* NAME +* ParseReqHeader - Parse the HTTP request header. +* +* SYNOPSIS +* rc_t ParseReqHeader( struct ReqInfo *Request ); +* +* FUNCTION +* This is the main function for parsing the HTTP request headers. +* It first calls "ParseReqLine()" to actually parse the "Request +* Line" (the first line of an HTTP request) and then calls +* subsequently "ParseMsgLine()" for every non-empty line following +* the request-line. +* +* The results of this parsing process are stored in a data structure +* of the type "ReqInfo", which is later used for searching in and +* reconstructing of the header informations. +* +* INPUTS +* Request - A pointer to a data structure of the type ReqInfo. +* +* RESULT +* Returns "OK" if everything went well. +* +* BUGS +* It doesn't check if "Request" is a NULL pointer. +* +* SEE ALSO +* ParseRespHeader(), ParseReqLine(), ParseMsgLine(). +* +****************************************************************************** +* +*/ + +rc_t ParseReqHeader( struct ReqInfo *Request ) +{ + char *Buffer; + char *Param; + int Key; + struct MsgHeader *Header; + + Header = NULL; + Buffer = Request->HeadBuff; + if( Request->State == RI_READ_OK ) + { + Buffer = ParseReqLine( Buffer, Request ); + //LogMsg( LG_SERVER, DEBUG, "DEBUG: *** Parsed Req %s", Buffer ); + if( Request->State == RI_PARSE_ERROR ) + return( WARN ); + } + else + { + Request->State = RI_PARSE_ERROR; + return( WARN ); + } + + while( Buffer != NULL && *Buffer != '\0' ) + { + Key = -1; + Param = NULL; + Buffer = ParseMsgLine( Buffer, &Key, &Param ); + //LogMsg( LG_SERVER, DEBUG, "DEBUG: *** Parsed Msg %s", Buffer ); + if( Buffer != NULL ) + { + Header = AppendMsgHeader( Request->Last, Key, Param ); + Request->Last = Header; + } + if( Request->First == NULL ) + Request->First = Header; + } + if( Request->First == NULL ) + { + Request->State = RI_PARSE_WARN; + return( WARN ); + } + else + { + Request->State = RI_PARSE_OK; + return( OK ); + } +} + + +/****** http-readmsg/ParseRespHeader ***************************************** +* +* NAME +* ParseRespHeader - Parse the HTTP response header. +* +* SYNOPSIS +* rc_t ParseRespHeader( struct RespInfo *Response ); +* +* FUNCTION +* This is the main function for parsing the HTTP response headers. +* It first calls "ParseRespLine()" to actually parse the "Response +* Line" (the first line of an HTTP response) and then calls +* subsequently "ParseMsgLine()" for every non-empty line following +* the request-line. +* +* The results of this parsing process are stored in a data structure +* of the type "RespInfo", which is later used for searching in and +* reconstructing of the header informations. +* +* INPUTS +* Response - A pointer to a data structure of the type RespInfo. +* +* RESULT +* Returns "OK" if everything went well. +* +* BUGS +* Actually, it always returns an "OK" status code. +* It doesn't check if "Response" is a NULL pointer. +* +* SEE ALSO +* ParseReqHeader(), ParseRespLine(), ParseMsgLine(). +* +****************************************************************************** +* +*/ + +rc_t ParseRespHeader( struct RespInfo *Response ) +{ + char *Buffer; + char *Keyword; + char *Param; + size_t i; + int Key; + struct MsgHeader *Header; + + Header = NULL; + Buffer = Response->HeadBuff; + Buffer = ParseRespLine( Buffer, Response ); + + while( Buffer != NULL ) + { + Key = -1; + Param = NULL; + Buffer = ParseMsgLine( Buffer, &Key, &Param ); + if( Buffer != NULL ) + { + Header = AppendMsgHeader( Response->Last, Key, Param ); + Response->Last = Header; + } + if( Response->First == NULL ) + Response->First = Header; + } + return( OK ); +} + + +/****** http-readmsg/ParseReqLine ******************************************** +* +* NAME +* ParseReqLine - Parse the HTTP request line. +* +* SYNOPSIS +* char *ParseReqLine( char *Buffer, struct ReqInfo *Request ); +* +* FUNCTION +* This function parses the beginning of the buffer "Buffer" for the +* contents of a HTTP request line. Since the parsing process (as +* implemented here) is destructive to the original string, the buffer +* is first scanned for a <CR><LF> sequence (end-of-line mark of a +* HTTP message) while copying any other character encountered to a +* secondary buffer. This "Backup" of the request line is later used +* for logging purposes, so it can be referred to in case of a problem. +* +* Then the request line is parsed and broken up in its components, as +* they are: Request method, URL, protocol-id and version. These are +* stored in the appropriate places in a "ReqInfo" data structure. +* +* INPUTS +* Buffer - A pointer to the raw data of a HTTP request. +* Request - A pointer to a data structure of the type ReqInfo. +* +* RESULT +* A pointer into the buffer, pointing to the rest of the data to be +* processed. +* +* BUGS +* "Buffer" and "Request" are not checked for NULL pointers. +* The "Backup" of the request line has a maximum length of +* "MAXLINELEN". +* +* SEE ALSO +* ParseRespLine(). +* +****************************************************************************** +* +*/ + +char *ParseReqLine( char *Buffer, struct ReqInfo *Request ) +{ + char Tmp[ MAXLINELEN ]; + char *NewBuffer; + char *Ptr; + char *Keyword; + char *URL = NULL; + char *PVersion = NULL; + int Key = 0; + int PVmaj = -1; + int PVmin = -1; + int i; + int eol_found = FALSE; + + Keyword = Buffer; + + for( Ptr = Buffer, i = 0; i < MAXLINELEN; Ptr++, i++ ) + { + if( *Ptr == '\r') + Tmp[i] = '\0'; + else if( *Ptr == '\n' ) + { + Tmp[i] = '\0'; + eol_found = TRUE; + break; + } + else + Tmp[i] = *Ptr; + } + Tmp[i+1] = '\0'; + if( eol_found != TRUE ) + { + Request->State = RI_PARSE_ERROR; + return( NULL ); + } + + for( Ptr = Buffer; *Ptr != '\n'; Ptr++ ) + { + if( *Ptr == ' ' ) + { + if( URL == NULL ) + { + *Ptr = '\0'; + URL = ++Ptr; + } + else + { + *Ptr = '\0'; + ++Ptr; + if( strcmp( "HTTP/", Ptr ) ) + { + Ptr += 5; + PVersion = Ptr; + } + } + } + else if( *Ptr == '\r' ) + { + *Ptr = '\0'; + } + } + *Ptr = '\0'; + NewBuffer = ++Ptr; + + if( PVersion != NULL ) + { + for( Ptr = PVersion; *Ptr != '\0'; Ptr++ ) + { + if( *Ptr == '.' ) + { + *Ptr = '\0'; + ++Ptr; + break; + } + } + PVmaj = strtol( PVersion, NULL, 10 ); + PVmin = strtol( Ptr, NULL, 10 ); + } + + if( URL != NULL ) + { + Request->Line.Vanilla = (char*)mymalloc( strlen( Tmp ) + 1 ); + Request->Line.Method = HTTP_GetMKey( Keyword ); + // SplitURL( URL, &Request->Line.URL ); + Request->Line.URL.Path = URL; + Request->Line.Version.Major = PVmaj; + Request->Line.Version.Minor = PVmin; + strcpy( Request->Line.Vanilla, Tmp ); + Request->State = RI_PARSE_OK; + return( NewBuffer ); + } + else + { + Request->State = RI_PARSE_ERROR; + return( NULL ); + } +} + + +/****** http-readmsg/ParseRespLine ******************************************* +* +* NAME +* ParseRespLine - Parse the HTTP response line. +* +* SYNOPSIS +* char *ParseRespLine( char *Buffer, struct RespInfo *Response ); +* +* FUNCTION +* This function parses the beginning of the buffer "Buffer" for the +* contents of a HTTP response line. Since the parsing process (as +* implemented here) is destructive to the original string, the buffer +* is first scanned for a <CR><LF> sequence (end-of-line mark of a +* HTTP message) while copying any other character encountered to a +* secondary buffer. This "Backup" of the response line is later used +* for logging purposes, so it can be referred to in case of a problem. +* +* Then the response line is parsed and broken up in its components, as +* they are: Protocol-id and version, (numeric) status code and +* "reason phrase". These are stored in the appropriate places in a +* "RespInfo" data structure. +* +* INPUTS +* Buffer - A pointer to the raw data of a HTTP request. +* Response - A pointer to a data structure of the type RespInfo. +* +* RESULT +* A pointer into the buffer, pointing to the rest of the data to be +* processed. +* +* BUGS +* "Buffer" and "Response" are not checked for NULL pointers. +* The "Backup" of the response line has a maximum length of +* "MAXLINELEN". +* +* SEE ALSO +* ParseReqLine(). +* +****************************************************************************** +* +*/ + +char *ParseRespLine( char *Buffer, struct RespInfo *Response ) +{ + char Tmp[ MAXLINELEN ]; + char *Ptr; + char *Reason = NULL; + char *PVersion = NULL; + char *Status = NULL; + char *PVmaj = NULL; + char *PVmin = NULL; + int i; + + for( Ptr = Buffer, i = 0; i <= MAXLINELEN - 1; Ptr++, i++ ) + { + if( *Ptr == '\r') + Tmp[i] = '\0'; + else if( *Ptr == '\n' ) + { + Tmp[i] = '\0'; + break; + } + else + Tmp[i] = *Ptr; + } + Tmp[i+1] = '\0'; + + Response->Line.Vanilla = (char*)mymalloc( strlen( Tmp ) + 1 ); + strcpy( Response->Line.Vanilla, Tmp ); + + if( strcmp( "HTTP/", Buffer ) ) + { + PVmaj = Buffer + 5; + for( Ptr = PVmaj; *Ptr != ' '; Ptr++ ) + { + if( *Ptr == '.' ) + { + *Ptr = '\0'; + PVmin = ++Ptr; + } + } + *Ptr = '\0'; + Response->Line.Version.Major = strtol( PVmaj, NULL, 10 ); + Response->Line.Version.Minor = strtol( PVmin, NULL, 10 ); + } + else + return( NULL ); + + Status = ++Ptr; + while( *Ptr != ' ' ) + Ptr++; + *Ptr = '\0'; + Response->Line.Status = strtol( Status, NULL, 10 ); + + Ptr++; + Response->Line.Reason = Ptr; + + while( *Ptr != '\n' ) + { + if( *Ptr == '\r' ) + *Ptr = '\0'; + Ptr++; + } + *Ptr = '\0'; + + return( ++Ptr ); +} + + +/****** http-readmsg/ParseMsgLine ******************************************** +* +* NAME +* ParseMsgLine - Parse a HTTP message header line. +* +* SYNOPSIS +* char *ParseMsgLine( char *Buffer, int *Key, char **Param ); +* +* FUNCTION +* This function parses a HTTP message header field into the +* components field name and field content ("value" of this field). +* The appropriate token for the field name is stored in the variable +* where "Key" points to and "Param" points to the field content +* string. +* +* INPUTS +* Buffer - A pointer to the raw data of a HTTP request. +* Key - A pointer to a variable which will store the field name token. +* Param - A pointer to a character pointer, which will refer to +* the field content string. +* +* RESULT +* A pointer into the buffer, pointing to the rest of the data to be +* processed. +* +* NOTES +* In case of unknown field names, the field content string will +* contain not only the value of the field, instead it will contain the +* complete header line. +* +* BUGS +* "Buffer", "Key" and "Param" are not checked against NULL pointers. +* +****************************************************************************** +* +*/ + +char *ParseMsgLine( char *Buffer, int *Key, char **Param ) +{ + char *Keyword; + char *Ptr; + int HaveKey = FALSE; + + if( ( *Buffer == ' ' ) || ( *Buffer == '\t' ) ) + { + *Key = HKEY_CONTINUE; + *Param = Buffer; + + for( Ptr = Buffer; *Ptr != '\n'; Ptr++ ) + { + if( *Ptr == '\r' ) + *Ptr = '\0'; + else if( *Ptr == '\0' ) + break; + } + *Ptr = '\0'; + return( ++Ptr ); + } + + Keyword = Buffer; + for( Ptr = Buffer; *Ptr != '\n'; Ptr++ ) + { + if( *Ptr == ':' ) + { + if( HaveKey == FALSE ) + { + HaveKey = TRUE; + *Ptr = '\0'; + *Key = HTTP_GetHKey( Keyword ); + if( *Key != HKEY_UNKNOWN ) + { + Ptr++; + while( ( *Ptr == ' ' ) || ( *Ptr == '\t' ) ) + ++Ptr; + *Param = Ptr; + } + else + { + *Ptr = ':'; + *Param = Buffer; + } + } + } + else if( *Ptr == '\r' ) + *Ptr = '\0'; + else if( *Ptr == '\0' ) + break; + } + *Ptr = '\0'; + + if( *Key == -1 || HaveKey == FALSE ) + return( NULL ); + else + return( ++Ptr ); +} + + +/****** http-readmsg/splitURL ************************************************ +* +* NAME +* splitURL - break up an URL string into its components. +* +* SYNOPSIS +* void splitURL( char *Buffer, struct URLComps *URL ); +* +* FUNCTION +* This function searches in a linked list of "MsgHeader" elements +* for one with a "Content_Length" token, and returns the integer +* value of it. +* +* INPUTS +* Buffer - the URL string. +* URL - a pointer to structure, which holds the pointers to the +* the strings of the components. +* +* RESULT +* If the creation of a buffer for the components fails, all components +* of URL will have NULL pointers. If no protocol is found in Buffer, +* URL->Path will contain the complete contents of Buffer (it is +* assumed that Buffer conatins a relative URL). In this case +* URL->Extra whill always be NULL. +* URL->Servername may be NULL, if there was no Servername separator +* ("//") found - this may be the case for URLs pointing to "this" +* Server ("localhost"). +* +****************************************************************************** +* +*/ + +void SplitURL( char *Buffer, struct URLComps *URL ) +{ + char *NewBuffer; + size_t BuffSize; + char *Ptr1; + char *Ptr2; + char *Tmp; + int HaveProto = FALSE; + int CheckSep = FALSE; + int HaveServer = FALSE; + int HavePath = FALSE; + int HaveExtra = FALSE; + + BuffSize = strlen( Buffer ) + 4; + NewBuffer = (char*)mymalloc( BuffSize ); + if( NewBuffer != NULL ) + { + bzero( NewBuffer, BuffSize ); + Tmp = NewBuffer; + for( Ptr1 = Buffer, Ptr2 = NewBuffer; Ptr1 <= Buffer + BuffSize; Ptr1++, Ptr2++ ) + { + if( HaveProto == FALSE ) + { + if( *Ptr1 == ':' ) + { + HaveProto = TRUE; + URL->Protocol = Tmp; + Tmp = Ptr2 + 1; + } + else + { + *Ptr2 = *Ptr1; + } + } + else if( CheckSep == FALSE ) + { + CheckSep = TRUE; + if( *Ptr1 == '/' && *(Ptr1+1) == '/' ) + { + Ptr1++; + } + else + { + HaveServer = TRUE; + URL->Servername = NULL; + Ptr1--; + } + } + else if( HaveServer == FALSE ) + { + if( *Ptr1 == '/' ) + { + HaveServer = TRUE; + URL->Servername = Tmp; + Tmp = Ptr2 + 1; + Ptr1--; + } + else + { + *Ptr2 = *Ptr1; + } + } + else if( HavePath == FALSE ) + { + if( *Ptr1 == '#' || *Ptr1 == '?' ) + { + HavePath = TRUE; + URL->Path = Tmp; + Tmp = Ptr2 + 1; + Ptr1--; + } + else + { + *Ptr2 = *Ptr1; + } + } + else + { + if( HaveExtra == FALSE ) + { + HaveExtra = TRUE; + URL->Extra = Tmp; + } + *Ptr2 = *Ptr1; + } + } + if( HaveProto == FALSE ) + { + URL->Path = Tmp; + } + } + else + { + URL->Protocol = NULL; + URL->Servername = NULL; + URL->Path = NULL; + URL->Extra = NULL; + } + + return; +} + + +/****** http-readmsg/GetContentLength **************************************** +* +* NAME +* GetContentLength - search for the "Content-Length" header in a HTTP +* message and return the value if found. +* +* SYNOPSIS +* size_t GetContentLength( struct MsgHeader *Ptr ); +* +* FUNCTION +* This function searches in a linked list of "MsgHeader" elements +* for one with a "Content_Length" token, and returns the integer +* value of it. +* +* INPUTS +* Ptr - A pointer to a "MsgHeader" node. +* +* RESULT +* 0 if no "Content-Length" header is found, otherwise the value of +* this message header converted into an integer (more precisely: the +* return value of "strtol()"). +* +* BUGS +* The return value of "strtol()" should maybe checked for proper +* results. +* +* SEE ALSO +* GetFieldContent(). +* +****************************************************************************** +* +*/ + +size_t GetContentLength( struct MsgHeader *Ptr ) +{ + while( Ptr != NULL ) + { + if( Ptr->Field == HKEY_Content_Length ) + return( strtol( Ptr->Content, NULL, 10 ) ); + Ptr = Ptr->Next; + } + return( 0 ); +} + + +/****** http-readmsg/GetFieldContent ***************************************** +* +* NAME +* GetFieldContent - Return the content of a specific message header. +* +* SYNOPSIS +* char *GetFieldContent( struct MsgHeader *Ptr, int Field, +* struct MsgHeader **Next ); +* +* FUNCTION +* This function searches in a linked list of "MsgHeader" elements +* for one with the token in the argument "Field", and returns the +* value of it. +* +* INPUTS +* Ptr - A pointer to a "MsgHeader" node. +* Field - The token of the field to search for. +* Next - A pointer to the next "MsgHeader" in the list. +* +* RESULT +* NULL if the header is not found, otherwise a pointer to the content +* string. +* +* SEE ALSO +* GetContentLength(). +* +****************************************************************************** +* +*/ + +char *GetFieldContent( struct MsgHeader *Ptr, int Field, struct MsgHeader **Next ) +{ + while( Ptr != NULL ) + { + if( Ptr->Field == Field ) + { + if( Next != NULL ) + *Next = Ptr->Next; + return( Ptr->Content ); + } + Ptr = Ptr->Next; + } + return( NULL ); +} + + +/****** http-readmsg/GetRealm ************************************************ +* +* NAME +* GetRealm - Search for specific Authentication realms. +* +* SYNOPSIS +* int GetRealm( char *String ); +* +* FUNCTION +* This function searches in the "WWW-Authenticate" header for specific +* authentication realm strings. If one of them is found, the +* appropriate code for this realm is returned. +* +* INPUTS +* String - A pointer to the contents of the "WWW-Authenticate" header +* field. +* +* RESULT +* A realm type code. +* +* BUGS +* "String" is not checked against a NULL pointer. +* +****************************************************************************** +* +*/ + +int GetRealm( char *String ) +{ + struct KeywordKey RealmKeyTable[] = + { + { "httpserver-IPClass-A", REALM_IPCLASS_A }, + { "httpserver-IPClass-B", REALM_IPCLASS_B }, + { "httpserver-IPClass-C", REALM_IPCLASS_C }, + { "httpserver-IPAddress", REALM_IPADDRESS }, + { "httpserver-Hostname", REALM_HOSTNAME }, + { "httpserver-Domain", REALM_DOMAIN }, + }; +#define NUM_REALMS 6 + + char *Buff; + char *Ptr; + char *Tmp; + int i; + + Ptr = String; + if( ( strncasecmp( "realm=", Ptr, 6 ) == 0 ) ) + { + Ptr = Ptr + 6; + if( ( Buff = (char*)mymalloc( strlen( Ptr ) + 1 ) ) == NULL ) + return( REALM_ERROR ); + strcpy( Buff, Ptr ); + + /* Kill Quotes... */ + if( *Ptr == '"' ) + { + Ptr++; + Tmp = strrchr( Ptr, '"' ); + if( Tmp != NULL ) + *Tmp = '\0'; + } + for( i = 0; i < NUM_REALMS; i++ ) + { + if( strcmp( RealmKeyTable[i].Keyword, Ptr ) == 0 ) + { + free( Buff ); + return( RealmKeyTable[i].Key ); + } + } + return( REALM_UNKNOWN ); + } + else + return( REALM_ERROR ); +} |