From 2b4cd3fba71c2382a5cfab0549c8e173a457ebfb Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Sat, 6 Jan 2018 22:13:11 -0500 Subject: [PATCH] re-organize into "barrels". add utils service --- src/abstractions/index.ts | 4 + .../abstractions/messaging.service.ts | 0 .../abstractions/platformUtils.service.ts | 2 +- .../abstractions/storage.service.ts | 0 .../abstractions/utils.service.ts | 0 .../{cipherType.enum.ts => cipherType.ts} | 0 .../{deviceType.enum.ts => deviceType.ts} | 0 ...cryptionType.enum.ts => encryptionType.ts} | 0 src/enums/{fieldType.enum.ts => fieldType.ts} | 0 src/enums/index.ts | 5 + ...cureNoteType.enum.ts => secureNoteType.ts} | 0 src/globals.d.ts | 2 + src/index.ts | 13 +- src/services/index.ts | 1 + src/services/utils.service.ts | 155 ++++++++++++++++++ tsconfig.json | 1 - 16 files changed, 172 insertions(+), 11 deletions(-) create mode 100644 src/abstractions/index.ts rename src/{services => }/abstractions/messaging.service.ts (100%) rename src/{services => }/abstractions/platformUtils.service.ts (90%) rename src/{services => }/abstractions/storage.service.ts (100%) rename src/{services => }/abstractions/utils.service.ts (100%) rename src/enums/{cipherType.enum.ts => cipherType.ts} (100%) rename src/enums/{deviceType.enum.ts => deviceType.ts} (100%) rename src/enums/{encryptionType.enum.ts => encryptionType.ts} (100%) rename src/enums/{fieldType.enum.ts => fieldType.ts} (100%) create mode 100644 src/enums/index.ts rename src/enums/{secureNoteType.enum.ts => secureNoteType.ts} (100%) create mode 100644 src/globals.d.ts create mode 100644 src/services/index.ts create mode 100644 src/services/utils.service.ts diff --git a/src/abstractions/index.ts b/src/abstractions/index.ts new file mode 100644 index 0000000000..664cbb0dcf --- /dev/null +++ b/src/abstractions/index.ts @@ -0,0 +1,4 @@ +export { MessagingService } from './messaging.service'; +export { PlatformUtilsService } from './platformUtils.service'; +export { StorageService } from './storage.service'; +export { UtilsService } from './utils.service'; diff --git a/src/services/abstractions/messaging.service.ts b/src/abstractions/messaging.service.ts similarity index 100% rename from src/services/abstractions/messaging.service.ts rename to src/abstractions/messaging.service.ts diff --git a/src/services/abstractions/platformUtils.service.ts b/src/abstractions/platformUtils.service.ts similarity index 90% rename from src/services/abstractions/platformUtils.service.ts rename to src/abstractions/platformUtils.service.ts index 063c18dcdd..f4b29c23c5 100644 --- a/src/services/abstractions/platformUtils.service.ts +++ b/src/abstractions/platformUtils.service.ts @@ -1,4 +1,4 @@ -import { DeviceType } from '../../enums/deviceType.enum'; +import { DeviceType } from '../enums/deviceType.enum'; export interface PlatformUtilsService { getDevice(): DeviceType; diff --git a/src/services/abstractions/storage.service.ts b/src/abstractions/storage.service.ts similarity index 100% rename from src/services/abstractions/storage.service.ts rename to src/abstractions/storage.service.ts diff --git a/src/services/abstractions/utils.service.ts b/src/abstractions/utils.service.ts similarity index 100% rename from src/services/abstractions/utils.service.ts rename to src/abstractions/utils.service.ts diff --git a/src/enums/cipherType.enum.ts b/src/enums/cipherType.ts similarity index 100% rename from src/enums/cipherType.enum.ts rename to src/enums/cipherType.ts diff --git a/src/enums/deviceType.enum.ts b/src/enums/deviceType.ts similarity index 100% rename from src/enums/deviceType.enum.ts rename to src/enums/deviceType.ts diff --git a/src/enums/encryptionType.enum.ts b/src/enums/encryptionType.ts similarity index 100% rename from src/enums/encryptionType.enum.ts rename to src/enums/encryptionType.ts diff --git a/src/enums/fieldType.enum.ts b/src/enums/fieldType.ts similarity index 100% rename from src/enums/fieldType.enum.ts rename to src/enums/fieldType.ts diff --git a/src/enums/index.ts b/src/enums/index.ts new file mode 100644 index 0000000000..d1fff1d889 --- /dev/null +++ b/src/enums/index.ts @@ -0,0 +1,5 @@ +export { CipherType } from './cipherType'; +export { DeviceType } from './deviceType'; +export { EncryptionType } from './encryptionType'; +export { FieldType } from './fieldType'; +export { SecureNoteType } from './secureNoteType'; diff --git a/src/enums/secureNoteType.enum.ts b/src/enums/secureNoteType.ts similarity index 100% rename from src/enums/secureNoteType.enum.ts rename to src/enums/secureNoteType.ts diff --git a/src/globals.d.ts b/src/globals.d.ts new file mode 100644 index 0000000000..4859a0869e --- /dev/null +++ b/src/globals.d.ts @@ -0,0 +1,2 @@ +declare function escape(s: string): string; +declare function unescape(s: string): string; diff --git a/src/index.ts b/src/index.ts index 76e0a577cd..9d88a216d8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,5 @@ -export { CipherType } from './enums/cipherType.enum'; -export { DeviceType } from './enums/deviceType.enum'; -export { EncryptionType } from './enums/encryptionType.enum'; -export { FieldType } from './enums/fieldType.enum'; -export { SecureNoteType } from './enums/secureNoteType.enum'; +import * as Abstractions from './abstractions'; +import * as Enums from './enums'; +import * as Services from './services'; -export { MessagingService } from './services/abstractions/messaging.service'; -export { PlatformUtilsService } from './services/abstractions/platformUtils.service'; -export { StorageService } from './services/abstractions/storage.service'; -export { UtilsService } from './services/abstractions/utils.service'; +export { Abstractions, Enums, Services }; diff --git a/src/services/index.ts b/src/services/index.ts new file mode 100644 index 0000000000..f93851e07e --- /dev/null +++ b/src/services/index.ts @@ -0,0 +1 @@ +export { UtilsService } from './utils.service'; diff --git a/src/services/utils.service.ts b/src/services/utils.service.ts new file mode 100644 index 0000000000..359a743a91 --- /dev/null +++ b/src/services/utils.service.ts @@ -0,0 +1,155 @@ +import { UtilsService as UtilsServiceAbstraction } from '../abstractions/utils.service'; + +export class UtilsService implements UtilsServiceAbstraction { + static copyToClipboard(text: string, doc?: Document): void { + doc = doc || document; + if ((window as any).clipboardData && (window as any).clipboardData.setData) { + // IE specific code path to prevent textarea being shown while dialog is visible. + (window as any).clipboardData.setData('Text', text); + } else if (doc.queryCommandSupported && doc.queryCommandSupported('copy')) { + const textarea = doc.createElement('textarea'); + textarea.textContent = text; + // Prevent scrolling to bottom of page in MS Edge. + textarea.style.position = 'fixed'; + doc.body.appendChild(textarea); + textarea.select(); + + try { + // Security exception may be thrown by some browsers. + doc.execCommand('copy'); + } catch (e) { + // tslint:disable-next-line + console.warn('Copy to clipboard failed.', e); + } finally { + doc.body.removeChild(textarea); + } + } + } + + static urlBase64Decode(str: string): string { + let output = str.replace(/-/g, '+').replace(/_/g, '/'); + switch (output.length % 4) { + case 0: + break; + case 2: + output += '=='; + break; + case 3: + output += '='; + break; + default: + throw new Error('Illegal base64url string!'); + } + + return decodeURIComponent(escape(window.atob(output))); + } + + // ref: http://stackoverflow.com/a/2117523/1090359 + static newGuid(): string { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { + // tslint:disable-next-line + const r = Math.random() * 16 | 0; + // tslint:disable-next-line + const v = c === 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); + } + + // EFForg/OpenWireless + // ref https://github.com/EFForg/OpenWireless/blob/master/app/js/diceware.js + static secureRandomNumber(min: number, max: number): number { + let rval = 0; + const range = max - min + 1; + const bitsNeeded = Math.ceil(Math.log2(range)); + if (bitsNeeded > 53) { + throw new Error('We cannot generate numbers larger than 53 bits.'); + } + + const bytesNeeded = Math.ceil(bitsNeeded / 8); + const mask = Math.pow(2, bitsNeeded) - 1; + // 7776 -> (2^13 = 8192) -1 == 8191 or 0x00001111 11111111 + + // Create byte array and fill with N random numbers + const byteArray = new Uint8Array(bytesNeeded); + window.crypto.getRandomValues(byteArray); + + let p = (bytesNeeded - 1) * 8; + for (let i = 0; i < bytesNeeded; i++) { + rval += byteArray[i] * Math.pow(2, p); + p -= 8; + } + + // Use & to apply the mask and reduce the number of recursive lookups + // tslint:disable-next-line + rval = rval & mask; + + if (rval >= range) { + // Integer out of acceptable range + return UtilsService.secureRandomNumber(min, max); + } + + // Return an integer that falls within the range + return min + rval; + } + + static fromB64ToArray(str: string): Uint8Array { + const binaryString = window.atob(str); + const bytes = new Uint8Array(binaryString.length); + for (let i = 0; i < binaryString.length; i++) { + bytes[i] = binaryString.charCodeAt(i); + } + return bytes; + } + + static fromUtf8ToArray(str: string): Uint8Array { + const strUtf8 = unescape(encodeURIComponent(str)); + const arr = new Uint8Array(strUtf8.length); + for (let i = 0; i < strUtf8.length; i++) { + arr[i] = strUtf8.charCodeAt(i); + } + return arr; + } + + static fromBufferToB64(buffer: ArrayBuffer): string { + let binary = ''; + const bytes = new Uint8Array(buffer); + for (let i = 0; i < bytes.byteLength; i++) { + binary += String.fromCharCode(bytes[i]); + } + return window.btoa(binary); + } + + static fromBufferToUtf8(buffer: ArrayBuffer): string { + const bytes = new Uint8Array(buffer); + const encodedString = String.fromCharCode.apply(null, bytes); + return decodeURIComponent(escape(encodedString)); + } + + static getHostname(uriString: string): string { + if (uriString == null) { + return null; + } + + uriString = uriString.trim(); + if (uriString === '') { + return null; + } + + if (uriString.startsWith('http://') || uriString.startsWith('https://')) { + try { + const url = new URL(uriString); + return url.hostname; + } catch (e) { } + } + + return null; + } + + getHostname(uriString: string): string { + return UtilsService.getHostname(uriString); + } + + copyToClipboard(text: string, doc?: Document) { + UtilsService.copyToClipboard(text, doc); + } +} diff --git a/tsconfig.json b/tsconfig.json index 0db9afbea2..60f0d3494f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,7 +3,6 @@ "moduleResolution": "node", "target": "ES2016", "module": "es6", - "strict": true, "sourceMap": true, "declaration": true, "allowSyntheticDefaultImports": true,