Web workers
This commit is contained in:
parent
600d04eba9
commit
9004c4ed29
11 changed files with 811 additions and 643 deletions
196
Cargo.lock
generated
196
Cargo.lock
generated
|
@ -361,6 +361,22 @@ dependencies = [
|
|||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.2"
|
||||
|
@ -419,6 +435,15 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
|
||||
dependencies = [
|
||||
"instant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.17"
|
||||
|
@ -453,6 +478,21 @@ version = "1.0.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||
dependencies = [
|
||||
"foreign-types-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-shared"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.0.1"
|
||||
|
@ -766,6 +806,19 @@ dependencies = [
|
|||
"tokio-rustls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-tls"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"hyper",
|
||||
"native-tls",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.2.3"
|
||||
|
@ -787,6 +840,15 @@ dependencies = [
|
|||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.5.0"
|
||||
|
@ -941,6 +1003,24 @@ dependencies = [
|
|||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"openssl",
|
||||
"openssl-probe",
|
||||
"openssl-sys",
|
||||
"schannel",
|
||||
"security-framework",
|
||||
"security-framework-sys",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.1"
|
||||
|
@ -1053,7 +1133,7 @@ dependencies = [
|
|||
"js-sys",
|
||||
"mime_guess",
|
||||
"omegaupload-common",
|
||||
"reqwasm",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"tar",
|
||||
"tree_magic_mini",
|
||||
|
@ -1075,6 +1155,51 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"openssl-macros",
|
||||
"openssl-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-macros"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-probe"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.2.0"
|
||||
|
@ -1265,6 +1390,15 @@ version = "0.6.27"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reqwasm"
|
||||
version = "0.5.0"
|
||||
|
@ -1290,11 +1424,13 @@ dependencies = [
|
|||
"http-body",
|
||||
"hyper",
|
||||
"hyper-rustls",
|
||||
"hyper-tls",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"mime",
|
||||
"native-tls",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustls",
|
||||
|
@ -1303,6 +1439,7 @@ dependencies = [
|
|||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tokio-rustls",
|
||||
"tower-service",
|
||||
"url",
|
||||
|
@ -1381,6 +1518,16 @@ version = "1.0.10"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sct"
|
||||
version = "0.7.0"
|
||||
|
@ -1400,6 +1547,29 @@ dependencies = [
|
|||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
"security-framework-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework-sys"
|
||||
version = "2.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.140"
|
||||
|
@ -1571,6 +1741,20 @@ dependencies = [
|
|||
"xattr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"remove_dir_all",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.3"
|
||||
|
@ -1671,6 +1855,16 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-native-tls"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b"
|
||||
dependencies = [
|
||||
"native-tls",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.23.4"
|
||||
|
|
|
@ -294,18 +294,18 @@ impl From<Expiration> for HeaderValue {
|
|||
|
||||
pub struct ParseHeaderValueError;
|
||||
|
||||
#[cfg(feature = "wasm")]
|
||||
impl TryFrom<reqwasm::http::Headers> for Expiration {
|
||||
type Error = ParseHeaderValueError;
|
||||
// #[cfg(feature = "wasm")]
|
||||
// impl TryFrom<reqwest::header::HeaderMap<&str>> for Expiration {
|
||||
// type Error = ParseHeaderValueError;
|
||||
|
||||
fn try_from(headers: reqwasm::http::Headers) -> Result<Self, Self::Error> {
|
||||
headers
|
||||
.get(http::header::EXPIRES.as_str())
|
||||
.as_deref()
|
||||
.and_then(|v| Self::try_from(v).ok())
|
||||
.ok_or(ParseHeaderValueError)
|
||||
}
|
||||
}
|
||||
// fn try_from(headers: reqwest::header::HeaderMap) -> Result<Self, Self::Error> {
|
||||
// headers
|
||||
// .get(http::header::EXPIRES.as_str())
|
||||
// .as_deref()
|
||||
// .and_then(|v| Self::try_from(v).ok())
|
||||
// .ok_or(ParseHeaderValueError)
|
||||
// }
|
||||
// }
|
||||
|
||||
impl TryFrom<HeaderValue> for Expiration {
|
||||
type Error = ParseHeaderValueError;
|
||||
|
|
|
@ -19,7 +19,6 @@ gloo-console = "0.2.1"
|
|||
http = "0.2.8"
|
||||
js-sys = "0.3.59"
|
||||
mime_guess = "2.0.4"
|
||||
reqwasm = "0.5.0"
|
||||
tree_magic_mini = { version = "3.0.3", features = ["with-gpl-data"] }
|
||||
serde = { version = "1.0.140", features = ["derive"] }
|
||||
wasm-bindgen = { version = "0.2.82", features = ["serde-serialize"] }
|
||||
|
@ -27,6 +26,7 @@ wasm-bindgen-futures = "0.4.32"
|
|||
zip = { version = "0.6.2", default-features = false, features = ["deflate"] }
|
||||
flate2 = "1.0.24"
|
||||
tar = "0.4.38"
|
||||
reqwest = "0.11"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3.59"
|
||||
|
|
33
web/src/bg_encrypt.ts
Normal file
33
web/src/bg_encrypt.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
// OmegaUpload Web Frontend
|
||||
// Copyright (C) 2021 Edward Shen
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import { encrypt_array_buffer } from '../pkg';
|
||||
|
||||
interface BgData {
|
||||
location: string,
|
||||
data: any
|
||||
}
|
||||
|
||||
addEventListener('message', (event: MessageEvent<BgData>) => {
|
||||
let { location, data } = event.data;
|
||||
console.log('[js-worker] Sending data to rust in a worker thread...');
|
||||
encrypt_array_buffer(location, data).then(url => {
|
||||
console.log("done buffer");
|
||||
postMessage(url);
|
||||
}).catch(e => console.error(e));
|
||||
})
|
||||
|
||||
postMessage("init");
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
use std::{hint::unreachable_unchecked, marker::PhantomData};
|
||||
|
||||
use gloo_console::log;
|
||||
use js_sys::{Array, JsString, Object};
|
||||
use wasm_bindgen::JsValue;
|
||||
|
||||
|
@ -37,7 +38,10 @@ impl From<IdbObject<Ready>> for Object {
|
|||
Ok(o) => o,
|
||||
// SAFETY: IdbObject maintains the invariant that it can eventually
|
||||
// be constructed into a JS object.
|
||||
_ => unsafe { unreachable_unchecked() },
|
||||
_ => {
|
||||
log!("IdbObject invariant violated?!");
|
||||
unsafe { unreachable_unchecked() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
import { start } from '../pkg';
|
||||
import './main.scss';
|
||||
|
||||
start();
|
||||
|
||||
window.addEventListener("hashchange", () => location.reload());
|
||||
|
|
|
@ -24,17 +24,16 @@ use decrypt::{DecryptedData, MimeType};
|
|||
use gloo_console::{error, log};
|
||||
use http::uri::PathAndQuery;
|
||||
use http::{StatusCode, Uri};
|
||||
use js_sys::{Array, JsString, Object, Uint8Array};
|
||||
use js_sys::{Array, JsString, Object};
|
||||
use omegaupload_common::base64;
|
||||
use omegaupload_common::crypto::seal_in_place;
|
||||
use omegaupload_common::crypto::{Error as CryptoError, Key};
|
||||
use omegaupload_common::fragment::Builder;
|
||||
use omegaupload_common::secrecy::{ExposeSecret, Secret, SecretString, SecretVec};
|
||||
use omegaupload_common::{Expiration, PartialParsedUrl, Url};
|
||||
use reqwasm::http::Request;
|
||||
use wasm_bindgen::prelude::{wasm_bindgen, Closure};
|
||||
use wasm_bindgen::{JsCast, JsValue};
|
||||
use wasm_bindgen_futures::{spawn_local, JsFuture};
|
||||
use wasm_bindgen_futures::spawn_local;
|
||||
use web_sys::{Event, IdbObjectStore, IdbOpenDbRequest, IdbTransactionMode, Location, Window};
|
||||
|
||||
use crate::decrypt::decrypt;
|
||||
|
@ -173,51 +172,36 @@ pub fn start() {
|
|||
|
||||
#[wasm_bindgen]
|
||||
#[allow(clippy::future_not_send)]
|
||||
pub fn encrypt_string(data: String) {
|
||||
spawn_local(async move {
|
||||
if let Err(e) = do_encrypt(data.into_bytes()).await {
|
||||
log!(format!("[rs] Error encrypting string: {}", e));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
#[allow(clippy::future_not_send)]
|
||||
pub fn encrypt_array_buffer(data: Vec<u8>) {
|
||||
spawn_local(async move {
|
||||
if let Err(e) = do_encrypt(data).await {
|
||||
log!(format!("[rs] Error encrypting array buffer: {}", e));
|
||||
}
|
||||
});
|
||||
pub async fn encrypt_array_buffer(location: String, data: Vec<u8>) -> Result<JsString, JsString> {
|
||||
do_encrypt(location, data).await.map_err(|e| {
|
||||
log!(format!("[rs] Error encrypting array buffer: {}", e));
|
||||
JsString::from(e.to_string())
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(clippy::future_not_send)]
|
||||
async fn do_encrypt(mut data: Vec<u8>) -> Result<()> {
|
||||
async fn do_encrypt(location: String, mut data: Vec<u8>) -> Result<JsString> {
|
||||
let (data, key) = {
|
||||
let enc_key = seal_in_place(&mut data, None)?;
|
||||
let key = SecretString::new(base64::encode(&enc_key.expose_secret().as_ref()));
|
||||
(data, key)
|
||||
};
|
||||
|
||||
let s: String = location().to_string().into();
|
||||
let mut url = Url::from_str(&s)?;
|
||||
let mut url = Url::from_str(&location)?;
|
||||
let fragment = Builder::new(key);
|
||||
|
||||
let js_data = Uint8Array::new_with_length(u32::try_from(data.len()).expect("Data too large"));
|
||||
js_data.copy_from(&data);
|
||||
|
||||
let short_code = Request::post(url.as_ref())
|
||||
.body(js_data)
|
||||
let short_code = reqwest::Client::new()
|
||||
.post(url.as_ref())
|
||||
.body(data)
|
||||
.send()
|
||||
.await?
|
||||
.text()
|
||||
.await?;
|
||||
|
||||
url.set_path(&short_code);
|
||||
url.set_fragment(Some(fragment.build().expose_secret()));
|
||||
location()
|
||||
.set_href(url.as_ref())
|
||||
.expect("Unable to navigate to encrypted upload");
|
||||
Ok(())
|
||||
|
||||
Ok(JsString::from(url.as_ref()))
|
||||
}
|
||||
|
||||
#[allow(clippy::future_not_send)]
|
||||
|
@ -228,31 +212,26 @@ async fn fetch_resources(
|
|||
name: Option<String>,
|
||||
language: Option<String>,
|
||||
) -> Result<()> {
|
||||
match Request::get(&request_uri.to_string()).send().await {
|
||||
match reqwest::Client::new()
|
||||
.get(&request_uri.to_string())
|
||||
.send()
|
||||
.await
|
||||
{
|
||||
Ok(resp) if resp.status() == StatusCode::OK => {
|
||||
let expires = Expiration::try_from(resp.headers()).map_or_else(
|
||||
|_| "This item does not expire.".to_string(),
|
||||
|expires| expires.to_string(),
|
||||
);
|
||||
let expires = resp
|
||||
.headers()
|
||||
.get(http::header::EXPIRES)
|
||||
.and_then(|header| Expiration::try_from(header).ok())
|
||||
.map_or_else(
|
||||
|| "This item does not expire.".to_string(),
|
||||
|expires| expires.to_string(),
|
||||
);
|
||||
|
||||
let data = {
|
||||
let data_fut = resp
|
||||
.as_raw()
|
||||
.array_buffer()
|
||||
.expect("to get raw bytes from a response");
|
||||
let data = match JsFuture::from(data_fut).await {
|
||||
Ok(data) => data,
|
||||
Err(e) => {
|
||||
render_message(
|
||||
"Network failure: Failed to completely read encryption paste.".into(),
|
||||
);
|
||||
bail!(format!(
|
||||
"JsFuture returned an error while fetching resp buffer: {e:?}",
|
||||
));
|
||||
}
|
||||
};
|
||||
Uint8Array::new(&data).to_vec()
|
||||
};
|
||||
let data = resp
|
||||
.bytes()
|
||||
.await
|
||||
.expect("to get raw bytes from a response")
|
||||
.to_vec();
|
||||
|
||||
if data.len() as u128 > DOWNLOAD_SIZE_LIMIT {
|
||||
render_message("The paste is too large to decrypt from the web browser. You must use the CLI tool to download this paste.".into());
|
||||
|
@ -300,7 +279,7 @@ async fn fetch_resources(
|
|||
render_message("Invalid paste URL.".into());
|
||||
}
|
||||
Ok(err) => {
|
||||
render_message(err.status_text().into());
|
||||
render_message(err.status().as_str().into());
|
||||
}
|
||||
Err(err) => {
|
||||
render_message(format!("{err}").into());
|
||||
|
|
|
@ -40,6 +40,7 @@ hr {
|
|||
main {
|
||||
display: inline-flex;
|
||||
min-width: 100%;
|
||||
max-width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
|
@ -121,11 +122,9 @@ textarea {
|
|||
.button {
|
||||
@extend .hljs;
|
||||
|
||||
border: 1px solid white;
|
||||
border-radius: $padding;
|
||||
padding: $padding;
|
||||
margin: $padding;
|
||||
font-size: 16px;
|
||||
text-decoration: underline;
|
||||
border: none;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
|
|
|
@ -14,28 +14,29 @@
|
|||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import './main.scss';
|
||||
import ReactDom from 'react-dom';
|
||||
import React, { useState } from 'react';
|
||||
import { encrypt_string, encrypt_array_buffer } from '../pkg';
|
||||
|
||||
import hljs from 'highlight.js'
|
||||
(window as any).hljs = hljs;
|
||||
require('highlightjs-line-numbers.js');
|
||||
let hljs;
|
||||
if (typeof WorkerGlobalScope === 'undefined' || !(self instanceof WorkerGlobalScope)) {
|
||||
hljs = require('highlight.js');
|
||||
(window as any).hljs = hljs;
|
||||
require('highlightjs-line-numbers.js');
|
||||
}
|
||||
|
||||
|
||||
const FileForm = () => {
|
||||
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
let file = event.target.files![0];
|
||||
const fr = new FileReader();
|
||||
fr.onload = (_e) => {
|
||||
let data = new Uint8Array(fr.result as ArrayBuffer);
|
||||
encrypt_array_buffer(data);
|
||||
encryptMessage(new Uint8Array(fr.result as ArrayBuffer));
|
||||
}
|
||||
fr.readAsArrayBuffer(file);
|
||||
}
|
||||
|
||||
return <>
|
||||
<label className="file-upload" >
|
||||
<label className="file-upload hljs-meta" >
|
||||
Select a file
|
||||
<input type="file" onChange={handleChange} />
|
||||
</label>
|
||||
|
@ -43,12 +44,14 @@ const FileForm = () => {
|
|||
}
|
||||
|
||||
const PasteForm = () => {
|
||||
const [value, setValue] = useState("");
|
||||
const [data, setValue] = useState("");
|
||||
|
||||
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
if (value.trim() !== "") {
|
||||
encrypt_string(value);
|
||||
if (data.trim() !== "") {
|
||||
encryptMessage(new TextEncoder().encode(data));
|
||||
} else {
|
||||
console.log("[js] Not sending string because it was empty.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,14 +59,28 @@ const PasteForm = () => {
|
|||
<form className='hljs centered' onSubmit={handleSubmit}>
|
||||
<textarea
|
||||
placeholder="すいちゃんは~ 今日もかわい~!!"
|
||||
value={value}
|
||||
value={data}
|
||||
onChange={(e) => setValue(e.target.value)}
|
||||
/>
|
||||
<input className="text-upload" type="submit" value="submit" />
|
||||
<input className="text-upload hljs-meta" type="submit" value="Submit" />
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
function encryptMessage(data: Uint8Array) {
|
||||
const worker = new Worker(new URL('./bg_encrypt.ts', import.meta.url));
|
||||
worker.onmessage = (event: MessageEvent<string>) => {
|
||||
console.log(event);
|
||||
if (event.data === 'init') {
|
||||
console.log("[js] Sending data to worker");
|
||||
const message = { data, location: window.location.toString() };
|
||||
worker.postMessage(message, [message.data.buffer]);
|
||||
} else {
|
||||
window.location.assign(event.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createUploadUi() {
|
||||
const html = <main className='hljs centered fullscreen'>
|
||||
<FileForm />
|
||||
|
@ -149,7 +166,7 @@ function loadFromDb(mimeType: string, name?: string, language?: string) {
|
|||
};
|
||||
}
|
||||
|
||||
function createStringPasteUi(data, mimeType: string, name: string, lang?: string) {
|
||||
function createStringPasteUi(data, mimeType: string, name: string, lang?: string, skipSyntaxHighlight?: boolean) {
|
||||
const html = <main>
|
||||
<pre className='paste'>
|
||||
<p className='unselectable centered'>{data.expiration}</p>
|
||||
|
@ -165,6 +182,10 @@ function createStringPasteUi(data, mimeType: string, name: string, lang?: string
|
|||
|
||||
ReactDom.render(html, document.body);
|
||||
|
||||
if (skipSyntaxHighlight) {
|
||||
return;
|
||||
}
|
||||
|
||||
let languages = undefined;
|
||||
|
||||
if (!hljs.getLanguage(lang)) {
|
||||
|
@ -203,6 +224,7 @@ function createStringPasteUi(data, mimeType: string, name: string, lang?: string
|
|||
}
|
||||
|
||||
// If we still haven't set languages here, then we're leaving it up to the
|
||||
// library
|
||||
if (!languages) {
|
||||
console.log("[js] Deferring to hljs inference for syntax highlighting.");
|
||||
} else {
|
||||
|
@ -226,7 +248,7 @@ function createBlobPasteUi(data, name: string) {
|
|||
<p className='display-anyways hljs-comment' onClick={() => {
|
||||
data.data.text().then(text => {
|
||||
data.data = text;
|
||||
createStringPasteUi(data, "application/octet-stream", name);
|
||||
createStringPasteUi(data, "application/octet-stream", name, undefined, true);
|
||||
})
|
||||
}}>Display anyways?</p>
|
||||
</main>;
|
||||
|
@ -337,6 +359,5 @@ function getObjectUrl(data, mimeType?: string) {
|
|||
return URL.createObjectURL(new Blob([data], { type: mimeType }));
|
||||
}
|
||||
|
||||
window.addEventListener("hashchange", () => location.reload());
|
||||
|
||||
export { renderMessage, createUploadUi, loadFromDb };
|
||||
|
|
2
web/vendor/MPLUS_FONTS
vendored
2
web/vendor/MPLUS_FONTS
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 8690be3625964d9992e7be4bc3e1a61a80161cc6
|
||||
Subproject commit a1268635894c5ee23dfdece570418ca07b66c3fc
|
Loading…
Reference in a new issue