Skip to content

Commit

Permalink
Merge pull request #313 from TFNS/269-parser-logic-improvement
Browse files Browse the repository at this point in the history
Parser logic improvements
  • Loading branch information
JJ-8 authored Aug 24, 2024
2 parents 4045522 + 10d5afa commit 4ea6b91
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 103 deletions.
84 changes: 77 additions & 7 deletions front/src/components/Dialogs/TaskImportDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,29 @@
<template #prepend>
<q-icon name="data_object" />
</template>
<template #option="scope">
<q-item v-bind="scope.itemProps">
<q-item-section>
<q-item-label class="flex">
{{ scope.opt.label }}
<q-space />
{{
scope.opt.amount > 0 ? `(${scope.opt.amount})` : '(0)'
}}
</q-item-label>
</q-item-section>
</q-item>
</template>
<template #selected-item="scope">
<q-item-section>
<q-item-label>
{{ scope.opt.label }}
{{
scope.opt.amount > 0 ? `(${scope.opt.amount})` : '(0)'
}}
</q-item-label>
</q-item-section>
</template>
</q-select>

<q-input
Expand All @@ -41,7 +64,10 @@
'font-family': 'monospace',
}"
:hint="currentParser.value.hint"
@paste="onPaste"
@paste="detectParser"
@blur="detectParser"
@focus="detectParser"
@update:model-value="detectParser"
/>
</div>
</q-tab-panel>
Expand Down Expand Up @@ -95,6 +121,7 @@ import { Ctf, makeId } from 'src/ctfnote/models';
import parsers, { ParsedTask } from 'src/ctfnote/parsers';
import { defineComponent, ref } from 'vue';
import TaskTagsList from 'src/components/Task/TaskTagsList.vue';
import RawParser from 'src/ctfnote/parsers/raw';
export default defineComponent({
components: {
Expand All @@ -107,7 +134,11 @@ export default defineComponent({
setup() {
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
useDialogPluginComponent();
const parserOptions = parsers.map((p) => ({ label: p.name, value: p }));
const parserOptions = parsers.map((p) => ({
label: p.name,
value: p,
amount: 0,
}));
const columns = [
{ name: 'keep', label: '', field: 'keep' },
Expand Down Expand Up @@ -165,14 +196,53 @@ export default defineComponent({
}
},
autoDetectParser() {
for (const parser of parsers) {
if (parser.isValid(this.model)) {
const p = this.parserOptions.find((opt) => opt.value == parser);
if (p) this.currentParser = p;
const outputOfParser = parsers.map((p) => {
let challenges: ParsedTask[] = [];
try {
challenges = p.parse(this.model);
} catch (e) {}
return {
parser: p,
challenges: challenges,
};
});
// assign the amount of challenges to the parser options
this.parserOptions.forEach((opt) => {
const parser = outputOfParser.find(
(p) => p.parser.name === opt.value.name
);
if (parser) {
opt.amount = parser.challenges.length;
}
});
// find the parser with the most tasks, but exclude the raw parser
// since it will count the amount of newlines which does not always make sense
const max = outputOfParser
.filter((p) => p.parser.name !== RawParser.name)
.reduce(
(acc, cur) =>
cur.challenges.length > acc ? cur.challenges.length : acc,
0
);
const bestParser = outputOfParser.find((p) => p.challenges.length == max);
if (
bestParser &&
bestParser.challenges.length > 0 &&
(bestParser.challenges.length > this.currentParser.amount ||
this.currentParser.label == RawParser.name) // it must be an improvement, except overriding the raw parser is allowed
) {
const p = this.parserOptions.find(
(opt) => opt.value == bestParser.parser
);
if (p) this.currentParser = p;
} else if (this.currentParser.amount == 0) {
this.currentParser = this.parserOptions[0];
}
},
onPaste() {
detectParser() {
void this.$nextTick(() => this.autoDetectParser());
},
normalizeTags(tags: string[]): string[] {
Expand Down
15 changes: 1 addition & 14 deletions front/src/ctfnote/parsers/angstrom.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ParsedTask, Parser } from '.';
import { parseJson, parseJsonStrict } from '../utils';
import { parseJsonStrict } from '../utils';

const AngstromParser: Parser = {
name: 'ångstromCTF parser',
Expand All @@ -26,19 +26,6 @@ const AngstromParser: Parser = {
}
return tasks;
},
isValid(s) {
const data =
parseJson<
Array<{ title: string; category: string; description: string }>
>(s);
return (
Array.isArray(data) &&
data.length > 0 &&
data[0].title != null &&
data[0].category != null &&
data[0].description != null
);
},
};

export default AngstromParser;
7 changes: 1 addition & 6 deletions front/src/ctfnote/parsers/cini.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ParsedTask, Parser } from '.';
import { parseJson, parseJsonStrict } from '../utils';
import { parseJsonStrict } from '../utils';

interface Events {
gamePause?: unknown;
Expand Down Expand Up @@ -46,11 +46,6 @@ const CINIParser: Parser = {

return tasks;
},
isValid(s) {
const data = parseJson<Events>(s);
if (data == null) return false;
return data.gamePause !== undefined && data.events !== undefined;
},
};

export default CINIParser;
6 changes: 1 addition & 5 deletions front/src/ctfnote/parsers/ctfd.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ParsedTask, Parser } from '.';
import { parseJson, parseJsonStrict } from '../utils';
import { parseJsonStrict } from '../utils';

interface CTFdTags {
value: string;
Expand Down Expand Up @@ -30,10 +30,6 @@ const CTFDParser: Parser = {
}
return tasks;
},
isValid(s) {
const data = parseJson<{ data?: unknown }>(s);
return Array.isArray(data?.data);
},
};

export default CTFDParser;
14 changes: 0 additions & 14 deletions front/src/ctfnote/parsers/hitcon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,6 @@ const HitconParser: Parser = {

return tasks;
},
isValid(s) {
const data =
parseJsonStrict<
[{ name: string; category: string; description: string }]
>(s);
if (data == null || data.length < 1) {
return false;
}
return (
data[0].name != null &&
data[0].category != null &&
data[0].description != null
);
},
};

export default HitconParser;
13 changes: 1 addition & 12 deletions front/src/ctfnote/parsers/htb.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ParsedTask, Parser } from '.';
import { parseJson, parseJsonStrict } from '../utils';
import { parseJsonStrict } from '../utils';

// output of https://ctf.hackthebox.com/api/public/challengeCategories
const challengeCategories: { [index: number]: string } = {
Expand Down Expand Up @@ -67,17 +67,6 @@ const HTBParser: Parser = {
}
return tasks;
},
isValid(s) {
const data = parseJson<{
challenges: Array<{
id: number;
name: string;
description: string;
challenge_category_id: number;
}>;
}>(s);
return Array.isArray(data?.challenges);
},
};

export default HTBParser;
1 change: 0 additions & 1 deletion front/src/ctfnote/parsers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export type ParsedTask = {
export type Parser = {
name: string;
hint: string;
isValid(s: string): boolean;
parse(s: string): ParsedTask[];
};

Expand Down
31 changes: 6 additions & 25 deletions front/src/ctfnote/parsers/justctf.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ParsedTask, Parser } from '.';
import { parseJson, parseJsonStrict } from '../utils';
import { parseJsonStrict } from '../utils';

const justCTFParser: Parser = {
name: 'justCTF parser',
Expand All @@ -25,7 +25,11 @@ const justCTFParser: Parser = {
}

for (const challenge of data) {
if (!challenge.description || !challenge.name) {
if (
!challenge.description ||
!challenge.name ||
!Array.isArray(challenge.categories)
) {
continue;
}

Expand All @@ -37,29 +41,6 @@ const justCTFParser: Parser = {
}
return tasks;
},
isValid(s) {
const data = parseJson<
[
{
id: number;
name: string;
categories: [string];
difficult: string;
description: string;
points: number;
solvers: number;
}
]
>(s);
return (
data != null &&
data?.length > 0 &&
data[0].id != null &&
data[0].name != null &&
Array.isArray(data[0].categories) &&
data[0].points != null
);
},
};

export default justCTFParser;
14 changes: 1 addition & 13 deletions front/src/ctfnote/parsers/pico.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ParsedTask, Parser } from '.';
import { parseJson, parseJsonStrict } from '../utils';
import { parseJsonStrict } from '../utils';

const PicoParser: Parser = {
name: 'picoCTF parser',
Expand All @@ -21,18 +21,6 @@ const PicoParser: Parser = {
}
return tasks;
},
isValid(s) {
const data = parseJson<{
results: Array<{ name: string; category: { name: string } }>;
}>(s);
return (
data?.results != null &&
Array.isArray(data?.results) &&
data?.results.length > 0 &&
data?.results[0].name != null &&
data?.results[0].category.name != null
);
},
};

export default PicoParser;
6 changes: 0 additions & 6 deletions front/src/ctfnote/parsers/raw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,6 @@ const RawParser: Parser = {
}
return tasks;
},
isValid(s) {
return s
.trim()
.split('\n')
.every((s) => /[^|]+\|[^|]+/.exec(s));
},
};

export default RawParser;

0 comments on commit 4ea6b91

Please sign in to comment.