mirror of
https://github.com/Av0idD4rk/packmate.git
synced 2026-10-23 21:42:06 +00:00
Сменил реализацию hexdump, добавил настройку ширины в байтах
This commit is contained in:
parent
b1401579f9
commit
567946ac2a
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -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(),],
|
||||
})
|
||||
|
||||
Loading…
Reference in New Issue
Block a user