Переехал с TS на Vanilla JS

+ Фавикон
+ Компонент пакета с hex-viewer внутри
+ Vuex
* Бутстрап в бандле вместо внешнего скрипта
This commit is contained in:
saber-nyan 2019-04-30 00:55:22 +03:00
parent 82e8aeb16a
commit e771d8b01c
No known key found for this signature in database
GPG Key ID: 7B069E9C295E6B4A
34 changed files with 2534 additions and 589 deletions

View File

@ -1,5 +1,5 @@
module.exports = {
presets: [
"@vue/app",
'@vue/app',
],
};

1978
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -8,19 +8,47 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"bootstrap": "^4.3.1",
"core-js": "^2.6.5",
"jquery": "^3.4.0",
"popper.js": "^1.15.0",
"vue": "^2.6.10",
"vue-class-component": "^7.0.2",
"vue-property-decorator": "^8.1.0",
"vue-router": "^3.0.3"
"vue-router": "^3.0.3",
"vuex": "^3.0.1"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.6.0",
"@vue/cli-plugin-typescript": "^3.6.0",
"@vue/cli-service": "^3.6.0",
"typescript": "^3.4.3",
"@vue/cli-plugin-babel": "^3.7.0",
"@vue/cli-plugin-eslint": "^3.7.0",
"@vue/cli-service": "^3.7.0",
"babel-eslint": "^10.0.1",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.0.0",
"vue-template-compiler": "^2.5.21"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"rules": {
"indent": [
"warn",
"tab"
],
"comma-dangle": [
"warn",
"always"
],
"no-console": "off"
},
"parserOptions": {
"parser": "babel-eslint"
}
},
"postcss": {
"plugins": {
"autoprefixer": {}

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
public/apple-touch-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

9
public/browserconfig.xml Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#afd9f0</TileColor>
</tile>
</msapplication>
</browserconfig>

BIN
public/favicon-16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
public/favicon-32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -4,9 +4,15 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="apple-touch-icon" sizes="180x180" href="<%= BASE_URL %>apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="<%= BASE_URL %>favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="<%= BASE_URL %>favicon-16x16.png">
<link rel="manifest" href="<%= BASE_URL %>site.webmanifest">
<link rel="mask-icon" href="<%= BASE_URL %>safari-pinned-tab.svg" color="#44beff">
<meta name="msapplication-TileColor" content="#afd9f0">
<meta name="theme-color" content="#afd9f0">
<title>Packmate</title>
</head>
<body>
@ -17,14 +23,5 @@
<div id="app"></div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
crossorigin="anonymous"></script>
</body>
</html>

BIN
public/mstile-150x150.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,135 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="1453.000000pt" height="1453.000000pt" viewBox="0 0 1453.000000 1453.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.11, written by Peter Selinger 2001-2013
</metadata>
<g transform="translate(0.000000,1453.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M7065 14523 c-1372 -40 -2685 -458 -3825 -1216 -157 -105 -420 -294
-420 -303 0 -2 17 3 38 11 20 8 84 26 142 40 58 14 148 39 200 54 127 39 219
58 314 66 44 4 100 13 124 20 25 8 81 17 126 21 44 3 89 11 99 16 95 49 332
73 722 73 306 -1 463 -10 636 -40 167 -28 298 -56 404 -85 44 -12 103 -27 130
-34 60 -16 250 -77 320 -104 28 -11 86 -33 130 -50 175 -66 550 -246 619 -296
17 -13 67 -44 111 -70 44 -26 102 -61 129 -78 l49 -32 47 17 c88 31 191 13
245 -43 l28 -29 51 46 c69 62 286 203 366 238 36 16 70 32 75 36 10 7 190 82
290 121 108 42 410 138 433 138 8 0 28 6 45 14 74 32 376 88 657 120 368 43
516 44 1020 6 413 -30 709 -73 915 -133 100 -28 208 -97 265 -170 45 -55 45
-64 11 -142 -10 -22 -30 -69 -44 -105 -67 -171 -218 -472 -339 -680 -99 -168
-127 -225 -128 -254 0 -10 30 -52 68 -94 117 -130 132 -147 132 -154 0 -5 -30
-56 -66 -115 -37 -60 -80 -133 -97 -163 l-29 -54 13 -106 c17 -136 15 -322 -4
-430 -18 -94 -51 -233 -61 -248 -3 -5 -12 -57 -21 -115 -11 -82 -22 -122 -50
-176 -40 -81 -39 -76 -22 -93 12 -12 35 -47 179 -269 59 -90 124 -186 228
-337 24 -34 64 -86 89 -115 25 -29 69 -80 96 -112 67 -79 238 -252 298 -299
104 -84 198 -144 317 -205 126 -63 185 -100 177 -108 -5 -4 -168 10 -302 27
-174 21 -383 102 -532 206 -37 26 -81 57 -98 68 -51 36 -118 98 -163 150 -59
71 -58 69 -75 102 -14 25 -16 26 -17 8 0 -12 5 -46 11 -75 6 -30 17 -88 24
-129 7 -41 23 -127 35 -190 25 -135 46 -281 60 -435 6 -60 17 -171 25 -245 8
-74 17 -227 20 -340 3 -113 10 -234 15 -270 5 -36 12 -361 16 -723 6 -514 4
-679 -6 -755 -15 -117 -5 -231 36 -387 14 -55 30 -122 35 -150 5 -27 14 -59
19 -70 5 -11 21 -55 35 -97 57 -171 195 -440 297 -582 15 -21 30 -55 34 -75 3
-20 19 -49 34 -66 37 -39 59 -94 49 -120 -7 -18 -8 -18 -8 -2 -2 36 -77 134
-206 268 -121 125 -211 233 -277 334 -114 176 -160 253 -217 370 -76 158 -129
292 -157 400 -6 22 -10 -1 -15 -85 -11 -185 -39 -500 -49 -560 -6 -30 -14 -84
-19 -120 -20 -141 -42 -266 -51 -290 -5 -14 -12 -45 -16 -70 -3 -24 -10 -51
-14 -60 -4 -8 -15 -40 -24 -70 -8 -30 -24 -72 -35 -93 l-19 -38 59 -112 c32
-62 66 -126 74 -144 34 -73 147 -194 252 -270 29 -21 54 -43 56 -48 3 -7 -48
-9 -147 -7 -125 3 -164 7 -227 27 -75 23 -179 73 -210 101 -8 8 -20 14 -26 14
-24 0 -203 227 -203 258 0 6 -4 12 -8 12 -4 0 -14 16 -21 35 -15 44 -27 45
-34 3 -3 -18 -13 -67 -21 -108 -8 -41 -19 -97 -25 -125 -9 -47 -40 -144 -61
-190 -49 -111 -60 -139 -60 -151 0 -8 -4 -14 -10 -14 -5 0 -10 -5 -10 -11 0
-14 -72 -124 -134 -204 -79 -103 -216 -211 -346 -275 -36 -17 -73 -35 -82 -41
-10 -5 -24 -9 -31 -9 -7 0 -29 -11 -47 -25 -20 -15 -36 -21 -38 -15 -4 11 56
118 111 199 29 43 161 298 184 356 22 57 113 322 113 331 0 3 -28 -15 -62 -39
-93 -66 -223 -138 -308 -171 -41 -15 -84 -32 -95 -37 -18 -7 -178 -49 -189
-49 -7 0 -98 -158 -119 -205 -23 -53 -38 -164 -25 -188 5 -10 8 -20 6 -22 -14
-14 -74 70 -99 137 -41 111 -64 391 -39 477 5 19 7 37 5 40 -3 2 -59 -51 -126
-119 -117 -120 -180 -209 -249 -350 -12 -25 -26 -53 -31 -63 -5 -9 -12 -37
-15 -61 l-6 -43 88 -5 c107 -6 186 -41 249 -109 22 -24 80 -88 129 -142 139
-152 297 -276 471 -367 44 -23 99 -55 123 -71 24 -16 47 -29 53 -29 5 0 14
-11 20 -24 9 -18 26 -28 78 -41 36 -9 104 -28 151 -42 162 -48 179 -52 287
-56 153 -6 377 -46 513 -91 54 -17 75 -20 125 -13 108 15 388 22 510 14 66 -4
206 -11 310 -15 189 -8 190 -8 260 -42 125 -60 200 -115 256 -187 29 -38 56
-72 61 -78 10 -11 305 279 472 465 1000 1111 1631 2489 1815 3965 111 884 56
1797 -159 2654 -293 1167 -851 2216 -1656 3111 -124 138 -431 444 -564 561
-775 687 -1713 1214 -2692 1514 -605 185 -1213 288 -1858 315 -135 5 -276 9
-315 8 -38 -1 -110 -3 -160 -5z"/>
<path d="M2499 12743 c-148 -127 -480 -454 -623 -613 -1067 -1189 -1702 -2650
-1846 -4242 -43 -480 -29 -1086 35 -1568 198 -1471 822 -2821 1811 -3920 137
-152 430 -443 579 -574 106 -94 110 -96 119 -74 21 50 111 196 156 253 42 52
61 67 138 104 50 23 114 50 144 59 68 20 327 28 418 11 36 -6 94 -15 130 -20
36 -4 124 -18 195 -29 72 -12 158 -25 193 -30 54 -8 152 -34 204 -55 13 -5 21
0 29 18 6 14 21 28 33 32 18 5 569 26 764 29 46 1 72 5 72 12 0 7 15 23 33 36
54 41 222 138 239 138 8 0 22 7 29 16 7 9 40 37 74 62 58 45 485 466 555 548
19 23 67 78 105 124 39 45 80 86 93 91 31 12 84 11 116 -1 23 -8 26 -7 26 14
0 19 -27 65 -50 86 -9 8 -72 90 -98 128 -14 21 -42 70 -63 111 l-37 73 -7 -33
c-9 -46 -46 -158 -62 -189 -7 -14 -13 -29 -13 -35 0 -18 -44 -98 -93 -172 -81
-121 -197 -214 -197 -157 0 13 -67 149 -85 172 -92 115 -132 161 -139 161 -5
1 -37 27 -71 58 -35 32 -69 63 -76 68 -24 18 -86 55 -93 55 -7 0 46 -114 57
-118 4 -2 7 -8 7 -14 0 -5 17 -40 39 -76 105 -182 127 -232 101 -232 -5 0 -10
4 -10 8 0 5 -10 14 -22 19 -62 29 -319 251 -360 310 -16 24 -37 51 -47 61 -21
21 -66 79 -113 147 -28 42 -103 193 -145 295 -8 21 -11 14 -16 -48 -8 -79 -45
-261 -57 -277 -4 -5 -11 -26 -15 -45 -4 -19 -11 -39 -15 -45 -4 -5 -13 -28
-20 -50 -35 -108 -220 -355 -266 -355 -13 0 -26 -4 -29 -10 -3 -5 -34 -26 -68
-46 -70 -41 -77 -48 -77 -87 0 -16 -4 -26 -10 -22 -15 9 -12 73 3 82 40 24
110 216 126 343 6 41 15 106 21 143 10 58 9 71 -3 85 -18 20 -127 181 -127
187 0 2 -13 23 -29 47 -16 24 -42 66 -57 94 -16 28 -60 104 -99 168 -111 186
-308 565 -330 636 -4 14 -10 27 -14 30 -3 3 -14 21 -23 40 l-17 35 0 -60 c0
-107 60 -452 88 -505 5 -9 12 -31 16 -50 4 -19 11 -39 15 -45 4 -5 11 -26 15
-45 19 -90 158 -362 271 -530 48 -71 85 -132 83 -135 -6 -5 -145 86 -241 158
-128 97 -297 286 -298 335 0 6 -3 12 -8 12 -7 0 -38 56 -65 120 -9 19 -25 57
-36 83 -11 26 -23 63 -27 83 -3 19 -10 36 -14 39 -5 3 -11 24 -15 48 -4 23
-11 47 -16 53 -4 5 -13 44 -19 85 -6 40 -17 83 -23 94 -16 28 -22 822 -7 965
6 58 16 164 21 235 6 72 17 153 24 180 20 73 28 132 17 120 -5 -5 -23 -35 -39
-65 -50 -92 -58 -105 -70 -113 -7 -4 -13 -12 -13 -18 0 -13 -41 -72 -58 -82
-6 -4 -12 -14 -12 -20 0 -17 -188 -217 -204 -217 -7 0 -24 -10 -37 -21 -45
-41 -214 -145 -259 -161 -25 -9 -76 -19 -114 -22 -38 -4 -82 -14 -98 -22 -16
-8 -33 -12 -38 -9 -15 9 16 36 74 66 70 35 96 51 118 72 10 9 23 17 28 17 6 0
10 5 10 11 0 7 11 22 24 34 42 39 114 152 167 263 65 137 63 131 95 237 15 50
30 95 35 100 4 6 10 28 14 50 4 22 13 46 19 54 14 18 13 241 -2 250 -5 3 -13
38 -17 76 -3 39 -10 79 -15 90 -5 11 -14 67 -20 125 -6 58 -15 140 -20 183
-45 362 -43 1174 4 1477 8 52 18 124 22 160 3 35 10 71 15 80 4 8 12 44 18 80
12 83 66 302 80 330 5 9 12 31 16 50 4 19 13 46 21 60 7 14 31 70 54 125 22
55 45 108 50 117 19 34 9 36 -47 8 -117 -57 -191 -86 -263 -101 -25 -6 -54
-14 -65 -20 -58 -27 -335 -42 -460 -24 -80 11 -194 72 -302 163 -80 66 -71 73
47 42 56 -15 316 -8 333 9 6 6 24 11 40 11 16 0 43 6 60 14 18 8 61 27 97 42
36 16 83 39 105 51 22 13 51 28 65 35 14 7 27 15 30 18 3 3 16 11 30 18 48 24
70 39 126 83 31 24 90 71 132 104 43 33 82 64 89 70 6 5 28 21 47 35 42 29 42
45 3 113 -42 75 -57 115 -76 212 -34 173 -2 389 109 725 27 82 60 213 60 237
0 6 -20 35 -44 63 -48 56 -58 90 -44 156 11 48 32 11 -207 359 -126 183 -363
575 -408 675 -13 30 -36 80 -50 110 -60 129 -66 151 -52 198 7 23 12 42 10 42
-1 0 -54 -44 -116 -97z"/>
<path d="M6445 1929 c-5 -7 -25 -8 -56 -4 -29 4 -49 3 -49 -3 0 -5 -35 -12
-77 -16 -80 -6 -212 -31 -248 -46 -11 -4 -36 -14 -55 -21 -19 -7 -53 -24 -75
-39 -46 -30 -58 -37 -142 -86 -35 -19 -65 -40 -69 -45 -3 -5 13 -48 36 -97 62
-131 68 -143 90 -200 11 -29 20 -62 20 -73 0 -11 16 -47 35 -80 19 -33 38 -72
41 -87 4 -15 10 -31 14 -37 14 -18 32 -174 28 -240 -3 -54 -1 -65 12 -65 15 0
145 40 190 58 14 6 59 20 100 32 41 12 84 25 95 30 51 20 248 80 266 80 11 0
52 14 91 30 107 46 113 40 38 -35 -27 -28 -50 -54 -50 -58 0 -4 -46 -54 -102
-110 -104 -103 -238 -259 -238 -276 0 -5 -3 -11 -8 -13 -7 -3 -27 -30 -133
-177 -18 -24 -49 -76 -69 -115 -20 -39 -44 -84 -54 -99 -10 -15 -17 -29 -15
-32 13 -13 474 -67 765 -89 l70 -6 11 68 c15 90 43 205 54 216 5 6 9 17 9 26
0 23 103 221 159 305 25 38 61 99 79 135 18 35 40 74 50 85 29 35 132 252 132
279 0 9 4 16 9 16 5 0 14 21 20 46 10 40 74 126 84 113 10 -12 27 -70 32 -109
7 -46 38 -152 60 -205 7 -16 16 -41 20 -55 3 -14 12 -38 20 -55 7 -16 18 -41
23 -55 24 -55 75 -158 105 -211 35 -62 137 -221 147 -229 3 -3 20 -34 37 -70
18 -36 48 -88 67 -117 19 -29 37 -65 41 -81 3 -17 14 -37 24 -46 17 -15 29
-15 167 4 182 25 536 89 547 100 7 7 -67 111 -85 118 -4 2 -8 8 -8 14 0 11
-88 121 -101 126 -5 2 -9 8 -9 13 0 5 -19 33 -42 62 -24 29 -54 68 -68 86 -14
18 -34 45 -46 59 -32 41 -124 171 -124 176 0 3 -19 33 -43 68 -24 35 -53 82
-65 106 l-22 42 28 0 c15 -1 54 -7 87 -15 33 -8 83 -19 110 -25 28 -6 57 -15
66 -20 9 -5 33 -12 53 -15 20 -4 53 -16 73 -26 21 -11 48 -19 60 -19 13 0 23
-4 23 -9 0 -5 13 -11 29 -14 16 -4 56 -19 89 -35 l60 -28 6 60 c3 32 6 85 6
117 0 33 4 59 9 59 4 0 11 25 14 56 3 31 11 62 16 67 6 6 11 19 11 29 0 10 4
18 8 18 4 0 15 28 25 63 10 34 49 124 87 199 72 141 83 184 53 195 -10 4 -37
19 -60 35 -23 15 -45 28 -49 28 -8 0 -22 6 -169 75 -44 21 -100 40 -125 43
-25 2 -50 8 -55 13 -6 4 -51 13 -100 19 -50 7 -100 17 -113 23 -26 12 -340 -5
-407 -23 -100 -26 -153 -44 -194 -62 -38 -18 -55 -20 -146 -14 -56 3 -127 13
-157 21 -30 7 -74 12 -99 10 -99 -8 -216 -28 -246 -42 -29 -13 -37 -13 -75 0
-64 22 -148 45 -193 53 -22 3 -51 13 -64 21 -14 9 -59 18 -108 21 -46 3 -86 9
-89 13 -8 13 -192 11 -199 -2z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.3 KiB

21
public/site.webmanifest Normal file
View File

@ -0,0 +1,21 @@
{
"name": "Packmate",
"short_name": "Packmate",
"start_url": ".",
"description": "Packet monitoring tool for CTFs.",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#afd9f0",
"background_color": "#ffffff",
"display": "standalone"
}

View File

@ -8,10 +8,4 @@
body {
font-size: .875rem;
}
.feather {
width: 16px;
height: 16px;
vertical-align: text-bottom;
}
</style>

View File

@ -1,19 +1,38 @@
<template>
<main class="col-md-9 ml-sm-auto col-lg-10 px-4">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1>Content</h1>
</div>
<Packet v-for="packet in packets"
:key="packet.id"
:id="packet.id"
:content="packet.content"
:timestamp="packet.timestamp"></Packet>
</main>
</template>
<script lang="ts">
import {Component, Prop, Vue} from "vue-property-decorator";
<script>
import Packet from "@/components/Packet.vue";
@Component
export default class Content extends Vue {
@Prop() private servicePort?: string;
@Prop() private streamId?: string;
}
export default {
name: 'Content',
props: ['servicePort', 'streamId',],
data: function () {
return {
packets: [
{
id: 39,
timestamp: 1556555231394,
content: 'wuAAUEtPbKUAAAAAoAL///jUAAACBAW0BAIIChMcPpEAAAAAAQMDBw==',
},
{
id: 40,
timestamp: 1556555231392,
content: 'AFDC4CVNkpxLT2ymoBJxIIKHAAACBAW0BAIICoTZHMUTHD6RAQMDBw==',
},
],
}
},
components: {Packet,},
}
</script>
<style scoped>

View File

@ -5,27 +5,19 @@
</li>
</template>
<script lang="ts">
import {Component, Prop, Vue} from "vue-property-decorator";
@Component({
methods: {
/**
* Returns true if current component active
* @param input parent prefix
*/
subIsActive(input) {
const paths = Array.isArray(input) ? input : [input];
return paths.some(path => {
return this.$route.path.indexOf(path) === 0;
});
}
}
})
export default class CrfService extends Vue {
@Prop() private port!: number;
@Prop() private name!: string;
}
<script>
export default {
name: "CtfService",
methods: {
subIsActive(prefix) {
const paths = Array.isArray(prefix) ? prefix : [prefix,];
return paths.some(path => {
return this.$route.path.indexOf(path) === 0;
})
},
},
props: ['port', 'name',],
}
</script>
<style scoped>

View File

@ -2,11 +2,6 @@
<nav class="navbar navbar-dark fixed-top bg-dark flex-md-nowrap p-0 shadow navbar-expand-lg navbar-expand">
<router-link to="/" class="navbar-brand col-sm-3 col-md-2 mr-0">Packmate</router-link>
<!-- <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"-->
<!-- aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">-->
<!-- <span class="navbar-toggler-icon"></span>-->
<!-- </button>-->
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<CtfService
@ -18,17 +13,18 @@
<li class="nav-item">
<button type="button" class="btn btn-link">
<svg id="i-plus" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="16" height="16"
fill="none" stroke="#ffffff" stroke-linecap="round" stroke-linejoin="round"
stroke-width="2">
fill="none" stroke="#ffffff" stroke-linecap="round" stroke-linejoin="round"
stroke-width="2">
<path d="M16 2 L16 30 M2 16 L30 16"></path>
</svg>
</button>
</li>
</ul>
<div class="my-2 my-lg-0" style="margin-right: 10px;">
<button type="button" class="btn btn-link">
<button type="button" class="btn btn-link" @click="$emit('settingsButtonClicked')">
<svg id="i-settings" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="16" height="16"
fill="none" stroke="#ffffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
fill="none" stroke="#ffffff" stroke-linecap="round" stroke-linejoin="round"
stroke-width="2">
<path d="M13 2 L13 6 11 7 8 4 4 8 7 11 6 13 2 13 2 19 6 19 7 21 4 24 8 28 11 25 13 26 13 30 19 30 19 26 21 25 24 28 28 24 25 21 26 19 30 19 30 13 26 13 25 11 28 8 24 4 21 7 19 6 19 2 Z"></path>
<circle cx="16" cy="16" r="4"></circle>
</svg>
@ -38,26 +34,23 @@
</nav>
</template>
<script lang="ts">
import {Component, Vue} from "vue-property-decorator";
import CtfService from "@/components/CtfService.vue";
<script>
import CtfService from "@/components/CtfService.vue";
@Component({
data() {
return {
ctfServices: [
{
port: 1337,
name: "ShittyService",
},
],
};
},
components: {CtfService}
})
export default class Navbar extends Vue {
}
export default {
name: "Navbar",
data: function () {
return {
ctfServices: [
{
port: 1337,
name: 'ShittyService',
},
],
}
},
components: {CtfService,},
}
</script>
<style scoped>
@ -85,6 +78,7 @@
border-color: transparent;
box-shadow: 0 0 0 3px rgba(255, 255, 255, .25);
}
svg {
position: absolute;
top: 50%;

40
src/components/Packet.vue Normal file
View File

@ -0,0 +1,40 @@
<template>
<div>
<div>#{{id}} at {{new Date(timestamp * 1000)}}</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>
</div>
</div>
</template>
<script>
import {Hexdump,} from '@/components/hexdump.js' // Why the fuck is this working, Babel?!?!
export default {
name: 'Packet',
props: ['id', 'content', 'timestamp',],
mounted() {
const instance = new Hexdump(atob(this.$props.content), {
container: 'hexdump-' + this.$props.id,
base: 'hex',
width: 16,
ascii: false,
byteGrouping: 1,
html: false,
lineNumber: true,
style: {
lineNumberLeft: '',
lineNumberRight: ':',
stringLeft: '|',
stringRight: '|',
hexLeft: '',
hexRight: '',
hexNull: '.g',
stringNull: '.',
},
});
console.trace('created hexview', instance);
},
}
</script>

View File

@ -1,14 +1,61 @@
<template>
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
Test modal!
<button @click="$emit('close')">
Close
</button>
</div>
</div>
</div>
</template>
<script lang="ts">
import {Component, Vue} from "vue-property-decorator";
@Component
export default class SettingsModal extends Vue {
}
<script>
export default {
name: "SettingsModal",
data: function () {
return {
escapeKeyCallback: (e) => {
if (e.key === 'Escape') this.$emit('close');
},
}
},
mounted() {
document.addEventListener('keyup', this.$data.escapeKeyCallback);
},
beforeDestroy() {
document.removeEventListener('keyup', this.$data.escapeKeyCallback);
},
}
</script>
<style scoped>
.modal-mask {
position: fixed;
z-index: 9998;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .5);
display: table;
transition: opacity .3s ease;
}
.modal-wrapper {
display: table-cell;
vertical-align: middle;
}
.modal-container {
width: 300px;
margin: 0 auto;
padding: 20px 30px;
background-color: #fff;
border-radius: 2px;
box-shadow: 0 2px 8px rgba(0, 0, 0, .33);
transition: all .3s ease;
font-family: Helvetica, Arial, sans-serif;
}
</style>

View File

@ -12,30 +12,26 @@
</nav>
</template>
<script lang="ts">
import {Component, Prop, Vue} from "vue-property-decorator";
import Stream from "@/components/Stream.vue";
<script>
import Stream from "@/components/Stream.vue";
@Component({
components: {Stream},
data() {
return {
streams: [
{
id: 111,
time: 1556411080,
},
]
};
export default {
name: 'Sidebar',
props: ['servicePort', 'streamId',],
data: function () {
return {
streams: [
{
id: 111,
time: 1556411080,
},
],
}
})
export default class Sidebar extends Vue {
@Prop() private servicePort?: string;
@Prop() private streamId?: string;
}
},
components: {Stream,},
}
</script>
<style scoped>
<style>
.sidebar {
position: fixed;
top: 0;

View File

@ -1,7 +1,6 @@
<template>
<li class="nav-item">
<router-link class="nav-link" active-class="active"
:to="{ name: 'home', params: { servicePort: $route.params.servicePort, streamId: id} }">
<router-link class="nav-link" active-class="active" :to="{ name: 'home', params: { servicePort: $route.params.servicePort, streamId: id} }">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>
#{{id}}<br/>
{{time}}
@ -9,19 +8,14 @@
</li>
</template>
<script lang="ts">
import {Component, Prop, Vue} from "vue-property-decorator";
@Component
export default class Stream extends Vue {
@Prop() private id!: number;
@Prop() private time!: number;
}
<script>
export default {
name: "Stream",
props: ['id', 'time',],
}
</script>
<style scoped>
.sidebar .nav-link {
font-weight: 500;
color: #333;

398
src/components/hexdump.js Normal file
View File

@ -0,0 +1,398 @@
// 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;
}
}
};

14
src/main.js Normal file
View File

@ -0,0 +1,14 @@
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import 'bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css'
Vue.config.productionTip = false;
new Vue({
router,
store,
render: h => h(App),
}).$mount('#app');

View File

@ -1,10 +0,0 @@
import Vue from 'vue';
import App from './App.vue';
import router from './router';
Vue.config.productionTip = false;
new Vue({
router,
render: (h) => h(App),
}).$mount('#app');

16
src/router.js Normal file
View File

@ -0,0 +1,16 @@
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
Vue.use(Router);
export default new Router({
routes: [
{
path: '/:servicePort?/:streamId?',
name: 'home',
component: Home,
props: true,
},
],
})

View File

@ -1,24 +0,0 @@
import Vue from 'vue';
import Router from 'vue-router';
import Home from './views/Home.vue';
Vue.use(Router);
export default new Router({
routes: [
{
path: '/:servicePort?/:streamId?',
name: 'home',
component: Home,
props: true,
},
// {
// path: '/about',
// name: 'about',
// // route level code-splitting
// // this generates a separate chunk (about.[hash].js) for this route
// // which is lazy-loaded when the route is visited.
// component: () => import(/* webpackChunkName: "about" */ './views/About.vue'),
// },
],
});

17
src/shims-tsx.d.ts vendored
View File

@ -1,17 +0,0 @@
import Vue, {VNode} from 'vue';
declare global {
namespace JSX {
// tslint:disable no-empty-interface
interface Element extends VNode {
}
// tslint:disable no-empty-interface
interface ElementClass extends Vue {
}
interface IntrinsicElements {
[elem: string]: any;
}
}
}

4
src/shims-vue.d.ts vendored
View File

@ -1,4 +0,0 @@
declare module '*.vue' {
import Vue from 'vue';
export default Vue;
}

16
src/store.js Normal file
View File

@ -0,0 +1,16 @@
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
})

View File

@ -1,31 +1,55 @@
<!--suppress HtmlDeprecatedTag -->
<template>
<div>
<Navbar></Navbar>
<Navbar @settingsButtonClicked="showSettingsModal = true"></Navbar>
<div class="container-fluid">
<div class="row">
<Sidebar :servicePort="servicePort" :streamId="streamId"/>
<Content :servicePort="servicePort" :streamId="streamId"/>
<Sidebar :servicePort="servicePort" :streamId="streamId"></Sidebar>
<Content :servicePort="servicePort" :streamId="streamId"></Content>
</div>
</div>
<transition name="modal">
<SettingsModal v-if="showSettingsModal" @close="showSettingsModal = false"></SettingsModal>
</transition>
</div>
</template>
<script lang="ts">
import {Component, Prop, Vue} from "vue-property-decorator";
import Sidebar from "@/components/Sidebar.vue";
import Content from "@/components/Content.vue";
import Navbar from "@/components/Navbar.vue";
<script>
@Component({
components: {
Navbar,
Sidebar,
Content,
},
})
export default class Home extends Vue {
@Prop() private servicePort?: string;
@Prop() private streamId?: string;
}
import SettingsModal from "@/components/SettingsModal.vue";
import Navbar from "@/components/Navbar.vue";
import Sidebar from "@/components/Sidebar.vue";
import Content from "@/components/Content.vue";
export default {
name: 'Home',
data: function () {
return {
showSettingsModal: false,
}
},
props: ['servicePort', 'streamId',],
components: {
SettingsModal,
Navbar,
Sidebar,
Content,
},
}
</script>
<style scoped>
.modal-enter {
opacity: 0;
}
.modal-leave-active {
opacity: 0;
}
.modal-enter .modal-container,
.modal-leave-active .modal-container {
-webkit-transform: scale(1.1);
transform: scale(1.1);
}
</style>

View File

@ -1,39 +0,0 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env"
],
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}

View File

@ -1,26 +0,0 @@
{
"defaultSeverity": "warning",
"extends": [
"tslint:recommended"
],
"linterOptions": {
"exclude": [
"node_modules/**"
]
},
"rules": {
"quotemark": [
true,
"single"
],
"indent": [
true,
"tabs",
4
],
"interface-name": false,
"ordered-imports": false,
"object-literal-sort-keys": false,
"no-consecutive-blank-lines": false
}
}

View File

@ -1,3 +0,0 @@
module.exports = {
lintOnSave: false,
};