mirror of
https://gitlab.com/Theopse/fbi-i18n-zh.git
synced 2025-05-22 15:59:18 +08:00
Polish up URL sending protocol, adapt servefiles to send URLs over socket.
This commit is contained in:
parent
d06374d838
commit
13a88f7adb
@ -1,7 +1,5 @@
|
|||||||
# servefiles
|
# servefiles
|
||||||
|
|
||||||
Simple Python script for serving local files to FBI's QR code installer. Requires [Python](https://www.python.org/downloads/), [Pillow](https://pypi.python.org/pypi/Pillow), [qrcode](https://pypi.python.org/pypi/qrcode), and [netifaces](https://pypi.python.org/pypi/netifaces).
|
Simple Python script for serving local files to FBI's remote installer. Requires [Python](https://www.python.org/downloads/).
|
||||||
|
|
||||||
**Usage**: python servefiles.py (file/directory)
|
**Usage**: python servefiles.py (ip) (file/directory)
|
||||||
|
|
||||||
If you are on Windows, you can drag and drop a CIA file or directory onto **servefiles.bat**.
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
python servefiles.py %1
|
|
@ -1,33 +1,30 @@
|
|||||||
import atexit
|
import atexit
|
||||||
import os
|
import os
|
||||||
|
import socket
|
||||||
|
import struct
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import threading
|
import threading
|
||||||
|
import time
|
||||||
import urllib
|
import urllib
|
||||||
|
|
||||||
import netifaces
|
|
||||||
import qrcode
|
|
||||||
|
|
||||||
from PIL import ImageTk
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from SimpleHTTPServer import SimpleHTTPRequestHandler
|
from SimpleHTTPServer import SimpleHTTPRequestHandler
|
||||||
from SocketServer import TCPServer
|
from SocketServer import TCPServer
|
||||||
from Tkinter import Tk, Frame, Label, BitmapImage
|
|
||||||
from urlparse import urljoin
|
from urlparse import urljoin
|
||||||
from urllib import pathname2url, quote
|
from urllib import pathname2url, quote
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from http.server import SimpleHTTPRequestHandler
|
from http.server import SimpleHTTPRequestHandler
|
||||||
from socketserver import TCPServer
|
from socketserver import TCPServer
|
||||||
from tkinter import Tk, Frame, Label, BitmapImage
|
|
||||||
from urllib.parse import urljoin, quote
|
from urllib.parse import urljoin, quote
|
||||||
from urllib.request import pathname2url
|
from urllib.request import pathname2url
|
||||||
|
|
||||||
if len(sys.argv) < 2:
|
if len(sys.argv) < 3:
|
||||||
print("Please specify a file/directory.")
|
print("Usage: " + sys.argv[0] + " <ip> <file/directory>")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
directory = sys.argv[1]
|
ip = sys.argv[1]
|
||||||
|
directory = sys.argv[2]
|
||||||
|
|
||||||
if not os.path.exists(directory):
|
if not os.path.exists(directory):
|
||||||
print(directory + ": No such file or directory.")
|
print(directory + ": No such file or directory.")
|
||||||
@ -35,19 +32,19 @@ if not os.path.exists(directory):
|
|||||||
|
|
||||||
print("Preparing data...")
|
print("Preparing data...")
|
||||||
|
|
||||||
baseUrl = netifaces.ifaddresses(netifaces.gateways()['default'][netifaces.AF_INET][1])[2][0]['addr'] + ":8080/"
|
baseUrl = [(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1] + ":8080/"
|
||||||
qrData = ""
|
payload = ""
|
||||||
|
|
||||||
if os.path.isfile(directory):
|
if os.path.isfile(directory):
|
||||||
if directory.endswith(('.cia', '.tik')):
|
if directory.endswith(('.cia', '.tik')):
|
||||||
qrData += baseUrl + quote(os.path.basename(directory))
|
payload += baseUrl + quote(os.path.basename(directory))
|
||||||
|
|
||||||
directory = os.path.dirname(directory)
|
directory = os.path.dirname(directory)
|
||||||
else:
|
else:
|
||||||
for file in [ file for file in next(os.walk(directory))[2] if file.endswith(('.cia', '.tik')) ]:
|
for file in [ file for file in next(os.walk(directory))[2] if file.endswith(('.cia', '.tik')) ]:
|
||||||
qrData += baseUrl + quote(file) + "\n"
|
payload += baseUrl + quote(file) + "\n"
|
||||||
|
|
||||||
if len(qrData) == 0:
|
if len(payload) == 0:
|
||||||
print("No files to serve.")
|
print("No files to serve.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
@ -56,37 +53,38 @@ if not directory == "":
|
|||||||
|
|
||||||
print("")
|
print("")
|
||||||
print("URLS:")
|
print("URLS:")
|
||||||
print(qrData)
|
print(payload)
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
print("Generating QR code...")
|
|
||||||
|
|
||||||
try:
|
|
||||||
qrImage = qrcode.make(qrData, box_size=5)
|
|
||||||
except qrcode.exceptions.DataOverflowError:
|
|
||||||
print("Error: URL list too large for a QR code. Try reducing file name lengths or the number of files to send.")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
print("Opening HTTP server on port 8080...")
|
print("Opening HTTP server on port 8080...")
|
||||||
|
|
||||||
server = TCPServer(("", 8080), SimpleHTTPRequestHandler)
|
server = TCPServer(("", 8080), SimpleHTTPRequestHandler)
|
||||||
thread = threading.Thread(target=server.serve_forever)
|
thread = threading.Thread(target=server.serve_forever)
|
||||||
thread.start()
|
thread.start()
|
||||||
atexit.register(server.shutdown)
|
|
||||||
|
|
||||||
print("Displaying QR code...")
|
try:
|
||||||
|
print("Sending URL(s) to " + ip + ":5000...")
|
||||||
|
|
||||||
root = Tk()
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
root.title("QR Code")
|
sock.connect((ip, 5000))
|
||||||
|
|
||||||
frame = Frame(root)
|
payloadBytes = bytes(payload, "ascii")
|
||||||
frame.pack()
|
networkPayload = struct.pack('!L', len(payloadBytes)) + payloadBytes
|
||||||
|
|
||||||
qrBitmap = ImageTk.PhotoImage(qrImage)
|
sentLength = 0
|
||||||
qrLabel = Label(frame, image=qrBitmap)
|
while sentLength < len(networkPayload):
|
||||||
qrLabel.pack()
|
sent = sock.send(networkPayload[sentLength:])
|
||||||
|
if sent == 0:
|
||||||
|
raise RuntimeError("Socket connection broken.")
|
||||||
|
|
||||||
|
sentLength += sent
|
||||||
|
|
||||||
root.mainloop()
|
while len(sock.recv(1)) < 1:
|
||||||
|
time.sleep(0.05)
|
||||||
|
|
||||||
|
sock.close()
|
||||||
|
except Exception as e:
|
||||||
|
print("Error: " + str(e))
|
||||||
|
|
||||||
print("Shutting down HTTP server...")
|
print("Shutting down HTTP server...")
|
||||||
|
|
||||||
|
@ -49,5 +49,6 @@ void action_import_secure_value(linked_list* items, list_item* selected);
|
|||||||
void action_export_secure_value(linked_list* items, list_item* selected);
|
void action_export_secure_value(linked_list* items, list_item* selected);
|
||||||
void action_delete_secure_value(linked_list* items, list_item* selected);
|
void action_delete_secure_value(linked_list* items, list_item* selected);
|
||||||
|
|
||||||
void action_url_install(const char* confirmMessage, const char* urls);
|
void action_url_install(const char* confirmMessage, const char* urls, void* finishedData, void (*finished)(void* data));
|
||||||
|
|
||||||
void action_install_titledb(linked_list* items, list_item* selected);
|
void action_install_titledb(linked_list* items, list_item* selected);
|
@ -10,5 +10,5 @@ void action_install_titledb(linked_list* items, list_item* selected) {
|
|||||||
char url[128];
|
char url[128];
|
||||||
snprintf(url, sizeof(url), "https://api.titledb.com/v0/proxy/%016llX", ((titledb_info*) selected->data)->titleId);
|
snprintf(url, sizeof(url), "https://api.titledb.com/v0/proxy/%016llX", ((titledb_info*) selected->data)->titleId);
|
||||||
|
|
||||||
action_url_install("Install the selected title from TitleDB?", url);
|
action_url_install("Install the selected title from TitleDB?", url, NULL, NULL);
|
||||||
}
|
}
|
@ -19,6 +19,9 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
char urls[URLS_MAX][URL_MAX];
|
char urls[URLS_MAX][URL_MAX];
|
||||||
|
|
||||||
|
void* finishedData;
|
||||||
|
void (*finished)(void* data);
|
||||||
|
|
||||||
bool cdn;
|
bool cdn;
|
||||||
bool cdnDecided;
|
bool cdnDecided;
|
||||||
|
|
||||||
@ -31,6 +34,14 @@ typedef struct {
|
|||||||
data_op_data installInfo;
|
data_op_data installInfo;
|
||||||
} url_install_data;
|
} url_install_data;
|
||||||
|
|
||||||
|
static void action_url_install_free_data(url_install_data* data) {
|
||||||
|
if(data->finished != NULL) {
|
||||||
|
data->finished(data->finishedData);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
static void action_url_install_cdn_check_onresponse(ui_view* view, void* data, bool response) {
|
static void action_url_install_cdn_check_onresponse(ui_view* view, void* data, bool response) {
|
||||||
url_install_data* installData = (url_install_data*) data;
|
url_install_data* installData = (url_install_data*) data;
|
||||||
|
|
||||||
@ -248,6 +259,8 @@ static void action_url_install_install_update(ui_view* view, void* data, float*
|
|||||||
prompt_display("Success", "Install finished.", COLOR_TEXT, false, NULL, NULL, NULL);
|
prompt_display("Success", "Install finished.", COLOR_TEXT, false, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
action_url_install_free_data(installData);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,14 +281,18 @@ static void action_url_install_confirm_onresponse(ui_view* view, void* data, boo
|
|||||||
info_display("Installing From URL(s)", "Press B to cancel.", true, data, action_url_install_install_update, NULL);
|
info_display("Installing From URL(s)", "Press B to cancel.", true, data, action_url_install_install_update, NULL);
|
||||||
} else {
|
} else {
|
||||||
error_display_res(NULL, NULL, res, "Failed to initiate installation.");
|
error_display_res(NULL, NULL, res, "Failed to initiate installation.");
|
||||||
|
|
||||||
|
action_url_install_free_data(installData);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
action_url_install_free_data(installData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void action_url_install(const char* confirmMessage, const char* urls) {
|
void action_url_install(const char* confirmMessage, const char* urls, void* finishedData, void (*finished)(void* data)) {
|
||||||
url_install_data* data = (url_install_data*) calloc(1, sizeof(url_install_data));
|
url_install_data* data = (url_install_data*) calloc(1, sizeof(url_install_data));
|
||||||
if(data == NULL) {
|
if(data == NULL) {
|
||||||
error_display(NULL, NULL, "Failed to allocate QR install data.");
|
error_display(NULL, NULL, "Failed to allocate URL install data.");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -313,6 +330,9 @@ void action_url_install(const char* confirmMessage, const char* urls) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data->finishedData = finishedData;
|
||||||
|
data->finished = finished;
|
||||||
|
|
||||||
data->cdn = false;
|
data->cdn = false;
|
||||||
data->cdnDecided = false;
|
data->cdnDecided = false;
|
||||||
|
|
||||||
|
@ -202,7 +202,7 @@ static void remoteinstall_qr_update(ui_view* view, void* data, float* progress,
|
|||||||
|
|
||||||
remoteinstall_set_last_urls((const char*) qrData.payload);
|
remoteinstall_set_last_urls((const char*) qrData.payload);
|
||||||
|
|
||||||
action_url_install("Install from the scanned QR code?", (const char*) qrData.payload);
|
action_url_install("Install from the scanned QR code?", (const char*) qrData.payload, NULL, NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -255,6 +255,7 @@ void remoteinstall_scan_qr_code() {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int serverSocket;
|
int serverSocket;
|
||||||
|
int clientSocket;
|
||||||
} remoteinstall_network_data;
|
} remoteinstall_network_data;
|
||||||
|
|
||||||
static int remoteinstall_network_recvwait(int sockfd, void* buf, size_t len, int flags) {
|
static int remoteinstall_network_recvwait(int sockfd, void* buf, size_t len, int flags) {
|
||||||
@ -269,7 +270,33 @@ static int remoteinstall_network_recvwait(int sockfd, void* buf, size_t len, int
|
|||||||
return ret < 0 ? ret : (int) read;
|
return ret < 0 ? ret : (int) read;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int remoteinstall_network_sendwait(int sockfd, void* buf, size_t len, int flags) {
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
size_t written = 0;
|
||||||
|
while(((ret = send(sockfd, buf + written, len - written, flags)) >= 0 && (written += ret) < len) || errno == EAGAIN) {
|
||||||
|
errno = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret < 0 ? ret : (int) written;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remoteinstall_network_close_client(void* data) {
|
||||||
|
remoteinstall_network_data* networkData = (remoteinstall_network_data*) data;
|
||||||
|
|
||||||
|
if(networkData->clientSocket != 0) {
|
||||||
|
u8 ack = 0;
|
||||||
|
remoteinstall_network_sendwait(networkData->clientSocket, &ack, sizeof(ack), 0);
|
||||||
|
|
||||||
|
close(networkData->clientSocket);
|
||||||
|
networkData->clientSocket = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void remoteinstall_network_free_data(remoteinstall_network_data* data) {
|
static void remoteinstall_network_free_data(remoteinstall_network_data* data) {
|
||||||
|
remoteinstall_network_close_client(data);
|
||||||
|
|
||||||
if(data->serverSocket != 0) {
|
if(data->serverSocket != 0) {
|
||||||
close(data->serverSocket);
|
close(data->serverSocket);
|
||||||
data->serverSocket = 0;
|
data->serverSocket = 0;
|
||||||
@ -295,29 +322,44 @@ static void remoteinstall_network_update(ui_view* view, void* data, float* progr
|
|||||||
|
|
||||||
int sock = accept(networkData->serverSocket, (struct sockaddr*) &client, &clientLen);
|
int sock = accept(networkData->serverSocket, (struct sockaddr*) &client, &clientLen);
|
||||||
if(sock >= 0) {
|
if(sock >= 0) {
|
||||||
u32 size = 0;
|
networkData->clientSocket = sock;
|
||||||
if(remoteinstall_network_recvwait(sock, &size, sizeof(size), 0) == sizeof(size)) {
|
|
||||||
if(size < 128 * 1024) {
|
|
||||||
char* urls = (char*) calloc(size, sizeof(char));
|
|
||||||
if(urls != NULL) {
|
|
||||||
if(remoteinstall_network_recvwait(sock, urls, size, 0) == size) {
|
|
||||||
action_url_install("Install from the received URL(s)?", urls);
|
|
||||||
} else {
|
|
||||||
error_display_errno(NULL, NULL, errno, "Failed to read URL(s).");
|
|
||||||
}
|
|
||||||
|
|
||||||
free(urls);
|
u32 size = 0;
|
||||||
} else {
|
if(remoteinstall_network_recvwait(networkData->clientSocket, &size, sizeof(size), 0) != sizeof(size)) {
|
||||||
error_display(NULL, NULL, "Failed to allocate URL buffer.");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
error_display(NULL, NULL, "Payload too large.");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
error_display_errno(NULL, NULL, errno, "Failed to read payload length.");
|
error_display_errno(NULL, NULL, errno, "Failed to read payload length.");
|
||||||
|
|
||||||
|
remoteinstall_network_close_client(data);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(sock);
|
size = ntohl(size);
|
||||||
|
if(size >= 128 * 1024) {
|
||||||
|
error_display(NULL, NULL, "Payload too large.");
|
||||||
|
|
||||||
|
remoteinstall_network_close_client(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* urls = (char*) calloc(size, sizeof(char));
|
||||||
|
if(urls == NULL) {
|
||||||
|
error_display(NULL, NULL, "Failed to allocate URL buffer.");
|
||||||
|
|
||||||
|
remoteinstall_network_close_client(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(remoteinstall_network_recvwait(networkData->clientSocket, urls, size, 0) != size) {
|
||||||
|
error_display_errno(NULL, NULL, errno, "Failed to read URL(s).");
|
||||||
|
|
||||||
|
free(urls);
|
||||||
|
remoteinstall_network_close_client(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteinstall_set_last_urls(urls);
|
||||||
|
action_url_install("Install from the received URL(s)?", urls, data, remoteinstall_network_close_client);
|
||||||
|
|
||||||
|
free(urls);
|
||||||
} else if(errno != EAGAIN) {
|
} else if(errno != EAGAIN) {
|
||||||
if(errno == 22 || errno == 115) {
|
if(errno == 22 || errno == 115) {
|
||||||
ui_pop();
|
ui_pop();
|
||||||
@ -355,9 +397,6 @@ void remoteinstall_receive_urls_network() {
|
|||||||
|
|
||||||
data->serverSocket = sock;
|
data->serverSocket = sock;
|
||||||
|
|
||||||
int bufSize = 1024 * 32;
|
|
||||||
setsockopt(data->serverSocket, SOL_SOCKET, SO_RCVBUF, &bufSize, sizeof(bufSize));
|
|
||||||
|
|
||||||
struct sockaddr_in server;
|
struct sockaddr_in server;
|
||||||
server.sin_family = AF_INET;
|
server.sin_family = AF_INET;
|
||||||
server.sin_port = htons(5000);
|
server.sin_port = htons(5000);
|
||||||
@ -393,7 +432,7 @@ void remoteinstall_manually_enter_urls() {
|
|||||||
if(swkbdInputText(&swkbd, textBuf, sizeof(textBuf)) == SWKBD_BUTTON_CONFIRM) {
|
if(swkbdInputText(&swkbd, textBuf, sizeof(textBuf)) == SWKBD_BUTTON_CONFIRM) {
|
||||||
remoteinstall_set_last_urls(textBuf);
|
remoteinstall_set_last_urls(textBuf);
|
||||||
|
|
||||||
action_url_install("Install from the entered URL(s)?", textBuf);
|
action_url_install("Install from the entered URL(s)?", textBuf, NULL, NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -401,7 +440,7 @@ void remoteinstall_manually_enter_urls() {
|
|||||||
void remoteinstall_repeat_last_request() {
|
void remoteinstall_repeat_last_request() {
|
||||||
char textBuf[4096];
|
char textBuf[4096];
|
||||||
if(remoteinstall_get_last_urls(textBuf, sizeof(textBuf))) {
|
if(remoteinstall_get_last_urls(textBuf, sizeof(textBuf))) {
|
||||||
action_url_install("Install from the last requested URL(s)?", textBuf);
|
action_url_install("Install from the last requested URL(s)?", textBuf, NULL, NULL);
|
||||||
} else {
|
} else {
|
||||||
prompt_display("Failure", "No previously requested URL(s) could be found.", COLOR_TEXT, false, NULL, NULL, NULL);
|
prompt_display("Failure", "No previously requested URL(s) could be found.", COLOR_TEXT, false, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user