From: TimePath Date: Wed, 26 Aug 2015 23:38:54 +0000 (+1000) Subject: Move urllib to /lib X-Git-Tag: xonotic-v0.8.2~2020 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=bc01573d1b12cc8a102d1b8b22777d5bd71c3420;p=xonotic%2Fxonotic-data.pk3dir.git Move urllib to /lib --- diff --git a/qcsrc/client/miscfunctions.qc b/qcsrc/client/miscfunctions.qc index 845a56410..c9c599945 100644 --- a/qcsrc/client/miscfunctions.qc +++ b/qcsrc/client/miscfunctions.qc @@ -7,7 +7,6 @@ #include "../common/command/generic.qh" #include "../common/teams.qh" -#include "../common/urllib.qh" #include "../common/util.qh" #include "../csqcmodellib/cl_model.qh" diff --git a/qcsrc/client/progs.src b/qcsrc/client/progs.src index b9006dd2c..3c6ccc1c6 100644 --- a/qcsrc/client/progs.src +++ b/qcsrc/client/progs.src @@ -53,7 +53,6 @@ weapons/projectile.qc // TODO ../common/playerstats.qc ../common/p2mathlib.qc ../common/test.qc -../common/urllib.qc ../common/util.qc ../common/viewloc.qc diff --git a/qcsrc/common/constants.qh b/qcsrc/common/constants.qh index bc18b4dc7..707840188 100644 --- a/qcsrc/common/constants.qh +++ b/qcsrc/common/constants.qh @@ -362,16 +362,6 @@ const int SPAWN_PRIO_NEAR_TEAMMATE_SAMETEAM = 100; const int SPAWN_PRIO_RACE_PREVIOUS_SPAWN = 50; const int SPAWN_PRIO_GOOD_DISTANCE = 10; -// URI handles -const int URI_GET_DISCARD = 0; -const int URI_GET_IPBAN = 1; -const int URI_GET_IPBAN_END = 16; -const int URI_GET_CURL = 17; -const int URI_GET_CURL_END = 32; -const int URI_GET_UPDATENOTIFICATION = 33; -const int URI_GET_URLLIB = 128; -const int URI_GET_URLLIB_END = 191; - // gametype vote flags const int GTV_FORBIDDEN = 0; // Cannot be voted const int GTV_AVAILABLE = 1; // Can be voted diff --git a/qcsrc/common/playerstats.qc b/qcsrc/common/playerstats.qc index e46e12fa1..ea783a12d 100644 --- a/qcsrc/common/playerstats.qc +++ b/qcsrc/common/playerstats.qc @@ -5,7 +5,6 @@ #include "../dpdefs/dpextensions.qh" #include "constants.qh" #include "util.qh" - #include "urllib.qh" #include "weapons/all.qh" #include "../server/weapons/accuracy.qh" #include "../server/defs.qh" diff --git a/qcsrc/common/urllib.qc b/qcsrc/common/urllib.qc deleted file mode 100644 index 8529ebd6d..000000000 --- a/qcsrc/common/urllib.qc +++ /dev/null @@ -1,400 +0,0 @@ -#if defined(CSQC) - #include "../dpdefs/csprogsdefs.qh" - #include "constants.qh" - #include "util.qh" - #include "urllib.qh" -#elif defined(MENUQC) -#elif defined(SVQC) - #include "../dpdefs/progsdefs.qh" - #include "../dpdefs/dpextensions.qh" - #include "constants.qh" - #include "util.qh" - #include "urllib.qh" -#endif - -// files -.float url_fh; -const float URL_FH_CURL = -1; -const float URL_FH_STDOUT = -2; - -// URLs -.string url_url; -.float url_wbuf; -.float url_wbufpos; -.float url_rbuf; -.float url_rbufpos; -.float url_id; -.url_ready_func url_ready; -.entity url_ready_pass; - -// for multi handles -.int url_attempt; -.int url_mode; - -entity url_fromid[NUM_URL_ID]; -int autocvar__urllib_nextslot; - -float url_URI_Get_Callback(int id, float status, string data) -{ - if(id < MIN_URL_ID) - return 0; - id -= MIN_URL_ID; - if(id >= NUM_URL_ID) - return 0; - entity e; - e = url_fromid[id]; - if(!e) - return 0; - if(e.url_rbuf >= 0 || e.url_wbuf >= 0) - { - printf("WARNING: handle %d (%s) has already received data?!?\n", id + NUM_URL_ID, e.url_url); - return 0; - } - - // whatever happens, we will remove the URL from the list of IDs - url_fromid[id] = world; - - // if we get here, we MUST have both buffers cleared - if(e.url_rbuf != -1 || e.url_wbuf != -1 || e.url_fh != URL_FH_CURL) - error("url_URI_Get_Callback: not a request waiting for data"); - - if(status == 0) - { - // WE GOT DATA! - float n, i; - n = tokenizebyseparator(data, "\n"); - e.url_rbuf = buf_create(); - if(e.url_rbuf < 0) - { - print("url_URI_Get_Callback: out of memory in buf_create\n"); - e.url_ready(e, e.url_ready_pass, URL_READY_ERROR); - strunzone(e.url_url); - remove(e); - return 1; - } - e.url_rbufpos = 0; - if(e.url_rbuf < 0) - { - print("url_URI_Get_Callback: out of memory in buf_create\n"); - e.url_ready(e, e.url_ready_pass, URL_READY_ERROR); - strunzone(e.url_url); - remove(e); - return 1; - } - for(i = 0; i < n; ++i) - bufstr_set(e.url_rbuf, i, argv(i)); - e.url_ready(e, e.url_ready_pass, URL_READY_CANREAD); - return 1; - } - else - { - // an ERROR - e.url_ready(e, e.url_ready_pass, -fabs(status)); - strunzone(e.url_url); - remove(e); - return 1; - } -} - -void url_single_fopen(string url, int mode, url_ready_func rdy, entity pass) -{ - entity e; - int i; - if(strstrofs(url, "://", 0) >= 0) - { - switch(mode) - { - case FILE_WRITE: - case FILE_APPEND: - // collect data to a stringbuffer for a POST request - // attempts to close will result in a reading handle - - // create a writing end that does nothing yet - e = spawn(); - e.classname = "url_single_fopen_file"; - e.url_url = strzone(url); - e.url_fh = URL_FH_CURL; - e.url_wbuf = buf_create(); - if(e.url_wbuf < 0) - { - print("url_single_fopen: out of memory in buf_create\n"); - rdy(e, pass, URL_READY_ERROR); - strunzone(e.url_url); - remove(e); - return; - } - e.url_wbufpos = 0; - e.url_rbuf = -1; - e.url_ready = rdy; - e.url_ready_pass = pass; - rdy(e, pass, URL_READY_CANWRITE); - break; - - case FILE_READ: - // read data only - - // get slot for HTTP request - for(i = autocvar__urllib_nextslot; i < NUM_URL_ID; ++i) - if(url_fromid[i] == world) - break; - if(i >= NUM_URL_ID) - { - for(i = 0; i < autocvar__urllib_nextslot; ++i) - if(url_fromid[i] == world) - break; - if(i >= autocvar__urllib_nextslot) - { - print("url_single_fopen: too many concurrent requests\n"); - rdy(world, pass, URL_READY_ERROR); - return; - } - } - - // GET the data - if(!crypto_uri_postbuf(url, i + MIN_URL_ID, string_null, string_null, -1, 0)) - { - print("url_single_fopen: failure in crypto_uri_postbuf\n"); - rdy(world, pass, URL_READY_ERROR); - return; - } - - // Make a dummy handle object (no buffers at - // all). Wait for data to come from the - // server, then call the callback - e = spawn(); - e.classname = "url_single_fopen_file"; - e.url_url = strzone(url); - e.url_fh = URL_FH_CURL; - e.url_rbuf = -1; - e.url_wbuf = -1; - e.url_ready = rdy; - e.url_ready_pass = pass; - e.url_id = i; - url_fromid[i] = e; - - // make sure this slot won't be reused quickly even on map change - cvar_set("_urllib_nextslot", ftos((i + 1) % NUM_URL_ID)); - break; - } - } - else if(url == "-") - { - switch(mode) - { - case FILE_WRITE: - case FILE_APPEND: - e = spawn(); - e.classname = "url_single_fopen_stdout"; - e.url_fh = URL_FH_STDOUT; - e.url_ready = rdy; - e.url_ready_pass = pass; - rdy(e, pass, URL_READY_CANWRITE); - break; - case FILE_READ: - print("url_single_fopen: cannot open '-' for reading\n"); - rdy(world, pass, URL_READY_ERROR); - break; - } - } - else - { - float fh; - fh = fopen(url, mode); - if(fh < 0) - { - rdy(world, pass, URL_READY_ERROR); - return; - } - else - { - e = spawn(); - e.classname = "url_single_fopen_file"; - e.url_fh = fh; - e.url_ready = rdy; - e.url_ready_pass = pass; - if(mode == FILE_READ) - rdy(e, pass, URL_READY_CANREAD); - else - rdy(e, pass, URL_READY_CANWRITE); - } - } -} - -// close a file -void url_fclose(entity e) -{ - int i; - - if(e.url_fh == URL_FH_CURL) - { - if(e.url_rbuf == -1 || e.url_wbuf != -1) // not(post GET/POST request) - if(e.url_rbuf != -1 || e.url_wbuf == -1) // not(pre POST request) - error("url_fclose: not closable in current state"); - - // closing an URL! - if(e.url_wbuf >= 0) - { - // we are closing the write end (HTTP POST request) - - // get slot for HTTP request - for(i = autocvar__urllib_nextslot; i < NUM_URL_ID; ++i) - if(url_fromid[i] == world) - break; - if(i >= NUM_URL_ID) - { - for(i = 0; i < autocvar__urllib_nextslot; ++i) - if(url_fromid[i] == world) - break; - if(i >= autocvar__urllib_nextslot) - { - print("url_fclose: too many concurrent requests\n"); - e.url_ready(e,e.url_ready_pass, URL_READY_ERROR); - buf_del(e.url_wbuf); - strunzone(e.url_url); - remove(e); - return; - } - } - - // POST the data - if(!crypto_uri_postbuf(e.url_url, i + MIN_URL_ID, "text/plain", "", e.url_wbuf, 0)) - { - print("url_fclose: failure in crypto_uri_postbuf\n"); - e.url_ready(e, e.url_ready_pass, URL_READY_ERROR); - buf_del(e.url_wbuf); - strunzone(e.url_url); - remove(e); - return; - } - - // delete write end. File handle is now in unusable - // state. Wait for data to come from the server, then - // call the callback - buf_del(e.url_wbuf); - e.url_wbuf = -1; - e.url_id = i; - url_fromid[i] = e; - - // make sure this slot won't be reused quickly even on map change - cvar_set("_urllib_nextslot", ftos((i + 1) % NUM_URL_ID)); - } - else - { - // we have READ all data, just close - e.url_ready(e, e.url_ready_pass, URL_READY_CLOSED); - buf_del(e.url_rbuf); - strunzone(e.url_url); - remove(e); - } - } - else if(e.url_fh == URL_FH_STDOUT) - { - e.url_ready(e, e.url_ready_pass, URL_READY_CLOSED); // closing creates no reading handle - remove(e); - } - else - { - // file - fclose(e.url_fh); - e.url_ready(e, e.url_ready_pass, URL_READY_CLOSED); // closing creates no reading handle - remove(e); - } -} - -// with \n (blame FRIK_FILE) -string url_fgets(entity e) -{ - if(e.url_fh == URL_FH_CURL) - { - if(e.url_rbuf == -1) - error("url_fgets: not readable in current state"); - // curl - string s; - s = bufstr_get(e.url_rbuf, e.url_rbufpos); - e.url_rbufpos += 1; - return s; - } - else if(e.url_fh == URL_FH_STDOUT) - { - // stdout - return string_null; - } - else - { - // file - return fgets(e.url_fh); - } -} - -// without \n (blame FRIK_FILE) -void url_fputs(entity e, string s) -{ - if(e.url_fh == URL_FH_CURL) - { - if(e.url_wbuf == -1) - error("url_fputs: not writable in current state"); - // curl - bufstr_set(e.url_wbuf, e.url_wbufpos, s); - e.url_wbufpos += 1; - } - else if(e.url_fh == URL_FH_STDOUT) - { - // stdout - print(s); - } - else - { - // file - fputs(e.url_fh, s); - } -} - -// multi URL object, tries URLs separated by space in sequence -void url_multi_ready(entity fh, entity me, float status) -{ - float n; - if(status == URL_READY_ERROR || status < 0) - { - if(status == -422) // Unprocessable Entity - { - print("uri_multi_ready: got HTTP error 422, data is in unusable format - not continuing\n"); - me.url_ready(fh, me.url_ready_pass, status); - strunzone(me.url_url); - remove(me); - return; - } - me.url_attempt += 1; - n = tokenize_console(me.url_url); - if(n <= me.url_attempt) - { - me.url_ready(fh, me.url_ready_pass, status); - strunzone(me.url_url); - remove(me); - return; - } - url_single_fopen(argv(me.url_attempt), me.url_mode, url_multi_ready, me); - return; - } - me.url_ready(fh, me.url_ready_pass, status); -} -void url_multi_fopen(string url, int mode, url_ready_func rdy, entity pass) -{ - float n; - n = tokenize_console(url); - if(n <= 0) - { - print("url_multi_fopen: need at least one URL\n"); - rdy(world, pass, URL_READY_ERROR); - return; - } - - entity me; - me = spawn(); - me.classname = "url_multi"; - me.url_url = strzone(url); - me.url_attempt = 0; - me.url_mode = mode; - me.url_ready = rdy; - me.url_ready_pass = pass; - url_single_fopen(argv(0), mode, url_multi_ready, me); -} diff --git a/qcsrc/common/urllib.qh b/qcsrc/common/urllib.qh deleted file mode 100644 index d58a0b1aa..000000000 --- a/qcsrc/common/urllib.qh +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef URLLIB_H -#define URLLIB_H - -const float URL_READY_ERROR = -1; -const float URL_READY_CLOSED = 0; -const float URL_READY_CANWRITE = 1; -const float URL_READY_CANREAD = 2; -// errors: -1, or negative HTTP status code -typedef void(entity handle, entity pass, float status) url_ready_func; - -void url_single_fopen(string url, float mode, url_ready_func rdy, entity pass); -void url_fclose(entity e); -string url_fgets(entity e); -void url_fputs(entity e, string s); - -// returns true if handled -float url_URI_Get_Callback(int id, float status, string data); -#define MIN_URL_ID URI_GET_URLLIB -#define NUM_URL_ID (URI_GET_URLLIB_END - URI_GET_URLLIB + 1) - -void url_multi_fopen(string url, float mode, url_ready_func rdy, entity pass); -#endif diff --git a/qcsrc/lib/_all.inc b/qcsrc/lib/_all.inc index 410eac721..1e7b85f48 100644 --- a/qcsrc/lib/_all.inc +++ b/qcsrc/lib/_all.inc @@ -7,3 +7,4 @@ #include "OO.qh" #include "Progname.qh" #include "Registry.qh" +#include "urllib.qc" diff --git a/qcsrc/lib/urllib.qc b/qcsrc/lib/urllib.qc new file mode 100644 index 000000000..ce8de504b --- /dev/null +++ b/qcsrc/lib/urllib.qc @@ -0,0 +1,388 @@ +#include "urllib.qh" + +// files +.float url_fh; +const float URL_FH_CURL = -1; +const float URL_FH_STDOUT = -2; + +// URLs +.string url_url; +.float url_wbuf; +.float url_wbufpos; +.float url_rbuf; +.float url_rbufpos; +.float url_id; +.url_ready_func url_ready; +.entity url_ready_pass; + +// for multi handles +.int url_attempt; +.int url_mode; + +entity url_fromid[NUM_URL_ID]; +int autocvar__urllib_nextslot; + +float url_URI_Get_Callback(int id, float status, string data) +{ + if(id < MIN_URL_ID) + return 0; + id -= MIN_URL_ID; + if(id >= NUM_URL_ID) + return 0; + entity e; + e = url_fromid[id]; + if(!e) + return 0; + if(e.url_rbuf >= 0 || e.url_wbuf >= 0) + { + printf("WARNING: handle %d (%s) has already received data?!?\n", id + NUM_URL_ID, e.url_url); + return 0; + } + + // whatever happens, we will remove the URL from the list of IDs + url_fromid[id] = NULL; + + // if we get here, we MUST have both buffers cleared + if(e.url_rbuf != -1 || e.url_wbuf != -1 || e.url_fh != URL_FH_CURL) + error("url_URI_Get_Callback: not a request waiting for data"); + + if(status == 0) + { + // WE GOT DATA! + float n, i; + n = tokenizebyseparator(data, "\n"); + e.url_rbuf = buf_create(); + if(e.url_rbuf < 0) + { + print("url_URI_Get_Callback: out of memory in buf_create\n"); + e.url_ready(e, e.url_ready_pass, URL_READY_ERROR); + strunzone(e.url_url); + remove(e); + return 1; + } + e.url_rbufpos = 0; + if(e.url_rbuf < 0) + { + print("url_URI_Get_Callback: out of memory in buf_create\n"); + e.url_ready(e, e.url_ready_pass, URL_READY_ERROR); + strunzone(e.url_url); + remove(e); + return 1; + } + for(i = 0; i < n; ++i) + bufstr_set(e.url_rbuf, i, argv(i)); + e.url_ready(e, e.url_ready_pass, URL_READY_CANREAD); + return 1; + } + else + { + // an ERROR + e.url_ready(e, e.url_ready_pass, -fabs(status)); + strunzone(e.url_url); + remove(e); + return 1; + } +} + +void url_single_fopen(string url, int mode, url_ready_func rdy, entity pass) +{ + entity e; + int i; + if(strstrofs(url, "://", 0) >= 0) + { + switch(mode) + { + case FILE_WRITE: + case FILE_APPEND: + // collect data to a stringbuffer for a POST request + // attempts to close will result in a reading handle + + // create a writing end that does nothing yet + e = spawn(); + e.classname = "url_single_fopen_file"; + e.url_url = strzone(url); + e.url_fh = URL_FH_CURL; + e.url_wbuf = buf_create(); + if(e.url_wbuf < 0) + { + print("url_single_fopen: out of memory in buf_create\n"); + rdy(e, pass, URL_READY_ERROR); + strunzone(e.url_url); + remove(e); + return; + } + e.url_wbufpos = 0; + e.url_rbuf = -1; + e.url_ready = rdy; + e.url_ready_pass = pass; + rdy(e, pass, URL_READY_CANWRITE); + break; + + case FILE_READ: + // read data only + + // get slot for HTTP request + for(i = autocvar__urllib_nextslot; i < NUM_URL_ID; ++i) + if(url_fromid[i] == NULL) + break; + if(i >= NUM_URL_ID) + { + for(i = 0; i < autocvar__urllib_nextslot; ++i) + if(url_fromid[i] == NULL) + break; + if(i >= autocvar__urllib_nextslot) + { + print("url_single_fopen: too many concurrent requests\n"); + rdy(NULL, pass, URL_READY_ERROR); + return; + } + } + + // GET the data + if(!crypto_uri_postbuf(url, i + MIN_URL_ID, string_null, string_null, -1, 0)) + { + print("url_single_fopen: failure in crypto_uri_postbuf\n"); + rdy(NULL, pass, URL_READY_ERROR); + return; + } + + // Make a dummy handle object (no buffers at + // all). Wait for data to come from the + // server, then call the callback + e = spawn(); + e.classname = "url_single_fopen_file"; + e.url_url = strzone(url); + e.url_fh = URL_FH_CURL; + e.url_rbuf = -1; + e.url_wbuf = -1; + e.url_ready = rdy; + e.url_ready_pass = pass; + e.url_id = i; + url_fromid[i] = e; + + // make sure this slot won't be reused quickly even on map change + cvar_set("_urllib_nextslot", ftos((i + 1) % NUM_URL_ID)); + break; + } + } + else if(url == "-") + { + switch(mode) + { + case FILE_WRITE: + case FILE_APPEND: + e = spawn(); + e.classname = "url_single_fopen_stdout"; + e.url_fh = URL_FH_STDOUT; + e.url_ready = rdy; + e.url_ready_pass = pass; + rdy(e, pass, URL_READY_CANWRITE); + break; + case FILE_READ: + print("url_single_fopen: cannot open '-' for reading\n"); + rdy(NULL, pass, URL_READY_ERROR); + break; + } + } + else + { + float fh; + fh = fopen(url, mode); + if(fh < 0) + { + rdy(NULL, pass, URL_READY_ERROR); + return; + } + else + { + e = spawn(); + e.classname = "url_single_fopen_file"; + e.url_fh = fh; + e.url_ready = rdy; + e.url_ready_pass = pass; + if(mode == FILE_READ) + rdy(e, pass, URL_READY_CANREAD); + else + rdy(e, pass, URL_READY_CANWRITE); + } + } +} + +// close a file +void url_fclose(entity e) +{ + int i; + + if(e.url_fh == URL_FH_CURL) + { + if(e.url_rbuf == -1 || e.url_wbuf != -1) // not(post GET/POST request) + if(e.url_rbuf != -1 || e.url_wbuf == -1) // not(pre POST request) + error("url_fclose: not closable in current state"); + + // closing an URL! + if(e.url_wbuf >= 0) + { + // we are closing the write end (HTTP POST request) + + // get slot for HTTP request + for(i = autocvar__urllib_nextslot; i < NUM_URL_ID; ++i) + if(url_fromid[i] == NULL) + break; + if(i >= NUM_URL_ID) + { + for(i = 0; i < autocvar__urllib_nextslot; ++i) + if(url_fromid[i] == NULL) + break; + if(i >= autocvar__urllib_nextslot) + { + print("url_fclose: too many concurrent requests\n"); + e.url_ready(e,e.url_ready_pass, URL_READY_ERROR); + buf_del(e.url_wbuf); + strunzone(e.url_url); + remove(e); + return; + } + } + + // POST the data + if(!crypto_uri_postbuf(e.url_url, i + MIN_URL_ID, "text/plain", "", e.url_wbuf, 0)) + { + print("url_fclose: failure in crypto_uri_postbuf\n"); + e.url_ready(e, e.url_ready_pass, URL_READY_ERROR); + buf_del(e.url_wbuf); + strunzone(e.url_url); + remove(e); + return; + } + + // delete write end. File handle is now in unusable + // state. Wait for data to come from the server, then + // call the callback + buf_del(e.url_wbuf); + e.url_wbuf = -1; + e.url_id = i; + url_fromid[i] = e; + + // make sure this slot won't be reused quickly even on map change + cvar_set("_urllib_nextslot", ftos((i + 1) % NUM_URL_ID)); + } + else + { + // we have READ all data, just close + e.url_ready(e, e.url_ready_pass, URL_READY_CLOSED); + buf_del(e.url_rbuf); + strunzone(e.url_url); + remove(e); + } + } + else if(e.url_fh == URL_FH_STDOUT) + { + e.url_ready(e, e.url_ready_pass, URL_READY_CLOSED); // closing creates no reading handle + remove(e); + } + else + { + // file + fclose(e.url_fh); + e.url_ready(e, e.url_ready_pass, URL_READY_CLOSED); // closing creates no reading handle + remove(e); + } +} + +// with \n (blame FRIK_FILE) +string url_fgets(entity e) +{ + if(e.url_fh == URL_FH_CURL) + { + if(e.url_rbuf == -1) + error("url_fgets: not readable in current state"); + // curl + string s; + s = bufstr_get(e.url_rbuf, e.url_rbufpos); + e.url_rbufpos += 1; + return s; + } + else if(e.url_fh == URL_FH_STDOUT) + { + // stdout + return string_null; + } + else + { + // file + return fgets(e.url_fh); + } +} + +// without \n (blame FRIK_FILE) +void url_fputs(entity e, string s) +{ + if(e.url_fh == URL_FH_CURL) + { + if(e.url_wbuf == -1) + error("url_fputs: not writable in current state"); + // curl + bufstr_set(e.url_wbuf, e.url_wbufpos, s); + e.url_wbufpos += 1; + } + else if(e.url_fh == URL_FH_STDOUT) + { + // stdout + print(s); + } + else + { + // file + fputs(e.url_fh, s); + } +} + +// multi URL object, tries URLs separated by space in sequence +void url_multi_ready(entity fh, entity me, float status) +{ + float n; + if(status == URL_READY_ERROR || status < 0) + { + if(status == -422) // Unprocessable Entity + { + print("uri_multi_ready: got HTTP error 422, data is in unusable format - not continuing\n"); + me.url_ready(fh, me.url_ready_pass, status); + strunzone(me.url_url); + remove(me); + return; + } + me.url_attempt += 1; + n = tokenize_console(me.url_url); + if(n <= me.url_attempt) + { + me.url_ready(fh, me.url_ready_pass, status); + strunzone(me.url_url); + remove(me); + return; + } + url_single_fopen(argv(me.url_attempt), me.url_mode, url_multi_ready, me); + return; + } + me.url_ready(fh, me.url_ready_pass, status); +} +void url_multi_fopen(string url, int mode, url_ready_func rdy, entity pass) +{ + float n; + n = tokenize_console(url); + if(n <= 0) + { + print("url_multi_fopen: need at least one URL\n"); + rdy(NULL, pass, URL_READY_ERROR); + return; + } + + entity me; + me = spawn(); + me.classname = "url_multi"; + me.url_url = strzone(url); + me.url_attempt = 0; + me.url_mode = mode; + me.url_ready = rdy; + me.url_ready_pass = pass; + url_single_fopen(argv(0), mode, url_multi_ready, me); +} diff --git a/qcsrc/lib/urllib.qh b/qcsrc/lib/urllib.qh new file mode 100644 index 000000000..6f1967851 --- /dev/null +++ b/qcsrc/lib/urllib.qh @@ -0,0 +1,34 @@ +#ifndef URLLIB_H +#define URLLIB_H + +#include "../common/util.qh" + +// URI handles +const int URI_GET_DISCARD = 0; +const int URI_GET_IPBAN = 1; +const int URI_GET_IPBAN_END = 16; +const int URI_GET_CURL = 17; +const int URI_GET_CURL_END = 32; +const int URI_GET_UPDATENOTIFICATION = 33; +const int URI_GET_URLLIB = 128; +const int URI_GET_URLLIB_END = 191; + +const float URL_READY_ERROR = -1; +const float URL_READY_CLOSED = 0; +const float URL_READY_CANWRITE = 1; +const float URL_READY_CANREAD = 2; +// errors: -1, or negative HTTP status code +typedef void(entity handle, entity pass, float status) url_ready_func; + +void url_single_fopen(string url, float mode, url_ready_func rdy, entity pass); +void url_fclose(entity e); +string url_fgets(entity e); +void url_fputs(entity e, string s); + +// returns true if handled +float url_URI_Get_Callback(int id, float status, string data); +#define MIN_URL_ID URI_GET_URLLIB +#define NUM_URL_ID (URI_GET_URLLIB_END - URI_GET_URLLIB + 1) + +void url_multi_fopen(string url, float mode, url_ready_func rdy, entity pass); +#endif diff --git a/qcsrc/menu/progs.src b/qcsrc/menu/progs.src index 0a1a715f0..4192c6991 100644 --- a/qcsrc/menu/progs.src +++ b/qcsrc/menu/progs.src @@ -21,7 +21,6 @@ xonotic/util.qc ../common/mapinfo.qc ../common/playerstats.qc ../common/test.qc -../common/urllib.qc ../common/util.qc ../common/items/all.qc diff --git a/qcsrc/menu/xonotic/util.qc b/qcsrc/menu/xonotic/util.qc index a50fb4cb1..a5fa9da47 100644 --- a/qcsrc/menu/xonotic/util.qc +++ b/qcsrc/menu/xonotic/util.qc @@ -4,7 +4,6 @@ #include "../../common/campaign_common.qh" #include "../../common/constants.qh" #include "../../common/mapinfo.qh" -#include "../../common/urllib.qh" #include "../../common/util.qh" #include "../../common/command/generic.qh" diff --git a/qcsrc/server/miscfunctions.qc b/qcsrc/server/miscfunctions.qc index e757e0172..71fb2de5e 100644 --- a/qcsrc/server/miscfunctions.qc +++ b/qcsrc/server/miscfunctions.qc @@ -18,7 +18,6 @@ #include "../common/playerstats.qh" #include "../common/teams.qh" #include "../common/triggers/subs.qh" -#include "../common/urllib.qh" #include "../common/util.qh" #include "../common/turrets/sv_turrets.qh" #include "../common/weapons/all.qh" diff --git a/qcsrc/server/mutators/mutators_include.qc b/qcsrc/server/mutators/mutators_include.qc index 1286317eb..a703fdc19 100644 --- a/qcsrc/server/mutators/mutators_include.qc +++ b/qcsrc/server/mutators/mutators_include.qc @@ -15,7 +15,6 @@ #include "../../common/nades.qh" #include "../../common/buffs.qh" #include "../../common/test.qh" - #include "../../common/urllib.qh" #include "../../common/command/markup.qh" #include "../../common/command/rpn.qh" #include "../../common/command/generic.qh" diff --git a/qcsrc/server/progs.src b/qcsrc/server/progs.src index 4aea59eb6..0cf64cae3 100644 --- a/qcsrc/server/progs.src +++ b/qcsrc/server/progs.src @@ -102,7 +102,6 @@ weapons/weaponsystem.qc ../common/test.qc ../common/viewloc.qc ../common/triggers/include.qc -../common/urllib.qc ../common/util.qc ../common/items/all.qc diff --git a/qcsrc/server/weapons/weaponstats.qc b/qcsrc/server/weapons/weaponstats.qc index a84969904..09d277046 100644 --- a/qcsrc/server/weapons/weaponstats.qc +++ b/qcsrc/server/weapons/weaponstats.qc @@ -3,7 +3,6 @@ #include "../g_world.qh" -#include "../../common/urllib.qh" #include "../../common/weapons/all.qh" void WeaponStats_Init()