📄 uri.c
字号:
* Parameters :
* token * in ; token
*
* Description : Function useful in debugging for printing a token.
* Compiled out with DBGONLY macro.
*
* Return : void ;
*
* Note :
************************************************************************/
DBGONLY( void print_token( token * in ) {
int i = 0;
printf( "Token Size : %d\n\'", in->size );
for( i = 0; i < in->size; i++ ) {
putchar( in->buff[i] );}
putchar( '\'' ); putchar( '\n' );}
)
/************************************************************************
* Function : token_string_casecmp
*
* Parameters :
* token * in1 ; Token object whose buffer is to be compared
* char * in2 ; string of characters to compare with
*
* Description : Compares buffer in the token object with the buffer
* in in2
*
* Return : int ;
* < 0 string1 less than string2
* 0 string1 identical to string2
* > 0 string1 greater than string2
*
* Note :
************************************************************************/
int token_string_casecmp( token * in1,
char *in2 ) {
int in2_length = strlen( in2 );
if( in1->size != in2_length )
return 1;
else
return strncasecmp( in1->buff, in2, in1->size );
}
/************************************************************************
* Function : token_string_cmp
*
* Parameters :
* token * in1 ; Token object whose buffer is to be compared
* char * in2 ; string of characters to compare with
*
* Description : Compares a null terminated string to a token (exact)
*
* Return : int ;
* < 0 string1 less than string2
* 0 string1 identical to string2
* > 0 string1 greater than string2
*
* Note :
************************************************************************/
int
token_string_cmp( token * in1,
char *in2 )
{
int in2_length = strlen( in2 );
if( in1->size != in2_length )
return 1;
else
return strncmp( in1->buff, in2, in1->size );
}
/************************************************************************
* Function : token_cmp
*
* Parameters :
* token *in1 ; First token object whose buffer is to be compared
* token *in2 ; Second token object used for the comparison
*
* Description : Compares two tokens
*
* Return : int ;
* < 0 string1 less than string2
* 0 string1 identical to string2
* > 0 string1 greater than string2
*
* Note :
************************************************************************/
int
token_cmp( token * in1,
token * in2 )
{
if( in1->size != in2->size )
return 1;
else
return memcmp( in1->buff, in2->buff, in1->size );
}
/************************************************************************
* Function : parse_port
*
* Parameters :
* int max ; sets a maximum limit
* char * port ; port to be parsed.
* unsigned short * out ; out parameter where the port is parsed
* and converted into network format
*
* Description : parses a port (i.e. '4000') and converts it into a
* network ordered unsigned short int.
*
* Return : int ;
*
* Note :
************************************************************************/
int
parse_port( int max,
char *port,
unsigned short *out )
{
char *finger = port; // current location
char *max_ptr = finger + max;
unsigned short temp = 0; // area where port string is converted to integer
while( ( finger < max_ptr ) && ( isdigit( *finger ) ) ) {
temp = temp * 10;
temp += ( *finger ) - '0';
finger++;
}
*out = htons( temp );
return finger - port; // return the number of bytes parsed
}
#ifdef _WIN32
void
copy_port_name(int max,
char *inport,
char *outport )
{
char *finger = inport; // current location
char *max_ptr = finger + max;
while( ( finger < max_ptr ) && ( isdigit( *finger ) ) ) {
*outport = *finger;
outport++;
finger++;
}
*outport = 0;
}
#endif
/************************************************************************
* Function : parse_hostport
*
* Parameters :
* char *in ; string of characters representing host and port
* int max ; sets a maximum limit
* hostport_type *out ; out parameter where the host and port
* are represented as an internet address
*
* Description : Parses a string representing a host and port
* (e.g. "127.127.0.1:80" or "localhost") and fills out a
* hostport_type struct with internet address and a token
* representing the full host and port. uses gethostbyname.
*
* Return : int ;
*
* Note :
************************************************************************/
int
parse_hostport( char *in,
int max,
hostport_type * out )
{
#define BUFFER_SIZE 8192
int i = 0;
int begin_port;
int hostport_size = 0;
int host_size = 0;
struct hostent *h = NULL;
int errcode = 0;
char *temp_host_name = NULL;
int last_dot = -1;
#ifdef _WIN32
struct addrinfo *addrInfoPtr;
struct sockaddr_in * saiPtr;
char port_name[32];
unsigned long temp;
#endif
out->text.size = 0;
out->text.buff = NULL;
out->IPv4address.sin_port = htons( 80 ); //default port is 80
memset( &out->IPv4address.sin_zero, 0, 8 );
#ifdef _WIN32
sprintf(port_name, "%d", 80); //default port is 80
#endif
// look at the input string, up to the first ":" or "/"
// and find the last "."
while( ( i < max ) && ( in[i] != ':' ) && ( in[i] != '/' )
&& ( ( isalnum( in[i] ) ) || ( in[i] == '.' )
|| ( in[i] == '-' ) ) ) {
i++;
if( in[i] == '.' ) {
last_dot = i;
}
}
// this is where in the in string the host name ends
host_size = i;
// what is hostport_size?
if( ( i < max ) && ( in[i] == ':' ) ) {
// there is a port in the address
begin_port = i + 1;
//convert port
if( !( hostport_size = parse_port( max - begin_port,
&in[begin_port],
&out->IPv4address.sin_port ) ) )
{
return UPNP_E_INVALID_URL;
}
hostport_size += begin_port; // hostport_size is the offset past the port
#ifdef _WIN32
copy_port_name(max - begin_port, &in[begin_port], port_name);
#endif
} else
hostport_size = host_size; // hostport_size is the offset past the port
//convert to temporary null terminated string
temp_host_name = ( char * )malloc( host_size + 1 );
if( temp_host_name == NULL )
return UPNP_E_OUTOF_MEMORY;
memcpy( temp_host_name, in, host_size );
temp_host_name[host_size] = '\0';
// now temp_host_name has the whole host name, less the port if there is one
//check to see if host name is an ipv4 address
if( ( last_dot != -1 ) && ( last_dot + 1 < host_size )
&& ( isdigit( temp_host_name[last_dot + 1] ) ) ) {
// has a ., so it is a dotted quad
//must be ipv4 address
#ifndef _WIN32
errcode = inet_pton( AF_INET,
temp_host_name, &out->IPv4address.sin_addr );
if( errcode == 1 ) {
out->IPv4address.sin_family = AF_INET;
} else {
out->IPv4address.sin_addr.s_addr = 0;
out->IPv4address.sin_family = AF_INET;
free( temp_host_name );
temp_host_name = NULL;
return UPNP_E_INVALID_URL;
}
#else
saiPtr = (struct sockaddr_in *) &(out->IPv4address);
saiPtr->sin_port = htons(atoi(port_name));
temp = inet_addr(temp_host_name);
saiPtr->sin_addr.S_un.S_addr = inet_addr(temp_host_name);
out->IPv4address.sin_family = AF_INET;
#endif
} else {
// it is not ipv4
int errCode = 0;
//call gethostbyname_r (reentrant form of gethostbyname)
#ifdef _WIN32
errcode = getaddrinfo( temp_host_name, port_name, 0, &addrInfoPtr);
if (errCode == 0 ) {
if ((addrInfoPtr->ai_family == PF_INET) && ( addrInfoPtr->ai_addrlen == 4 )) {
out->IPv4address.sin_addr = *((struct in_addr*)(addrInfoPtr->ai_addr));
out->IPv4address.sin_family = AF_INET;
}
} else {
out->IPv4address.sin_addr.s_addr = 0;
out->IPv4address.sin_family = AF_INET;
free( temp_host_name );
temp_host_name = NULL;
return UPNP_E_INVALID_URL;
}
freeaddrinfo(addrInfoPtr);
#else
errcode = gethostbyname_r( temp_host_name,
&h_buf,
temp_hostbyname_buff,
BUFFER_SIZE, &h, &errcode );
if( errcode == 0 ) {
if( h ) {
if( ( h->h_addrtype == AF_INET ) && ( h->h_length == 4 ) ) {
out->IPv4address.sin_addr =
( *( struct in_addr * )h->h_addr );
out->IPv4address.sin_family = AF_INET;
}
}
} else {
out->IPv4address.sin_addr.s_addr = 0;
out->IPv4address.sin_family = AF_INET;
free( temp_host_name );
temp_host_name = NULL;
return UPNP_E_INVALID_URL;
}
#endif
}
if( temp_host_name ) {
free( temp_host_name );
temp_host_name = NULL;
}
out->text.size = hostport_size;
out->text.buff = in;
return hostport_size;
}
/************************************************************************
* Function : parse_scheme
*
* Parameters :
* char * in ; string of characters representing a scheme
* int max ; maximum number of characters
* token * out ; output parameter whose buffer is filled in with
* the scheme
*
* Description : parses a uri scheme starting at in[0] as defined in
* http://www.ietf.org/rfc/rfc2396.txt (RFC explaining URIs)
* (e.g. "http:" -> scheme= "http").
* Note, string MUST include ':' within the max charcters
*
* Return : int ;
*
* Note :
************************************************************************/
int
parse_scheme( char *in,
int max,
token * out )
{
int i = 0;
out->size = 0;
out->buff = NULL;
if( ( max == 0 ) || ( !isalpha( in[0] ) ) )
return FALSE;
i++;
while( ( i < max ) && ( in[i] != ':' ) ) {
if( !( isalnum( in[i] ) || ( in[i] == '+' ) || ( in[i] == '-' )
|| ( in[i] == '.' ) ) )
return FALSE;
i++;
}
if( i < max ) {
out->size = i;
out->buff = &in[0];
return i;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -