#include #include #include #include #include #include "../logger.h" #include "utils.h" int regex_match(const char *subject, str_array_t patterns, str_array_t *results) { pcre2_code *re; int errornumber; int rc = PCRE2_ERROR_NOMATCH; PCRE2_SIZE subject_len = strlen(subject); PCRE2_SIZE offset = 0, erroroffset; PCRE2_SIZE *ovector; pcre2_match_data *match_data; for (unsigned short i = 0; i < patterns.n; i++) { DEBUG_PRINT("Gets pattern: %s\n", patterns.str[i]); re = pcre2_compile((PCRE2_SPTR)patterns.str[i], PCRE2_ZERO_TERMINATED, 0, &errornumber, &erroroffset, NULL); if (re == NULL) { PCRE2_UCHAR buffer[256]; pcre2_get_error_message(errornumber, buffer, sizeof(buffer)); LOG("PCRE2", "compilation failed at offset %d: %s\n", (int)erroroffset, buffer); return 1; } match_data = pcre2_match_data_create_from_pattern(re, NULL); unsigned char i = 0; while (offset < subject_len && (rc = pcre2_match(re, (PCRE2_SPTR)subject, (PCRE2_SIZE)subject_len, offset, 0, match_data, NULL)) > 0) { // results->str = realloc(results->str, sizeof(char *) * (rc + // results->n)); resize_str_array(results, rc + i); ovector = pcre2_get_ovector_pointer(match_data); DEBUG_PRINT("Get %d captures.\n", rc - 1); DEBUG_PRINT("Match succeeded at offset %d.\n", (int)ovector[0]); for (unsigned short j = 1; j < rc; j++) { PCRE2_SIZE substring_length = ovector[2 * j + 1] - ovector[2 * j]; PCRE2_SPTR substring = (PCRE2_SPTR)subject + ovector[2 * j]; /* Here we need to manually control the str array, * as PCRE2_SPTR == const unsigned char * (which cannot be directly casted) */ results->str[j] = malloc(substring_length + 1); sprintf(results->str[j], "%.*s", (int)substring_length, substring); DEBUG_PRINT("index: %2d, substring_length: %d\n", j, (int)substring_length); } offset = ovector[1]; DEBUG_PRINT("offset: %zu, subject_len: %zu\n", offset, subject_len); i++; } pcre2_match_data_free(match_data); pcre2_code_free(re); if (rc <= 0) { switch (rc) { case PCRE2_ERROR_NOMATCH: DEBUG_PRINT("No match found.\n"); return 0; break; case 0: LOG("PCRE2", "ovector was not big enough for all the captured substrings\n"); break; default: LOG("PCRE2", "Matching error %d\n", rc); return 1; } } } return 0; } int repchr(char *str, char t, char r) { int c = 0; for (size_t i = 0; str[i] != '\0'; i++) { if (str[i] == t) { str[i] = r; c++; } } return c; } void free_and_nullify(void *p) { if (p) { free(p); p = NULL; } }