This commit is contained in:
恍兮惚兮 2024-10-20 14:07:21 +08:00
parent b79bda0f1f
commit ea03dc7dd6
4 changed files with 153 additions and 135 deletions

View File

@ -62,7 +62,7 @@ include(generate_product_version)
set(VERSION_MAJOR 3) set(VERSION_MAJOR 3)
set(VERSION_MINOR 15) set(VERSION_MINOR 15)
set(VERSION_PATCH 0) set(VERSION_PATCH 1)
set(VERSION_REVISION 0) set(VERSION_REVISION 0)
if(BUILD_CORE) if(BUILD_CORE)

View File

@ -471,29 +471,6 @@ Return Value:
--***************************************************************************/ --***************************************************************************/
std::string urlDecode(const std::string &encoded)
{
std::string decoded;
for (size_t i = 0; i < encoded.size(); i++)
{
if (encoded[i] == '%')
{
char ch = std::stoi(encoded.substr(i + 1, 2), 0, 16);
decoded += ch;
i = i + 2;
}
else if (encoded[i] == '+')
{
decoded += ' ';
}
else
{
decoded += encoded[i];
}
}
return decoded;
}
#pragma optimize("", off) #pragma optimize("", off)
const wchar_t *LUNA_CONTENTBYPASS(const wchar_t *_) const wchar_t *LUNA_CONTENTBYPASS(const wchar_t *_)
{ {
@ -507,57 +484,114 @@ SendHttpResponse(
IN PHTTP_REQUEST pRequest) IN PHTTP_REQUEST pRequest)
{ {
HTTP_RESPONSE response; HTTP_RESPONSE response;
HTTP_DATA_CHUNK dataChunk;
DWORD result; DWORD result;
DWORD bytesSent; DWORD bytesSent;
USHORT StatusCode = 200; ULONG BytesRead;
PSTR pReason = "OK"; HTTP_DATA_CHUNK dataChunk;
std::string recv;
std::string buff;
buff.resize(2048);
bool recving = true;
// //
// Initialize the HTTP response structure. // Initialize the HTTP response structure.
// //
INITIALIZE_HTTP_RESPONSE(&response, StatusCode, pReason); INITIALIZE_HTTP_RESPONSE(&response, 200, "OK");
// //
// Add a known header. // For POST, we'll echo back the entity that we got from the client.
// //
ADD_KNOWN_HEADER(response, HttpHeaderContentType, "text/html"); // NOTE: If we had passed the HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY
std::string url(pRequest->pRawUrl, pRequest->RawUrlLength); // flag with HttpReceiveHttpRequest(), the entity would have
auto fnd = url.find('?'); // been a part of HTTP_REQUEST (using the pEntityChunks field).
// Since we have not passed that flag, we can be assured that
if (fnd != url.npos) // there are no entity bodies in HTTP_REQUEST.
//
if (pRequest->Flags & HTTP_REQUEST_FLAG_MORE_ENTITY_BODY_EXISTS)
{ {
url = url.substr(fnd + 1); // The entity body is send over multiple calls. Let's collect all
url = urlDecode(url); // of these in a file & send it back. We'll create a temp file
url = WideStringToString(LUNA_CONTENTBYPASS(StringToWideString(url).c_str()));
// //
// Add an entity chunk
//
dataChunk.DataChunkType = HttpDataChunkFromMemory;
dataChunk.FromMemory.pBuffer = (PVOID)url.c_str();
dataChunk.FromMemory.BufferLength = (ULONG)url.size();
response.EntityChunkCount = 1; do
response.pEntityChunks = &dataChunk; {
//
// Read the entity chunk from the request.
//
BytesRead = 0;
result = HttpReceiveRequestEntityBody(
hReqQueue,
pRequest->RequestId,
0,
buff.data(),
buff.capacity(),
&BytesRead,
NULL);
switch (result)
{
case NO_ERROR:
case ERROR_HANDLE_EOF:
if (BytesRead != 0)
{
recv += buff.substr(0, BytesRead);
}
if (result == ERROR_HANDLE_EOF)
recving = false;
break;
default:
recving = false;
}
} while (recving);
} }
if (recv.size())
recv = WideStringToString(LUNA_CONTENTBYPASS(StringToWideString(recv).c_str()));
if (recv.size())
{
ADD_KNOWN_HEADER(
response,
HttpHeaderContentLength,
std::to_string(recv.size()).c_str());
}
result =
HttpSendHttpResponse(
hReqQueue, // ReqQueueHandle
pRequest->RequestId, // Request ID
recv.size() ? HTTP_SEND_RESPONSE_FLAG_MORE_DATA : 0,
&response, // HTTP response
NULL, // pReserved1
&bytesSent, // bytes sent (optional)
NULL, // pReserved2
0, // Reserved3
NULL, // LPOVERLAPPED
NULL // pReserved4
);
if (result != NO_ERROR)
{
return result;
}
if (!recv.size())
return result;
// //
// Since we are sending all the entity body in one call, we don't have // Send entity body from a file handle.
// to specify the Content-Length.
// //
dataChunk.DataChunkType = HttpDataChunkFromMemory;
dataChunk.FromMemory.pBuffer = (PVOID)recv.c_str();
dataChunk.FromMemory.BufferLength = (ULONG)recv.size();
result = HttpSendHttpResponse( result = HttpSendResponseEntityBody(
hReqQueue, // ReqQueueHandle hReqQueue,
pRequest->RequestId, // Request ID pRequest->RequestId,
0, // Flags 0, // This is the last send.
&response, // HTTP response 1, // Entity Chunk Count.
NULL, // pReserved1 &dataChunk,
&bytesSent, // bytes sent (OPTIONAL) NULL,
NULL, // pReserved2 (must be NULL) NULL,
0, // Reserved3 (must be 0) 0,
NULL, // LPOVERLAPPED (OPTIONAL) NULL,
NULL // pReserved4 (must be NULL) NULL);
);
return result; return result;
} }

View File

@ -8,6 +8,12 @@ namespace
constexpr auto magicrecv = L"\x01LUNAFROMHOST\x01"; constexpr auto magicrecv = L"\x01LUNAFROMHOST\x01";
} }
namespace namespace
{
bool useclipboard = true;
bool usehttp = true;
int usehttp_port = 0;
}
namespace
{ {
void parsebefore(wchar_t *text, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len) void parsebefore(wchar_t *text, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
@ -150,25 +156,11 @@ namespace v8script
} }
} }
} }
auto port = 0;
auto useclipboard = !std::filesystem::exists(std::filesystem::path(getModuleFilename().value()).replace_filename("disable.clipboard"));
auto usehttp = !std::filesystem::exists(std::filesystem::path(getModuleFilename().value()).replace_filename("disable.http"));
if (usehttp)
{
port = makehttpgetserverinternal();
ConsoleOutput("%d %d", GetCurrentProcessId(), port);
hook_LUNA_CONTENTBYPASS();
dont_detach = true;
}
if (useclipboard)
{
hookClipboard();
}
auto lunajspatch = LoadResData(L"lunajspatch", L"JSSOURCE"); auto lunajspatch = LoadResData(L"lunajspatch", L"JSSOURCE");
strReplace(lunajspatch, "IS_PACKED", std::to_string(is_packed)); strReplace(lunajspatch, "IS_PACKED", std::to_string(is_packed));
strReplace(lunajspatch, "IS_USECLIPBOARD", std::to_string(useclipboard)); strReplace(lunajspatch, "IS_USECLIPBOARD", std::to_string(useclipboard));
strReplace(lunajspatch, "INTERNAL_HTTP_PORT", std::to_string(port)); strReplace(lunajspatch, "INTERNAL_HTTP_PORT", std::to_string(usehttp_port));
NewFromUtf8(&v8string, isolate, lunajspatch.c_str(), 1, -1); NewFromUtf8(&v8string, isolate, lunajspatch.c_str(), 1, -1);
ConsoleOutput("v8string %p", v8string); ConsoleOutput("v8string %p", v8string);
if (v8string == 0) if (v8string == 0)
@ -363,10 +355,24 @@ bool tryhookv8()
auto hm = GetModuleHandleW(moduleName); auto hm = GetModuleHandleW(moduleName);
if (hm == 0) if (hm == 0)
continue; continue;
auto ok = hookstring(hm); if (hookstring(hm))
ok |= v8script::v8runscript(hm); {
if (ok) useclipboard = !std::filesystem::exists(std::filesystem::path(getModuleFilename().value()).replace_filename("disable.clipboard"));
return true; usehttp = !std::filesystem::exists(std::filesystem::path(getModuleFilename().value()).replace_filename("disable.http"));
if (usehttp)
{
usehttp_port = makehttpgetserverinternal();
ConsoleOutput("%d %d", GetCurrentProcessId(), usehttp_port);
hook_LUNA_CONTENTBYPASS();
dont_detach = true;
}
if (useclipboard)
{
hookClipboard();
}
return v8script::v8runscript(hm);
}
} }
return false; return false;
} }

View File

@ -12,7 +12,6 @@ function splitfonttext(transwithfont) {
} }
else if (transwithfont.substr(0, magicrecv.length) == magicrecv) { else if (transwithfont.substr(0, magicrecv.length) == magicrecv) {
transwithfont = transwithfont.substr(magicrecv.length) transwithfont = transwithfont.substr(magicrecv.length)
//magic font \x02 text
split = transwithfont.search('\x02') split = transwithfont.search('\x02')
fontface = transwithfont.substr(0, split) fontface = transwithfont.substr(0, split)
text = transwithfont.substr(split + 1) text = transwithfont.substr(split + 1)
@ -22,61 +21,40 @@ function splitfonttext(transwithfont) {
return transwithfont; return transwithfont;
} }
} }
function syncquery(s) { function cppjsio(name, s_raw, lpsplit) {
if (internal_http_port == 0) { throw new Error('') }
var xhr = new XMLHttpRequest();
var url = 'http://127.0.0.1:' + internal_http_port + '/fuck?' + s
xhr.open('GET', url, false);
xhr.send();
if (xhr.status === 200) {
return xhr.responseText;//解析这个会导致v8::String::Length的v8StringUtf8Length出现错误但不影响。
} else {
throw new Error('')
}
}
function makecomplexs(name, s_raw, lpsplit) {
return magicsend + name + '\x03' + lpsplit.toString() + '\x02' + s_raw;
}
function cppjsio(s) {
try {
return syncquery(s)
}
catch (err) {
try {
if (!is_useclipboard) { throw new Error('') }
const _clipboard = require('nw.gui').Clipboard.get();
_clipboard.set(s, 'text');
return _clipboard.get('text');
}
catch (err2) {
try {
if (!is_useclipboard) { throw new Error('') }
const clipboard = require('electron').clipboard;
clipboard.writeText(s);
return clipboard.readText();
}
catch (err3) {
return s_raw;
}
}
}
}
function clipboardsender(name, s_raw, lpsplit) {
//magic split \x02 text
if (!s_raw) if (!s_raw)
return s_raw return s_raw
transwithfont = cppjsio(makecomplexs(name, s_raw, lpsplit)) transwithfont = ''
if (transwithfont.length == 0) return s_raw; s = magicsend + name + '\x03' + lpsplit.toString() + '\x02' + s_raw;
if (internal_http_port) {
var xhr = new XMLHttpRequest();
var url = 'http://127.0.0.1:' + internal_http_port + '/fuck'
xhr.open('POST', url, false);
xhr.send(s);
if (xhr.status === 200) {
transwithfont = xhr.responseText;
}
}
else if (is_useclipboard) {
try {
const _clipboard = require('nw.gui').Clipboard.get();
_clipboard.set(s, 'text');
transwithfont = _clipboard.get('text');
}
catch (err) {
try {
const clipboard = require('electron').clipboard;
clipboard.writeText(s);
transwithfont = clipboard.readText();
}
catch (err2) {
}
}
}
if (!transwithfont) return s_raw;
return splitfonttext(transwithfont) return splitfonttext(transwithfont)
} }
function clipboardsender_only_send(name, s_raw, lpsplit) {
//magic split \x02 text
if (!s_raw)
return s_raw
cppjsio(makecomplexs(name, s_raw, lpsplit))
}
function rpgmakerhook() { function rpgmakerhook() {
if (Window_Message.prototype.originstartMessage) { } if (Window_Message.prototype.originstartMessage) { }
@ -99,7 +77,7 @@ function rpgmakerhook() {
setInterval(function () { setInterval(function () {
for (lpsplit in Bitmap.prototype.collectstring) { for (lpsplit in Bitmap.prototype.collectstring) {
if (Bitmap.prototype.collectstring[lpsplit].length) { if (Bitmap.prototype.collectstring[lpsplit].length) {
clipboardsender_only_send('rpgmakermv', Bitmap.prototype.collectstring[lpsplit], lpsplit) cppjsio('rpgmakermv', Bitmap.prototype.collectstring[lpsplit], lpsplit)
Bitmap.prototype.collectstring[lpsplit] = '' Bitmap.prototype.collectstring[lpsplit] = ''
} }
} }
@ -121,12 +99,12 @@ function rpgmakerhook() {
} }
Window_Message.prototype.startMessage = function () { Window_Message.prototype.startMessage = function () {
gametext = $gameMessage.allText(); gametext = $gameMessage.allText();
resp = clipboardsender('rpgmakermv', gametext, 0); resp = cppjsio('rpgmakermv', gametext, 0);
$gameMessage._texts = [resp] $gameMessage._texts = [resp]
this.originstartMessage(); this.originstartMessage();
}; };
Window_Base.prototype.drawText = function (text, x, y, maxWidth, align) { Window_Base.prototype.drawText = function (text, x, y, maxWidth, align) {
text = clipboardsender('rpgmakermv', text, 1) text = cppjsio('rpgmakermv', text, 1)
return this.drawText_origin(text, x, y, maxWidth, align) return this.drawText_origin(text, x, y, maxWidth, align)
} }
Window_Base.prototype.lastcalltime = 0 Window_Base.prototype.lastcalltime = 0
@ -135,7 +113,7 @@ function rpgmakerhook() {
__now = new Date().getTime() __now = new Date().getTime()
Window_Base.prototype.lastcalltime = __now Window_Base.prototype.lastcalltime = __now
if (__now - __last > 100) if (__now - __last > 100)
text = clipboardsender('rpgmakermv', text, 2) text = cppjsio('rpgmakermv', text, 2)
else { else {
Bitmap.prototype.collectstring[2] += text; Bitmap.prototype.collectstring[2] += text;
} }
@ -150,7 +128,7 @@ function tyranohook() {
tyrano.plugin.kag.tag.chara_ptext.startorigin = tyrano.plugin.kag.tag.chara_ptext.start; tyrano.plugin.kag.tag.chara_ptext.startorigin = tyrano.plugin.kag.tag.chara_ptext.start;
tyrano.plugin.kag.tag.text.start = function (pm) { tyrano.plugin.kag.tag.text.start = function (pm) {
if (1 != this.kag.stat.is_script && 1 != this.kag.stat.is_html) { if (1 != this.kag.stat.is_script && 1 != this.kag.stat.is_html) {
pm.val = clipboardsender('tyranoscript', pm.val, 0); pm.val = cppjsio('tyranoscript', pm.val, 0);
if (fontface) { if (fontface) {
this.kag.stat.font.face = fontface this.kag.stat.font.face = fontface
} }
@ -158,7 +136,7 @@ function tyranohook() {
return this.originstart(pm) return this.originstart(pm)
} }
tyrano.plugin.kag.tag.chara_ptext.start = function (pm) { tyrano.plugin.kag.tag.chara_ptext.start = function (pm) {
pm.name = clipboardsender('tyranoscript', pm.name, 1) pm.name = cppjsio('tyranoscript', pm.name, 1)
return this.startorigin(pm) return this.startorigin(pm)
} }
} }