diff --git a/lib/modules/Protocols.pmod/HTTP.pmod/Query.pike b/lib/modules/Protocols.pmod/HTTP.pmod/Query.pike index 14ad8eff59e94ab9b2656aec1b7aca8a509e2ae0..2c12b34578c4e9a83952b3cae5950cf7a5c58a30 100644 --- a/lib/modules/Protocols.pmod/HTTP.pmod/Query.pike +++ b/lib/modules/Protocols.pmod/HTTP.pmod/Query.pike @@ -177,15 +177,23 @@ static void ponder_answer() static void connect(string server,int port) { +#ifdef HTTP_QUERY_DEBUG + werror("<- (connect %O:%d)\n",server,port); +#endif if (catch { con->connect(server,port); }) { if (!(errno=con->errno())) errno=22; /* EINVAL */ +#ifdef HTTP_QUERY_DEBUG + werror("<- (error %d)\n",errno); +#endif destruct(con); con=0; ok=0; return; } - +#ifdef HTTP_QUERY_DEBUG + werror("<- %O\n",request); +#endif con->write(request); ponder_answer(); @@ -199,6 +207,10 @@ static void async_close() static void async_read(mixed dummy,string s) { +#ifdef HTTP_QUERY_DEBUG + werror("-> %O\n",s); +#endif + buf+=s; if (-1!=search(buf,"\r\n\r\n")) { @@ -210,6 +222,9 @@ static void async_read(mixed dummy,string s) static void async_write() { con->set_blocking(); +#ifdef HTTP_QUERY_DEBUG + werror("<- %O\n",request); +#endif con->write(request); con->set_nonblocking(async_read,0,async_close); } @@ -217,6 +232,9 @@ static void async_write() static void async_connected() { con->set_nonblocking(async_read,async_write,async_close); +#ifdef HTTP_QUERY_DEBUG + werror("<- %O\n",""); +#endif con->write(""); } @@ -274,6 +292,9 @@ void async_got_host(string server,int port) void async_fetch_read(mixed dummy,string data) { +#ifdef HTTP_QUERY_DEBUG + werror("-> %O\n",data); +#endif buf+=data; } @@ -293,8 +314,9 @@ string headers_encode(mapping h) return Array.map( indices(h), lambda(string hname,mapping headers) { - if (stringp(headers[hname])) - return String.capitalize(hname) + + if (stringp(headers[hname]) || + intp(headers[hname])) + return String.capitalize(replace(hname,"_","-")) + ": " + headers[hname]; }, h )*"\r\n" + "\r\n"; } @@ -422,7 +444,11 @@ object sync_request(string server,int port,string query, if (data!="") headers->content_length=strlen(data); + werror("headers is %O\n",headers); + headers=headers_encode(headers); + + werror("headers is:\n%s\n",headers); } request=query+"\r\n"+headers+"\r\n"+data; diff --git a/lib/modules/Protocols.pmod/HTTP.pmod/module.pmod b/lib/modules/Protocols.pmod/HTTP.pmod/module.pmod index 4216d9df674929b0500e769402759bbf2498800f..2a037cca6a4410e41803ea74c66e42bbbc0be5d9 100644 --- a/lib/modules/Protocols.pmod/HTTP.pmod/module.pmod +++ b/lib/modules/Protocols.pmod/HTTP.pmod/module.pmod @@ -2,16 +2,18 @@ //! module Protocols //! submodule HTTP //! method object(Protocols.HTTP.Query) get_url(string url) +//! method object(Protocols.HTTP.Query) get_url(string url,mapping query_variables) //! Sends a HTTP GET request to the server in the URL //! and returns the created and initialized <ref>Query</ref> object. //! 0 is returned upon failure. //! //! method array(string) get_url_nice(string url) +//! method array(string) get_url_nice(string url,mapping query_variables) //! Returns an array of ({content_type,data}) //! after calling the requested server for the information. //! 0 is returned upon failure. -object get_url(string url) +object get_url(string url,void|mapping query_variables) { object con=master()->resolv("Protocols")["HTTP"]["Query"](); @@ -26,9 +28,17 @@ object get_url(string url) (host=url,query=""); if (prot!="http") - error("Protocols.HTTP can't handle %O or any other protocol then HTTP\n", + error("Protocols.HTTP can't handle %O or any other protocol than HTTP\n", prot); + if (query_variables) + { + if (search(query,"?")!=-1) + query+="&"+http_encode_query(query_variables); + else + query+="?"+http_encode_query(query_variables); + } + con->sync_request(host,port, "GET /"+query+" HTTP/1.0", (["user-agent": @@ -38,8 +48,164 @@ object get_url(string url) return con; } -array(string) get_url_nice(string url) +array(string) get_url_nice(string url,void|mapping query_variables) +{ + object c=get_url(url,query_variables); + return c && ({c->headers["content-type"],c->data()}); +} + +array(string) get_url_result(string url,void|mapping query_variables) +{ + return get_url(url,query_variables)[1]; +} + +object post_url(string url,mapping query_variables) +{ + object con=master()->resolv("Protocols")["HTTP"]["Query"](); + + string prot="http",host; + int port=80; + string query; + + sscanf(url,"%[^:/]://%[^:/]:%d/%s",prot,host,port,query) == 4 || + (port=80,sscanf(url,"%[^:/]://%[^:/]/%s",prot,host,query)) == 3 || + (prot="http",sscanf(url,"%[^:/]:%d/%s",host,port,query)) == 3 || + (port=80,sscanf(url,"%[^:/]/%s",host,query)) == 2 || + (host=url,query=""); + + if (prot!="http") + error("Protocols.HTTP can't handle %O or any other protocol than HTTP\n", + prot); + + con->sync_request(host,port, + "POST /"+query+" HTTP/1.0", + (["user-agent": + "Mozilla/4.0 compatible (Pike HTTP client)", + "content-type": + "application/x-www-form-urlencoded"]), + http_encode_query(query_variables)); + + if (!con->ok) return 0; + return con; +} + +array(string) post_url_nice(string url,mapping query_variables) { - object c=get_url(url); + object c=post_url(url,query_variables); return c && ({c->headers["content-type"],c->data()}); } + +array(string) post_url_result(string url,mapping query_variables) +{ + return post_url(url,query_variables)[1]; +} + +//! +//! method string unentity(string s) +//! Helper function for replacing HTML entities +//! with the corresponding iso-8859-1 characters. +//! note: +//! All characters isn't replaced, only those with +//! corresponding iso-8859-1 characters. + +string unentity(string s) +{ + return replace( + s, + + ({"Æ", "Á", "Â", "À", "Å", "Ã", + "Ä", "Ç", "Ð", "É", "Ê", "È", + "Ë", "Í", "Î", "Ì", "Ï", "Ñ", + "Ó", "Ô", "Ò", "Ø", "Õ", "Ö", + "Þ", "Ú", "Û", "Ù", "Ü", "Ý", + "á", "â", "æ", "à", "'", "å", + "*", "ã", "ä", "¦", "ç", "¢", + ":", ",", "@", "©", "°", "$", + "é", "ê", "è", " ", " ", "=", + "ð", "ë", "!", "½", "¼", "¾", + "⅛", "⅜", "⅝", "⅞", ">", ">", + "½", "‐", "í", "î", "¡", "ì", + "¿", "ï", "«", "(", "[", "<", "<", + "—", "µ", "·", " ", "–", "¬", + "ñ", "ó", "ô", "ò", "ø", "õ", + "ö", "¶", "%", ".", "+", "±", + "£", "?", """, "»", "®", ")", + "]", "§", ";", "­", "¹", "²", "³", + "ß", "þ", "˜", "™", "ú", "û", + "ù", "ü", "ý", "¥", "ÿ", "|", + "&"}), + + ({ "�", "�", "�", "�", "�", "�", "�", "�", "�", "�", "�", "�", + "�", "�", "�", "�", "�", "�", "�", "�", "�", "�", "�", "�", "�", "�", + "�", "�", "�", "�", "�", "�", "�", "�", "'", "�", "*", "�", + "�", "�", "�", "�", ":", ",", "@", "�", "�", + "$", "�", "�", "�", " ", " ", "=", "�", "�", + "!", "�", "�", "�", "⅛", "⅜", "⅝", + "⅞", ">", ">", "½", "‐", "�", "�", "�", "�", "�", + "�", "�", "(", "[", "<", "<", "—", "�", "�", "", + "–", "�", "�", "�", "�", "�", "�", "�", "�", "�", "%", + ".", "+", "�", "�", "?", "\"", "�", "�", ")", + "]", "�", ";", "�", "�", "�", "�", "�", "�", "~", + "™", "�", "�", "�", "�", "�", "�", "�", "|", "&", }), + ); +} + +string http_encode_query(mapping variables) +{ + return Array.map(indices(variables), + lambda(string ind) + { + return http_encode_string(ind)+"="+ + http_encode_string(variables[ind]); + })*"&"; +} + +string http_encode_string(string f) +{ + return replace( + f, + ({ "\000", "\001", "\002", "\003", "\004", "\005", "\006", "\007", + "\010", "\011", "\012", "\013", "\014", "\015", "\016", "\017", + "\020", "\021", "\022", "\023", "\024", "\025", "\026", "\027", + "\030", "\031", "\032", "\033", "\034", "\035", "\036", "\037", + "\200", "\201", "\202", "\203", "\204", "\205", "\206", "\207", + "\210", "\211", "\212", "\213", "\214", "\215", "\216", "\217", + "\220", "\221", "\222", "\223", "\224", "\225", "\226", "\227", + "\230", "\231", "\232", "\233", "\234", "\235", "\236", "\237", + " ", "%", "'", "\"" }), + ({ + "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07", + "%08", "%09", "%0a", "%0b", "%0c", "%0d", "%0e", "%0f", + "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17", + "%18", "%19", "%1a", "%1b", "%1c", "%1d", "%1e", "%1f", + "%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87", + "%88", "%89", "%8a", "%8b", "%8c", "%8d", "%8e", "%8f", + "%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97", + "%98", "%99", "%9a", "%9b", "%9c", "%9d", "%9e", "%9f", + "%20", "%25", "%27", "%22"})); +} + +string http_encode_cookie(string f) +{ + return replace( + f, + ({ "\000", "\001", "\002", "\003", "\004", "\005", "\006", "\007", + "\010", "\011", "\012", "\013", "\014", "\015", "\016", "\017", + "\020", "\021", "\022", "\023", "\024", "\025", "\026", "\027", + "\030", "\031", "\032", "\033", "\034", "\035", "\036", "\037", + "\200", "\201", "\202", "\203", "\204", "\205", "\206", "\207", + "\210", "\211", "\212", "\213", "\214", "\215", "\216", "\217", + "\220", "\221", "\222", "\223", "\224", "\225", "\226", "\227", + "\230", "\231", "\232", "\233", "\234", "\235", "\236", "\237", + " ", "%", "'", "\"", ",", ";", "=" }), + ({ + "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07", + "%08", "%09", "%0a", "%0b", "%0c", "%0d", "%0e", "%0f", + "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17", + "%18", "%19", "%1a", "%1b", "%1c", "%1d", "%1e", "%1f", + "%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87", + "%88", "%89", "%8a", "%8b", "%8c", "%8d", "%8e", "%8f", + "%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97", + "%98", "%99", "%9a", "%9b", "%9c", "%9d", "%9e", "%9f", + "%20", "%25", "%27", "%22", "%2c", "%3b", "%3d" })); +}