Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/data/txt/http.txtcap
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,17 @@
00b0 63 6f 6d 0d 0a 43 6f 6e 6e 65 63 74 69 6f 6e 3a com..Connection:
00c0 20 4b 65 65 70 2d 41 6c 69 76 65 0d 0a 0d 0a Keep-Alive....

0000 00 e0 81 00 b0 28 00 09 6b 88 f5 c9 08 00 45 00 .....(..k.....E.
0010 00 c1 d2 49 40 00 80 06 c8 5b 0a 00 00 05 cf 2e ...I@....[......
0020 86 5e 0c c3 00 50 a8 00 76 87 7d e0 14 02 50 18 .^...P..v.}...P.
0030 fa f0 ad 62 00 00 48 45 41 44 20 2f 76 34 2f 69 ...b..HEAD /v4/i
0040 75 69 64 65 6e 74 2e 63 61 62 3f 30 33 30 37 30 uident.cab?03070
0050 31 31 32 30 38 20 48 54 54 50 2f 31 2e 31 0d 0a 11208 HTTP/1.1..
0060 41 63 63 65 70 74 3a 20 2a 2f 2a 0d 0a 55 73 65 Accept: */*..Use
0070 72 2d 41 67 65 6e 74 3a 20 49 6e 64 75 73 74 72 r-Agent: Industr
0080 79 20 55 70 64 61 74 65 20 43 6f 6e 74 72 6f 6c y Update Control
0090 0d 0a 48 6f 73 74 3a 20 77 69 6e 64 6f 77 73 75 ..Host: windowsu
00a0 70 64 61 74 65 2e 6d 69 63 72 6f 73 6f 66 74 2e pdate.microsoft.
00b0 63 6f 6d 0d 0a 43 6f 6e 6e 65 63 74 69 6f 6e 3a com..Connection:
00c0 20 4b 65 65 70 2d 41 6c 69 76 65 0d 0a 0d 0a Keep-Alive....

59 changes: 53 additions & 6 deletions src/headerP/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ import {
filter_dict,
tcp_result,
} from ".";
import {
char,
choice,
endOfInput,
everyCharUntil,
many,
many1,
possibly,
regex,
sequence,
tup,
whitespace,
} from "../parser";

export enum tcp_flagE {
"ns",
Expand Down Expand Up @@ -41,6 +54,34 @@ export interface taged_value<T> {
// HACK
const reHexDigits = /^[0-9a-fA-F]+/;

export type parsed_Frame = [
string,
string,
string | null,
string,
string | null
];

export const InputFrameParser = many1<parsed_Frame>(
sequence(
tup(
regex(reHexDigits),
many1(sequence(tup(whitespace, regex(reHexDigits)))).map((res) =>
res.map((e) => e[1]).join("")
),
possibly(whitespace),
everyCharUntil(choice(tup(char("\n"), endOfInput))),
choice(tup(char("\n"), endOfInput))
)
)
);

export const inputFramesParser = many(
sequence<[parsed_Frame[], string | null], null>(
tup(InputFrameParser, possibly(char("\n")))
)
);

export function filter(o: string[][], data: header_type[]): any {
let cond_parm = ["arp", "ipv4", "ipv6", "tcp", "http", "icmp"];
let arg_parm: { [key: string]: (x: header_type, e: string) => boolean } = {
Expand Down Expand Up @@ -210,12 +251,18 @@ export const convertToBin = (data: string): Uint8Array => {
};

// cleaning the offset, the hex-visualisation, and the spaces
export const cleanInput = (data: string): string => {
return data
.split("\n")
.map((s) => s.slice(5, Math.min(s.length, 54)))
.join("")
.replace(/\s/g, "");
export const cleanInput = (data: string) => {
let result = inputFramesParser.run(data);

if (result.isError) {
console.log(result);
throw new Error(result.error as string);
}

let unwraped = result.result.map((x) => x[0].map((frame) => frame[1]));
let out: string[] = [];
for (let a in unwraped) out = [...out, ...unwraped[a]];
return out.join("");
};

// Use it only if executed by <ts->node <!>
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import cli from "./cli";

cli();
cli()
73 changes: 73 additions & 0 deletions src/parser/pComb.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Parser, { ParserTuple } from "./parser";
import ParserState from "./pState";
import { decoder } from "./utils";

/** Takes an array of parsers, and returns a new parser that matches each of them sequentially, collecting up the results into an array. */
export const sequence = <R extends any[], D>(parsers: ParserTuple<R, D>) =>
Expand All @@ -26,6 +27,7 @@ export const many = function many<T>(parser: Parser<T>): Parser<T[]> {

while (true) {
const out = parser.pf(nextState);
console.log(out.index)

if (out.isError) {
break;
Expand Down Expand Up @@ -87,3 +89,74 @@ export function coroutine<T>(parserFn: ParserFn<T>): Parser<T> {
}
});
}

export const many1 = function many1<T>(parser: Parser<T>): Parser<T[]> {
return new Parser(function many1$state(state) {
if (state.isError) return state;

const resState = many(parser).pf(state);
if (resState.result.length) return resState;

return state.updateError(
`ParseError 'many1' (position ${state.index}): Expecting to match at least one value`
);
});
};

export function everythingUntil(parser: Parser<any>): Parser<number[]> {
return new Parser((state) => {
if (state.isError) return state;

const results = [];
let nextState = state;

while (true) {
const out = parser.pf(nextState);

if (out.isError) {
const { index, dataView } = nextState;

if (dataView.byteLength <= index) {
return nextState.updateError(
`ParseError 'everythingUntil' (position ${nextState.index}): Unexpected end of input.`
);
}

const val = dataView.getUint8(index);
if (val) {
results.push(val);
nextState = nextState.updateByteIndex(1).updateResult(val);
}
} else {
break;
}
}

return nextState.updateResult(results);
});
}
// TODO type return type
export const choice = <R extends any[], D>(parsers: ParserTuple<R, D>) => {
if (parsers.length === 0) throw new Error(`List of parsers can't be empty.`);

return new Parser(function choice$state(state) {
if (state.isError) return state;

let error = null;
for (const parser of parsers) {
const out = parser.pf(state);

if (!out.isError) return out;

if (error === null || (error && out.index > error.index)) {
error = out;
}
}

return error as ParserState<any, any>;
});
};

export const everyCharUntil = (parser: Parser<any>) => everythingUntil(parser)
.map(results => decoder.decode(Uint8Array.from(results)));

81 changes: 81 additions & 0 deletions src/parser/pGen.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import Parser, { ParsingFunction } from "./parser";
import { many } from "./pComb";
import ParserState, { InputTypes } from "./pState";
import {
encoder,
getCharacterLength,
getNextCharWidth,
getString,
getUtf8Char,
reLetter,
reLetters,
reWhitespaces,
} from "./utils";

/* doesn't support the bitOffset <!>*/
Expand Down Expand Up @@ -95,3 +103,76 @@ export const addIndex = (n: number) =>

export const addByteIndex = (n: number) =>
new Parser((s) => (s.isError ? s : s.updateBitIndex(n)));

export const whitespace: Parser<string> = regex(reWhitespaces).errorMap(
({ index }) =>
`ParseError 'whitespace' (position ${index}): Expecting to match at least one space`
);

export const letters: Parser<string> = regex(reLetters).errorMap(
({ index }) =>
`ParseError 'letters' (position ${index}): expecting to match at least one letter`
);

export const char = function char(c: string): Parser<string> {
if (!c || getCharacterLength(c) !== 1) {
throw new TypeError(
`char must be called with a single character, but got ${c}`
);
}

return new Parser(function char$state(state) {
if (state.isError) return state;

const { index, dataView } = state;
if (index < dataView.byteLength) {
const charWidth = getNextCharWidth(index, dataView);
if (index + charWidth <= dataView.byteLength) {
const char = getUtf8Char(index, charWidth, dataView);
return char === c
? state.updateByteIndex(charWidth).updateResult(c)
: state.updateError(
`ParseError (position ${index}): Expecting character '${c}', got '${char}'`
);
}
}
return state.updateError(
`ParseError (position ${index}): Expecting character '${c}', but got end of input.`
);
});
};

export const anyChar: Parser<string> = new Parser(function anyChar$state(
state
) {
if (state.isError) return state;

const { index, dataView } = state;
if (index < dataView.byteLength) {
const charWidth = getNextCharWidth(index, dataView);
if (index + charWidth <= dataView.byteLength) {
const char = getUtf8Char(index, charWidth, dataView);
return state.updateByteIndex(charWidth).updateResult(char);
}
}
return state.updateError(
`ParseError (position ${index}): Expecting a character, but got end of input.`
);
});

export const endOfInput = new Parser<null>(function endOfInput$state(state) {
if (state.isError) return state;
const { dataView, index, inputType } = state;
if (index !== dataView.byteLength) {
const errorByte =
inputType === InputTypes.STRING
? String.fromCharCode(dataView.getUint8(index))
: `0x${dataView.getUint8(index).toString(16).padStart(2, "0")}`;

return state.updateError(
`ParseError 'endOfInput' (position ${index}): Expected end of input but got '${errorByte}'`
);
}

return state.updateResult(null);
});