mirror of
https://github.com/Theldus/alertik.git
synced 2024-11-21 15:33:15 +01:00
Add POSIX Reg Extended tool
This commit is contained in:
parent
32b9d8b772
commit
82f59c760b
22
tools/Makefile
Normal file
22
tools/Makefile
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#
|
||||||
|
# Alertik: a tiny 'syslog' server & notification tool for Mikrotik routers.
|
||||||
|
# This is free and unencumbered software released into the public domain.
|
||||||
|
#
|
||||||
|
|
||||||
|
CC ?= cc
|
||||||
|
CC_JS = emcc
|
||||||
|
CFLAGS += -Wall -Wextra -O2
|
||||||
|
CFLAGS_JS += $(CFLAGS)
|
||||||
|
CFLAGS_JS += -s EXPORTED_FUNCTIONS='["_do_regex", "_malloc", "_free"]'
|
||||||
|
CFLAGS_JS += -s 'EXPORTED_RUNTIME_METHODS=["stringToUTF8", "UTF8ToString", "setValue"]'
|
||||||
|
|
||||||
|
all: regext.js regext Makefile
|
||||||
|
|
||||||
|
regext.js: regext.c
|
||||||
|
$(CC_JS) $(CFLAGS_JS) regext.c -o regext.js
|
||||||
|
|
||||||
|
regext: regext.c
|
||||||
|
$(CC) $(CFLAGS) -DUSE_C regext.c -o regext
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f regext.js regext.wasm regext *.o
|
232
tools/index.html
Normal file
232
tools/index.html
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>POSIX Regex Extended Validator</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
background-color: #e0f7da;
|
||||||
|
color: #2e7d32;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100vh;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
background-color: #a5d6a7;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||||
|
padding: 20px;
|
||||||
|
max-width: 800px;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.container h1 {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.form-group label {
|
||||||
|
font-weight: bold;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
.form-group textarea,
|
||||||
|
.form-group input {
|
||||||
|
width: calc(100% - 20px);
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid #81c784;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
textarea {
|
||||||
|
resize: none;
|
||||||
|
}
|
||||||
|
input[readonly],
|
||||||
|
.output {
|
||||||
|
background-color: #f1f8e9;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.form-group input[type="text"].no-match {
|
||||||
|
background-color: #ffcccb;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding-left: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
ul li {
|
||||||
|
background-color: #f1f8e9;
|
||||||
|
border: 1px solid #81c784;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
.result {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.env-variable {
|
||||||
|
margin-top: 10px;
|
||||||
|
font-style: italic;
|
||||||
|
color: #1b5e20;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.footer img {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.flex-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.flex-item {
|
||||||
|
width: 48%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>POSIX Regex Extended Validator</h1>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="regex">Your Regex</label>
|
||||||
|
<textarea id="regex" placeholder="Enter your regex" oninput="validateRegex()"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="inputString">Input Field</label>
|
||||||
|
<textarea id="inputString" placeholder="Enter input string" oninput="validateRegex()"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="flex-container">
|
||||||
|
<div class="flex-item">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="isMatch">Matches?</label>
|
||||||
|
<input type="text" id="isMatch" readonly />
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="matches">Matching Output</label>
|
||||||
|
<input type="text" id="matches" readonly />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-item">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="groups">Matching Groups</label>
|
||||||
|
<ul id="groups" class="output"></ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="envVariable" class="env-variable"></div>
|
||||||
|
<div class="footer">
|
||||||
|
<a href="https://github.com/Theldus/alertik" target="_blank">
|
||||||
|
<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" alt="GitHub Logo" />
|
||||||
|
</a>
|
||||||
|
<span>by Theldus</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script async type="text/javascript" src="regext.js"></script>
|
||||||
|
<script>
|
||||||
|
function arrayToPtr(array, bytes_per_element) {
|
||||||
|
var ptr = Module._malloc(array.length * bytes_per_element);
|
||||||
|
for (var i = 0; i < array.length; i++) {
|
||||||
|
Module.setValue(ptr + i * bytes_per_element, array[i], "i32");
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ptrToArray(ptr, length, bytes_per_element) {
|
||||||
|
var array = new Int32Array(length);
|
||||||
|
var pos = ptr / bytes_per_element;
|
||||||
|
array.set(Module.HEAP32.subarray(pos, pos + length));
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateRegex() {
|
||||||
|
const regexInput = document.getElementById("regex").value;
|
||||||
|
const inputString = document.getElementById("inputString").value;
|
||||||
|
const isMatchInput = document.getElementById("isMatch");
|
||||||
|
const matchesInput = document.getElementById("matches");
|
||||||
|
const groupsList = document.getElementById("groups");
|
||||||
|
const envVariable = document.getElementById("envVariable");
|
||||||
|
|
||||||
|
if (regexInput === "" || inputString === "") {
|
||||||
|
isMatchInput.value = "";
|
||||||
|
matchesInput.value = "";
|
||||||
|
groupsList.innerHTML = "";
|
||||||
|
envVariable.textContent = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const subExpr = new Int32Array(1);
|
||||||
|
const rmSo = new Int32Array(32);
|
||||||
|
const rmEo = new Int32Array(32);
|
||||||
|
const errorMsg = new Uint8Array(128);
|
||||||
|
|
||||||
|
const rePtr = Module._malloc(regexInput.length + 1);
|
||||||
|
Module.stringToUTF8(regexInput, rePtr, regexInput.length + 1);
|
||||||
|
|
||||||
|
const strPtr = Module._malloc(inputString.length + 1);
|
||||||
|
Module.stringToUTF8(inputString, strPtr, inputString.length + 1);
|
||||||
|
|
||||||
|
const subExprPtr = arrayToPtr(subExpr, 4);
|
||||||
|
const rmSoPtr = arrayToPtr(rmSo, 4);
|
||||||
|
const rmEoPtr = arrayToPtr(rmEo, 4);
|
||||||
|
const errorMsgPtr = arrayToPtr(errorMsg, 1);
|
||||||
|
|
||||||
|
const result = Module._do_regex(rePtr, strPtr, subExprPtr, rmSoPtr,
|
||||||
|
rmEoPtr, errorMsgPtr);
|
||||||
|
|
||||||
|
if (result === -1) {
|
||||||
|
const errorMsgStr = Module.UTF8ToString(errorMsgPtr);
|
||||||
|
isMatchInput.value = "Invalid Regex";
|
||||||
|
matchesInput.value = "";
|
||||||
|
groupsList.innerHTML = "";
|
||||||
|
envVariable.textContent = "";
|
||||||
|
isMatchInput.classList.add("no-match");
|
||||||
|
} else if (result === 0) {
|
||||||
|
isMatchInput.value = "No";
|
||||||
|
matchesInput.value = "";
|
||||||
|
groupsList.innerHTML = "";
|
||||||
|
envVariable.textContent = "";
|
||||||
|
isMatchInput.classList.add("no-match");
|
||||||
|
} else {
|
||||||
|
const subExprCount = ptrToArray(subExprPtr, 1, 4)[0] + 1;
|
||||||
|
const rmSoArray = ptrToArray(rmSoPtr, subExprCount, 4);
|
||||||
|
const rmEoArray = ptrToArray(rmEoPtr, subExprCount, 4);
|
||||||
|
|
||||||
|
isMatchInput.value = "Yes";
|
||||||
|
matchesInput.value = inputString.substring(rmSoArray[0], rmEoArray[0]);
|
||||||
|
|
||||||
|
let groupsHtml = "";
|
||||||
|
for (let i = 1; i < subExprCount; i++) {
|
||||||
|
const match = inputString.substring(rmSoArray[i], rmEoArray[i]);
|
||||||
|
groupsHtml += `<li>$${i}: ${match}</li>`;
|
||||||
|
}
|
||||||
|
groupsList.innerHTML = groupsHtml;
|
||||||
|
envVariable.textContent =
|
||||||
|
`Example environment var: EVENT0_MATCH_STR="${regexInput}"`;
|
||||||
|
isMatchInput.classList.remove("no-match");
|
||||||
|
}
|
||||||
|
|
||||||
|
Module._free(rePtr);
|
||||||
|
Module._free(strPtr);
|
||||||
|
Module._free(subExprPtr);
|
||||||
|
Module._free(rmSoPtr);
|
||||||
|
Module._free(rmEoPtr);
|
||||||
|
Module._free(errorMsgPtr);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
100
tools/regext.c
Normal file
100
tools/regext.c
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* Alertik: a tiny 'syslog' server & notification tool for Mikrotik routers.
|
||||||
|
* This is free and unencumbered software released into the public domain.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <regex.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef DBG
|
||||||
|
#define LOG(...) printf(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define LOG(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int do_regex(
|
||||||
|
const char *re, const char *str,
|
||||||
|
int32_t *sub_expr, int32_t *rm_so, int32_t *rm_eo,
|
||||||
|
char *error_msg)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
regex_t regex;
|
||||||
|
regmatch_t pmatch[32];
|
||||||
|
|
||||||
|
if ((ret = regcomp(®ex, re, REG_EXTENDED))) {
|
||||||
|
regerror(ret, ®ex, error_msg, 128);
|
||||||
|
regfree(®ex);
|
||||||
|
LOG("Error: %s\n", error_msg);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (regexec(®ex, str, 32, pmatch, 0) == REG_NOMATCH) {
|
||||||
|
LOG("No match!\n");
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
*sub_expr = regex.re_nsub;
|
||||||
|
if (!regex.re_nsub) {
|
||||||
|
regfree(®ex);
|
||||||
|
LOG("Match without subexpressions!\n");
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG("N subexpr: %d\n", *sub_expr);
|
||||||
|
|
||||||
|
/* If exists sub-expressions, save them. */
|
||||||
|
for (size_t i = 0; i < regex.re_nsub + 1; i++) {
|
||||||
|
rm_so[i - 0] = pmatch[i].rm_so;
|
||||||
|
rm_eo[i - 0] = pmatch[i].rm_eo;
|
||||||
|
LOG("rm_so[i-1] = %d\nrm_eo[i-1] = %d\n",
|
||||||
|
rm_so[i],
|
||||||
|
rm_eo[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
regfree(®ex);
|
||||||
|
return (2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_C
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int32_t se, so[32], eo[32];
|
||||||
|
char msg[128] = {0};
|
||||||
|
|
||||||
|
char *re = argv[1];
|
||||||
|
char *in = argv[2];
|
||||||
|
|
||||||
|
if (argc < 3) {
|
||||||
|
fprintf(stderr, "Usage: %s <regex> <input-text>\n", argv[0]);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Regex : %s\n", re);
|
||||||
|
printf("input-text: %s\n", in);
|
||||||
|
|
||||||
|
int r = do_regex(re, in, &se, so, eo, msg);
|
||||||
|
switch (r) {
|
||||||
|
case -1:
|
||||||
|
printf("Error, reason: %s\n", msg);
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
printf("No match!\n");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
printf("Match without sub-expressions!\n");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
printf("Match!!: %.*s\n", eo[0]-so[0], in+so[0]);
|
||||||
|
printf("Found %d sub-expressions:\n", se);
|
||||||
|
for (int i = 1; i < se+1; i++) {
|
||||||
|
printf("$%d: %.*s\n", i, eo[i]-so[i], in+so[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user