UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2025 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "rewrite.h" 30 #include "config.h" 31 32 33 RewriteRule* rewrite_rule_create(ServerConfiguration *cfg, cxmutstr regex, cxmutstr url) { 34 const CxAllocator *a = cfg->a; 35 36 regex_t reg; 37 if(regex.ptr) { 38 if(regcomp(&reg, regex.ptr, REG_EXTENDED)) { 39 log_ereport(LOG_FAILURE, "rewrite: cannot compile regex: %s", regex.ptr); 40 return NULL; 41 } 42 } 43 44 RewriteRule *rule = cxMalloc(a, sizeof(RewriteRule)); 45 if(!rule) { 46 return NULL; 47 } 48 rule->has_regex = regex.ptr != NULL; 49 rule->regex = reg; 50 rule->url = string_template_compile(a, cx_strcast(url)); 51 if(!rule->url) { 52 return NULL; 53 } 54 55 return rule; 56 } 57 58 59 typedef struct RVar { 60 cxstring str; 61 regmatch_t *match; 62 int nmatch; 63 } RVar; 64 65 static cxmutstr get_var( 66 const CxAllocator *a, 67 StringTemplateSegment *seg, 68 RVar *vardata, 69 WSBool *free_str) 70 { 71 if(seg->type != STRING_SEGMENT_NUM_PLACEHOLDER || seg->num < 0 || seg->num >= vardata->nmatch) { 72 return (cxmutstr){NULL, 0}; 73 } 74 regmatch_t m = vardata->match[seg->num]; 75 if(m.rm_eo == -1 || m.rm_so == -1) { 76 return (cxmutstr){NULL, 0}; 77 } 78 cxstring ret = cx_strsubsl(vardata->str, m.rm_so, m.rm_eo-m.rm_so); 79 return (cxmutstr){(char*)ret.ptr, ret.length}; 80 } 81 82 int rewrite_url( 83 RewriteRule *rule, 84 regmatch_t *match, 85 int nmatch, 86 const CxAllocator *a, 87 const char *url, 88 char **new_url) 89 { 90 *new_url = NULL; 91 92 RVar vars; 93 vars.str = cx_str(url); 94 vars.match = match; 95 vars.nmatch = nmatch; 96 97 regmatch_t rewrite_match[WS_REWRITE_NMATCH]; 98 if(rule->has_regex) { 99 if(regexec(&rule->regex, url, WS_REWRITE_NMATCH, rewrite_match, 0) != 0) { 100 return 0; 101 } 102 vars.match = rewrite_match; 103 vars.nmatch = WS_REWRITE_NMATCH; 104 } 105 106 // build new url 107 cxmutstr newstr = string_template_build_string(rule->url, a, (strtpl_var_func)get_var, &vars); 108 if(newstr.length == 0) { 109 return 1; 110 } 111 *new_url = newstr.ptr; 112 113 return 0; 114 } 115