Commit 43bc709b authored by Philipp Schafft's avatar Philipp Schafft 🦁

Feature: Added new resource match system

parent fd2556b4
......@@ -7,6 +7,7 @@ bin_PROGRAMS = icecast
noinst_HEADERS = \
icecasttypes.h \
admin.h \
resourcematch.h \
main.h \
cfgfile.h \
logging.h \
......@@ -69,6 +70,7 @@ icecast_SOURCES = \
xslt.c \
fserve.c \
admin.c \
resourcematch.c \
md5.c \
matchfile.c \
tls.c \
......
/* Icecast
*
* This program is distributed under the GNU General Public License, version 2.
* A copy of this license is included with this source.
*
* Copyright 2018, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "resourcematch.h"
static size_t count_groups(const char *pattern)
{
size_t ret = 0;
while (*pattern) {
for (; *pattern && *pattern != '%'; pattern++);
if (!*pattern) {
return ret;
}
pattern++;
if (!*pattern)
return ret;
if (*pattern != '%')
ret++;
pattern++;
}
return ret;
}
static resourcematch_extract_t * allocate_extract(const char *pattern)
{
size_t groups = count_groups(pattern);
resourcematch_extract_t *ret;
ret = calloc(1, sizeof(*ret));
if (!ret)
return NULL;
ret->groups = groups;
ret->group = calloc(groups, sizeof(*ret->group));
return ret;
}
static void strip_common_prefix(const char **pattern, const char **string)
{
const char *p = *pattern;
const char *s = *string;
for (; *p && *p != '%' && *p == *s; p++, s++);
*pattern = p;
*string = s;
}
static inline void setup_group(resourcematch_extract_t *extract, size_t idx, char type)
{
if (!extract)
return;
extract->group[idx].type = type;
extract->group[idx].raw = NULL;
}
static inline resourcematch_result_t match_lli(const char **string, resourcematch_extract_t *extract, size_t idx, int base)
{
long long int ret;
char *endptr;
errno = 0;
ret = strtoll(*string, &endptr, base);
if (errno != 0)
return RESOURCEMATCH_ERROR;
if (extract) {
extract->group[idx].result.lli = ret;
}
*string = endptr;
return RESOURCEMATCH_MATCH;
}
resourcematch_result_t resourcematch_match(const char *pattern, const char *string, resourcematch_extract_t **extract)
{
resourcematch_result_t ret;
resourcematch_extract_t *matches = NULL;
size_t idx = 0;
if (!pattern || !string)
return RESOURCEMATCH_ERROR;
if (extract) {
matches = allocate_extract(pattern);
if (!matches)
return RESOURCEMATCH_NOMATCH;
}
while (1) {
strip_common_prefix(&pattern, &string);
if (!*pattern && !*string) {
if (extract)
*extract = matches;
return RESOURCEMATCH_MATCH;
} else if (!*pattern || !*string) {
if (extract)
resourcematch_extract_free(matches);
return RESOURCEMATCH_NOMATCH;
}
if (*pattern != '%') {
if (extract)
resourcematch_extract_free(matches);
return RESOURCEMATCH_NOMATCH;
}
pattern++;
switch (*pattern) {
case '%':
if (*string == '%') {
string++;
} else {
if (extract)
resourcematch_extract_free(matches);
return RESOURCEMATCH_NOMATCH;
}
break;
#define _test_int(type,base) \
case (type): \
setup_group(matches, idx, *pattern); \
\
ret = match_lli(&string, matches, idx, (base)); \
if (ret != RESOURCEMATCH_MATCH) { \
if (extract) \
resourcematch_extract_free(matches); \
\
return ret; \
} \
idx++; \
break;
_test_int('i', 0);
_test_int('d', 10);
_test_int('x', 16);
_test_int('o', 8);
default:
if (extract)
resourcematch_extract_free(matches);
return RESOURCEMATCH_ERROR;
break;
}
pattern++;
}
}
void resourcematch_extract_free(resourcematch_extract_t *extract)
{
size_t i;
if (!extract)
return;
for (i = 0; i < extract->groups; i++) {
free(extract->group[i].raw);
}
free(extract->group);
free(extract);
}
/* Icecast
*
* This program is distributed under the GNU General Public License, version 2.
* A copy of this license is included with this source.
*
* Copyright 2018, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/
#ifndef __RESOURCEMATCH_H__
#define __RESOURCEMATCH_H__
#include <sys/types.h>
typedef enum {
RESOURCEMATCH_ERROR,
RESOURCEMATCH_MATCH,
RESOURCEMATCH_NOMATCH
} resourcematch_result_t;
typedef struct {
char type;
char *raw;
union {
const char *string;
long long int lli;
} result;
} resourcematch_group_t;
typedef struct {
size_t groups;
resourcematch_group_t *group;
} resourcematch_extract_t;
resourcematch_result_t resourcematch_match(const char *pattern, const char *string, resourcematch_extract_t **extract);
void resourcematch_extract_free(resourcematch_extract_t *extract);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment