#include #include #include #include #include #include "../logger.h" #include "utils.h" static void print_error(int code) { PCRE2_UCHAR message[256]; if (pcre2_get_error_message(code, message, sizeof(message) / sizeof(PCRE2_UCHAR))) LOG("PCRE2", "Error: %s\n", (const char *)message); } 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); 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)); int valid_n = results->n; resize_str_array(results, rc - 1 + results->n); 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[valid_n + j - 1] = malloc(substring_length + 1); sprintf(results->str[valid_n + j - 1], "%.*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); } 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"); break; case 0: LOG("PCRE2", "ovector was not big enough for all the captured substrings\n"); break; default: print_error(rc); return 1; } } } return 0; } int substitute_str(const char *subject, const char *pattern, const char *replacement, char **presult) { pcre2_code *re; pcre2_match_context *match_context; int rc, error; PCRE2_SIZE erroffset, outlength; PCRE2_UCHAR *outbuf; re = pcre2_compile((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, PCRE2_MULTILINE, &error, &erroffset, 0); if (!re) { print_error(error); return 1; } match_context = pcre2_match_context_create(0); outlength = 0; rc = pcre2_substitute(re, (PCRE2_SPTR)subject, PCRE2_ZERO_TERMINATED, 0, PCRE2_SUBSTITUTE_GLOBAL | PCRE2_SUBSTITUTE_OVERFLOW_LENGTH | PCRE2_SUBSTITUTE_EXTENDED, 0, match_context, (PCRE2_SPTR)replacement, PCRE2_ZERO_TERMINATED, 0, &outlength); if (rc != PCRE2_ERROR_NOMEMORY) { print_error(rc); return 1; } outbuf = malloc(outlength * sizeof(PCRE2_UCHAR)); rc = pcre2_substitute(re, (PCRE2_SPTR)subject, PCRE2_ZERO_TERMINATED, 0, PCRE2_SUBSTITUTE_GLOBAL | PCRE2_SUBSTITUTE_EXTENDED, 0, match_context, (PCRE2_SPTR)replacement, PCRE2_ZERO_TERMINATED, outbuf, &outlength); if (rc < 0) { print_error(rc); return 1; } *presult = (char *)outbuf; pcre2_match_context_free(match_context); pcre2_code_free(re); return 0; } const char *mimeType2ext(const char *mimeType) { static char mimeType_l[CHAR_MAX]; strcpy(mimeType_l, mimeType); const char *exts[2]; size_t extsCount = 0; char *token = strtok(mimeType_l, "/"); while (token != NULL && extsCount < 2) { exts[extsCount++] = token; token = strtok(NULL, "/"); } if (extsCount == 2) { return exts[1]; } return "mp4"; // Cannot parse, use default } 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; }