diff options
-rw-r--r-- | core/io/http_client.cpp | 15 | ||||
-rw-r--r-- | core/io/http_client.h | 2 | ||||
-rw-r--r-- | core/ustring.cpp | 42 | ||||
-rw-r--r-- | core/ustring.h | 2 | ||||
-rw-r--r-- | doc/base/classes.xml | 48 | ||||
-rw-r--r-- | tools/doc/doc_data.cpp | 2 | ||||
-rw-r--r-- | tools/docdump/makehtml.py | 19 |
7 files changed, 120 insertions, 10 deletions
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index 24012660d2..58092efd4b 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -579,7 +579,7 @@ Error HTTPClient::_get_http_data(uint8_t* p_buffer, int p_bytes,int &r_received) void HTTPClient::_bind_methods() { - ObjectTypeDB::bind_method(_MD("connect:Error","host","port","use_ssl"),&HTTPClient::connect,DEFVAL(false),DEFVAL(true)); + ObjectTypeDB::bind_method(_MD("connect:Error","host","port","use_ssl","verify_host"),&HTTPClient::connect,DEFVAL(false),DEFVAL(true)); ObjectTypeDB::bind_method(_MD("set_connection","connection:StreamPeer"),&HTTPClient::set_connection); ObjectTypeDB::bind_method(_MD("request","method","url","headers","body"),&HTTPClient::request,DEFVAL(String())); ObjectTypeDB::bind_method(_MD("send_body_text","body"),&HTTPClient::send_body_text); @@ -601,6 +601,8 @@ void HTTPClient::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_status"),&HTTPClient::get_status); ObjectTypeDB::bind_method(_MD("poll:Error"),&HTTPClient::poll); + ObjectTypeDB::bind_method(_MD("query_string_from_dict:String","fields"),&HTTPClient::query_string_from_dict); + BIND_CONSTANT( METHOD_GET ); BIND_CONSTANT( METHOD_HEAD ); @@ -689,6 +691,16 @@ void HTTPClient::set_read_chunk_size(int p_size) { read_chunk_size=p_size; } +String HTTPClient::query_string_from_dict(const Dictionary& p_dict) { + String query = ""; + Array keys = p_dict.keys(); + for (int i = 0; i < keys.size(); ++i) { + query += "&" + String(keys[i]).http_escape() + "=" + String(p_dict[keys[i]]).http_escape(); + } + query.erase(0, 1); + return query; +} + HTTPClient::HTTPClient(){ tcp_connection = StreamPeerTCP::create_ref(); @@ -710,4 +722,3 @@ HTTPClient::~HTTPClient(){ } - diff --git a/core/io/http_client.h b/core/io/http_client.h index 21281f38c5..b103dc43fc 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -192,6 +192,8 @@ public: Error poll(); + String query_string_from_dict(const Dictionary& p_dict); + HTTPClient(); ~HTTPClient(); }; diff --git a/core/ustring.cpp b/core/ustring.cpp index 7582376fe0..2dffdf066c 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -3079,6 +3079,48 @@ String String::world_wrap(int p_chars_per_line) const { return ret; } +String String::http_escape() const { + const CharString temp = utf8(); + String res; + for (int i = 0; i < length(); ++i) { + CharType ord = temp[i]; + if (ord == '.' || ord == '-' || ord == '_' || ord == '~' || + (ord >= 'a' && ord <= 'z') || + (ord >= 'A' && ord <= 'Z') || + (ord >= '0' && ord <= '9')) { + res += ord; + } else { + char h_Val[3]; + snprintf(h_Val, 3, "%.2X", ord); + res += "%"; + res += h_Val; + } + } + return res; +} + +String String::http_unescape() const { + String res; + for (int i = 0; i < length(); ++i) { + if (ord_at(i) == '%' && i+2 < length()) { + CharType ord1 = ord_at(i+1); + if ((ord1 >= '0' && ord1 <= '9') || (ord1 >= 'A' && ord1 <= 'Z')) { + CharType ord2 = ord_at(i+2); + if ((ord2 >= '0' && ord2 <= '9') || (ord2 >= 'A' && ord2 <= 'Z')) { + char bytes[2] = {ord1, ord2}; + res += (char)strtol(bytes, NULL, 16); + i+=2; + } + } else { + res += ord_at(i); + } + } else { + res += ord_at(i); + } + } + return String::utf8(res.ascii()); +} + String String::c_unescape() const { String escaped=*this; diff --git a/core/ustring.h b/core/ustring.h index fa25a07eb0..2f3c4bff4d 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -207,6 +207,8 @@ public: String xml_escape(bool p_escape_quotes=false) const; String xml_unescape() const; + String http_escape() const; + String http_unescape() const; String c_escape() const; String c_unescape() const; String world_wrap(int p_chars_per_line) const; diff --git a/doc/base/classes.xml b/doc/base/classes.xml index 24c5799350..e805adce6d 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -12518,9 +12518,13 @@ This approximation makes straight segments between each point, then subdivides t </argument> <argument index="2" name="use_ssl" type="bool" default="false"> </argument> - <argument index="3" name="arg3" type="bool" default="true"> + <argument index="3" name="verify_host" type="bool" default="true"> </argument> <description> + Connect to a host. This needs to be done before any requests are sent. +The host should not have http:// prepended but will strip the protocol identifier if provided. + +verify_host will check the SSL identity of the host if set to true. </description> </method> <method name="set_connection"> @@ -12541,6 +12545,20 @@ This approximation makes straight segments between each point, then subdivides t <argument index="3" name="body" type="String" default=""""> </argument> <description> + Sends a request to the connected host. The url is the what is normally behind the hostname, +i.e; +http://somehost.com/index.php +url would be "index.php" + +Headers are HTTP request headers + +To create a POST request with query strings to push to the server, do: +var fields = {"username" : "user", + "password" : "pass"} +var queryString = httpClient.query_string_from_dict(fields) +var headers = ["Content-Type: application/x-www-form-urlencoded", + "Content-Length: " + str(queryString.length())] +var result = httpClient.request(httpClient.METHOD_POST, "index.php", headers, queryString) </description> </method> <method name="send_body_text"> @@ -12548,7 +12566,8 @@ This approximation makes straight segments between each point, then subdivides t </return> <argument index="0" name="body" type="String"> </argument> - <description> + <description> + Stub function </description> </method> <method name="send_body_data"> @@ -12557,6 +12576,7 @@ This approximation makes straight segments between each point, then subdivides t <argument index="0" name="body" type="RawArray"> </argument> <description> + Stub function </description> </method> <method name="close"> @@ -12609,12 +12629,14 @@ This approximation makes straight segments between each point, then subdivides t <argument index="0" name="bytes" type="int"> </argument> <description> + Sets the size of the buffer used and maximum bytes to read per iteration </description> </method> <method name="set_blocking_mode"> <argument index="0" name="enabled" type="bool"> </argument> <description> + If set to true, execute will wait until all data is read from the response. </description> </method> <method name="is_blocking_mode_enabled" qualifiers="const"> @@ -12627,14 +12649,30 @@ This approximation makes straight segments between each point, then subdivides t <return type="int"> </return> <description> + Returns a status string like STATUS_REQUESTING. Need to call [method poll] in order to get status updates. </description> </method> <method name="poll"> <return type="Error"> </return> - <description> - </description> - </method> + <description> + This needs to be called in order to have any request processed. Check results with [method get_status] + </description> + </method> + <method name="query_string_from_dict"> + <return type="String"> + </return> + <argument index="0" name="fields" type="Dictionary"> + </argument> + <description> + Generates a GET/POST application/x-www-form-urlencoded style query string from a provided dictionary. + +var fields = {"username": "user", "password": "pass"} +String queryString = httpClient.query_string_from_dict(fields) + +returns:= "username=user&password=pass" + </description> + </method> </methods> <constants> <constant name="METHOD_GET" value="0"> diff --git a/tools/doc/doc_data.cpp b/tools/doc/doc_data.cpp index 432f358627..c1d3e5e314 100644 --- a/tools/doc/doc_data.cpp +++ b/tools/doc/doc_data.cpp @@ -189,9 +189,11 @@ void DocData::generate(bool p_basic_types) { arginfo=E->get().return_val; if (arginfo.type==Variant::NIL) continue; +#ifdef DEBUG_METHODS_ENABLED if (m && m->get_return_type()!=StringName()) method.return_type=m->get_return_type(); else +#endif method.return_type=(arginfo.hint==PROPERTY_HINT_RESOURCE_TYPE)?arginfo.hint_string:Variant::get_type_name(arginfo.type); } else { diff --git a/tools/docdump/makehtml.py b/tools/docdump/makehtml.py index d533ca1b8b..9b9c62f33b 100644 --- a/tools/docdump/makehtml.py +++ b/tools/docdump/makehtml.py @@ -1,5 +1,19 @@ import sys import xml.etree.ElementTree as ET +from xml.sax.saxutils import escape, unescape + +html_escape_table = { + '"': """, + "'": "'" +} + +html_unescape_table = {v:k for k, v in html_escape_table.items()} + +def html_escape(text): + return escape(text, html_escape_table) + +def html_unescape(text): + return unescape(text, html_unescape_table) input_list = [] @@ -96,7 +110,7 @@ def make_html_class_list(class_list,columns): idx=0 for n in class_list: - col = idx/col_max + col = int(idx/col_max) if (col>=columns): col=columns-1 fit_columns[col]+=[n] @@ -299,6 +313,7 @@ def make_type(p_type,p_parent): def make_text_def(class_name,parent,text): + text = html_escape(text) pos=0 while(True): pos = text.find("[",pos) @@ -598,7 +613,6 @@ def make_html_class(node): descr=node.find("description") if (descr!=None and descr.text.strip()!=""): - h4=ET.SubElement(div,"h4") h4.text="Description:" @@ -644,7 +658,6 @@ def make_html_class(node): class_names=[] classes={} - for file in input_list: tree = ET.parse(file) doc=tree.getroot() |