📄 http_client.c
字号:
unsigned short temp=0; while ( (finger<max_ptr) && ( isdigit(*finger) ) ) { temp=temp*10; temp+=(*finger)-'0'; finger++; } *out= htons(temp); return finger-port;}//*************************************************************************//* Name: parse_hostport//*//* 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.//*//* In: char *in , int max (max size to be considered //* to avoid //* running into bad memory)//*//* Out: out->text.size (size of text parsed as host and port)//* Note: out->text.buff points to in. No new memory is created.//*//* Return Codes: length of host port text, out->text.size//* Error Codes: UPNP_E_INVALID_URL (if either host or port can not be //* resolved) //* UPNP_E_OUTOF_MEMORY (if the function ran out//* of memory)//*************************************************************************int parse_hostport( char *in , int max, hostport_type *out){ int i=0; int begin_port; int hostport_size=0; int host_size=0; struct hostent * h; char * temp_host_name; out->IPv4address.sin_port=htons(80); //default port is 80 bzero( &out->IPv4address.sin_zero,8); while ( (i<max) && (in[i]!=':') && (in[i]!='/') && ( (isalnum(in[i])) || (in[i]=='.') || (in[i]=='-') )) i++; host_size=i; if ( (i<max) && (in[i]==':')) { 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; } else hostport_size=host_size; //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'; if ( ( h=gethostbyname(temp_host_name)) && (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); return UPNP_E_INVALID_URL; } free(temp_host_name); out->text.size=hostport_size; out->text.buff=in; return hostport_size; }//*************************************************************************//* Name: parse_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//* In: char *in , int max (max size to be considered //* to avoid //* running into bad memory)//*//* Out: out->size (length of scheme)//* Note: out->buff simply points to in. (no new memory)//* Return Codes: length of scheme//* Error Codes: 0 if scheme is not found //*************************************************************************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; } return FALSE;}//*************************************************************************//* Name: remove_dots//*//* Description: removes ".", and ".." from a path. If a ".." can not//* be resolved (i.e. the .. would go past the root of//* the path) an error is returned. The input IS//* modified in place.)//* In: char *in , int max (max size to be considered //* to avoid //* running into bad memory)//*//* Out: char * in (with ".", and ".." rmeoved from the path)//* Return Codes: UPNP_E_SUCCESS, UPNP_E_OUTOF_MEMORY, UPNP_E_INVALID_URL//* Examples: //* char path[30]="/../hello";//* remove_dots(path, strlen(path)) -> UPNP_E_INVALID_URL//* char path[30]="/./hello";//* remove_dots(path, strlen(path)) -> UPNP_E_SUCCESS, //* in = "/hello"//* char path[30]="/./hello/foo/../goodbye" -> //* UPNP_E_SUCCESS, in = "/hello/goodbye"//*************************************************************************int remove_dots(char *in, int size){ char * copyTo=in; char * copyFrom=in; char * max=in+size; char **Segments=NULL; int lastSegment=-1; Segments=malloc(sizeof(char*) * size); if (Segments==NULL) return UPNP_E_OUTOF_MEMORY; Segments[0]=NULL; while ( (copyFrom<max) && (*copyFrom!='?') && (*copyFrom!='#')) { if ( ((*copyFrom)=='.') && ( (copyFrom==in) || (*(copyFrom-1)=='/') )) { if ( (copyFrom+1==max) || ( *(copyFrom+1)=='/')) { copyFrom+=2; continue; } else if ( ( *(copyFrom+1)=='.') && ( (copyFrom+2==max) || ( *(copyFrom+2)=='/'))) { copyFrom+=3; if (lastSegment>0) { copyTo=Segments[--lastSegment]; } else { free(Segments); DBGONLY(UpnpPrintf(UPNP_CRITICAL,API,__FILE__,__LINE__,"ERROR RESOLVING URL, ../ at ROOT")); return UPNP_E_INVALID_URL; } continue; } } if ( (*copyFrom)=='/') { lastSegment++; Segments[lastSegment]=copyTo+1; } (*copyTo)=(*copyFrom); copyTo++; copyFrom++; } if (copyFrom<max) { while (copyFrom<max) { (*copyTo)=(*copyFrom); copyTo++; copyFrom++; } } (*copyTo)=0; free(Segments); return UPNP_E_SUCCESS;}//*************************************************************************//* Name: resolve_rel_url//*//* Description: resolves a relative url with a base url//* returning a NEW (dynamically allocated with malloc)//* full url. //* if the base_url is NULL, then a copy of rel_url is passed back//* if the rel_url is absolute then a copy of rel_url is passed back//* if neither the base nor the rel_url are Absolute then NULL //* is returned.//* otherwise it tries and resolves the relative url with the //* base as described in: http://www.ietf.org/rfc/rfc2396.txt//* (RFC explaining URIs) //* Note: resolution of '..' is NOT implemented, but '.' is //* resolved //* In: char *base_url, (can be fixed constant string) //* char * rel_url (MUST be allocated with malloc, will be //* freed on success)//*//* Out: Dynamically allocated string (caller must free) //* containing the full absolute url//* Return Codes: //* Error Codes: NULL in case of error //*************************************************************************char * resolve_rel_url( char * base_url, char * rel_url){ uri_type base; uri_type rel; char temp_path='/'; int i=0; char* finger=NULL; char* last_slash=NULL; char * out=NULL; char * out_finger=NULL; if ( base_url && rel_url) { out = (char *) malloc(strlen(base_url) + strlen(rel_url)+2); out_finger=out; } else { if (rel_url) return strdup(rel_url); else return NULL; } if (out==NULL) { return NULL; } if ( (parse_uri(rel_url,strlen(rel_url),&rel))==HTTP_SUCCESS ) { if (rel.type==ABSOLUTE) { strcpy(out,rel_url); } else { if ( (parse_uri(base_url, strlen(base_url),&base)==HTTP_SUCCESS) && (base.type==ABSOLUTE) ) { if (strlen(rel_url)==0) { strcpy(out,base_url); } else { memcpy(out,base.scheme.buff,base.scheme.size); out_finger+=base.scheme.size; (*out_finger)=':'; out_finger++; if (rel.hostport.text.size>0) { sprintf(out_finger,"%s",rel_url); } else { if (base.hostport.text.size>0) { memcpy(out_finger,"//",2); out_finger+=2; memcpy(out_finger,base.hostport.text.buff,base.hostport.text.size); out_finger+=base.hostport.text.size; } if (rel.path_type==ABS_PATH) { strcpy(out_finger,rel_url); } else { if (base.pathquery.size==0) { base.pathquery.size=1; base.pathquery.buff=&temp_path; } finger =out_finger; last_slash=finger; i=0; while ( (i<base.pathquery.size) && (base.pathquery.buff[i]!='?')) { (*finger)=base.pathquery.buff[i]; if (base.pathquery.buff[i]=='/') last_slash=finger+1; i++; finger++; } i=0; strcpy(last_slash,rel_url); if (remove_dots(out_finger, strlen(out_finger))!=UPNP_E_SUCCESS) { free(out); //free(rel_url); return NULL; } } } } } else { free(out); //free(rel_url); return NULL; } } } else { free(out); //free(rel_url); return NULL; } //free(rel_url); return out; }//*************************************************************************//* Name: parse_uri//*//* Description: parses a uri //* as defined in http://www.ietf.org/rfc/rfc2396.txt//* (RFC explaining URIs)//* handles absolute, relative, and opaque uris//* Parses into the following pieces://* scheme, hostport, pathquery, fragment//* (path and query are treated as one token)//* Caller should check for the pieces they require.//* In: char *in , int max (max size to be considered to avoid //* running into bad memory)//*//* Out: uri_type * out (memory allocated by caller)//* Each of the pieces that are present are filled in.//* Plus the type of uri (ABSOULTE, RELATIVE), and type of //* path (ABS_PATH, REL_PATH, OPAQUE_PART)//* Return Codes: HTTP_SUCCESS//* Error Codes: returns the error code returned from//* parse_hostport if an address is expected but not resolved //*************************************************************************int parse_uri( char * in, int max, uri_type * out){ int begin_path=0; int begin_hostport=0; int begin_fragment=0; if ( (begin_hostport=parse_scheme(in, max,&out->scheme) )) { out->type=ABSOLUTE; out->path_type=OPAQUE_PART; begin_hostport++; } else { out->type=RELATIVE; out->path_type=REL_PATH; } if ( ( (begin_hostport+1) <max) && (in[begin_hostport]=='/') && (in[begin_hostport+1]=='/')) { begin_hostport+=2; if ( ( begin_path=parse_hostport(&in[begin_hostport], max-begin_hostport, &out->hostport)) >= 0 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -