6 #include "motoroutput.h"
7 #include "util_check.h"
8 #include "util_string.h"
10 #include "http-iconv.h"
17 static void location_sub (ustring& url, MNode* query, MlEnv* mlenv) {
18 upair scheme, delim, user, pass, host, port, rest;
21 if (checkURL (url, &scheme, &delim, &user, &pass, &host, &port, &rest)) {
22 ans.assign (scheme.first, scheme.second).append (delim.first, delim.second);
23 if (user.first != user.second) {
24 ans.append (user.first, user.second);
25 if (pass.first != pass.second) {
26 ans.append (uColon).append (pass.first, pass.second);
28 ans.append (CharConst ("@"));
30 ans.append (host.first, host.second);
31 if (port.first != port.second) {
32 ans.append (uColon).append (port.first, port.second);
35 ans.append (urlencode_path (rest.first, rest.second));
37 ans.append (percentEncode_path (rest.first, rest.second));
41 ans.assign (urlencode_path (url.begin (), url.end ()));
43 ans.assign (percentEncode_path (url.begin (), url.end ()));
47 ans.append (buildQuery (query));
52 static void url_sub (const ustring& url, HTTPSend* http, bool noencode) {
56 static uregex re ("^([a-z]{1,6})://([a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*)(:([0-9]{1,5}))?/");
61 if (usearch (b, e, m, re)) {
62 http->proto = ustring (m[1].first, m[1].second);
63 http->host.host = ustring (m[2].first, m[2].second);
65 http->host.port = to_uint32 (ustring (m[5].first, m[5].second));
67 if (http->proto == uHttps)
68 http->host.port = 443;
72 if (http->proto == uHttps) {
73 // throw (ustring (CharConst ("proxy connection of SSL protocol not implemented.")));
74 // XXX experimental https proxy connection.
76 http->path = ustring (m[0].second - 1, e);
78 http->path = percentEncode_path (m[0].second - 1, e);
83 http->path = ustring (b, m[0].second - 1);
84 http->path.append (percentEncode_path (m[0].second - 1, e));
88 http->conhost = http->host;
90 http->path = ustring (m[0].second - 1, e);
92 http->path = percentEncode_path (m[0].second - 1, e);
95 // throw (str + ": bad URL.");
96 http->proto.resize (0);
97 http->host.host.resize (0);
102 http->path = percentEncode_path (str);
106 static void request_cookie (MNode* cookie, HTTPSend* http) {
109 if (cookie && cookie->isCons ()) {
111 if ((a = cookie->car ())) {
113 http->cookie.push_back (HTTPSend::mapelem (to_string (a->car ()), to_string (a->cdr ())));
115 ustring t = to_string (a);
119 u = to_string (cookie->car ());
120 http->cookie.push_back (HTTPSend::mapelem (t, u));
128 static void request_headerquery (MNode* headerquery, HTTPSend* http) {
131 if (headerquery && headerquery->isCons ()) {
132 while (headerquery) {
133 if ((a = headerquery->car ())) {
135 http->header_req.push_back (HTTPSend::mapelem (to_string (a->car ()), to_string (a->cdr ())));
137 nextNode (headerquery);
139 http->header_req.push_back (HTTPSend::mapelem (to_string (a), to_string (headerquery->car ())));
142 nextNode (headerquery);
154 (error [#continue | :continue BOOL] [:error-var VARIABLE]) -> NIL
155 error-htmlコマンドオプションで指定したひな形を出力する。
158 //#AFUNC error ml_error
159 MNode* ml_error (MNode* cell, MlEnv* mlenv) {
160 MNode* arg = cell->cdr ();
163 std::vector<MNode*> keywords;
164 static paramList kwlist[] = {
165 {CharConst ("continue"), true},
166 {CharConst ("error-var"), false},
170 setParams (arg, 0, NULL, kwlist, &keywords, NULL);
171 if (keywords[0] && eval_bool (keywords[0], mlenv))
174 ev = eval (keywords[1], mlenv);
178 mlenv->env->setErrorFlag ();
180 if (ev ()->isCons ()) {
182 while (a && a->isCons ()) {
183 mlenv->env->setErrorVar (to_string (a->car ()));
187 mlenv->env->setErrorVar (to_string (ev ()));
200 (forbidden [#continue | :continue BOOL]) -> NIL
201 403 Forbiddenレスポンスを出力する。
202 continueオプションを付けない場合,以降のファンクションの実行を中断する。
205 //#AFUNC forbidden ml_forbidden
206 MNode* ml_forbidden (MNode* cell, MlEnv* mlenv) {
207 MNode* arg = cell->cdr ();
209 std::vector<MNode*> keywords;
210 static paramList kwlist[] = {
211 {CharConst ("continue"), true},
215 setParams (arg, 0, NULL, kwlist, &keywords, NULL);
216 if (keywords[0] && eval_bool (keywords[0], mlenv))
219 if (! mlenv->env->responseDone)
220 mlenv->env->forbiddenResponse ();
221 mlenv->env->setErrorFlag ();
231 (no-content [#continue | :continue BOOL]) -> NIL
232 200 No Contentレスポンスを出力する。
233 continueオプションを付けない場合,以降のファンクションの実行を中断する。
236 //#AFUNC no-content ml_no_content
237 MNode* ml_no_content (MNode* cell, MlEnv* mlenv) {
238 MNode* arg = cell->cdr ();
240 std::vector<MNode*> keywords;
241 static paramList kwlist[] = {
242 {CharConst ("continue"), true},
246 setParams (arg, 0, NULL, kwlist, &keywords, NULL);
247 if (keywords[0] && eval_bool (keywords[0], mlenv))
250 if (! mlenv->env->responseDone)
251 mlenv->env->noContentResponse ();
252 mlenv->env->setErrorFlag ();
262 // (location [#continue | :continue BOOL] URL ['(NAME VALUE)...]) -> NIL
263 (location [#continue | :continue BOOL] URL [:query '((NAME . VALUE)...) | #raw]) -> NIL
265 Locationヘッダを含むレスポンスを出力する。
268 //#AFUNC location ml_location
269 MNode* ml_location (MNode* cell, MlEnv* mlenv) {
270 MNode* arg = cell->cdr ();
275 std::vector<MNode*> params;
276 std::vector<MNode*> keywords;
277 static paramList kwlist[] = {
278 {CharConst ("continue"), true},
279 {CharConst ("query"), false},
280 {CharConst ("raw"), true},
284 setParams (arg, 1, ¶ms, kwlist, &keywords, NULL);
285 url = eval_text1 (params[0], mlenv);
286 if (keywords[0] && eval_bool (keywords[0], mlenv))
288 if (keywords[1]) // query
289 query = eval (keywords[1], mlenv);
290 if (keywords[2] && eval_bool (keywords[2], mlenv)) // raw
294 if (! checkURLSafe (url))
295 throw (url + ": bad URL.");
297 // location_sub (url, query (), rest, mlenv);
298 location_sub (url, query (), mlenv);
300 mlenv->env->location (url);
310 // (location-html URL [#continue | :continue BOOL] ['(NAME VALUE)...]) -> NIL
311 (location-html URL [#continue | :continue BOOL] [:query '((NAME . VALUE)...) | #raw]) -> NIL
314 //#AFUNC location-html ml_location_html
315 MNode* ml_location_html (MNode* cell, MlEnv* mlenv) {
316 MNode* arg = cell->cdr ();
321 std::vector<MNode*> params;
322 std::vector<MNode*> keywords;
323 static paramList kwlist[] = {
324 {CharConst ("continue"), true},
325 {CharConst ("query"), false},
326 {CharConst ("raw"), true},
330 setParams (arg, 1, ¶ms, kwlist, &keywords, NULL);
331 url = eval_text1 (params[0], mlenv);
332 if (keywords[0] && eval_bool (keywords[0], mlenv))
334 if (keywords[1]) // query
335 query = eval (keywords[1], mlenv);
336 if (keywords[2] && eval_bool (keywords[2], mlenv)) // raw
340 if (! checkURLSafe (url))
341 throw (url + ": bad URL.");
343 location_sub (url, query (), mlenv);
345 mlenv->env->location_html (url);
354 ===response-no-cache===
355 (response-no-cache) -> NIL
358 //#AFUNC response-no-cache ml_response_no_cache
359 MNode* ml_response_no_cache (MNode* cell, MlEnv* mlenv) {
360 MNode* arg = cell->cdr ();
363 throw (uErrorWrongNumber);
365 mlenv->env->http.fNoCache = true;
372 (build-url SCHEME HOST PATH [:user NAME] [:password TEXT | :pw TEXT] [:port NUMBER] [:query '((NAME . VALUE) ...)]) -> STRING
375 //#AFUNC build-url ml_build_url
376 MNode* ml_build_url (MNode* cell, MlEnv* mlenv) {
377 MNode* arg = cell->cdr ();
385 AutoDelete<ustring> ans;
388 std::vector<MNode*> params;
389 std::vector<MNode*> keywords;
390 static paramList kwlist[] = {
391 {CharConst ("user"), false},
392 {CharConst ("password"), false},
393 {CharConst ("pw"), false},
394 {CharConst ("port"), false},
395 {CharConst ("query"), false},
399 setParams (arg, 3, ¶ms, kwlist, &keywords, NULL);
400 scheme = eval_text1 (params[0], mlenv);
401 host = eval_text1 (params[1], mlenv);
402 path = eval_text1 (params[2], mlenv);
403 if (keywords[0]) // user
404 user = eval (keywords[0], mlenv);
405 if (keywords[1]) // password
406 pwd = eval (keywords[1], mlenv);
407 if (keywords[2]) // pw
408 pwd = eval (keywords[2], mlenv);
409 if (evkw (3, t)) // port
410 port = to_int (t ());
411 if (keywords[4]) // query
412 query = eval (keywords[4], mlenv);
414 if (! checkScheme (scheme))
415 throw (scheme + ": bad scheme.");
416 if (! matchHostname (host))
417 throw (host + ": bad hostname.");
420 ans ()->append (scheme).append (CharConst ("://"));
422 u = to_string (user ());
424 #ifdef QUERYENCODEALT
425 ans ()->append (urlencode (u.begin (), u.end ()));
427 ans ()->append (percentEncode (u.begin (), u.end ()));
430 ans ()->append (uColon);
431 u = to_string (pwd ());
433 #ifdef QUERYENCODEALT
434 ans ()->append (urlencode (u.begin (), u.end ()));
436 ans ()->append (percentEncode (u.begin (), u.end ()));
439 ans ()->append (CharConst ("@"));
441 ans ()->append (host);
443 ans ()->append (uColon).append (to_ustring (port));
445 if (path[0] != '/') {
446 ans ()->append (uSlash);
448 #ifdef QUERYENCODEALT
449 ans ()->append (urlencode_path (path.begin (), path.end ()));
451 ans ()->append (percentEncode_path (path.begin (), path.end ()));
454 ans ()->append (buildQuery (query ()));
457 return newMNode_str (ans.release ());
462 (build-url-path ELEMENT...) -> STRING
465 //#AFUNC build-url-path ml_build_url_path
466 MNode* ml_build_url_path (MNode* cell, MlEnv* mlenv) {
467 MNode* arg = cell->cdr ();
468 AutoDelete<ustring> ans;
475 t = eval (arg->car (), mlenv);
476 if (! isNil (t ())) {
477 u = to_string (t ());
479 #ifdef QUERYENCODEALT
480 ans ()->append (urlencode (u.begin (), u.end ()));
482 ans ()->append (percentEncode (u.begin (), u.end ()));
486 #ifdef QUERYENCODEALT
487 ans ()->append (uSlash).append (urlencode (u.begin (), u.end ()));
489 ans ()->append (uSlash).append (percentEncode (u.begin (), u.end ()));
496 return newMNode_str (ans.release ());
501 (build-query '((NAME . VALUE)...)) -> STRING
504 //#AFUNC build-query ml_build_query
505 MNode* ml_build_query (MNode* cell, MlEnv* mlenv) {
506 MNode* arg = cell->cdr ();
514 throw (uErrorWrongNumber);
515 query = eval (arg->car (), mlenv);
518 throw (uErrorWrongNumber);
521 if (e && e->isCons ()) {
523 if ((a = e->car ())) {
526 ans.append (percentEncode (to_string (a->car ())));
527 if (! isNil (a->cdr ())) {
529 ans.append (percentEncode (to_string (a->cdr ())));
537 return newMNode_str (new ustring (ans));
542 (http-date INTEGER) -> STRING
545 //#AFUNC http-date ml_http_date
546 MNode* ml_http_date (MNode* cell, MlEnv* mlenv) {
547 MNode* arg = cell->cdr ();
554 throw (uErrorWrongNumber);
555 tm = eval_int64 (arg->car (), mlenv);
558 throw (uErrorWrongNumber);
560 gmtime_r (&tm, &tms);
561 s = strftime (b, 64, "%a, %d %b %Y %H:%M:%S GMT", &tms);
563 return newMNode_str (new ustring (b, s));
568 (hostnamep STRING) -> BOOL
571 //#AFUNC hostnamep ml_hostnamep
572 MNode* ml_hostnamep (MNode* cell, MlEnv* mlenv) {
573 MNode* arg = cell->cdr ();
577 throw (uErrorWrongNumber);
578 hostname = eval_str (arg->car (), mlenv);
581 throw (uErrorWrongNumber);
583 return newMNode_bool (matchHostname (hostname));
588 ($http-get URL [#get] [#post] [#put] [#delete] [#file] [#head]
589 [:id STRING] [:password STRING | :pw STRING]
590 [:query '((NAME . VALUE) ...)] [:get-query '((NAME . VALUE) ...)]
591 [:post-file-serial '((NAME . VALUE) ...)]
592 [:post-file-named '((NAME . VALUE) ...)]
593 [:post-file-static '((NAME . VALUE) ...)]
595 [:raw-file-serial NAME] [:raw-file-named NAME] [:raw-file-static NAME]
596 [:query-type MIMETYPE]
597 [:cookie '((NAME . VALUE) ...)] [:header '((NAME . VALUE) ...)]
598 [:proxy-host STRING] [:proxy-port NUMBER]
599 [:proxy-id STRING] [:proxy-password STRING | :proxy-pw STRING]
600 [#sjis] [#euc-jp] [:iconv NAME]
602 [#no-verify] [#no-encode]
603 [SUBFUNCTION...]) -> LAST VALUE
606 //#MFUNC $http-get ml_http_get cMLHttpGetID
607 MNode* ml_http_get (MNode* cell, MlEnv* mlenv) {
608 MNode* arg = cell->cdr ();
609 MLHttpGet obj (mlenv);
612 MNodePtr headerquery;
614 bool fnoverify = false;
615 bool fnoencode = false;
616 std::vector<MNode*> params;
617 std::vector<MNode*> keywords;
622 static paramList kwlist[] = {
623 {CharConst ("get"), true}, // 0
624 {CharConst ("post"), true}, // 1
625 {CharConst ("put"), true}, // 2
626 {CharConst ("delete"), true}, // 3
627 {CharConst ("file"), true}, // 4
628 {CharConst ("id"), false}, // 5
629 {CharConst ("password"), false}, // 6
630 {CharConst ("pw"), false}, // 7
631 {CharConst ("query"), false}, // 8
632 {CharConst ("get-query"), false}, // 9
633 {CharConst ("post-file-serial"), false}, // 10
634 {CharConst ("post-file-named"), false}, // 11
635 {CharConst ("post-file-static"), false}, // 12
636 {CharConst ("cookie"), false}, // 13
637 {CharConst ("header"), false}, // 14
638 {CharConst ("proxy-host"), false}, // 15
639 {CharConst ("proxy-port"), false}, // 16
640 {CharConst ("proxy-id"), false}, // 17
641 {CharConst ("proxy-password"), false}, // 18
642 {CharConst ("proxy-pw"), false}, // 19
643 {CharConst ("sjis"), true}, // 20
644 {CharConst ("euc-jp"), true}, // 21
645 {CharConst ("iconv"), false}, // 22
646 {CharConst ("on-error"), false}, // 23
647 {CharConst ("no-verify"), true}, // 24
648 {CharConst ("raw-query"), false}, // 25
649 {CharConst ("query-type"), false}, // 26
650 {CharConst ("raw-file-serial"), false}, // 27
651 {CharConst ("raw-file-named"), false}, // 28
652 {CharConst ("raw-file-static"), false}, // 29
653 {CharConst ("no-encode"), true}, // 30
654 {CharConst ("head"), true}, // 31
658 setParams (arg, 1, ¶ms, kwlist, &keywords, &rest);
659 url = eval_str (params[0], mlenv);
660 assert (obj.http == NULL);
661 if (keywords[20] && eval_bool (keywords[20], mlenv)) // sjis
662 obj.http = new HTTPSendIConv ("SHIFT_JIS");
663 else if (keywords[21] && eval_bool (keywords[21], mlenv)) // euc-jp
664 obj.http = new HTTPSendIConv ("EUC-JP");
665 else if (evkw (22, t)) {
666 ustring code = to_string (t ());
667 static uregex re ("^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$");
669 if (usearch (code, m, re)) {
670 obj.http = new HTTPSendIConv (code.c_str ()); // throw on error
672 throw (ustring (code).append (CharConst (": unknown encoding.")));
675 obj.http = new HTTPSend;
676 if (keywords[0] && eval_bool (keywords[0], mlenv)) // get
677 obj.http->setMethod (HTTPSend::M_GET);
678 if (keywords[1] && eval_bool (keywords[1], mlenv)) // post
679 obj.http->setMethod (HTTPSend::M_POST);
680 if (keywords[2] && eval_bool (keywords[2], mlenv)) // put
681 obj.http->setMethod (HTTPSend::M_PUT);
682 if (keywords[3] && eval_bool (keywords[3], mlenv)) // delete
683 obj.http->setMethod (HTTPSend::M_DELETE);
684 if (keywords[31] && eval_bool (keywords[31], mlenv)) // head
685 obj.http->setMethod (HTTPSend::M_HEAD);
686 if (keywords[4] && eval_bool (keywords[4], mlenv)) // file
687 obj.http->setPostFileMethod ();
688 if (evkw (5, t)) // id
689 obj.http->id = omitCtrl (to_string (t ()));
690 if (evkw (6, t)) // password
691 obj.http->pw = omitCtrl (to_string (t ()));
692 if (evkw (7, t)) // pw
693 obj.http->pw = omitCtrl (to_string (t ()));
694 if (evkw (8, t)) // query
695 obj.http->params = t ();
696 if (evkw (9, t)) // get-query
697 obj.http->getparams = t ();
698 if (evkw (10, t)) // post-file-serial
699 obj.http->fileparams_store = t ();
700 if (evkw (11, t)) // post-file-named
701 obj.http->fileparams_storage = t ();
702 if (evkw (12, t)) // post-file-static
703 obj.http->fileparams_static = t ();
704 if (evkw (13, t)) // cookie
706 if (evkw (14, t)) // header
708 if (evkw (15, t)) { // proxy-host
709 obj.http->conhost.host = omitNonAsciiWord (to_string (t ()));
710 obj.http->useproxy = true;
711 if (evkw (16, t)) // proxy-port
712 obj.http->conhost.port = to_uint32 (to_string (t ()));
713 if (evkw (17, t)) // proxy-id
714 obj.http->proxyid = omitCtrl (to_string (t ()));
715 if (evkw (18, t)) // proxy-password
716 obj.http->proxypw = omitCtrl (to_string (t ()));
717 if (evkw (19, t)) // proxy-pw
718 obj.http->proxypw = omitCtrl (to_string (t ()));
721 errfn = eval (keywords[23], mlenv);
723 fnoverify = eval_bool (keywords[24], mlenv);
725 obj.http->rawquery = to_string (t ());
727 obj.http->querytype = to_string (t ());
728 if (! matchASCII (obj.http->querytype.begin (), obj.http->querytype.end ()))
729 throw (obj.http->querytype + ustring (CharConst (": bad type")));
731 if (evkw (27, t)) // raw-file-serial
732 obj.http->rawqueryfile = mlenv->env->path_store_file (to_string (t ()));
733 if (evkw (28, t)) // raw-file-named
734 obj.http->rawqueryfile = mlenv->env->path_storage_file (to_string (t ()));
735 if (evkw (29, t)) // raw-file-static
736 obj.http->rawqueryfile = mlenv->env->path_static_file (to_string (t ()));
737 if (keywords[30]) // no-encode
738 fnoencode = eval_bool (keywords[30], mlenv);
740 url_sub (url, obj.http, fnoencode);
741 if (obj.http->proto.empty ()) {
742 throw (obj.http->path + ": bad URL.");
744 request_cookie (cookie (), obj.http);
745 request_headerquery (headerquery (), obj.http);
748 if (obj.http->proto == uHttp) {
750 TcpClient* c = new TcpClient;
752 rc = c->connect (&obj.http->conhost);
755 obj.http->submit (*obj.client, obj.buf, mlenv);
756 } else if (obj.http->proto == uHttps) {
757 if (obj.http->useproxy) {
759 ProxySslClient* c = new ProxySslClient (fnoverify);
760 c->proxyid = obj.http->proxyid;
761 c->proxypw = obj.http->proxypw;
762 obj.http->proxyid = uEmpty;
763 obj.http->proxypw = uEmpty;
765 rc = c->connect (&obj.http->conhost, &obj.http->host);
767 obj.http->useproxy = false;
770 SslClient* c = new SslClient (fnoverify);
772 rc = c->connect (&obj.http->conhost, &obj.http->host);
776 obj.http->submit (*obj.client, obj.buf, mlenv);
778 throw (obj.http->proto + ": protocol not supported.");
780 obj.http->readReplyHead (*obj.client, obj.buf);
782 mlenv->setMStack (&obj);
784 ans = progn (rest, mlenv);
785 } catch (ustring& msg) {
787 onErrorFn (errfn (), mlenv);
792 mlenv->stopBreak (cell->car ());
794 return ans.release ();
798 ===subfunctions of $http-get===
803 (http-status) -> NUMBER
806 //#SFUNC http-status ml_http_get_http_status
807 MNode* ml_http_get_http_status (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
808 MNode* arg = cell->cdr ();
809 MLHttpGet* obj = (MLHttpGet*)mobj;
812 throw (uErrorWrongNumber);
814 return newMNode_num (obj->http->responseCode);
818 ====http-response====
819 (http-response) -> STRING
822 //#SFUNC http-response ml_http_get_http_response
823 MNode* ml_http_get_http_response (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
824 MNode* arg = cell->cdr ();
825 MLHttpGet* obj = (MLHttpGet*)mobj;
829 throw (uErrorWrongNumber);
831 obj->http->readReplyBody (*obj->client, obj->buf, ans);
833 return newMNode_str (new ustring (ans));
837 ====http-response-file====
838 (http-response-file FILENAME) -> NIL
841 //#SFUNC http-response-file ml_http_get_http_response_file
842 MNode* ml_http_get_http_response_file (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
843 MNode* arg = cell->cdr ();
844 MLHttpGet* obj = (MLHttpGet*)mobj;
849 throw (uErrorWrongNumber);
850 name = eval_str (arg->car (), mlenv);
853 throw (uErrorWrongNumber);
855 tgt = mlenv->env->path_store_file (name);
856 tmp.assign (tgt).append (CharConst ("-tmp")).append (to_ustring (getpid ()));
858 std::ofstream stream;
859 MotorOutputOStream out (&stream);
860 stream.open (tmp.c_str (), std::ios_base::out | std::ios_base::binary);
861 obj->http->readReplyBody (*obj->client, obj->buf, &out);
863 rename (tmp.c_str (), tgt.c_str ());
870 ====http-response-output====
871 (http-response-output [#continue | :continue BOOL]) -> NIL
874 //#SFUNC http-response-output ml_http_get_http_response_output
875 MNode* ml_http_get_http_response_output (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
876 MNode* arg = cell->cdr ();
877 MLHttpGet* obj = (MLHttpGet*)mobj;
879 std::vector<MNode*> keywords;
880 static paramList kwlist[] = {
881 {CharConst ("continue"), true},
885 setParams (arg, 0, NULL, kwlist, &keywords, NULL);
886 if (keywords[0] && eval_bool (keywords[0], mlenv))
889 if (! mlenv->env->responseDone)
890 mlenv->env->standardResponse_html ();
891 obj->http->readReplyBody (*obj->client, obj->buf, mlenv->env->output);
901 (get-cookie NAME) -> STRING
904 //#SFUNC get-cookie ml_http_get_get_cookie
905 MNode* ml_http_get_get_cookie (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
906 MNode* arg = cell->cdr ();
907 MLHttpGet* obj = (MLHttpGet*)mobj;
912 throw (uErrorWrongNumber);
913 name = eval_str (arg->car (), mlenv);
916 throw (uErrorWrongNumber);
918 for (i = 0; i < obj->http->cookie_reply.size (); i ++) {
919 if (obj->http->cookie_reply[i].key == name) {
920 return newMNode_str (new ustring (obj->http->cookie_reply[i].value));
928 ====get-cookie-all====
929 (get-cookie-all) -> LIST of (NAME . VALUE)
932 //#SFUNC get-cookie-all ml_http_get_get_cookie_all
933 MNode* ml_http_get_get_cookie_all (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
934 MNode* arg = cell->cdr ();
935 MLHttpGet* obj = (MLHttpGet*)mobj;
941 throw (uErrorWrongNumber);
943 for (i = 0; i < obj->http->cookie_reply.size (); i ++) {
945 a->set_car (newMNode_str (new ustring (obj->http->cookie_reply[i].key)));
946 a->set_cdr (newMNode_str (new ustring (obj->http->cookie_reply[i].value)));
950 return ans.release ();
954 ====http-content-type====
955 (http-content-type) -> STRING
958 //#SFUNC http-content-type ml_http_content_type
959 MNode* ml_http_content_type (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
960 MNode* arg = cell->cdr ();
961 MLHttpGet* obj = (MLHttpGet*)mobj;
963 static ustring name (CharConst ("content-type"));
965 u = obj->http->findHeader (name);
970 if (splitChar (b, e, ';', m)) {
971 return newMNode_str (new ustring (toLower (b, m)));
973 return newMNode_str (new ustring (toLower (b, e)));
981 ====http-get-header====
982 (http-get-header NAME) -> STRING
985 //#SFUNC http-get-header ml_http_get_header
986 MNode* ml_http_get_header (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
987 MNode* arg = cell->cdr ();
988 MLHttpGet* obj = (MLHttpGet*)mobj;
993 throw (uErrorWrongNumber);
994 name = eval_str (arg->car (), mlenv);
997 throw (uErrorWrongNumber);
999 name = toLower (name.begin (), name.end ());
1000 u = obj->http->findHeader (name);
1002 return newMNode_str (new ustring (*u));
1009 ====http-get-header-all====
1010 (http-get-header-all) -> LIST of (NAME . VALUE)
1013 //#SFUNC http-get-header-all ml_http_get_header_all
1014 MNode* ml_http_get_header_all (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
1015 MNode* arg = cell->cdr ();
1016 MLHttpGet* obj = (MLHttpGet*)mobj;
1019 std::vector<HTTPSend::mapelem>::const_iterator b = obj->http->header_reply.begin ();
1020 std::vector<HTTPSend::mapelem>::const_iterator e = obj->http->header_reply.end ();
1023 throw (uErrorWrongNumber);
1025 for (; b < e; b ++) {
1027 a->set_car (newMNode_str (new ustring (b->first)));
1028 a->set_cdr (newMNode_str (new ustring (b->second)));
1032 return ans.release ();