mirror of
https://github.com/Adamcake/Bolt.git
synced 2026-04-18 00:06:52 -04:00
Revert "Merge branch 'Adamcake:master' into refactor/front-end"
This reverts commit093e5aca0e, reversing changes made to4f12d36e7a. Temporary fix to auth window not being able to authenticate
This commit is contained in:
File diff suppressed because one or more lines are too long
2
app/dist/index.html
vendored
2
app/dist/index.html
vendored
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Bolt Launcher</title>
|
||||
<script type="module" crossorigin src="/assets/index-CfEoSnmR.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-dPPSjzHg.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-B5crSLm9.css">
|
||||
</head>
|
||||
<body
|
||||
|
||||
@@ -309,7 +309,7 @@ export async function launchOfficialClient(
|
||||
? bolt.osrsAppInstalledHash
|
||||
: bolt.rs3AppInstalledHash;
|
||||
|
||||
const launch = async (hash?: string, exe?: Promise<ArrayBuffer>) => {
|
||||
const launch = async (hash?: string, exe?: Blob) => {
|
||||
const params: Record<string, string> = {};
|
||||
if (hash) params.hash = hash;
|
||||
if (jx_session_id) params.jx_session_id = jx_session_id;
|
||||
@@ -320,7 +320,7 @@ export async function launchOfficialClient(
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/octet-stream' },
|
||||
body: await exe
|
||||
body: exe
|
||||
}
|
||||
);
|
||||
response.text().then((text) => logger.info(`Game launch status: '${text.trim()}'`));
|
||||
@@ -416,6 +416,6 @@ export async function launchOfficialClient(
|
||||
// stitch all the data together, slice the exe out of it, and launch the game
|
||||
Promise.all(chunk_promises).then((x) => {
|
||||
const exeFile = new Blob(x).slice(exeOffset, exeOffset + <number>exeSize);
|
||||
launch(metafile.id, exeFile.arrayBuffer());
|
||||
launch(metafile.id, exeFile);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,21 +1,4 @@
|
||||
#include "resource_handler.hxx"
|
||||
#include "include/cef_urlrequest.h"
|
||||
#include "include/internal/cef_types.h"
|
||||
|
||||
// returns content-length or -1 if it's malformed or nonexistent
|
||||
// CEF interprets -1 as "unknown length"
|
||||
static int64_t GetContentLength(CefRefPtr<CefResponse> response) {
|
||||
std::string content_length = response->GetHeaderByName("Content-Length").ToString();
|
||||
if (content_length.size() == 0) {
|
||||
return -1;
|
||||
}
|
||||
int64_t length = 0;
|
||||
for (auto it = content_length.begin(); it != content_length.end(); it++) {
|
||||
if (*it < '0' || *it > '9') return -1;
|
||||
length = (length * 10) + ((int64_t)(*it) - '0');
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
bool Browser::ResourceHandler::Open(CefRefPtr<CefRequest>, bool& handle_request, CefRefPtr<CefCallback>) {
|
||||
handle_request = true;
|
||||
@@ -82,103 +65,3 @@ void Browser::ResourceHandler::finish() {
|
||||
this->file_manager = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Browser::DefaultURLHandler::DefaultURLHandler(CefRefPtr<CefRequest> request): urlrequest_complete(false), headers_checked(false), urlrequest_callback(nullptr), cursor(0) {
|
||||
this->url_request = CefURLRequest::Create(request, this, nullptr);
|
||||
}
|
||||
|
||||
CefResourceRequestHandler::ReturnValue Browser::DefaultURLHandler::OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, CefRefPtr<CefCallback> callback) {
|
||||
// use CefResourceRequestHandler::OnBeforeResourceLoad to stall asynchronously on the IO thread
|
||||
// until the request completes, if it hasn't already
|
||||
if (urlrequest_complete) {
|
||||
return RV_CONTINUE;
|
||||
} else {
|
||||
this->urlrequest_callback = callback;
|
||||
return RV_CONTINUE_ASYNC;
|
||||
}
|
||||
}
|
||||
|
||||
CefRefPtr<CefResourceHandler> Browser::DefaultURLHandler::GetResourceHandler(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request) {
|
||||
return this;
|
||||
}
|
||||
|
||||
bool Browser::DefaultURLHandler::Open(CefRefPtr<CefRequest> request, bool& handle_request, CefRefPtr<CefCallback> callback) {
|
||||
handle_request = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Browser::DefaultURLHandler::GetResponseHeaders(CefRefPtr<CefResponse> response, int64_t& response_length, CefString& redirectUrl) {
|
||||
CefRefPtr<CefResponse> url_response = this->url_request->GetResponse();
|
||||
CefResponse::HeaderMap headers;
|
||||
url_response->GetHeaderMap(headers);
|
||||
response->SetHeaderMap(headers);
|
||||
response->SetStatus(url_response->GetStatus());
|
||||
response->SetStatusText(url_response->GetStatusText());
|
||||
response->SetMimeType(url_response->GetMimeType());
|
||||
response->SetCharset(url_response->GetCharset());
|
||||
response->SetHeaderByName("Access-Control-Allow-Origin", "*", true);
|
||||
response_length = GetContentLength(url_response);
|
||||
}
|
||||
|
||||
bool Browser::DefaultURLHandler::Read(void* data_out, int bytes_to_read, int& bytes_read, CefRefPtr<CefResourceReadCallback> callback) {
|
||||
if (this->cursor == this->data.size()) {
|
||||
// "To indicate response completion set |bytes_read| to 0 and return false."
|
||||
bytes_read = 0;
|
||||
return false;
|
||||
}
|
||||
if (this->cursor + bytes_to_read <= this->data.size()) {
|
||||
// requested read is entirely in bounds
|
||||
bytes_read = bytes_to_read;
|
||||
memcpy(data_out, &this->data[this->cursor], bytes_read);
|
||||
this->cursor += bytes_to_read;
|
||||
} else {
|
||||
// read only to end of string
|
||||
bytes_read = this->data.size() - this->cursor;
|
||||
memcpy(data_out, &this->data[this->cursor], bytes_read);
|
||||
this->cursor = this->data.size();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Browser::DefaultURLHandler::Skip(int64_t bytes_to_skip, int64_t& bytes_skipped, CefRefPtr<CefResourceSkipCallback> callback) {
|
||||
if (this->cursor + bytes_to_skip <= this->data.size()) {
|
||||
// skip in bounds
|
||||
bytes_skipped = bytes_to_skip;
|
||||
this->cursor += bytes_to_skip;
|
||||
} else {
|
||||
// skip to end of string
|
||||
bytes_skipped = this->data.size() - this->cursor;
|
||||
this->cursor = this->data.size();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Browser::DefaultURLHandler::Cancel() {
|
||||
this->cursor = this->data.size();
|
||||
}
|
||||
|
||||
void Browser::DefaultURLHandler::OnRequestComplete(CefRefPtr<CefURLRequest> request) {
|
||||
this->urlrequest_complete = true;
|
||||
if (this->urlrequest_callback) {
|
||||
this->urlrequest_callback->Continue();
|
||||
}
|
||||
}
|
||||
|
||||
void Browser::DefaultURLHandler::OnUploadProgress(CefRefPtr<CefURLRequest> request, int64_t current, int64_t total) {}
|
||||
void Browser::DefaultURLHandler::OnDownloadProgress(CefRefPtr<CefURLRequest> request, int64_t current, int64_t total) {}
|
||||
|
||||
void Browser::DefaultURLHandler::OnDownloadData(CefRefPtr<CefURLRequest> request, const void* data, size_t data_length) {
|
||||
CefRefPtr<CefResponse> response = request->GetResponse();
|
||||
if (!this->headers_checked && response) {
|
||||
const int64_t content_length = GetContentLength(response);
|
||||
if (content_length != -1) this->data.reserve(content_length);
|
||||
this->headers_checked = true;
|
||||
}
|
||||
size_t write_offset = this->data.size();
|
||||
this->data.resize(write_offset + data_length);
|
||||
memcpy(this->data.data() + write_offset, data, data_length);
|
||||
}
|
||||
|
||||
bool Browser::DefaultURLHandler::GetAuthCredentials(bool isProxy, const CefString& host, int port, const CefString& realm, const CefString& scheme, CefRefPtr<CefAuthCallback> callback) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
#include "include/cef_base.h"
|
||||
#include "include/cef_resource_request_handler.h"
|
||||
#include "include/cef_urlrequest.h"
|
||||
#include <string>
|
||||
|
||||
namespace Browser {
|
||||
@@ -56,38 +55,5 @@ namespace Browser {
|
||||
DISALLOW_COPY_AND_ASSIGN(ResourceHandler);
|
||||
};
|
||||
|
||||
/// Struct for bridging a CefURLRequestClient to a CefResourceHandler
|
||||
/// https://github.com/chromiumembedded/cef/blob/5735/include/cef_resource_request_handler.h
|
||||
/// https://github.com/chromiumembedded/cef/blob/5735/include/cef_resource_handler.h
|
||||
/// https://github.com/chromiumembedded/cef/blob/5735/include/cef_urlrequest.h#L137
|
||||
struct DefaultURLHandler: public CefResourceRequestHandler, CefResourceHandler, CefURLRequestClient {
|
||||
DefaultURLHandler(CefRefPtr<CefRequest>);
|
||||
|
||||
CefResourceRequestHandler::ReturnValue OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, CefRefPtr<CefCallback> callback) override;
|
||||
CefRefPtr<CefResourceHandler> GetResourceHandler(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request) override;
|
||||
|
||||
bool Open(CefRefPtr<CefRequest> request, bool& handle_request, CefRefPtr<CefCallback> callback) override;
|
||||
void GetResponseHeaders(CefRefPtr<CefResponse> response, int64_t& response_length, CefString& redirectUrl) override;
|
||||
bool Read(void* data_out, int bytes_to_read, int& bytes_read, CefRefPtr<CefResourceReadCallback> callback) override;
|
||||
bool Skip(int64_t bytes_to_skip, int64_t& bytes_skipped, CefRefPtr<CefResourceSkipCallback> callback) override;
|
||||
void Cancel() override;
|
||||
|
||||
void OnRequestComplete(CefRefPtr<CefURLRequest> request) override;
|
||||
void OnUploadProgress(CefRefPtr<CefURLRequest> request, int64_t current, int64_t total) override;
|
||||
void OnDownloadProgress(CefRefPtr<CefURLRequest> request, int64_t current, int64_t total) override;
|
||||
void OnDownloadData(CefRefPtr<CefURLRequest> request, const void* data, size_t data_length) override;
|
||||
bool GetAuthCredentials(bool isProxy, const CefString& host, int port, const CefString& realm, const CefString& scheme, CefRefPtr<CefAuthCallback> callback) override;
|
||||
|
||||
private:
|
||||
CefRefPtr<CefURLRequest> url_request;
|
||||
CefRefPtr<CefCallback> urlrequest_callback;
|
||||
bool urlrequest_complete;
|
||||
bool headers_checked;
|
||||
std::vector<uint8_t> data;
|
||||
size_t cursor;
|
||||
IMPLEMENT_REFCOUNTING(DefaultURLHandler);
|
||||
DISALLOW_COPY_AND_ASSIGN(DefaultURLHandler);
|
||||
};
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -454,18 +454,7 @@ CefRefPtr<CefResourceRequestHandler> Browser::Launcher::GetResourceRequestHandle
|
||||
}
|
||||
}
|
||||
|
||||
if (!browser->IsSame(this->browser) || !frame->IsMain()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// default way to handle web requests from the main window is to make a CefURLRequest that's not subject to CORS safety
|
||||
disable_default_handling = true;
|
||||
CefRefPtr<CefRequest> new_request = CefRequest::Create();
|
||||
CefRequest::HeaderMap headers;
|
||||
request->GetHeaderMap(headers); // doesn't include Referer header
|
||||
headers.erase("Origin");
|
||||
new_request->Set(request->GetURL(), request->GetMethod(), request->GetPostData(), headers);
|
||||
return new DefaultURLHandler(new_request);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Browser::Launcher::OnBrowserDestroyed(CefRefPtr<CefBrowserView> view, CefRefPtr<CefBrowser> browser) {
|
||||
@@ -555,26 +544,6 @@ void Browser::Launcher::Refresh() const {
|
||||
this->browser->GetMainFrame()->LoadURL(this->BuildURL());
|
||||
}
|
||||
|
||||
void Browser::Launcher::ParseQuery(std::string_view query, std::function<void(const std::string_view&, const std::string_view&)> callback) {
|
||||
size_t pos = 0;
|
||||
while (true) {
|
||||
const size_t next_and = query.find('&', pos);
|
||||
const size_t next_eq = query.find('=', pos);
|
||||
if (next_eq == std::string_view::npos) break;
|
||||
else if (next_and != std::string_view::npos && next_eq > next_and) {
|
||||
pos = next_and + 1;
|
||||
continue;
|
||||
}
|
||||
const bool is_last = next_and == std::string_view::npos;
|
||||
const auto end = is_last ? query.end() : query.begin() + next_and;
|
||||
const std::string_view key(query.begin() + pos, query.begin() + next_eq);
|
||||
const std::string_view val(query.begin() + next_eq + 1, end);
|
||||
callback(key, val);
|
||||
if (is_last) break;
|
||||
pos = next_and + 1;
|
||||
}
|
||||
}
|
||||
|
||||
CefRefPtr<CefResourceRequestHandler> SaveFileFromPost(CefRefPtr<CefRequest> request, const std::filesystem::path::value_type* path) {
|
||||
CefRefPtr<CefPostData> post_data = request->GetPostData();
|
||||
if (post_data->GetElementCount() != 1) {
|
||||
|
||||
@@ -4,10 +4,7 @@
|
||||
#include "../browser.hxx"
|
||||
#include "../file_manager.hxx"
|
||||
|
||||
#include "include/cef_parser.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
|
||||
namespace Browser {
|
||||
struct Launcher: public Window {
|
||||
@@ -40,9 +37,6 @@ namespace Browser {
|
||||
/// inserting their contents into the query params
|
||||
CefString BuildURL() const;
|
||||
|
||||
/// Goes through all the key-value pairs in the given query string and calls the callback for each one.
|
||||
void ParseQuery(std::string_view query, std::function<void(const std::string_view&, const std::string_view&)> callback);
|
||||
|
||||
/*
|
||||
Functions called by GetResourceRequestHandler. The result will be returned immediately and must not be null.
|
||||
The request and URL query string are provided for parsing.
|
||||
@@ -82,23 +76,4 @@ namespace Browser {
|
||||
};
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define PQTOSTRING ToWString
|
||||
#else
|
||||
#define PQTOSTRING ToString
|
||||
#endif
|
||||
|
||||
#define PQCHECK(KEY) \
|
||||
if (key == #KEY) { \
|
||||
has_##KEY = true; \
|
||||
KEY = CefURIDecode(std::string(val), true, (cef_uri_unescape_rule_t)(UU_SPACES | UU_PATH_SEPARATORS | UU_URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS | UU_REPLACE_PLUS_WITH_SPACE)).PQTOSTRING(); \
|
||||
return; \
|
||||
}
|
||||
|
||||
#define PQBOOL(KEY) \
|
||||
if (key == #KEY) { \
|
||||
KEY = (val.size() > 0 && val != "0"); \
|
||||
return; \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#include "window_launcher.hxx"
|
||||
#include "resource_handler.hxx"
|
||||
|
||||
#include "include/cef_parser.h"
|
||||
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
#include <fcntl.h>
|
||||
#include <filesystem>
|
||||
#include <fmt/core.h>
|
||||
#include <functional>
|
||||
#include <spawn.h>
|
||||
|
||||
// see #34 for why this function exists and why it can't be run between fork-exec or just run `env`.
|
||||
@@ -38,6 +41,28 @@ bool FindJava(const char* java_home, std::string& out) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void ParseQuery(std::string_view query, std::function<void(const std::string_view&, const std::string_view&)> callback) {
|
||||
size_t pos = 0;
|
||||
while (true) {
|
||||
const size_t next_and = query.find('&', pos);
|
||||
const size_t next_eq = query.find('=', pos);
|
||||
if (next_eq == std::string_view::npos) break;
|
||||
else if (next_and != std::string_view::npos && next_eq > next_and) {
|
||||
pos = next_and + 1;
|
||||
continue;
|
||||
}
|
||||
const bool is_last = next_and == std::string_view::npos;
|
||||
const auto end = is_last ? query.end() : query.begin() + next_and;
|
||||
const std::string_view key(query.begin() + pos, query.begin() + next_eq);
|
||||
const std::string_view val(query.begin() + next_eq + 1, end);
|
||||
callback(key, val);
|
||||
if (is_last) break;
|
||||
pos = next_and + 1;
|
||||
}
|
||||
}
|
||||
const cef_uri_unescape_rule_t pqrule = (cef_uri_unescape_rule_t)(UU_SPACES | UU_PATH_SEPARATORS | UU_URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS | UU_REPLACE_PLUS_WITH_SPACE);
|
||||
#define PQCHECK(KEY) if (key == #KEY) { has_##KEY = true; KEY = CefURIDecode(std::string(val), true, pqrule).ToString(); return; }
|
||||
|
||||
CefRefPtr<CefResourceRequestHandler> Browser::Launcher::LaunchRs3Deb(CefRefPtr<CefRequest> request, std::string_view query) {
|
||||
/* strings that I don't want to be searchable, which also need to be mutable for passing to env functions */
|
||||
// PULSE_PROP_OVERRIDE=
|
||||
@@ -77,14 +102,18 @@ CefRefPtr<CefResourceRequestHandler> Browser::Launcher::LaunchRs3Deb(CefRefPtr<C
|
||||
#if defined(BOLT_PLUGINS)
|
||||
bool plugin_loader = false;
|
||||
#endif
|
||||
this->ParseQuery(query, [&](const std::string_view& key, const std::string_view& val) {
|
||||
ParseQuery(query, [&](const std::string_view& key, const std::string_view& val) {
|
||||
PQCHECK(hash)
|
||||
PQCHECK(config_uri)
|
||||
PQCHECK(jx_session_id)
|
||||
PQCHECK(jx_character_id)
|
||||
PQCHECK(jx_display_name)
|
||||
|
||||
#if defined(BOLT_PLUGINS)
|
||||
PQBOOL(plugin_loader)
|
||||
// no reason to URIDecode this
|
||||
if (key == "plugin_loader" && val == "1") {
|
||||
plugin_loader = true;
|
||||
}
|
||||
#endif
|
||||
});
|
||||
|
||||
@@ -315,7 +344,7 @@ CefRefPtr<CefResourceRequestHandler> Browser::Launcher::LaunchRuneliteJar(CefRef
|
||||
bool has_jx_character_id = false;
|
||||
std::string jx_display_name;
|
||||
bool has_jx_display_name = false;
|
||||
this->ParseQuery(query, [&](const std::string_view& key, const std::string_view& val) {
|
||||
ParseQuery(query, [&](const std::string_view& key, const std::string_view& val) {
|
||||
PQCHECK(rl_path)
|
||||
PQCHECK(id)
|
||||
PQCHECK(jx_session_id)
|
||||
@@ -472,7 +501,7 @@ CefRefPtr<CefResourceRequestHandler> Browser::Launcher::LaunchHdosJar(CefRefPtr<
|
||||
bool has_jx_character_id = false;
|
||||
std::string jx_display_name;
|
||||
bool has_jx_display_name = false;
|
||||
this->ParseQuery(query, [&](const std::string_view& key, const std::string_view& val) {
|
||||
ParseQuery(query, [&](const std::string_view& key, const std::string_view& val) {
|
||||
PQCHECK(version)
|
||||
PQCHECK(jx_session_id)
|
||||
PQCHECK(jx_character_id)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "window_launcher.hxx"
|
||||
#include "resource_handler.hxx"
|
||||
|
||||
#include <iostream>
|
||||
#include <shellapi.h>
|
||||
|
||||
CefRefPtr<CefResourceRequestHandler> Browser::Launcher::LaunchRs3Deb(CefRefPtr<CefRequest> request, std::string_view query) {
|
||||
@@ -10,144 +9,9 @@ CefRefPtr<CefResourceRequestHandler> Browser::Launcher::LaunchRs3Deb(CefRefPtr<C
|
||||
}
|
||||
|
||||
CefRefPtr<CefResourceRequestHandler> Browser::Launcher::LaunchRs3Exe(CefRefPtr<CefRequest> request, std::string_view query) {
|
||||
const CefRefPtr<CefPostData> post_data = request->GetPostData();
|
||||
|
||||
// parse query
|
||||
std::wstring hash;
|
||||
bool has_hash = false;
|
||||
std::wstring config_uri;
|
||||
bool has_config_uri = false;
|
||||
std::wstring jx_session_id;
|
||||
bool has_jx_session_id = false;
|
||||
std::wstring jx_character_id;
|
||||
bool has_jx_character_id = false;
|
||||
std::wstring jx_display_name;
|
||||
bool has_jx_display_name = false;
|
||||
#if defined(BOLT_PLUGINS)
|
||||
bool plugin_loader = false;
|
||||
#endif
|
||||
this->ParseQuery(query, [&](const std::string_view& key, const std::string_view& val) {
|
||||
PQCHECK(hash)
|
||||
PQCHECK(config_uri)
|
||||
PQCHECK(jx_session_id)
|
||||
PQCHECK(jx_character_id)
|
||||
PQCHECK(jx_display_name)
|
||||
#if defined(BOLT_PLUGINS)
|
||||
PQBOOL(plugin_loader)
|
||||
#endif
|
||||
});
|
||||
|
||||
// if there was a "hash" in the query string, we need to save the new game exe and the new hash
|
||||
if (has_hash) {
|
||||
if (post_data == nullptr || post_data->GetElementCount() != 1) {
|
||||
// hash param must be accompanied by POST data containing the file it's a hash of,
|
||||
// so hash but no POST is a bad request
|
||||
const char* data = "Bad Request";
|
||||
return new ResourceHandler(reinterpret_cast<const unsigned char*>(data), strlen(data), 400, "text/plain");
|
||||
}
|
||||
std::ofstream file(this->rs3_exe_path, std::ios::out | std::ios::binary);
|
||||
if (file.fail()) {
|
||||
const char* data = "Failed to save executable; if the game is already running, close it and try again\n";
|
||||
return new Browser::ResourceHandler(reinterpret_cast<const unsigned char*>(data), strlen(data), 500, "text/plain");
|
||||
}
|
||||
CefPostData::ElementVector vec;
|
||||
post_data->GetElements(vec);
|
||||
size_t exe_size = vec[0]->GetBytesCount();
|
||||
unsigned char* exe = new unsigned char[exe_size];
|
||||
vec[0]->GetBytes(exe_size, exe);
|
||||
file.write((const char*)exe, exe_size);
|
||||
file.close();
|
||||
delete[] exe;
|
||||
}
|
||||
|
||||
// create the command line for the new process
|
||||
std::wstring command_line = std::wstring(L"\"") + this->rs3_exe_path.wstring() + L"\"";
|
||||
if (has_config_uri) {
|
||||
command_line += L" --configURI \"";
|
||||
command_line += config_uri;
|
||||
command_line += L"\"";
|
||||
}
|
||||
|
||||
// create the environment block for the new process
|
||||
std::wstring session_key = L"JX_SESSION_ID=";
|
||||
std::wstring character_key = L"JX_CHARACTER_ID=";
|
||||
std::wstring name_key = L"JX_DISPLAY_NAME=";
|
||||
LPWCH env = GetEnvironmentStringsW();
|
||||
size_t env_size = 0;
|
||||
while (env[env_size] != '\0') {
|
||||
while (env[env_size] != '\0') env_size += 1;
|
||||
env_size += 1;
|
||||
}
|
||||
const size_t current_process_env_size = env_size;
|
||||
if (has_jx_session_id) env_size += session_key.size() + jx_session_id.size() + 1;
|
||||
if (has_jx_character_id) env_size += character_key.size() + jx_character_id.size() + 1;
|
||||
if (has_jx_display_name) env_size += name_key.size() + jx_display_name.size() + 1;
|
||||
wchar_t* new_env = new wchar_t[env_size + 1];
|
||||
memcpy(&new_env[0], env, current_process_env_size * sizeof(*env));
|
||||
FreeEnvironmentStringsW(env);
|
||||
wchar_t* cursor = &new_env[current_process_env_size];
|
||||
if (has_jx_session_id) {
|
||||
memcpy(cursor, &session_key[0], session_key.size() * sizeof(session_key[0]));
|
||||
cursor += session_key.size();
|
||||
memcpy(cursor, &jx_session_id[0], jx_session_id.size() * sizeof(jx_session_id[0]));
|
||||
cursor += jx_session_id.size();
|
||||
*cursor = '\0';
|
||||
cursor += 1;
|
||||
}
|
||||
if (has_jx_character_id) {
|
||||
memcpy(cursor, &character_key[0], character_key.size() * sizeof(character_key[0]));
|
||||
cursor += character_key.size();
|
||||
memcpy(cursor, &jx_character_id[0], jx_character_id.size() * sizeof(jx_character_id[0]));
|
||||
cursor += jx_character_id.size();
|
||||
*cursor = '\0';
|
||||
cursor += 1;
|
||||
}
|
||||
if (has_jx_display_name) {
|
||||
memcpy(cursor, &name_key[0], name_key.size() * sizeof(name_key[0]));
|
||||
cursor += name_key.size();
|
||||
memcpy(cursor, &jx_display_name[0], jx_display_name.size() * sizeof(jx_display_name[0]));
|
||||
cursor += jx_display_name.size();
|
||||
*cursor = '\0';
|
||||
cursor += 1;
|
||||
}
|
||||
*cursor = '\0';
|
||||
|
||||
PROCESS_INFORMATION pi;
|
||||
STARTUPINFOW si;
|
||||
ZeroMemory(&si, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
|
||||
if (!CreateProcessW(
|
||||
NULL,
|
||||
&command_line[0],
|
||||
NULL,
|
||||
NULL,
|
||||
false,
|
||||
CREATE_UNICODE_ENVIRONMENT, // CREATE_SUSPENDED goes here
|
||||
new_env,
|
||||
NULL,
|
||||
&si,
|
||||
&pi
|
||||
)) {
|
||||
delete[] new_env;
|
||||
const DWORD error = GetLastError();
|
||||
const std::string error_message = "CreateProcess failed with error " + std::to_string(error) + "\n";
|
||||
return new ResourceHandler(error_message, 500, "text/plain");
|
||||
}
|
||||
delete[] new_env;
|
||||
|
||||
if (has_hash) {
|
||||
std::wofstream file(this->rs3_exe_hash_path, std::ios::out | std::ios::binary);
|
||||
if (file.fail()) {
|
||||
const char* data = "OK, but unable to save hash file\n";
|
||||
return new Browser::ResourceHandler(reinterpret_cast<const unsigned char*>(data), strlen(data), 200, "text/plain");
|
||||
}
|
||||
file << hash;
|
||||
file.close();
|
||||
}
|
||||
|
||||
const char* data = "OK\n";
|
||||
return new ResourceHandler(reinterpret_cast<const unsigned char*>(data), strlen(data), 200, "text/plain");
|
||||
// TODO
|
||||
const char* data = ".exe is not supported on this platform\n";
|
||||
return new ResourceHandler(reinterpret_cast<const unsigned char*>(data), strlen(data), 400, "text/plain");
|
||||
}
|
||||
|
||||
CefRefPtr<CefResourceRequestHandler> Browser::Launcher::LaunchRs3App(CefRefPtr<CefRequest> request, std::string_view query) {
|
||||
|
||||
44
src/main.cxx
44
src/main.cxx
@@ -135,8 +135,31 @@ void BoltFailToObtainLockfile(std::filesystem::path tempdir) {
|
||||
|
||||
#if defined(__linux__)
|
||||
int main(int argc, char* argv[]) {
|
||||
CefMainArgs main_args(argc, argv);
|
||||
// Provide CEF with command-line arguments
|
||||
// Add a flag to disable web security, because a certain company's API endpoints don't have correct
|
||||
// access control settings; remove this setting if they ever get their stuff together
|
||||
// Also add a flag to disable GPUCache being saved on disk because it just breaks sometimes?
|
||||
const char* arg1 = "--disable-web-security";
|
||||
const char* arg2 = "--disable-gpu-shader-disk-cache";
|
||||
const size_t arg1_len = strlen(arg1);
|
||||
const size_t arg2_len = strlen(arg2);
|
||||
char* arg1_ = new char[arg1_len + 1];
|
||||
char* arg2_ = new char[arg2_len + 1];
|
||||
memcpy(arg1_, arg1, arg1_len);
|
||||
memcpy(arg2_, arg2, arg2_len);
|
||||
arg1_[arg1_len] = '\0';
|
||||
arg2_[arg2_len] = '\0';
|
||||
char** argv_ = new char*[argc + 2];
|
||||
memcpy(argv_, argv, argc * sizeof(char*));
|
||||
argv_[argc] = arg1_;
|
||||
argv_[argc + 1] = arg2_;
|
||||
|
||||
CefMainArgs main_args(argc + 2, argv_);
|
||||
int ret = BoltRunAnyProcess(main_args);
|
||||
|
||||
delete[] argv_;
|
||||
delete[] arg2_;
|
||||
delete[] arg1_;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -237,9 +260,15 @@ int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t* lpCmdLine, i
|
||||
fmt::print("Exiting with error: CommandLineToArgvW failed\n");
|
||||
return 1;
|
||||
}
|
||||
const wchar_t* const arg = L"--disable-web-security";
|
||||
const wchar_t* subp_arg = L"--type=";
|
||||
bool has_arg = false;
|
||||
bool is_subprocess = false;
|
||||
for(size_t i = 0; i < argc; i += 1) {
|
||||
// check if arg is --disable-web-security
|
||||
if (wcsstr(argv[i], arg)) {
|
||||
has_arg = true;
|
||||
}
|
||||
// check if arg begins with --type=
|
||||
if (wcsncmp(argv[i], subp_arg, wcslen(subp_arg)) == 0) {
|
||||
is_subprocess = true;
|
||||
@@ -252,13 +281,24 @@ int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t* lpCmdLine, i
|
||||
int ret = BoltRunAnyProcess(CefMainArgs(hInstance));
|
||||
CefShutdown();
|
||||
return ret;
|
||||
} else {
|
||||
} else if (has_arg) {
|
||||
// CefApp struct - this implements handlers used by multiple processes
|
||||
Browser::App cef_app_;
|
||||
CefRefPtr<Browser::App> cef_app = &cef_app_;
|
||||
int ret = BoltRunBrowserProcess(CefMainArgs(hInstance), cef_app);
|
||||
CefShutdown();
|
||||
return ret;
|
||||
} else {
|
||||
wchar_t module_name[1024];
|
||||
GetModuleFileNameW(NULL, module_name, 1024);
|
||||
std::wstring command_line(lpCmdLine);
|
||||
command_line += std::wstring(L" ");
|
||||
command_line += std::wstring(arg);
|
||||
PROCESS_INFORMATION process_info;
|
||||
STARTUPINFOW startup_info;
|
||||
GetStartupInfoW(&startup_info);
|
||||
CreateProcessW(module_name, command_line.data(), NULL, NULL, 0, 0, NULL, NULL, &startup_info, &process_info);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user