Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- {=======================================================================================]
- | |
- | _____ _ _ _____ _ _ _____ |
- | | __|_|_____| |_ ___ | __|___ ___|_|___| |_ | __|___ ___ ___ ___ ___ ___ |
- | |__ | | | . | .'| |__ | _| _| | . | _| |__ | _| .'| | | -_| _| |
- | |_____|_|_|_|_|___|__,| |_____|___|_| |_| _|_| |_____|___|__,|_|_|_|_|___|_| |
- | |_| |
- | ..by Officer Barbrady & Janilabo |
- [=======================================================================================}
- const
- SOCKET_SCAN = True; // Scan for Socket Threats?
- HTTP_SCAN = True; // Scan for HTTP Threats?
- WEB_SCAN = True; // Scan for Web Threats?
- FILE_SCAN = True; // Scan for File Threats?
- CODE_SCAN = True; // Scan for Fishy Code and Unhuman (abnormal) Code?
- FILTER_COMMENTS = True; // Doesn't pay attention to stuff inside comments
- // Recommended to keep this feature enabled, a lot less false positives!
- COMMENT_FILTER = '@'; // CHAR, NOT STRING! Used in debug box for displaying the filtered comments (doesn't effect scan, as these will be empty chars in filteredScriptText for scan).
- FILTER_STRINGS = True; // Doesn't pay attention to stuff INSIDE string signs.
- // So, this feature still detects stuff that falls outside those '' signs! :)
- STRING_FILTER = '%'; // CHAR, NOT STRING! Used in debug box for displaying the filtered strings (doesn't effect scan, these will be empty chars in filteredScriptText for scan).
- DEBUG_FILTERED_SCRIPT = True; // Debug the script, that was filtered (used for most script parts), before scan statistics (displays empty chars with COMMENT_FILTER & STRING_FILTER).
- DEBUG_SCAN_STEPS = True;
- GUI_WIDTH = 800;
- GUI_HEIGHT = 500;
- DEFAULT = 'Times New Roman';
- VERSION = 1.66; // Don't touch... Script version.
- POINTS_VERY_LOW = 1;
- POINTS_LOW = 2; // DON'T TOUCH!
- POINTS_MEDIUM = 4; // DON'T TOUCH!
- POINTS_HIGH = 6; // DON'T TOUCH!
- POINTS_VERY_HIGH = 9; // DON'T TOUCH!
- type
- TMatchMethod = (mmAll, mmIgnoreCase, mmOverlap, mmWholeWords, mmStrictWW, mmGreedyRegex);
- TMatchMethods = set of TMatchMethod;
- TRegexMatch = record
- position, size: Integer;
- text: string;
- end;
- TRegexMatchArray = array of TRegexMatch;
- T2DRegexMatchArray = array of TRegexMatchArray;
- TRegexModifier = (rm_G, rm_I, rm_M, rm_S, rm_X, rm_R);
- TRegexModifiers = set of TRegexModifier;
- TRange = record
- minimum, maximum: Integer;
- end;
- TRangeArray = array of TRange;
- TRiskLevel = (rl_VeryLow, rl_Low, rl_Medium, rl_High, rl_VeryHigh);
- TScanInformation = record
- points: Integer;
- timeStamp: string;
- lineTracker: array of array[0..2] of Integer;
- foundThreats, timing: Integer;
- threat: array of record
- name, timeStamp: string;
- enabled: Boolean;
- foundItems, timing: Integer;
- item: array of record
- caption, message, description, timeStamp: string;
- riskLevel: TRiskLevel;
- enabled: Boolean;
- timing: Integer;
- detect: record
- text: string;
- regex: Boolean;
- methods: TMatchMethods;
- requirement: record
- minimum, maximum: Integer;
- end;
- filters: array of record
- text: string;
- regexTags: array of Char;
- regexStrs: TStringArray;
- modifiers: TRegexModifiers;
- positions: TRangeArray;
- end;
- end;
- found: array of record
- timeStamp: string;
- position: TRange;
- line: Integer;
- end;
- end;
- end;
- script: record
- original, display, filtered: string;
- linePositions: TIntegerArray;
- end;
- end;
- var
- DsgnForm: TForm;
- ScriptEdit: TMemo;
- ScanButton, UpdateButton: TButton;
- totalTiming: Integer;
- pressed: Boolean;
- data: TScanInformation;
- procedure Append(var str: string; data: string);
- begin
- str := (str + data);
- end;
- function CenterEx(str: string; size: Integer; fill: Char): string;
- var
- l, p: Integer;
- begin
- l := Length(str);
- case (l < size) of
- True:
- case (l = 0) of
- False:
- begin
- p := (((size - l) div 2) + 1);
- Result := (StringOfChar(fill, (p - 1)) + str + StringOfChar(fill, ((size - (p + l)) + 1)));
- end;
- True: Result := StringOfChar(fill, size);
- end;
- False: Result := str;
- end;
- end;
- function ParseTextReport: string;
- var
- t, i, h, f, cs, ts, x, y: Integer;
- r, li, kd, th: string;
- begin
- Result := '';
- Append(Result, '*************************************************' + #13#10);
- Append(Result, '* _ _ _ _ _ _ _ _ __ *' + #13#10);
- Append(Result, '* /_`/ `/_//|/ /_//_`/_// //_// *' + #13#10);
- Append(Result, '* ._//_,/ // | / \/_,/ /_// \/ *' + #13#10);
- Append(Result, '* *' + #13#10);
- Append(Result, '*************************************************' + #13#10);
- Append(Result, ' ' + #13#10);
- if DEBUG_FILTERED_SCRIPT then
- if (data.script.display <> '') then
- begin
- Append(Result, '<===============[Filtered Script]===============>' + #13#10);
- Append(Result, data.script.display + #13#10);
- Append(Result, '<===============================================>' + #13#10);
- Append(Result, ' ' + #13#10);
- end;
- if DEBUG_SCAN_STEPS then
- begin
- for t := 0 to High(data.threat) do
- if (data.threat[t].enabled) then
- Inc(ts);
- Append(Result, '<=================[Scan Steps]==================>' + #13#10);
- Append(Result,' ┌────────────────────────────────────────────── ' + #13#10);
- for t := 0 to High(data.threat) do
- begin
- if data.threat[t].enabled then
- begin
- Append(Result, (' ├─<' + data.threat[t].timeStamp + '> Step ' + IntToStr(cs + 1) + '/' + IntToStr(ts) + ' - ' + data.threat[t].name + 's [' + IntToStr(data.threat[t].timing) + ' ms.]') + #13#10);
- Inc(cs);
- for i := 0 to High(data.threat[t].item) do
- if data.threat[t].item[i].enabled then
- begin
- Append(Result, (' ├───<' + data.threat[t].item[i].timeStamp + '> Scan for ' + data.threat[t].item[i].caption + ' [' + IntToStr(data.threat[t].item[i].timing) + ' ms.]') + #13#10);
- h := High(data.threat[t].item[i].found);
- if (h > -1) then
- begin
- if (h > 0) then
- Append(Result, (' ├─────<' + data.threat[t].item[i].found[0].timeStamp + '> DETECTED ' + IntToStr(h + 1) + ' THREATS:') + #13#10)
- else
- Append(Result, (' ├─────<' + data.threat[t].item[i].found[0].timeStamp + '> DETECTED ' + IntToStr(h + 1) + ' THREAT:') + #13#10);
- for f := 0 to h do
- case (data.threat[t].item[i].found[f].line = -1) of
- True: Append(Result, (' ├───────<' + data.threat[t].item[i].found[f].timeStamp + '> Could not find ' + data.threat[t].item[i].caption + ' @ ANY line!') + #13#10);
- False: Append(Result, (' ├───────<' + data.threat[t].item[i].found[f].timeStamp + '> Found ' + data.threat[t].item[i].caption + ' @ line ' + IntToStr(data.threat[t].item[i].found[f].line) + '!') + #13#10);
- end;
- end;
- end;
- end;
- if ((cs > 0) and (cs < ts)) then
- Append(Result, ' │' + #13#10);
- end;
- Append(Result, ' └────────────────────────────────────────────── ' + #13#10);
- Append(Result, CenterEx(('--- Scanning ' + IntToStr(Length(data.script.linePositions)) + ' lines took ' + IntToStr(data.timing) + ' ms. ---'), 49, ' ') + #13#10);
- Append(Result, '<===============================================>' + #13#10);
- Append(Result, ' ' + #13#10);
- end;
- for t := 0 to High(data.threat) do
- if data.threat[t].enabled then
- if (data.threat[t].foundItems > 0) then
- begin
- Append(Result, ('<' + CenterEx(('[Messages for ' + data.threat[t].name + 's]'), 47, '=') + '>') + #13#10);
- for i := 0 to High(data.threat[t].item) do
- begin
- h := High(data.threat[t].item[i].found);
- if (h > -1) then
- begin
- case data.threat[t].item[i].riskLevel of
- rl_VeryLow: r := 'VERY LOW';
- rl_Low: r := 'LOW';
- rl_Medium: r := 'MEDIUM';
- rl_High: r := 'HIGH';
- rl_VeryHigh: r := 'VERY HIGH';
- end;
- Append(Result, (' ' + data.threat[t].item[i].message + ' [Risk level: ' + r + ']') + #13#10);
- end;
- end;
- Append(Result, '<===============================================>' + #13#10);
- Append(Result, ' ' + #13#10);
- end;
- y := Length(data.lineTracker);
- if (y > 0) then
- begin
- Append(Result, '<=============[Lines with Threats]==============>' + #13#10);
- Append(Result, ' LINE | KIND | THREAT ' + #13#10);
- Append(Result, ' -----+----------------+------------------------ ' + #13#10);
- for x := 0 to (y - 1) do
- begin
- case (data.threat[data.lineTracker[x][0]].item[data.lineTracker[x][1]].found[data.lineTracker[x][2]].line > -1) of
- True: li := IntToStr(data.threat[data.lineTracker[x][0]].item[data.lineTracker[x][1]].found[data.lineTracker[x][2]].line);
- False: li := 'NONE';
- end;
- kd := data.threat[data.lineTracker[x][0]].name;
- th := data.threat[data.lineTracker[x][0]].item[data.lineTracker[x][1]].caption;
- Append(Result, ' ' + (li + Padr(' ', (Length(' LINE |') - Length(li)) - 2)) + '| ' + (kd + Padr(' ', (Length(' KIND |') - Length(kd)) - 2)) + '| ' + th + #13#10);
- end;
- Append(Result, '<===============================================>' + #13#10);
- Append(Result, ' ' + #13#10);
- end;
- case data.points of
- 0: r := 'None';
- 1..2: r := 'Very Low';
- 3..5: r := 'Low';
- 6..9: r := 'Medium';
- 10..14: r := 'High';
- else
- r := 'Very High';
- end;
- Append(Result, '<================[Scan Results]=================>' + #13#10);
- for t := 0 to High(data.threat) do
- begin
- kd := (data.threat[t].name + 's');
- Append(Result, ' ' + kd + StringOfChar('.', (47 - (Length(kd) + Length(IntToStr(data.threat[t].foundItems))))) + IntToStr(data.threat[t].foundItems) + #13#10);
- end;
- Append(Result, ' -----------------------------------------------' + #13#10);
- Append(Result, ' Overall threats' + StringOfChar('.', (47 - (Length('Overall threats') + Length(IntToStr(data.foundThreats))))) + IntToStr(data.foundThreats) + #13#10);
- Append(Result, ' Script Risk Level' + StringOfChar('.', (47 - (Length('Script Risk Level') + Length(r)))) + r + #13#10);
- Append(Result, '<===============================================>' + #13#10);
- Append(Result, ' ' + #13#10);
- Append(Result, '<===================[FINISHED]==================>' + #13#10);
- Append(Result, ' Remember to visit the thread for latest updates.' + #13#10);
- Append(Result, ' Thank you for using! ' + #13#10);
- r := '~ Total Time Taken ' + IntToStr(GetSystemTime - totalTiming) + ' ms. ~';
- Append(Result, StringOfChar(' ', Round((49 - Length(r)) div 2)) + r + #13#10);
- Append(Result, '<===============================================>');
- end;
- function AddThreat(var x: TScanInformation; name: string): Integer;
- var
- l: Integer;
- begin
- l := Length(x.threat);
- SetLength(x.threat, (l + 1));
- x.threat[l].name := name;
- Result := l;
- end;
- function AddItem(var x: TScanInformation; threatID: Integer; caption, message, description: string; riskLevel: TRiskLevel; detectText: string; detectRegex: Boolean; detectMethods: TMatchMethods; detectMinReq, detectMaxReq: Integer): Integer;
- var
- l: Integer;
- begin
- Result := -1;
- if ((threatID < 0) or (High(x.threat) < threatID)) then
- Exit;
- l := Length(x.threat[threatID].item);
- SetLength(x.threat[threatID].item, (l + 1));
- x.threat[threatID].item[l].caption := caption;
- x.threat[threatID].item[l].message := message;
- x.threat[threatID].item[l].description := description;
- x.threat[threatID].item[l].riskLevel := riskLevel;
- x.threat[threatID].item[l].detect.text := detectText;
- x.threat[threatID].item[l].detect.regex := detectRegex;
- x.threat[threatID].item[l].detect.methods := detectMethods;
- x.threat[threatID].item[l].detect.requirement.minimum := detectMinReq;
- x.threat[threatID].item[l].detect.requirement.maximum := detectMaxReq;
- Result := l;
- end;
- function AddFilter( var x: TScanInformation; threatID, itemID: Integer; text: string; regexTags: array of Char; regexStrs: TStringArray; modifiers: TRegexModifiers): Integer;
- var
- l, h, i: Integer;
- begin
- Result := -1;
- if ((threatID > -1) and (High(x.threat) >= threatID)) then
- if ((itemID > -1) and (High(x.threat[threatID].item) >= itemID)) then
- begin
- l := Length(x.threat[threatID].item[itemID].detect.filters);
- SetLength(x.threat[threatID].item[itemID].detect.filters, (l + 1));
- x.threat[threatID].item[itemID].detect.filters[l].text := text;
- h := Min(High(regexTags), High(regexStrs));
- SetLength(x.threat[threatID].item[itemID].detect.filters[l].regexTags, (h + 1));
- for i := 0 to h do
- x.threat[threatID].item[itemID].detect.filters[l].regexTags[i] := regexTags[i];
- SetLength(x.threat[threatID].item[itemID].detect.filters[l].regexStrs, (h + 1));
- for i := 0 to h do
- x.threat[threatID].item[itemID].detect.filters[l].regexStrs[i] := regexStrs[i];
- x.threat[threatID].item[itemID].detect.filters[l].modifiers := TRegexModifiers(modifiers);
- Result := l;
- end;
- end;
- procedure SetupThreats;
- var
- tmp, r_tmp: TStringArray;
- i, f1, f2: Integer;
- ID: TIntegerArray;
- rl: array of TRiskLevel;
- begin
- {THREATS}
- tmp := ['Socket Threat', 'HTTP Threat', 'Web Threat', 'File Threat', 'Fishy Code', 'Unhuman Code'];
- SetLength(ID, (High(tmp) + 1));
- for i := 0 to High(tmp) do
- ID[i] := AddThreat(data, tmp[i]);
- {SOCKET}
- rl := [rl_VeryHigh, rl_VeryHigh, rl_VeryHigh, rl_High, rl_High, rl_High, rl_High, rl_High];
- tmp := ['CreateSocket', 'ConnectSocket', 'SendSocket', 'RecvSocket', 'RecvSocketStr', 'RecvSocketEx', 'BindSocket', 'SocketInfo'];
- for i := 0 to High(tmp) do
- AddItem(data, ID[0], tmp[i], 'Found "' + tmp[i] + '"', '-', rl[i], Lowercase(tmp[i]), False, [mmAll, mmIgnoreCase, mmWholeWords], 1, -1);
- {HTTP}
- rl := [rl_VeryHigh, rl_High, rl_High, rl_High, rl_Medium, rl_Medium, rl_Medium, rl_High, rl_High];
- tmp := ['AddPostVariable', 'GetPage', 'PostHTTPPage', 'PostHTTPPageEx', 'GetRawHeaders', 'SetHTTPUserAgent', 'GetHTTPPage', 'InitializeHTTPClient', 'InitializeHTTPClientWrap'];
- for i := 0 to High(tmp) do
- AddItem(data, ID[1], tmp[i], 'Found "' + tmp[i] + '"', '-', rl[i], Lowercase(tmp[i]), False, [mmAll, mmIgnoreCase, mmWholeWords], 1, -1);
- {WEB}
- AddItem(data, ID[2], 'OpenWebPage', 'Found "OpenWebPage"', '-', rl_High, 'openwebpage', False, [mmAll, mmIgnoreCase, mmWholeWords], 1, -1);
- {FILE}
- rl := [rl_High, rl_High, rl_VeryHigh, rl_Medium, rl_High, rl_Medium, rl_Medium, rl_High, rl_High, rl_Medium, rl_Medium, rl_VeryHigh, rl_VeryHigh, rl_High, rl_Low, rl_VeryHigh];
- tmp := ['CreateFile', 'OpenFile', 'RewriteFile', 'ReadFileString', 'WriteFileString', 'DirectoryExists', 'FileExists', 'CreateDirectory', 'ForceDirectories', 'GetFiles', 'GetDirectories', 'DeleteFile', 'RenameFile', 'WriteINI', 'ReadINI', 'DeleteINI'];
- for i := 0 to High(tmp) do
- AddItem(data, ID[3], tmp[i], 'Found "' + tmp[i] + '(*)"', '-', rl[i], Lowercase(tmp[i]), False, [mmAll, mmIgnoreCase, mmWholeWords], 1, -1);
- {FISHY}
- rl := [rl_Medium, rl_VeryHigh, rl_High];
- tmp := ['Name', 'Pass', 'Pin'];
- for i := 0 to High(tmp) do
- case i of
- 0: f1 := AddItem(data, ID[4], tmp[i], 'The variable "' + tmp[i] + '" is used more then once', '-', rl[i], Lowercase(tmp[i]), False, [mmAll, mmIgnoreCase, mmWholeWords], 2, -1);
- 2: f2 := AddItem(data, ID[4], tmp[i], 'The variable "' + tmp[i] + '" is used more then once', '-', rl[i], Lowercase(tmp[i]), False, [mmAll, mmIgnoreCase, mmWholeWords], 2, -1);
- else
- AddItem(data, ID[4], tmp[i], 'The variable "' + tmp[i] + '" is used more then once', '-', rl[i], Lowercase(tmp[i]), False, [mmAll, mmIgnoreCase, mmWholeWords], 2, -1);
- end;
- AddFilter(data, ID[4], f1, 'font . name', [' '], ['(\s*)'], [rm_I]);
- AddFilter(data, ID[4], f2, ' inpin @', [' ', '@'], ['(\s*)', '(\()(\s*)players(\s*)(\[)(\s*)\w+(\s*)(\])(\s*)(\.)(\s*)pin(\s*)(\))'], [rm_I]);
- AddItem(data, ID[4], 'ToStr(Players[*])', 'Player data sent to ToStr()', '-', rl_VeryHigh, 'ToStr(\s*)(\()(\s*)players(\s*)(\[)(\s*)[a-zA-Z0-9]*(\s*)(\])(\s*)(\))', True, [mmAll, mmIgnoreCase, mmWholeWords], 1, -1);
- rl := [rl_Medium, rl_Medium, rl_Medium, rl_Medium, rl_High, rl_High, rl_Medium, rl_Medium];
- tmp := ['TradeScreen', 'SomeoneTrades', 'GetTradersName', 'TradeScreenName', 'AcceptTrade', 'Accept', 'Waiting', 'PlayerAccepted'];
- for i := 0 to High(tmp) do
- AddItem(data, ID[4], tmp[i], 'Picked up trading activity command "' + tmp[i] + '" (UNUSUAL)', '-', rl[i], Lowercase(tmp[i]), False, [mmAll, mmIgnoreCase, mmWholeWords], 1, -1);
- {UNHUMAN}
- rl := [rl_Low, rl_Low];
- tmp := ['MMouse(x, y, 1, 1)', 'Mouse(x, y, 1, 1, *)'];
- r_tmp := ['(\W)mmouse(\s*)(\()(\s*)x(\s*),(\s*)y(\s*),(\s*)1(\s*),(\s*)1(\s*)(\))', '(\W)mouse(\s*)(\()(\s*)x(\s*),(\s*)y(\s*),(\s*)1(\s*),(\s*)1(\s*),(.*?)(\))'];
- for i := 0 to High(r_tmp) do
- AddItem(data, ID[5], tmp[i], 'Found "' + tmp[i] + '" (potential ban)', '-', rl[i], Lowercase(r_tmp[i]), True, [mmAll, mmIgnoreCase], 1, -1);
- AddItem(data, ID[5], 'Random[Range]', 'Couldn''t find any randomness in script (potential ban)', '-', rl_Medium, '((\W)random(\s*)|(\W)randomrange(\s*))', True, [mmAll, mmIgnoreCase, mmWholeWords], 0, 0);
- SetLength(r_tmp, 0);
- SetLength(tmp, 0);
- end;
- function OpenWebsite(site: string): Boolean;
- begin
- site := Trim(site);
- Result := (Pos('.', site) > 0);
- if Result then
- OpenWebPage(site);
- end;
- function TimeStamp: string;
- var
- Hours, Minutes, Seconds, Milliseconds: Word;
- tTSA: TStringArray;
- i: Integer;
- begin
- DecodeTime(Now, Hours, Minutes, Seconds, Milliseconds);
- if (Hours > 23) then
- Hours := 0;
- tTSA := [IntToStr(Hours), IntToStr(Minutes), IntToStr(Seconds), IntToStr(Milliseconds)];
- for i := 0 to 2 do
- if (StrToInt(tTSA[i]) < 10) then
- tTSA[i] := ('0' + string(tTSA[i]));
- while (Length(tTSA[3]) < 3) do
- tTSA[3] := (string(tTSA[3]) + '0');
- Result := string(tTSA[0] + ':' + tTSA[1] + ':' + tTSA[2] + ':' + tTSA[3]);
- end;
- procedure TIADelete(var TIA: TIntegerArray; x: Integer);
- var
- i, h: Integer;
- begin
- h := High(TIA);
- if ((x > h) or (x < 0)) then
- Exit;
- for i := x to (h - 1) do
- TIA[i] := TIA[(i + 1)];
- SetLength(TIA, h);
- end;
- procedure TIAInsert(var TIA: TIntegerArray; index: Integer; int: Integer);
- var
- i, l: Integer;
- begin
- l := Length(TIA);
- SetLength(TIA, (l + 1));
- if (index < 0) then
- index := 0;
- if (index > l) then
- index := l;
- if (l > index) then
- for i := (l - 1) downto index do
- TIA[(i + 1)] := Integer(TIA[i]);
- TIA[index] := Integer(int);
- end;
- {==============================================================================]
- Explanation: Returns string of all TSA items binded together. Places glue between the indexes.
- [==============================================================================}
- function TSAConcatEx(TSA: TStringArray; glue: string): string;
- var
- h, i: Integer;
- begin
- Result := '';
- h := High(TSA);
- if (h > -1) then
- begin
- for i := 0 to (h - 1) do
- Result := (Result + string(TSA[i]) + string(glue));
- Result := (Result + string(TSA[i]));
- end;
- end;
- {==============================================================================]
- Explanation: Explodes str with multiple separators/delimiters (d).
- The importance order for d items is from left to right (=>).
- So place the important ones first and then less important after those.
- [==============================================================================}
- function ExplodeMulti(d: TStringArray; str: string): TStringArray;
- var
- p, h, i, x, o, m, l, y, z: Integer;
- begin
- h := High(d);
- if ((h > -1) and (str <> '')) then
- begin
- o := 1;
- SetLength(Result, Length(str));
- repeat
- l := 0;
- for x := 0 to h do
- begin
- p := Pos(d[x], str);
- case (p < 1) of
- True:
- begin
- z := High(d);
- if ((x <= z) and (x > -1)) then
- begin
- for y := x to (z - 1) do
- d[y] := d[(y + 1)];
- SetLength(d, z);
- end;
- Dec(x);
- Dec(h);
- end;
- False:
- if ((l = 0) or (p < l)) then
- begin
- m := x;
- l := p;
- end;
- end;
- end;
- if (l > 0) then
- begin
- Result[i] := Copy(str, 1, (l - 1));
- Delete(str, 1, ((l + Length(d[m])) - 1));
- Inc(i);
- end else
- Result[i] := Copy(str, 1, Length(str));
- until (l = 0);
- SetLength(Result, (i + 1));
- end else
- Result := [string(str)];
- end;
- {==============================================================================]
- Explanation: Finds position from s items in str. Stores the ID of the found s item to index variable.
- The importance order for d items is from left to right (=>).
- So place the important ones first and then less important after those.
- Contains field for offset.
- [==============================================================================}
- function PosMultiIDEx(s: TStringArray; str: string; var index: Integer; offset: Integer): Integer;
- var
- h, i, p, t: Integer;
- begin
- if (offset < 1) then
- offset := 1;
- Result := -1;
- index := -1;
- h := High(s);
- if ((h > -1) and (str <> '')) then
- begin
- t := (Length(str) + 1);
- Result := t;
- for i := 0 to h do
- begin
- p := PosEx(s[i], str, offset);
- if ((p > 0) and (p < Result)) then
- begin
- Result := p;
- index := i;
- end;
- end;
- if (Result = t) then
- Result := 0;
- end;
- end;
- function PosAll(s, str: string): TIntegerArray;
- var
- sL, strL, o, p, r: Integer;
- begin
- sL := Length(s);
- strL := Length(str);
- if (sL <= strL) then
- begin
- SetLength(Result, strL);
- repeat
- p := PosEx(s, str, (o + 1));
- if (p > 0) then
- begin
- Result[r] := p;
- o := p;
- Inc(r);
- end;
- until (p <= 0);
- end;
- SetLength(Result, r);
- end;
- {==============================================================================]
- Explanation: Indents str with spaces (just like the feature in SCAR, Ctrl+Shift+[I/U]).
- shift is the amount of spaces. It can be positive value (indent), 0 (no change) or negative value (unindent).
- [==============================================================================}
- procedure Indentation(var str: string; shift: Integer);
- var
- d, tmp, nl: TStringArray;
- p, h, i, x, o, m, l, y, z: Integer;
- s: string;
- begin
- if ((str <> '') and (shift <> 0)) then
- begin
- d := [#13#10, #13, #10];
- h := High(d);
- o := 1;
- SetLength(tmp, Length(str));
- SetLength(nl, Length(str));
- repeat
- l := 0;
- for x := 0 to h do
- begin
- p := Pos(d[x], str);
- case (p < 1) of
- True:
- begin
- z := High(d);
- if ((x <= z) and (x > -1)) then
- begin
- for y := x to (z - 1) do
- d[y] := d[(y + 1)];
- SetLength(d, z);
- end;
- Dec(x);
- Dec(h);
- end;
- False:
- if ((l = 0) or (p < l)) then
- begin
- m := x;
- l := p;
- end;
- end;
- end;
- if (l > 0) then
- begin
- tmp[i] := Copy(str, 1, (l - 1));
- nl[i] := string(d[m]);
- Delete(str, 1, ((l + Length(d[m])) - 1));
- Inc(i);
- end else
- tmp[i] := Copy(str, 1, Length(str));
- until (l = 0);
- str := '';
- SetLength(tmp, (i + 1));
- SetLength(nl, i);
- case (shift > 0) of
- True:
- begin
- s := StringOfChar(' ', shift);
- for x := 0 to i do
- begin
- str := (str + (s + tmp[x]));
- if (x < i) then
- str := (str + nl[x]);
- end;
- end;
- False:
- begin
- shift := iAbs(shift);
- for x := 0 to i do
- begin
- y := 0;
- l := Length(tmp[x]);
- while ((y < shift) and (y < l) and (tmp[x][(y + 1)] = ' ')) do
- Inc(y);
- if (y > 0) then
- Delete(tmp[x], 1, y);
- str := (str + tmp[x]);
- if (x < i) then
- str := (str + nl[x]);
- end;
- end;
- end;
- SetLength(tmp, 0);
- SetLength(nl, 0);
- end;
- end;
- function ToRange(minimum, maximum: Integer): TRange;
- begin
- Result.minimum := Integer(minimum);
- Result.maximum := Integer(maximum);
- end;
- {==============================================================================]
- Explanation: Returns true if int is in any range from ranges of TRA.
- [==============================================================================}
- function TRAContains(TRA: TRangeArray; int: Integer): Boolean;
- var
- h, i: Integer;
- begin
- h := High(TRA);
- case (h > -1) of
- True:
- begin
- for i := 0 to h do
- if ((int >= TRA[i].minimum) and (int <= TRA[i].maximum)) then
- Break;
- Result := (i <= h);
- end;
- False: Result := False;
- end;
- end;
- procedure TRAAppend(var TRA: TRangeArray; x: TRange);
- var
- aL: Integer;
- begin
- aL := (Length(TRA) + 1);
- SetLength(TRA, aL);
- TRA[(aL - 1)] := TRange(x);
- end;
- procedure TRADelete(var TRA: TRangeArray; x: Integer);
- var
- i, h: Integer;
- begin
- h := High(TRA);
- if ((x > h) or (x < 0)) then
- Exit;
- for i := x to (h - 1) do
- TRA[i] := TRA[(i + 1)];
- SetLength(TRA, h);
- end;
- function TrackCaS(str: string; var comments, strings: TRangeArray): Boolean;
- var
- s, i, o, e, x, l, a, ls: Integer;
- t: TStringArray;
- begin
- Result := False;
- SetLength(comments, 0);
- SetLength(strings, 0);
- l := Length(str);
- ls := -1;
- if (l > 0) then
- begin
- o := 1;
- t := ['//', '(*', '{', ''''];
- repeat
- s := PosMultiIDEx(t, str, i, o);
- case (s <= ls) of
- True: Exit;
- False: ls := s;
- end;
- if (s > 0) then
- begin
- o := (s + 1);
- a := 0;
- case i of
- 0, 1, 2:
- begin
- case i of
- 0:
- begin
- e := PosMultiIDEx([#13#10, #13, #10], str, x, o);
- if (x = 0) then
- a := 1;
- if (e = 0) then
- e := l;
- TRAAppend(comments, ToRange(s, e));
- end;
- 1, 2:
- begin
- case i of
- 1:
- begin
- e := PosEx('*)', str, o);
- a := 1;
- end;
- 2: e := PosEx('}', str, o);
- end;
- if (e = 0) then
- e := l;
- TRAAppend(comments, ToRange(s, (e + a)));
- end;
- end;
- end;
- 3:
- begin
- e := PosMultiIDEx([#13#10, #13, #10, ''''], str, x, o);
- if (x = 0) then
- a := 1;
- case (e = 0) of
- True:
- begin
- e := l;
- TRAAppend(strings, ToRange(s, e));
- end;
- False:
- case x of
- 0, 1, 2: TRAAppend(strings, ToRange(s, e));
- 3: TRAAppend(strings, ToRange(s, (e + a)));
- end;
- end;
- end;
- end;
- o := ((e + 1) + a);
- end;
- until ((s = 0) or (x = -1) or (o > l));
- end;
- end;
- {==============================================================================]
- Explanation: Trims all TSA items.
- [==============================================================================}
- procedure TSATrim(var TSA: TStringArray);
- var
- h, i: Integer;
- begin
- h := High(TSA);
- for i := 0 to h do
- TSA[i] := Trim(TSA[i]);
- end;
- {==============================================================================]
- Explanation: Returns all the positions by items from s array in str. Place s items in importance order (=>)
- If overlap is set to true, strings can overlap.
- (['aa'], 'baaaah', False) => [2,3,4]
- (['aa'], 'baaaah', True) => [2,4]
- [==============================================================================}
- function PosAllMulti(s: TStringArray; str: string; overlap: Boolean): TIntegerArray;
- var
- h, l, p, o, x, i, t, r, y, d: Integer;
- begin
- h := High(s);
- y := Length(str);
- if ((y > 0) and (h > -1)) then
- begin
- SetLength(Result, y);
- o := 1;
- repeat
- p := 0;
- for x := 0 to h do
- begin
- t := PosEx(s[x], str, (l + o));
- case (t < 1) of
- True:
- begin
- for d := x to (h - 1) do
- s[d] := s[(d + 1)];
- SetLength(s, h);
- Dec(x);
- Dec(h);
- end;
- False:
- if ((p = 0) or (t < p)) then
- begin
- p := t;
- i := x;
- end;
- end;
- end;
- if (p > 0) then
- begin
- Result[r] := p;
- Inc(r);
- l := p;
- if not overlap then
- o := Length(s[i]);
- end;
- until (p <= 0);
- end;
- SetLength(Result, r);
- end;
- procedure FillStrRangeEx(var str: string; fillWith: Char; range: TRange; exceptions: TIntegerArray);
- var
- i, l, c: Integer;
- begin
- l := Length(str);
- if ((l > 0) and not (range.minimum > range.maximum)) then
- begin
- if (range.minimum < 1) then
- range.minimum := 1;
- if (range.maximum > l) then
- range.maximum := l;
- if (range.minimum > l) then
- Exit;
- c := iAbs(range.maximum - range.minimum);
- for i := range.minimum to range.maximum do
- if not InIntArray(exceptions, i) then
- str[i] := fillWith;
- end;
- end;
- function FilterScriptData(scriptData: string): string;
- var
- h, i, l: Integer;
- newLines: TIntegerArray;
- comments, strings: TRangeArray;
- tmp: TStringArray;
- go: Boolean;
- begin
- Result := string(scriptData);
- l := Length(Result);
- data.script.display := string(Result);
- if (l > 0) then
- begin
- go := FILTER_STRINGS;
- if not go then
- go := FILTER_COMMENTS;
- if go then
- begin
- newLines := PosAllMulti([#13#10, #13, #10], Result, False);
- TrackCaS(scriptData, comments, strings);
- h := High(comments);
- if FILTER_COMMENTS then
- for i := 0 to h do
- begin
- FillStrRangeEx(Result, '!', comments[i], newLines);
- FillStrRangeEx(data.script.display, COMMENT_FILTER, comments[i], newLines);
- end;
- h := High(strings);
- if FILTER_COMMENTS then
- for i := 0 to h do
- begin
- FillStrRangeEx(Result, '!', strings[i], newLines);
- FillStrRangeEx(data.script.display, STRING_FILTER, strings[i], newLines);
- end;
- SetLength(newLines, 0);
- SetLength(comments, 0);
- SetLength(strings, 0);
- Result := ReplaceWrap(Result, '!', '', [rfReplaceAll]);
- end;
- tmp := ExplodeMulti([#13#10, #13, #10], Result);
- TSATrim(tmp);
- Result := TSAConcatEx(tmp, #13#10);
- SetLength(tmp, 0);
- tmp := ExplodeMulti([#13#10, #13, #10], data.script.display);
- data.script.display := '';
- h := High(tmp);
- for i := 0 to h do
- tmp[i] := (' ' + StringOfChar('0', (Length(IntToStr(h + 1)) - Length(IntToStr(i + 1)))) + IntToStr(i + 1) + '. ' + tmp[i]);
- data.script.display := TSAConcatEx(tmp, #13#10);
- SetLength(tmp, 0);
- end;
- end;
- {==============================================================================]
- Explanation: Function for tracing findStr's from data.
- Contains also custom fields for regexTags and regexStrs;
- each tag performs a regex action, that is set to regexStrs, during the search.
- [==============================================================================}
- function TraceStrsEx(findStr: string; regexTags: array of Char; regexStrs: TStringArray; data: string; modifiers: TRegexModifiers): TRangeArray;
- var
- re: TRegExp;
- p, l, r, s, c, h, t: Integer;
- q: string;
- begin
- l := Length(data);
- s := Length(findStr);
- if ((l > 0) and (s > 0)) then
- begin
- h := High(regexTags);
- if (High(regexStrs) < h) then
- SetLength(regexStrs, (h + 1));
- SetLength(Result, l);
- q := '.\+*?[^]$(){}=!<>|:-';
- for c := h downto 0 do
- begin
- t := Pos(q, regexTags[c]);
- if (t > 0) then
- Delete(q, t, 1);
- end;
- for c := s downto 1 do
- if (Pos(findStr[c], q) > 0) then
- Insert('\', findStr, c);
- for t := 0 to h do
- findStr := Replace(findStr, regexTags[t], regexStrs[t], [rfReplaceAll]);
- re := TRegExp.Create;
- re.ModifierI := (rm_I in modifiers);
- re.ModifierG := (rm_G in modifiers);
- re.ModifierM := (rm_M in modifiers);
- re.ModifierS := (rm_S in modifiers);
- re.ModifierX := (rm_X in modifiers);
- re.ModifierR := (rm_R in modifiers);
- re.Expression := findStr;
- re.InputString := data;
- p := 1;
- if re.ExecPos(p) then
- repeat
- if (re.Match[0] <> '') then
- begin
- p := (re.MatchPos[0] + 1);
- Result[r].minimum := re.MatchPos[0];
- Result[r].maximum := (Result[r].minimum + (re.MatchLen[0] - 1));
- Inc(r);
- end;
- until not re.ExecPos(p);
- SetLength(Result, r);
- re.Free;
- end else
- SetLength(Result, 0);
- end;
- {==============================================================================]
- Explanation: Returns all the positions, as TRangeArray, of found/matching strings (findStr) in text.
- Uses a set of TMatchMethod (methods) for string matching.
- Contains field for offset.
- If regex field is set as true, then this function searches for the regex you use.
- [==============================================================================}
- function PosFindEx(text, findStr: string; methods: TMatchMethods; offset: Integer; regex: Boolean): TRangeArray;
- var
- rmArr: TRegexMatchArray;
- rmArr2D: T2DRegexMatchArray;
- sb, sa: string;
- r, i, l, f, p, d, o, x, y, abL, abR, abX, abP, spA, spB, spH, spL, spI, spR, spD: Integer;
- re: TRegExp;
- ma, mb, a, s, ol: Boolean;
- c: TIntegerArray;
- t: array of TRangeArray;
- begin
- l := Length(text);
- f := Length(findStr);
- if ((l > 0) and (f > 0) and (offset <= l)) then
- begin
- if (offset < 1) then
- offset := 1;
- if not regex then
- begin
- for i := f downto 1 do
- if (Pos(findStr[i], '.\+*?[^]$(){}=!<>|:-') > 0) then
- Insert('\', findStr, i);
- SetLength(Result, l);
- re := TRegExp.Create;
- re.InputString := text;
- re.Expression := findStr;
- if (mmIgnoreCase in methods) then
- re.ModifierI := True;
- re.ModifierM := True;
- a := (mmAll in methods);
- re.ModifierG := (mmGreedyRegex in methods);
- ol := (mmOverlap in methods);
- if not ol then
- o := (Length(findStr) - 1);
- Inc(o);
- p := offset;
- while re.ExecPos(p) do
- begin
- Result[r].minimum := re.MatchPos[0];
- Result[r].maximum := (Result[r].minimum + re.MatchLen[0]);
- p := (Result[r].minimum + o);
- Inc(r);
- end;
- p := Offset;
- re.Free;
- SetLength(Result, r);
- if ((r > 0) and (mmWholeWords in methods)) then
- begin
- s := (mmStrictWW in methods);
- if not s then
- c := [65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, // A-Z
- 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, // a-z
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57]; // 0-9
- case ol of
- True:
- begin
- spH := High(Result);
- if (spH > -1) then
- begin
- SetLength(t, (spH + 1));
- t[0] := [TRange(Result[0])];
- if (spH > 0) then
- begin
- spR := 1;
- for spI := 1 to spH do
- begin
- for spA := 0 to (spR - 1) do
- begin
- spL := Length(t[spA]);
- for spB := 0 to (spL - 1) do
- begin
- spD := IAbs(Result[spI].minimum - t[spA][spB].minimum);
- if (spD <= f) then
- begin
- SetLength(t[spA], (spL + 1));
- t[spA][spL].minimum := Integer(Result[spI].minimum);
- Break;
- end;
- end;
- if (spB < spL) then
- Break;
- end;
- if (spA >= spR) then
- begin
- t[spR] := [TRange(Result[spI])];
- Inc(spR);
- end;
- end;
- end;
- SetLength(t, spR);
- spH := High(t);
- for spI := spH downto 0 do
- begin
- spB := Low(t[spI]);
- spA := High(t[spI]);
- abX := 1;
- abP := t[spI][spB].minimum;
- abL := Length(text);
- case ((abL > 0) and (abP > 1)) of
- True:
- begin
- if ((abP - abX) < 1) then
- abX := ((abP - abX) + (abX - 1));
- if (abP > (abL + 1)) then
- begin
- abR := ((abP - abL) - 1);
- abX := (abX - abR);
- end;
- sb := Copy(text, ((abP - abX) - abR), abX);
- end;
- False: sb := '';
- end;
- abX := 1;
- abP := (t[spI][spA].minimum + f);
- abL := Length(text);
- case ((abL > 0) and (abP <= abL)) of
- True:
- begin
- if (abP < 1) then
- begin
- abX := (abX - iAbs(abP - 1));
- abP := 1;
- end;
- if ((abX > 0) and ((abP + abX) > abL)) then
- abX := (abX - (((abP + abX) - abL) - 1));
- sa := Copy(text, abP, abX);
- end;
- False: sa := '';
- end;
- case s of
- True:
- begin
- mb := (sb = '');
- if not mb then
- mb := ((sb = ' ') or (sb = #13#10) or (sb = #13) or (sb = #10));
- ma := (sa = '');
- if not ma then
- ma := ((sa = ' ') or (sa = #13#10) or (sa = #13) or (sa = #10));
- end;
- False:
- begin
- mb := (sb = '');
- if not mb then
- mb := not InIntArray(c, Ord(sb[1]));
- ma := (sa = '');
- if not ma then
- ma := not InIntArray(c, Ord(sa[1]));
- end;
- end;
- if not (mb and ma) then
- begin
- for spD := spI to (spH - 1) do
- t[spD] := t[(spD + 1)];
- SetLength(t, spH);
- Dec(spH);
- end;
- end;
- spH := High(t);
- if (spH > -1) then
- begin
- for spI := 0 to spH do
- IncEx(spR, (High(t[spI]) + 1));
- SetLength(Result, spR);
- spR := 0;
- for spI := 0 to spH do
- begin
- spL := High(t[spI]);
- for spA := 0 to spL do
- begin
- Result[spR] := TRange(t[spI][spA]);
- Inc(spR);
- end;
- end;
- SetLength(Result, spR);
- end else
- SetLength(Result, 0);
- end else
- r := 0;
- end;
- False:
- begin
- for x := (r - 1) downto 0 do
- begin
- abX := 1;
- abP := Result[x].minimum;
- abL := Length(text);
- case ((abL > 0) and (abP > 1)) of
- True:
- begin
- if ((abP - abX) < 1) then
- abX := ((abP - abX) + (abX - 1));
- if (abP > (abL + 1)) then
- begin
- abR := ((abP - abL) - 1);
- abX := (abX - abR);
- end;
- sb := Copy(text, ((abP - abX) - abR), abX);
- end;
- False: sb := '';
- end;
- abX := 1;
- abP := (Result[x].minimum + f);
- abL := Length(text);
- case ((abL > 0) and (abP <= abL)) of
- True:
- begin
- if (abP < 1) then
- begin
- abX := (abX - iAbs(abP - 1));
- abP := 1;
- end;
- if ((abX > 0) and ((abP + abX) > abL)) then
- abX := (abX - (((abP + abX) - abL) - 1));
- sa := Copy(text, abP, abX);
- end;
- False: sa := '';
- end;
- case s of
- True:
- begin
- mb := (sb = '');
- if not mb then
- mb := ((sb = ' ') or (sb = #13#10) or (sb = #13) or (sb = #10));
- ma := (sa = '');
- if not ma then
- ma := ((sa = ' ') or (sa = #13#10) or (sa = #13) or (sa = #10));
- end;
- False:
- begin
- mb := (sb = '');
- if not mb then
- mb := not InIntArray(c, Ord(sb[1]));
- ma := (sa = '');
- if not ma then
- ma := not InIntArray(c, Ord(sa[1]));
- end;
- end;
- if not (mb and ma) then
- begin
- y := (r - 1);
- for d := x to (y - 1) do
- Result[d] := Result[(d + 1)];
- SetLength(Result, y);
- Dec(r);
- end;
- end;
- end;
- end;
- end;
- if (not a and (r > 0)) then
- SetLength(Result, 1);
- end else
- begin
- SetLength(rmArr, l);
- re := TRegExp.Create;
- re.InputString := text;
- re.Expression := findStr;
- if (mmIgnoreCase in methods) then
- re.ModifierI := True;
- re.ModifierM := True;
- a := (mmAll in methods);
- re.ModifierG := (mmGreedyRegex in methods);
- ol := (mmOverlap in methods);
- p := offset;
- while re.ExecPos(p) do
- begin
- rmArr[r].position := re.MatchPos[0];
- rmArr[r].text := re.Match[0];
- rmArr[r].size := re.MatchLen[0];
- if ol then
- p := (rmArr[r].position + 1)
- else
- p := (rmArr[r].position + rmArr[r].size);
- Inc(r);
- end;
- p := Offset;
- re.Free;
- SetLength(rmArr, r);
- if ((r > 0) and (mmWholeWords in methods)) then
- begin
- s := (mmStrictWW in methods);
- if not s then
- c := [65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, // A-Z
- 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, // a-z
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57]; // 0-9
- case ol of
- True:
- begin
- spH := High(rmArr);
- if (spH > -1) then
- begin
- SetLength(rmArr2D, (spH + 1));
- rmArr2D[0] := [TRegexMatch(rmArr[0])];
- if (spH > 0) then
- begin
- spR := 1;
- for spI := 1 to spH do
- begin
- for spA := 0 to (spR - 1) do
- begin
- spL := Length(rmArr2D[spA]);
- for spB := 0 to (spL - 1) do
- begin
- spD := IAbs(rmArr[spI].position - rmArr2D[spA][spB].position);
- if (spD <= rmArr2D[spA][spB].size) then
- begin
- SetLength(rmArr2D[spA], (spL + 1));
- rmArr2D[spA][spL] := TRegexMatch(rmArr[spI]);
- Break;
- end;
- end;
- if (spB < spL) then
- Break;
- end;
- if (spA >= spR) then
- begin
- rmArr2D[spR] := [TRegexMatch(rmArr[spI])];
- Inc(spR);
- end;
- end;
- end;
- SetLength(rmArr2D, spR);
- spH := High(rmArr2D);
- for spI := spH downto 0 do
- begin
- spB := Low(rmArr2D[spI]);
- spA := High(rmArr2D[spI]);
- abX := 1;
- abP := rmArr2D[spI][spB].position;
- abL := Length(text);
- case ((abL > 0) and (abP > 1)) of
- True:
- begin
- if ((abP - abX) < 1) then
- abX := ((abP - abX) + (abX - 1));
- if (abP > (abL + 1)) then
- begin
- abR := ((abP - abL) - 1);
- abX := (abX - abR);
- end;
- sb := Copy(text, ((abP - abX) - abR), abX);
- end;
- False: sb := '';
- end;
- abX := 1;
- abP := (rmArr2D[spI][spA].position + rmArr2D[spI][spA].size);
- abL := Length(text);
- case ((abL > 0) and (abP <= abL)) of
- True:
- begin
- if (abP < 1) then
- begin
- abX := (abX - iAbs(abP - 1));
- abP := 1;
- end;
- if ((abX > 0) and ((abP + abX) > abL)) then
- abX := (abX - (((abP + abX) - abL) - 1));
- sa := Copy(text, abP, abX);
- end;
- False: sa := '';
- end;
- case s of
- True:
- begin
- mb := (sb = '');
- if not mb then
- mb := ((sb = ' ') or (sb = #13#10) or (sb = #13) or (sb = #10));
- ma := (sa = '');
- if not ma then
- ma := ((sa = ' ') or (sa = #13#10) or (sa = #13) or (sa = #10));
- end;
- False:
- begin
- mb := (sb = '');
- if not mb then
- mb := not InIntArray(c, Ord(sb[1]));
- ma := (sa = '');
- if not ma then
- ma := not InIntArray(c, Ord(sa[1]));
- end;
- end;
- if not (mb and ma) then
- begin
- for spD := spI to (spH - 1) do
- rmArr2D[spD] := rmArr2D[(spD + 1)];
- SetLength(rmArr2D, spH);
- Dec(spH);
- end;
- end;
- spH := High(rmArr2D);
- if (spH > -1) then
- begin
- for spI := 0 to spH do
- IncEx(spR, (High(rmArr2D[spI]) + 1));
- SetLength(rmArr, spR);
- spR := 0;
- for spI := 0 to spH do
- begin
- spL := High(rmArr2D[spI]);
- for spA := 0 to spL do
- begin
- rmArr[spR] := TRegexMatch(rmArr2D[spI][spA]);
- Inc(spR);
- end;
- end;
- SetLength(rmArr, spR);
- r := spR;
- end else
- SetLength(rmArr, 0);
- end else
- r := 0;
- end;
- False:
- begin
- for x := (r - 1) downto 0 do
- begin
- abX := 1;
- abP := rmArr[x].position;
- abL := Length(text);
- case ((abL > 0) and (abP > 1)) of
- True:
- begin
- if ((abP - abX) < 1) then
- abX := ((abP - abX) + (abX - 1));
- if (abP > (abL + 1)) then
- begin
- abR := ((abP - abL) - 1);
- abX := (abX - abR);
- end;
- sb := Copy(text, ((abP - abX) - abR), abX);
- end;
- False: sb := '';
- end;
- abX := 1;
- abP := (rmArr[x].position + rmArr[x].size);
- abL := Length(text);
- case ((abL > 0) and (abP <= abL)) of
- True:
- begin
- if (abP < 1) then
- begin
- abX := (abX - iAbs(abP - 1));
- abP := 1;
- end;
- if ((abX > 0) and ((abP + abX) > abL)) then
- abX := (abX - (((abP + abX) - abL) - 1));
- sa := Copy(text, abP, abX);
- end;
- False: sa := '';
- end;
- case s of
- True:
- begin
- mb := (sb = '');
- if not mb then
- mb := ((sb = ' ') or (sb = #13#10) or (sb = #13) or (sb = #10));
- ma := (sa = '');
- if not ma then
- ma := ((sa = ' ') or (sa = #13#10) or (sa = #13) or (sa = #10));
- end;
- False:
- begin
- mb := (sb = '');
- if not mb then
- mb := not InIntArray(c, Ord(sb[1]));
- ma := (sa = '');
- if not ma then
- ma := not InIntArray(c, Ord(sa[1]));
- end;
- end;
- if not (mb and ma) then
- begin
- y := (r - 1);
- for d := x to (y - 1) do
- rmArr[d] := rmArr[(d + 1)];
- SetLength(rmArr, y);
- Dec(r);
- end;
- end;
- end;
- end;
- end;
- case (r > 0) of
- True:
- begin
- if not a then
- r := 1;
- SetLength(Result, r);
- for i := 0 to (r - 1) do
- begin
- Result[i].minimum := rmArr[i].position;
- Result[i].maximum := (Result[i].minimum + rmArr[i].size);
- end;
- end;
- False: SetLength(Result, 0);
- end;
- end;
- end else
- SetLength(Result, 0);
- end;
- function PositionToLine(position: Integer): Integer;
- var
- h: Integer;
- begin
- Result := 1;
- h := High(data.script.linePositions);
- if (h > -1) then
- case (h > 0) of
- True:
- for Result := 1 to (h + 1) do
- if (position < data.script.linePositions[(Result - 1)]) then
- Break;
- False:
- if (position >= data.script.linePositions[0]) then
- Result := 2;
- end;
- Dec(Result);
- end;
- procedure FindThreats;
- var
- a, b, x, y, t, i, d, st, tt, it, z, l, v, o: Integer;
- f: TRangeArray;
- mx, mn, zr: Boolean;
- begin
- data.timeStamp := TimeStamp;
- st := GetSystemTime;
- for t := 0 to High(data.threat) do
- begin
- data.threat[t].timeStamp := TimeStamp;
- tt := GetSystemTime;
- if data.threat[t].enabled then
- for i := 0 to High(data.threat[t].item) do
- begin
- data.threat[t].item[i].timeStamp := TimeStamp;
- it := GetSystemTime;
- if data.threat[t].item[i].enabled then
- begin
- f := PosFindEx(data.script.filtered, data.threat[t].item[i].detect.text, data.threat[t].item[i].detect.methods, 1, data.threat[t].item[i].detect.regex);
- y := High(f);
- mn := (data.threat[t].item[i].detect.requirement.minimum = -1);
- if not mn then
- mn := ((y + 1) >= data.threat[t].item[i].detect.requirement.minimum);
- mx := (data.threat[t].item[i].detect.requirement.maximum = -1);
- if not mx then
- mx := ((y + 1) <= data.threat[t].item[i].detect.requirement.maximum);
- zr := ((y = -1) and (mn and mx));
- if (mn and mx) then
- begin
- if not zr then
- begin
- b := High(data.threat[t].item[i].detect.filters);
- for a := 0 to b do
- begin
- data.threat[t].item[i].detect.filters[a].positions := TraceStrsEx(data.threat[t].item[i].detect.filters[a].text, data.threat[t].item[i].detect.filters[a].regexTags, data.threat[t].item[i].detect.filters[a].regexStrs, data.script.filtered, TRegexModifiers(data.threat[t].item[i].detect.filters[a].modifiers));
- for d := y downto 0 do
- if (TRAContains(data.threat[t].item[i].detect.filters[a].positions, f[d].minimum) or TRAContains(data.threat[t].item[i].detect.filters[a].positions, f[d].maximum)) then
- begin
- TRADelete(f, d);
- Dec(y);
- end;
- if (y < 0) then
- Break;
- end;
- end;
- if (zr or (y > -1)) then
- begin
- case zr of
- True:
- begin
- z := 1;
- IncEx(data.foundThreats, z);
- IncEx(data.threat[t].foundItems, z);
- SetLength(data.threat[t].item[i].found, z);
- data.threat[t].item[i].found[0].timeStamp := TimeStamp;
- data.threat[t].item[i].found[0].line := -1;
- end;
- False:
- begin
- z := (y + 1);
- IncEx(data.foundThreats, z);
- IncEx(data.threat[t].foundItems, z);
- SetLength(data.threat[t].item[i].found, z);
- for x := 0 to y do
- begin
- data.threat[t].item[i].found[x].timeStamp := TimeStamp;
- data.threat[t].item[i].found[x].position := TRange(f[x]);
- data.threat[t].item[i].found[x].line := PositionToLine(f[x].minimum);
- end;
- end;
- end;
- case data.threat[t].item[i].riskLevel of
- rl_VeryLow: IncEx(data.points, (POINTS_VERY_LOW * z));
- rl_Low: IncEx(data.points, (POINTS_LOW * z));
- rl_Medium: IncEx(data.points, (POINTS_MEDIUM * z));
- rl_High: IncEx(data.points, (POINTS_HIGH * z));
- rl_VeryHigh: IncEx(data.points, (POINTS_VERY_HIGH * z));
- end;
- end;
- end;
- end;
- data.threat[t].item[i].timing := (GetSystemTime - it);
- end;
- data.threat[t].timing := (GetSystemTime - tt);
- end;
- data.timing := (GetSystemTime - st);
- for t := 0 to High(data.threat) do
- if (data.threat[t].foundItems > 0) then
- for i := 0 to High(data.threat[t].item) do
- begin
- v := 0;
- z := High(data.threat[t].item[i].found);
- for x := 0 to z do
- begin
- l := Length(data.lineTracker);
- while (v < l) do
- begin
- if (data.threat[t].item[i].found[x].line < data.threat[data.lineTracker[v][0]].item[data.lineTracker[v][1]].found[data.lineTracker[v][2]].line) then
- Break;
- Inc(v);
- end;
- SetLength(data.lineTracker, (l + 1));
- if (l > v) then
- for o := (l - 1) downto v do
- data.lineTracker[(o + 1)] := data.lineTracker[o];
- data.lineTracker[v][0] := t;
- data.lineTracker[v][1] := i;
- data.lineTracker[v][2] := x;
- end;
- end;
- end;
- (*
- Auther: Officer Barbrady
- *)
- procedure Scan;
- var
- a, b: Integer;
- begin
- SetLength(data.lineTracker, 0);
- data.foundThreats := 0;
- data.timeStamp := '';
- for a := 0 to High(data.threat) do
- begin
- data.threat[a].foundItems := 0;
- data.threat[a].timeStamp := '';
- for b := 0 to High(data.threat[a].item) do
- begin
- data.threat[a].item[b].timeStamp := '';
- SetLength(data.threat[a].item[b].found, 0);
- end;
- end;
- data.threat[0].enabled := SOCKET_SCAN;
- data.threat[1].enabled := HTTP_SCAN;
- data.threat[2].enabled := WEB_SCAN;
- data.threat[3].enabled := FILE_SCAN;
- data.threat[4].enabled := CODE_SCAN;
- data.threat[5].enabled := CODE_SCAN;
- for a := 0 to 5 do
- for b := 0 to High(data.threat[a].item) do
- data.threat[a].item[b].enabled := True;
- FindThreats;
- WriteLn(ParseTextReport);
- end;
- (*
- Auther: Officer Barbrady
- *)
- procedure OpenThread(Sender: TObject);
- begin
- OpenWebsite('http://villavu.com/forum/showthread.php?t=103408');
- end;
- (*
- Auther: Officer Barbrady
- *)
- procedure SaveFormInfo(Sender: TObject);
- var
- tmp: TStringArray;
- begin
- ScanButton.Caption := 'Scanning... Please wait!';
- totalTiming := GetSystemTime;
- DsgnForm.ModalResult := mrOk;
- tmp := ExplodeMulti([#13#10, #13, #10], ScriptEdit.Text);
- data.script.original := TSAConcatEx(tmp, #13#10);
- SetLength(tmp, 0);
- data.script.filtered := FilterScriptData(data.script.original);
- Indentation(data.script.filtered, 1);
- data.script.linePositions := PosAll(#13#10, data.script.filtered);
- TIAInsert(data.script.linePositions, 0, 1);
- pressed := True;
- DsgnForm.Close;
- end;
- procedure ResizeGUI(sender: TObject);
- begin
- with ScriptEdit do
- begin
- Width := (DsgnForm.Width - 10);
- Height := (DsgnForm.Height - 45);
- end;
- with ScanButton do
- begin
- Left := ((DsgnForm.Width - 406) div 2);
- Top := (DsgnForm.Height - 35);
- end;
- with UpdateButton do
- begin
- Left := (ScanButton.Left + ScanButton.Width + 3);
- Top := (DsgnForm.Height - 35);
- end;
- end;
- (*
- Auther: Officer Barbrady
- *)
- procedure InitForm;
- begin
- DsgnForm := TForm.Create(nil);
- with DsgnForm do
- begin
- Caption := ('Simba Script Scanner v' + FloatToStr(VERSION));
- Left := 377;
- Top := 380;
- Width := GUI_WIDTH;
- Height := GUI_HEIGHT;
- Font.Name := DEFAULT;
- end;
- DsgnForm.OnResize := @ResizeGUI;
- ScriptEdit := TMemo.Create(DsgnForm);
- with ScriptEdit do
- begin
- Parent := DsgnForm;
- Left := 5;
- Top := 5;
- Width := (DsgnForm.Width - 10);
- Height := (DsgnForm.Height - 45);
- Font.Name := 'Courier New';
- Font.Size := 10;
- WordWrap := False;
- with ScriptEdit.Lines do
- Add('Paste script into this box, it will look for suspicious lines of code!');
- ScrollBars := ssBoth;
- end;
- ScanButton := TButton.Create(DsgnForm);
- with ScanButton do
- begin
- Parent := DsgnForm;
- Caption := 'Scan';
- Left := ((DsgnForm.Width - 406) div 2);
- Top := (DsgnForm.Height - 35);
- Width := 200;
- Height := 30;
- Font.Size := 12;
- OnClick := @SaveFormInfo;
- end;
- UpdateButton := TButton.Create(DsgnForm);
- with UpdateButton do
- begin
- Parent := DsgnForm;
- Caption := 'Update';
- Left := (ScanButton.Left + ScanButton.Width + 3);
- Top := (DsgnForm.Height - 35);
- Width := 200;
- Height := 30;
- Font.Size := 12;
- OnClick := @OpenThread;
- end;
- end;
- procedure SafeInitForm;
- var
- v: TVariantArray;
- begin
- SetLength(V, 0);
- ThreadSafeCall('InitForm', v);
- end;
- procedure ShowFormModal;
- begin
- DsgnForm.ShowModal;
- end;
- procedure SafeShowFormModal;
- var
- v: TVariantArray;
- begin
- SetLength(V, 0);
- ThreadSafeCall('ShowFormModal', v);
- end;
- begin
- ClearDebug;
- SetupThreats;
- try
- SafeInitForm;
- SafeShowFormModal;
- if pressed then
- Scan;
- except
- WriteLn('Error with form :(');
- finally
- DsgnForm.Free;
- data.script.original := '';
- data.script.filtered := '';
- data.script.display := '';
- SetLength(data.threat, 0);
- data.foundThreats := 0;
- data.timeStamp := '';
- SetLength(data.script.linePositions, 0);
- SetLength(data.lineTracker, 0);
- end;
- end.
Advertisement
Add Comment
Please, Sign In to add comment