aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan200101 <sentrycraft123@gmail.com>2021-04-22 20:23:58 +0200
committerJan200101 <sentrycraft123@gmail.com>2021-04-22 20:23:58 +0200
commit6867c3f51eb7702a1379a66f12627b35924edbed (patch)
treebd1800625704c65a313efe7dfa8f142c7f346a05
parent63e5e87d71e42f6f252b97468d2e4e7f3b95277a (diff)
downloadpolecat-6867c3f51eb7702a1379a66f12627b35924edbed.tar.gz
polecat-6867c3f51eb7702a1379a66f12627b35924edbed.zip
add list & search command, fix bug in installer parser, […]
- add list and search command to find what is on lutris without using lutris or the website - correct info command from not erroring when no slug was found - allow upper and lower Y on installer - remove pointless getInstaller function - fix bug in installer where if a value is not given its NULL and we cannot stringify NULL - replace manual malloc, strcpy with strdup - remove lutris_debug definition
-rw-r--r--src/common.h12
-rw-r--r--src/lutris.c173
-rw-r--r--src/lutris.h6
3 files changed, 172 insertions, 19 deletions
diff --git a/src/common.h b/src/common.h
index b206f7b..9680e8d 100644
--- a/src/common.h
+++ b/src/common.h
@@ -8,9 +8,15 @@
#define ARRAY_LEN(arr) sizeof(arr) / sizeof(arr[0])
-#define WINE_API "https://lutris.net/api/runners/wine"
-#define DXVK_API "https://api.github.com/repos/lutris/dxvk/releases"
-#define INSTALLER_API "https://lutris.net/api/installers/"
+#define GITHUB_API "https://api.github.com"
+#define LUTRIS_API "https://lutris.net/api"
+#define WINE_API LUTRIS_API "/runners/wine"
+#define DXVK_API GITHUB_API"/repos/lutris/dxvk/releases"
+#define INSTALLER_API LUTRIS_API "/installers/"
+#define GAME_API LUTRIS_API "/games"
+#define GAME_SEARCH_API GAME_API "?search=%s"
+#define GAME_INSTALLER_API GAME_API "/%s/installers"
+
#ifndef NAME
#warning "no name specified, setting it to \"polecat\""
diff --git a/src/lutris.c b/src/lutris.c
index 7527f25..bd2a2d4 100644
--- a/src/lutris.c
+++ b/src/lutris.c
@@ -5,14 +5,13 @@
#include <unistd.h>
#include <linux/limits.h>
#include <libgen.h>
-
#include "lutris.h"
#include "net.h"
static const struct Command lutris_commands[] = {
-#ifdef DEBUG
+ { .name = "search", .func = lutris_search, .description = "search for lutris installers" },
+ { .name = "list", .func = lutris_list, .description = "list installers for a game"},
{ .name = "install", .func = lutris_install, .description = "install a lutris script" },
-#endif
{ .name = "info", .func = lutris_info, .description = "show information about a lutris script" },
};
@@ -26,6 +25,106 @@ char* getpwd()
COMMAND_GROUP_FUNC(lutris)
+COMMAND(lutris, search)
+{
+ if (argc == 2 && argv[1][0] != '\0')
+ {
+ // argv being modifyable is not always a given so lets
+ // lets make a mutable copy
+ char* str = strdup(argv[1]);
+ // in the case we need to do replacing we allocate more
+ // since we'll free in anyway
+ size_t allocsize = strlen(str) * 2;
+ str = realloc(str, allocsize);
+ lutris_escapeString(str, allocsize);
+ char* url = malloc(strlen(GAME_SEARCH_API) + strlen(str));
+ sprintf(url, GAME_SEARCH_API, str);
+
+ struct json_object* queryresult = fetchJSON(url);
+ free(str);
+ free(url);
+
+ if (queryresult)
+ {
+ struct json_object* searchresults;
+ json_object_object_get_ex(queryresult, "results", &searchresults);
+ if (searchresults)
+ {
+ struct json_object* values[2];
+ size_t arrlen = json_object_array_length(searchresults);
+
+ for (size_t i = 0; i < arrlen; ++i)
+ {
+ struct json_object* entry = json_object_array_get_idx(searchresults, i);
+ json_object_object_get_ex(entry, "name", &values[0]);
+ json_object_object_get_ex(entry, "slug", &values[1]);
+
+ printf("%s - %s\n", json_object_get_string(values[0]), json_object_get_string(values[1]));
+ }
+ }
+
+ json_object_put(queryresult);
+ }
+ }
+ else
+ {
+ puts(USAGE_STR " lutris search <text>\nSearch for games and list their slug");
+ }
+
+ return 0;
+}
+
+COMMAND(lutris, list)
+{
+ if (argc == 2)
+ {
+ // argv being modifyable is not always a given so lets
+ // lets make a mutable copy
+ char* str = strdup(argv[1]);
+ // in the case we need to do replacing we allocate more
+ // since we'll free in anyway
+ size_t allocsize = strlen(str) * 2;
+ str = realloc(str, allocsize);
+ lutris_escapeString(str, allocsize);
+ char* url = malloc(strlen(GAME_INSTALLER_API) + strlen(str));
+ sprintf(url, GAME_INSTALLER_API, str);
+
+ struct json_object* queryresult = fetchJSON(url);
+ free(str);
+ free(url);
+
+ if (queryresult)
+ {
+ struct json_object* installers;
+ json_object_object_get_ex(queryresult, "installers", &installers);
+ if (installers)
+ {
+ struct json_object* values[4];
+ size_t arrlen = json_object_array_length(installers);
+
+ for (size_t i = 0; i < arrlen; ++i)
+ {
+ struct json_object* entry = json_object_array_get_idx(installers, i);
+ json_object_object_get_ex(entry, "slug", &values[0]);
+ json_object_object_get_ex(entry, "runner", &values[1]);
+ json_object_object_get_ex(entry, "name", &values[2]);
+ json_object_object_get_ex(entry, "version", &values[3]);
+
+ printf("%s - (%s) %s %s\n", json_object_get_string(values[0]), json_object_get_string(values[1]), json_object_get_string(values[2]), json_object_get_string(values[3]));
+ }
+ }
+
+ json_object_put(queryresult);
+ }
+ }
+ else
+ {
+ puts(USAGE_STR " lutris list <slug>\nList game installers");
+ }
+
+ return 0;
+}
+
COMMAND(lutris, install)
{
if (argc == 2)
@@ -34,9 +133,10 @@ COMMAND(lutris, install)
if (installer.error == NONE)
{
- printf("Install %s - %s to the current directory? (y/n)\n", installer.name, installer.version);
+ printf("Install %s - %s to the current directory?\n\nNOTE:\tpolecat will use the wine that is on your path\n\t\tit is suggested to install the right wine version\n\t\tand use `wine env` to put it on the path\n\n(y/N)\n", installer.name, installer.version);
- if (getchar() == 'y')
+ int inp = getchar();
+ if (inp == 'y' || inp == 'Y')
{
// fetch all files required by installer
for (size_t i = 0; i < installer.filecount; ++i)
@@ -183,7 +283,8 @@ COMMAND(lutris, info)
if (argc == 2)
{
struct script_t installer = lutris_getInstaller(argv[1]);
- if (installer.error > NO_JSON || installer.error == NONE)
+
+ if (installer.error > NO_SLUG || installer.error == NONE)
{
printf("[%s]", runnerStr[installer.runner]);
@@ -262,10 +363,54 @@ COMMAND(lutris, info)
COMMAND_HELP(lutris, " lutris")
-void lutris_getInstallerURL(char* buffer, char* name, size_t size)
+void lutris_escapeString(char* str, size_t size)
{
- strncpy(buffer, INSTALLER_API, size);
- strncat(buffer, name, size - strlen(buffer));
+ char* tail = str + size;
+
+ while (str != tail)
+ {
+ switch (*str)
+ {
+ // from rfc3986 https://tools.ietf.org/html/rfc3986#page-13
+ // we generally don't want delimiters
+ // so we strip them if found
+ case ':':
+ case '/':
+ case '?':
+ case '#':
+ case '[':
+ case ']':
+ case '@':
+ case '!':
+ case '$':
+ case '&':
+ case '\'':
+ case '(':
+ case ')':
+ case '*':
+ case '+':
+ case ',':
+ case ';':
+ case '=':
+ // since dest and src overlap we need a non overlapping solution
+ memmove(str, str+1, (size_t)(tail-str-1));
+ break;
+
+ case ' ':
+ // spaces are special and need to be encoded
+ memmove(str+3, str+1, (size_t)(tail-str-3));
+ str[0] = '%';
+ str[1] = '2';
+ str[2] = '0';
+ str += 3;
+ if (str >= tail) str[3] = '\0';
+ break;
+
+ /* fallthrough */
+ default:
+ ++str;
+ }
+ }
}
struct script_t lutris_getInstaller(char* installername)
@@ -288,7 +433,8 @@ struct script_t lutris_getInstaller(char* installername)
if (installername)
{
char installerurl[PATH_MAX];
- lutris_getInstallerURL(installerurl, installername, sizeof(installerurl));
+ strncpy(installerurl, INSTALLER_API, sizeof(installerurl));
+ strncat(installerurl, installername, sizeof(installerurl) - strlen(installerurl) - 1);
struct json_object* installerjson = fetchJSON(installerurl);
@@ -542,6 +688,9 @@ struct script_t lutris_getInstaller(char* installername)
for (size_t j = 0; j < installer.directives[i]->size; ++j)
{
str = json_object_get_string(options[j+offset]);
+ // there will always be some attributes ommited
+ // from an installer, just replace those with an empty string
+ if (!str) str = "";
installer.directives[i]->arguments[j] = malloc(strlen(str) * sizeof(char) +1);
strcpy(installer.directives[i]->arguments[j], str);
}
@@ -640,7 +789,6 @@ size_t parseVar(char** pvar, struct list_t** variables, size_t variable_count)
tail = ++head;
while (*tail <= 'z' && *tail >= 'A') // we ONLY accept ascii variables
{
-
++tail;
}
@@ -661,8 +809,7 @@ size_t parseVar(char** pvar, struct list_t** variables, size_t variable_count)
switch (variables[i]->type)
{
case value_string:
- value = malloc(strlen(variables[i]->value.str) + 1);
- strncpy(value, variables[i]->value.str, strlen(variables[i]->value.str) + 1);
+ value = strdup(variables[i]->value.str);
break;
case value_function:
diff --git a/src/lutris.h b/src/lutris.h
index cc92370..abd56f7 100644
--- a/src/lutris.h
+++ b/src/lutris.h
@@ -139,14 +139,14 @@ struct script_t {
#include "command.h"
-COMMAND(lutris, debug);
-
COMMAND_GROUP(lutris);
+COMMAND(lutris, search);
+COMMAND(lutris, list);
COMMAND(lutris, install);
COMMAND(lutris, info);
COMMAND(lutris, help);
-void lutris_getInstallerURL(char*, char*, size_t);
+void lutris_escapeString(char*, size_t);
struct script_t lutris_getInstaller(char*);
void lutris_freeInstaller(struct script_t*);