Changeset 12513


Ignore:
Timestamp:
2006-08-24T11:10:07+12:00 (18 years ago)
Author:
kjdon
Message:

Added Stefan's fileupload code to replace use of cgicc by depositor. parsing post data, generating fileupload structures and saving the file

Location:
trunk/gsdl/src/recpt
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/gsdl/src/recpt/cgiutils.cpp

    r11998 r12513  
    2525
    2626#include "cgiutils.h"
     27#include "md5.h"
     28#include "fileutil.h"
    2729#include "gsdlunicode.h"
    2830#include "fileutil.h"
    2931#include "unitool.h" // in mg, for output_utf8_char
     32
     33#if defined(GSDL_USE_OBJECTSPACE)
     34#  include <ospace\std\iostream>
     35#  include <ospace\std\fstream>
     36#elif defined(GSDL_USE_IOS_H)
     37#  include <iostream.h>
     38#  include <fstream.h>
     39#else
     40#  include <iostream>
     41#  include <fstream>
     42#endif
    3043
    3144
     
    5770  t.push_back(o1);
    5871  t.push_back(o2);
     72}
     73
     74static text_t::iterator getline (text_t::iterator first,
     75                 text_t::iterator last,
     76                 bool include_crlf) {
     77  while (first != last) {
     78    if (((first+1) != last) && (*first == 13) && (*(first+1) == 10)) {
     79      // found <CRLF>
     80      if (include_crlf) first += 2;
     81      break;
     82    }
     83    first++;
     84  }
     85  return first;
     86}
     87
     88static void process_post_section (text_t &argname, text_t &argdata, text_t &filename, text_t &filedata,
     89                  text_t &filetype, bool &isfile, text_t &argstr,
     90                  fileupload_tmap &fileuploads, const text_t &gsdlhome) {
     91
     92  if (!argname.empty()) {
     93
     94    if (!isfile) {
     95      // argdata includes a trailing <CRLF> that we must remove
     96      if ((argdata.size() > 1) && (*(argdata.end()-2) == 13) && (*(argdata.end()-1) == 10)) {
     97    argdata.erase(argdata.end()-2, argdata.end());
     98      }
     99      if (!argstr.empty()) argstr += "&";
     100      argstr += argname + "=" + argdata;
     101
     102    } else if (!filename.empty()) {
     103      // filedata includes a trailing <CRLF> that we must remove
     104      if ((filedata.size() > 1) && (*(filedata.end()-2) == 13) && (*(filedata.end()-1) == 10)) {
     105    filedata.erase(filedata.end()-2, filedata.end());
     106      }
     107
     108      // create tmp_name for storing the file on disk
     109      text_t tmp_name = md5data(filedata);
     110      tmp_name = filename_cat(gsdlhome, "tmp", tmp_name);
     111      char *tmp_name_c = tmp_name.getcstr();
     112
     113      // write the file data to disk
     114      outconvertclass out;
     115      ofstream filestream(tmp_name_c, ios::out | ios::binary);
     116      filestream << out << filedata;
     117      filestream.close();
     118      delete tmp_name_c;
     119
     120      // populate the fields of a fileupload_t and put it in the
     121      // fileuploads map
     122      fileupload_t fu;
     123      // note that filename currently may or may not include the path since
     124      // some browsers (e.g. IE) include the path while others
     125      // (e.g. mozilla) do not. we should probably remove the path from
     126      // this field here to get a consistent value across all browsers.
     127      text_t::iterator slash = findlastchar(filename.begin(), filename.end(), '\\');
     128      if (slash != filename.end()) {
     129    filename = substr(slash+1, filename.end());
     130      }
     131      fu.name = filename;
     132      fu.type = filetype;
     133      // size has yet to be implemented
     134      fu.size = 0;
     135      fu.tmp_name = tmp_name;
     136      fileuploads[argname] = fu;
     137    }
     138  }
     139  isfile = false;
     140  argname.clear();
     141  argdata.clear();
     142  filename.clear();
     143  filedata.clear();
     144  filetype.clear();
     145}
     146
     147// parse data obtained through a CGI POST request
     148text_t parse_post_data (text_t &content_type, text_t &raw_post_data,
     149            fileupload_tmap &fileuploads, const text_t &gsdlhome) {
     150
     151  text_t argstr;
     152
     153  text_t::iterator content_type_begin = content_type.begin();
     154  text_t::iterator content_type_end = content_type.end();
     155  if (findword(content_type_begin, content_type_end, "multipart/form-data") == content_type_end) {
     156    // a simple post request
     157    return raw_post_data;
     158
     159  } else {
     160    // multipart/form data - may contain one or more uploaded files
     161
     162    /*
     163      content_type should look something like the following
     164        multipart/form-data; boundary=---------------------------7d411e1a50330
     165   
     166      while raw_post_data will be as follows
     167        -----------------------------7d43e73450330CRLF
     168    Content-Disposition: form-data; name="e"<CRLF>
     169    <CRLF>
     170    d-0testss--1-0-00---4----0--0-110--1en-Zz-1---10-about-0--00031-001utfZz-8-0<CRLF>
     171    -----------------------------7d43e73450330<CRLF>
     172    Content-Disposition: form-data; name="afile"; filename="C:\somedoc.doc"<CRLF>
     173    Content-Type: application/msword<CRLF>
     174    <CRLF>
     175    <Content of file><CRLF>
     176   
     177    */
     178
     179    // first get the boundary from content-type
     180    text_t::iterator boundary_begin = findword(content_type_begin, content_type_end, "boundary=");
     181    if (boundary_begin+9 < content_type_end) boundary_begin += 9;
     182    else {
     183      // error
     184      return "";
     185    }
     186    text_t boundary = substr(boundary_begin, getline(boundary_begin, content_type_end, false));
     187    int boundary_len = boundary.size();
     188
     189    text_t argname, argdata, filename, filedata, filetype;
     190    bool isfile = false;
     191    text_t::iterator data_here = raw_post_data.begin();
     192    text_t::iterator data_end = raw_post_data.end();
     193    while (data_here != data_end) {
     194     
     195      // get the next available line (including the trailing <CRLF>
     196      text_t line = substr(data_here, getline(data_here, data_end, true));
     197      data_here += line.size();
     198      text_t::iterator line_begin = line.begin();
     199      text_t::iterator line_end = line.end();
     200      if (findword(line_begin, line_end, boundary) != line_end) {
     201    // we've found a boundary
     202    process_post_section(argname, argdata, filename, filedata, filetype,
     203                 isfile, argstr, fileuploads, gsdlhome);
     204
     205      } else if (findword(line_begin, line_end, "Content-Disposition: form-data") != line_end) {
     206    // we've found the the beginning of a new section
     207    argname.clear();
     208    argdata.clear();
     209
     210    // get the name of this piece of form data
     211    text_t::iterator it = findword(line_begin, line_end, "name=\"");
     212    if (it == line_end) break; // error - this shouldn't happen
     213    it = findchar(it, line_end, '"');
     214    if ((it != line_end) && (it+1 != line_end)) {
     215      argname = substr(it+1, findchar(it+1, line_end, '"'));
     216    }
     217
     218    // if this piece of form data contains filename="" it's a file
     219    // upload and needs to be treated special
     220    it = (findword(line_begin, line_end, "filename=\""));
     221    if (it != line_end) {
     222      // we've found a file upload
     223      isfile = true;
     224      it = findchar(it, line_end, '"');
     225      if ((it != line_end) && (it+1 != line_end)) {
     226        filename = substr(it+1, findchar(it+1, line_end, '"'));
     227      }
     228
     229      // the next line is the content-type of this section
     230      line = substr(data_here, getline(data_here, data_end, true));
     231      data_here += line.size();
     232      line_begin = line.begin();
     233      line_end = line.end();
     234      it = (findword(line_begin, line_end, "Content-Type: "));
     235      if (it != line_end) {
     236        filetype = substr(it+14, getline(it, line_end, false));
     237      }
     238    }
     239
     240    // eat up the next line as it's just a <CRLF> on it's own
     241    data_here += 2;
     242
     243      } else {
     244    if (isfile) filedata += line;
     245    else argdata += line;
     246      }
     247    }
     248
     249    // process last section
     250    process_post_section(argname, argdata, filename, filedata, filetype,
     251             isfile, argstr, fileuploads, gsdlhome);
     252
     253    return argstr;
     254  }
    59255}
    60256
     
    465661}
    466662
     663void add_fileupload_args (const cgiargsinfoclass &argsinfo,
     664              cgiargsclass &args,
     665              fileupload_tmap &fileuploads,
     666              ostream &logout) {
     667 
     668  const cgiarginfo *info = argsinfo.getarginfo("a");
     669  fileupload_tmap::const_iterator this_file = fileuploads.begin();
     670  fileupload_tmap::const_iterator end_file = fileuploads.end();
     671  while (this_file != end_file) {
     672    const cgiarginfo *info = argsinfo.getarginfo((*this_file).first);
     673    if (info != NULL) {
     674      if ((*info).fileupload && (file_exists((*this_file).second.tmp_name))) {
     675    args.setargfile((*this_file).first, (*this_file).second);
     676      }
     677    }
     678    this_file++;
     679  }
     680}
    467681
    468682// compress_save_args will compress the arguments and return
  • trunk/gsdl/src/recpt/cgiutils.h

    r2426 r12513  
    3232#include "cgiargs.h"
    3333
     34// parse data obtained through a CGI POST request
     35text_t parse_post_data (text_t &content_type, text_t &raw_post_data,
     36            fileupload_tmap &fileuploads, const text_t &gsdlhome);
    3437
    3538// convert %xx and + to their appropriate equivalents
     
    8285               ostream &logout);
    8386
     87void add_fileupload_args (const cgiargsinfoclass &argsinfo,
     88              cgiargsclass &args,
     89              fileupload_tmap &fileuploads,
     90              ostream &logout);
     91
    8492// compress_save_args will compress the arguments and return
    8593// them in compressed_args. If an error was encountered
Note: See TracChangeset for help on using the changeset viewer.