Format code

This commit is contained in:
Nicola Benaglia 2025-05-13 06:15:26 +02:00
parent 035142504b
commit 452c3a0894
12 changed files with 502 additions and 449 deletions

View File

@ -1,5 +1,5 @@
import { useCallback, useContext, useEffect, useState } from 'react'; import { useCallback, useContext, useEffect, useState } from 'react';
import Logo2 from '../assets/svgs/Logo2.svg'; import Logo2 from '../../assets/svgs/Logo2.svg';
import { import {
MyContext, MyContext,
getArbitraryEndpointReact, getArbitraryEndpointReact,

View File

@ -7,22 +7,25 @@ const keysToEncrypt = ['keyPair'];
async function initializeKeyAndIV() { async function initializeKeyAndIV() {
if (!inMemoryKey) { if (!inMemoryKey) {
inMemoryKey = await generateKey(); // Generates the key in memory inMemoryKey = await generateKey(); // Generates the key in memory
} }
} }
async function generateKey(): Promise<CryptoKey> { async function generateKey(): Promise<CryptoKey> {
return await crypto.subtle.generateKey( return await crypto.subtle.generateKey(
{ {
name: "AES-GCM", name: 'AES-GCM',
length: 256 length: 256,
}, },
true, true,
["encrypt", "decrypt"] ['encrypt', 'decrypt']
); );
} }
async function encryptData(data: string, key: CryptoKey): Promise<{ iv: Uint8Array; encryptedData: ArrayBuffer }> { async function encryptData(
data: string,
key: CryptoKey
): Promise<{ iv: Uint8Array; encryptedData: ArrayBuffer }> {
const encoder = new TextEncoder(); const encoder = new TextEncoder();
const encodedData = encoder.encode(data); const encodedData = encoder.encode(data);
@ -31,8 +34,8 @@ async function encryptData(data: string, key: CryptoKey): Promise<{ iv: Uint8Arr
const encryptedData = await crypto.subtle.encrypt( const encryptedData = await crypto.subtle.encrypt(
{ {
name: "AES-GCM", name: 'AES-GCM',
iv: iv iv: iv,
}, },
key, key,
encodedData encodedData
@ -41,11 +44,15 @@ async function encryptData(data: string, key: CryptoKey): Promise<{ iv: Uint8Arr
return { iv, encryptedData }; return { iv, encryptedData };
} }
async function decryptData(encryptedData: ArrayBuffer, key: CryptoKey, iv: Uint8Array): Promise<string> { async function decryptData(
encryptedData: ArrayBuffer,
key: CryptoKey,
iv: Uint8Array
): Promise<string> {
const decryptedData = await crypto.subtle.decrypt( const decryptedData = await crypto.subtle.decrypt(
{ {
name: "AES-GCM", name: 'AES-GCM',
iv: iv iv: iv,
}, },
key, key,
encryptedData encryptedData
@ -83,7 +90,10 @@ export const storeData = async (key: string, payload: any): Promise<string> => {
const { iv, encryptedData } = await encryptData(base64Data, inMemoryKey); const { iv, encryptedData } = await encryptData(base64Data, inMemoryKey);
// Combine IV and encrypted data into a single Uint8Array // Combine IV and encrypted data into a single Uint8Array
const combinedData = new Uint8Array([...iv, ...new Uint8Array(encryptedData)]); const combinedData = new Uint8Array([
...iv,
...new Uint8Array(encryptedData),
]);
const encryptedBase64Data = btoa(String.fromCharCode(...combinedData)); const encryptedBase64Data = btoa(String.fromCharCode(...combinedData));
await SecureStoragePlugin.set({ key, value: encryptedBase64Data }); await SecureStoragePlugin.set({ key, value: encryptedBase64Data });
} else { } else {
@ -91,10 +101,9 @@ export const storeData = async (key: string, payload: any): Promise<string> => {
await SecureStoragePlugin.set({ key, value: base64Data }); await SecureStoragePlugin.set({ key, value: base64Data });
} }
return "Data saved successfully"; return 'Data saved successfully';
}; };
export const getData = async <T = any>(key: string): Promise<T | null> => { export const getData = async <T = any>(key: string): Promise<T | null> => {
await initializeKeyAndIV(); await initializeKeyAndIV();
@ -105,13 +114,17 @@ export const getData = async <T = any>(key: string): Promise<T | null> => {
if (keysToEncrypt.includes(key) && inMemoryKey) { if (keysToEncrypt.includes(key) && inMemoryKey) {
// Decode the Base64-encoded encrypted data // Decode the Base64-encoded encrypted data
const combinedData = atob(storedDataBase64.value) const combinedData = atob(storedDataBase64.value)
.split("") .split('')
.map((c) => c.charCodeAt(0)); .map((c) => c.charCodeAt(0));
const iv = new Uint8Array(combinedData.slice(0, 12)); // First 12 bytes are the IV const iv = new Uint8Array(combinedData.slice(0, 12)); // First 12 bytes are the IV
const encryptedData = new Uint8Array(combinedData.slice(12)).buffer; const encryptedData = new Uint8Array(combinedData.slice(12)).buffer;
const decryptedBase64Data = await decryptData(encryptedData, inMemoryKey, iv); const decryptedBase64Data = await decryptData(
encryptedData,
inMemoryKey,
iv
);
return base64ToJson(decryptedBase64Data); return base64ToJson(decryptedBase64Data);
} else { } else {
// Decode non-encrypted data // Decode non-encrypted data
@ -121,21 +134,21 @@ export const getData = async <T = any>(key: string): Promise<T | null> => {
return null; return null;
} }
} catch (error) { } catch (error) {
return null return null;
} }
}; };
// Remove keys from storage and log out // Remove keys from storage and log out
export async function removeKeysAndLogout(keys: string[], event: MessageEvent, request: any) { export async function removeKeysAndLogout(
keys: string[],
event: MessageEvent,
request: any
) {
try { try {
for (const key of keys) { for (const key of keys) {
try { try {
await SecureStoragePlugin.remove({ key }); await SecureStoragePlugin.remove({ key });
await SecureStoragePlugin.remove({ key: `${key}_iv` }); // Remove associated IV await SecureStoragePlugin.remove({ key: `${key}_iv` }); // Remove associated IV
} catch (error) { } catch (error) {
console.warn(`Key not found: ${key}`); console.warn(`Key not found: ${key}`);
} }
@ -144,13 +157,13 @@ export async function removeKeysAndLogout(keys: string[], event: MessageEvent, r
event.source.postMessage( event.source.postMessage(
{ {
requestId: request.requestId, requestId: request.requestId,
action: "logout", action: 'logout',
payload: true, payload: true,
type: "backgroundMessageResponse", type: 'backgroundMessageResponse',
}, },
event.origin event.origin
); );
} catch (error) { } catch (error) {
console.error("Error removing keys:", error); console.error('Error removing keys:', error);
} }
} }

View File

@ -1,31 +1,31 @@
export function decodeIfEncoded(input) { export function decodeIfEncoded(input) {
try { try {
// Check if input is URI-encoded by encoding and decoding // Check if input is URI-encoded by encoding and decoding
const encoded = encodeURIComponent(decodeURIComponent(input)); const encoded = encodeURIComponent(decodeURIComponent(input));
if (encoded === input) { if (encoded === input) {
// Input is URI-encoded, so decode it // Input is URI-encoded, so decode it
return decodeURIComponent(input); return decodeURIComponent(input);
}
} catch (e) {
// decodeURIComponent throws an error if input is not encoded
console.error("Error decoding URI:", e);
} }
} catch (e) {
// Return input as-is if not URI-encoded // decodeURIComponent throws an error if input is not encoded
return input; console.error('Error decoding URI:', e);
} }
export const isValidBase64 = (str: string): boolean => { // Return input as-is if not URI-encoded
if (typeof str !== "string" || str.length % 4 !== 0) return false; return input;
}
const base64Regex = /^[A-Za-z0-9+/]*={0,2}$/;
return base64Regex.test(str); export const isValidBase64 = (str: string): boolean => {
}; if (typeof str !== 'string' || str.length % 4 !== 0) return false;
export const isValidBase64WithDecode = (str: string): boolean => { const base64Regex = /^[A-Za-z0-9+/]*={0,2}$/;
try { return base64Regex.test(str);
return isValidBase64(str) && Boolean(atob(str)); };
} catch {
return false; export const isValidBase64WithDecode = (str: string): boolean => {
} try {
}; return isValidBase64(str) && Boolean(atob(str));
} catch {
return false;
}
};

View File

@ -1,38 +1,59 @@
// @ts-nocheck // @ts-nocheck
import Base58 from '../deps/Base58' import Base58 from '../deps/Base58';
import ed2curve from '../deps/ed2curve' import ed2curve from '../deps/ed2curve';
import nacl from '../deps/nacl-fast' import nacl from '../deps/nacl-fast';
import {Sha256} from 'asmcrypto.js' import { Sha256 } from 'asmcrypto.js';
export const decryptChatMessage = (
encryptedMessage,
privateKey,
recipientPublicKey,
lastReference
) => {
const test = encryptedMessage;
let _encryptedMessage = atob(encryptedMessage);
const binaryLength = _encryptedMessage.length;
const bytes = new Uint8Array(binaryLength);
export const decryptChatMessage = (encryptedMessage, privateKey, recipientPublicKey, lastReference) => { for (let i = 0; i < binaryLength; i++) {
const test = encryptedMessage bytes[i] = _encryptedMessage.charCodeAt(i);
let _encryptedMessage = atob(encryptedMessage) }
const binaryLength = _encryptedMessage.length
const bytes = new Uint8Array(binaryLength)
for (let i = 0; i < binaryLength; i++) { const _base58RecipientPublicKey =
bytes[i] = _encryptedMessage.charCodeAt(i) recipientPublicKey instanceof Uint8Array
} ? Base58.encode(recipientPublicKey)
: recipientPublicKey;
const _recipientPublicKey = Base58.decode(_base58RecipientPublicKey);
const _lastReference =
const _base58RecipientPublicKey = recipientPublicKey instanceof Uint8Array ? Base58.encode(recipientPublicKey) : recipientPublicKey lastReference instanceof Uint8Array
const _recipientPublicKey = Base58.decode(_base58RecipientPublicKey) ? lastReference
: Base58.decode(lastReference);
const _lastReference = lastReference instanceof Uint8Array ? lastReference : Base58.decode(lastReference) const convertedPrivateKey = ed2curve.convertSecretKey(privateKey);
const convertedPublicKey = ed2curve.convertPublicKey(_recipientPublicKey);
const sharedSecret = new Uint8Array(32);
nacl.lowlevel.crypto_scalarmult(
sharedSecret,
convertedPrivateKey,
convertedPublicKey
);
const convertedPrivateKey = ed2curve.convertSecretKey(privateKey) const _chatEncryptionSeed = new Sha256()
const convertedPublicKey = ed2curve.convertPublicKey(_recipientPublicKey) .process(sharedSecret)
const sharedSecret = new Uint8Array(32); .finish().result;
nacl.lowlevel.crypto_scalarmult(sharedSecret, convertedPrivateKey, convertedPublicKey) const _decryptedMessage = nacl.secretbox.open(
bytes,
_lastReference.slice(0, 24),
_chatEncryptionSeed
);
const _chatEncryptionSeed = new Sha256().process(sharedSecret).finish().result let decryptedMessage = '';
const _decryptedMessage = nacl.secretbox.open(bytes, _lastReference.slice(0, 24), _chatEncryptionSeed)
let decryptedMessage = '' _decryptedMessage === false
? decryptedMessage
: (decryptedMessage = new TextDecoder('utf-8').decode(_decryptedMessage));
_decryptedMessage === false ? decryptedMessage : decryptedMessage = new TextDecoder('utf-8').decode(_decryptedMessage) return decryptedMessage;
};
return decryptedMessage
}

View File

@ -1,33 +1,38 @@
// @ts-nocheck // @ts-nocheck
import { crypto } from '../constants/decryptWallet' import { crypto } from '../constants/decryptWallet';
import Base58 from '../deps/Base58' import Base58 from '../deps/Base58';
import {AES_CBC, HmacSha512} from 'asmcrypto.js' import { AES_CBC, HmacSha512 } from 'asmcrypto.js';
import { doInitWorkers, kdf } from '../deps/kdf' import { doInitWorkers, kdf } from '../deps/kdf';
export const decryptStoredWallet = async (password, wallet) => { export const decryptStoredWallet = async (password, wallet) => {
const threads = doInitWorkers(crypto.kdfThreads) const threads = doInitWorkers(crypto.kdfThreads);
const encryptedSeedBytes = Base58.decode(wallet.encryptedSeed) const encryptedSeedBytes = Base58.decode(wallet.encryptedSeed);
const iv = Base58.decode(wallet.iv) const iv = Base58.decode(wallet.iv);
const salt = Base58.decode(wallet.salt) const salt = Base58.decode(wallet.salt);
const key = await kdf(password, salt, threads) const key = await kdf(password, salt, threads);
const encryptionKey = key.slice(0, 32) const encryptionKey = key.slice(0, 32);
const macKey = key.slice(32, 63) const macKey = key.slice(32, 63);
const mac = new HmacSha512(macKey).process(encryptedSeedBytes).finish().result const mac = new HmacSha512(macKey)
if (Base58.encode(mac) !== wallet.mac) { .process(encryptedSeedBytes)
throw new Error("Incorrect password") .finish().result;
} if (Base58.encode(mac) !== wallet.mac) {
const decryptedBytes = AES_CBC.decrypt(encryptedSeedBytes, encryptionKey, false, iv) throw new Error('Incorrect password');
return decryptedBytes }
} const decryptedBytes = AES_CBC.decrypt(
encryptedSeedBytes,
encryptionKey,
false,
iv
);
return decryptedBytes;
};
export const decryptStoredWalletFromSeedPhrase = async (password) => { export const decryptStoredWalletFromSeedPhrase = async (password) => {
const threads = doInitWorkers(crypto.kdfThreads) const threads = doInitWorkers(crypto.kdfThreads);
const salt = new Uint8Array(void 0) const salt = new Uint8Array(void 0);
const seed = await kdf(password, salt, threads);
const seed = await kdf(password, salt, threads) return seed;
return seed };
}

View File

@ -1,11 +1,12 @@
export const executeEvent = (eventName: string, data: any)=> { export const executeEvent = (eventName: string, data: any) => {
const event = new CustomEvent(eventName, {detail: data}) const event = new CustomEvent(eventName, { detail: data });
document.dispatchEvent(event) document.dispatchEvent(event);
} };
export const subscribeToEvent = (eventName: string, listener: any)=> {
document.addEventListener(eventName, listener)
}
export const unsubscribeFromEvent = (eventName: string, listener: any)=> { export const subscribeToEvent = (eventName: string, listener: any) => {
document.removeEventListener(eventName, listener) document.addEventListener(eventName, listener);
} };
export const unsubscribeFromEvent = (eventName: string, listener: any) => {
document.removeEventListener(eventName, listener);
};

View File

@ -1,34 +1,28 @@
import moment from "moment"; export const delay = (time: number) =>
new Promise((_, reject) =>
export const delay = (time: number) => new Promise((_, reject) =>
setTimeout(() => reject(new Error('Request timed out')), time) setTimeout(() => reject(new Error('Request timed out')), time)
); );
// const originalHtml = `<p>---------- Forwarded message ---------</p><p>From: Alex</p><p>Date: Mon, Jun 9 2014 9:32 PM</p><p>Subject: Batteries </p><p>To: Jessica</p><p><br></p><p><br></p>`;
// export function updateMessageDetails(newFrom: string, newDateMillis: number, newTo: string) {
// let htmlString = originalHtml
// // Use Moment.js to format the date from milliseconds
// const formattedDate = moment(newDateMillis).format('ddd, MMM D YYYY h:mm A');
// // Replace the From, Date, and To fields in the HTML string
// htmlString = htmlString.replace(/<p>From:.*?<\/p>/, `<p>From: ${newFrom}</p>`);
// htmlString = htmlString.replace(/<p>Date:.*?<\/p>/, `<p>Date: ${formattedDate}</p>`);
// htmlString = htmlString.replace(/<p>To:.*?<\/p>/, `<p>To: ${newTo}</p>`);
// return htmlString;
// }
const originalHtml = `<p>---------- Forwarded message ---------</p><p>From: Alex</p><p>Subject: Batteries </p><p>To: Jessica</p><p><br></p><p><br></p>`; const originalHtml = `<p>---------- Forwarded message ---------</p><p>From: Alex</p><p>Subject: Batteries </p><p>To: Jessica</p><p><br></p><p><br></p>`;
export function updateMessageDetails(
newFrom: string,
newSubject: string,
newTo: string
) {
let htmlString = originalHtml;
export function updateMessageDetails(newFrom: string, newSubject: string, newTo: string) { htmlString = htmlString.replace(
let htmlString = originalHtml /<p>From:.*?<\/p>/,
`<p>From: ${newFrom}</p>`
);
htmlString = htmlString.replace(/<p>From:.*?<\/p>/, `<p>From: ${newFrom}</p>`); htmlString = htmlString.replace(
htmlString = htmlString.replace(/<p>Subject:.*?<\/p>/, `<p>Subject: ${newSubject}</p>`); /<p>Subject:.*?<\/p>/,
htmlString = htmlString.replace(/<p>To:.*?<\/p>/, `<p>To: ${newTo}</p>`); `<p>Subject: ${newSubject}</p>`
);
return htmlString; htmlString = htmlString.replace(/<p>To:.*?<\/p>/, `<p>To: ${newTo}</p>`);
}
return htmlString;
}

View File

@ -1,90 +1,107 @@
import { openIndexedDB } from "../components/Apps/useQortalMessageListener"; import { openIndexedDB } from '../components/Apps/useQortalMessageListener';
import { fileToBase64 } from "./fileReading"; import { fileToBase64 } from './fileReading';
export async function handleGetFileFromIndexedDB(event) { export async function handleGetFileFromIndexedDB(event) {
try { try {
const { fileId, requestId } = event.data; const { fileId, requestId } = event.data;
const db = await openIndexedDB(); const db = await openIndexedDB();
const transaction = db.transaction(["files"], "readonly"); const transaction = db.transaction(['files'], 'readonly');
const objectStore = transaction.objectStore("files"); const objectStore = transaction.objectStore('files');
const getRequest = objectStore.get(fileId);
getRequest.onsuccess = async function (event) {
if (getRequest.result) {
const file = getRequest.result.data;
try {
const base64String = await fileToBase64(file);
// Create a new transaction to delete the file
const deleteTransaction = db.transaction(["files"], "readwrite");
const deleteObjectStore = deleteTransaction.objectStore("files");
const deleteRequest = deleteObjectStore.delete(fileId);
deleteRequest.onsuccess = function () {
try {
const targetOrigin = window.location.origin;
window.postMessage( const getRequest = objectStore.get(fileId);
{ action: "getFileFromIndexedDBResponse", requestId, result: base64String },
targetOrigin
);
} catch (error) {
console.log('error', error)
}
};
deleteRequest.onerror = function () {
console.error(`Error deleting file with ID ${fileId} from IndexedDB`);
};
} catch (error) {
console.error("Error converting file to Base64:", error);
event.ports[0].postMessage({
result: null,
error: "Failed to convert file to Base64",
});
const targetOrigin = window.location.origin;
window.postMessage( getRequest.onsuccess = async function (event) {
{ action: "getFileFromIndexedDBResponse", requestId, result: null, if (getRequest.result) {
error: "Failed to convert file to Base64" const file = getRequest.result.data;
},
targetOrigin try {
const base64String = await fileToBase64(file);
// Create a new transaction to delete the file
const deleteTransaction = db.transaction(['files'], 'readwrite');
const deleteObjectStore = deleteTransaction.objectStore('files');
const deleteRequest = deleteObjectStore.delete(fileId);
deleteRequest.onsuccess = function () {
try {
const targetOrigin = window.location.origin;
window.postMessage(
{
action: 'getFileFromIndexedDBResponse',
requestId,
result: base64String,
},
targetOrigin
);
} catch (error) {
console.log('error', error);
}
};
deleteRequest.onerror = function () {
console.error(
`Error deleting file with ID ${fileId} from IndexedDB`
); );
} };
} else { } catch (error) {
console.error(`File with ID ${fileId} not found in IndexedDB`); console.error('Error converting file to Base64:', error);
event.ports[0].postMessage({
result: null,
error: 'Failed to convert file to Base64',
});
const targetOrigin = window.location.origin; const targetOrigin = window.location.origin;
window.postMessage( window.postMessage(
{ action: "getFileFromIndexedDBResponse", requestId, result: null, {
error: 'File not found in IndexedDB' action: 'getFileFromIndexedDBResponse',
}, requestId,
targetOrigin result: null,
error: 'Failed to convert file to Base64',
},
targetOrigin
); );
} }
}; } else {
console.error(`File with ID ${fileId} not found in IndexedDB`);
getRequest.onerror = function () { const targetOrigin = window.location.origin;
console.error(`Error retrieving file with ID ${fileId} from IndexedDB`);
window.postMessage(
event.source.postMessage( {
{ action: "getFileFromIndexedDBResponse", requestId, result: null, action: 'getFileFromIndexedDBResponse',
error: 'Error retrieving file from IndexedDB' requestId,
}, result: null,
event.origin error: 'File not found in IndexedDB',
},
targetOrigin
); );
}; }
} catch (error) { };
const { requestId } = event.data;
console.error("Error opening IndexedDB:", error); getRequest.onerror = function () {
console.error(`Error retrieving file with ID ${fileId} from IndexedDB`);
event.source.postMessage( event.source.postMessage(
{ action: "getFileFromIndexedDBResponse", requestId, result: null, {
error: 'Error opening IndexedDB' action: 'getFileFromIndexedDBResponse',
}, requestId,
result: null,
error: 'Error retrieving file from IndexedDB',
},
event.origin event.origin
); );
} };
} } catch (error) {
const { requestId } = event.data;
console.error('Error opening IndexedDB:', error);
event.source.postMessage(
{
action: 'getFileFromIndexedDBResponse',
requestId,
result: null,
error: 'Error opening IndexedDB',
},
event.origin
);
}
}

View File

@ -1,123 +1,125 @@
export const mimeToExtensionMap = { export const mimeToExtensionMap = {
// Documents // Documents
"application/pdf": ".pdf", 'application/pdf': '.pdf',
"application/msword": ".doc", 'application/msword': '.doc',
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": ".docx", 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
"application/vnd.ms-excel": ".xls", '.docx',
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": ".xlsx", 'application/vnd.ms-excel': '.xls',
"application/vnd.ms-powerpoint": ".ppt", 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': '.xlsx',
"application/vnd.openxmlformats-officedocument.presentationml.presentation": ".pptx", 'application/vnd.ms-powerpoint': '.ppt',
"application/vnd.oasis.opendocument.text": ".odt", 'application/vnd.openxmlformats-officedocument.presentationml.presentation':
"application/vnd.oasis.opendocument.spreadsheet": ".ods", '.pptx',
"application/vnd.oasis.opendocument.presentation": ".odp", 'application/vnd.oasis.opendocument.text': '.odt',
"text/plain": ".txt", 'application/vnd.oasis.opendocument.spreadsheet': '.ods',
"text/csv": ".csv", 'application/vnd.oasis.opendocument.presentation': '.odp',
"application/xhtml+xml": ".xhtml", 'text/plain': '.txt',
"application/xml": ".xml", 'text/csv': '.csv',
"application/rtf": ".rtf", 'application/xhtml+xml': '.xhtml',
"application/vnd.apple.pages": ".pages", 'application/xml': '.xml',
"application/vnd.google-apps.document": ".gdoc", 'application/rtf': '.rtf',
"application/vnd.google-apps.spreadsheet": ".gsheet", 'application/vnd.apple.pages': '.pages',
"application/vnd.google-apps.presentation": ".gslides", 'application/vnd.google-apps.document': '.gdoc',
'application/vnd.google-apps.spreadsheet': '.gsheet',
'application/vnd.google-apps.presentation': '.gslides',
// Images // Images
"image/jpeg": ".jpg", 'image/jpeg': '.jpg',
"image/png": ".png", 'image/png': '.png',
"image/gif": ".gif", 'image/gif': '.gif',
"image/webp": ".webp", 'image/webp': '.webp',
"image/svg+xml": ".svg", 'image/svg+xml': '.svg',
"image/tiff": ".tif", 'image/tiff': '.tif',
"image/bmp": ".bmp", 'image/bmp': '.bmp',
"image/x-icon": ".ico", 'image/x-icon': '.ico',
"image/heic": ".heic", 'image/heic': '.heic',
"image/heif": ".heif", 'image/heif': '.heif',
"image/apng": ".apng", 'image/apng': '.apng',
"image/avif": ".avif", 'image/avif': '.avif',
// Audio // Audio
"audio/mpeg": ".mp3", 'audio/mpeg': '.mp3',
"audio/ogg": ".ogg", 'audio/ogg': '.ogg',
"audio/wav": ".wav", 'audio/wav': '.wav',
"audio/webm": ".weba", 'audio/webm': '.weba',
"audio/aac": ".aac", 'audio/aac': '.aac',
"audio/flac": ".flac", 'audio/flac': '.flac',
"audio/x-m4a": ".m4a", 'audio/x-m4a': '.m4a',
"audio/x-ms-wma": ".wma", 'audio/x-ms-wma': '.wma',
"audio/midi": ".midi", 'audio/midi': '.midi',
"audio/x-midi": ".mid", 'audio/x-midi': '.mid',
// Video // Video
"video/mp4": ".mp4", 'video/mp4': '.mp4',
"video/webm": ".webm", 'video/webm': '.webm',
"video/ogg": ".ogv", 'video/ogg': '.ogv',
"video/x-msvideo": ".avi", 'video/x-msvideo': '.avi',
"video/quicktime": ".mov", 'video/quicktime': '.mov',
"video/x-ms-wmv": ".wmv", 'video/x-ms-wmv': '.wmv',
"video/mpeg": ".mpeg", 'video/mpeg': '.mpeg',
"video/3gpp": ".3gp", 'video/3gpp': '.3gp',
"video/3gpp2": ".3g2", 'video/3gpp2': '.3g2',
"video/x-matroska": ".mkv", 'video/x-matroska': '.mkv',
"video/x-flv": ".flv", 'video/x-flv': '.flv',
"video/x-ms-asf": ".asf", 'video/x-ms-asf': '.asf',
// Archives // Archives
"application/zip": ".zip", 'application/zip': '.zip',
"application/x-rar-compressed": ".rar", 'application/x-rar-compressed': '.rar',
"application/x-tar": ".tar", 'application/x-tar': '.tar',
"application/x-7z-compressed": ".7z", 'application/x-7z-compressed': '.7z',
"application/x-gzip": ".gz", 'application/x-gzip': '.gz',
"application/x-bzip2": ".bz2", 'application/x-bzip2': '.bz2',
"application/x-apple-diskimage": ".dmg", 'application/x-apple-diskimage': '.dmg',
"application/vnd.android.package-archive": ".apk", 'application/vnd.android.package-archive': '.apk',
"application/x-iso9660-image": ".iso", 'application/x-iso9660-image': '.iso',
// Code Files // Code Files
"text/javascript": ".js", 'text/javascript': '.js',
"text/css": ".css", 'text/css': '.css',
"text/html": ".html", 'text/html': '.html',
"application/json": ".json", 'application/json': '.json',
"text/xml": ".xml", 'text/xml': '.xml',
"application/x-sh": ".sh", 'application/x-sh': '.sh',
"application/x-csh": ".csh", 'application/x-csh': '.csh',
"text/x-python": ".py", 'text/x-python': '.py',
"text/x-java-source": ".java", 'text/x-java-source': '.java',
"application/java-archive": ".jar", 'application/java-archive': '.jar',
"application/vnd.microsoft.portable-executable": ".exe", 'application/vnd.microsoft.portable-executable': '.exe',
"application/x-msdownload": ".msi", 'application/x-msdownload': '.msi',
"text/x-c": ".c", 'text/x-c': '.c',
"text/x-c++": ".cpp", 'text/x-c++': '.cpp',
"text/x-go": ".go", 'text/x-go': '.go',
"application/x-perl": ".pl", 'application/x-perl': '.pl',
"text/x-php": ".php", 'text/x-php': '.php',
"text/x-ruby": ".rb", 'text/x-ruby': '.rb',
"text/x-sql": ".sql", 'text/x-sql': '.sql',
"application/x-httpd-php": ".php", 'application/x-httpd-php': '.php',
"application/x-python-code": ".pyc", 'application/x-python-code': '.pyc',
// ROM Files // ROM Files
"application/x-nintendo-nes-rom": ".nes", 'application/x-nintendo-nes-rom': '.nes',
"application/x-snes-rom": ".smc", 'application/x-snes-rom': '.smc',
"application/x-gameboy-rom": ".gb", 'application/x-gameboy-rom': '.gb',
"application/x-gameboy-advance-rom": ".gba", 'application/x-gameboy-advance-rom': '.gba',
"application/x-n64-rom": ".n64", 'application/x-n64-rom': '.n64',
"application/x-sega-genesis-rom": ".gen", 'application/x-sega-genesis-rom': '.gen',
"application/x-sega-master-system-rom": ".sms", 'application/x-sega-master-system-rom': '.sms',
"application/x-psx-rom": ".iso", // PlayStation ROMs 'application/x-psx-rom': '.iso', // PlayStation ROMs
"application/x-bios-rom": ".rom", 'application/x-bios-rom': '.rom',
"application/x-flash-rom": ".bin", 'application/x-flash-rom': '.bin',
"application/x-eeprom": ".eep", 'application/x-eeprom': '.eep',
"application/x-c64-rom": ".prg", 'application/x-c64-rom': '.prg',
// Miscellaneous // Miscellaneous
"application/octet-stream": ".bin", // General binary files 'application/octet-stream': '.bin', // General binary files
"application/x-shockwave-flash": ".swf", 'application/x-shockwave-flash': '.swf',
"application/x-silverlight-app": ".xap", 'application/x-silverlight-app': '.xap',
"application/x-ms-shortcut": ".lnk", 'application/x-ms-shortcut': '.lnk',
"application/vnd.ms-fontobject": ".eot", 'application/vnd.ms-fontobject': '.eot',
"font/woff": ".woff", 'font/woff': '.woff',
"font/woff2": ".woff2", 'font/woff2': '.woff2',
"font/ttf": ".ttf", 'font/ttf': '.ttf',
"font/otf": ".otf", 'font/otf': '.otf',
"application/vnd.visio": ".vsd", 'application/vnd.visio': '.vsd',
"application/vnd.ms-project": ".mpp", 'application/vnd.ms-project': '.mpp',
}; };

View File

@ -1,56 +1,57 @@
import moment from "moment" import moment from 'moment';
export function formatTimestamp(timestamp: number): string { export function formatTimestamp(timestamp: number): string {
const now = moment() const now = moment();
const timestampMoment = moment(timestamp) const timestampMoment = moment(timestamp);
const elapsedTime = now.diff(timestampMoment, 'minutes') const elapsedTime = now.diff(timestampMoment, 'minutes');
if (elapsedTime < 1) { if (elapsedTime < 1) {
return 'Just now' return 'Just now';
} else if (elapsedTime < 60) { } else if (elapsedTime < 60) {
return `${elapsedTime}m ago` return `${elapsedTime}m ago`;
} else if (elapsedTime < 1440) { } else if (elapsedTime < 1440) {
return `${Math.floor(elapsedTime / 60)}h ago` return `${Math.floor(elapsedTime / 60)}h ago`;
} else { } else {
return timestampMoment.format('MMM D, YYYY') return timestampMoment.format('MMM D, YYYY');
}
} }
export function formatTimestampForum(timestamp: number): string {
const now = moment();
const timestampMoment = moment(timestamp);
const elapsedTime = now.diff(timestampMoment, 'minutes');
if (elapsedTime < 1) {
return `Just now - ${timestampMoment.format('h:mm A')}`;
} else if (elapsedTime < 60) {
return `${elapsedTime}m ago - ${timestampMoment.format('h:mm A')}`;
} else if (elapsedTime < 1440) {
return `${Math.floor(elapsedTime / 60)}h ago - ${timestampMoment.format('h:mm A')}`;
} else {
return timestampMoment.format('MMM D, YYYY - h:mm A');
}
} }
export const formatDate = (unixTimestamp: number): string => { export function formatTimestampForum(timestamp: number): string {
const date = moment(unixTimestamp, 'x').fromNow() const now = moment();
const timestampMoment = moment(timestamp);
return date const elapsedTime = now.diff(timestampMoment, 'minutes');
}
export function sortArrayByTimestampAndGroupName(array) { if (elapsedTime < 1) {
return array.sort((a, b) => { return `Just now - ${timestampMoment.format('h:mm A')}`;
if (a.timestamp && b.timestamp) { } else if (elapsedTime < 60) {
// Both have timestamp, sort by timestamp descending return `${elapsedTime}m ago - ${timestampMoment.format('h:mm A')}`;
return b.timestamp - a.timestamp; } else if (elapsedTime < 1440) {
} else if (a.timestamp) { return `${Math.floor(elapsedTime / 60)}h ago - ${timestampMoment.format('h:mm A')}`;
// Only `a` has timestamp, it comes first } else {
return -1; return timestampMoment.format('MMM D, YYYY - h:mm A');
} else if (b.timestamp) { }
// Only `b` has timestamp, it comes first }
return 1;
} else { export const formatDate = (unixTimestamp: number): string => {
// Neither has timestamp, sort alphabetically by groupName const date = moment(unixTimestamp, 'x').fromNow();
return a.groupName.localeCompare(b.groupName);
} return date;
}); };
}
export function sortArrayByTimestampAndGroupName(array) {
return array.sort((a, b) => {
if (a.timestamp && b.timestamp) {
// Both have timestamp, sort by timestamp descending
return b.timestamp - a.timestamp;
} else if (a.timestamp) {
// Only `a` has timestamp, it comes first
return -1;
} else if (b.timestamp) {
// Only `b` has timestamp, it comes first
return 1;
} else {
// Neither has timestamp, sort alphabetically by groupName
return a.groupName.localeCompare(b.groupName);
}
});
}

View File

@ -1,55 +1,55 @@
// @ts-nocheck // @ts-nocheck
const utils = { const utils = {
int32ToBytes (word) { int32ToBytes(word) {
var byteArray = [] var byteArray = [];
for (var b = 0; b < 32; b += 8) { for (var b = 0; b < 32; b += 8) {
byteArray.push((word >>> (24 - b % 32)) & 0xFF) byteArray.push((word >>> (24 - (b % 32))) & 0xff);
}
return byteArray
},
stringtoUTF8Array (message) {
if (typeof message === 'string') {
var s = unescape(encodeURIComponent(message)) // UTF-8
message = new Uint8Array(s.length)
for (var i = 0; i < s.length; i++) {
message[i] = s.charCodeAt(i) & 0xff
}
}
return message
},
// ...buffers then buffers.foreach and append to buffer1
appendBuffer (buffer1, buffer2) {
buffer1 = new Uint8Array(buffer1)
buffer2 = new Uint8Array(buffer2)
const tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength)
tmp.set(buffer1, 0)
tmp.set(buffer2, buffer1.byteLength)
return tmp
},
int64ToBytes (int64) {
// we want to represent the input as a 8-bytes array
var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]
for (var index = 0; index < byteArray.length; index++) {
var byte = int64 & 0xff
byteArray[byteArray.length - index - 1] = byte
int64 = (int64 - byte) / 256
}
return byteArray
},
equal (buf1, buf2) {
if (buf1.byteLength != buf2.byteLength) return false
var dv1 = new Uint8Array(buf1)
var dv2 = new Uint8Array(buf2)
for (var i = 0; i != buf1.byteLength; i++) {
if (dv1[i] != dv2[i]) return false
}
return true
} }
} return byteArray;
},
export default utils stringtoUTF8Array(message) {
if (typeof message === 'string') {
var s = unescape(encodeURIComponent(message)); // UTF-8
message = new Uint8Array(s.length);
for (var i = 0; i < s.length; i++) {
message[i] = s.charCodeAt(i) & 0xff;
}
}
return message;
},
// ...buffers then buffers.foreach and append to buffer1
appendBuffer(buffer1, buffer2) {
buffer1 = new Uint8Array(buffer1);
buffer2 = new Uint8Array(buffer2);
const tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
tmp.set(buffer1, 0);
tmp.set(buffer2, buffer1.byteLength);
return tmp;
},
int64ToBytes(int64) {
// we want to represent the input as a 8-bytes array
var byteArray = [0, 0, 0, 0, 0, 0, 0, 0];
for (var index = 0; index < byteArray.length; index++) {
var byte = int64 & 0xff;
byteArray[byteArray.length - index - 1] = byte;
int64 = (int64 - byte) / 256;
}
return byteArray;
},
equal(buf1, buf2) {
if (buf1.byteLength != buf2.byteLength) return false;
var dv1 = new Uint8Array(buf1);
var dv2 = new Uint8Array(buf2);
for (var i = 0; i != buf1.byteLength; i++) {
if (dv1[i] != dv2[i]) return false;
}
return true;
},
};
export default utils;

View File

@ -1,21 +1,20 @@
// @ts-nocheck // @ts-nocheck
import Base58 from "../deps/Base58" import Base58 from '../deps/Base58';
export const validateAddress = (address) => { export const validateAddress = (address) => {
let isAddress = false let isAddress = false;
try { try {
const decodePubKey = Base58.decode(address) const decodePubKey = Base58.decode(address);
if (!(decodePubKey instanceof Uint8Array && decodePubKey.length == 25)) { if (!(decodePubKey instanceof Uint8Array && decodePubKey.length == 25)) {
isAddress = false isAddress = false;
} else { } else {
isAddress = true isAddress = true;
} }
} catch (error) {
} catch (error) { console.log(error);
}
}
return isAddress return isAddress;
} };