mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-11-23 05:45:37 +08:00
v8
This commit is contained in:
parent
b79bda0f1f
commit
ea03dc7dd6
@ -62,7 +62,7 @@ include(generate_product_version)
|
||||
|
||||
set(VERSION_MAJOR 3)
|
||||
set(VERSION_MINOR 15)
|
||||
set(VERSION_PATCH 0)
|
||||
set(VERSION_PATCH 1)
|
||||
set(VERSION_REVISION 0)
|
||||
|
||||
if(BUILD_CORE)
|
||||
|
@ -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)
|
||||
const wchar_t *LUNA_CONTENTBYPASS(const wchar_t *_)
|
||||
{
|
||||
@ -507,57 +484,114 @@ SendHttpResponse(
|
||||
IN PHTTP_REQUEST pRequest)
|
||||
{
|
||||
HTTP_RESPONSE response;
|
||||
HTTP_DATA_CHUNK dataChunk;
|
||||
DWORD result;
|
||||
DWORD bytesSent;
|
||||
USHORT StatusCode = 200;
|
||||
PSTR pReason = "OK";
|
||||
|
||||
ULONG BytesRead;
|
||||
HTTP_DATA_CHUNK dataChunk;
|
||||
std::string recv;
|
||||
std::string buff;
|
||||
buff.resize(2048);
|
||||
bool recving = true;
|
||||
//
|
||||
// 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");
|
||||
std::string url(pRequest->pRawUrl, pRequest->RawUrlLength);
|
||||
auto fnd = url.find('?');
|
||||
|
||||
if (fnd != url.npos)
|
||||
// NOTE: If we had passed the HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY
|
||||
// flag with HttpReceiveHttpRequest(), the entity would have
|
||||
// been a part of HTTP_REQUEST (using the pEntityChunks field).
|
||||
// Since we have not passed that flag, we can be assured that
|
||||
// there are no entity bodies in HTTP_REQUEST.
|
||||
//
|
||||
if (pRequest->Flags & HTTP_REQUEST_FLAG_MORE_ENTITY_BODY_EXISTS)
|
||||
{
|
||||
url = url.substr(fnd + 1);
|
||||
url = urlDecode(url);
|
||||
url = WideStringToString(LUNA_CONTENTBYPASS(StringToWideString(url).c_str()));
|
||||
// The entity body is send over multiple calls. Let's collect all
|
||||
// of these in a file & send it back. We'll create a temp file
|
||||
//
|
||||
// Add an entity chunk
|
||||
//
|
||||
dataChunk.DataChunkType = HttpDataChunkFromMemory;
|
||||
dataChunk.FromMemory.pBuffer = (PVOID)url.c_str();
|
||||
dataChunk.FromMemory.BufferLength = (ULONG)url.size();
|
||||
|
||||
response.EntityChunkCount = 1;
|
||||
response.pEntityChunks = &dataChunk;
|
||||
do
|
||||
{
|
||||
//
|
||||
// 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
|
||||
// to specify the Content-Length.
|
||||
// Send entity body from a file handle.
|
||||
//
|
||||
dataChunk.DataChunkType = HttpDataChunkFromMemory;
|
||||
dataChunk.FromMemory.pBuffer = (PVOID)recv.c_str();
|
||||
dataChunk.FromMemory.BufferLength = (ULONG)recv.size();
|
||||
|
||||
result = HttpSendHttpResponse(
|
||||
hReqQueue, // ReqQueueHandle
|
||||
pRequest->RequestId, // Request ID
|
||||
0, // Flags
|
||||
&response, // HTTP response
|
||||
NULL, // pReserved1
|
||||
&bytesSent, // bytes sent (OPTIONAL)
|
||||
NULL, // pReserved2 (must be NULL)
|
||||
0, // Reserved3 (must be 0)
|
||||
NULL, // LPOVERLAPPED (OPTIONAL)
|
||||
NULL // pReserved4 (must be NULL)
|
||||
);
|
||||
result = HttpSendResponseEntityBody(
|
||||
hReqQueue,
|
||||
pRequest->RequestId,
|
||||
0, // This is the last send.
|
||||
1, // Entity Chunk Count.
|
||||
&dataChunk,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
return result;
|
||||
}
|
@ -8,6 +8,12 @@ namespace
|
||||
constexpr auto magicrecv = L"\x01LUNAFROMHOST\x01";
|
||||
}
|
||||
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)
|
||||
@ -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");
|
||||
strReplace(lunajspatch, "IS_PACKED", std::to_string(is_packed));
|
||||
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);
|
||||
ConsoleOutput("v8string %p", v8string);
|
||||
if (v8string == 0)
|
||||
@ -363,10 +355,24 @@ bool tryhookv8()
|
||||
auto hm = GetModuleHandleW(moduleName);
|
||||
if (hm == 0)
|
||||
continue;
|
||||
auto ok = hookstring(hm);
|
||||
ok |= v8script::v8runscript(hm);
|
||||
if (ok)
|
||||
return true;
|
||||
if (hookstring(hm))
|
||||
{
|
||||
useclipboard = !std::filesystem::exists(std::filesystem::path(getModuleFilename().value()).replace_filename("disable.clipboard"));
|
||||
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;
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ function splitfonttext(transwithfont) {
|
||||
}
|
||||
else if (transwithfont.substr(0, magicrecv.length) == magicrecv) {
|
||||
transwithfont = transwithfont.substr(magicrecv.length)
|
||||
//magic font \x02 text
|
||||
split = transwithfont.search('\x02')
|
||||
fontface = transwithfont.substr(0, split)
|
||||
text = transwithfont.substr(split + 1)
|
||||
@ -22,61 +21,40 @@ function splitfonttext(transwithfont) {
|
||||
return transwithfont;
|
||||
}
|
||||
}
|
||||
function syncquery(s) {
|
||||
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
|
||||
function cppjsio(name, s_raw, lpsplit) {
|
||||
if (!s_raw)
|
||||
return s_raw
|
||||
transwithfont = cppjsio(makecomplexs(name, s_raw, lpsplit))
|
||||
if (transwithfont.length == 0) return s_raw;
|
||||
transwithfont = ''
|
||||
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)
|
||||
}
|
||||
|
||||
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() {
|
||||
|
||||
if (Window_Message.prototype.originstartMessage) { }
|
||||
@ -99,7 +77,7 @@ function rpgmakerhook() {
|
||||
setInterval(function () {
|
||||
for (lpsplit in Bitmap.prototype.collectstring) {
|
||||
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] = ''
|
||||
}
|
||||
}
|
||||
@ -121,12 +99,12 @@ function rpgmakerhook() {
|
||||
}
|
||||
Window_Message.prototype.startMessage = function () {
|
||||
gametext = $gameMessage.allText();
|
||||
resp = clipboardsender('rpgmakermv', gametext, 0);
|
||||
resp = cppjsio('rpgmakermv', gametext, 0);
|
||||
$gameMessage._texts = [resp]
|
||||
this.originstartMessage();
|
||||
};
|
||||
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)
|
||||
}
|
||||
Window_Base.prototype.lastcalltime = 0
|
||||
@ -135,7 +113,7 @@ function rpgmakerhook() {
|
||||
__now = new Date().getTime()
|
||||
Window_Base.prototype.lastcalltime = __now
|
||||
if (__now - __last > 100)
|
||||
text = clipboardsender('rpgmakermv', text, 2)
|
||||
text = cppjsio('rpgmakermv', text, 2)
|
||||
else {
|
||||
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.text.start = function (pm) {
|
||||
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) {
|
||||
this.kag.stat.font.face = fontface
|
||||
}
|
||||
@ -158,7 +136,7 @@ function tyranohook() {
|
||||
return this.originstart(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)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user