OSDN Git Service

http-get function.
authorvisor <visor@users.sourceforge.jp>
Sun, 27 Dec 2009 14:01:50 +0000 (23:01 +0900)
committervisor <visor@users.sourceforge.jp>
Sun, 27 Dec 2009 14:01:50 +0000 (23:01 +0900)
15 files changed:
bin/MKID.pl
bin/MKTABLE.pl
bin/MKWTABLE.pl
lib/http.cc
lib/http.h
lib/motoroutput.cc
lib/motoroutput.h
lib/util_string.cc
lib/util_string.h
lib/util_tcp.h
ml/Makefile
ml/main.cc
modules/ml-http.cc
modules/ml-http.h
modules/ml-xml.cc

index 52a9acb..f1a2b88 100755 (executable)
@@ -2,6 +2,8 @@
 
 my @ID;
 my @SRCS;
+my $target = "ml-id.h";
+my $targetTmp = "$target-$$";
 
 open (IN, "../Makefile.conf");
 while (<IN>) {
@@ -22,7 +24,7 @@ foreach (@SRCS) {
     }
 }
 
-open (OUT, "> ml-id.h");
+open (OUT, "> $targetTmp");
 print OUT "#ifndef ML_ID_H\n";
 print OUT "#define ML_ID_H\n\n";
 my $c = 0;
@@ -33,6 +35,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";
+}
+
 exit;
 
 sub  p {
@@ -62,3 +71,11 @@ sub  sum {
     }
     $sum;
 }
+
+sub  cmpFile {
+    my ($f1, $f2) = @_;
+    my ($rc);
+
+    $rc = system ('/usr/bin/cmp', '-s', $f1, $f2) >> 8;
+    return $rc;
+}
index 8442e11..c60b396 100755 (executable)
@@ -7,6 +7,8 @@ my @MTFN;
 my @WFN;
 my @HDR;
 my @SRCS;
+my $target = "ftable.cc";
+my $targetTmp = "$target-$$";
 
 open (IN, "../Makefile.conf");
 while (<IN>) {
@@ -27,7 +29,7 @@ foreach (@SRCS) {
     }
 }
 
-open (OUT, "> ftable.cc");
+open (OUT, "> $targetTmp");
 print OUT "#include \"ftable.h\"\n";
 print OUT "#include \"mftable.h\"\n";
 foreach (@HDR) {
@@ -41,6 +43,13 @@ print OUT "//============================================================\n";
 &wikiftable;
 close (OUT);
 
+if (-f $target && ! cmpFile ($target, $targetTmp)) {
+    unlink ($targetTmp);
+} else {
+    rename ($targetTmp, $target);
+    print "$target\n";
+}
+
 exit;
 
 sub  p {
@@ -162,3 +171,11 @@ sub  wikiftable {
     print OUT "FTable  GWikiFTable (wikiftable);\n";
     
 }
+
+sub  cmpFile {
+    my ($f1, $f2) = @_;
+    my ($rc);
+
+    $rc = system ('/usr/bin/cmp', '-s', $f1, $f2) >> 8;
+    return $rc;
+}
index 93d7c37..cf44b55 100755 (executable)
@@ -5,6 +5,8 @@ my @FN;
 my @FN2;
 my @HDR;
 my @SRCS;
+my $target = "wikitable.cc";
+my $targetTmp = "$target-$$";
 
 opendir (DIR, "../wiki");
 @a = readdir (DIR);
@@ -19,7 +21,7 @@ foreach (@SRCS) {
     &p ($_);
 }
 
-open (OUT, "> wikitable.cc");
+open (OUT, "> $targetTmp");
 print OUT "#include \"wikitable.h\"\n";
 foreach (@HDR) {
     print OUT "#include \"$_\"\n";
@@ -57,6 +59,13 @@ print OUT "WikiFuncTable  GWikiFuncTable (wftable);\n";
 print OUT "//============================================================\n";
 close (OUT);
 
+if (-f $target && ! cmpFile ($target, $targetTmp)) {
+    unlink ($targetTmp);
+} else {
+    rename ($targetTmp, $target);
+    print "$target\n";
+}
+
 exit;
 
 sub  p {
@@ -127,3 +136,11 @@ sub  setFN {
        }
     }
 }
+
+sub  cmpFile {
+    my ($f1, $f2) = @_;
+    my ($rc);
+
+    $rc = system ('/usr/bin/cmp', '-s', $f1, $f2) >> 8;
+    return $rc;
+}
index e6bc477..832d740 100644 (file)
@@ -327,7 +327,7 @@ ustring  HTTPSend::query () {
 int  HTTPSend::readReplyHead (TcpClient& client, TcpBuf& buf) {
     ustring  line;
     bool  rc;
-    uiterator  b, e;
+    uiterator  b, e, m1, m2;
 
     if (status != HTTP_QUERY)
        return 0;
@@ -347,10 +347,16 @@ int  HTTPSend::readReplyHead (TcpClient& client, TcpBuf& buf) {
            break;
        b = line.begin ();
        e = line.end ();
-       if (matchSkip (b, e, CharConst ("Set-Cookie:"))) {
-           skipSpace (b, e);
-           readCookie (b, e);
-       } else {
+       if (splitChar (b, e, ':', m1)) {
+           ustring  s;
+           m2 = m1 + 1;
+           skipSpace (m2, e);
+//         toLower ((ustring::iterator*)&b, (ustring::iterator*)&m1);
+           s = toLower (b, m1);
+           header_reply.push_back (mapelem (s, ustring (m2, e)));
+           if (match (s, CharConst ("set-cookie"))) {
+               readCookie (m2, e);
+           }
        }
     }
     status = HTTP_HEAD;
@@ -358,52 +364,56 @@ int  HTTPSend::readReplyHead (TcpClient& client, TcpBuf& buf) {
     return  responseCode;
 }
 
-void  HTTPSend::readReplyBody (TcpClient& client, TcpBuf& buf, ustring& ans) {
+void  HTTPSend::readReplyBody (TcpClient& client, TcpBuf& buf, MotorOutput* out) {
     if (status != HTTP_HEAD)
        return;
 
-    ans.assign (buf.start, buf.tail);
+    out->out (buf.start, buf.tail);
     buf.consume ();
     while (buf.fill (client)) {
-       ans.append (buf.start, buf.tail);
+       out->out (buf.start, buf.tail);
        buf.consume ();
     }
     status = HTTP_DONE;
 }
 
-void  HTTPSend::readReplyBody (TcpClient& client, TcpBuf& buf, std::ostream& out) {
-    if (status != HTTP_HEAD)
-       return;
+void  HTTPSend::readReplyBody (TcpClient& client, TcpBuf& buf, ustring& ans) {
+    std::stringstream  ostr;
+    MotorOutputOStream  out (&ostr);
+    readReplyBody (client, buf, &out);
+    ans = ostr.str ();
+}
 
-    out << ustring (buf.start, buf.tail);
-    buf.consume ();
-    while (buf.fill (client)) {
-       out << ustring (buf.start, buf.tail);
-       buf.consume ();
+const ustring*  HTTPSend::findHeader (const ustring& name) {
+    std::vector<mapelem>::const_iterator  b = header_reply.begin ();
+    std::vector<mapelem>::const_iterator  e = header_reply.end ();
+
+    for (; b < e; b ++) {
+       if (b->first == name) {
+           return &b->second;
+       }
     }
-    status = HTTP_DONE;
+    return NULL;
 }
 
 void  HTTPSend::readCookie (uiterator b, uiterator e) {
     std::vector<ustring>  ary;
-    ustring::size_type  ix;
-    uiterator  it, ie;
+    uiterator  ib, ie, im;
     static uregex  re ("; *");
 
     split (b, e, re, ary);
     if (ary.size () > 0) {
        CookieInfo  ci;
 
-       it = ary[0].begin ();
+       ib = ary[0].begin ();
        ie = ary[0].end ();
-       ix = ary[0].find ('=', 0);
-       if (ix == ustring::npos) {
-           ci.key = ary[0];
+       if (splitChar (ib, ie, '=', im)) {
+           ci.key.assign (ib, im);
+           ci.value.assign (im + 1, ie);
        } else {
-           ci.key.assign (it, it + ix);
-           ci.value.assign (it + ix + 1, ie);
+           ci.key.assign (ib, ie);
        }
-       cookie_get.push_back (ci);
+       cookie_reply.push_back (ci);
     }
 }
 
index cceca62..ebae8d4 100644 (file)
@@ -55,6 +55,8 @@ class  CookieInfo {
 
 class  HTTPSend {
  public:
+    typedef  std::pair<ustring,ustring>  mapelem;
+
     enum {
        HTTP_INIT,
        HTTP_OPEN,
@@ -71,7 +73,8 @@ class  HTTPSend {
     ustring  id;
     ustring  pw;
     ustring  cookie;
-    std::vector<CookieInfo>  cookie_get;
+    std::vector<mapelem>  header_reply;
+    std::vector<CookieInfo>  cookie_reply;
     int  responseCode;
 
     HTTPSend () {
@@ -85,8 +88,10 @@ class  HTTPSend {
 
     virtual ustring  query ();
     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);
-    virtual void  readReplyBody (TcpClient& client, TcpBuf& buf, std::ostream& out);
+    virtual const ustring*  findHeader (const ustring& name);
+ private:
     virtual void  readCookie (uiterator b, uiterator e);
 };
 
index 7393337..2706d70 100644 (file)
@@ -9,8 +9,6 @@
 #include <boost/lexical_cast.hpp>
 #include <iostream>
 
-using namespace  std;
-
 /* ============================================================ */
 static uregex  re_encode ("(<)|(>)|(&)|(\")|(')");
 static uregex  re_encode_br ("(<)|(>)|(&)|(\")|(')|(\n)");
@@ -163,8 +161,8 @@ MotorOutput*  MotorOutput::out_file (const ustring& src) {
 }
 
 /* ============================================================ */
-MotorOutput*  MotorOutputOStream::out (const ustring::value_type* s, size_t len) {
-    cout.write (s, len);
+MotorOutput*  MotorOutputCOut::out (const ustring::value_type* s, size_t len) {
+    std::cout.write (s, len);
     return this;
 }
 
@@ -175,6 +173,12 @@ MotorOutput*  MotorOutputString::out (const ustring::value_type* s, size_t len)
 }
 
 /* ============================================================ */
+MotorOutput*  MotorOutputOStream::out (const ustring::value_type* s, size_t len) {
+    ostream->write (s, len);
+    return this;
+}
+
+/* ============================================================ */
 static void  format_hex (ustring& ans, MNode* a, std::vector<ustring>& par, bool fcap) {
     uint32_t  v = 0;
     char  buf[32];
index 8fdf923..5064261 100644 (file)
@@ -44,10 +44,10 @@ class  MotorOutput {
     }
 };
 
-class  MotorOutputOStream: public MotorOutput {
+class  MotorOutputCOut: public MotorOutput {
  public:
-    MotorOutputOStream () {};
-    virtual  ~MotorOutputOStream () {};
+    MotorOutputCOut () {};
+    virtual  ~MotorOutputCOut () {};
 
     virtual MotorOutput*  out (const ustring::value_type* s, size_t len);
 };
@@ -70,6 +70,16 @@ class  MotorOutputString: public MotorOutput {
     };
 };
 
+class  MotorOutputOStream: public MotorOutput {
+ public:
+    std::ostream*  ostream;
+
+    MotorOutputOStream (std::ostream* _ostream): ostream (_ostream) {};
+    virtual  ~MotorOutputOStream () {};
+
+    virtual MotorOutput*  out (const ustring::value_type* s, size_t len);
+};
+
 class  MNodePtr;
 ustring  outamp (const ustring& t);
 ustring  outamp_br (const ustring& t);
index 3e4638f..2f092a5 100644 (file)
@@ -7,6 +7,7 @@
 #include <boost/regex.hpp>
 #include <iconv.h>
 #include <vector>
+#include <algorithm>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
@@ -290,19 +291,16 @@ void  split (uiterator b, uiterator e, uregex& re, std::vector<ustring>& ans) {
     }
 }
 
-/*
-bool  splitChar (uiterator b, uiterator e, uiterator::value_type ch, uiterator& m1, uiterator& m2) {
+bool  splitChar (uiterator b, uiterator e, uiterator::value_type ch, uiterator& m1) {
     for (; b < e; b ++) {
        if (*b == ch) {
-           m2 = m1 = b;
-           m2 ++;
+           m1 = b;
            return true;
        }
     }
-    m1 = m2 = e;
+    m1 = e;
     return false;
 }
-*/
 
 static char  Base64Char[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 ustring  base64Encode (uiterator b, uiterator e) {
@@ -749,3 +747,28 @@ void  skipSpace (uiterator& b, uiterator e) {
        b ++;
     }
 }
+
+static ustring::value_type  toLower_ustring_value (ustring::value_type v) {
+    if ('A' <= v && v <= 'Z') {
+       return v - 'A' + 'a';
+    } else {
+       return v;
+    }
+}
+
+#if 0
+void  toLower (ustring::iterator* b, ustring::iterator* e) {
+    transform (*b, *e, *b, toLower_ustring_value);
+}
+#endif
+
+ustring  toLower (uiterator b, uiterator e) {
+    ustring::iterator  i;
+    ustring  ans;
+    ans.resize (e - b);
+    i = ans.begin ();
+    for (; b < e; b ++, i++) {
+       *i = toLower_ustring_value (*b);
+    }
+    return ans;
+}
index 0887ad8..00d66d9 100644 (file)
@@ -168,7 +168,7 @@ ustring  dirPart (char* path);
 ustring  dirPart (const ustring& path);
 ustring  filePart_osSafe (const ustring& path);
 void  split (uiterator b, uiterator e, uregex& re, std::vector<ustring>& ans);
-//bool  splitChar (uiterator& b, uiterator& e, uiterator::value_type ch, uiterator& m1, uiterator& m2);
+bool  splitChar (uiterator b, uiterator e, uiterator::value_type ch, uiterator& m1);
 ustring  base64Encode (uiterator b, uiterator e);
 ustring  filenameEncode (const ustring& text);
 ustring  escape_re (const ustring& text);
@@ -202,5 +202,6 @@ ustring  dtoustring (double val);
 uint32_t  hextoul (uiterator b, uiterator e);
 ustring  toCRLF (const ustring& str);
 void  skipSpace (uiterator& b, uiterator e);
+ustring  toLower (uiterator b, uiterator e);
 
 #endif /* UTIL_STRING_H */
index 37af75f..d19e5d1 100644 (file)
@@ -39,8 +39,8 @@ class  TcpBuf {
     ustring::iterator  tail;
 
     TcpBuf () {
-//     buf.assign (65536, '\0');
-       buf.assign (256, 0);
+       buf.assign (65536, '\0');
+//     buf.assign (256, 0);
        start = tail = buf.begin ();
     };
     virtual  ~TcpBuf () {};
index a30db8a..3e651c8 100644 (file)
@@ -108,7 +108,7 @@ beforedepend:
        ../bin/MKWTABLE.pl
        ../bin/MKID.pl
 
-ftable.cc: ${MSRCS}
+ftable.cc: ${MSRCS} ../Makefile.conf
 #ftable.cc:
        ../bin/MKTABLE.pl
 
@@ -116,7 +116,7 @@ wikitable.cc: wikicmd.cc wikiline.cc
 #wikitable.cc:
        ../bin/MKWTABLE.pl
 
-ml-id.h: ${MSRCS}
+ml-id.h: ${MSRCS} ../Makefile.conf
 #ml-id.h:
        ../bin/MKID.pl
 
index 31e036d..f30e51c 100644 (file)
@@ -30,7 +30,7 @@ int  main (int argc, char** argv) {
     } else {
 //     form = new CGIFormUTF8;
        form = new CGIFormUTF8JPMS;
-       out = new MotorOutputOStream;
+       out = new MotorOutputCOut;
     }
 #else
     form = new CGIFormUTF8;
@@ -78,4 +78,6 @@ int  main (int argc, char** argv) {
  Ex1:;
     delete out;
     delete form;
+
+    return 0;
 }
index 71c6a14..0f1cc05 100644 (file)
@@ -2,6 +2,7 @@
 #include "ml.h"
 #include "mlenv.h"
 #include "motorenv.h"
+#include "motoroutput.h"
 #include "util_check.h"
 #include "util_string.h"
 #include "http.h"
@@ -335,10 +336,11 @@ MNode*  ml_http_get_http_response_file (MNode* cell, MlEnv* mlenv, MLFunc* mobj)
     tgt = mlenv->env->path_store_file (name);
     tmp.assign (tgt).append (CharConst ("-tmp")).append (boost::lexical_cast<ustring> (getpid ()));
     {
-       std::ofstream  out;
-       out.open (tmp.c_str (), std::ios_base::out | std::ios_base::binary);
-       obj->http.readReplyBody (obj->client, obj->buf, out);
-       out.close ();
+       std::ofstream  stream;
+       MotorOutputOStream  out (&stream);
+       stream.open (tmp.c_str (), std::ios_base::out | std::ios_base::binary);
+       obj->http.readReplyBody (obj->client, obj->buf, &out);
+       stream.close ();
        rename (tmp.c_str (), tgt.c_str ());
     }
 
@@ -355,7 +357,8 @@ MNode*  ml_http_get_http_response_output (MNode* cell, MlEnv* mlenv, MLFunc* mob
     MNode*  arg = cell->cdr ();
     MLHttpGet*  obj = (MLHttpGet*)mobj;
 
-    obj->http.readReplyBody (obj->client, obj->buf, std::cout);
+//    obj->http.readReplyBody (obj->client, obj->buf, std::cout);
+    obj->http.readReplyBody (obj->client, obj->buf, mlenv->env->output);
 
     return NULL;
 }
@@ -379,9 +382,9 @@ MNode*  ml_http_get_get_cookie (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
     if (arg)
        throw (uErrorWrongNumber);
 
-    for (i = 0; i < obj->http.cookie_get.size (); i ++) {
-       if (obj->http.cookie_get[i].key == name) {
-           return newMNode_str (new ustring (obj->http.cookie_get[i].value));
+    for (i = 0; i < obj->http.cookie_reply.size (); i ++) {
+       if (obj->http.cookie_reply[i].key == name) {
+           return newMNode_str (new ustring (obj->http.cookie_reply[i].value));
        }
     }
 
@@ -404,13 +407,88 @@ MNode*  ml_http_get_get_cookie_all (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
     if (arg)
        throw (uErrorWrongNumber);
 
-    for (i = 0; i < obj->http.cookie_get.size (); i ++) {
+    for (i = 0; i < obj->http.cookie_reply.size (); i ++) {
        a = new MNode;
-       a->set_car (newMNode_str (new ustring (obj->http.cookie_get[i].key)));
+       a->set_car (newMNode_str (new ustring (obj->http.cookie_reply[i].key)));
        a->set_cdr (new MNode);
-       a->cdr ()->set_car (newMNode_str (new ustring (obj->http.cookie_get[i].value)));
+       a->cdr ()->set_car (newMNode_str (new ustring (obj->http.cookie_reply[i].value)));
        ans.append (a);
     }
 
     return ans.release ();
 }
+
+/*DOC:
+====http-content-type====
+ (http-content-type) -> STRING
+
+*/
+//#SFUNC       http-content-type       ml_http_content_type
+MNode*  ml_http_content_type (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
+    MNode*  arg = cell->cdr ();
+    MLHttpGet*  obj = (MLHttpGet*)mobj;
+    const ustring*  u;
+    static ustring  name (CharConst ("content-type"));
+
+    u = obj->http.findHeader (name);
+    if (u) {
+       uiterator  b, e, m;
+       b = u->begin ();
+       e = u->end ();
+       if (splitChar (b, e, ';', m)) {
+           return newMNode_str (new ustring (toLower (b, m)));
+       } else {
+           return newMNode_str (new ustring (toLower (b, e)));
+       }
+    } 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:
+====http-get-header====
+ (http-get-header NAME) -> STRING
+
+*/
+//#SFUNC       http-get-header ml_http_get_header
+MNode*  ml_http_get_header (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
+    MNode*  arg = cell->cdr ();
+    MLHttpGet*  obj = (MLHttpGet*)mobj;
+    ustring  name;
+    const ustring*  u;
+
+    if (! arg)
+       throw (uErrorWrongNumber);
+    name = eval_str (arg->car (), mlenv);
+    nextNode (arg);
+    if (arg)
+       throw (uErrorWrongNumber);
+
+    name = toLower (name.begin (), name.end ());
+    u = obj->http.findHeader (name);
+    if (u) {
+       return newMNode_str (new ustring (*u));
+    } else {
+       return NULL;
+    }
+}
index 44acf50..2ee1c36 100644 (file)
@@ -30,5 +30,7 @@ MNode*  ml_http_get_http_response_file (MNode* cell, MlEnv* mlenv, MLFunc* mobj)
 MNode*  ml_http_get_http_response_output (MNode* cell, MlEnv* mlenv, MLFunc* mobj);
 MNode*  ml_http_get_get_cookie (MNode* cell, MlEnv* mlenv, MLFunc* mobj);
 MNode*  ml_http_get_get_cookie_all (MNode* cell, MlEnv* mlenv, MLFunc* mobj);
+MNode*  ml_http_content_type (MNode* cell, MlEnv* mlenv, MLFunc* mobj);
+MNode*  ml_http_get_header (MNode* cell, MlEnv* mlenv, MLFunc* mobj);
 
 #endif /* ML_HTTP_H */
index 331642d..42563bc 100644 (file)
@@ -273,7 +273,7 @@ MNode*  ml_xml_output (MNode* cell, MlEnv* mlenv) {
     if (! mlenv->env->responseDone)
        mlenv->env->standardResponse (ustring (CharConst (kMIME_XML)), ustring (CharConst (kCODE_UTF8)));
 
-    MotorOutputOStream  out;
+    MotorOutputCOut  out;
 
     out.out (CharConst ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"));
     xmlWrite (&out, xml ());