From 5dd3541b0f60354d303283c15c90a171efd58c15 Mon Sep 17 00:00:00 2001 From: Rudolf Polzer Date: Tue, 7 Feb 2012 23:39:45 +0100 Subject: [PATCH] provide the "curl" command in all QC VMs --- commands.cfg | 1 + qcsrc/client/miscfunctions.qc | 21 ++++++ qcsrc/client/progs.src | 2 + qcsrc/common/command/generic.qc | 109 ++++++++++++++++++++++++++++++++ qcsrc/common/command/generic.qh | 2 + qcsrc/common/constants.qh | 10 +++ qcsrc/common/urllib.qc | 14 ++-- qcsrc/common/urllib.qh | 4 +- qcsrc/menu/command/menu_cmd.qc | 91 -------------------------- qcsrc/menu/progs.src | 2 + qcsrc/menu/xonotic/util.qc | 15 +++-- qcsrc/menu/xonotic/util.qh | 7 -- qcsrc/server/ipban.qc | 2 + qcsrc/server/miscfunctions.qc | 49 +++++++------- 14 files changed, 192 insertions(+), 137 deletions(-) diff --git a/commands.cfg b/commands.cfg index b3a9062d2..174a45834 100644 --- a/commands.cfg +++ b/commands.cfg @@ -52,6 +52,7 @@ alias who "qc_cmd_svcmd who ${* ?}" // Displa // generic commands (across all programs) alias addtolist "qc_cmd_svmenu addtolist ${* ?}" // Add a string to a cvar +alias qc_curl "qc_cmd_svmenu curl ${* ?}" // curl requests alias dumpcommands "qc_cmd_svmenu dumpcommands ${* ?}" // Dump all commands on the program to *_cmd_dump.txt alias maplist "qc_cmd_svmenu maplist ${* ?}" // Automatic control of maplist alias nextframe "qc_cmd_svmenu nextframe ${* ?}" // do something next frame diff --git a/qcsrc/client/miscfunctions.qc b/qcsrc/client/miscfunctions.qc index 6e4e2dd87..070096fbf 100644 --- a/qcsrc/client/miscfunctions.qc +++ b/qcsrc/client/miscfunctions.qc @@ -606,3 +606,24 @@ float getplayerisdead(float pl) return FALSE; } + +void URI_Get_Callback(float id, float status, string data) +{ + if(url_URI_Get_Callback(id, status, data)) + { + // handled + } + else if (id == URI_GET_DISCARD) + { + // discard + } + else if (id >= URI_GET_CURL && id <= URI_GET_CURL_END) + { + // sv_cmd curl + Curl_URI_Get_Callback(id, status, data); + } + else + { + print(sprintf(_("Received HTTP request data for an invalid id %d.\n"), id)); + } +} diff --git a/qcsrc/client/progs.src b/qcsrc/client/progs.src index 972efb6a0..8756fe944 100644 --- a/qcsrc/client/progs.src +++ b/qcsrc/client/progs.src @@ -22,6 +22,7 @@ Defs.qc ../common/command/rpn.qh ../common/command/generic.qh ../common/command/shared_defs.qh +../common/urllib.qh command/cl_cmd.qh @@ -99,6 +100,7 @@ noise.qc ../common/items.qc ../server/w_all.qc ../common/explosion_equation.qc +../common/urllib.qc command/cl_cmd.qc diff --git a/qcsrc/common/command/generic.qc b/qcsrc/common/command/generic.qc index d0cd7a304..68ee8c712 100644 --- a/qcsrc/common/command/generic.qc +++ b/qcsrc/common/command/generic.qc @@ -65,6 +65,114 @@ void GenericCommand_addtolist(float request, float argc) } } +float curl_uri_get_pos; +float curl_uri_get_exec[URI_GET_CURL_END - URI_GET_CURL + 1]; +string curl_uri_get_cvar[URI_GET_CURL_END - URI_GET_CURL + 1]; +void Curl_URI_Get_Callback(float id, float status, string data) +{ + float i; + float do_exec; + string do_cvar; + i = id - URI_GET_CURL; + do_exec = curl_uri_get_exec[i]; + do_cvar = curl_uri_get_cvar[i]; + if(status != 0) + { + print(sprintf(_("error: status is %d\n"), status)); + if(do_cvar) + strunzone(do_cvar); + return; + } + if(do_exec) + localcmd(data); + if(do_cvar) + { + cvar_set(do_cvar, data); + strunzone(do_cvar); + } + if(!do_exec && !do_cvar) + print(data); +} + +void GenericCommand_curl(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + float do_exec; + string do_cvar; + float key; + float i, j; + string url; + float buf; + float r; + + do_exec = FALSE; + do_cvar = string_null; + key = -1; + + for(i = 1; i+1 < argc; ++i) + { + if(argv(i) == "--cvar" && i+2 < argc) + { + ++i; + do_cvar = strzone(argv(i)); + continue; + } + if(argv(i) == "--exec") + { + do_exec = TRUE; + continue; + } + if(argv(i) == "--key" && i+2 < argc) + { + ++i; + key = stof(argv(i)); + continue; + } + break; + } + + // now, argv(i) is the URL + // following args may be POST parameters + url = argv(i); + ++i; + buf = buf_create(); + j = 0; + for(; i+1 < argc; i += 2) + bufstr_set(buf, ++j, sprintf("%s=%s", uri_escape(argv(i)), uri_escape(argv(i+1)))); + if(i < argc) + bufstr_set(buf, ++j, sprintf("submit=%s", uri_escape(argv(i)))); + + if(j == 0) // no args: GET + r = crypto_uri_postbuf(url, URI_GET_CURL + curl_uri_get_pos, string_null, string_null, -1, key); + else // with args: POST + r = crypto_uri_postbuf(url, URI_GET_CURL + curl_uri_get_pos, "application/x-www-form-urlencoded", "&", buf, key); + + if(r) + { + curl_uri_get_exec[curl_uri_get_pos] = do_exec; + curl_uri_get_cvar[curl_uri_get_pos] = do_cvar; + curl_uri_get_pos = mod(curl_uri_get_pos + 1, URI_GET_CURL_END - URI_GET_CURL + 1); + } + else + print(_("error creating curl handle\n")); + + buf_del(buf); + + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " curl [--key N] [--cvar] [--exec] URL [postargs...]")); + return; + } + } +} + void GenericCommand_dumpcommands(float request) { switch(request) @@ -352,6 +460,7 @@ void GenericCommand_(float request) // Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;) #define GENERIC_COMMANDS(request,arguments,command) \ GENERIC_COMMAND("addtolist", GenericCommand_addtolist(request, arguments), "Add a string to a cvar") \ + GENERIC_COMMAND("curl", GenericCommand_curl(request, arguments), "Queries an URL") \ GENERIC_COMMAND("dumpcommands", GenericCommand_dumpcommands(request), "Dump all commands on the program to *_cmd_dump.txt") \ GENERIC_COMMAND("maplist", GenericCommand_maplist(request, arguments), "Automatic control of maplist") \ GENERIC_COMMAND("nextframe", GenericCommand_nextframe(request, arguments, command), "Execute the given command next frame of this VM") \ diff --git a/qcsrc/common/command/generic.qh b/qcsrc/common/command/generic.qh index 6fa7d3822..4391555c6 100644 --- a/qcsrc/common/command/generic.qh +++ b/qcsrc/common/command/generic.qh @@ -15,3 +15,5 @@ string GetProgramCommandPrefix(void); #define CMD_Write(s) fputs(fh, s) #define CMD_Write_Alias(execute,command,description) CMD_Write(sprintf("alias %-20s \"%-13s %-20s ${* ?}\" // %s\n", command, execute, command, description)) void GenericCommand_macro_write_aliases(float fh); + +void Curl_URI_Get_Callback(float id, float status, string data); diff --git a/qcsrc/common/constants.qh b/qcsrc/common/constants.qh index e413ad94a..3e9795690 100644 --- a/qcsrc/common/constants.qh +++ b/qcsrc/common/constants.qh @@ -586,3 +586,13 @@ noref var vector autocvar_sv_player_headsize = '24 24 12'; #define SPAWN_PRIO_NEAR_TEAMMATE_SAMETEAM 100 #define SPAWN_PRIO_RACE_PREVIOUS_SPAWN 50 #define SPAWN_PRIO_GOOD_DISTANCE 10 + +// URI handles +#define URI_GET_DISCARD 0 +#define URI_GET_IPBAN 1 +#define URI_GET_IPBAN_END 16 +#define URI_GET_CURL 17 +#define URI_GET_CURL_END 32 +#define URI_GET_UPDATENOTIFICATION 33 +#define URI_GET_URLLIB 128 +#define URI_GET_URLLIB_END 191 diff --git a/qcsrc/common/urllib.qc b/qcsrc/common/urllib.qc index 1bc065027..9a5e0e7da 100644 --- a/qcsrc/common/urllib.qc +++ b/qcsrc/common/urllib.qc @@ -13,6 +13,10 @@ .url_ready_func url_ready; .entity url_ready_pass; +// for multi handles +.float url_attempt; +.float url_mode; + entity url_fromid[NUM_URL_ID]; float autocvar__urllib_nextslot; @@ -345,16 +349,16 @@ void url_multi_ready(entity fh, entity me, float status) remove(me); return; } - me.cnt += 1; + me.url_attempt += 1; n = tokenize_console(me.url_url); - if(n <= me.cnt) + 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.cnt), me.lip, url_multi_ready, me); + url_single_fopen(argv(me.url_attempt), me.url_mode, url_multi_ready, me); return; } me.url_ready(fh, me.url_ready_pass, status); @@ -374,8 +378,8 @@ void url_multi_fopen(string url, float mode, url_ready_func rdy, entity pass) me = spawn(); me.classname = "url_multi"; me.url_url = strzone(url); - me.cnt = 0; - me.lip = mode; + 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 index f92178b2f..8a871c6b3 100644 --- a/qcsrc/common/urllib.qh +++ b/qcsrc/common/urllib.qh @@ -12,7 +12,7 @@ void url_fputs(entity e, string s); // returns true if handled float url_URI_Get_Callback(float id, float status, string data); -#define MIN_URL_ID 128 -#define NUM_URL_ID 64 +#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); diff --git a/qcsrc/menu/command/menu_cmd.qc b/qcsrc/menu/command/menu_cmd.qc index 3be6edc66..0e0df0589 100644 --- a/qcsrc/menu/command/menu_cmd.qc +++ b/qcsrc/menu/command/menu_cmd.qc @@ -25,35 +25,6 @@ void _dumptree_close(entity pass, entity me) } } -float curl_uri_get_pos; -float curl_uri_get_exec[URI_GET_CURL_END - URI_GET_CURL + 1]; -string curl_uri_get_cvar[URI_GET_CURL_END - URI_GET_CURL + 1]; -void Curl_URI_Get_Callback(float id, float status, string data) -{ - float i; - float do_exec; - string do_cvar; - i = id - URI_GET_CURL; - do_exec = curl_uri_get_exec[i]; - do_cvar = curl_uri_get_cvar[i]; - if(status != 0) - { - print(sprintf(_("error: status is %d\n"), status)); - if(do_cvar) - strunzone(do_cvar); - return; - } - if(do_exec) - localcmd(data); - if(do_cvar) - { - cvar_set(do_cvar, data); - strunzone(do_cvar); - } - if(!do_exec && !do_cvar) - print(data); -} - void GameCommand(string theCommand) { float argc; @@ -119,68 +90,6 @@ void GameCommand(string theCommand) if(argv(0) == "curl") { - float do_exec; - string do_cvar; - float key; - float i, j; - string url; - float buf; - float r; - - do_exec = FALSE; - do_cvar = string_null; - key = -1; - - for(i = 1; i+1 < argc; ++i) - { - if(argv(i) == "--cvar" && i+2 < argc) - { - ++i; - do_cvar = strzone(argv(i)); - continue; - } - if(argv(i) == "--exec") - { - do_exec = TRUE; - continue; - } - if(argv(i) == "--key" && i+2 < argc) - { - ++i; - key = stof(argv(i)); - continue; - } - break; - } - - // now, argv(i) is the URL - // following args may be POST parameters - url = argv(i); - ++i; - buf = buf_create(); - j = 0; - for(; i+1 < argc; i += 2) - bufstr_set(buf, ++j, sprintf("%s=%s", uri_escape(argv(i)), uri_escape(argv(i+1)))); - if(i < argc) - bufstr_set(buf, ++j, sprintf("submit=%s", uri_escape(argv(i)))); - - if(j == 0) // no args: GET - r = crypto_uri_postbuf(url, URI_GET_CURL + curl_uri_get_pos, string_null, string_null, -1, key); - else // with args: POST - r = crypto_uri_postbuf(url, URI_GET_CURL + curl_uri_get_pos, "application/x-www-form-urlencoded", "&", buf, key); - - if(r) - { - curl_uri_get_exec[curl_uri_get_pos] = do_exec; - curl_uri_get_cvar[curl_uri_get_pos] = do_cvar; - curl_uri_get_pos = mod(curl_uri_get_pos + 1, URI_GET_CURL_END - URI_GET_CURL + 1); - } - else - print(_("error creating curl handle\n")); - - buf_del(buf); - - return; } print(_("Invalid command. For a list of supported commands, try menu_cmd help.\n")); diff --git a/qcsrc/menu/progs.src b/qcsrc/menu/progs.src index 1f70e0e7b..0f545e60c 100644 --- a/qcsrc/menu/progs.src +++ b/qcsrc/menu/progs.src @@ -19,6 +19,7 @@ oo/base.h ../common/command/rpn.qh ../common/command/generic.qh ../common/command/shared_defs.qh +../common/urllib.qh command/menu_cmd.qh menu.qh @@ -44,6 +45,7 @@ xonotic/util.qc ../common/campaign_setup.qc ../common/mapinfo.qc ../common/items.qc +../common/urllib.qc ../warpzonelib/mathlib.qc diff --git a/qcsrc/menu/xonotic/util.qc b/qcsrc/menu/xonotic/util.qc index 486bcce8d..ab86bebae 100644 --- a/qcsrc/menu/xonotic/util.qc +++ b/qcsrc/menu/xonotic/util.qc @@ -259,18 +259,23 @@ string _Nex_ExtResponseSystem_UpdateToURL; void URI_Get_Callback(float id, float status, string data) { - if (id == URI_GET_DISCARD) + if(url_URI_Get_Callback(id, status, data)) { - // discard + // handled } - else if(id == URI_GET_UPDATENOTIFICATION) + else if (id == URI_GET_DISCARD) { - UpdateNotification_URI_Get_Callback(id, status, data); + // discard } - else if(id >= URI_GET_CURL && id <= URI_GET_CURL_END) + else if (id >= URI_GET_CURL && id <= URI_GET_CURL_END) { + // sv_cmd curl Curl_URI_Get_Callback(id, status, data); } + else if (id == URI_GET_UPDATENOTIFICATION) + { + UpdateNotification_URI_Get_Callback(id, status, data); + } else { print(sprintf(_("Received HTTP request data for an invalid id %d.\n"), id)); diff --git a/qcsrc/menu/xonotic/util.qh b/qcsrc/menu/xonotic/util.qh index f682fd30f..be13ee289 100644 --- a/qcsrc/menu/xonotic/util.qh +++ b/qcsrc/menu/xonotic/util.qh @@ -23,15 +23,8 @@ string getZonedTooltipForIdentifier(string s); string resolvemod(string m); -float URI_GET_DISCARD = 0; - -float URI_GET_UPDATENOTIFICATION = 1; void UpdateNotification_URI_Get_Callback(float id, float status, string data); -float URI_GET_CURL = 2; -float URI_GET_CURL_END = 9; -void Curl_URI_Get_Callback(float id, float status, string data); - void URI_Get_Callback(float id, float status, string data); // game type list box stuff (does not NEED to contain all game types, other diff --git a/qcsrc/server/ipban.qc b/qcsrc/server/ipban.qc index b40a1e3a2..2034b27dc 100644 --- a/qcsrc/server/ipban.qc +++ b/qcsrc/server/ipban.qc @@ -19,6 +19,8 @@ * server IP that registered the ban */ +#define MAX_IPBAN_URIS (URI_GET_IPBAN_END - URI_GET_IPBAN + 1) + float Ban_Insert(string ip, float bantime, string reason, float dosync); void OnlineBanList_SendBan(string ip, float bantime, string reason) diff --git a/qcsrc/server/miscfunctions.qc b/qcsrc/server/miscfunctions.qc index b780a8511..8afee84d0 100644 --- a/qcsrc/server/miscfunctions.qc +++ b/qcsrc/server/miscfunctions.qc @@ -1984,35 +1984,30 @@ float WarpZone_Projectile_Touch_ImpactFilter_Callback() } #define PROJECTILE_TOUCH if(WarpZone_Projectile_Touch()) return -float MAX_IPBAN_URIS = 16; - -float URI_GET_DISCARD = 0; -float URI_GET_IPBAN = 1; -float URI_GET_IPBAN_END = 16; - void URI_Get_Callback(float id, float status, string data) { - dprint("Received HTTP request data for id ", ftos(id), "; status is ", ftos(status), "\nData is:\n"); - dprint(data); - dprint("\nEnd of data.\n"); - - if(url_URI_Get_Callback(id, status, data)) - { - // handled - } - else if (id == URI_GET_DISCARD) - { - // discard - } - else if (id >= URI_GET_IPBAN && id <= URI_GET_IPBAN_END) - { - // online ban list - OnlineBanList_URI_Get_Callback(id, status, data); - } - else - { - print("Received HTTP request data for an invalid id ", ftos(id), ".\n"); - } + if(url_URI_Get_Callback(id, status, data)) + { + // handled + } + else if (id == URI_GET_DISCARD) + { + // discard + } + else if (id >= URI_GET_CURL && id <= URI_GET_CURL_END) + { + // sv_cmd curl + Curl_URI_Get_Callback(id, status, data); + } + else if (id >= URI_GET_IPBAN && id <= URI_GET_IPBAN_END) + { + // online ban list + OnlineBanList_URI_Get_Callback(id, status, data); + } + else + { + print("Received HTTP request data for an invalid id ", ftos(id), ".\n"); + } } string uid2name(string myuid) { -- 2.39.2