parse.c
上传用户:seven77cht
上传日期:2007-01-04
资源大小:486k
文件大小:25k
- /***************************************
- $Header: /home/amb/wwwoffle/RCS/parse.c 2.65 2000/01/19 18:58:08 amb Exp $
- WWWOFFLE - World Wide Web Offline Explorer - Version 2.5d.
- Functions to parse the HTTP requests.
- ******************/ /******************
- Written by Andrew M. Bishop
- This file Copyright 1996,97,98,99,2000 Andrew M. Bishop
- It may be distributed under the GNU Public License, version 2, or
- any higher version. See section COPYING of the GNU Public license
- for conditions under which this file may be redistributed.
- ***************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <time.h>
- #include <unistd.h>
- #include "wwwoffle.h"
- #include "misc.h"
- #include "proto.h"
- #include "errors.h"
- #include "config.h"
- /*+ The time that the program went online. +*/
- time_t OnlineTime=0;
- /*+ Headers from a request that can be re-used in automatically generated requests. +*/
- static char *reusable_headers[]={"User-Agent",
- "Accept",
- "Accept-Charset",
- "Accept-Language",
- "From",
- "Proxy-Authorization"};
- /*+ Headers that we do not allow the users to censor. +*/
- static char *non_censored_headers[]={"Host",
- "Connection",
- "Proxy-Connection",
- "Authorization"};
- /*+ Headers that are difficult with HTTP/1.1. +*/
- static char *deleted_http11_headers[]={"If-Match",
- "If-None-Match",
- "If-Range",
- "Range",
- "Upgrade",
- "Accept-Encoding"};
- /*+ The headers from the request that are re-usable. +*/
- static Header *reusable_header;
- static int AddToHeaderRaw(Header *head,char *line);
- /*++++++++++++++++++++++++++++++++++++++
- Parse the request to the server.
- char *ParseRequest Returns the URL or NULL if it failed.
- int fd The file descriptor to read the request from.
- Header **request_head Return the header of the request.
- Body **request_body Return the body of the request.
- ++++++++++++++++++++++++++++++++++++++*/
- char *ParseRequest(int fd,Header **request_head,Body **request_body)
- {
- char *url=NULL,*line=NULL;
- int i,length=-1;
- *request_head=NULL;
- *request_body=NULL;
- reusable_header=CreateHeader("GET reusable HTTP/1.0rn",1);
- while((line=read_line_or_timeout(fd,line,SocketTimeout)))
- {
- char *key,*val;
- if(!*request_head) /* first line */
- {
- *request_head=CreateHeader(line,1);
- if(!*(*request_head)->url)
- return(NULL);
- url=(char*)malloc(strlen((*request_head)->url)+1);
- strcpy(url,(*request_head)->url);
- continue;
- }
- if(!AddToHeaderRaw(*request_head,line))
- break;
- key=(*request_head)->key[(*request_head)->n-1];
- val=(*request_head)->val[(*request_head)->n-1];
- /* Find the content length */
- if(!strcasecmp("Content-Length",key))
- length=atoi(val);
- /* Find re-usable headers (for recursive requests) */
- for(i=0;i<sizeof(reusable_headers)/sizeof(char*);i++)
- if(!strcmp(reusable_headers[i],key))
- AddToHeader(reusable_header,key,val);
- /* Check for firewall operation. */
- if(!strcasecmp("Host",key) && url && *url=='/')
- {
- char *oldurl=url;
- url=(char*)malloc(strlen(url)+strlen(val)+8);
- strcpy(url,"http://");
- strcat(url,val);
- strcat(url,oldurl);
- free(oldurl);
- }
- /* Check for passwords */
- if(!strcasecmp("Authorization",key))
- {
- char *p=val,*copy,*userpass;
- int l;
- while(*p!=' ') p++;
- while(*p==' ') p++;
- userpass=URLEncodePassword(Base64Decode(p,&l));
- p=url;
- if(*url=='/')
- {
- char *localhost=GetLocalHost(1);
- copy=(char*)malloc(strlen(url)+strlen(userpass)+strlen(localhost)+10);
- strcpy(copy,"http://");
- strcat(copy,userpass);
- strcat(copy,"@");
- strcat(copy,localhost);
- }
- else
- {
- copy=(char*)malloc(strlen(url)+strlen(userpass)+2);
- while(*p!=':') p++; p++;
- while(*p=='/') p++;
- strncpy(copy,url,p-url);
- copy[p-url]=0;
- strcat(copy,userpass);
- strcat(copy,"@");
- }
- strcat(copy,p);
- free(url);
- url=copy;
- }
- }
- if(line)
- free(line);
- if(!*request_head)
- return(NULL);
- if(!strcmp("POST",(*request_head)->method) ||
- !strcmp("PUT",(*request_head)->method))
- {
- if(length==-1)
- {free(url);return(NULL);}
- *request_body=CreateBody(length);
- if(length)
- {
- int m,l=length;
- do
- {
- m=read_data_or_timeout(fd,&(*request_body)->content[length-l],l,SocketTimeout);
- }
- while(m>0 && (l-=m));
- if(l)
- {free(url);return(NULL);}
- empty_buffer(fd);
- }
- (*request_body)->content[length]=0;
- url=(char*)realloc((void*)url,strlen(url)+40);
- if(strchr(url,'?'))
- {
- char *from=url+strlen(url),*to=from+1;
- while(*from!='?')
- *to--=*from--;
- *to='!';
- }
- else
- strcat(url,"?");
- sprintf(url+strlen(url),"!%s:%s.%08lx",(*request_head)->method,MakeHash((*request_body)->content),time(NULL));
- }
- return(url);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Modify the request to ask for changes since the spooled file.
- int RequestChanges Returns 1 if the file needs changes made, 0 if not, or -1 in case of an error.
- int fd The file descriptor of the spooled file.
- Header *request_head The head of the HTTP request to modify.
- ++++++++++++++++++++++++++++++++++++++*/
- int RequestChanges(int fd,Header *request_head)
- {
- struct stat buf;
- int status,retval=0;
- Header *spooled_head=NULL;
- status=ParseReply(fd,NULL,&spooled_head);
- if(status==0 || fstat(fd,&buf))
- {
- PrintMessage(Debug,"Requesting URL (Empty or no status).");
- retval=1;
- }
- else if(status<200 || status>=400)
- {
- PrintMessage(Debug,"Requesting URL (Error status).");
- retval=1;
- }
- else
- {
- char *expires,*head,*val;
- if(RequestExpired && (expires=GetHeader(spooled_head,"Expires",NULL)))
- {
- time_t since=DateToTimeT(expires);
- if(since<=time(NULL))
- {
- PrintMessage(Debug,"Requesting URL (Expiry date of '%s').",expires);
- retval=1;
- }
- }
- if(retval==0)
- if(RequestNoCache && (GetHeader(spooled_head,head="Pragma" ,val="no-cache") ||
- GetHeader(spooled_head,head="Cache-Control",val="no-cache")))
- {
- PrintMessage(Debug,"Requesting URL (No cache header '%s: %s').",head,val);
- retval=1;
- }
- if(retval==0)
- if(RequestChangedOnce && buf.st_mtime>OnlineTime)
- {
- PrintMessage(Debug,"Not requesting URL (Only once per online session).");
- retval=0;
- }
- else if((time(NULL)-buf.st_mtime)<RequestChanged)
- {
- PrintMessage(Debug,"Not requesting URL (Last changed %d seconds ago).",time(NULL)-buf.st_mtime);
- retval=0;
- }
- else
- {
- AddToHeader(request_head,"If-Modified-Since",RFC822Date(buf.st_mtime,1));
- PrintMessage(Debug,"Requesting URL (Making a conditional request).");
- retval=1;
- }
- }
- if(spooled_head)
- FreeHeader(spooled_head);
- return(retval);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Return the location that the URL has been moved to.
- char *MovedLocation Returns the new URL.
- URL *Url The original URL.
- Header *reply_head The head of the original HTTP reply.
- ++++++++++++++++++++++++++++++++++++++*/
- char *MovedLocation(URL *Url,Header *reply_head)
- {
- char *location;
- char *new;
- location=GetHeader(reply_head,"Location",NULL);
- if(!location)
- return(NULL);
- new=LinkURL(Url,location);
- if(new==location)
- {
- new=(char*)malloc(strlen(location)+1);
- strcpy(new,location);
- }
- return(new);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Create a new request for a page.
- Header *RequestURL Ask for a page.
- URL *Url The URL to get.
- char *referer The Refering URL or NULL if none.
- ++++++++++++++++++++++++++++++++++++++*/
- Header *RequestURL(URL *Url,char *referer)
- {
- char *top=(char*)malloc(strlen(Url->name)+32);
- Header *new;
- int i;
- sprintf(top,"GET %s HTTP/1.0rn",Url->name);
- new=CreateHeader(top,1);
- free(top);
- if(Url->user)
- {
- char *userpass=(char*)malloc(strlen(Url->user)+(Url->pass?strlen(Url->pass):0)+2);
- char *auth=(char*)malloc((strlen(Url->user)+(Url->pass?strlen(Url->pass):0))*2+16);
- strcpy(userpass,Url->user);
- strcat(userpass,":");
- if(Url->pass)
- strcat(userpass,Url->pass);
- sprintf(auth,"Basic %s",Base64Encode(userpass,strlen(userpass)));
- AddToHeader(new,"Authorization",auth);
- free(userpass);
- free(auth);
- }
- if(referer)
- AddToHeader(new,"Referer",referer);
- if(reusable_header->n)
- for(i=0;i<reusable_header->n;i++)
- AddToHeader(new,reusable_header->key[i],reusable_header->val[i]);
- return(new);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Modify the request taking into account censoring of header and modified URL.
- URL *Url The actual URL.
- Header *request_head The head of the HTTP request possibly with a different URL.
- ++++++++++++++++++++++++++++++++++++++*/
- void ModifyRequest(URL *Url,Header *request_head)
- {
- int i,j;
- /* Modify the top line of the header. */
- free(request_head->url);
- request_head->url=(char*)malloc(strlen(Url->name)+1);
- strcpy(request_head->url,Url->name);
- /* Remove the false arguments from POST/PUT URLs. */
- if(!strcmp(request_head->method,"POST") ||
- !strcmp(request_head->method,"PUT"))
- {
- char *pling=strstr(request_head->url,"?!");
- char *pling2=strchr(++pling+1,'!');
- if(pling2)
- for(;pling<pling2;pling++)
- *pling=*(pling+1);
- *(pling-1)=0;
- }
- /* Add a host header */
- RemoveFromHeader(request_head,"Host",NULL);
- AddToHeader(request_head,"Host",Url->host);
- /* Add a Connection / Proxy-Connection header */
- RemoveFromHeader(request_head,"Connection",NULL);
- RemoveFromHeader(request_head,"Proxy-Connection",NULL);
- if(!strcmp(request_head->version,"HTTP/1.1"))
- strcpy(request_head->version,"HTTP/1.0");
- AddToHeader(request_head,"Connection","close");
- AddToHeader(request_head,"Proxy-Connection","close");
- /* Check the authorisation header. */
- RemoveFromHeader(request_head,"Authorization",NULL);
- if(Url->user)
- {
- char *userpass=(char*)malloc(strlen(Url->user)+(Url->pass?strlen(Url->pass):0)+2);
- char *auth=(char*)malloc((strlen(Url->user)+(Url->pass?strlen(Url->pass):0))*2+16);
- strcpy(userpass,Url->user);
- strcat(userpass,":");
- if(Url->pass)
- strcat(userpass,Url->pass);
- sprintf(auth,"Basic %s",Base64Encode(userpass,strlen(userpass)));
- AddToHeader(request_head,"Authorization",auth);
- free(userpass);
- free(auth);
- }
- /* Remove some headers */
- for(j=0;j<sizeof(deleted_http11_headers)/sizeof(char*);j++)
- RemoveFromHeader(request_head,deleted_http11_headers[j],NULL);
- RemoveFromHeader(request_head,"Pragma","wwwoffle");
- /* Censor the header */
- for(i=0;i<request_head->n;i++)
- {
- char *censor;
- if(!request_head->key[i])
- continue;
- for(j=0;j<sizeof(non_censored_headers)/sizeof(char*);j++)
- if(!strcasecmp(non_censored_headers[j],request_head->key[i]))
- continue;
- if((censor=CensoredHeader(Url->name,request_head->key[i],request_head->val[i])))
- {
- if(censor!=request_head->val[i])
- {
- PrintMessage(Debug,"CensorRequestHeader replaced '%s: %s' by '%s: %s'.",request_head->key[i],request_head->val[i],request_head->key[i],censor);
- request_head->size+=strlen(censor)-strlen(request_head->val[i]);
- free(request_head->val[i]);
- request_head->val[i]=censor;
- }
- }
- else
- {
- PrintMessage(Debug,"CensorRequestHeader removed '%s: %s'.",request_head->key[i],request_head->val[i]);
- RemoveFromHeader(request_head,request_head->key[i],request_head->val[i]);
- continue;
- }
- if(!strcasecmp("Referer",request_head->key[i]))
- {
- char *pling=strstr(request_head->val[i],"?!");
- if(pling)
- {
- char *pling2=strchr(++pling+1,'!');
- if(pling2)
- for(;pling<pling2;pling++)
- *pling=*(pling+1);
- *(pling-1)=0;
- }
- }
- }
- }
- /*++++++++++++++++++++++++++++++++++++++
- Change the request to one that contains an authorisation string if required.
- char *proxy The name of the proxy.
- Header *request_head The HTTP request head.
- ++++++++++++++++++++++++++++++++++++++*/
- void MakeRequestAuthorised(char *proxy,Header *request_head)
- {
- char *userpass=WhatProxyAuth(proxy);
- RemoveFromHeader(request_head,"Proxy-Authorization",NULL);
- if(userpass)
- {
- char *auth=(char*)malloc(strlen(userpass)*2+8);
- sprintf(auth,"Basic %s",Base64Encode(userpass,strlen(userpass)));
- AddToHeader(request_head,"Proxy-Authorization",auth);
- free(userpass);
- free(auth);
- }
- }
- /*++++++++++++++++++++++++++++++++++++++
- Change the request from one to a proxy to a normal one.
- Header *request_head The head of the HTTP request.
- ++++++++++++++++++++++++++++++++++++++*/
- void MakeRequestNonProxy(Header *request_head)
- {
- char *p=request_head->url,*q=request_head->url;
- /* The URL is already in canonical form because of the ModifyRequest() function. */
- while(*p!=':') /* 'http://' */
- p++;
- p+=3;
- while(*p!='/') /* 'www.host.domain/' */
- p++;
- while(*p)
- *q++=*p++;
- *q=0;
- /* Remove the proxy connection & authorization headers. */
- RemoveFromHeader(request_head,"Proxy-Connection","close");
- RemoveFromHeader(request_head,"Proxy-Authorization",NULL);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Parse the reply from the server.
- int ParseReply Return the numeric status of the reply.
- int fd The file descriptor to read from (or -1 to use the Protocol's method).
- URL *Url The URL that we are reading.
- Header **reply_head Return the head of the HTTP reply.
- ++++++++++++++++++++++++++++++++++++++*/
- int ParseReply(int fd,URL *Url,Header **reply_head)
- {
- char *line=NULL;
- *reply_head=NULL;
- while((fd==-1 && (line=(Url->Protocol->readhead)(line))) ||
- (fd!=-1 && (line=read_line(fd,line))))
- {
- if(!*reply_head) /* first line */
- {
- *reply_head=CreateHeader(line,0);
- if(!*(*reply_head)->version)
- break;
- continue;
- }
- if(!AddToHeaderRaw(*reply_head,line))
- break;
- }
- if(!line)
- return(0);
- free(line);
- if(*reply_head)
- return((*reply_head)->status);
- else
- return(0);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Find the status of a spooled page.
- int SpooledPageStatus Returns the status number.
- URL *Url The URL to check.
- ++++++++++++++++++++++++++++++++++++++*/
- int SpooledPageStatus(URL *Url)
- {
- int spool=OpenWebpageSpoolFile(1,Url);
- int status=0;
- if(spool!=-1)
- {
- char *reply;
- init_buffer(spool);
- reply=read_line(spool,NULL);
- if(reply)
- {
- sscanf(reply,"%*s %d",&status);
- free(reply);
- }
- close(spool);
- }
- return(status);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Modify the reply taking into account censoring of the header.
- Header *reply_head The head of the HTTP reply.
- ++++++++++++++++++++++++++++++++++++++*/
- void ModifyReply(Header *reply_head)
- {
- int i;
- /* Add a Connection / Proxy-Connection header */
- RemoveFromHeader(reply_head,"Connection",NULL);
- RemoveFromHeader(reply_head,"Proxy-Connection",NULL);
- if(!strcmp(reply_head->version,"HTTP/1.1"))
- strcpy(reply_head->version,"HTTP/1.0");
- AddToHeader(reply_head,"Connection","close");
- AddToHeader(reply_head,"Proxy-Connection","close");
- /* Censor the header */
- for(i=0;i<reply_head->n;i++)
- {
- int j;
- char *censor;
- if(!reply_head->key[i])
- continue;
- for(j=0;j<sizeof(non_censored_headers)/sizeof(char*);j++)
- if(!strcasecmp(non_censored_headers[j],reply_head->key[i]))
- continue;
- if((censor=CensoredHeader(NULL,reply_head->key[i],reply_head->val[i])))
- {
- if(censor!=reply_head->val[i])
- {
- PrintMessage(Debug,"CensorReplyHeader replaced '%s: %s' by '%s: %s'.",reply_head->key[i],reply_head->val[i],reply_head->key[i],censor);
- reply_head->size+=strlen(censor)-strlen(reply_head->val[i]);
- free(reply_head->val[i]);
- reply_head->val[i]=censor;
- }
- }
- else
- {
- PrintMessage(Debug,"CensorReplyHeader removed '%s: %s'.",reply_head->key[i],reply_head->val[i]);
- RemoveFromHeader(reply_head,reply_head->key[i],reply_head->val[i]);
- }
- }
- }
- /*++++++++++++++++++++++++++++++++++++++
- Create a new Header structure.
- Header *CreateHeader Returns the new header structure.
- char *line The top line in the original header.
- int type The type of header, request=1, reply=0;
- ++++++++++++++++++++++++++++++++++++++*/
- Header *CreateHeader(char *line,int type)
- {
- Header *new=(Header*)malloc(sizeof(*new));
- char *p=(char*)malloc(strlen(line)+1),*oldp=p;
- char *method="",*url="",*note="",*version="";
- int status=0;
- /* Parse the original header. */
- strcpy(p,line);
- new->type=type;
- if(type==1)
- {
- /* GET http://www/xxx HTTP/1.0rn */
- method=p;
- while(*p && !isspace(*p)) /* ^ */
- p++;
- if(!*p) goto eol_req;
- *p++=0;
- while(*p && isspace(*p)) /* ^ */
- p++;
- if(!*p) goto eol_req;
- url=p;
- while(*p && !isspace(*p)) /* ^ */
- p++;
- if(!*p) goto eol_req;
- *p++=0;
- while(*p && isspace(*p)) /* ^ */
- p++;
- if(!*p) goto eol_req;
- version=p;
- while(*p && !isspace(*p)) /* ^ */
- p++;
- *p=0;
- eol_req:
- if(!*version)
- version="HTTP/1.0";
- new->method=(char*)malloc(strlen(method)+1);
- strcpy(new->method,method);
- new->url=(char*)malloc(strlen(url)+1);
- strcpy(new->url,url);
- for(p=new->method;*p;p++)
- *p=toupper(*p);
- new->status=0;
- new->note=NULL;
- new->size=strlen(new->method)+strlen(new->url);
- }
- else
- {
- /* HTTP/1.1 200 OK or somethingrn */
- version=p;
- while(*p && !isspace(*p)) /* ^ */
- p++;
- if(!*p) goto eol_rep;
- *p++=0;
- while(*p && isspace(*p)) /* ^ */
- p++;
- if(!*p) goto eol_rep;
- status=atoi(p);
- while(*p && !isspace(*p)) /* ^ */
- p++;
- if(!*p) goto eol_rep;
- *p++=0;
- while(*p && isspace(*p)) /* ^ */
- p++;
- if(!*p) goto eol_rep;
- note=p;
- while(*p && !iscntrl(*p)) /* ^ */
- p++;
- *p=0;
- eol_rep:
- new->method=NULL;
- new->url=NULL;
- new->status=status%1000;
- new->note=(char*)malloc(strlen(note)+1);
- strcpy(new->note,note);
- new->size=strlen(new->note)+3; /* 3 = strlen(status) */
- }
- new->version=(char*)malloc(strlen(version)+1);
- strcpy(new->version,version);
- for(p=new->version;*p;p++)
- *p=toupper(*p);
- new->size+=strlen(new->version)+4; /* 4 = 2*' ' + 'rn' */
- new->size+=2; /* 2 = 'rn' */
- new->n=0;
- new->key=NULL;
- new->val=NULL;
- free(oldp);
- return(new);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Add a specified key and value to the header structure.
- Header *head The header structure to add to.
- char *key The key to add.
- char *val The value to add.
- ++++++++++++++++++++++++++++++++++++++*/
- void AddToHeader(Header *head,char *key,char *val)
- {
- int i;
- head->size+=strlen(key)+strlen(val)+4;
- if(head->key)
- for(i=0;i<head->n;i++)
- if(!head->key[i])
- {
- head->key[i]=(char*)malloc(strlen(key)+1);
- strcpy(head->key[i],key);
- head->val[i]=(char*)malloc(strlen(val)+1);
- strcpy(head->val[i],val);
- return;
- }
- if(head->key)
- {
- head->key=(char**)realloc((void*)head->key,sizeof(char*)*(head->n+1));
- head->val=(char**)realloc((void*)head->val,sizeof(char*)*(head->n+1));
- }
- else
- {
- head->key=(char**)malloc(sizeof(char*)*8);
- head->val=(char**)malloc(sizeof(char*)*8);
- }
- head->key[head->n]=(char*)malloc(strlen(key)+1);
- strcpy(head->key[head->n],key);
- head->val[head->n]=(char*)malloc(strlen(val)+1);
- strcpy(head->val[head->n],val);
- head->n++;
- }
- /*++++++++++++++++++++++++++++++++++++++
- Add a raw line to a header.
- int AddToHeaderRaw Returns 1 if OK, else 0.
- Header *head The header to add the line to.
- char *line The raw line of data.
- ++++++++++++++++++++++++++++++++++++++*/
- static int AddToHeaderRaw(Header *head,char *line)
- {
- char *key,*val,*r=line+strlen(line)-1;
- /* trim line */
- while(r>line && isspace(*r))
- r--;
- /* last line */
- if(r==line)
- return(0);
- /* split line */
- key=line;
- val=line;
- while(*val && *val!=':')
- val++;
- if(!*val)
- return(0);
- *++r=0;
- *val++=0;
- while(*val && isspace(*val))
- val++;
- /* Add to the header */
- AddToHeader(head,key,val);
- return(1);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Remove the specified key and value pair from a header structure.
- Header *head The header to remove from.
- char* key The key to look for and remove.
- char *val The value to look for and remove.
- ++++++++++++++++++++++++++++++++++++++*/
- void RemoveFromHeader(Header *head,char* key,char *val)
- {
- int i;
- for(i=0;i<head->n;i++)
- {
- if(!head->key[i])
- continue;
- if(!strcasecmp(head->key[i],key) &&
- (!val || !strncasecmp(head->val[i],val,strlen(val))))
- {
- head->size-=strlen(head->key[i])+strlen(head->val[i])+4;
- free(head->key[i]);
- head->key[i]=NULL;
- free(head->val[i]);
- head->val[i]=NULL;
- }
- }
- }
- /*++++++++++++++++++++++++++++++++++++++
- Search through a HTTP header for a specified key and value pair.
- char *GetHeader Returns the value for the header key or NULL if none.
- Header *head The header to search through.
- char* key The key to look for.
- char *val The value to look for.
- ++++++++++++++++++++++++++++++++++++++*/
- char *GetHeader(Header *head,char* key,char *val)
- {
- int i;
- for(i=0;i<head->n;i++)
- {
- if(!head->key[i])
- continue;
- if(!strcasecmp(head->key[i],key) &&
- (!val || !strncasecmp(head->val[i],val,strlen(val))))
- return(head->val[i]);
- }
- return(NULL);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Return a string that contains the whole of the header.
- char *HeaderString Returns the header as a string.
- Header *head The header structure to convert.
- ++++++++++++++++++++++++++++++++++++++*/
- char *HeaderString(Header *head)
- {
- char *str;
- int i;
- str=(char*)malloc(head->size+16);
- if(head->type==1)
- {
- strcpy(str,head->method);
- strcat(str," ");
- strcat(str,head->url);
- strcat(str," ");
- strcat(str,head->version);
- }
- else
- {
- if(*head->version)
- {
- strcpy(str,head->version);
- strcat(str," ");
- sprintf(str+strlen(head->version)+1,"%3d",head->status);
- strcat(str," ");
- strcat(str,head->note);
- }
- else
- strcpy(str,"HTTP/1.0 200 OK");
- }
- strcat(str,"rn");
- for(i=0;i<head->n;i++)
- {
- if(!head->key[i])
- continue;
- strcat(str,head->key[i]);
- strcat(str,": ");
- strcat(str,head->val[i]);
- strcat(str,"rn");
- }
- strcat(str,"rn");
- return(str);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Free a header structure.
- Header *head The header structure to free.
- ++++++++++++++++++++++++++++++++++++++*/
- void FreeHeader(Header *head)
- {
- int i;
- if(head->type)
- {
- free(head->method);
- free(head->url);
- }
- else
- free(head->note);
- free(head->version);
- for(i=0;i<head->n;i++)
- {
- if(!head->key[i])
- continue;
- free(head->key[i]);
- free(head->val[i]);
- }
- if(head->n)
- {
- free(head->key);
- free(head->val);
- }
- free(head);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Create a new Body structure.
- Header *CreateBody Returns the new body structure.
- int length The length of the body;
- ++++++++++++++++++++++++++++++++++++++*/
- Body *CreateBody(int length)
- {
- Body *new=(Body*)malloc(sizeof(*new));
- new->length=length;
- new->content=malloc(length+3);
- return(new);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Free a body structure.
- Body *body The body structure to free.
- ++++++++++++++++++++++++++++++++++++++*/
- void FreeBody(Body *body)
- {
- if(body->content)
- free(body->content);
- free(body);
- }