OSDN Git Service

fix for FreeBSD 11.1.
[hmh/hhml.git] / lib / formfile.cc
index e132b61..510bf65 100644 (file)
@@ -22,6 +22,19 @@ int  CGIFormFile::partAt (int i) {
     }
 }
 
+ustring  CGIFormFile::typeAt (int i) {
+    if (i >= 0) {
+       tary_t::iterator  it = typemap.find (i);
+       if (it == typemap.end ()) {
+           return uEmpty;
+       } else {
+           return it->second;
+       }
+    } else {
+       return uEmpty;
+    }
+}
+
 void  CGIFormFile::read_multipart (MotorEnv* env) {
 #ifdef DEBUG2
     std::cerr << "boundary:" << boundary << "\n";
@@ -39,7 +52,7 @@ void  CGIFormFile::read_multipart (MotorEnv* env) {
 }
 
 bool  CGIFormFile::saveData (MotorEnv* env) {
-    static const int  bsize = 65536 * 4;
+    static const size_t  bsize = 65536 * 4;
     size_t  size = postSize ();
     ustring  b;
     size_t  s;
@@ -57,16 +70,12 @@ bool  CGIFormFile::saveData (MotorEnv* env) {
            s = std::cin.read (&b[0], s).gcount ();
            if (s <= 0)
                break;
-           s = ::write (fp.fd, &b[0], s);
+           ::write (fp.fd, &b[0], s);
            size -= s;
            mapsize += s;
-           if (size > 0) {
-               std::cerr << "post-file[" << mypid << ":" << env->scriptName << "]: reading " << mapsize << "Bytes...\n"; // cerrはバッファリングされない
-           }
        }
-//     fp.close ();
-       close (0);              // cin
-       std::cerr << "post-file[" << mypid << ":" << env->scriptName << "]: done    " << mapsize << "Bytes\n";
+//     fp.close ();    mmapした後にクローズする。
+//     std::cerr << "post-file[" << mypid << ":" << env->scriptName << "]: done    " << mapsize << "Bytes\n";          // 出力サイズが大きいと、デッドロックする。
        mapdata = (char*)mmap (NULL, mapsize, PROT_READ, MAP_PRIVATE, fp.fd, 0);
 #ifdef DEBUG2
        std::cerr << (void*) mapdata << ": " << mapsize << "\n";
@@ -78,7 +87,7 @@ bool  CGIFormFile::saveData (MotorEnv* env) {
 }
 
 void  CGIFormFile::unlinkTmpFile () {
-    if (mapdata > 0) {
+    if (mapdata != NULL) {
        munmap (mapdata, mapsize);
        mapdata = NULL;
     }
@@ -88,19 +97,6 @@ void  CGIFormFile::unlinkTmpFile () {
     }
 }
 
-bool  CGIFormFile::isMultipart () {
-    ustring  e = getenvString (kCONTENT_TYPE);
-    umatch  m;
-    static uregex  re ("^" kMIME_FORMDATA "\\s*;\\s*boundary=\"?([ '()+,./0-9:=?A-Z_a-z-]*['()+,./0-9:=?A-Z_a-z-])");
-
-    if (usearch (e, m, re)) {
-       boundary = ustring (m[1]);
-       return true;
-    } else {
-       return false;
-    }
-}
-
 void  CGIFormFile::searchPart (MotorEnv* env) {
     char*  b = mapdata;
     char*  e = mapdata + mapsize;
@@ -133,14 +129,14 @@ void  CGIFormFile::searchPart (MotorEnv* env) {
 #endif /* DEBUG */
            if (filename.size () > 0) {
                int  k1, k2;
-//             v = to_ustring (parts.size ());
                k2 = parts.size ();
                fix (name);
-//             insert (filearg, name, v);
                parts.push_back (part (b, x));
                fix (filename);
+               fix (type);
                k1 = insert (iarg, name, filePart_osSafe (filename));
                datamap.insert (sary_t::value_type (k1, k2));
+               typemap.insert (tary_t::value_type (k2, type));
 #ifdef DEBUG2
                std::cerr << "insert(" << k1 << "," << k2 << ")\n";
 #endif /* DEBUG */
@@ -196,10 +192,70 @@ void  CGIFormFile::compileReg () {
     reN.assign (a);
 }
 
+class  ChSplitterNL {
+ public:
+    char*  b;          // 先頭
+    char*  t;          // 区切り文字列先頭
+    char*  u;          // 区切り文字列末尾
+    char*  e;          // 末尾
+
+    ChSplitterNL (char* _begin, char* _end) {
+       b = t = u = _begin;
+       e = _end;
+    };
+    ~ChSplitterNL () {};
+
+    bool  isEnd () {
+       return b == e;
+    };
+    ustring  pre () {
+       return ustring (b, t);
+    };
+    bool  next () {
+       b = t = u;
+       if (b < e) {
+           if (findNL ()) {
+           } else {
+               t = u = e;
+           }
+           return true;
+       } else {
+           return false;
+       }
+    };
+    bool  nextSep () {
+       b = t = u;
+       if (b < e) {
+           if (findNL ()) {
+               return true;
+           } else {
+               t = u = e;
+               return false;
+           }
+       } else {
+           t = u = e;
+           return false;
+       }
+    };
+    bool  findNL () {
+       for (; t < e; ++ t) {
+           if (*t == '\n') {
+               u = t + 1;
+               return true;
+           } else if (*t == '\r') {
+               u = t + 1;
+               if (u < e && *u == '\n')
+                   ++ u;
+               return true;
+           }
+       }
+       return false;
+    };
+};
+
 void  CGIFormFile::readMimeHead (char*& b, char* e, ustring& disp, ustring& name, ustring& filename, ustring& type) {
-    boost::match_results<char*>  m;
+    ChSplitterNL  sp (b, e);
     boost::match_results<char*>  m2;
-    char*  x;
     static uregex  re_disp1 ("^Content-Disposition:\\s*(.*);\\s*name=\"(.*)\";\\s*filename=\"(.*)\"$");
     static uregex  re_disp2 ("^Content-Disposition:\\s*(.*);\\s*name=\"(.*)\"$");
     static uregex  re_type ("^Content-Type:\\s*([a-zA-Z_0-9/.+-]*)(;\\s*(.*))?$");
@@ -208,42 +264,30 @@ void  CGIFormFile::readMimeHead (char*& b, char* e, ustring& disp, ustring& name
     name.resize (0);
     filename.resize (0);
     type.resize (0);
-    while (b != e && regex_search (b, e, m, re_nl, boost::regex_constants::match_single_line)) {
-       x = m[0].first;
+    while (sp.next ()) {
 #ifdef DEBUG2
-       std::cerr << "line:" << ustring (b, x) << "\n";
+       std::cerr << "line:" << sp.pre () << "\n";
 #endif /* DEBUG */
-       if (b == x) {           // empty line
-           b = m[0].second;
+       if (sp.b == sp.t) {
+           b = sp.u;
            break;
        }
-       if (regex_search (b, x, m2, re_disp1, boost::regex_constants::match_single_line)) {
+       if (regex_search (sp.b, sp.t, m2, re_disp1, boost::regex_constants::match_single_line)) {
            disp.assign (m2[1].first, m2[1].second - m2[1].first);
            name.assign (m2[2].first, m2[2].second - m2[2].first);
            filename.assign (m2[3].first, m2[3].second - m2[3].first);
-       } else if (regex_search (b, x, m2, re_disp2, boost::regex_constants::match_single_line)) {
+       } else if (regex_search (sp.b, sp.t, m2, re_disp2, boost::regex_constants::match_single_line)) {
            disp.assign (m2[1].first, m2[1].second - m2[1].first);
            name.assign (m2[2].first, m2[2].second - m2[2].first);
-       } else if (regex_search (b, x, m2, re_type, boost::regex_constants::match_single_line)) {
+       } else if (regex_search (sp.b, sp.t, m2, re_type, boost::regex_constants::match_single_line)) {
            type.assign (m2[1].first, m2[1].second - m2[1].first);
        } else {
 #ifdef DEBUG2
-           std::cerr << "not match:" << ustring (b, x) << "\n";
+           std::cerr << "not match:" << sp.pre () << "\n";
 #endif /* DEBUG */
        }
-       b = m[0].second;
-    }
-}
-
-#if 0
-bool  CGIFormFile::readFilename (int i, ustring& filename) {
-    if (0 <= i && i < parts.size ()) {
-       filename = filenames[i];
-       return true;
     }
-    return false;
 }
-#endif
 
 bool  CGIFormFile::saveFile (int i, const ustring& path, size_t max) {
     static size_t  bsize = 65536;