diff --git a/README.md b/README.md index b75993f..0b1ea17 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,19 @@ # Decodapz ## @TODO +- [ ] Add history (store only decoded/ASCII values) - [ ] Add options for each encoder - [x] `Hex` - [x] Allow separator selection - [x] Allow prefix selection - [ ] `Base64` - [ ] Generalize in `BaseN` + - [ ] Allow custom charset (String or RegExp) - [ ] Allow charset selection from predefined charsets - [ ] Standard - [ ] URL-safe - [ ] All (bruteforce) - [ ] Research for more ... - - [ ] Allow custom charset (String or RegExp) - [ ] Add encoders - [ ] `RotX` - [x] `URL` @@ -23,7 +24,7 @@ - [x] Length in words (spaces) - [ ] CRC32 - [ ] Hashes - - [ ] MD5 + - [x] MD5 - [x] SHA-1 - [x] SHA-256 - [x] SHA-512 \ No newline at end of file diff --git a/bower.json b/bower.json deleted file mode 100644 index 2b033c9..0000000 --- a/bower.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "decodapz", - "description": "", - "main": "main.ts", - "authors": [ - "zM_ " - ], - "license": "MIT", - "homepage": "https://github.com/ZanyMonk/Decodapz", - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "test", - "tests" - ], - "dependencies": { - "crypto-js": "^4.1.1" - } -} diff --git a/src/components/AutoDecoder.vue b/src/components/AutoDecoder.vue index 0fcc40c..01bd9d0 100644 --- a/src/components/AutoDecoder.vue +++ b/src/components/AutoDecoder.vue @@ -14,6 +14,9 @@ + + + @@ -23,24 +26,26 @@ import { Tooltip } from 'bootstrap'; import TextSetting from './TextSetting.vue' +import DropdownSetting from './DropdownSetting.vue' import CheckboxSetting from './CheckboxSetting.vue' function pick(obj, predicate) { if (!obj || typeof obj !== 'object') return obj - const newObj = {}; + const newObj = {} for (const [name, value] of Object.entries(obj)) { if (!predicate(name, value)) continue newObj[name] = value } - return newObj; + return newObj } export default { name: 'AutoDecoder', components: { TextSetting, + DropdownSetting, CheckboxSetting }, props: { @@ -72,15 +77,15 @@ export default { this.hasError = false const decoded = await this.decode(this.encodedValue) - if (newValue === oldValue // Value has not changed + if ( newValue === oldValue // Value has not changed || newValue.length === decoded.length && newValue === decoded // Own modification - ) return; + ) return if (newValue === false) { - this.encodedValue = 'Could not decode'; - this.hasError = true; + this.encodedValue = 'Could not decode' + this.hasError = true } else { - this.encodedValue = await this.encode(newValue); + this.encodedValue = await this.encode(newValue) } } }, @@ -93,10 +98,10 @@ export default { }, async settingChanged(setting, value) { setting.value = value - this.encodedValue = await this.encode(this.value); + this.encodedValue = await this.encode(this.value) }, async valueChanged(value) { - if (value.length === this.value.length && value === this.value) return false; + if (value.length === this.value.length && value === this.value) return false this.hasError = false const decoded = await this.decode(value) @@ -104,8 +109,8 @@ export default { if (decoded === false) { this.hasError = true this.$emit('error') - return false; - } + return false + } else if (decoded === true) return this.$emit('value-changed', decoded) return decoded @@ -117,6 +122,9 @@ export default { }, booleanSettings() { return pick(this.encoder.settings, (name, setting) => setting.type === Boolean) + }, + complexSettings() { + return pick(this.encoder.settings, (name, setting) => setting.type === Object) } }, mounted() { diff --git a/src/components/CheckboxSetting.vue b/src/components/CheckboxSetting.vue index cd7cdad..5cd94a8 100644 --- a/src/components/CheckboxSetting.vue +++ b/src/components/CheckboxSetting.vue @@ -12,7 +12,7 @@ + + diff --git a/src/components/TextSetting.vue b/src/components/TextSetting.vue index 56122b3..747b794 100644 --- a/src/components/TextSetting.vue +++ b/src/components/TextSetting.vue @@ -1,23 +1,23 @@ @@ -67,17 +68,12 @@ export default { } button { - transition: all .5s; + transition: background-color .3s; padding: 0 2px; height: $setting-height; width: $setting-height; z-index: 2; - - &.open { - position: absolute; - left: 0; - border-radius: 3px 0 0 3px; - } + border-radius: .3rem; i { font-size: 16px; @@ -90,21 +86,27 @@ export default { } input { - position: absolute; - left: 0; - transition: all .5s, bottom .5s; height: $setting-height; - width: $setting-height; + width: 100%; font-size: 14px; border: 1px solid #d4d4d4; border-left: none; - border-radius: 5px 3px 3px 5px; - padding-left: $setting-height + 5px; + border-radius: 0 3px 3px 0; z-index: 1; + outline: none; + } + + + &.open { + position: absolute; + display: flex; + left: 0; + right: 0; + bottom: 0; - &:focus { - outline: none; - width: 100%; + button { + flex: 0 0 $setting-height; + border-radius: .2rem 0 0 .2rem; } } } diff --git a/src/encoders/base64.ts b/src/encoders/base64.ts index f5a1ae9..5ac4192 100644 --- a/src/encoders/base64.ts +++ b/src/encoders/base64.ts @@ -1,9 +1,70 @@ +function expandPattern(pattern: string) { + return pattern.replace(/[a-zA-Z0-9]-[a-zA-Z0-9]/g, (match) => { + const [a, b] = match.split('-').map((s) => s.charCodeAt(0)) + + if (a === b) return String.fromCharCode(a) + + const diff = a > b ? -1 : 1 + let result = '' + for (let i = a; diff > 0 ? i <= b : i >= b; i += diff) { + result += String.fromCharCode(i) + } + + return result + }) +} + +const STANDARD_PATTERN = 'A-Za-z0-9+/=' +const STANDARD_CHARSET = expandPattern(STANDARD_PATTERN) + module.exports = { + settings: { + mode: { + type: Object, + choices: { + standard: { + label: 'Standard (RFC 4648)', + charset: STANDARD_PATTERN + }, + urlSafe: { + label: 'URL safe (RFC 4648 ยง5)', + charset: 'A-Za-z0-9-_=' + } + } + } + }, + + translate(base64: string, fromCharset: string, toCharset: string) { + console.log(base64) + console.log(fromCharset) + console.log(toCharset) + // let noNull = false + + // Throw ? + if (fromCharset.length !== toCharset.length) return false + if (fromCharset === toCharset) return base64 + + const dict: {[index:string]: any} = {} + fromCharset.split('').forEach((from, index) => { + dict[from] = toCharset.charAt(index) + }) + + const translated = base64.replace(new RegExp('[' + fromCharset + ']', 'g'), (c) => dict[c] || c) + + // if (noNull) translated = translated.replace('=', '') + + return translated + }, + encode(string: string) { - return this.$libs.CryptoJS.enc.Base64.stringify(this.$libs.CryptoJS.enc.Utf8.parse(string)); + return this.translate( + this.$libs.CryptoJS.enc.Base64.stringify(this.$libs.CryptoJS.enc.Utf8.parse(string)), + STANDARD_CHARSET, + expandPattern((this.settings.mode.value || this.settings.mode.choices.standard).charset) + ) }, decode(string: string) { - return this.$libs.CryptoJS.enc.Base64.parse(string).toString(this.$libs.CryptoJS.enc.Utf8); + return this.$libs.CryptoJS.enc.Base64.parse(string).toString(this.$libs.CryptoJS.enc.Utf8) } } \ No newline at end of file diff --git a/src/encoders/info.ts b/src/encoders/info.ts index 69346ae..95237f5 100644 --- a/src/encoders/info.ts +++ b/src/encoders/info.ts @@ -35,6 +35,6 @@ module.exports = { }, decode(string: string) { - return false; + return true; } } \ No newline at end of file diff --git a/src/scss/custom.scss b/src/scss/custom.scss index d928c68..dac3ed6 100644 --- a/src/scss/custom.scss +++ b/src/scss/custom.scss @@ -1,6 +1,11 @@ @import 'variables'; @import 'node_modules/bootstrap/scss/bootstrap'; +*::-moz-selection, +*::selection { + background: #1fff5a !important; +} + .setting button { transition: all .5s; padding: 0 2px;