Кривая подсветка паттернов

This commit is contained in:
saber-nyan 2019-11-26 17:51:09 +03:00
parent 2d8ef03275
commit 6534bc93d6
No known key found for this signature in database
GPG Key ID: 7B069E9C295E6B4A
3 changed files with 56 additions and 18 deletions

View File

@ -5,12 +5,12 @@
<button @click.prevent="copyText" class="btn btn-link">Copy text</button> <button @click.prevent="copyText" class="btn btn-link">Copy text</button>
<button @click.prevent="copyPythonBytes" class="btn btn-link">Copy as Python bytes</button> <button @click.prevent="copyPythonBytes" class="btn btn-link">Copy as Python bytes</button>
</div> </div>
<code v-if="!this.$store.state.hexdumpMode" <p v-if="!this.$store.state.hexdumpMode"
class="d-flex pt-2 pb-2 mb-3 border-bottom" class="pt-2 pb-2 mb-3 border-bottom"
v-html="base64ToHtml(packet.content)"/> v-html="stringdata"/>
<code v-else <p v-else
class="d-flex pt-2 pb-2 mb-3 border-bottom" class="pt-2 pb-2 mb-3 border-bottom"
v-html="escapeHtml(hexdata).split('\n').join('<br/>')"/> v-html="hexdata"/>
</div> </div>
</template> </template>
@ -30,7 +30,13 @@
computed: { computed: {
hexdata() { hexdata() {
const dataString = atob(this.packet.content); const dataString = atob(this.packet.content);
return this.hexdump(dataString, this.$store.state.hexdumpBlockSize, this.$store.state.hexdumpLineNumberBase); const dump = this.hexdump(dataString, this.$store.state.hexdumpBlockSize, this.$store.state.hexdumpLineNumberBase);
return this.escapeHtml(dump)
.split('\n')
.join('<br>');
},
stringdata() {
return this.base64ToHtml(this.packet.content);
}, },
}, },
methods: { methods: {
@ -64,7 +70,7 @@
}); });
}, },
escapeHtml(in_) { escapeHtml(in_) {
return in_.replace(/[&<>"'/]/g, s => { return in_.replace(/(<span style="background-color: #(?:[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})">|<\/span>)|[&<>"'/]/g, ($0, $1) => {
const entityMap = { const entityMap = {
'&': '&amp;', '&': '&amp;',
'<': '&lt;', '<': '&lt;',
@ -74,11 +80,36 @@
'/': '&#x2F;', '/': '&#x2F;',
}; };
return entityMap[s]; return $1 ? $1 : entityMap[$0];
}); });
}, },
base64ToHtml(in_) { base64ToHtml(in_) { // FIXME: Пересекающиеся паттерны приводят к неожиданным результатам
return this.escapeHtml(atob(in_)).split('\n').join('<br/>'); // Replace all \n to <br/> let raw = atob(in_);
const patterns = this.$store.state.patterns.reduce((obj, item) => {
obj[item.id] = item;
return obj;
}, {});
let offset = 0;
this.packet.matches
.sort((a, b) => a.startPosition - b.startPosition)
.forEach(match => {
const pattern = patterns[match.patternId];
if (!pattern) {
console.info(`Pattern #${match.patternId} does not exist`);
return;
}
const firstTag = `<span style="background-color: ${pattern.color}">`;
const secondTag = '</span>';
const positionStart = match.startPosition + offset;
raw = raw.substring(0, positionStart) + firstTag + raw.substring(positionStart);
offset += firstTag.length;
const positionEnd = match.endPosition + offset;
raw = raw.substring(0, positionEnd) + secondTag + raw.substring(positionEnd);
offset += secondTag.length;
});
return this.escapeHtml(raw).split('\n').join('<br>'); // Replace all \n to <br>
}, },
copyPythonBytes() { copyPythonBytes() {
@ -122,7 +153,7 @@
box-shadow: 0 0 5px 5px rgba(251, 233, 231, 0.4); box-shadow: 0 0 5px 5px rgba(251, 233, 231, 0.4);
} }
code { p {
font-family: "Ubuntu Mono", "Lucida Console", monospace; font-family: "Ubuntu Mono", "Lucida Console", monospace;
font-size: 100%; font-size: 100%;
color: black; color: black;

View File

@ -7,7 +7,7 @@
</button> </button>
</li> </li>
<b-dropdown-divider/> <b-dropdown-divider/>
<b-dropdown-item-button v-for="pattern in patterns" <b-dropdown-item-button v-for="pattern in this.$store.state.patterns"
:key="pattern.id" @click.stop.prevent="openPattern(pattern.id)"> :key="pattern.id" @click.stop.prevent="openPattern(pattern.id)">
<strong :style="`color: ${pattern.color};`">{{ pattern.name }}</strong>: <strong :style="`color: ${pattern.color};`">{{ pattern.name }}</strong>:
<code>{{ pattern.regex ? `/${pattern.value}/` : `'${pattern.value}'` }}</code>; <code>{{ pattern.regex ? `/${pattern.value}/` : `'${pattern.value}'` }}</code>;
@ -29,7 +29,7 @@
name: 'PatternsDropdown', name: 'PatternsDropdown',
data() { data() {
return { return {
patterns: Array(), // patterns: Array(),
}; };
}, },
mounted() { mounted() {
@ -41,7 +41,7 @@
}, },
updatePatterns() { updatePatterns() {
this.$http.get('pattern/') this.$http.get('pattern/')
.then(r => this.patterns = r.data) .then(r => this.$store.commit('setPatterns', r.data))
.catch(e => { .catch(e => {
this.$bvToast.toast(`Не удалось загрузить паттерны: ${e}`, { this.$bvToast.toast(`Не удалось загрузить паттерны: ${e}`, {
title: 'Сбой', title: 'Сбой',
@ -75,11 +75,11 @@
}, },
addPatternFromWs(pattern) { addPatternFromWs(pattern) {
this.patterns.push(pattern); this.$store.commit('addPattern', pattern);
}, },
deletePatternFromWs(id) { deletePatternFromWs(id) {
this.patterns = this.patterns.filter(o => o.id !== id); this.$store.commit('setPatterns', this.$store.state.patterns.filter(o => o.id !== id));
}, },
}, },
}; };

View File

@ -20,6 +20,8 @@ export default new Vuex.Store({
serviceModalName: '', serviceModalName: '',
serviceModalId: 0, serviceModalId: 0,
patterns: [],
}, },
mutations: { mutations: {
setApiLogin: (s, p) => s.apiLogin = p, setApiLogin: (s, p) => s.apiLogin = p,
@ -36,6 +38,9 @@ export default new Vuex.Store({
setServiceModalName: (s, p) => s.serviceModalName = p, setServiceModalName: (s, p) => s.serviceModalName = p,
setServiceModalId: (s, p) => s.serviceModalId = p, setServiceModalId: (s, p) => s.serviceModalId = p,
setPatterns: (s, p) => s.patterns = p,
addPattern: (s, p) => s.patterns.push(p),
}, },
actions: {}, actions: {},
plugins: [ plugins: [
@ -49,7 +54,9 @@ export default new Vuex.Store({
&& mName !== 'setServiceModalName' && mName !== 'setServiceModalName'
&& mName !== 'setServiceModalId' && mName !== 'setServiceModalId'
&& mName !== 'togglePause' && mName !== 'togglePause'
&& mName !== 'toggleHexdumpMode'; && mName !== 'toggleHexdumpMode'
&& mName !== 'setPatterns'
&& mName !== 'addPattern';
console.debug('Processing?', process); console.debug('Processing?', process);
return process; return process;
}, },