00001 00002 // 00003 // Copyright (c) 2000-2003 Intel Corporation 00004 // All rights reserved. 00005 // 00006 // Redistribution and use in source and binary forms, with or without 00007 // modification, are permitted provided that the following conditions are met: 00008 // 00009 // * Redistributions of source code must retain the above copyright notice, 00010 // this list of conditions and the following disclaimer. 00011 // * Redistributions in binary form must reproduce the above copyright notice, 00012 // this list of conditions and the following disclaimer in the documentation 00013 // and/or other materials provided with the distribution. 00014 // * Neither name of Intel Corporation nor the names of its contributors 00015 // may be used to endorse or promote products derived from this software 00016 // without specific prior written permission. 00017 // 00018 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00019 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00020 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00021 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR 00022 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00023 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00024 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00025 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00026 // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00027 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00028 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 // 00031 00032 #ifndef GENLIB_NET_URI_H 00033 #define GENLIB_NET_URI_H 00034 00035 #ifdef __cplusplus 00036 extern "C" { 00037 #endif 00038 00039 #include <fcntl.h> 00040 #include <string.h> 00041 #include <sys/types.h> 00042 #include <time.h> 00043 #include <errno.h> 00044 #include <ctype.h> 00045 #include <stdlib.h> 00046 #ifndef WIN32 00047 #include <arpa/inet.h> 00048 #include <sys/socket.h> 00049 #include <netinet/in.h> 00050 #include <unistd.h> 00051 #include <netdb.h> 00052 #include <sys/time.h> 00053 #else 00054 #include <time.h> 00055 00056 #define strncasecmp strnicmp 00057 #endif 00058 00059 #include "upnp.h" 00060 //#include <upnp_debug.h> 00061 00062 00063 #define HTTP_DATE_LENGTH 37 // length for HTTP DATE: 00064 //"DATE: Sun, 01 Jul 2000 08:15:23 GMT<cr><lf>" 00065 #define SEPARATORS "()<>@,;:\\\"/[]?={} \t" 00066 #define MARK "-_.!~*'()" 00067 #define RESERVED ";/?:@&=+$,{}" //added {} for compatibility 00068 #define HTTP_SUCCESS 1 00069 00070 #define FALSE 0 00071 #define TAB 9 00072 #define CR 13 00073 #define LF 10 00074 #define SOCKET_BUFFER_SIZE 5000 00075 00076 enum hostType { HOSTNAME, IPv4address }; 00077 enum pathType { ABS_PATH, REL_PATH, OPAQUE_PART }; 00078 #ifndef WIN32 00079 // there is a conflict in windows with other symbols 00080 enum uriType { ABSOLUTE, RELATIVE }; 00081 #else 00082 enum uriType { absolute, relative }; 00083 #endif 00084 00085 /* Buffer used in parsinghttp messages, urls, etc. generally this simply 00086 * holds a pointer into a larger array */ 00087 typedef struct TOKEN { 00088 const char *buff; 00089 int size; 00090 } token; 00091 00092 00093 /* Represents a host port:e.g. :"127.127.0.1:80" 00094 * text is a token pointing to the full string representation */ 00095 typedef struct HOSTPORT { 00096 token text; //full host port 00097 struct sockaddr_in IPv4address; //Network Byte Order 00098 } hostport_type; 00099 00100 /* Represents a URI used in parse_uri and elsewhere */ 00101 typedef struct URI{ 00102 enum uriType type; 00103 token scheme; 00104 enum pathType path_type; 00105 token pathquery; 00106 token fragment; 00107 hostport_type hostport; 00108 } uri_type; 00109 00110 /* Represents a list of URLs as in the "callback" header of SUBSCRIBE 00111 * message in GENA 00112 * char * URLs holds dynamic memory */ 00113 typedef struct URL_LIST { 00114 int size; 00115 char * URLs; //all the urls, delimited by <> 00116 uri_type *parsedURLs; 00117 } URL_list; 00118 00119 00120 /************************************************************************ 00121 * Function : replace_escaped 00122 * 00123 * Parameters : 00124 * char * in ; string of characters 00125 * int index ; index at which to start checking the characters 00126 * int *max ; 00127 * 00128 * Description : Replaces an escaped sequence with its unescaped version 00129 * as in http://www.ietf.org/rfc/rfc2396.txt (RFC explaining URIs) 00130 * Size of array is NOT checked (MUST be checked by caller) 00131 * 00132 * Return : int ; 00133 * 00134 * Note : This function modifies the string. If the sequence is an 00135 * escaped sequence it is replaced, the other characters in the 00136 * string are shifted over, and NULL characters are placed at the 00137 * end of the string. 00138 ************************************************************************/ 00139 int replace_escaped(char * in, int index, int *max); 00140 00141 /************************************************************************ 00142 * Function : copy_URL_list 00143 * 00144 * Parameters : 00145 * URL_list *in ; Source URL list 00146 * URL_list *out ; Destination URL list 00147 * 00148 * Description : Copies one URL_list into another. This includes 00149 * dynamically allocating the out->URLs field (the full string), 00150 * and the structures used to hold the parsedURLs. This memory MUST 00151 * be freed by the caller through: free_URL_list(&out) 00152 * 00153 * Return : int ; 00154 * HTTP_SUCCESS - On Success 00155 * UPNP_E_OUTOF_MEMORY - On Failure to allocate memory 00156 * 00157 * Note : 00158 ************************************************************************/ 00159 int copy_URL_list( URL_list *in, URL_list *out); 00160 00161 /************************************************************************ 00162 * Function : free_URL_list 00163 * 00164 * Parameters : 00165 * URL_list * list ; URL List object 00166 * 00167 * Description : Frees the memory associated with a URL_list. Frees the 00168 * dynamically allocated members of of list. Does NOT free the 00169 * pointer to the list itself ( i.e. does NOT free(list)) 00170 * 00171 * Return : void ; 00172 * 00173 * Note : 00174 ************************************************************************/ 00175 void free_URL_list(URL_list * list); 00176 00177 /************************************************************************ 00178 * Function : print_uri 00179 * 00180 * Parameters : 00181 * uri_type *in ; URI object 00182 * 00183 * Description : Function useful in debugging for printing a parsed uri. 00184 * Compiled out with DBGONLY macro. 00185 * 00186 * Return : void ; 00187 * 00188 * Note : 00189 ************************************************************************/ 00190 DBGONLY(void print_uri( uri_type *in);) 00191 00192 /************************************************************************ 00193 * Function : print_token 00194 * 00195 * Parameters : 00196 * token * in ; 00197 * 00198 * Description : Function useful in debugging for printing a token. 00199 * Compiled out with DBGONLY macro. 00200 * 00201 * Return : void ; 00202 * 00203 * Note : 00204 ************************************************************************/ 00205 void print_token( token * in); 00206 00207 /************************************************************************ 00208 * Function : token_string_casecmp 00209 * 00210 * Parameters : 00211 * token * in1 ; Token object whose buffer is to be compared 00212 * char * in2 ; string of characters to compare with 00213 * 00214 * Description : Compares buffer in the token object with the buffer 00215 * in in2 00216 * 00217 * Return : int ; 00218 * < 0 string1 less than string2 00219 * 0 string1 identical to string2 00220 * > 0 string1 greater than string2 00221 * 00222 * Note : 00223 ************************************************************************/ 00224 int token_string_casecmp( token * in1, char * in2); 00225 00226 /************************************************************************ 00227 * Function : token_string_cmp 00228 * 00229 * Parameters : 00230 * token * in1 ; Token object whose buffer is to be compared 00231 * char * in2 ; string of characters to compare with 00232 * 00233 * Description : Compares a null terminated string to a token (exact) 00234 * 00235 * Return : int ; 00236 * < 0 string1 less than string2 00237 * 0 string1 identical to string2 00238 * > 0 string1 greater than string2 00239 * 00240 * Note : 00241 ************************************************************************/ 00242 int token_string_cmp( token * in1, char * in2); 00243 00244 /************************************************************************ 00245 * Function : token_cmp 00246 * 00247 * Parameters : 00248 * token *in1 ; First token object whose buffer is to be compared 00249 * token *in2 ; Second token object used for the comparison 00250 * 00251 * Description : Compares two tokens 00252 * 00253 * Return : int ; 00254 * < 0 string1 less than string2 00255 * 0 string1 identical to string2 00256 * > 0 string1 greater than string2 00257 * 00258 * Note : 00259 ************************************************************************/ 00260 int token_cmp( token *in1, token *in2); 00261 00262 /************************************************************************ 00263 * Function : parse_port 00264 * 00265 * Parameters : 00266 * int max ; sets a maximum limit 00267 * char * port ; port to be parsed. 00268 * unsigned short * out ; out parameter where the port is parsed 00269 * and converted into network format 00270 * 00271 * Description : parses a port (i.e. '4000') and converts it into a 00272 * network ordered unsigned short int. 00273 * 00274 * Return : int ; 00275 * 00276 * Note : 00277 ************************************************************************/ 00278 int parse_port(int max, const char *port, unsigned short int *out); 00279 00280 /************************************************************************ 00281 * Function : parse_hostport 00282 * 00283 * Parameters : 00284 * char *in ; string of characters representing host and port 00285 * int max ; sets a maximum limit 00286 * hostport_type *out ; out parameter where the host and port 00287 * are represented as an internet address 00288 * 00289 * Description : Parses a string representing a host and port 00290 * (e.g. "127.127.0.1:80" or "localhost") and fills out a 00291 * hostport_type struct with internet address and a token 00292 * representing the full host and port. uses gethostbyname. 00293 * 00294 * Return : int ; 00295 * 00296 * Note : 00297 ************************************************************************/ 00298 int parse_hostport(const char *in, int max, hostport_type *out ); 00299 00300 /************************************************************************ 00301 * Function : remove_escaped_chars 00302 * 00303 * Parameters : 00304 * INOUT char *in ; string of characters to be modified 00305 * INOUT int *size ; size limit for the number of characters 00306 * 00307 * Description : removes http escaped characters such as: "%20" and 00308 * replaces them with their character representation. i.e. 00309 * "hello%20foo" -> "hello foo". The input IS MODIFIED in place. 00310 * (shortened). Extra characters are replaced with NULL. 00311 * 00312 * Return : int ; 00313 * UPNP_E_SUCCESS 00314 * 00315 * Note : 00316 ************************************************************************/ 00317 int remove_escaped_chars(char *in,int *size); 00318 00319 /************************************************************************ 00320 * Function : remove_dots 00321 * 00322 * Parameters : 00323 * char *in ; string of characters from which "dots" have to be 00324 * removed 00325 * int size ; size limit for the number of characters 00326 * 00327 * Description : Removes ".", and ".." from a path. If a ".." can not 00328 * be resolved (i.e. the .. would go past the root of the path) an 00329 * error is returned. The input IS modified in place.) 00330 * 00331 * Return : int ; 00332 * UPNP_E_SUCCESS - On Success 00333 * UPNP_E_OUTOF_MEMORY - On failure to allocate memory 00334 * UPNP_E_INVALID_URL - Failure to resolve URL 00335 * 00336 * Note : 00337 * Examples 00338 * char path[30]="/../hello"; 00339 * remove_dots(path, strlen(path)) -> UPNP_E_INVALID_URL 00340 * char path[30]="/./hello"; 00341 * remove_dots(path, strlen(path)) -> UPNP_E_SUCCESS, 00342 * in = "/hello" 00343 * char path[30]="/./hello/foo/../goodbye" -> 00344 * UPNP_E_SUCCESS, in = "/hello/goodbye" 00345 00346 ************************************************************************/ 00347 int remove_dots(char * in, int size); 00348 00349 /************************************************************************ 00350 * Function : resolve_rel_url 00351 * 00352 * Parameters : 00353 * char * base_url ; Base URL 00354 * char * rel_url ; Relative URL 00355 * 00356 * Description : resolves a relative url with a base url returning a NEW 00357 * (dynamically allocated with malloc) full url. If the base_url is 00358 * NULL, then a copy of the rel_url is passed back if the rel_url 00359 * is absolute then a copy of the rel_url is passed back if neither 00360 * the base nor the rel_url are Absolute then NULL is returned. 00361 * otherwise it tries and resolves the relative url with the base 00362 * as described in: http://www.ietf.org/rfc/rfc2396.txt (RFCs 00363 * explaining URIs) 00364 * : resolution of '..' is NOT implemented, but '.' is resolved 00365 * 00366 * Return : char * ; 00367 * 00368 * Note : 00369 ************************************************************************/ 00370 char * resolve_rel_url( char * base_url, char * rel_url); 00371 00372 /************************************************************************ 00373 * Function : parse_uri 00374 * 00375 * Parameters : 00376 * char * in ; character string containing uri information to be 00377 * parsed 00378 * int max ; maximum limit on the number of characters 00379 * uri_type * out ; out parameter which will have the parsed uri 00380 * information 00381 * 00382 * Description : parses a uri as defined in http://www.ietf.org/rfc/ 00383 * rfc2396.txt (RFC explaining URIs) 00384 * Handles absolute, relative, and opaque uris. Parses into the 00385 * following pieces: scheme, hostport, pathquery, fragment (path and 00386 * query are treated as one token) 00387 * Caller should check for the pieces they require. 00388 * 00389 * Return : int ; 00390 * 00391 * Note : 00392 ************************************************************************/ 00393 int parse_uri(const char * in, int max, uri_type * out); 00394 00395 /************************************************************************ 00396 * Function : parse_uri_and_unescape 00397 * 00398 * Parameters : 00399 * char * in ; 00400 * int max ; 00401 * uri_type * out ; 00402 * 00403 * Description : Same as parse_uri, except that all strings are 00404 * unescaped (%XX replaced by chars) 00405 * 00406 * Return : int ; 00407 * 00408 * Note: This modifies 'pathquery' and 'fragment' parts of the input 00409 ************************************************************************/ 00410 int parse_uri_and_unescape(char * in, int max, uri_type * out); 00411 00412 int parse_token( char * in, token * out, int max_size); 00413 00414 /************************************************************************ 00415 * commented #defines, functions and typdefs * 00416 ************************************************************************/ 00417 00418 /************************************************************************ 00419 * Commented #defines * 00420 ************************************************************************/ 00421 //#define HTTP_E_BAD_URL UPNP_E_INVALID_URL 00422 //#define HTTP_E_READ_SOCKET UPNP_E_SOCKET_READ 00423 //#define HTTP_E_BIND_SOCKET UPNP_E_SOCKET_BIND 00424 //#define HTTP_E_WRITE_SOCKET UPNP_E_SOCKET_WRITE 00425 //#define HTTP_E_CONNECT_SOCKET UPNP_E_SOCKET_CONNECT 00426 //#define HTTP_E_SOCKET UPNP_E_OUTOF_SOCKET 00427 //#define HTTP_E_BAD_RESPONSE UPNP_E_BAD_RESPONSE 00428 //#define HTTP_E_BAD_REQUEST UPNP_E_BAD_REQUEST 00429 //#define HTTP_E_BAD_IP_ADDRESS UPNP_E_INVALID_URL 00430 00431 //#define RESPONSE_TIMEOUT 30 00432 00433 /************************************************************************ 00434 * Commented typedefs * 00435 ************************************************************************/ 00436 //Buffer used to store data read from a socket during an http transfer 00437 //in function read_bytes. 00438 //typedef struct SOCKET_BUFFER{ 00439 // char buff[SOCKET_BUFFER_SIZE]; 00440 // int size; 00441 // struct SOCKET_BUFFER *next; 00442 //} socket_buffer; 00443 00444 //typedef struct HTTP_HEADER { 00445 // token header; 00446 // token value; 00447 // struct HTTP_HEADER * next; 00448 //} http_header; 00449 00450 //typedef struct HTTP_STATUS_LINE{ 00451 // token http_version; 00452 // token status_code; 00453 // token reason_phrase; 00454 //} http_status; 00455 00456 //typedef struct HTTP_REQUEST_LINE { 00457 // token http_version; 00458 // uri_type request_uri; 00459 // token method; 00460 //} http_request; 00461 00462 //Represents a parsed HTTP_MESSAGE head_list is dynamically allocated 00463 //typedef struct HTTP_MESSAGE { 00464 // http_status status; 00465 // http_request request; 00466 // http_header * header_list; 00467 // token content; 00468 //} http_message; 00469 00470 /************************************************************************ 00471 * Commented functions * 00472 ************************************************************************ 00473 00474 EXTERN_C int transferHTTP( char * request, char * toSend, 00475 int toSendSize, char **out, char * Url); 00476 00477 00478 EXTERN_C int transferHTTPRaw( char * toSend, int toSendSize, 00479 char **out, char *URL); 00480 00481 helper function 00482 EXTERN_C int transferHTTPparsedURL( char * request, 00483 char * toSend, int toSendSize, 00484 char **out, uri_type *URL); 00485 00486 assumes that char * out has enough space ( 38 characters) 00487 outputs the current time in the following null terminated string: 00488 "DATE: Sun, Jul 06 2000 08:53:01 GMT\r\n" 00489 EXTERN_C void currentTmToHttpDate(char *out); 00490 00491 EXTERN_C int parse_http_response( char * in, http_message * out, 00492 int max_len); 00493 00494 EXTERN_C int parse_http_request( char * in, http_message *out, 00495 int max_len); 00496 00497 EXTERN_C void print_http_message( http_message * message); 00498 EXTERN_C int search_for_header( http_message * in, 00499 char * header, token *out_value); 00500 00501 EXTERN_C void print_status_line(http_status *in); 00502 EXTERN_C void print_request_line(http_request *in); 00503 EXTERN_C int parse_http_line( char * in, int max_size); 00504 EXTERN_C int parse_not_LWS( char *in, token *out, int max_size); 00505 EXTERN_C int parse_LWS( char * in, int max_size); 00506 00507 EXTERN_C size_t write_bytes(int fd, char * bytes, size_t n, 00508 int timeout); 00509 EXTERN_C void free_http_message(http_message * message); 00510 00511 ************************************************************************/ 00512 00513 #ifdef __cplusplus 00514 } 00515 #endif 00516 00517 #endif // GENLIB_NET_URI_H
1.6.1