1
0
Fork 0
mirror of https://github.com/CorentinTh/it-tools.git synced 2025-08-09 07:25:18 +02:00
This commit is contained in:
sharevb 2024-07-14 20:43:12 +00:00 committed by GitHub
commit 9ff84803b6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 163 additions and 33 deletions

9
components.d.ts vendored
View file

@ -127,29 +127,22 @@ declare module '@vue/runtime-core' {
MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default'] MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default']
MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default'] MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default']
NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default'] NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default']
NCode: typeof import('naive-ui')['NCode']
NCollapseTransition: typeof import('naive-ui')['NCollapseTransition'] NCollapseTransition: typeof import('naive-ui')['NCollapseTransition']
NConfigProvider: typeof import('naive-ui')['NConfigProvider'] NConfigProvider: typeof import('naive-ui')['NConfigProvider']
NDivider: typeof import('naive-ui')['NDivider']
NEllipsis: typeof import('naive-ui')['NEllipsis'] NEllipsis: typeof import('naive-ui')['NEllipsis']
NFormItem: typeof import('naive-ui')['NFormItem']
NGi: typeof import('naive-ui')['NGi']
NGrid: typeof import('naive-ui')['NGrid']
NH1: typeof import('naive-ui')['NH1'] NH1: typeof import('naive-ui')['NH1']
NH3: typeof import('naive-ui')['NH3'] NH3: typeof import('naive-ui')['NH3']
NIcon: typeof import('naive-ui')['NIcon'] NIcon: typeof import('naive-ui')['NIcon']
NInputNumber: typeof import('naive-ui')['NInputNumber']
NLabel: typeof import('naive-ui')['NLabel']
NLayout: typeof import('naive-ui')['NLayout'] NLayout: typeof import('naive-ui')['NLayout']
NLayoutSider: typeof import('naive-ui')['NLayoutSider'] NLayoutSider: typeof import('naive-ui')['NLayoutSider']
NMenu: typeof import('naive-ui')['NMenu'] NMenu: typeof import('naive-ui')['NMenu']
NScrollbar: typeof import('naive-ui')['NScrollbar']
NSpin: typeof import('naive-ui')['NSpin'] NSpin: typeof import('naive-ui')['NSpin']
NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default'] NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default']
OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default'] OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default']
PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default'] PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default']
PdfSignatureChecker: typeof import('./src/tools/pdf-signature-checker/pdf-signature-checker.vue')['default'] PdfSignatureChecker: typeof import('./src/tools/pdf-signature-checker/pdf-signature-checker.vue')['default']
PdfSignatureDetails: typeof import('./src/tools/pdf-signature-checker/components/pdf-signature-details.vue')['default'] PdfSignatureDetails: typeof import('./src/tools/pdf-signature-checker/components/pdf-signature-details.vue')['default']
PdfUnlock: typeof import('./src/tools/pdf-unlock/pdf-unlock.vue')['default']
PercentageCalculator: typeof import('./src/tools/percentage-calculator/percentage-calculator.vue')['default'] PercentageCalculator: typeof import('./src/tools/percentage-calculator/percentage-calculator.vue')['default']
PhoneParserAndFormatter: typeof import('./src/tools/phone-parser-and-formatter/phone-parser-and-formatter.vue')['default'] PhoneParserAndFormatter: typeof import('./src/tools/phone-parser-and-formatter/phone-parser-and-formatter.vue')['default']
QrCodeGenerator: typeof import('./src/tools/qr-code-generator/qr-code-generator.vue')['default'] QrCodeGenerator: typeof import('./src/tools/qr-code-generator/qr-code-generator.vue')['default']

View file

@ -38,9 +38,11 @@
"@it-tools/bip39": "^0.0.4", "@it-tools/bip39": "^0.0.4",
"@it-tools/oggen": "^1.3.0", "@it-tools/oggen": "^1.3.0",
"@sindresorhus/slugify": "^2.2.1", "@sindresorhus/slugify": "^2.2.1",
"@tiptap/core": "2.1.12",
"@tiptap/pm": "2.1.6", "@tiptap/pm": "2.1.6",
"@tiptap/starter-kit": "2.1.6", "@tiptap/starter-kit": "2.1.6",
"@tiptap/vue-3": "2.0.3", "@tiptap/vue-3": "2.0.3",
"@types/emscripten": "^1.39.10",
"@types/figlet": "^1.5.8", "@types/figlet": "^1.5.8",
"@vicons/material": "^0.12.0", "@vicons/material": "^0.12.0",
"@vicons/tabler": "^0.12.0", "@vicons/tabler": "^0.12.0",
@ -64,7 +66,7 @@
"highlight.js": "^11.7.0", "highlight.js": "^11.7.0",
"iarna-toml-esm": "^3.0.5", "iarna-toml-esm": "^3.0.5",
"ibantools": "^4.3.3", "ibantools": "^4.3.3",
"js-base64": "^3.7.6", "js-base64": "^3.7.7",
"json5": "^2.2.3", "json5": "^2.2.3",
"jwt-decode": "^3.1.2", "jwt-decode": "^3.1.2",
"libphonenumber-js": "^1.10.28", "libphonenumber-js": "^1.10.28",
@ -80,6 +82,7 @@
"pdf-signature-reader": "^1.4.2", "pdf-signature-reader": "^1.4.2",
"pinia": "^2.0.34", "pinia": "^2.0.34",
"plausible-tracker": "^0.3.8", "plausible-tracker": "^0.3.8",
"qpdf-wasm-esm-embedded": "^1.1.1",
"qrcode": "^1.5.1", "qrcode": "^1.5.1",
"sql-formatter": "^13.0.0", "sql-formatter": "^13.0.0",
"ua-parser-js": "^1.0.35", "ua-parser-js": "^1.0.35",

40
pnpm-lock.yaml generated
View file

@ -14,6 +14,9 @@ dependencies:
'@sindresorhus/slugify': '@sindresorhus/slugify':
specifier: ^2.2.1 specifier: ^2.2.1
version: 2.2.1 version: 2.2.1
'@tiptap/core':
specifier: 2.1.12
version: 2.1.12(@tiptap/pm@2.1.6)
'@tiptap/pm': '@tiptap/pm':
specifier: 2.1.6 specifier: 2.1.6
version: 2.1.6 version: 2.1.6
@ -23,6 +26,9 @@ dependencies:
'@tiptap/vue-3': '@tiptap/vue-3':
specifier: 2.0.3 specifier: 2.0.3
version: 2.0.3(@tiptap/core@2.1.12)(@tiptap/pm@2.1.6)(vue@3.3.4) version: 2.0.3(@tiptap/core@2.1.12)(@tiptap/pm@2.1.6)(vue@3.3.4)
'@types/emscripten':
specifier: ^1.39.10
version: 1.39.10
'@types/figlet': '@types/figlet':
specifier: ^1.5.8 specifier: ^1.5.8
version: 1.5.8 version: 1.5.8
@ -93,7 +99,7 @@ dependencies:
specifier: ^4.3.3 specifier: ^4.3.3
version: 4.3.3 version: 4.3.3
js-base64: js-base64:
specifier: ^3.7.6 specifier: ^3.7.7
version: 3.7.7 version: 3.7.7
json5: json5:
specifier: ^2.2.3 specifier: ^2.2.3
@ -140,6 +146,9 @@ dependencies:
plausible-tracker: plausible-tracker:
specifier: ^0.3.8 specifier: ^0.3.8
version: 0.3.8 version: 0.3.8
qpdf-wasm-esm-embedded:
specifier: ^1.1.1
version: 1.1.1
qrcode: qrcode:
specifier: ^1.5.1 specifier: ^1.5.1
version: 1.5.1 version: 1.5.1
@ -2904,6 +2913,10 @@ packages:
'@types/trusted-types': 2.0.3 '@types/trusted-types': 2.0.3
dev: true dev: true
/@types/emscripten@1.39.10:
resolution: {integrity: sha512-TB/6hBkYQJxsZHSqyeuO1Jt0AB/bW6G7rHt9g7lML7SOF6lbgcHvw/Lr+69iqN0qxgXLhWKScAon73JNnptuDw==}
dev: false
/@types/estree@0.0.39: /@types/estree@0.0.39:
resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==}
dev: true dev: true
@ -3354,7 +3367,7 @@ packages:
dependencies: dependencies:
'@unhead/dom': 0.5.1 '@unhead/dom': 0.5.1
'@unhead/schema': 0.5.1 '@unhead/schema': 0.5.1
'@vueuse/shared': 10.8.0(vue@3.3.4) '@vueuse/shared': 10.11.0(vue@3.3.4)
unhead: 0.5.1 unhead: 0.5.1
vue: 3.3.4 vue: 3.3.4
transitivePeerDependencies: transitivePeerDependencies:
@ -3987,19 +4000,19 @@ packages:
- vue - vue
dev: false dev: false
/@vueuse/shared@10.3.0(vue@3.3.4): /@vueuse/shared@10.11.0(vue@3.3.4):
resolution: {integrity: sha512-kGqCTEuFPMK4+fNWy6dUOiYmxGcUbtznMwBZLC1PubidF4VZY05B+Oht7Jh7/6x4VOWGpvu3R37WHi81cKpiqg==} resolution: {integrity: sha512-fyNoIXEq3PfX1L3NkNhtVQUSRtqYwJtJg+Bp9rIzculIZWHTkKSysujrOk2J+NrRulLTQH9+3gGSfYLWSEWU1A==}
dependencies: dependencies:
vue-demi: 0.14.5(vue@3.3.4) vue-demi: 0.14.8(vue@3.3.4)
transitivePeerDependencies: transitivePeerDependencies:
- '@vue/composition-api' - '@vue/composition-api'
- vue - vue
dev: false dev: false
/@vueuse/shared@10.8.0(vue@3.3.4): /@vueuse/shared@10.3.0(vue@3.3.4):
resolution: {integrity: sha512-dUdy6zwHhULGxmr9YUg8e+EnB39gcM4Fe2oKBSrh3cOsV30JcMPtsyuspgFCUo5xxFNaeMf/W2yyKfST7Bg8oQ==} resolution: {integrity: sha512-kGqCTEuFPMK4+fNWy6dUOiYmxGcUbtznMwBZLC1PubidF4VZY05B+Oht7Jh7/6x4VOWGpvu3R37WHi81cKpiqg==}
dependencies: dependencies:
vue-demi: 0.14.7(vue@3.3.4) vue-demi: 0.14.5(vue@3.3.4)
transitivePeerDependencies: transitivePeerDependencies:
- '@vue/composition-api' - '@vue/composition-api'
- vue - vue
@ -7680,6 +7693,12 @@ packages:
engines: {node: '>=6'} engines: {node: '>=6'}
dev: true dev: true
/qpdf-wasm-esm-embedded@1.1.1:
resolution: {integrity: sha512-e6Pb8jRw+VflZQvsS+eOfYF9BqjubvTBnxJc44LhI1btg2WYNKE5/lGMmzWZ2gd9YrdWByf8IdNZw6S7+7t27w==}
dependencies:
'@types/emscripten': 1.39.10
dev: false
/qrcode@1.5.1: /qrcode@1.5.1:
resolution: {integrity: sha512-nS8NJ1Z3md8uTjKtP+SGGhfqmTCs5flU/xR623oI0JX+Wepz9R8UrRVCTBTJm3qGw3rH6jJ6MUHjkDx15cxSSg==} resolution: {integrity: sha512-nS8NJ1Z3md8uTjKtP+SGGhfqmTCs5flU/xR623oI0JX+Wepz9R8UrRVCTBTJm3qGw3rH6jJ6MUHjkDx15cxSSg==}
engines: {node: '>=10.13.0'} engines: {node: '>=10.13.0'}
@ -9158,8 +9177,8 @@ packages:
vue: 3.3.4 vue: 3.3.4
dev: false dev: false
/vue-demi@0.14.7(vue@3.3.4): /vue-demi@0.14.8(vue@3.3.4):
resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==} resolution: {integrity: sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==}
engines: {node: '>=12'} engines: {node: '>=12'}
hasBin: true hasBin: true
requiresBuild: true requiresBuild: true
@ -9449,6 +9468,7 @@ packages:
/workbox-google-analytics@7.0.0: /workbox-google-analytics@7.0.0:
resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==} resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==}
deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained
dependencies: dependencies:
workbox-background-sync: 7.0.0 workbox-background-sync: 7.0.0
workbox-core: 7.0.0 workbox-core: 7.0.0

View file

@ -1,6 +1,7 @@
import { extension as getExtensionFromMimeType, extension as getMimeTypeFromExtension } from 'mime-types'; import { extension as getExtensionFromMimeType, extension as getMimeTypeFromExtension } from 'mime-types';
import type { Ref } from 'vue'; import type { MaybeRef, Ref } from 'vue';
import _ from 'lodash'; import _ from 'lodash';
import { get } from '@vueuse/core';
export { export {
getMimeTypeFromBase64, getMimeTypeFromBase64,
@ -75,21 +76,11 @@ function downloadFromBase64({ sourceValue, filename, extension, fileMimeType }:
} }
function useDownloadFileFromBase64( function useDownloadFileFromBase64(
{ source, filename, extension, fileMimeType }:
{ source: Ref<string>; filename?: string; extension?: string; fileMimeType?: string }) {
return {
download() {
downloadFromBase64({ sourceValue: source.value, filename, extension, fileMimeType });
},
};
}
function useDownloadFileFromBase64Refs(
{ source, filename, extension }: { source, filename, extension }:
{ source: Ref<string>; filename?: Ref<string>; extension?: Ref<string> }) { { source: MaybeRef<string>; filename?: MaybeRef<string>; extension?: MaybeRef<string> }) {
return { return {
download() { download() {
downloadFromBase64({ sourceValue: source.value, filename: filename?.value, extension: extension?.value }); downloadFromBase64({ sourceValue: get(source), filename: get(filename), extension: get(extension) });
}, },
}; };
} }
@ -116,3 +107,13 @@ function previewImageFromBase64(base64String: string): HTMLImageElement {
return img; return img;
} }
function useDownloadFileFromBase64Refs(
{ source, filename, extension }:
{ source: Ref<string>; filename?: Ref<string>; extension?: Ref<string> }) {
return {
download() {
downloadFromBase64({ sourceValue: source.value, filename: filename?.value, extension: extension?.value });
},
};
}

View file

@ -81,11 +81,25 @@ import { tool as uuidGenerator } from './uuid-generator';
import { tool as macAddressLookup } from './mac-address-lookup'; import { tool as macAddressLookup } from './mac-address-lookup';
import { tool as xmlFormatter } from './xml-formatter'; import { tool as xmlFormatter } from './xml-formatter';
import { tool as yamlViewer } from './yaml-viewer'; import { tool as yamlViewer } from './yaml-viewer';
import { tool as pdfUnlock } from './pdf-unlock';
export const toolsByCategory: ToolCategory[] = [ export const toolsByCategory: ToolCategory[] = [
{ {
name: 'Crypto', name: 'Crypto',
components: [tokenGenerator, hashText, bcrypt, uuidGenerator, ulidGenerator, cypher, bip39, hmacGenerator, rsaKeyPairGenerator, passwordStrengthAnalyser, pdfSignatureChecker], components: [
tokenGenerator,
hashText,
bcrypt,
uuidGenerator,
ulidGenerator,
cypher,
bip39,
hmacGenerator,
rsaKeyPairGenerator,
passwordStrengthAnalyser,
pdfSignatureChecker,
pdfUnlock,
],
}, },
{ {
name: 'Converter', name: 'Converter',

View file

@ -0,0 +1,12 @@
import { LockOff } from '@vicons/tabler';
import { defineTool } from '../tool';
export const tool = defineTool({
name: 'Pdf Decrypt and Unlock',
path: '/pdf-unlock',
description: 'Decrypt a PDF and unlock (remove security permissions)',
keywords: ['pdf', 'unlock', 'decrypt'],
component: () => import('./pdf-unlock.vue'),
icon: LockOff,
createdAt: new Date('2024-01-09'),
});

View file

@ -0,0 +1,87 @@
<script setup lang="ts">
import { Base64 } from 'js-base64';
import createQPDFModule from 'qpdf-wasm-esm-embedded';
import { useDownloadFileFromBase64 } from '@/composable/downloadBase64';
const status = ref<'idle' | 'done' | 'error' | 'processing'>('idle');
const file = ref<File | null>(null);
const base64OutputPDF = ref('');
const fileName = ref('');
const logs = ref<string[]>([]);
const fileExtension = ref('pdf');
const { download } = useDownloadFileFromBase64(
{
source: base64OutputPDF,
filename: fileName,
extension: fileExtension,
});
async function onPDFFileUploaded(uploadedFile: File) {
file.value = uploadedFile;
const fileBuffer = await uploadedFile.arrayBuffer();
fileName.value = `decrypted_${uploadedFile.name}`;
status.value = 'processing';
try {
const outPdfBuffer = await callMainWithInOutPdf(fileBuffer,
[
'--decrypt',
'--warning-exit-0',
'--verbose',
'in.pdf',
'out.pdf',
],
0);
base64OutputPDF.value = `data:application/pdf;base64,${Base64.fromUint8Array(outPdfBuffer)}`;
status.value = 'done';
download();
}
catch (e) {
status.value = 'error';
}
}
async function callMainWithInOutPdf(data: ArrayBuffer, args: string[], expected_exitcode: number) {
logs.value = [];
const mod = await createQPDFModule({
print(text: string) {
logs.value.push(text);
},
printErr(text: string) {
logs.value.push(text);
},
});
mod.FS.writeFile('in.pdf', new Uint8Array(data));
const ret = mod.callMain(args);
if (expected_exitcode !== ret) {
throw new Error('Process run failed');
}
return mod.FS.readFile('out.pdf');
}
</script>
<template>
<div>
<div style="flex: 0 0 100%">
<div mx-auto max-w-600px>
<c-file-upload title="Drag and drop a PDF file here, or click to select a file" accept=".pdf" @file-upload="onPDFFileUploaded" />
</div>
</div>
<div mt-3 flex justify-center>
<c-alert v-if="status === 'error'" type="error">
An error occured processing {{ fileName }}
</c-alert>
<n-spin
v-if="status === 'processing'"
size="small"
/>
</div>
<c-card title="Logs">
<pre>{{ logs.join('\n') }}</pre>
</c-card>
</div>
</template>