Сменил реализацию hexdump, добавил настройку ширины в байтах

This commit is contained in:
saber-nyan 2019-05-06 19:33:39 +03:00
parent b1401579f9
commit 567946ac2a
No known key found for this signature in database
GPG Key ID: 7B069E9C295E6B4A
4 changed files with 69 additions and 425 deletions

View File

@ -2,45 +2,73 @@
<div>
<div>#{{id}} at {{new Date(timestamp * 1000).toLocaleDateString('ru-RU', {month: '2-digit', day: '2-digit', hour:'2-digit', minute: '2-digit', second: '2-digit'})}}</div>
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<pre :id="'hexdump-' + id"></pre>
<pre>{{ hexdata }}</pre>
</div>
</div>
</template>
<script>
import {Hexdump,} from '@/components/hexdump.js' // Why the fuck is this working, Babel?!?!
// import {Hexdump,} from '@/components/hexdump.js' // Why the fuck is this working, Babel?!?!
export default {
name: 'Packet',
props: ['id', 'content', 'timestamp',],
mounted() {
// const dataString = decodeURIComponent(escape(atob(this.$props.content)));
const dataString = atob(this.$props.content);
this.hex = new Hexdump(dataString, { // TODO: в настройки
container: 'hexdump-' + this.$props.id,
base: 'hex',
width: 16,
ascii: false,
byteGrouping: 1,
html: false,
lineNumber: true,
nonPrintable: '?',
style: {
lineNumberLeft: '',
lineNumberRight: ':',
stringLeft: '|',
stringRight: '|',
hexLeft: '',
hexRight: '',
hexNull: '.g',
stringNull: ' ',
},
});
methods: {
hexdump(buffer, blockSize) {
blockSize = parseInt(blockSize, 10) || 16;
let lines = [];
const hex = "0123456789ABCDEF";
for (let b = 0; b < buffer.length; b += blockSize) {
let block = buffer.slice(b, Math.min(b + blockSize, buffer.length));
let addr = ("0000" + b.toString(10)).slice(-4);
let codes = block.split('').map(function (ch) {
let code = ch.charCodeAt(0);
return " " + hex[(0xF0 & code) >> 4] + hex[0x0F & code];
}).join("");
codes += " ".repeat(blockSize - block.length);
// eslint-disable-next-line no-control-regex
let chars = block.replace(/[\x00-\x1F\x20]/g, '.');
chars += " ".repeat(blockSize - block.length);
lines.push(addr + " " + codes + " " + chars);
}
return lines.join("\n");
},
},
beforeDestroy() {
delete this.hex;
computed: {
hexdata() {
// const dataString = decodeURIComponent(escape(atob(this.$props.content)));
const dataString = atob(this.$props.content);
return this.hexdump(dataString, this.$store.state.hexdumpBlockSize);
},
},
// mounted() {
//
// this.hex = new Hexdump(dataString, { // TODO: в настройки
// container: 'hexdump-' + this.$props.id,
// base: 'hex',
// width: 16,
// ascii: false,
// byteGrouping: 1,
// html: false,
// // endian: 'little',
// lineNumber: true,
// nonPrintable: '?',
// style: {
// lineNumberLeft: '',
// lineNumberRight: ':',
// stringLeft: '|',
// stringRight: '|',
// hexLeft: '',
// hexRight: '',
// hexNull: '.g',
// stringNull: ' ',
// },
// });
// },
// beforeDestroy() {
// delete this.hex;
// },
}
</script>
<style scoped>

View File

@ -15,6 +15,10 @@
<label for="inputApiPassword">Пароль</label>
<input type="password" class="form-control" id="inputApiPassword" v-model="apiPassword">
</div>
<div class="form-group">
<label for="inputHexdumpBlockSize">Ширина блока HEX</label>
<input type="number" class="form-control" id="inputHexdumpBlockSize" v-model="hexdumpBlockSize">
</div>
<button type="submit" @click.prevent="$emit('close')" class="btn btn-primary">
Закрыть
</button>
@ -65,6 +69,14 @@ export default {
this.$store.commit('setApiPassword', value);
},
},
hexdumpBlockSize: {
get() {
return this.$store.state.hexdumpBlockSize;
},
set(value) {
this.$store.commit('setHexdumpBlockSize', value);
},
},
},
}
</script>

View File

@ -1,398 +0,0 @@
// Hexdump.js 0.1.1
// (c) 2011 Dustin Willis Webber
// Hexdump is freely distributable under the MIT license.
// For all details and documentation:
// http://github.com/mephux/hexdump.js
// Hexdump Initializer
// data => The string payload.
// options => hexdump configurations
export function Hexdump(data, options) {
const self = this;
self.hexdump = [];
self.hex = false;
self.options = {
container: options.container || ''
, width: options.width || 16
, byteGrouping: options.byteGrouping || 0
, ascii: options.ascii
, lineNumber: options.lineNumber
, endian: options.endian || 'big'
, html: options.html
, base: options.base || 'hexadecimal'
, nonPrintable: options.nonPrintable || '.'
, style: {
lineNumberLeft: options.style.lineNumberLeft || ''
, lineNumberRight: options.style.lineNumberRight || ':'
, stringLeft: options.style.stringLeft || '|'
, stringRight: options.style.stringRight || '|'
, hexLeft: options.style.hexLeft || ''
, hexRight: options.style.hexRight || ''
, hexNull: options.style.hexNull || '.'
, stringNull: options.style.stringNull || ' ',
},
};
if (self.options.base === 'hex') {
self.hex = true;
} else if (self.options.base === 'hexadecimal') {
self.hex = true;
}
// Check for the line number option and turn it off
// if not set unless it has been explicitly turned
// off by the user.
const ln = self.options.lineNumber;
if (typeof ln == "undefined" || ln == null) {
self.options.lineNumber = true;
}
const askey = self.options.ascii;
if (typeof askey == "undefined" || askey == null) {
self.options.ascii = false;
}
const html = self.options.html;
if (typeof html == "undefined" || html == null) {
self.options.html = true;
}
if (self.endian !== ('little' || 'big')) {
self.endian = 'big';
}
// Make sure spacing is within proper range.
if (self.options.byteGrouping > data.length) {
self.options.byteGrouping = data.length;
}
self.options.byteGrouping--;
// Make sure width is within proper range.
if (self.options.width > data.length) {
self.options.width = data.length;
}
// Base padding
self.padding = {
hex: 4,
dec: 5,
bin: 8,
};
// Base conversion logic
switch (self.options.base) {
case 'hexadecimal':
case 'hex':
case 16:
self.setNullPadding(self.padding.hex);
self.baseConvert = function (characters) {
for (let i = 0; i < characters.length; i++) {
return self.addPadding(characters[i].charCodeAt(0).toString(16), self.padding.hex);
}
};
break;
case 'decimal':
case 'dec':
case 10:
self.setNullPadding(self.padding.dec);
self.baseConvert = function (characters) {
for (let i = 0; i < characters.length; i++) {
return self.addPadding(characters[i].charCodeAt(0), self.padding.dec);
}
};
break;
case 'binary':
case 'bin':
case 2:
self.setNullPadding(self.padding.bin);
self.baseConvert = function (characters) {
for (let i = 0; i < characters.length; i++) {
let ddx = characters[i].charCodeAt(0), r = "";
for (let bbx = 0; bbx < 8; bbx++) {
r = (ddx % 2) + r;
ddx = Math.floor(ddx / 2);
}
return self.addPadding(r, self.padding.bin);
}
};
break;
default:
self.options.base = 'hex';
self.hex = true;
self.setNullPadding(self.padding.hex);
self.baseConvert = function (characters) {
for (let i = 0; i < characters.length; i++) {
return self.addPadding(characters[i].charCodeAt(0).toString(16), self.padding.hex);
}
};
}
const regex = new RegExp('.{1,' + this.options.width + '}', 'g');
self.data = data.match(regex);
self.nullCount = (self.options.width - self.data[self.data.length - 1].length);
self.hexCounter = 0;
self.stringCounter = 0;
for (let i = 0; i < self.data.length; i++) {
const tempData = self.process(self.data[i]);
self.hexdump.push({
data: tempData.data,
string: tempData.string,
length: self.data[i].length,
missing: (self.options.width - self.data[i].length),
});
}
self.dump();
}
Hexdump.prototype.dump = function () {
const self = this;
self.output = '';
for (let i = 0; i < self.hexdump.length; i++) {
if (self.options.lineNumber) {
let tempLineNumberStyle = '';
tempLineNumberStyle += self.options.style.lineNumberLeft;
const currentLineCount = (i * self.options.width); //.toString(16);
const temLineCount = 8 - currentLineCount.toString().length;
for (let l = 0; l < temLineCount; l++) {
tempLineNumberStyle += '0';
}
tempLineNumberStyle += currentLineCount;
tempLineNumberStyle += self.options.style.lineNumberRight + ' ';
if (self.options.html) {
self.output += '<span id="line-number">' + tempLineNumberStyle + '</span>';
} else {
self.output += tempLineNumberStyle;
}
}
let spacingCount = 0;
// var breakPoint = Math.floor(self.options.width / 2);
self.output += self.options.style.hexLeft;
for (let x = 0; x < self.hexdump[i].data.length; x++) {
if (spacingCount === self.options.byteGrouping) {
if (x === self.hexdump[i].data.length - 1) {
self.output += self.hexdump[i].data[x];
} else {
self.output += self.hexdump[i].data[x] + ' ';
}
spacingCount = 0;
} else {
self.output += self.hexdump[i].data[x];
spacingCount++;
}
}
self.output += self.options.style.hexRight;
self.appendString(self.hexdump[i]);
self.output += "\n";
}
const hexdump_container = document.getElementById(this.options.container);
hexdump_container.innerHTML = this.output;
};
Hexdump.prototype.appendString = function (data) {
const self = this;
self.output += ' ' + self.options.style.stringLeft;
self.output += data.string;
self.output += self.options.style.stringRight;
};
Hexdump.prototype.splitNulls = function (code) {
const split = [];
let buffer = "";
if (code && code.length > 2) {
for (let cc = 0; cc < code.length; cc++) {
const tempi = cc + 1;
if (tempi % 2 === 0) {
buffer += code[cc].toString();
split.push(buffer);
buffer = "";
} else {
buffer += code[cc].toString();
}
}
}
return split;
};
Hexdump.prototype.process = function (data) {
let i;
let splitHexWidth;
let y;
let split;
let code;
const self = this;
const stringArray = [];
const hexArray = [];
for (i = 0; i < data.length; i++) {
if (self.options.html) {
code = self.baseConvert(data[i]);
if (self.hex) {
split = self.splitNulls(code);
for (y = 0; y < split.length; y++) {
hexArray.push('<span data-hex-id="' + self.hexCounter + '">' +
split[y] + '</span>');
}
} else {
hexArray.push('<span data-hex-id="' + self.hexCounter + '">' +
code + '</span>');
}
stringArray.push('<span data-string-id="' + self.hexCounter + '">' +
self.checkForNonPrintable(data[i]) + '</span>');
} else {
code = self.baseConvert(data[i]);
if (self.hex) {
split = self.splitNulls(code);
for (y = 0; y < split.length; y++) {
hexArray.push(split[y]);
}
} else {
hexArray.push(code);
}
stringArray.push(self.checkForNonPrintable(data[i]));
}
self.hexCounter++;
}
if (self.hex) {
splitHexWidth = self.options.width * 2;
} else {
splitHexWidth = self.options.width;
}
if (hexArray.length < splitHexWidth) {
const amount = (splitHexWidth - hexArray.length);
for (i = 0; i < amount; i++) {
let nullHex = '';
if (self.options.html) {
nullHex = '<span data-hex-null="true">' + self.options.style.hexNull + '</span>';
} else {
nullHex = self.options.style.hexNull;
}
hexArray.push(nullHex);
}
}
if (stringArray.length < self.options.width) {
const stringAmount = self.options.width - stringArray.length;
for (i = 0; i < stringAmount; i++) {
let nullString = '';
if (self.options.html) {
nullString = '<span data-string-null="true">' + self.options.style.stringNull + '</span>';
} else {
nullString = self.options.style.stringNull;
}
stringArray.push(nullString);
}
}
return {data: hexArray, string: stringArray.join(''),};
};
Hexdump.prototype.setNullPadding = function (padding) {
const self = this;
const hexNull = self.options.style.hexNull[0];
self.options.style.hexNull = "";
if (self.hex) {
padding = padding / 2;
}
for (let p = 0; p < padding; p++) {
self.options.style.hexNull += hexNull;
}
};
Hexdump.prototype.addPadding = function (ch, padding) {
const self = this, length = ch.toString().length;
let pad = '';
for (let i = 0; i < (padding - length); i++) {
pad += '0'
}
if (self.options.endian === 'big') {
return pad + ch;
} else {
return ch + pad;
}
};
Hexdump.prototype.checkForNonPrintable = function (character) {
const self = this;
const c = character.charCodeAt(0).toString(16);
// noinspection EqualityComparisonWithCoercionJS
if (c == 0x9) {
return '.'
} else { // noinspection EqualityComparisonWithCoercionJS
if (c == 0x7F) {
return '.'
} else if (c.length > 2 && self.options.ascii) {
return '.'
} else {
return character;
}
}
};

View File

@ -9,11 +9,13 @@ export default new Vuex.Store({
apiUrl: 'http://127.0.0.1/api',
apiLogin: 'BinaryBears',
apiPassword: '123456',
hexdumpBlockSize: 16,
},
mutations: {
setApiUrl: (state, payload) => state.apiUrl = payload,
setApiLogin: (state, payload) => state.apiLogin = payload,
setApiPassword: (state, payload) => state.apiPassword = payload,
setHexdumpBlockSize: (state, payload) => state.hexdumpBlockSize = payload,
},
plugins: [createPersistedState(),],
})