OSDN Git Service

$http function.
authorvisor <visor@users.sourceforge.jp>
Sat, 17 Dec 2011 11:14:32 +0000 (20:14 +0900)
committervisor <visor@users.sourceforge.jp>
Sat, 17 Dec 2011 11:14:32 +0000 (20:14 +0900)
bin/MKID.pl
bin/MKTABLE.pl
lib/http.cc
lib/http.h
lib/httpconst.h
lib/util_base64.cc
lib/util_const.h
lib/util_tcp.cc
lib/util_tcp.h
modules/ml-http.cc
modules/ml-http.h

index 54914fb..c552295 100755 (executable)
@@ -12,22 +12,36 @@ foreach (@ARGV) {
 #          push (@CPPFLAGS, $_);
        }
     } else {
-       push (@SRCS, $_);
+       if (-f $_) {
+           push (@SRCS, $_);
+       } elsif (-f "../ext/$_") {
+           push (@SRCS, "../ext/$_");
+       } elsif (-f "../modules/$_") {
+           push (@SRCS, "../modules/$_");
+       } else {
+           die "$_: not found\n";
+       }
     }
 }
 
-foreach (@SRCS) {
-    if (-f $_) {
-       &p ($_);
-    } elsif (-f "../ext/$_") {
-       &p ("../ext/$_");
-    } elsif (-f "../modules/$_") {
-       &p ("../modules/$_");
-    } else {
-       die "$_: not found\n";
+if (-f $target) {
+    my $targetTime = &mtime ($target);
+    my $f = undef;
+    foreach (@SRCS) {
+       if ($targetTime < &mtime ($_)) {
+           $f = 1;
+           last;
+       }
+    }
+    if (! $f) {
+       exit;
     }
 }
 
+foreach (@SRCS) {
+    &p ($_);
+}
+
 open (OUT, "> $targetTmp");
 print OUT "#ifndef ML_ID_H\n";
 print OUT "#define ML_ID_H\n\n";
@@ -39,12 +53,13 @@ foreach (@ID) {
 print OUT "\n#endif /* ML_ID_H */\n";
 close (OUT);
 
-if (-f $target && ! cmpFile ($target, $targetTmp)) {
-    unlink ($targetTmp);
-} else {
-    rename ($targetTmp, $target);
-    print "$target\n";
-}
+#@#if (-f $target && ! cmpFile ($target, $targetTmp)) {
+#@#    unlink ($targetTmp);
+#@#} else {
+#@#    rename ($targetTmp, $target);
+#@#    print "$target\n";
+#@#}
+rename ($targetTmp, $target);
 
 exit;
 
@@ -83,3 +98,9 @@ sub  cmpFile {
     $rc = system ('/usr/bin/cmp', '-s', $f1, $f2) >> 8;
     return $rc;
 }
+
+sub  mtime {
+    my ($file) = @_;
+
+    (stat ($file))[9];
+}
index 70f384d..0eeb04d 100755 (executable)
@@ -18,22 +18,38 @@ foreach (@ARGV) {
            push (@CPPFLAGS, $_);
        }
     } else {
-       push (@SRCS, $_);
+#@#    push (@SRCS, $_);
+       if (-f $_) {
+           push (@SRCS, $_);
+       } elsif (-f "../ext/$_") {
+           push (@SRCS, "../ext/$_");
+       } elsif (-f "../modules/$_") {
+           push (@SRCS, "../modules/$_");
+       } else {
+           die "$_: not found\n";
+       }
     }
 }
 
-foreach (@SRCS) {
-    if (-f $_) {
-       &p ($_);
-    } elsif (-f "../ext/$_") {
-       &p ("../ext/$_");
-    } elsif (-f "../modules/$_") {
-       &p ("../modules/$_");
-    } else {
-       die "$_: not found\n";
+if (-f $target) {
+    my $targetTime = &mtime ($target);
+    my $f = undef;
+    foreach (@SRCS) {
+       if ($targetTime < &mtime ($_)) {
+           $f = 1;
+           last;
+       }
+    }
+    if (! $f) {
+       die "exit\n";
+       exit;
     }
 }
 
+foreach (@SRCS) {
+    &p ($_);
+}
+
 open (OUT, "> $targetTmp");
 print OUT "#include \"ftable.h\"\n";
 print OUT "#include \"mftable.h\"\n";
@@ -48,12 +64,13 @@ print OUT "//============================================================\n";
 &wikiftable;
 close (OUT);
 
-if (-f $target && ! cmpFile ($target, $targetTmp)) {
-    unlink ($targetTmp);
-} else {
-    rename ($targetTmp, $target);
-    print "$target\n";
-}
+#@#if (-f $target && ! cmpFile ($target, $targetTmp)) {
+#@#    unlink ($targetTmp);
+#@#} else {
+#@#    rename ($targetTmp, $target);
+#@#    print "$target\n";
+#@#}
+rename ($targetTmp, $target);
 
 exit;
 
@@ -215,3 +232,9 @@ sub  cmpFile {
     $rc = system ('/usr/bin/cmp', '-s', $f1, $f2) >> 8;
     return $rc;
 }
+
+sub  mtime {
+    my ($file) = @_;
+
+    (stat ($file))[9];
+}
index 5b119de..176522d 100644 (file)
@@ -2,6 +2,8 @@
 #include "httpconst.h"
 #include "motorenv.h"
 #include "motoroutput.h"
+#include "mlenv.h"
+#include "util_file.h"
 #include "util_string.h"
 #include "util_time.h"
 #include "util_base64.h"
@@ -10,6 +12,8 @@
 #include "util_random.h"
 #include "util_splitter.h"
 #include "util_tcp.h"
+#include "util_mimetype.h"
+#include "filemacro.h"
 #include "ustring.h"
 #include "utf8.h"
 #include <vector>
@@ -48,14 +52,6 @@ void  HTTPResponse::setCookie (const ustring& key, const ustring& val, const ust
        ck.append (cookieencode (val));
        ck.append (CharConst ("; path="));
        if (path.size () == 0) {
-#if 0
-//         char*  e = getenv (kSCRIPT_NAME);
-           if (e) {
-               ck.append (dirPart (e));
-           } else {
-               ck.append (uSlash);
-           }
-#endif
            if (env->scriptName.size () > 0) {
                ck.append (dirPart (env->scriptName));
            } else {
@@ -294,44 +290,37 @@ void  HTTPSend::setMethod (const ustring& _method, bool fpost) {
     }
 }
 
-void  HTTPSend::setParam (ustring& dst, const ustring& name, const ustring& value) {
-    if (dst.length () > 0)
-       dst.append (uAmp);
-    dst.append (urlencode (cv (name))).append (uEq).append (urlencode (cv (value)));
-}
-
-void  HTTPSend::setParam (const ustring& name, const ustring& value) {
-    setParam (params, name, value);
-}
-
-void  HTTPSend::setGetParam (const ustring& name, const ustring& value) {
-    setParam (getparams, name, value);
-}
-
-bool  HTTPSend::submit (TcpClient& client, TcpBuf& buf) {
+bool  HTTPSend::submit (TcpClient& client, TcpBuf& buf, MlEnv* mlenv) {
     bool  rc;
     ustring  q;
 
     if (status != HTTP_INIT)
        return false;
 
-    if (port.empty ()) {
+    if (host.port == 0) {
        if (proto == uHttp) {
-           port.assign (CharConst ("80"));
+           host.port = 80;
        } else if (proto == uHttps) {
-           port.assign (CharConst ("443"));
+           host.port = 443;
        }
     }
-    client.setAddr (host, port);
-    rc = client.connect ();
+    rc = client.connect (host);
     
     if (rc) {
        status = HTTP_OPEN;
-       q = query ();
+       q = query (mlenv);
        client.write (&*q.begin (), q.length ());
+#ifdef DEBUG2
+       std::cerr << q;
+#endif /* DEBUG */
        if (fpostdata) {
-           client.write (&*params.begin (), params.length ());
+           if (formData) {
+               writeFileForm (&client, mlenv);
+           } else {
+               writeQueryForm (params (), client);
+           }
        }
+       client.flush_write ();
        status = HTTP_QUERY;
     } else {
        return false;
@@ -340,8 +329,8 @@ bool  HTTPSend::submit (TcpClient& client, TcpBuf& buf) {
     return true;
 }
 
-int  HTTPSend::post (TcpClient& client, TcpBuf& buf, ustring& ans) {
-    if (submit (client, buf)) {
+int  HTTPSend::post (TcpClient& client, TcpBuf& buf, ustring& ans, MlEnv* mlenv) {
+    if (submit (client, buf, mlenv)) {
        readReplyHead (client, buf);
        readReplyBody (client, buf, ans);
     }
@@ -384,7 +373,7 @@ void  HTTPSend::makeCookieHeader (ustring& q) {
     }
 }
 
-ustring  HTTPSend::query () {
+ustring  HTTPSend::query (MlEnv* mlenv) {
     ustring  q;
 
     if (method.length () == 0) {
@@ -392,29 +381,28 @@ ustring  HTTPSend::query () {
     }
     q.assign (method).append (uSPC).append (path);
     if (fpostdata) {
-       if (getparams.length () > 0) {
-           q.append (CharConst ("?")).append (getparams);
+       if (formData)
+           makeSeparator ();
+       if (getparams ()) {
+           q.append (CharConst ("?"));
+           appendQueryForm (getparams (), q);
        }
        q.append (CharConst (" HTTP/1.0" kCRLF));
     } else {
-       if (getparams.length () > 0) {
-           q.append (CharConst ("?")).append (getparams);
-       } else if (params.length () > 0) {
-           q.append (CharConst ("?")).append (params);
+       q.append (CharConst ("?"));
+       if (getparams ()) {
+           appendQueryForm (getparams (), q);
+       } else if (params ()) {
+           appendQueryForm (params (), q);
        }
        q.append (CharConst (" HTTP/1.0" kCRLF));
     }
     if (reqhost.length () > 0) {
-//     q.append (CharConst ("Host: ")).append (reqhost).append (uCRLF);
        makeHeader (q, ustring (CharConst ("Host")), reqhost);
     } else {
-//     q.append (CharConst ("Host: ")).append (host).append (uCRLF);
-       makeHeader (q, ustring (CharConst ("Host")), host);
+       makeHeader (q, ustring (CharConst ("Host")), host.host);
     }
     q.append (CharConst ("Accept: */*" kCRLF));
-//    if (cookie.size () > 0) {
-//     makeHeader (q, ustring (CharConst ("Cookie")), cookie);
-//    }
     makeCookieHeader (q);
     if (id.length () > 0) {
        ustring  idpw;
@@ -430,12 +418,245 @@ ustring  HTTPSend::query () {
        makeHeader (q, (*i).first, (*i).second);
     }
     if (fpostdata)
-       q.append (CharConst ("Content-Length: ")).append (to_ustring (params.length ())).append (uCRLF);
+       if (formData) {
+           q.append (CharConst ("Content-Length: ")).append (to_ustring (writeFileForm (NULL, mlenv))).append (uCRLF);
+           q.append (CharConst ("Content-Type: multipart/form-data; boundary=")).append (separator).append (uCRLF);
+       } else {
+           q.append (CharConst ("Content-Length: ")).append (to_ustring (queryFormSize (params ()))).append (uCRLF);
+       }
     q.append (CharConst ("Connection: close" kCRLF kCRLF));
 
     return q;
 }
 
+void  HTTPSend::writeQueryForm (MNode* e, TcpClient& out) {
+    MNode*  a;
+    ustring  u;
+    int  c = 0;
+
+    if (e && e->isCons ()) {
+       while (e) {
+           if (a = e->car ()) {
+               if (c > 0)
+                   u.assign (uAmp).append (urlencode (cv (to_string (a->car ()))));
+               else
+                   u.assign (urlencode (cv (to_string (a->car ()))));
+               u.append (uEq);
+               out.write (&*u.begin (), u.length ());
+               u.assign (urlencode (cv (to_string (a->cdr ()))));
+               out.write (&*u.begin (), u.length ());
+               c ++;
+           }
+           nextNode (e);
+       }
+    }
+}
+
+void  HTTPSend::appendQueryForm (MNode* e, ustring& out) {
+    MNode*  a;
+    int  c = 0;
+
+    if (e && e->isCons ()) {
+       while (e) {
+           if (a = e->car ()) {
+               if (c > 0)
+                   out.append (uAmp).append (urlencode (cv (to_string (a->car ()))));
+               else
+                   out.append (urlencode (cv (to_string (a->car ()))));
+               out.append (uEq);
+               out.append (urlencode (cv (to_string (a->cdr ()))));
+               c ++;
+           }
+           nextNode (e);
+       }
+    }
+}
+
+size_t  HTTPSend::queryFormSize (MNode* e) {
+    MNode*  a;
+    ustring  u;
+    int  c = 0;
+    size_t  ans = 0;
+
+    if (e && e->isCons ()) {
+       while (e) {
+           if (a = e->car ()) {
+               if (c > 0)
+                   u.assign (uAmp).append (urlencode (cv (to_string (a->car ()))));
+               else
+                   u.assign (urlencode (cv (to_string (a->car ()))));
+               u.append (uEq);
+               ans += u.length ();
+               u.assign (urlencode (cv (to_string (a->cdr ()))));
+               ans += u.length ();
+               c ++;
+           }
+           nextNode (e);
+       }
+    }
+    return ans;
+}
+
+void  HTTPSend::makeSeparator () {
+    separator.assign (CharConst ("--------")).append (randomKey ()).append (randomKey ());
+}
+
+size_t  HTTPSend::writeFileForm (TcpClient* out, MlEnv* mlenv) {
+    size_t  ans = 0;
+    MNode*  e;
+    MNode*  a;
+    ustring  u;
+    ustring  name;
+    ustring  val;
+    ustring  path;
+
+    // text data
+    e = params ();
+    if (e && e->isCons ()) {
+       while (e) {
+           if (a = e->car ()) {
+               name = to_string (a->car ());
+               val = to_string (a->cdr ());
+               ans += writeFileFormPart_text (out, name, val);
+           }
+           nextNode (e);
+       }
+    }
+
+    // files in the temporal store
+    e = fileparams_store ();
+    if (e && e->isCons ()) {
+       while (e) {
+           if (a = e->car ()) {
+               name = to_string (a->car ());
+               val = to_string (a->cdr ());
+               path = mlenv->env->path_store_file (val);
+               ans += writeFileFormPart (out, name, val, path);
+           }
+           nextNode (e);
+       }
+    }
+
+    // files in the permanent store
+    e = fileparams_storage ();
+    if (e && e->isCons ()) {
+       while (e) {
+           if (a = e->car ()) {
+               name = to_string (a->car ());
+               val = to_string (a->cdr ());
+               path = mlenv->env->path_storage_file (val);
+               ans += writeFileFormPart (out, name, val, path);
+           }
+           nextNode (e);
+       }
+    }
+
+#if 0
+    // files in the content directory
+    e = fileparams_doc ();
+    if (e && e->isCons ()) {
+       while (e) {
+           if (a = e->car ()) {
+               name = to_string (a->car ());
+               val = to_string (a->cdr ());
+               path = val;     XXX
+               ans += writeFileFormPart (out, name, val, path);
+           }
+           nextNode (e);
+       }
+    }
+#endif
+
+    u.assign (CharConst ("--")).append (separator).append (CharConst ("--" kCRLF));
+    if (out)
+       out->write (&*u.begin (), u.length ());
+    ans += u.length ();
+#ifdef DEBUG2
+    if (out)
+       std::cerr << u;
+#endif /* DEBUG */
+    return ans;
+}
+
+size_t  HTTPSend::writeFileFormPart_text (TcpClient* out, const ustring& name, const ustring& val) {
+    size_t  ans = 0;
+    ustring  u;
+
+    u.assign (CharConst ("--")).append (separator).append (uCRLF);
+    u.append (CharConst ("Content-Disposition: form-data; name=" kQ2)).append (urlencode (cv (name))).append (CharConst (kQ2 kCRLF kCRLF));
+    u.append (cv (val)).append (uCRLF);
+    if (out)
+       out->write (&*u.begin (), u.length ());
+    ans += u.length ();
+#ifdef DEBUG2
+    if (out)
+       std::cerr << u;
+#endif /* DEBUG */
+    return ans;
+}
+
+size_t  HTTPSend::writeFileFormPart (TcpClient* out, const ustring& name, const ustring& filename, const ustring& path) {
+    size_t  ans = 0;
+    ustring  u;
+    off_t  s;
+
+    u.assign (CharConst ("--")).append (separator).append (uCRLF);
+    u.append (CharConst ("Content-Disposition: form-data; name=" kQ2)).append (urlencode (cv (name))).append (CharConst (kQ2 "; filename=" kQ2)).append (slashEncode (filename)).append (CharConst (kQ2 kCRLF));
+    u.append (CharConst ("Content-Type: ")).append (mimetype (getExt (filename))).append (CharConst (kCRLF kCRLF));
+    if (out)
+       out->write (&*u.begin (), u.length ());
+    ans += u.length ();
+#ifdef DEBUG2
+    if (out)
+       std::cerr << u;
+#endif /* DEBUG */
+    if (out) {
+       if (path.length () > 0)
+           ans += writeFile (out, path);
+       out->write (CharConst (kCRLF)); // XXX
+       ans += 2;
+    } else {
+       if (path.length () > 0)
+           if (fileSize (path, s))
+               ans += s;
+       ans += 2;
+    }
+#ifdef DEBUG2
+    if (out)
+       std::cerr << uCRLF;
+#endif /* DEBUG */
+    return ans;
+}
+
+size_t  HTTPSend::writeFile (TcpClient* out, const ustring& path) {
+    size_t  ans = 0;
+
+    if (path.size () > 0) {
+       FileMacro  f;
+       off_t  s;
+       ssize_t  n;
+       char  buf [65536];
+
+       if (f.openRead (path.c_str ())) {
+           s = f.size ();
+           ans = s;
+           while (s > 0) {
+               n = s < 65536 ? s : 65536;
+               n = f.read (buf, n);
+               if (n < 0)
+                   break;
+               out->write (buf, n);
+#ifdef DEBUG2
+               std::cerr << "--data--\n";
+#endif /* DEBUG */
+               s -= n;
+           }
+           f.close ();
+       }
+    }
+    return ans;
+}
+
 int  HTTPSend::readReplyHead (TcpClient& client, TcpBuf& buf) {
     ustring  line;
     bool  rc;
index 1d46001..68177b0 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef HTTP_H
 #define HTTP_H
 
+#include "ml.h"
 #include "util_tcp.h"
 #include "ustring.h"
 #include <boost/unordered_map.hpp>
@@ -66,12 +67,17 @@ class  HTTPSend {
     bool  fpostdata;
     ustring  method;
     ustring  proto;
-    ustring  host;
-    ustring  port;
+    HostSpec  host;
     ustring  reqhost;
     ustring  path;
-    ustring  params;
-    ustring  getparams;
+    MNodePtr  params;
+    MNodePtr  getparams;
+    MNodePtr  fileparams_store;
+    MNodePtr  fileparams_storage;
+    MNodePtr  fileparams_docs;
+    size_t  paramsLen;
+    ustring  separator;
+    bool  formData;
     ustring  id;
     ustring  pw;
     std::vector<mapelem>  cookie;
@@ -86,20 +92,27 @@ class  HTTPSend {
     HTTPSend () {
        status = HTTP_INIT;
        fpostdata = false;
+       paramsLen = 0;
        responseCode = 0;
        useproxy = false;
+       formData = false;
     };
     virtual  ~HTTPSend () {};
     virtual void  setMethod (const ustring& _method, bool fpost);
-    virtual void  setParam (ustring& dst, const ustring& name, const ustring& value);
-    virtual void  setParam (const ustring& name, const ustring& value);
-    virtual void  setGetParam (const ustring& name, const ustring& value);
-    virtual bool  submit (TcpClient& client, TcpBuf& buf);
-    virtual int  post (TcpClient& client, TcpBuf& buf, ustring& ans);
+    virtual bool  submit (TcpClient& client, TcpBuf& buf, MlEnv* mlenv);
+    virtual int  post (TcpClient& client, TcpBuf& buf, ustring& ans, MlEnv* mlenv);
 
     virtual void  makeHeader (ustring& q, const ustring& key, const ustring& val);
     virtual void  makeCookieHeader (ustring& q);
-    virtual ustring  query ();
+    virtual void  writeQueryForm (MNode* e, TcpClient& out);
+    virtual void  appendQueryForm (MNode* e, ustring& out);
+    virtual size_t  queryFormSize (MNode* e);
+    virtual void  makeSeparator ();
+    virtual size_t  writeFileForm (TcpClient* out, MlEnv* mlenv);
+    virtual size_t  writeFileFormPart_text (TcpClient* out, const ustring& name, const ustring& val);
+    virtual size_t  writeFileFormPart (TcpClient* out, const ustring& name, const ustring& filename, const ustring& path);
+    virtual size_t  writeFile (TcpClient* out, const ustring& path);
+    virtual ustring  query (MlEnv* mlenv);
     virtual int  readReplyHead (TcpClient& client, TcpBuf& buf);
     virtual void  readReplyBody (TcpClient& client, TcpBuf& buf, MotorOutput* out);
     virtual void  readReplyBody (TcpClient& client, TcpBuf& buf, ustring& ans);
index 7ac6ec1..053ef1b 100644 (file)
 #define kSSL_CLIENT_M_SERIAL   "SSL_CLIENT_M_SERIAL"
 #define kSSL_CLIENT_S_DN       "SSL_CLIENT_S_DN"
 #define kSSL_CLIENT_I_DN       "SSL_CLIENT_I_DN"
-#define SSL_CIPHER             "SSL_CIPHER"
-#define SSL_CIPHER_ALGKEYSIZE  "SSL_CIPHER_ALGKEYSIZE"
-#define SSL_CIPHER_EXPORT      "SSL_CIPHER_EXPORT"
-#define SSL_CIPHER_USEKEYSIZE  "SSL_CIPHER_USEKEYSIZE"
-#define SSL_CLIENT_VERIFY      "SSL_CLIENT_VERIFY"
-#define SSL_COMPRESS_METHOD    "SSL_COMPRESS_METHOD"
-#define SSL_PROTOCOL           "SSL_PROTOCOL"
-#define SSL_SERVER_A_KEY       "SSL_SERVER_A_KEY"
-#define SSL_SERVER_A_SIG       "SSL_SERVER_A_SIG"
-#define SSL_SERVER_I_DN                "SSL_SERVER_I_DN"
-#define SSL_SERVER_I_DN_C      "SSL_SERVER_I_DN_C"
-#define SSL_SERVER_I_DN_O      "SSL_SERVER_I_DN_O"
-#define SSL_SERVER_I_DN_OU     "SSL_SERVER_I_DN_OU"
-#define SSL_SERVER_M_SERIAL    "SSL_SERVER_M_SERIAL"
-#define SSL_SERVER_M_VERSION   "SSL_SERVER_M_VERSION"
-#define SSL_SERVER_S_DN                "SSL_SERVER_S_DN"
-#define SSL_SERVER_S_DN_C      "SSL_SERVER_S_DN_C"
-#define SSL_SERVER_S_DN_CN     "SSL_SERVER_S_DN_CN"
-#define SSL_SERVER_S_DN_L      "SSL_SERVER_S_DN_L"
-#define SSL_SERVER_S_DN_O      "SSL_SERVER_S_DN_O"
-#define SSL_SERVER_S_DN_ST     "SSL_SERVER_S_DN_ST"
-#define SSL_SERVER_V_END       "SSL_SERVER_V_END"
-#define SSL_SERVER_V_START     "SSL_SERVER_V_START"
-#define SSL_SESSION_ID         "SSL_SESSION_ID"
+#define kSSL_CIPHER            "SSL_CIPHER"
+#define kSSL_CIPHER_ALGKEYSIZE "SSL_CIPHER_ALGKEYSIZE"
+#define kSSL_CIPHER_EXPORT     "SSL_CIPHER_EXPORT"
+#define kSSL_CIPHER_USEKEYSIZE "SSL_CIPHER_USEKEYSIZE"
+#define kSSL_CLIENT_VERIFY     "SSL_CLIENT_VERIFY"
+#define kSSL_COMPRESS_METHOD   "SSL_COMPRESS_METHOD"
+#define kSSL_PROTOCOL          "SSL_PROTOCOL"
+#define kSSL_SERVER_A_KEY      "SSL_SERVER_A_KEY"
+#define kSSL_SERVER_A_SIG      "SSL_SERVER_A_SIG"
+#define kSSL_SERVER_I_DN       "SSL_SERVER_I_DN"
+#define kSSL_SERVER_I_DN_C     "SSL_SERVER_I_DN_C"
+#define kSSL_SERVER_I_DN_O     "SSL_SERVER_I_DN_O"
+#define kSSL_SERVER_I_DN_OU    "SSL_SERVER_I_DN_OU"
+#define kSSL_SERVER_M_SERIAL   "SSL_SERVER_M_SERIAL"
+#define kSSL_SERVER_M_VERSION  "SSL_SERVER_M_VERSION"
+#define kSSL_SERVER_S_DN       "SSL_SERVER_S_DN"
+#define kSSL_SERVER_S_DN_C     "SSL_SERVER_S_DN_C"
+#define kSSL_SERVER_S_DN_CN    "SSL_SERVER_S_DN_CN"
+#define kSSL_SERVER_S_DN_L     "SSL_SERVER_S_DN_L"
+#define kSSL_SERVER_S_DN_O     "SSL_SERVER_S_DN_O"
+#define kSSL_SERVER_S_DN_ST    "SSL_SERVER_S_DN_ST"
+#define kSSL_SERVER_V_END      "SSL_SERVER_V_END"
+#define kSSL_SERVER_V_START    "SSL_SERVER_V_START"
+#define kSSL_SESSION_ID                "SSL_SESSION_ID"
 #define kMETHOD_GET            "GET"
 #define kMETHOD_POST           "POST"
 #define kMIME_FORMDATA         "multipart/form-data"
index 85b4dc8..8f0b61a 100644 (file)
@@ -47,15 +47,30 @@ ustring  base64Decode (uiterator b, uiterator e) {
     u_int  c, x;
 
     size = e - b;
-    while (size >= 4) {
+//    while (size >= 4) {
+    while (size > 0) {
        c0 = *b ++;
        size --;
        if (isspace (c0)) {
        } else {
-           c1 = *b ++;
-           c2 = *b ++;
-           c3 = *b ++;
-           size -= 3;
+           if (size > 0) {
+               c1 = *b ++;
+               size --;
+           } else {
+               c1 = '=';
+           }
+           if (size > 0) {
+               c2 = *b ++;
+               size --;
+           } else {
+               c2 = '=';
+           }
+           if (size > 0) {
+               c3 = *b ++;
+               size --;
+           } else {
+               c3 = '=';
+           }
            x = 0;
 
            p = (char*)memchr (Base64Char, c0, sizeof (Base64Char) - 1);
index a0cdb8c..5554ebd 100644 (file)
@@ -4,6 +4,7 @@
 #include "ustring.h"
 
 #define  kCRLF "\r\n"
+#define  kQ2   "\""
 
 class  MNode;
 
index 109b1a9..455436b 100644 (file)
 #include "util_check.h"
 #include "ustring.h"
 #include <boost/regex.hpp>
-#include <string.h>
+#include <sys/uio.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/socket.h>
 #include <netdb.h>
-
-void  BasicTcpClient::init () {
-    addrInfo = NULL;
-    fd = -1;
-}
-
-void  BasicTcpClient::destruct () {
-    if (addrInfo) {
-       freeaddrinfo (addrInfo);
-       addrInfo = NULL;
-    }
-    close ();
-}
-
-void  BasicTcpClient::setAddr (const ustring& host, const ustring& port) {
-    assert (addrInfo == NULL);
-    if (! getaddrinfo (host.c_str (), port.c_str (), NULL, &addrInfo)) {
-    } else {
-       assert (addrInfo == NULL);
-    }
-}
-
-bool  BasicTcpClient::connect () {
-    struct addrinfo*  ai;
-
-    for (ai = addrInfo; ai; ai = ai->ai_next) {
-       if (ai->ai_family == PF_INET && connect_1 (ai))
-           return true;
-    }
-    return false;
-}
-
-void  BasicTcpClient::close () {
-    if (fd >= 0) {
-       ::close (fd);
-       fd = -1;
-    }
-}
-
-ssize_t  BasicTcpClient::read (void* buf, size_t nbytes) {
-    ssize_t  ans = 0;
-    fd_set  rfds;
-    struct timeval  tm;
-    int  rc;
-
-    FD_ZERO (&rfds);
-    FD_SET (fd, &rfds);
-    tm.tv_sec = limit;
-    tm.tv_usec = 0;
-    rc = select (fd + 1, &rfds, NULL, NULL, &tm);
-    if (rc > 0) {
-       ans = ::read (fd, buf, nbytes);
-    } else {
-       close ();
-    }
-    return ans;
-}
-
-ssize_t  BasicTcpClient::write (const void* buf, size_t nbytes) {
-    ssize_t  ans = 0;
-    ssize_t  s;
-    fd_set  wfds;
-    struct timeval  tm;
-    int  rc;
-    char*  p = (char*)buf;
-
-    while (nbytes > 0) {
-       FD_ZERO (&wfds);
-       FD_SET (fd, &wfds);
-       tm.tv_sec = limit;
-       tm.tv_usec = 0;
-       rc = select (fd + 1, NULL, &wfds, NULL, &tm);
-       if (rc > 0) {
-           s = ::write (fd, p, nbytes);
-           if (s == 0)
-               break;
-           ans += s;
-           p += s;
-           nbytes -= s;
-       } else {
-           close ();
-           break;
-       }
-    }
-    return ans;
-}
-
-bool  BasicTcpClient::connect_1 (struct addrinfo* ai) {
-//    struct sockaddr_in*  in;
-    int  rc;
-
-    assert (fd < 0);
-//    memset (&in, 0, sizeof (in));
-//    assert (ai->ai_family == PF_INET);
-//    in = (struct sockaddr_in*)ai->ai_addr;
-    fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
-    rc = ::connect (fd, ai->ai_addr, ai->ai_addrlen);
-    if (rc) {
-       close ();
-       return false;
-    }
-
-    return true;
-}
+#include <string.h>
+#include <unistd.h>
 
 //============================================================
 bool  TcpBuf::empty () {
@@ -168,37 +66,293 @@ void  TcpBuf::consume () {
 }
 
 //============================================================
-void  SslClient::setAddr (const ustring& _host, const ustring& _port) {
-    if (checkHostname (_host))
-       hostname = _host;
-    if (checkNum (_port))
-       port = _port;
+bool  TcpClient::connect (HostSpec& host) {
+    char pbuf[10];
+    const char*  bindaddr = NULL;
+    struct addrinfo  hints;
+    struct addrinfo*  res;
+    struct addrinfo*  res0;
+    bool  rc;
+
+    switch (host.ipv) {
+    case HostSpec::IPV4:
+       af = AF_INET;
+       break;
+    case HostSpec::IPV6:
+       af = AF_INET6;
+       break;
+    }
+
+    snprintf (pbuf, sizeof(pbuf), "%d", host.port);
+    memset (&hints, 0, sizeof (hints));
+    hints.ai_family = af;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = 0;
+    if ((err = getaddrinfo (host.host.c_str (), pbuf, &hints, &res0)) != 0) {
+//     seterr (err);
+       return false;
+    }
+    for (sd = -1, res = res0; res; res = res->ai_next) {
+       if ((sd = socket (res->ai_family, res->ai_socktype, res->ai_protocol)) == -1)
+           continue;
+       if (bindaddr != NULL && *bindaddr != '\0' && ! bind (bindaddr)) {
+//         failed to bind to 'bindaddr'
+           ::close (sd);
+           sd = -1;
+           continue;
+       }
+       if (::connect (sd, res->ai_addr, res->ai_addrlen) == 0)
+           break;
+       ::close (sd);
+       sd = -1;
+    }
+    freeaddrinfo (res0);
+    if (sd == -1) {
+//     syserr
+       return false;
+    }
+    
+#if 0
+    if (! reopen ()) {
+//     syserr
+       ::close(sd);
+    }
+#endif
+
+    rc = connect2 ();
+    if (! rc) {
+       close ();
+       return false;
+    }
+
+    noPush ();
+    return true;
+}
+
+bool  TcpClient::connect2 () {
+    // none
+    return true;
+}
+
+bool  TcpClient::bind (const char* addr) {
+    struct addrinfo  hints;
+    struct addrinfo*  res;
+    struct addrinfo*  res0;
+
+    memset (&hints, 0, sizeof (hints));
+    hints.ai_family = af;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = 0;
+    if ((err = getaddrinfo (addr, NULL, &hints, &res0)) != 0)
+       return false;
+    for (res = res0; res; res = res->ai_next)
+       if (::bind (sd, res->ai_addr, res->ai_addrlen) == 0)
+           return true;
+    return false;
+}
+
+void  TcpClient::noPush () {
+    int  val = 1;
+
+    setsockopt(sd, IPPROTO_TCP, TCP_NOPUSH, &val, sizeof(val));
+}
+
+void  TcpClient::close () {
+    if (sd >= 0) {
+       ::close (sd);
+       sd = -1;
+    }
+}
+
+ssize_t  TcpClient::read (void* buf, size_t nbytes) {
+    struct timeval  now;
+    struct timeval  timeout;
+    struct timeval  delta;
+    fd_set rfds;
+    ssize_t rlen, total;
+    int r;
+
+    if (timeLimit) {
+       FD_ZERO (&rfds);
+       gettimeofday (&timeout, NULL);
+       timeout.tv_sec += timeLimit;
+    }
+
+    total = 0;
+    while (nbytes > 0) {
+       while (timeLimit && ! FD_ISSET (sd, &rfds)) {
+           FD_SET (sd, &rfds);
+           gettimeofday (&now, NULL);
+           delta.tv_sec = timeout.tv_sec - now.tv_sec;
+           delta.tv_usec = timeout.tv_usec - now.tv_usec;
+           if (delta.tv_usec < 0) {
+               delta.tv_usec += 1000000;
+               delta.tv_sec --;
+           }
+           if (delta.tv_sec < 0) {
+               errno = ETIMEDOUT;
+//             syserr();
+               return -1;
+           }
+           errno = 0;
+           r = select (sd + 1, &rfds, NULL, NULL, &delta);
+           if (r == -1) {
+               if (errno == EINTR)
+                   continue;
+//             syserr();
+               return -1;
+           }
+       }
+       rlen = read2 (buf, nbytes);
+       if (rlen == 0)
+           break;
+       if (rlen < 0) {
+           if (errno == EINTR)
+               continue;
+           return -1;
+       }
+       nbytes -= rlen;
+       buf = (char*)buf + rlen;
+       total += rlen;
+    }
+    return total;
+}
+
+ssize_t  TcpClient::write (const void* buf, size_t nbytes) {
+    struct iovec iov;
+
+    iov.iov_base = __DECONST(char *, buf);
+    iov.iov_len = nbytes;
+    return write (&iov, 1);
+}
+
+void  TcpClient::flush_write () {
+    int  val;
+
+    val = 0;
+    setsockopt(sd, IPPROTO_TCP, TCP_NOPUSH, &val, sizeof(val));
+    val = 1;
+    setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
+}
+
+ssize_t  TcpClient::write (struct iovec* iov, int iovcnt) {
+    struct timeval  now;
+    struct timeval  timeout;
+    struct timeval  delta;
+    fd_set writefds;
+    ssize_t wlen, total;
+    int r;
+
+    if (timeLimit) {
+       FD_ZERO (&writefds);
+       gettimeofday (&timeout, NULL);
+       timeout.tv_sec += timeLimit;
+    }
+
+    total = 0;
+    while (iovcnt > 0) {
+       while (timeLimit && ! FD_ISSET (sd, &writefds)) {
+           FD_SET (sd, &writefds);
+           gettimeofday (&now, NULL);
+           delta.tv_sec = timeout.tv_sec - now.tv_sec;
+           delta.tv_usec = timeout.tv_usec - now.tv_usec;
+           if (delta.tv_usec < 0) {
+               delta.tv_usec += 1000000;
+               delta.tv_sec --;
+           }
+           if (delta.tv_sec < 0) {
+               errno = ETIMEDOUT;
+//             syserr();
+               return -1;
+           }
+           errno = 0;
+           r = select (sd + 1, NULL, &writefds, NULL, &delta);
+           if (r == -1) {
+               if (errno == EINTR)
+                   continue;
+               return -1;
+           }
+       }
+       errno = 0;
+       wlen = write2 (iov, iovcnt);
+       if (wlen == 0) {
+           /* we consider a short write a failure */
+           errno = EPIPE;
+//         syserr();
+           return -1;
+       }
+       if (wlen < 0) {
+           if (errno == EINTR)
+               continue;
+           return -1;
+       }
+       total += wlen;
+       while (iovcnt > 0 && wlen >= (ssize_t)iov->iov_len) {
+           wlen -= iov->iov_len;
+           iov++;
+           iovcnt--;
+       }
+       if (iovcnt > 0) {
+           iov->iov_len -= wlen;
+           iov->iov_base = __DECONST(char *, iov->iov_base) + wlen;
+       }
+    }
+    return total;
+}
+
+ssize_t  TcpClient::write2 (struct iovec* iov, int iovcnt) {
+    return writev (sd, iov, iovcnt);
 }
 
-bool  SslClient::connect () {
-    char*  argv[8];
-    int  rc;
+ssize_t  TcpClient::read2 (void* buf, size_t nbytes) {
+    return ::read (sd, buf, nbytes);
+}
+
+//============================================================
+bool  SslClient::connect (HostSpec& host) {
+    bool  rc;
+
+    rc = TcpClient::connect (host);
+    return rc;
+}
 
-    if (port.length () == 0)
-       port = ustring (CharConst ("443"));
-    argv[0] = (char*)cmd_httpsclient;
-    argv[1] = (char*)hostname.c_str ();
-    argv[2] = (char*)port.c_str ();
-    argv[3] = NULL;
-    rc = proc.open (argv);
-    return rc == 1;
+bool  SslClient::connect2 () {
+    return sslOpen ();
 }
 
-void  SslClient::close () {
-    proc.close ();
+bool  SslClient::sslOpen () {
+    if (!SSL_library_init()){
+       throw (ustring (CharConst ("SSL library init failed\n")));
+       close ();
+       return false;
+    }
+
+    SSL_load_error_strings();
+
+    ssl_meth = SSLv23_client_method();
+    ssl_ctx = SSL_CTX_new(ssl_meth);
+    SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
+
+    ssl = SSL_new(ssl_ctx);
+    if (ssl == NULL){
+       throw (ustring (CharConst ("SSL context creation failed\n")));
+       close ();
+       return false;
+    }
+    SSL_set_fd (ssl, sd);
+    if (SSL_connect(ssl) == -1){
+       ERR_print_errors_fp (stderr);
+       close ();
+       return false;
+    }
+    return true;
 }
 
-ssize_t  SslClient::read (void* buf, size_t nbytes) {
-    return proc.read ((char*)buf, nbytes);
+ssize_t  SslClient::write2 (struct iovec* iov, int iovcnt) {
+    return SSL_write(ssl, iov->iov_base, iov->iov_len);
 }
 
-ssize_t  SslClient::write (const void* buf, size_t nbytes) {
-    proc.write ((const char*)buf, nbytes);
-    return nbytes;
+ssize_t  SslClient::read2 (void* buf, size_t nbytes) {
+    return SSL_read (ssl, buf, nbytes);
 }
 
index c5ed935..e11be13 100644 (file)
@@ -1,50 +1,26 @@
 #ifndef UTIL_TCP_H
 #define UTIL_TCP_H
 
-#include "util_proc.h"
 #include "ustring.h"
+#include <ctype.h>
 #include <sys/types.h>
 #include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <openssl/crypto.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
 
-class  TcpClient {
- public:
-    TcpClient () {};
-    virtual  ~TcpClient () {};
-
-    virtual void  setAddr (const ustring& host, const ustring& port) = 0;
-    virtual bool  connect () = 0;
-    virtual void  close () = 0;
-    virtual ssize_t  read (void* buf, size_t nbytes) = 0;
-    virtual ssize_t  write (const void* buf, size_t nbytes) = 0;
-};
-
-class  BasicTcpClient: public TcpClient {
- public:
-    struct addrinfo*  addrInfo;
-    int  fd;
-    time_t  limit;
-
-    BasicTcpClient () {
 #ifdef DEBUG
-       limit = 10;
+#define DEFAULT_TIMELIMIT  10
 #else
-       limit = 120;
-#endif /* DEBUG */
-       init ();
-    };
-    virtual  ~BasicTcpClient () {
-       destruct ();
-    };
-    virtual void  init ();
-    virtual void  destruct ();
-    virtual void  setAddr (const ustring& host, const ustring& port);
-    virtual bool  connect ();
-    virtual void  close ();
-    virtual ssize_t  read (void* buf, size_t nbytes);
-    virtual ssize_t  write (const void* buf, size_t nbytes);
-    virtual bool  connect_1 (struct addrinfo* ai);
-};
+#define DEFAULT_TIMELIMIT  120
+#endif
 
+class  TcpClient;
 class  TcpBuf {
  public:
     ustring  buf;
@@ -64,20 +40,79 @@ class  TcpBuf {
     virtual void  consume ();
 };
 
-class  SslClient: public TcpClient {
+class  HostSpec {
  public:
-    ustring  hostname;
-    ustring  port;
-    ProcRW  proc;
+    enum {
+       IPV4,
+       IPV6,
+    }  ipv;
+    ustring  host;
+    int  port;
+    
+    HostSpec () {
+       ipv = IPV4;
+       port = 0;
+    };
+    virtual  ~HostSpec () {};
+    void  setIPv4 () {
+       ipv = IPV4;
+    };
+    void  setIPv6 () {
+       ipv = IPV6;
+    };
+};
 
-    SslClient () {};
-    virtual  ~SslClient () {};
+class  TcpClient {
+ public:
+    int  sd;
+    int  af;
+    int  err;
+    int  timeLimit;
 
-    virtual void  setAddr (const ustring& _host, const ustring& _port);
-    virtual bool  connect ();
+    TcpClient () {
+       sd = -1;
+       af = AF_UNSPEC;
+       err = 0;
+       timeLimit = DEFAULT_TIMELIMIT;
+    };
+    virtual  ~TcpClient () {
+       close ();
+    };
+    virtual bool  connect (HostSpec& host);
     virtual void  close ();
     virtual ssize_t  read (void* buf, size_t nbytes);
     virtual ssize_t  write (const void* buf, size_t nbytes);
+    virtual void  flush_write ();
+ protected:
+    virtual bool  bind (const char* addr);
+    virtual bool  connect2 ();
+    virtual void  noPush ();
+    virtual ssize_t  write (struct iovec* iov, int iovcnt);
+    virtual ssize_t  write2 (struct iovec* iov, int iovcnt);
+    virtual ssize_t  read2 (void* buf, size_t nbytes);
+};
+
+class  SslClient: public TcpClient {
+ public:
+    SSL*  ssl;
+    SSL_CTX*  ssl_ctx;
+    X509*  ssl_cert;
+    SSL_METHOD*  ssl_meth;
+
+    SslClient () {
+       ssl = NULL;
+       ssl_ctx = NULL;
+       ssl_cert = NULL;
+       ssl_meth = NULL;
+    };
+    virtual  ~SslClient () {};
+
+    virtual bool  connect (HostSpec& host);
+ protected:
+    virtual bool  connect2 ();
+    virtual bool  sslOpen ();
+    virtual ssize_t  write2 (struct iovec* iov, int iovcnt);
+    virtual ssize_t  read2 (void* buf, size_t nbytes);
 };
 
 #endif /* UTIL_TCP_H */
index b7f702e..e0e29b2 100644 (file)
@@ -93,86 +93,41 @@ static void  url_sub (const ustring& url, HTTPSend* http) {
                http->proto = uHttp;
                http->reqhost = ustring (m[2].first, m[2].second);
                http->path = str;
-               if (http->port.empty ())
-                   http->port.assign (CharConst ("80"));
+               if (http->host.port == 0)
+                   http->host.port = 80;
            }
        } else {
            http->proto = ustring (m[1].first, m[1].second);
-           http->host = ustring (m[2].first, m[2].second);
-           http->reqhost = http->host;
+           http->host.host = ustring (m[2].first, m[2].second);
+           http->reqhost = http->host.host;
            if (m[4].matched)
-               http->port = ustring (m[5].first, m[5].second);
+               http->host.port = to_uint32 (ustring (m[5].first, m[5].second));
            else
-               http->port.resize (0);
+               http->host.port = 0;
            http->path = urlencode (ustring (m[0].second - 1, e));
        }
     } else {
 //     throw (str + ": bad URL.");
        http->proto.resize (0);
-       http->host.resize (0);
-       http->port.resize (0);
+       http->host.host.resize (0);
+       http->host.port = 0;
        http->path = urlencode (str);
     }
 }
 
-static void  request_query (MNode* query, HTTPSend* http, bool getmethod = false) {
-    MNode*  a;
-    ustring* pp;
-
-#if 0
-    if (getmethod) {
-       pp = &http->getparams;
-    } else {
-       pp = &http->params;
-    }
-#endif
-    if (query && query->isCons ()) {
-       while (query) {
-           if (a = query->car ()) {
-#if 0
-               if (pp->size () > 0)
-                   pp->append (uAmp);
-               if (a->isCons ()) {
-                   pp->append (urlencode (to_string (a->car ()))).append (uEq).append (urlencode (to_string (a->cdr ())));
-               } else {
-                   pp->append (urlencode (to_string (a))).append (uEq);
-                   nextNode (query);
-                   if (query)
-                       pp->append (urlencode (to_string (query->car ())));
-               }
-#endif
-               if (getmethod) {
-                   http->setGetParam (to_string (a->car ()), to_string (a->cdr ()));
-               } else {
-                   http->setParam (to_string (a->car ()), to_string (a->cdr ()));
-               }
-           }
-           nextNode (query);
-       }
-    }
-    return;
-}
-
 static void  request_cookie (MNode* cookie, HTTPSend* http) {
     MNode*  a;
 
     if (cookie && cookie->isCons ()) {
        while (cookie) {
            if (a = cookie->car ()) {
-#if 0
-               if (http->cookie.size () > 0)
-                   http->cookie.append (CharConst ("; "));
-#endif
                if (a->isCons ()) {
-//                 http->cookie.append (cookieencode (to_string (a->car ()))).append (uEq).append (cookieencode (to_string (a->cdr ())));
                    http->cookie.push_back (HTTPSend::mapelem (to_string (a->car ()), to_string (a->cdr ())));
                } else {
-//                 http->cookie.append (cookieencode (to_string (a))).append (uEq);
                    ustring  t = to_string (a);
                    ustring  u;
                    nextNode (cookie);
                    if (cookie)
-//                     http->cookie.append (cookieencode (to_string (cookie->car ())));
                        u = to_string (cookie->car ());
                    http->cookie.push_back (HTTPSend::mapelem (t, u));
                }
@@ -375,7 +330,7 @@ MNode*  ml_response_no_cache (MNode* cell, MlEnv* mlenv) {
 
 /*DOC:
 ===$http-get==
- ($http-get [#post] [#sjis] [:id STRING] [:password STRING | :pw STRING] URL [:query '((NAME . VALUE) ...)] [:cookie '((NAME . VALUE) ...)] [:header '((NAME . VALUE) ...)] [SUBFUNCTION...])
+ ($http-get [#post] [#sjis] [#file] [:id STRING] [:password STRING | :pw STRING] URL [:query '((NAME . VALUE) ...)] [:cookie '((NAME . VALUE) ...)] [:header '((NAME . VALUE) ...)] [SUBFUNCTION...])
 
 */
 //#MFUNC       $http-get       ml_http_get     cMLHttpGetID
@@ -383,8 +338,6 @@ MNode*  ml_http_get (MNode* cell, MlEnv* mlenv) {
     MNode*  arg = cell->cdr ();
     MLHttpGet  obj (mlenv);
     ustring  url;
-    MNodePtr  query;
-    MNodePtr  getquery;
     MNodePtr  cookie;
     MNodePtr  headerquery;
 
@@ -407,18 +360,21 @@ MNode*  ml_http_get (MNode* cell, MlEnv* mlenv) {
        {CharConst ("header"), false},
        {CharConst ("get-query"), false},
        {CharConst ("sjis"), true},
+       {CharConst ("file"), true},
+       {CharConst ("post-file-serial"), false}, // 15
+       {CharConst ("post-file-named"), false},
        {NULL, 0, 0}
     };
 
     setParams (arg, 1, &params, kwlist, &keywords, &rest);
     url = eval_str (params[0], mlenv);
     assert (obj.http == NULL);
-    if (keywords[13]) {                // sjis
+    if (keywords[13] && eval_bool (keywords[13], mlenv)) { // sjis
        obj.http = new HTTPSendIConv ("SHIFT_JIS");
     } else {
        obj.http = new HTTPSend;
     }
-    if (keywords[0])           // post
+    if (keywords[0] && eval_bool (keywords[0], mlenv)) // post
        obj.http->setMethod (ustring (CharConst ("POST")), true);
     if (keywords[1])           // id
        obj.http->id = omitCtrl (eval_str (keywords[1], mlenv));
@@ -427,18 +383,17 @@ MNode*  ml_http_get (MNode* cell, MlEnv* mlenv) {
     if (keywords[3])           // pw
        obj.http->pw = omitCtrl (eval_str (keywords[3], mlenv));
     if (keywords[4])           // query
-       query = eval (keywords[4], mlenv);
+       obj.http->params = eval (keywords[4], mlenv);
     if (keywords[5])           // cookie
        cookie = eval (keywords[5], mlenv);
     if (keywords[6]) {         // proxy-host
-//     obj.http->host = omitNonAsciiWord (eval_str (keywords[6], mlenv));
        MNodePtr  h;
        h = eval (keywords[6], mlenv);
        if (! isNil (h ())) {
-           obj.http->host = omitNonAsciiWord (to_string (h ()));
+           obj.http->host.host = omitNonAsciiWord (to_string (h ()));
            obj.http->useproxy = true;
            if (keywords[7])            // proxy-port
-               obj.http->port = omitNonAsciiWord (eval_str (keywords[7], mlenv));
+               obj.http->host.port = to_uint32 (eval_str (keywords[7], mlenv));
            if (keywords[8])            // proxyid
                obj.http->proxyid = omitCtrl (eval_str (keywords[8], mlenv));
            if (keywords[9])            // proxypassword
@@ -451,26 +406,32 @@ MNode*  ml_http_get (MNode* cell, MlEnv* mlenv) {
        headerquery = eval (keywords[11], mlenv);
     }
     if (keywords[12]) {                // get-query
-       getquery = eval (keywords[12], mlenv);
+       obj.http->getparams = eval (keywords[12], mlenv);
+    }
+    if (keywords[14] && eval_bool (keywords[14], mlenv)) { // file
+       obj.http->formData = true;
+       obj.http->setMethod (ustring (CharConst ("POST")), true);
     }
+    if (keywords[15])          // post-file-serial
+       obj.http->fileparams_store = eval (keywords[15], mlenv);
+    if (keywords[16])          // post-file-named
+       obj.http->fileparams_storage = eval (keywords[16], mlenv);
     
     url_sub (url, obj.http);
     if (obj.http->proto.empty ()) {
        throw (obj.http->path + ": bad URL.");
     }
-    request_query (query (), obj.http);
-    request_query (getquery (), obj.http, true);
     request_cookie (cookie (), obj.http);
     request_headerquery (headerquery (), obj.http);
 
     if (obj.http->proto == uHttp) {
        if (! obj.client)
-           obj.client = new BasicTcpClient;
-       obj.http->submit (*obj.client, obj.buf);
+           obj.client = new TcpClient;
+       obj.http->submit (*obj.client, obj.buf, mlenv);
     } else if (obj.http->proto == uHttps) {
        if (! obj.client)
            obj.client = new SslClient;
-       obj.http->submit (*obj.client, obj.buf);
+       obj.http->submit (*obj.client, obj.buf, mlenv);
     } else {
        throw (obj.http->proto + ": protocol not supported.");
     }
@@ -579,7 +540,6 @@ MNode*  ml_http_get_http_response_output (MNode* cell, MlEnv* mlenv, MLFunc* mob
     if (keywords[0] && eval_bool (keywords[0], mlenv))
        cflag = true;
 
-//    obj->http->readReplyBody (*obj->client, obj->buf, std::cout);
     obj->http->readReplyBody (*obj->client, obj->buf, mlenv->env->output);
 
     if (! cflag)
@@ -667,26 +627,6 @@ MNode*  ml_http_content_type (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
     } else {
        return NULL;
     }
-
-#if 0
-    std::vector<std::pair<ustring,ustring> >::const_iterator  t, e;
-
-    t = obj->http->header_reply.begin ();
-    e = obj->http->header_reply.end ();
-    for (; t < e; t ++) {
-       if (match (t->first, CharConst ("content-type"))) {
-           uiterator  b, e, m;
-           b = t->second.begin ();
-           e = t->second.end ();
-           if (splitChar (b, e, ';', m)) {
-               return newMNode_str (new ustring (toLower_copy (b, m)));
-           } else {
-               return newMNode_str (new ustring (toLower_copy (b, e)));
-           }
-       }
-    }
-    return NULL;
-#endif
 }
 
 /*DOC:
index d35abc0..85407ae 100644 (file)
@@ -11,7 +11,6 @@ class  MlEnv;
 
 class  MLHttpGet: public MLFunc {
  public:
-//    HTTPSend  http;
     HTTPSend*  http;
     TcpClient*  client;
     TcpBuf  buf;