![]() |
HttpdForm Class ReferenceParse/store a http query_string/form-data body.
More...
|
Public Member Functions | |
HttpdForm (IFile *, const std::string &content_type, size_t content_length) | |
Default constructor (used in POST operations). | |
HttpdForm (const std::string &query_string, size_t length) | |
Another constructor (used in GET operations). | |
~HttpdForm () | |
void | EnableRaw (bool) |
void | strcpyval (std::string &, const char *) const |
Encode characters '<' '>' '&' as < > &. | |
bool | getfirst (std::string &n) const |
bool | getnext (std::string &n) const |
bool | getfirst (std::string &n, std::string &v) const |
bool | getnext (std::string &n, std::string &v) const |
int | getvalue (const std::string &, std::string &) const |
std::string | getvalue (const std::string &) const |
size_t | getlength (const std::string &) const |
cgi_v & | getbase () |
const std::string & | GetBoundary () const |
Private Types | |
typedef std::list< CGI * > | cgi_v |
list of key/value pairs. | |
Private Member Functions | |
HttpdForm (const HttpdForm &) | |
HttpdForm & | operator= (const HttpdForm &) |
Private Attributes | |
cgi_v | m_cgi |
cgi_v::const_iterator | m_current |
std::string | m_strBoundary |
bool | raw |
Classes | |
struct | CGI |
Store the name/value pairs from a GET/POST operation. More... |
Definition at line 48 of file HttpdForm.h.
typedef std::list<CGI *> HttpdForm::cgi_v [private] |
HttpdForm::HttpdForm | ( | IFile * | , | |
const std::string & | content_type, | |||
size_t | content_length | |||
) |
Default constructor (used in POST operations).
Input is read from stdin. Number of characters to read can be found in the environment variable CONTENT_LENGTH.
Definition at line 46 of file HttpdForm.cpp.
References Parse::EnableQuote(), Parse::getword(), m_cgi, m_current, m_strBoundary, and TMPSIZE.
00046 : 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 // Get headers until empty line 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 // get next header value 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 // Read content, save...? 00171 if (!current_filename.size()) // not a file 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 // remove trailing cr/linefeed 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 // current_filename.size() > 0 00189 { 00190 // read until m_strBoundary... 00191 FILE *fil; 00192 int out = 0; 00193 char c; 00194 char fn[2000]; // where post'd file will be saved 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); // next line 00248 } 00249 else 00250 { 00251 // couldn't open file 00252 break; 00253 } 00254 } 00255 } 00256 else 00257 { 00258 // Probably '<m_strBoundary>--' 00259 break; 00260 } 00261 } // while (!infil -> eof()) 00262 delete[] slask; 00263 } // if (m_strBoundary) 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; // tnx to FatherNitwit 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 '=': /* end of name */ 00288 slask[i] = 0; 00289 i = 0; 00290 strcpy(name,slask); 00291 got_name = true; 00292 break; 00293 case '&': /* end of value */ 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 '+': /* space */ 00308 slask[i++] = ' '; 00309 break; 00310 case '%': /* hex value */ 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: /* just another char */ 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 }
HttpdForm::HttpdForm | ( | const std::string & | query_string, | |
size_t | length | |||
) |
Another constructor (used in GET operations).
Input is read from the environment variable QUERY_STRING.
query_string | The httpd server provided QUERY_STRING | |
length | Query string length. |
Definition at line 348 of file HttpdForm.cpp.
References m_cgi, m_current, and TMPSIZE.
00348 : 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 '=': /* end of name */ 00369 slask[i] = 0; 00370 i = 0; 00371 strcpy(name,slask); 00372 got_name = true; 00373 break; 00374 case '&': /* end of value */ 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 '+': /* space */ 00389 slask[i++] = ' '; 00390 break; 00391 case '%': /* hex value */ 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: /* just another char */ 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 }
HttpdForm::~HttpdForm | ( | ) |
Definition at line 419 of file HttpdForm.cpp.
References m_cgi.
00420 { 00421 CGI *cgi = NULL; //,*tmp; 00422 00423 for (cgi_v::iterator it = m_cgi.begin(); it != m_cgi.end(); it++) 00424 { 00425 cgi = *it; 00426 delete cgi; 00427 } 00428 }
HttpdForm::HttpdForm | ( | const HttpdForm & | ) | [inline, private] |
void HttpdForm::EnableRaw | ( | bool | ) |
void HttpdForm::strcpyval | ( | std::string & | , | |
const char * | ||||
) | const |
Encode characters '<' '>' '&' as < > &.
Definition at line 437 of file HttpdForm.cpp.
Referenced by getnext(), and getvalue().
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 }
bool HttpdForm::getfirst | ( | std::string & | n | ) | const |
bool HttpdForm::getnext | ( | std::string & | n | ) | const |
Definition at line 471 of file HttpdForm.cpp.
References m_cgi, and m_current.
Referenced by getfirst().
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 }
bool HttpdForm::getfirst | ( | std::string & | n, | |
std::string & | v | |||
) | const |
bool HttpdForm::getnext | ( | std::string & | n, | |
std::string & | v | |||
) | const |
Definition at line 495 of file HttpdForm.cpp.
References m_cgi, m_current, raw, and strcpyval().
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 }
int HttpdForm::getvalue | ( | const std::string & | , | |
std::string & | ||||
) | const |
Definition at line 520 of file HttpdForm.cpp.
References m_cgi, raw, and strcpyval().
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 }
std::string HttpdForm::getvalue | ( | const std::string & | ) | const |
Definition at line 553 of file HttpdForm.cpp.
References m_cgi.
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 }
size_t HttpdForm::getlength | ( | const std::string & | ) | const |
Definition at line 567 of file HttpdForm.cpp.
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 }
HttpdForm::cgi_v & HttpdForm::getbase | ( | ) |
const std::string & HttpdForm::GetBoundary | ( | ) | const |
Definition at line 606 of file HttpdForm.cpp.
References m_strBoundary.
00607 { 00608 return m_strBoundary; 00609 }
cgi_v HttpdForm::m_cgi [private] |
Definition at line 106 of file HttpdForm.h.
Referenced by getbase(), getfirst(), getlength(), getnext(), getvalue(), HttpdForm(), and ~HttpdForm().
cgi_v::const_iterator HttpdForm::m_current [mutable, private] |
std::string HttpdForm::m_strBoundary [private] |
bool HttpdForm::raw [private] |
Definition at line 109 of file HttpdForm.h.
Referenced by EnableRaw(), getlength(), getnext(), and getvalue().