UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
web_cgame.cpp
Go to the documentation of this file.
1 
6 /*
7 Copyright (C) 2002-2020 UFO: Alien Invasion.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 See the GNU General Public License for more details.m
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 */
24 
25 #include "web_cgame.h"
26 #include "web_main.h"
27 #include "../cl_shared.h"
28 #include "../cgame/cl_game.h"
29 #include "../ui/ui_main.h"
30 #include "../../shared/parse.h"
31 
36 
37 #define URL_SIZE 576
38 
50 static const char* WEB_CGameGetURL (char* out, size_t outSize, const char* url, const char* cgameId, int category, const char* filename, int userId = -1)
51 {
52  char categoryStr[MAX_VAR];
53  Com_sprintf(categoryStr, sizeof(categoryStr), "%i", category);
54  char userIdStr[MAX_VAR];
55  Com_sprintf(userIdStr, sizeof(userIdStr), "%i", userId);
56 
57  const struct urlIds_s {
58  const char* id;
59  const char* replace;
60  bool mandatory;
61  } urlIds[] = {
62  {"$cgame$", cgameId, true},
63  {"$category$", categoryStr, category >= 0},
64  {"$file$", filename, filename != nullptr},
65  {"$userid$", userIdStr, userId > 0}
66  };
67 
68  Q_strncpyz(out, url, outSize);
69 
70  const size_t entries = lengthof(urlIds);
71  for (int i = 0; i < entries; i++) {
72  const urlIds_s& id = urlIds[i];
73  if (strstr(out, id.id) != nullptr) {
74  char encoded[256] = { '\0' };
75  const char* replace = encoded;
76  if (id.replace != nullptr) {
77  if (!HTTP_Encode(id.replace, encoded, sizeof(encoded))) {
78  Com_Printf("failed to encode '%s'\n", id.replace);
79  return nullptr;
80  }
81  }
82  char buf1[URL_SIZE];
83  if (!Q_strreplace(out, id.id, replace, buf1, sizeof(buf1))) {
84  Com_Printf("failed to replace '%s'\n", id.id);
85  return nullptr;
86  }
87  Q_strncpyz(out, buf1, outSize);
88  } else if (id.mandatory) {
89  Com_Printf("'%s' is missing in the url\n", id.id);
90  return nullptr;
91  }
92  }
93 
94  return out;
95 }
96 
106 bool WEB_CGameUpload (const char* cgameId, int category, const char* filename)
107 {
108  if (Q_strnull(cgameId))
109  return false;
110 
111  if (Q_strnull(filename))
112  return false;
113 
114  if (!WEB_CheckAuth())
115  return false;
116 
117  const char* fullPath = va("%s/%s", FS_Gamedir(), filename);
118  /* we ignore this, because this file is not in the users save path,
119  * but part of the game data. Don't upload this. */
120  if (!FS_FileExists("%s", fullPath)) {
121  Com_Printf("no user data: '%s'\n", fullPath);
122  UI_ExecuteConfunc("cgame_uploadfailed");
123  return false;
124  }
125 
126  char url[URL_SIZE];
127  const char* encodedURL = WEB_CGameGetURL(url, sizeof(url), web_cgameuploadurl->string, cgameId, category, nullptr);
128  if (encodedURL == nullptr) {
129  UI_ExecuteConfunc("cgame_uploadfailed");
130  return false;
131  }
132 
133  if (!WEB_PutFile("cgame", fullPath, encodedURL)) {
134  Com_Printf("failed to upload the team from file '%s'\n", filename);
135  UI_ExecuteConfunc("cgame_uploadfailed");
136  return false;
137  }
138 
139  Com_Printf("uploaded the team '%s'\n", filename);
140  UI_ExecuteConfunc("cgame_uploadsuccessful");
141  return true;
142 }
143 
152 bool WEB_CGameDelete (const char* cgameId, int category, const char* filename)
153 {
154  if (!WEB_CheckAuth())
155  return false;
156 
157  char url[URL_SIZE];
158  const char* encodedURL = WEB_CGameGetURL(url, sizeof(url), web_cgamedeleteurl->string, cgameId, category, filename);
159  if (encodedURL == nullptr)
160  return false;
161 
162  if (!WEB_GetURL(encodedURL, nullptr)) {
163  Com_Printf("failed to delete the cgame file '%s' from the server\n", filename);
164  UI_ExecuteConfunc("cgame_deletefailed");
165  return false;
166  }
167 
168  Com_Printf("deleted the cgame file '%s'\n", filename);
169 
170  char idBuf[MAX_VAR];
171  const char* id = Com_SkipPath(filename);
172  Com_StripExtension(id, idBuf, sizeof(idBuf));
173 
174  UI_ExecuteConfunc("cgame_deletesuccessful \"%s\" %i %i", idBuf, category, web_userid->integer);
175  return true;
176 }
177 
187 bool WEB_CGameDownloadFromUser (const char* cgameId, int category, const char* filename, int userId)
188 {
189  char url[URL_SIZE];
190  const char* encodedURL = WEB_CGameGetURL(url, sizeof(url), web_cgamedownloadurl->string, cgameId, category, filename, userId);
191  if (encodedURL == nullptr)
192  return false;
193 
194  char buf[MAX_OSPATH];
195  GAME_GetRelativeSavePath(buf, sizeof(buf));
196  Q_strcat(buf, sizeof(buf), "%s", filename);
197 
198  ScopedFile f;
199  FS_OpenFile(buf, &f, FILE_WRITE);
200  if (!f) {
201  Com_Printf("Could not open the target file\n");
202  return false;
203  }
204 
205  /* no login is needed here */
206  if (!HTTP_GetToFile(encodedURL, f.getFile())) {
207  Com_Printf("cgame file download failed from '%s'\n", url);
208  return false;
209  }
210  return true;
211 }
212 
218 static void WEB_ListCGameFilesCallback (const char* responseBuf, void* userdata)
219 {
220  int* count = (int*)userdata;
221 
222  if (count != nullptr)
223  *count = 0;
224 
225  if (!responseBuf) {
226  Com_Printf("Could not load the cgame list\n");
227  return;
228  }
229 
230  struct entry_s {
231  int userId;
232  int category;
233  char file[MAX_OSPATH];
234  char name[MAX_VAR];
235  };
236 
237  const value_t values[] = {
238  {"userid", V_INT, offsetof(entry_s, userId), MEMBER_SIZEOF(entry_s, userId)},
239  {"category", V_INT, offsetof(entry_s, category), MEMBER_SIZEOF(entry_s, category)},
240  {"file", V_STRING, offsetof(entry_s, file), 0},
241  {"name", V_STRING, offsetof(entry_s, name), 0},
242  {nullptr, V_NULL, 0, 0}
243  };
244 
245  entry_s entry;
246 
247  const char* token = Com_Parse(&responseBuf);
248  if (token[0] != '{') {
249  Com_Printf("invalid token: '%s' - expected {\n", token);
250  return;
251  }
252  int num = 0;
253  int level = 1;
254  for (;;) {
255  token = Com_Parse(&responseBuf);
256  if (!responseBuf)
257  break;
258  if (token[0] == '{') {
259  level++;
260  OBJZERO(entry);
261  continue;
262  }
263  if (token[0] == '}') {
264  level--;
265  if (level == 0) {
266  break;
267  }
268  char idBuf[MAX_VAR];
269  const char* id = Com_SkipPath(entry.file);
270  Com_StripExtension(id, idBuf, sizeof(idBuf));
271  const bool ownEntry = entry.userId == web_userid->integer;
272  UI_ExecuteConfunc("cgamefiles_add \"%s\" %i %i \"%s\" \"%s\" %i", idBuf, entry.category, entry.userId, id, entry.name, ownEntry ? 1 : 0);
273  num++;
274  continue;
275  }
276 
277  const value_t* value;
278  for (value = values; value->string; value++) {
279  if (!Q_streq(token, value->string))
280  continue;
281  token = Com_Parse(&responseBuf);
282  if (!responseBuf)
283  break;
284  /* found a normal particle value */
285  Com_EParseValue(&entry, token, value->type, value->ofs, value->size);
286  break;
287  }
288  if (value->string == nullptr) {
289  Com_DPrintf(DEBUG_CLIENT, "invalid value found: '%s'\n", token);
290  // skip the invalid value for this and try to go on
291  token = Com_Parse(&responseBuf);
292  }
293  }
294  if (num == 0) {
295  UI_ExecuteConfunc("cgamefiles_nofilesfound");
296  }
297  Com_Printf("found %i cgame file entries\n", num);
298  if (count != nullptr)
299  *count = num;
300 }
301 
310 int WEB_CGameListForUser (const char* cgameId, int category, int userId)
311 {
312  if (userId == -1) {
313  if (!WEB_CheckAuth())
314  return -1;
315 
316  userId = web_userid->integer;
317  }
318 
319  char url[URL_SIZE];
320  const char* encodedURL = WEB_CGameGetURL(url, sizeof(url), web_cgamelisturl->string, cgameId, category, nullptr, userId);
321  if (encodedURL == nullptr)
322  return -1;
323 
324  UI_ExecuteConfunc("cgamefiles_clear");
325  int count = 0;
326  if (!WEB_GetURL(encodedURL, WEB_ListCGameFilesCallback, &count)) {
327  Com_Printf("failed to query the cgame list for '%s' in category %i and for user %i\n", cgameId, category, userId);
328  return -1;
329  }
330 
331  return count;
332 }
333 
334 static void WEB_UploadCGame_f (void)
335 {
336  if (Cmd_Argc() < 3) {
337  Com_Printf("Usage: %s <category> <filename>\n", Cmd_Argv(0));
338  return;
339  }
340  const char* name = GAME_GetCurrentName();
341  if (name == nullptr) {
342  Com_Printf("No active cgame type\n");
343  return;
344  }
345  const int category = atoi(Cmd_Argv(1));
346  char filename[MAX_OSPATH];
347  GAME_GetRelativeSavePath(filename, sizeof(filename));
348  Q_strcat(filename, sizeof(filename), "%s", Cmd_Argv(2));
349  WEB_CGameUpload(name, category, filename);
350 }
351 
352 static void WEB_DeleteCGame_f (void)
353 {
354  if (Cmd_Argc() < 3) {
355  Com_Printf("Usage: %s <category> <filename>\n", Cmd_Argv(0));
356  return;
357  }
358  const char* name = GAME_GetCurrentName();
359  if (name == nullptr) {
360  Com_Printf("No active cgame type\n");
361  return;
362  }
363  const int category = atoi(Cmd_Argv(1));
364  const char* filename = Cmd_Argv(2);
365  WEB_CGameDelete(name, category, filename);
366 }
367 
368 static void WEB_DownloadCGame_f (void)
369 {
370  if (Cmd_Argc() < 3) {
371  Com_Printf("Usage: %s <category> <filename> [<userid>]\n", Cmd_Argv(0));
372  return;
373  }
374  const char* name = GAME_GetCurrentName();
375  if (name == nullptr) {
376  Com_Printf("No active cgame type\n");
377  return;
378  }
379  const int category = atoi(Cmd_Argv(1));
380  const char* filename = Cmd_Argv(2);
381  const int userId = Cmd_Argc() == 4 ? atoi(Cmd_Argv(3)) : -1;
382  WEB_CGameDownloadFromUser(name, category, filename, userId);
383 }
384 
385 static void WEB_ListCGame_f (void)
386 {
387  if (Cmd_Argc() < 2) {
388  Com_Printf("Usage: %s <category> [<userid>]\n", Cmd_Argv(0));
389  return;
390  }
391  const char* name = GAME_GetCurrentName();
392  if (name == nullptr) {
393  Com_Printf("No active cgame type\n");
394  return;
395  }
396  const int category = atoi(Cmd_Argv(1));
397  const int userId = Cmd_Argc() == 3 ? atoi(Cmd_Argv(2)) : -1;
398  if (WEB_CGameListForUser(name, category, userId) == -1) {
399  Com_Printf("failed to list the cgame files for '%s' in category %i for userid %i\n", name, category, userId);
400  }
401 }
402 
403 void WEB_CGameCvars (void)
404 {
405  web_cgamedownloadurl = Cvar_Get("web_cgamedownloadurl", WEB_API_SERVER "cgame/$cgame$/$userid$/$category$/$file$", 0, "The url to download a shared cgame file from. Use $userid$, $category$, $cgame$ and $file$ as placeholders.");
406  web_cgamelisturl = Cvar_Get("web_cgamelisturl", WEB_API_SERVER "api/cgamelist.php?cgame=$cgame$&category=$category$&userid=$userid$", 0, "The url to get the cgame file list from.");
407  web_cgamedeleteurl = Cvar_Get("web_cgamedeleteurl", WEB_API_SERVER "api/cgamedelete.php?cgame=$cgame$&category=$category$&file=$file$", 0, "The url to call if you want to delete one of your own cgame files again.");
408  web_cgameuploadurl = Cvar_Get("web_cgameuploadurl", WEB_API_SERVER "api/cgameupload.php?cgame=$cgame$&category=$category$", 0, "The url to upload a cgame file to.");
409 }
410 
411 void WEB_CGameCommands (void)
412 {
413  Cmd_AddCommand("web_uploadcgame", WEB_UploadCGame_f, "Upload a file for a cgame to the UFOAI server");
414  Cmd_AddCommand("web_deletecgame", WEB_DeleteCGame_f, "Delete one of your own cgame files from the server");
415  Cmd_AddCommand("web_downloadcgame", WEB_DownloadCGame_f, "Download a cgame file from the UFOAI server");
416  Cmd_AddCommand("web_listcgame", WEB_ListCGame_f, "Show all files for a cgame on the UFOAI server");
417 }
bool Q_strnull(const char *string)
Definition: shared.h:138
const char * Cmd_Argv(int arg)
Returns a given argument.
Definition: cmd.cpp:516
void Cmd_AddCommand(const char *cmdName, xcommand_t function, const char *desc)
Add a new command to the script interface.
Definition: cmd.cpp:744
static cvar_t * web_cgameuploadurl
Definition: web_cgame.cpp:34
const char * Com_SkipPath(const char *pathname)
Returns just the filename from a given path.
Definition: shared.cpp:37
cvar_t * web_userid
Definition: web_main.cpp:35
int FS_OpenFile(const char *filename, qFILE *file, filemode_t mode)
Finds and opens the file in the search path.
Definition: files.cpp:162
static void WEB_ListCGameFilesCallback(const char *responseBuf, void *userdata)
The http callback for the cgame list command.
Definition: web_cgame.cpp:218
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
Definition: shared.cpp:410
This is a cvar definition. Cvars can be user modified and used in our menus e.g.
Definition: cvar.h:71
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition: shared.cpp:494
void Com_StripExtension(const char *in, char *out, const size_t size)
Removes the file extension from a filename.
Definition: shared.cpp:259
bool FS_FileExists(const char *filename,...)
Checks whether a file exists (not in virtual filesystem)
Definition: files.cpp:1581
const char * filename
Definition: ioapi.h:41
static cvar_t * web_cgamelisturl
Definition: web_cgame.cpp:35
#define MAX_OSPATH
Definition: filesys.h:44
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
FILE * getFile() const
Definition: filesys.h:214
valueTypes_t type
Definition: scripts.h:170
#define WEB_API_SERVER
Definition: web_main.h:31
int integer
Definition: cvar.h:81
static void WEB_ListCGame_f(void)
Definition: web_cgame.cpp:385
voidpf void * buf
Definition: ioapi.h:42
void WEB_CGameCommands(void)
Definition: web_cgame.cpp:411
static const char * WEB_CGameGetURL(char *out, size_t outSize, const char *url, const char *cgameId, int category, const char *filename, int userId=-1)
Replaces placeholders in the urls with given values.
Definition: web_cgame.cpp:50
const char * FS_Gamedir(void)
Called to find where to write a file (savegames, etc)
Definition: files.cpp:68
GLuint * id
Definition: r_gl.h:149
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition: shared.cpp:457
#define DEBUG_CLIENT
Definition: defines.h:59
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags, const char *desc)
Init or return a cvar.
Definition: cvar.cpp:342
#define OBJZERO(obj)
Definition: shared.h:178
bool WEB_PutFile(const char *formName, const char *fileName, const char *url, upparam_t *params)
Uploads a file to the server with the login credentials.
Definition: web_main.cpp:87
#define MAX_VAR
Definition: shared.h:36
int Cmd_Argc(void)
Return the number of arguments of the current command. "command parameter" will result in a argc of 2...
Definition: cmd.cpp:505
static cvar_t * web_cgamedownloadurl
Definition: web_cgame.cpp:32
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
Definition: common.cpp:398
bool HTTP_GetToFile(const char *url, FILE *file, const char *postfields)
Downloads the given url into the given file.
Definition: http.cpp:336
static void WEB_DownloadCGame_f(void)
Definition: web_cgame.cpp:368
static void WEB_DeleteCGame_f(void)
Definition: web_cgame.cpp:352
const char * string
Definition: scripts.h:169
bool WEB_CheckAuth(void)
Pushes the webauth window if the password is not yet set.
Definition: web_main.cpp:176
int WEB_CGameListForUser(const char *cgameId, int category, int userId)
Shows the uploaded files for the particular cgame category and the given userid.
Definition: web_cgame.cpp:310
QGL_EXTERN GLuint count
Definition: r_gl.h:99
size_t ofs
Definition: scripts.h:171
QGL_EXTERN GLfloat f
Definition: r_gl.h:114
static cvar_t * web_cgamedeleteurl
Definition: web_cgame.cpp:33
const char * GAME_GetCurrentName(void)
Definition: cl_game.cpp:231
int Com_EParseValue(void *base, const char *token, valueTypes_t type, int ofs, size_t size)
Definition: scripts.cpp:978
const char * Com_Parse(const char *data_p[], char *target, size_t size, bool replaceWhitespaces)
Parse a token out of a string.
Definition: parse.cpp:107
Definition: scripts.h:49
bool HTTP_Encode(const char *url, char *out, size_t outLength)
This function converts the given url to an URL encoded string. All input characters that are not a-z...
Definition: http.cpp:352
QGL_EXTERN GLint i
Definition: r_gl.h:113
static void WEB_UploadCGame_f(void)
Definition: web_cgame.cpp:334
char * string
Definition: cvar.h:73
bool WEB_CGameUpload(const char *cgameId, int category, const char *filename)
Uploads a file to the server.
Definition: web_cgame.cpp:106
UFOAI web interface management. Authentication as well as uploading/downloading stuff to and from you...
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
Definition: shared.cpp:475
#define MEMBER_SIZEOF(TYPE, MEMBER)
Definition: scripts.h:34
bool Q_strreplace(const char *source, const char *pattern, const char *replace, char *dest, size_t destsize)
Replaces the first occurence of the given pattern in the source string with the given replace string...
Definition: shared.cpp:596
size_t size
Definition: scripts.h:172
Definition: scripts.h:52
bool WEB_CGameDelete(const char *cgameId, int category, const char *filename)
Deletes a user owned file on the server.
Definition: web_cgame.cpp:152
#define lengthof(x)
Definition: shared.h:105
void WEB_CGameCvars(void)
Definition: web_cgame.cpp:403
#define Q_streq(a, b)
Definition: shared.h:136
UFOAI web interface management. c(lient)game related stuff.
#define URL_SIZE
Definition: web_cgame.cpp:37
const char * GAME_GetRelativeSavePath(char *buf, size_t bufSize)
Definition: cl_game.cpp:1602
level_locals_t level
Definition: g_main.cpp:38
bool WEB_CGameDownloadFromUser(const char *cgameId, int category, const char *filename, int userId)
Downloads a file from the server and store it in the user directory.
Definition: web_cgame.cpp:187
void UI_ExecuteConfunc(const char *fmt,...)
Executes confunc - just to identify those confuncs in the code - in this frame.
Definition: ui_main.cpp:110
bool WEB_GetURL(const char *url, http_callback_t callback, void *userdata)
Downloads the given url and notify the callback. The login credentials are automatically added as GET...
Definition: web_main.cpp:44