OSDN Git Service

fix percent encode functions.
authorvisor <visor@users.sourceforge.jp>
Tue, 27 Mar 2012 15:33:27 +0000 (00:33 +0900)
committervisor <visor@users.sourceforge.jp>
Tue, 27 Mar 2012 15:33:27 +0000 (00:33 +0900)
lib/http.cc
lib/util_string.cc
lib/util_string.h
modules/ml-encode.cc
modules/ml-http.cc
modules/motor-function.cc
wiki/wikimotor.cc

index aa5debf..46a9e44 100644 (file)
@@ -422,10 +422,11 @@ ustring  HTTPSend::query (MlEnv* mlenv) {
        }
        q.append (CharConst (" HTTP/1.0" kCRLF));
     } else {
-       q.append (CharConst ("?"));
        if (getparams ()) {
+           q.append (CharConst ("?"));
            appendQueryForm (getparams (), q);
        } else if (params ()) {
+           q.append (CharConst ("?"));
            appendQueryForm (params (), q);
        }
        q.append (CharConst (" HTTP/1.0" kCRLF));
@@ -471,12 +472,11 @@ void  HTTPSend::writeQueryForm (MNode* e, TcpClient& out) {
        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 (uAmp);
+               u.append (percentEncode (cv (to_string (a->car ()))));
                u.append (uEq);
                out.write (&*u.begin (), u.length ());
-               u.assign (urlencode (cv (to_string (a->cdr ()))));
+               u.assign (percentEncode (cv (to_string (a->cdr ()))));
                out.write (&*u.begin (), u.length ());
                c ++;
            }
@@ -493,11 +493,10 @@ void  HTTPSend::appendQueryForm (MNode* e, ustring& out) {
        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 (uAmp);
+               out.append (percentEncode (cv (to_string (a->car ()))));
                out.append (uEq);
-               out.append (urlencode (cv (to_string (a->cdr ()))));
+               out.append (percentEncode (cv (to_string (a->cdr ()))));
                c ++;
            }
            nextNode (e);
@@ -515,12 +514,11 @@ size_t  HTTPSend::queryFormSize (MNode* e) {
        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 (uAmp);
+               u.append (percentEncode (cv (to_string (a->car ()))));
                u.append (uEq);
                ans += u.length ();
-               u.assign (urlencode (cv (to_string (a->cdr ()))));
+               u.assign (percentEncode (cv (to_string (a->cdr ()))));
                ans += u.length ();
                c ++;
            }
@@ -616,7 +614,7 @@ size_t  HTTPSend::writeFileFormPart_text (TcpClient* out, const ustring& name, c
     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 (CharConst ("Content-Disposition: form-data; name=" kQ2)).append (percentEncode (cv (name))).append (CharConst (kQ2 kCRLF kCRLF));
     u.append (cv (val)).append (uCRLF);
     if (out)
        out->write (&*u.begin (), u.length ());
@@ -634,7 +632,7 @@ size_t  HTTPSend::writeFileFormPart (TcpClient* out, const ustring& name, const
     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-Disposition: form-data; name=" kQ2)).append (percentEncode (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 ());
index 100e771..cbf9ccd 100644 (file)
@@ -132,6 +132,15 @@ static char  hexchar (int c) {
        return '0';
 }
 
+static char  hexchar_c (int c) {
+    if (0 <= c && c <= 9)
+       return '0' + c;
+    else if (10 <= c <= 15)
+       return 'A' - 10 + c;
+    else
+       return '0';
+}
+
 static ustring  percentHex (int c) {
     ustring  ans (3, '%');
 
@@ -140,6 +149,14 @@ static ustring  percentHex (int c) {
     return ans;
 }
 
+static ustring  percentHEX (int c) {
+    ustring  ans (3, '%');
+
+    ans[1] = hexchar_c ((c >> 4) & 0x0f);
+    ans[2] = hexchar_c (c & 0x0f);
+    return ans;
+}
+
 ustring  urldecode_nonul (const ustring& str) {
     ustring  ans;
     static uregex  re ("(\\+)|%([0-9a-fA-F][0-9a-fA-F])|\\x00");
@@ -224,6 +241,7 @@ bool  to_bool (const ustring& v) {
     }
 }
 
+#if 0
 static ustring  percentEncode (const ustring& text, uregex& re) {
     /* $1 -> _
        $2 -> %HEX
@@ -267,12 +285,71 @@ static ustring  percentEncode (const ustring& text, uregex& re) {
        return text;
     }
 }
+#endif
+
+static ustring  percentEncode (uiterator b, uiterator e, const uregex& re) {
+    // $1 -> _
+    // $2 -> %HEX
+    umatch  m;
+    ustring  ans;
+
+    while (b < e && usearch (b, e, m, re)) {
+       if (b < m[0].first)
+           ans.append (b, m[0].first);
+       if (m[1].matched) {
+           ans.append (uUScore);
+       } else if (m[2].matched) {
+           ans.append (percentHEX (*m[2].first));
+       } else {
+           assert (0);
+       }
+       b = m[0].second;
+    }
+    if (b < e)
+       ans.append (b, e);
+
+    return ans;
+}
 
+#if 0
 ustring  urlencode (const ustring& url) {
     static uregex  re ("(\\x00)|([^a-zA-Z0-9_.,/\x80-\xff-])");
     
     return percentEncode (url, re);
 }
+#endif
+
+ustring  percentEncode (uiterator b, uiterator e) {
+    static uregex  re ("(\\x00)|([^A-Za-z0-9_.~\x80-\xff-])");
+
+    return percentEncode (b, e, re);
+}
+
+ustring  percentEncode (const ustring& str) {
+    return percentEncode (str.begin (), str.end ());
+}
+
+ustring  percentEncode_path (uiterator b, uiterator e) {
+    uiterator  i;
+    ustring  ans;
+
+    for (i = b; i < e; i ++) {
+       if (*i == '/') {
+           if (b < i)
+               ans.append (percentEncode (b, i));
+           ans.append (CharConst ("/"));
+           b = i + 1;
+       }
+    }
+    if (b < e)
+       ans.append (percentEncode (b, e));
+
+    return ans;
+}
+
+ustring  percentEncode_path (const ustring& str) {
+    percentEncode_path (str.begin (), str.end ());
+}
 
 ustring  percentDecode (const ustring& str) {
     ustring  ans;
@@ -304,7 +381,7 @@ ustring  percentDecode (const ustring& str) {
 ustring  cookieencode (const ustring& text) {
     static uregex  re ("([\\x00-\\x1f\\x7f])|([ ,;%\\x80-\\xff])");
 
-    return percentEncode (text, re);
+    return percentEncode (text.begin (), text.end (), re);
 }
 
 ustring  cookiedecode (const ustring& text) {
index ee26335..c082c5e 100644 (file)
@@ -57,7 +57,10 @@ ustring  omitNL (const ustring& str);
 ustring  omitNonAscii (const ustring& str);
 ustring  omitNonAsciiWord (const ustring& str);
 bool  to_bool (const ustring& v);
-ustring  urlencode (const ustring& url);
+ustring  percentEncode (uiterator b, uiterator e);
+ustring  percentEncode (const ustring& str);
+ustring  percentEncode_path (uiterator b, uiterator e);
+ustring  percentEncode_path (const ustring& str);
 ustring  percentDecode (const ustring& str);
 ustring  cookieencode (const ustring& text);
 ustring  cookiedecode (const ustring& text);
index 707e9b7..e46213a 100644 (file)
@@ -164,7 +164,7 @@ MNode*  ml_percent_encode (MNode* cell, MlEnv* mlenv) {
        nextNode (arg);
     }
 
-    return newMNode_str (new ustring (urlencode (str)));
+    return newMNode_str (new ustring (percentEncode (str)));
 }
 
 /*DOC:
index 3cdbe23..535b504 100644 (file)
@@ -14,7 +14,6 @@
 static void  location_sub (ustring& url, MNode* query, MNode* arg, MlEnv* mlenv) {
     MNodePtr  p;
     MNode*  a;
-    ustring  str;
     int  c;
     uiterator  b, e;
     umatch  m;
@@ -23,10 +22,9 @@ static void  location_sub (ustring& url, MNode* query, MNode* arg, MlEnv* mlenv)
     b = url.begin ();
     e = url.end ();
     if (usearch (b, e, m, re)) {
-       str = ustring (m[0].second, e);
-       url = ustring (m[0].first, m[0].second) + urlencode (str);
+       url = ustring (m[0].first, m[0].second) + percentEncode_path (m[0].second, e);
     } else {
-       url = urlencode (url);
+       url = percentEncode_path (url);
     }
 
     c = 0;
@@ -38,9 +36,9 @@ static void  location_sub (ustring& url, MNode* query, MNode* arg, MlEnv* mlenv)
            else
                url.append (CharConst ("&"));
            c ++;
-           url.append (urlencode (to_string (a->car ())));
+           url.append (percentEncode (to_string (a->car ())));
            url.append (uEq);
-           url.append (urlencode (to_string (a->cdr ())));
+           url.append (percentEncode (to_string (a->cdr ())));
        } else {
            throw (to_string (a) + uErrorBadValue);
        }
@@ -63,13 +61,11 @@ static void  location_sub (ustring& url, MNode* query, MNode* arg, MlEnv* mlenv)
                url.append (CharConst ("&"));
            c ++;
        
-           str = to_string (p ()->car ());
-           url.append (urlencode (str));
+           url.append (percentEncode (to_string (p ()->car ())));
            url.append (uEq);
            a = p ()->cdr ();
            if (a && a->isCons ()) {
-               str = to_string (a->car ());
-               url.append (urlencode (str));
+               url.append (percentEncode (to_string (a->car ())));
            }
        }
        nextNode (arg);
@@ -104,14 +100,14 @@ static void  url_sub (const ustring& url, HTTPSend* http) {
                http->host.port = to_uint32 (ustring (m[5].first, m[5].second));
            else
                http->host.port = 0;
-           http->path = urlencode (ustring (m[0].second - 1, e));
+           http->path = percentEncode_path (m[0].second - 1, e);
        }
     } else {
 //     throw (str + ": bad URL.");
        http->proto.resize (0);
        http->host.host.resize (0);
        http->host.port = 0;
-       http->path = urlencode (str);
+       http->path = percentEncode_path (str);
     }
 }
 
index 3086282..715a0ae 100644 (file)
@@ -82,14 +82,11 @@ void  mf_js (const std::vector<ustring>& args, MlEnv* mlenv) {
 //#MTFUNC      url     mf_url
 void  mf_url (const std::vector<ustring>& args, MlEnv* mlenv) {
     MNode*  v;
-    ustring  u;
 
     if (args.size () == 1) {
        v = mlenv->getVar (args[0]);
        if (v) {
-           u = v->to_string ();
-           u = urlencode (u);
-           mlenv->env->output->out_raw (u);
+           mlenv->env->output->out_raw (percentEncode_path (v->to_string ()));
        }
     } else {
        throw (uErrorWrongNumber);              // ***
index bed654e..1c20b60 100644 (file)
@@ -518,12 +518,10 @@ bool  WikiMotorObjVec::splitURLPath (WikiFormat* wiki, ustring& path, ustring& p
     vpath.splitCharA ('/', names);
     n = names.size () - 1;
     for (i = 0; i <= n; i ++) {
-       u = urlencode (names[i]->textOut (wiki));
-       if (i > 0) {
-           path.append (uSlash).append (u);
-       } else {
-           path.append (u);
-       }
+       u = percentEncode (names[i]->textOut (wiki));
+       if (i > 0)
+           path.append (uSlash);
+       path.append (u);
     }
 
     if (fparams) {
@@ -534,15 +532,15 @@ bool  WikiMotorObjVec::splitURLPath (WikiFormat* wiki, ustring& path, ustring& p
            if (i > 0)
                params.append (uAmp);
            if (namevals[i].get()->splitChar (wiki, '=', name, value)) {
-               params.append (urlencode (name)).append (uEq).append (urlencode (value));
+               params.append (percentEncode (name)).append (uEq).append (percentEncode (value));
            } else {
-               params.append (urlencode (name));
+               params.append (percentEncode (name));
            }
        }
     }
 
     if (fanchor) {
-       anchor = urlencode (vanchor.textOut (wiki));
+       anchor = percentEncode (vanchor.textOut (wiki));
     }
 
     return true;