Logo
~Sockets~
~Examples~
~Contact~


HttpdForm Class Reference
[Webserver framework]

Parse/store a http query_string/form-data body. More...

#include <HttpdForm.h>

List of all members.


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_vgetbase ()
const std::string & GetBoundary () const

Private Types

typedef std::list< CGI * > cgi_v
 list of key/value pairs.

Private Member Functions

 HttpdForm (const HttpdForm &)
HttpdFormoperator= (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...

Detailed Description

Parse/store a http query_string/form-data body.

Definition at line 48 of file HttpdForm.h.


Member Typedef Documentation

typedef std::list<CGI *> HttpdForm::cgi_v [private]

list of key/value pairs.

Definition at line 64 of file HttpdForm.h.


Constructor & Destructor Documentation

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.

Parameters:
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]

Definition at line 104 of file HttpdForm.h.

00104 {}


Member Function Documentation

void HttpdForm::EnableRaw ( bool   ) 

Definition at line 431 of file HttpdForm.cpp.

References raw.

00432 {
00433         raw = b;
00434 }

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 += "&lt;";
00445                 }
00446                 else
00447                 if (value[i] == '>')
00448                 {
00449                         v += "&gt;";
00450                 }
00451                 else
00452                 if (value[i] == '&')
00453                 {
00454                         v += "&amp;";
00455                 }
00456                 else
00457                 {
00458                         v += value[i];
00459                 }
00460         }
00461 }

bool HttpdForm::getfirst ( std::string &  n  )  const

Definition at line 464 of file HttpdForm.cpp.

References getnext(), m_cgi, and m_current.

00465 {
00466         m_current = m_cgi.begin();
00467         return getnext(n);
00468 }

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

Definition at line 488 of file HttpdForm.cpp.

References getnext(), m_cgi, and m_current.

00489 {
00490         m_current = m_cgi.begin();
00491         return getnext(n,v);
00492 }

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.

References m_cgi, and raw.

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 '<': // &lt;
00587                         case '>': // &gt;
00588                                 l += 4;
00589                                 break;
00590                         case '&': // &amp;
00591                                 l += 5;
00592                                 break;
00593                         }
00594                 }
00595         }
00596         return l;
00597 }

HttpdForm::cgi_v & HttpdForm::getbase (  ) 

Definition at line 600 of file HttpdForm.cpp.

References m_cgi.

00601 {
00602         return m_cgi;
00603 }

const std::string & HttpdForm::GetBoundary (  )  const

Definition at line 606 of file HttpdForm.cpp.

References m_strBoundary.

00607 {
00608         return m_strBoundary;
00609 }

HttpdForm& HttpdForm::operator= ( const HttpdForm  )  [inline, private]

Definition at line 105 of file HttpdForm.h.

00105 { return *this; }


Member Data Documentation

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]

Definition at line 107 of file HttpdForm.h.

Referenced by getfirst(), getnext(), and HttpdForm().

std::string HttpdForm::m_strBoundary [private]

Definition at line 108 of file HttpdForm.h.

Referenced by GetBoundary(), and HttpdForm().

bool HttpdForm::raw [private]

Definition at line 109 of file HttpdForm.h.

Referenced by EnableRaw(), getlength(), getnext(), and getvalue().


The documentation for this class was generated from the following files:
Page, code, and content Copyright (C) 2007 by Anders Hedström
Generated for C++ Sockets by  doxygen 1.4.4