00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef _WIN32
00026 #pragma warning(disable:4786)
00027 #include <windows.h>
00028 #endif
00029 #include <stdio.h>
00030 #include <string.h>
00031 #include <stdlib.h>
00032 #include <sys/types.h>
00033 #ifdef WIN32
00034 #else
00035 #include <unistd.h>
00036 #include <sys/time.h>
00037 #include <sys/socket.h>
00038 #endif
00039
00040
00041 #include "Parse.h"
00042 #include "Form.h"
00043
00044
00045
00046
00047
00048
00049
00050
00051 #define DEB(x)
00052
00053 namespace Cgi {
00054
00055
00056
00057
00058
00059 Form::Form(FILE *infil )
00060 :m_strBoundary(NULL)
00061 ,raw(false)
00062 {
00063 CGI *cgi = NULL;
00064 char *c_t = getenv("CONTENT_TYPE");
00065 char *c_l = getenv("CONTENT_LENGTH");
00066 int extra = 2;
00067 char name[200];
00068 char slask[8888];
00069
00070
00071 m_current = m_cgi.end();
00072 *name = 0;
00073
00074 if (c_t && !strncmp(c_t, "multipart/form-data",19))
00075 {
00076 Parse pa(c_t,";=");
00077 char *tempcmp = NULL;
00078 int tc = 0;
00079 int l = 0;
00080 DEB( fprintf(fil,"Form:: multipart/form-data<br>\n");)
00081 pa.getword(slask);
00082 while (*slask)
00083 {
00084 DEB( fprintf(fil,"Content-type parse: '%s'\n",slask);)
00085 if (!strcmp(slask,"boundary"))
00086 {
00087 m_strBoundary = new char[200];
00088 pa.getword(m_strBoundary);
00089 l = strlen(m_strBoundary);
00090 tempcmp = new char[l + extra];
00091 }
00092
00093 pa.getword(slask);
00094 }
00095 if (m_strBoundary)
00096 {
00097 char content_type[200];
00098 char current_name[200];
00099 char current_filename[200];
00100 DEB( fprintf(fil,"Form:: boundary = '%s'<br>\n",m_strBoundary);)
00101 fgets(slask, 200, infil);
00102 while (!feof(infil))
00103 {
00104 while (strlen(slask) && (slask[strlen(slask) - 1] == 13 || slask[strlen(slask) - 1] == 10))
00105 slask[strlen(slask) - 1] = 0;
00106 *content_type = 0;
00107 *current_name = 0;
00108 *current_filename = 0;
00109 if ((strstr(slask,m_strBoundary) || strstr(m_strBoundary,slask)) && strcmp(slask, m_strBoundary))
00110 {
00111 strcpy(m_strBoundary, slask);
00112 l = strlen(m_strBoundary);
00113 delete[] tempcmp;
00114 tempcmp = new char[l + extra];
00115 }
00116 if (!strcmp(slask, m_strBoundary))
00117 {
00118
00119 fgets(slask, 200, infil);
00120 while (strlen(slask) && (slask[strlen(slask) - 1] == 13 || slask[strlen(slask) - 1] == 10))
00121 slask[strlen(slask) - 1] = 0;
00122 while (!feof(infil) && *slask)
00123 {
00124 DEB( fprintf(fil,"Field header: '%s'\n",slask);)
00125 Parse pa(slask,";");
00126 pa.getword(slask);
00127 if (!strcmp(slask,"Content-type:"))
00128 {
00129 pa.getword(content_type);
00130 }
00131 else
00132 if (!strcmp(slask,"Content-Disposition:"))
00133 {
00134 pa.getword(slask);
00135 if (!strcmp(slask,"form-data"))
00136 {
00137 DEB( fprintf(fil,"Form:: Content-Disposition: form-data;<br>\n");)
00138 pa.EnableQuote(true);
00139 pa.getword(slask);
00140 while (*slask)
00141 {
00142 Parse pa2(slask,"=");
00143 pa2.getword(name);
00144 pa2.getrest(slask);
00145 if (!strcmp(name,"name"))
00146 {
00147 if (*slask == '"')
00148 {
00149 strcpy(current_name, slask + 1);
00150 current_name[strlen(current_name) - 1] = 0;
00151 }
00152 else
00153 {
00154 strcpy(current_name,slask);
00155 }
00156 DEB( fprintf(fil,"Form:: name = '%s'<br>\n",current_name);)
00157 }
00158 else
00159 if (!strcmp(name,"filename"))
00160 {
00161 if (*slask == '"')
00162 {
00163 strcpy(current_filename, slask + 1);
00164 current_filename[strlen(current_filename) - 1] = 0;
00165 }
00166 else
00167 {
00168 strcpy(current_filename,slask);
00169 }
00170 DEB( fprintf(fil,"Form:: filename = '%s'<br>\n",current_filename);)
00171 int x = -1;
00172 for (int i = 0; i < (int)strlen(current_filename); i++)
00173 {
00174 if (current_filename[i] == '/' || current_filename[i] == '\\')
00175 x = i + 1;
00176 }
00177 if (x > -1)
00178 {
00179 memmove(current_filename,current_filename + x,strlen(current_filename + x) + 1);
00180 }
00181 }
00182 pa.getword(slask);
00183 }
00184 }
00185 }
00186
00187 fgets(slask, 200, infil);
00188 while (strlen(slask) && (slask[strlen(slask) - 1] == 13 || slask[strlen(slask) - 1] == 10))
00189 slask[strlen(slask) - 1] = 0;
00190 }
00191
00192 if (!*current_filename)
00193 {
00194 std::string val;
00195 fgets(slask,1000,infil);
00196 while (!feof(infil) && strncmp(slask,m_strBoundary,strlen(m_strBoundary)))
00197 {
00198 DEB( fprintf(fil," * Content: %s",slask);)
00199 val += slask;
00200 fgets(slask,1000,infil);
00201 }
00202 DEB( fprintf(fil," * End of Content: %s",slask);)
00203
00204 while (val.size() && (val[val.size() - 1] == 13 || val[val.size() - 1] == 10))
00205 {
00206 val = val.substr(0,val.size() - 1);
00207 }
00208 cgi = new CGI;
00209 cgi -> name = new char[strlen(current_name) + 1];
00210 strcpy(cgi -> name,current_name);
00211 cgi -> value = new char[val.size() + 1];
00212 strcpy(cgi -> value,val.c_str() );
00213 cgi -> path = NULL;
00214
00215 m_cgi.push_back(cgi);
00216 }
00217 else
00218 if (*current_filename)
00219 {
00220 DEB( fprintf(fil,"Form:: save file<br>\n");)
00221
00222 FILE *fil;
00223 int out = 0;
00224 char c;
00225 char fn[1000];
00226 #ifdef WIN32
00227 {
00228 char tmp_path[1000];
00229 ::GetTempPath(1000, tmp_path);
00230 if (tmp_path[strlen(tmp_path) - 1] != '\\')
00231 {
00232 strcat(tmp_path, "\\");
00233 }
00234 sprintf(fn,"%s%s",tmp_path,current_filename);
00235 }
00236 #else
00237 sprintf(fn,"/tmp/%s",current_filename);
00238 #endif
00239 if ((fil = fopen(fn, "wb")) != NULL)
00240 {
00241 fread(&c,1,1,infil);
00242 while (!feof(infil))
00243 {
00244 if (out)
00245 {
00246 fwrite(&tempcmp[tc],1,1,fil);
00247 }
00248 tempcmp[tc] = c;
00249 tc++;
00250 if (tc >= l + extra)
00251 {
00252 tc = 0;
00253 out = 1;
00254 }
00255
00256 if (tc)
00257 {
00258 if (!strncmp(tempcmp + tc + extra, m_strBoundary, l - tc) &&
00259 !strncmp(tempcmp, m_strBoundary + l - tc, tc))
00260 {
00261 break;
00262 }
00263 }
00264 else
00265 {
00266 if (!strncmp(tempcmp + extra, m_strBoundary, l))
00267 {
00268 break;
00269 }
00270 }
00271 fread(&c,1,1,infil);
00272 }
00273 fclose(fil);
00274
00275 cgi = new CGI;
00276 cgi -> name = new char[strlen(current_name) + 1];
00277 strcpy(cgi -> name,current_name);
00278 cgi -> value = new char[strlen(fn) + 1];
00279 strcpy(cgi -> value,fn);
00280 cgi -> path = new char[strlen(fn) + 1];
00281 strcpy(cgi -> path,fn);
00282
00283 m_cgi.push_back(cgi);
00284
00285 strcpy(slask, m_strBoundary);
00286 fgets(slask + strlen(slask), 200, infil);
00287 }
00288 else
00289 {
00290
00291 DEB( fprintf(fil,"Form:: couldn't create '%s'...<br>\n",fn);)
00292 break;
00293 }
00294 }
00295 else
00296 {
00297
00298 DEB( fprintf(fil,"Form:: bad input?<br>\n");)
00299 break;
00300 }
00301 }
00302 else
00303 {
00304
00305 DEB( fprintf(fil,"Form:: end of boundary<br>\n");)
00306 break;
00307 }
00308 DEB( fprintf(fil,"Form:: ready for next field<br>\n");)
00309 }
00310 }
00311 if (tempcmp)
00312 {
00313 delete[] tempcmp;
00314 }
00315 DEB( fprintf(fil,"\n");)
00316 }
00317 else
00318 {
00319 int i = 0;
00320 int cl = c_l ? atoi(c_l) : -1;
00321 char c,chigh,clow;
00322
00323
00324 m_current = m_cgi.end();
00325
00326 *name = 0;
00327
00328 fread(&c,1,1,infil);
00329 cl--;
00330 while (cl >= 0 && !feof(infil))
00331 {
00332 switch (c)
00333 {
00334 case '=':
00335 slask[i] = 0;
00336 i = 0;
00337 strcpy(name,slask);
00338 break;
00339 case '&':
00340 slask[i] = 0;
00341 i = 0;
00342 cgi = new CGI;
00343 cgi -> name = new char[strlen(name) + 1];
00344 strcpy(cgi -> name,name);
00345 cgi -> value = new char[strlen(slask) + 1];
00346 strcpy(cgi -> value,slask);
00347 cgi -> path = NULL;
00348 DEB( fprintf(fil,"\nform '%s' = '%s'<br>\n",name,slask);)
00349
00350 m_cgi.push_back(cgi);
00351 break;
00352 case '+':
00353 slask[i++] = ' ';
00354 break;
00355 case '%':
00356 fread(&chigh,1,1,infil);
00357 cl--;
00358 chigh -= 48;
00359 chigh &= 0xff - 32;
00360 if (chigh > 9)
00361 chigh -= 7;
00362 fread(&clow,1,1,infil);
00363 cl--;
00364 clow -= 48;
00365 clow &= 0xff - 32;
00366 if (clow > 9)
00367 clow -= 7;
00368 slask[i++] = (char)(chigh * 16 + clow);
00369 break;
00370 default:
00371 slask[i++] = c;
00372 break;
00373 }
00374
00375 if (cl > 0)
00376 {
00377 fread(&c,1,1,infil);
00378 }
00379 cl--;
00380 }
00381 slask[i] = 0;
00382 i = 0;
00383 cgi = new CGI;
00384 cgi -> name = new char[strlen(name) + 1];
00385 strcpy(cgi -> name,name);
00386 cgi -> value = new char[strlen(slask) + 1];
00387 strcpy(cgi -> value,slask);
00388 cgi -> path = NULL;
00389 DEB( fprintf(fil,"\nform '%s' = '%s'<br>\n",name,slask);)
00390
00391 m_cgi.push_back(cgi);
00392 }
00393 }
00394
00395
00396
00397
00398 Form::Form(char *buffer,int l)
00399 :m_strBoundary(NULL)
00400 ,raw(false)
00401 {
00402 CGI *cgi = NULL;
00403 char slask[8888];
00404 char name[200];
00405 int i = 0;
00406 char c,chigh,clow;
00407 int ptr = 0;
00408
00409
00410 m_current = m_cgi.end();
00411
00412 *name = 0;
00413
00414 ptr = 0;
00415 while (ptr < l)
00416 {
00417 c = buffer[ptr++];
00418 switch (c)
00419 {
00420 case '=':
00421 slask[i] = 0;
00422 i = 0;
00423 strcpy(name,slask);
00424 break;
00425 case '&':
00426 slask[i] = 0;
00427 i = 0;
00428 cgi = new CGI;
00429 cgi -> name = new char[strlen(name) + 1];
00430 strcpy(cgi -> name,name);
00431 cgi -> value = new char[strlen(slask) + 1];
00432 strcpy(cgi -> value,slask);
00433 cgi -> path = NULL;
00434
00435 m_cgi.push_back(cgi);
00436 break;
00437 case '+':
00438 slask[i++] = ' ';
00439 break;
00440 case '%':
00441 chigh = buffer[ptr++];
00442 chigh -= 48;
00443 chigh &= 0xff - 32;
00444 if (chigh > 9)
00445 chigh -= 7;
00446 clow = buffer[ptr++];
00447 clow -= 48;
00448 clow &= 0xff - 32;
00449 if (clow > 9)
00450 clow -= 7;
00451 slask[i++] = (char)(chigh * 16 + clow);
00452 break;
00453 default:
00454 slask[i++] = c;
00455 break;
00456 }
00457 }
00458 slask[i] = 0;
00459 i = 0;
00460 cgi = new CGI;
00461 cgi -> name = new char[strlen(name) + 1];
00462 strcpy(cgi -> name,name);
00463 cgi -> value = new char[strlen(slask) + 1];
00464 strcpy(cgi -> value,slask);
00465 cgi -> path = NULL;
00466
00467 m_cgi.push_back(cgi);
00468 }
00469
00470 Form::~Form()
00471 {
00472 CGI *cgi = NULL;
00473
00474
00475 for (cgi_v::iterator it = m_cgi.begin(); it != m_cgi.end(); it++)
00476 {
00477 cgi = *it;
00478 delete[] cgi -> name;
00479 delete[] cgi -> value;
00480 if (cgi -> path)
00481 {
00482 unlink(cgi -> path);
00483 delete[] cgi -> path;
00484 }
00485
00486 delete cgi;
00487 }
00488 if (m_strBoundary)
00489 {
00490 delete[] m_strBoundary;
00491 }
00492 }
00493
00494
00495 void Form::EnableRaw(bool b)
00496 {
00497 raw = b;
00498 }
00499
00500
00501 void Form::strcpyval(char *v,char *value,size_t len)
00502 {
00503 *v = 0;
00504 for (size_t i = 0; i < strlen(value); i++)
00505 {
00506 if (value[i] == '<')
00507 {
00508 if (strlen(v) < len - 4)
00509 sprintf(v + strlen(v),"<");
00510 }
00511 else
00512 if (value[i] == '>')
00513 {
00514 if (strlen(v) < len - 4)
00515 sprintf(v + strlen(v),">");
00516 }
00517 else
00518 if (value[i] == '&')
00519 {
00520 if (strlen(v) < len - 5)
00521 sprintf(v + strlen(v),"&");
00522 }
00523 else
00524 {
00525 if (strlen(v) < len - 1)
00526 sprintf(v + strlen(v),"%c",value[i]);
00527 }
00528 }
00529
00530 }
00531
00532
00533
00534
00535 bool Form::getfirst(char *n,short len)
00536 {
00537 m_current = m_cgi.begin();
00538 return getnext(n,len);
00539 }
00540
00541 bool Form::getnext(char *n,short len)
00542 {
00543 if (m_current != m_cgi.end() )
00544 {
00545 CGI *current = *m_current;
00546 strncpy(n,current -> name,len - 1);
00547 n[len - 1] = 0;
00548 m_current++;
00549 return true;
00550 } else
00551 *n = 0;
00552 return false;
00553 }
00554
00555
00556
00557 bool Form::getfirst(char *n,short len,char *v,short vlen)
00558 {
00559 m_current = m_cgi.begin();
00560 return getnext(n,len,v,vlen);
00561 }
00562
00563 bool Form::getnext(char *n,short len,char *v,short vlen)
00564 {
00565 if (m_current != m_cgi.end() )
00566 {
00567 CGI *current = *m_current;
00568 strncpy(n,current -> name,len - 1);
00569 n[len - 1] = 0;
00570 if (raw)
00571 {
00572 strncpy(v,current -> value,vlen - 1);
00573 v[vlen - 1] = 0;
00574 }
00575 else
00576 {
00577 strcpyval(v,current -> value,vlen);
00578 }
00579 m_current++;
00580 return true;
00581 } else
00582 *n = 0;
00583 return false;
00584 }
00585
00586
00587 int Form::getvalue(const std::string& n,char *v,short len)
00588 {
00589 CGI *cgi = NULL;
00590 int r = 0;
00591
00592
00593 for (cgi_v::iterator it = m_cgi.begin(); it != m_cgi.end(); it++)
00594 {
00595 cgi = *it;
00596 if (!strcmp(cgi -> name,n.c_str()))
00597 break;
00598 cgi = NULL;
00599 }
00600 if (cgi)
00601 {
00602 if (raw)
00603 {
00604 strncpy(v,cgi -> value,len - 1);
00605 v[len - 1] = 0;
00606 }
00607 else
00608 {
00609 strcpyval(v,cgi -> value,len);
00610 }
00611 r++;
00612 } else
00613 *v = 0;
00614
00615 return r;
00616 }
00617
00618 std::string Form::getvalue(const std::string& n)
00619 {
00620
00621 for (cgi_v::iterator it = m_cgi.begin(); it != m_cgi.end(); it++)
00622 {
00623 CGI *cgi = *it;
00624 if (!strcmp(cgi -> name,n.c_str() ))
00625 {
00626 return cgi -> value;
00627 }
00628 }
00629 return "";
00630 }
00631
00632 size_t Form::getlength(char *n)
00633 {
00634 CGI *cgi = NULL;
00635 size_t l;
00636
00637
00638 for (cgi_v::iterator it = m_cgi.begin(); it != m_cgi.end(); it++)
00639 {
00640 cgi = *it;
00641 if (!strcmp(cgi -> name,n))
00642 break;
00643 cgi = NULL;
00644 }
00645 l = cgi ? strlen(cgi -> value) : 0;
00646 if (cgi && !raw)
00647 {
00648 for (size_t i = 0; i < strlen(cgi -> value); i++)
00649 {
00650 switch (cgi -> value[i])
00651 {
00652 case '<':
00653 case '>':
00654 l += 4;
00655 break;
00656 case '&':
00657 l += 5;
00658 break;
00659 }
00660 }
00661 }
00662 return l;
00663 }
00664
00665
00666 char *Form::GetBoundary()
00667 {
00668 return m_strBoundary ? m_strBoundary : (char *)"";
00669 }
00670
00671
00672 }