Files
DorkNet/DorkNet.Quest/src/config.cpp
T
Alexa 975753deac feat: DorkNet.Quest, a sideload patcher for the 2023 Quest client
Patches the Quest build of Rec Room 2023.03.21 (20230317 / 2128210, the
same appVersion as the PC client) to connect to a DorkNet server, using
one native hook library loaded via DT_NEEDED on libmain.so.

- host rewrite onto <svc>.<ServerHost> or a {service}-dev.example.com template
- Photon app ids and region injection (PhotonRegion must match PC)
- TLS / pinning / image-signature bypass, integrity callbacks neutralised
- no-Meta-account build; the server treats platform id 0/1/blank as a
  placeholder and keys those accounts by device id
- build.ps1 -Obb packages a DorkNet-<ver>.xapk with one-command
  installers for Windows and macOS/Linux; app is named via AppName
- README, docs/quest.md and NOTICE updated; credits RecFlare and
  And64InlineHook (MIT)

Tested on a Quest 2: all hooks arm, requests reach the dev server.
2026-10-15 20:29:32 +03:00

82 lines
4.0 KiB
C++

// Runtime config loader: applies an optional on-device cfg over the baked-in
// defaults. The cfg format is "Key = Value", one per line, '#' comments and
// [section] headers ignored -- the same keys DorkNet.ClientMod uses on PC, so a
// PC config reads here too.
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
extern "C" int __android_log_print(int prio, const char *tag, const char *fmt, ...);
#define CLOGI(...) __android_log_print(4, "DORKNET", __VA_ARGS__)
static void trim(char *s) {
char *p = s;
while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') p++;
if (p != s) memmove(s, p, strlen(p) + 1);
size_t n = strlen(s);
while (n && (s[n - 1] == ' ' || s[n - 1] == '\t' || s[n - 1] == '\r' || s[n - 1] == '\n'))
s[--n] = '\0';
}
static bool as_bool(const char *v, bool dflt) {
if (!v || !*v) return dflt;
if (!strcasecmp(v, "true") || !strcasecmp(v, "1") || !strcasecmp(v, "yes") || !strcasecmp(v, "on"))
return true;
if (!strcasecmp(v, "false") || !strcasecmp(v, "0") || !strcasecmp(v, "no") || !strcasecmp(v, "off"))
return false;
return dflt;
}
// Accept a bare host or a full URL; store just the host.
static void set_host(char *out, size_t cap, const char *val) {
const char *scheme = strstr(val, "://");
const char *host = scheme ? scheme + 3 : val;
size_t i = 0;
for (; host[i] && host[i] != '/' && i + 1 < cap; i++) out[i] = host[i];
out[i] = '\0';
}
void dn_load_runtime_config(char *server_host, size_t server_host_cap,
char *oculus_appid, size_t oculus_appid_cap,
char *photon_realtime, char *photon_voice, char *photon_chat,
char *photon_server, size_t photon_server_cap, int *photon_port,
char *photon_region, size_t photon_region_cap,
bool *tls_bypass, bool *accept_images,
bool *log_http, bool *debug_http, int *body_max) {
char path[256];
snprintf(path, sizeof(path), "/sdcard/Android/data/%s/files/%s", DN_PACKAGE, DN_RUNTIME_CFG_NAME);
FILE *f = fopen(path, "r");
if (!f) { CLOGI("no runtime config at %s; using baked-in defaults", path); return; }
char line[256];
while (fgets(line, sizeof(line), f)) {
char *hash = strchr(line, '#');
if (hash) *hash = '\0';
char *eq = strchr(line, '=');
if (!eq) continue;
*eq = '\0';
char *key = line, *val = eq + 1;
trim(key);
trim(val);
if (!strcasecmp(key, "ServerHost") && *val) set_host(server_host, server_host_cap, val);
else if (!strcasecmp(key, "OculusAppId")) {
oculus_appid[0] = '\0';
strncpy(oculus_appid, val, oculus_appid_cap - 1);
}
else if (!strcasecmp(key, "PhotonAppId") && *val) strncpy(photon_realtime, val, 63);
else if (!strcasecmp(key, "PhotonVoiceAppId") && *val) strncpy(photon_voice, val, 63);
else if (!strcasecmp(key, "PhotonChatAppId") && *val) strncpy(photon_chat, val, 63);
else if (!strcasecmp(key, "PhotonNameServer")) set_host(photon_server, photon_server_cap, val);
else if (!strcasecmp(key, "PhotonNameServerPort")) *photon_port = atoi(val);
else if (!strcasecmp(key, "PhotonRegion") && *val) { photon_region[0] = ''; strncpy(photon_region, val, photon_region_cap - 1); }
else if (!strcasecmp(key, "EnableTlsTrustBypass")) *tls_bypass = as_bool(val, *tls_bypass);
else if (!strcasecmp(key, "AcceptUnsignedImages")) *accept_images = as_bool(val, *accept_images);
else if (!strcasecmp(key, "LogHttp")) *log_http = as_bool(val, *log_http);
else if (!strcasecmp(key, "Debug")) *debug_http = as_bool(val, *debug_http);
else if (!strcasecmp(key, "LogHttpBodyMax") && *val) *body_max = atoi(val);
}
fclose(f);
CLOGI("runtime config applied from %s", path);
}