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