Files
SRB2Kart-Saturn/src/d_protocol.c
T
2024-04-04 03:53:00 +02:00

280 lines
7.4 KiB
C

// SONIC ROBO BLAST 2 KART
//-----------------------------------------------------------------------------
// Copyright (C) 2021 by "Fafabis".
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file d_protocol.c
/// \brief srb2kart:// protocol stuff
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#if defined (__unix__) || defined (UNIXCOMMON)
#include <sys/types.h>
#include <pwd.h>
#elif defined (__WIN32)
#include <tchar.h>
#endif
#ifdef HAVE_CURL
#include <curl/curl.h>
#endif
#include "doomdef.h"
#include "m_argv.h"
#include "d_main.h"
#include "d_clisrv.h"
#include "d_netfil.h"
#include "d_protocol.h"
#include "i_system.h"
// PROTOS
#if defined (__WIN32)
static HKEY OpenKey(HKEY hRootKey, const char* strKey);
static boolean SetStringValue(HKEY hRegistryKey, const char *valueName, const char *data);
#endif
static char *GetExePath(void)
{
static char buf[PATH_MAX];
#if defined (__linux__)
if (readlink("/proc/self/exe", buf, PATH_MAX) < 0)
I_Error("PROTOCOL: Error reading /proc/");
#elif defined (__FreeBSD__)
if (readlink("/proc/curproc/file", buf, PATH_MAX) < 0)
I_Error("PROTOCOL: Error reading /proc/");
#elif defined (__WIN32)
GetModuleFileName(NULL, buf, PATH_MAX);
#endif
return buf;
}
static boolean RegisterProtocols(const char *path)
{
#if defined (__WIN32)
HKEY hKey = OpenKey(HKEY_CURRENT_USER,"Software\\Classes\\srb2kart");
SetStringValue(hKey, "URL Protocol", "");
RegCloseKey(hKey);
hKey = OpenKey(HKEY_CURRENT_USER,"Software\\Classes\\srb2kart\\shell\\open\\command");
SetStringValue(hKey, "", va("\"%s\" \"%%1\"", path));
RegCloseKey(hKey);
#elif defined (__unix__) || defined (UNIXCOMMON)
FILE *desktopfile = NULL;
FILE *mimefile = NULL;
struct passwd *pw = getpwuid(getuid());
const char *homedir = pw->pw_dir;
char buffer[255];
boolean alreadyexists = false;
boolean newfolder = false;
struct stat sb;
char *applicationsfolder = va("%s/.local/share/applications/", homedir);
if (system("which update-desktop-database > /dev/null 2>&1"))
{
// command not found, probably doesn't have freedesktop, so let's ignore
CONS_Alert(CONS_ERROR, "Unable to register protocols. Your system doesn't seem to have freedesktop.\n");
return false;
}
if (stat(applicationsfolder, &sb) == -1)
{
// location doesn't exist, so let's actually create it
newfolder = true;
I_mkdir(applicationsfolder, 0755);
}
desktopfile = fopen(va("%s/.local/share/applications/srb2kart-handler.desktop", homedir), "w");
if (!desktopfile)
I_Error("Unable to register protocols. Error creating .desktop file.");
fprintf(desktopfile,
"[Desktop Entry]\n"
"Type=Application\n"
"Name=SRB2Kart Scheme Handler\n"
"Exec=bash -c '%s %%u'\n"
"NoDisplay=true\n"
"StartupNotify=false\n"
"MimeType=x-scheme-handler/srb2kart;\n",
path);
fclose(desktopfile);
mimefile = fopen(va("%s/.local/share/applications/mimeinfo.cache", homedir), "a+");
if (!mimefile)
I_Error("Unable to register protocols. Error opening mime file.");
while (fgets(buffer, 255, mimefile))
{
if (strncmp(buffer, "x-scheme-handler/srb2kart=srb2kart-handler.desktop;", 43)==0)
{
alreadyexists = true;
break;
}
}
if (!alreadyexists)
fprintf(mimefile, "x-scheme-handler/srb2kart=srb2kart-handler.desktop;\n");
if (newfolder)
{
if (system(va("update-desktop-database %s/.local/share/applications/", homedir)) == -1)
{
CONS_Alert(CONS_ERROR, "Unable to register protocols. Could not run call to run update-desktop-database sucessfully.\n");
return false;
}
}
#endif
return true;
}
static void DeleteProtocols(void)
{
#if defined (__WIN32)
HKEY hKey;
RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\Classes\\srb2kart\\shell\\open\\command"), 0, KEY_ALL_ACCESS, &hKey);
RegDeleteValue(hKey, _T(""));
RegCloseKey(hKey);
RegDeleteKey(HKEY_CURRENT_USER, _T("Software\\Classes\\srb2kart\\shell\\open\\command"));
RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\Classes\\srb2kart\\shell\\open"), 0, KEY_ALL_ACCESS, &hKey);
RegDeleteValue(hKey, _T(""));
RegCloseKey(hKey);
RegDeleteKey(HKEY_CURRENT_USER, _T("Software\\Classes\\srb2kart\\shell\\open"));
RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\Classes\\srb2kart\\shell"), 0, KEY_ALL_ACCESS, &hKey);
RegDeleteValue(hKey, _T(""));
RegCloseKey(hKey);
RegDeleteKey(HKEY_CURRENT_USER, _T("Software\\Classes\\srb2kart\\shell"));
RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\Classes\\srb2kart"), 0, KEY_ALL_ACCESS, &hKey);
RegDeleteValue(hKey, _T("URL Protocol"));
RegDeleteValue(hKey, _T(""));
RegCloseKey(hKey);
RegDeleteKey(HKEY_CURRENT_USER, _T("Software\\Classes\\srb2kart"));
#elif defined (__unix__) || defined (UNIXCOMMON)
struct passwd *pw = getpwuid(getuid());
const char *homedir = pw->pw_dir;
remove(va("%s/.local/share/applications/srb2kart-handler.desktop", homedir));
#endif
}
#if defined (__WIN32)
static HKEY OpenKey(HKEY hRootKey, const char* strKey)
{
HKEY hKey;
LONG nError = RegOpenKeyEx(hRootKey, strKey, 0, KEY_ALL_ACCESS, &hKey);
if (nError==ERROR_FILE_NOT_FOUND)
{
CONS_Printf("PROTOCOL: Creating registry key: %s\n", strKey);
nError = RegCreateKeyEx(hRootKey, strKey, 0, NULL, REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL, &hKey, NULL);
}
if (nError)
I_Error("Unable to register protocols. Could not create Registry Key.");
return hKey;
}
static boolean SetStringValue(HKEY hRegistryKey, const char *valueName, const char *data)
{
I_Assert(hRegistryKey != NULL);
return (RegSetValueExA(hRegistryKey,
valueName,
0,
REG_SZ,
(const BYTE *)data,
strlen(data) + 1) == ERROR_SUCCESS);
}
#endif
void D_SetupProtocol(void)
{
FILE *fp = NULL;
char *result = NULL;
char buffer[PATH_MAX];
const char *exe_path = GetExePath();
const char *protocolfile = va("%s/protocol.txt", srb2home);
if (dedicated)
return;
fp = fopen(protocolfile, "a+");
result = fgets(buffer, PATH_MAX, fp);
if (result)
{
if (strcmp(buffer, "no") == 0)
{
fclose(fp);
return;
}
else if (strcmp(buffer, exe_path) != 0)
{
// overwrite
fclose(fp);
fp = fopen(protocolfile, "w");
RegisterProtocols(exe_path);
fprintf(fp, "%s", exe_path);
fclose(fp);
return;
}
}
else // probably first time
{
if (RegisterProtocols(exe_path))
fprintf(fp, "%s", exe_path);
else
fprintf(fp, "no");
}
fclose(fp);
}
void D_DeleteProtocol(void)
{
FILE *fp = NULL;
DeleteProtocols();
fp = fopen(va("%s/protocol.txt", srb2home), "w");
fprintf(fp, "no");
fclose(fp);
}
void D_CreateProtocol(void)
{
FILE *fp = NULL;
const char *exe_path = GetExePath();
fp = fopen(va("%s/protocol.txt", srb2home), "w");
RegisterProtocols(exe_path);
fprintf(fp, "%s", exe_path);
fclose(fp);
}
#ifdef HAVE_CURL
void D_DownloadReplay(const char *url, const char *path)
{
FILE *fp = NULL;
CURL *curl;
CURLcode cc;
curl = curl_easy_init();
if (!curl)
I_Error("Unable to download replay. Error initializing CURL.");
fp = fopen(path, "wb");
CONS_Printf("REPLAY: URL: %s\n", url);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlwrite_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
cc = curl_easy_perform(curl);
if (cc != CURLE_OK)
I_Error("Unable to download replay. URL gave response code %u.", cc);
curl_easy_cleanup(curl);
fclose(fp);
}
#endif