Google
Web alhem.net

Form.cpp

Go to the documentation of this file.
00001 
00007 /*
00008 Copyright (C) 1999  Anders Hedstrom
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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 //#include "list.h"
00041 #include "Parse.h"
00042 #include "Form.h"
00043 
00044 /*
00045 #define DEB(x) { \
00046         FILE *fil = fopen("/tmp/debug","at"); \
00047         x; \
00048         fclose(fil); \
00049 }
00050 */
00051 #define DEB(x)
00052 
00053 namespace Cgi {
00054 
00055 // CONTENT_TYPE=multipart/form-data; boundary=---------------------------80261298425718
00056 
00057 // Form() -- request_method POST
00058 
00059 Form::Form(FILE *infil /* = stdin */)
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 //      cgibase = NULL;
00071         m_current = m_cgi.end(); //NULL;
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                                 // Get headers until empty line
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); // 'name' or 'filename'
00144                                                                         pa2.getrest(slask); // value
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                                                 // get next header value
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                                 // Read content, save...?
00192                                         if (!*current_filename) // not a file
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                                                 // remove trailing cr/linefeed
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]; //strlen(slask) + 1];
00212                                                 strcpy(cgi -> value,val.c_str() );
00213                                                 cgi -> path = NULL;
00214 //                                              addlist(&cgibase, (LIST *)cgi);
00215                                                 m_cgi.push_back(cgi);
00216                                         }
00217                                         else
00218                                         if (*current_filename)
00219                                         {
00220 DEB(                                            fprintf(fil,"Form:: save file<br>\n");)
00221                                         // read until m_strBoundary...
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 //                                                              fwrite(&c,1,1,fil);
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 //                                                      addlist(&cgibase, (LIST *)cgi);
00283                                                         m_cgi.push_back(cgi);
00284                                                 
00285                                                         strcpy(slask, m_strBoundary);
00286                                                         fgets(slask + strlen(slask), 200, infil); // next line
00287                                                 }
00288                                                 else
00289                                                 {
00290                                                         // couldn't open file
00291 DEB(                                                    fprintf(fil,"Form:: couldn't create '%s'...<br>\n",fn);)
00292                                                         break;
00293                                                 }
00294                                         }
00295                                         else
00296                                         {
00297                                                 // bad input?
00298 DEB(                                            fprintf(fil,"Form:: bad input?<br>\n");)
00299                                                 break;
00300                                         }
00301                                 }
00302                                 else
00303                                 {
00304                                         // Probably '<m_strBoundary>--'
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                         } // while (!feof(infil))
00310                 } // if (m_strBoundary)
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 //              cgibase = NULL;
00324                 m_current = m_cgi.end(); //NULL;
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 '=': /* end of name */
00335                                         slask[i] = 0;
00336                                         i = 0;
00337                                         strcpy(name,slask);
00338                                         break;
00339                                 case '&': /* end of value */
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 //                                      addlist(&cgibase, (LIST *)cgi);
00350                                         m_cgi.push_back(cgi);
00351                                         break;
00352                                 case '+': /* space */
00353                                         slask[i++] = ' ';
00354                                         break;
00355                                 case '%': /* hex value */
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: /* just another char */
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 //              addlist(&cgibase, (LIST *)cgi);
00391                 m_cgi.push_back(cgi);
00392         }
00393 }
00394 
00395 
00396 // Form(buffer,l) -- request_method GET
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 //      cgibase = NULL;
00410         m_current = m_cgi.end(); //NULL;
00411 
00412         *name = 0;
00413 
00414         ptr = 0;
00415         while (ptr < l)
00416         {
00417                 c = buffer[ptr++];
00418                 switch (c)
00419                 {
00420                         case '=': /* end of name */
00421                                 slask[i] = 0;
00422                                 i = 0;
00423                                 strcpy(name,slask);
00424                                 break;
00425                         case '&': /* end of value */
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 //                              addlist(&cgibase, (LIST *)cgi);
00435                                 m_cgi.push_back(cgi);
00436                                 break;
00437                         case '+': /* space */
00438                                 slask[i++] = ' ';
00439                                 break;
00440                         case '%': /* hex value */
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: /* just another char */
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 //      addlist(&cgibase, (LIST *)cgi);
00467         m_cgi.push_back(cgi);
00468 }
00469 
00470 Form::~Form()
00471 {
00472         CGI *cgi = NULL; //,*tmp;
00473 
00474 //      for (cgi = cgibase; cgi; cgi = tmp)
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 //              tmp = cgi -> next;
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),"&lt;");
00510                 }
00511                 else
00512                 if (value[i] == '>')
00513                 {
00514                         if (strlen(v) < len - 4)
00515                                 sprintf(v + strlen(v),"&gt;");
00516                 }
00517                 else
00518                 if (value[i] == '&')
00519                 {
00520                         if (strlen(v) < len - 5)
00521                                 sprintf(v + strlen(v),"&amp;");
00522                 }
00523                 else
00524                 {
00525                         if (strlen(v) < len - 1)
00526                                 sprintf(v + strlen(v),"%c",value[i]);
00527                 }
00528         }
00529 //      v[len - 1] = 0;
00530 }
00531 
00532 
00533 /* get names */
00534 
00535 bool Form::getfirst(char *n,short len)
00536 {
00537         m_current = m_cgi.begin(); //cgibase;
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++; //current = current -> next;
00549                 return true;
00550         } else
00551                 *n = 0;
00552         return false;
00553 }
00554 
00555 /* get names and values */
00556 
00557 bool Form::getfirst(char *n,short len,char *v,short vlen)
00558 {
00559         m_current = m_cgi.begin(); //cgibase;
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++; // = current -> next;
00580                 return true;
00581         } else
00582                 *n = 0;
00583         return false;
00584 }
00585 
00586 /* get value */
00587 int Form::getvalue(const std::string& n,char *v,short len)
00588 {
00589         CGI *cgi = NULL;
00590         int r = 0;
00591 
00592 //      for (cgi = cgibase; cgi; cgi = cgi -> next)
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 //      for (CGI *cgi = cgibase; cgi; cgi = cgi -> next)
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 //      for (cgi = cgibase; cgi; cgi = cgi -> next)
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 '<': // &lt;
00653                         case '>': // &gt;
00654                                 l += 4;
00655                                 break;
00656                         case '&': // &amp;
00657                                 l += 5;
00658                                 break;
00659                         }
00660                 }
00661         }
00662         return l; //cgi ? strlen(cgi -> value) : 0;
00663 }
00664 
00665 
00666 char *Form::GetBoundary()
00667 {
00668         return m_strBoundary ? m_strBoundary : (char *)"";
00669 }
00670 
00671 
00672 } // namespace

Generated for cgi++ by doxygen 1.3.7

Page, code, and content Copyright (C) 2004 by Anders Hedström