... | ... |
@@ -31,8 +31,10 @@ |
31 | 31 |
typedef struct wk_post { |
32 | 32 |
char *name; |
33 | 33 |
char *value; |
34 |
- int isfile; |
|
34 |
+ char *tofile; |
|
35 |
+ int bufid; |
|
35 | 36 |
int filewritten; |
37 |
+ int valueterminated; |
|
36 | 38 |
} wk_post; |
37 | 39 |
|
38 | 40 |
typedef enum wkc_status { |
... | ... |
@@ -59,6 +61,8 @@ typedef struct wk_client { |
59 | 61 |
int sizepost; |
60 | 62 |
int usedpost; |
61 | 63 |
wk_post *post; |
64 |
+ int pendingpost; |
|
65 |
+ int inpostvar; |
|
62 | 66 |
} wk_client; |
63 | 67 |
|
64 | 68 |
typedef struct wk_clientblock { |
... | ... |
@@ -102,8 +106,9 @@ static wk_client *wk_clientacquire(_wk *web); |
102 | 106 |
static int wk_clientrelease(_wk *web, int connid); |
103 | 107 |
static wk_client *wk_clientget(_wk *web, int connid); |
104 | 108 |
static int wk_clientservicereadheader(_wk *web, wk_client *client); |
109 |
+static int wk_clientservicereadpost(_wk *web, wk_client *client); |
|
105 | 110 |
static int wk_postadd(_wk *web, wk_client *client,char *varname, char *tofile); |
106 |
-static int wk_postset(_wk *web, wk_client *client,char *varname, char *value); |
|
111 |
+static int wk_postset(_wk *web, wk_client *client,char *varname, char *data, int datalen); |
|
107 | 112 |
static char *wk_postget(_wk *web, wk_client *client,char *varname, int *isfile); |
108 | 113 |
static int wk_postfree(_wk *web, wk_client *client); |
109 | 114 |
|
... | ... |
@@ -245,6 +250,7 @@ wk_service(wk *paramweb) |
245 | 250 |
wk_close((wk *)web,client->connid); |
246 | 251 |
continue; /* internal error */ |
247 | 252 |
} |
253 |
+ sbuf_discard(in); |
|
248 | 254 |
if(sbuf_unused(in)<=0) { |
249 | 255 |
/* no room for the new data */ |
250 | 256 |
sselect_delread(web->ssel,fd); |
... | ... |
@@ -261,8 +267,13 @@ wk_service(wk *paramweb) |
261 | 267 |
wk_close((wk *) web, client->connid); |
262 | 268 |
continue; |
263 | 269 |
} |
264 |
- } else if(client->status==wkc_post) { |
|
265 |
-#warning TODO |
|
270 |
+ } |
|
271 |
+ if(client->status==wkc_post) { |
|
272 |
+ if(wk_clientservicereadpost(web,client)==-1) { |
|
273 |
+ /* internal error, protocol error or no enough memory */ |
|
274 |
+ wk_close((wk *) web, client->connid); |
|
275 |
+ continue; |
|
276 |
+ } |
|
266 | 277 |
} |
267 | 278 |
} |
268 | 279 |
} |
... | ... |
@@ -871,14 +882,15 @@ wk_clientservicereadheader(_wk *web, wk_client *client) |
871 | 882 |
char *lineend; |
872 | 883 |
char *sep; |
873 | 884 |
wk_uri *uri; |
885 |
+ wk_action action; |
|
874 | 886 |
/* check if we have all the headers */ |
875 | 887 |
if((in=wk_sbufget((wk *)web, client->inbufid))==NULL) |
876 | 888 |
return(-1); /* internal error */ |
877 |
- sbuf_discard(in); |
|
878 | 889 |
if((end=str_findfirstempty(sbuf_ptr(in),sbuf_count(in)))==NULL) { |
890 |
+ sbuf_discard(in); |
|
879 | 891 |
if(sbuf_unused(in)==0) |
880 | 892 |
return(-1); /* header part too long */ |
881 |
- /* uncomplete headers, have to wait for more data */ |
|
893 |
+ /* incomplete headers, have to wait for more data */ |
|
882 | 894 |
return(0); |
883 | 895 |
} |
884 | 896 |
/* get memory for the uri data */ |
... | ... |
@@ -942,44 +954,138 @@ wk_clientservicereadheader(_wk *web, wk_client *client) |
942 | 954 |
/* call the http method */ |
943 | 955 |
client->serviced=1; |
944 | 956 |
client->continuationactive=0; |
945 |
-#warning TODO: wkc_post |
|
946 |
- client->continuationactive=web->callback_http((wk *)web, client->connid, uri, web->userptr); |
|
957 |
+ action=web->callback_http((wk *)web, client->connid, uri, web->userptr); |
|
958 |
+ if(action==wkact_continuation) { |
|
959 |
+ client->serviced=1; |
|
960 |
+ client->continuationactive=1; |
|
961 |
+ client->status=wkc_none; |
|
962 |
+ } else if(action==wkact_post) { |
|
963 |
+ char *lenvar; |
|
964 |
+ char *contenttype; |
|
965 |
+ if(strcmp(client->uri.method,"POST")!=0 || |
|
966 |
+ (lenvar=wk_uri_getheader(&(client->uri),"Content-Length",NULL))==NULL) { |
|
967 |
+ return(-1); /* malformed post */ |
|
968 |
+ } |
|
969 |
+ if((contenttype=wk_uri_getheader(&(client->uri),"Content-Type",NULL))==NULL || |
|
970 |
+ strcmp(contenttype,"application/x-www-form-urlencoded")!=0) { |
|
971 |
+ return(-1); /* unsupported encoding */ |
|
972 |
+ } |
|
973 |
+ while(*lenvar==' ' || *lenvar=='\t') |
|
974 |
+ lenvar++; |
|
975 |
+ client->serviced=1; |
|
976 |
+ client->continuationactive=0; |
|
977 |
+ client->status=wkc_post; |
|
978 |
+ client->pendingpost=atoi(lenvar); |
|
979 |
+ client->inpostvar=-1; |
|
980 |
+ } else { |
|
981 |
+ client->serviced=1; |
|
982 |
+ client->continuationactive=0; |
|
983 |
+ client->status=wkc_none; |
|
984 |
+ } |
|
985 |
+ return(0); |
|
986 |
+} |
|
987 |
+ |
|
988 |
+static int |
|
989 |
+wk_clientservicereadpost(_wk *web, wk_client *client) |
|
990 |
+{ |
|
991 |
+ sbuf *in; |
|
992 |
+ char *buf; |
|
993 |
+ int buflen; |
|
994 |
+ char *sep; |
|
995 |
+ char *start; |
|
996 |
+ char *end; |
|
997 |
+ if((in=wk_sbufget((wk *)web, client->inbufid))==NULL) |
|
998 |
+ return(-1); /* internal error */ |
|
999 |
+ while(sbuf_count(in)>0) { |
|
1000 |
+ if(client->inpostvar==-1) { |
|
1001 |
+ sbuf_discard(in); |
|
1002 |
+ buf=sbuf_ptr(in); |
|
1003 |
+ buflen=sbuf_count(in); |
|
1004 |
+ if(buflen>client->pendingpost) |
|
1005 |
+ buflen=client->pendingpost; |
|
1006 |
+ if((sep=memchr(buf,'=',buflen))==NULL) |
|
1007 |
+ return(0); /* varname not found */ |
|
1008 |
+ *sep='\0'; |
|
1009 |
+ for(client->inpostvar=0;client->inpostvar<client->usedpost;client->inpostvar++) { |
|
1010 |
+ if(strcmp(client->post[client->inpostvar].name,buf)==0) |
|
1011 |
+ break; |
|
1012 |
+ } |
|
1013 |
+ sbuf_getbytes(in,(sep+1)-buf); |
|
1014 |
+ client->pendingpost-=((sep+1)-buf); |
|
1015 |
+ } |
|
1016 |
+ start=sbuf_ptr(in); |
|
1017 |
+ end=start+sbuf_count(in); |
|
1018 |
+ if((end-start)>client->pendingpost) |
|
1019 |
+ end=start+client->pendingpost; |
|
1020 |
+ if((sep=memchr(start,'&',end-start))!=NULL) |
|
1021 |
+ end=sep; |
|
1022 |
+ if(client->inpostvar>=0) { |
|
1023 |
+ if(client->inpostvar<client->usedpost) |
|
1024 |
+ wk_postset(web,client,client->post[client->inpostvar].name,start,end-start); |
|
1025 |
+ sbuf_getbytes(in,end-start); |
|
1026 |
+ client->pendingpost-=(end-start); |
|
1027 |
+ } |
|
1028 |
+ if(*sep=='&') { |
|
1029 |
+ sbuf_getbytes(in,1); |
|
1030 |
+ client->pendingpost--; |
|
1031 |
+ client->inpostvar=-1; |
|
1032 |
+ } |
|
1033 |
+ } |
|
947 | 1034 |
return(0); |
948 | 1035 |
} |
949 | 1036 |
|
1037 |
+ |
|
950 | 1038 |
static int |
951 | 1039 |
wk_postadd(_wk *web, wk_client *client,char *varname, char *tofile) |
952 | 1040 |
{ |
953 | 1041 |
wk_post *post; |
1042 |
+ sbuf *buf; |
|
1043 |
+ int i; |
|
954 | 1044 |
if(client->post==NULL || client->sizepost==client->usedpost) { |
955 | 1045 |
wk_post *newpost; |
956 | 1046 |
if((newpost=(wk_post *)realloc(client->post,(client->sizepost+POSTBLOCK)*sizeof(wk_post)))==NULL) |
957 | 1047 |
return(-1); /* insufficient memory */ |
958 | 1048 |
client->post=newpost; |
959 | 1049 |
memset(client->post+client->sizepost,0,POSTBLOCK*sizeof(wk_post)); |
1050 |
+ for(i=0;i<POSTBLOCK;i++) |
|
1051 |
+ client->post[client->sizepost+i].bufid=-1; |
|
960 | 1052 |
client->sizepost+=POSTBLOCK; |
961 | 1053 |
} |
962 | 1054 |
post=client->post+client->usedpost; |
963 |
- if((post->name=strdup(varname))==NULL) |
|
1055 |
+ if((post->bufid=wk_sbufacquire((wk *)web))==-1) |
|
964 | 1056 |
return(-1); /* insufficient memory */ |
1057 |
+ if((buf=wk_sbufget((wk *)web,post->bufid))==NULL) { |
|
1058 |
+ post->bufid=-1; |
|
1059 |
+ return(-1); /* internal error */ |
|
1060 |
+ } |
|
1061 |
+ if((strlen(varname)+1)>(sbuf_unused(buf)-2)) { |
|
1062 |
+ wk_sbufrelease((wk *)web,post->bufid),post->bufid=-1; |
|
1063 |
+ return(-1); /* varname too long */ |
|
1064 |
+ } |
|
1065 |
+ post->name=sbuf_ptrunused(buf); |
|
1066 |
+ sbuf_addstr(buf,varname); |
|
965 | 1067 |
if(tofile!=NULL) { |
966 |
- if((post->value=strdup(tofile))==NULL) { |
|
967 |
- free(post->name),post->name=NULL; |
|
968 |
- return(-1); /* insufficient memory */ |
|
1068 |
+ if((strlen(tofile)+1)>(sbuf_unused(buf))) { |
|
1069 |
+ wk_sbufrelease((wk *)web,post->bufid),post->bufid=-1; |
|
1070 |
+ return(-1); /* varname+tofile too long */ |
|
969 | 1071 |
} |
970 |
- } else |
|
971 |
- post->isfile=0; |
|
1072 |
+ post->tofile=sbuf_ptrunused(buf); |
|
1073 |
+ sbuf_addstr(buf,tofile); |
|
1074 |
+ } |
|
1075 |
+ post->value=NULL; |
|
1076 |
+ post->filewritten=0; |
|
1077 |
+ post->valueterminated=0; |
|
972 | 1078 |
return(0); |
973 | 1079 |
} |
974 | 1080 |
|
975 | 1081 |
static int |
976 |
-wk_postset(_wk *web, wk_client *client,char *varname, char *value) |
|
1082 |
+wk_postset(_wk *web, wk_client *client,char *varname, char *data, int datalen) |
|
977 | 1083 |
{ |
978 | 1084 |
int i; |
979 | 1085 |
wk_post *post; |
980 | 1086 |
int fd; |
981 |
- int len; |
|
982 |
- if(varname==NULL || value==NULL) |
|
1087 |
+ sbuf *buf; |
|
1088 |
+ if(varname==NULL || data==NULL || datalen==0) |
|
983 | 1089 |
return(-1); |
984 | 1090 |
for(i=0;i<client->usedpost;i++) { |
985 | 1091 |
if(strcmp(client->post[i].name,varname)==0) |
... | ... |
@@ -988,21 +1094,26 @@ wk_postset(_wk *web, wk_client *client,char *varname, char *value) |
988 | 1094 |
if(i>=client->usedpost) |
989 | 1095 |
return(-1); /* var not found */ |
990 | 1096 |
post=client->post+i; |
991 |
- if(post->isfile) { |
|
992 |
- if((fd=open(post->value,O_CREAT|O_APPEND,0600))==-1) |
|
1097 |
+ if(post->tofile!=NULL) { |
|
1098 |
+ if((fd=open(post->tofile,O_CREAT|O_APPEND,0600))==-1) |
|
993 | 1099 |
return(-1); /* couldn't open file */ |
994 |
- len=strlen(value); |
|
995 |
- if(write(fd,value,len)!=len) { |
|
1100 |
+ if(write(fd,data,datalen)!=datalen) { |
|
996 | 1101 |
close(fd),fd=-1; |
997 |
- return(-1); /* couldn't open file */ |
|
1102 |
+ return(-1); /* couldn't write all data */ |
|
998 | 1103 |
} |
999 | 1104 |
close(fd),fd=-1; |
1000 | 1105 |
post->filewritten=1; |
1001 | 1106 |
} else { |
1002 |
- if(post->value!=NULL) |
|
1003 |
- free(post->value),post->value=NULL; |
|
1004 |
- if((post->value=strdup(value))==NULL) |
|
1005 |
- return(-1); |
|
1107 |
+ if((buf=wk_sbufget((wk *)web,post->bufid))==NULL) { |
|
1108 |
+ post->bufid=-1; |
|
1109 |
+ return(-1); /* internal error */ |
|
1110 |
+ } |
|
1111 |
+ if(post->value==NULL) |
|
1112 |
+ post->value=sbuf_ptrunused(buf); |
|
1113 |
+ if(datalen>(sbuf_unused(buf)-1)) |
|
1114 |
+ datalen=sbuf_unused(buf)-1; |
|
1115 |
+ sbuf_add(buf,data,datalen); |
|
1116 |
+ post->valueterminated=0; |
|
1006 | 1117 |
} |
1007 | 1118 |
return(0); |
1008 | 1119 |
} |
... | ... |
@@ -1012,6 +1123,7 @@ wk_postget(_wk *web, wk_client *client,char *varname, int *isfile) |
1012 | 1123 |
{ |
1013 | 1124 |
int i; |
1014 | 1125 |
wk_post *post; |
1126 |
+ sbuf *buf; |
|
1015 | 1127 |
if(varname==NULL) |
1016 | 1128 |
return(NULL); |
1017 | 1129 |
for(i=0;i<client->usedpost;i++) { |
... | ... |
@@ -1021,10 +1133,23 @@ wk_postget(_wk *web, wk_client *client,char *varname, int *isfile) |
1021 | 1133 |
if(i>=client->usedpost) |
1022 | 1134 |
return(NULL); /* var not found */ |
1023 | 1135 |
post=client->post+i; |
1136 |
+ /* file post */ |
|
1024 | 1137 |
if(isfile!=NULL) |
1025 |
- *isfile=post->isfile; |
|
1026 |
- if(post->isfile && !post->filewritten) |
|
1027 |
- return(NULL); |
|
1138 |
+ *isfile=(post->tofile!=NULL)?1:0; |
|
1139 |
+ if(post->tofile) { |
|
1140 |
+ if(!post->filewritten) |
|
1141 |
+ return(NULL); |
|
1142 |
+ return(post->tofile); |
|
1143 |
+ } |
|
1144 |
+ /* buffer post */ |
|
1145 |
+ if((buf=wk_sbufget((wk *)web,post->bufid))==NULL) |
|
1146 |
+ return(NULL); /* internal error */ |
|
1147 |
+ if(!post->valueterminated) { |
|
1148 |
+ if(sbuf_unused(buf)<1) |
|
1149 |
+ return(NULL); /* internal error */ |
|
1150 |
+ *(sbuf_ptrunused(buf))='\0'; |
|
1151 |
+ post->valueterminated=1; |
|
1152 |
+ } |
|
1028 | 1153 |
return(post->value); |
1029 | 1154 |
} |
1030 | 1155 |
|
... | ... |
@@ -1032,12 +1157,11 @@ static int |
1032 | 1157 |
wk_postfree(_wk *web, wk_client *client) |
1033 | 1158 |
{ |
1034 | 1159 |
int i; |
1160 |
+ wk_post *post; |
|
1035 | 1161 |
for(i=0;i<client->usedpost;i++) { |
1036 |
- if(client->post[i].name!=NULL) |
|
1037 |
- free(client->post[i].name),client->post[i].name=NULL; |
|
1038 |
- if(client->post[i].value!=NULL) |
|
1039 |
- free(client->post[i].value),client->post[i].value=NULL; |
|
1040 |
- client->post[i].isfile=0; |
|
1162 |
+ post=client->post+i; |
|
1163 |
+ if(post->bufid!=-1) |
|
1164 |
+ wk_sbufrelease((wk *)web,post->bufid),post->bufid=-1; |
|
1041 | 1165 |
} |
1042 | 1166 |
if(client->post!=NULL) { |
1043 | 1167 |
client->usedpost=0; |