Logo
~Sockets~
~Examples~
~Contact~


HttpdForm.cpp

Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 1999-2007  Anders Hedstrom
00008 
00009 This library is made available under the terms of the GNU GPL.
00010 
00011 If you would like to use this library in a closed-source application,
00012 a separate license agreement is available. For information about 
00013 the closed-source license agreement for the C++ sockets library,
00014 please visit http://www.alhem.net/Sockets/license.html and/or
00015 email license@alhem.net.
00016 
00017 This program is free software; you can redistribute it and/or
00018 modify it under the terms of the GNU General Public License
00019 as published by the Free Software Foundation; either version 2
00020 of the License, or (at your option) any later version.
00021 
00022 This program is distributed in the hope that it will be useful,
00023 but WITHOUT ANY WARRANTY; without even the implied warranty of
00024 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00025 GNU General Public License for more details.
00026 
00027 You should have received a copy of the GNU General Public License
00028 along with this program; if not, write to the Free Software
00029 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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                                         // 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 }
00344 
00345 
00346 // HttpdForm(buffer,l) -- request_method GET
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 '=': /* 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 }
00417 
00418 
00419 HttpdForm::~HttpdForm()
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 }
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 += "&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 }
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 '<': // &lt;
00587                         case '>': // &gt;
00588                                 l += 4;
00589                                 break;
00590                         case '&': // &amp;
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 
Page, code, and content Copyright (C) 2007 by Anders Hedström
Generated for C++ Sockets by  doxygen 1.4.4