src/server/safs/common.c

Sun, 19 Mar 2023 16:48:19 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 19 Mar 2023 16:48:19 +0100
changeset 484
c036a8b242a8
parent 415
d938228c382e
child 490
d218607f5a7e
permissions
-rw-r--r--

implement webdav xattr namespace lists

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2013 Olaf Wintermann. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "common.h"

#include "../daemon/httprequest.h"
#include "../daemon/log.h"

#include "../util/pblock.h"
#include "../util/util.h"
#include <cx/map.h>
#include <cx/hash_map.h>

static CxMap *var_names;

enum SAFVarNames {
    COMMONSAF_INSERT_CLIENT = 1,
    COMMONSAF_INSERT_VARS,
    COMMONSAF_INSERT_REQPB,
    COMMONSAF_INSERT_HEADERS,
    COMMONSAF_INSERT_SRVHDRS,
    COMMONSAF_SET_CLIENT,
    COMMONSAF_SET_VARS,
    COMMONSAF_SET_REQPB,
    COMMONSAF_SET_HEADERS,
    COMMONSAF_SET_SRVHDRS,
    COMMONSAF_REMOVE_CLIENT,
    COMMONSAF_REMOVE_VARS,
    COMMONSAF_REMOVE_REQPB,
    COMMONSAF_REMOVE_HEADERS,
    COMMONSAF_REMOVE_SRVHDRS,
    COMMONSAF_ABORT,
    COMMONSAF_NOACTION,
    COMMONSAF_ERROR,
    COMMONSAF_ESCAPE,
    COMMONSAF_FIND_PATHINFO_FORWARD,
    COMMONSAF_HTTP_DOWNGRADE,
    COMMONSAF_HTTP_UPGRADE,
    COMMONSAF_KEEP_ALIVE,
    COMMONSAF_NAME,
    COMMONSAF_SENTHDRS,
    COMMONSAF_STOP,
    COMMONSAF_URL
};

#define COMMONSAF_RET_DEF 0
#define COMMONSAF_RET_NOACTION 1
#define COMMONSAF_RET_STOP 2
#define COMMONSAF_REQ_ABORTED -1
#define COMMONSAF_RET_ERROR -2

void common_saf_init() {
    var_names = cxHashMapCreate(cxDefaultAllocator, 32);
    
    cxMapPut(var_names, cx_hash_key_str("insert-client"), (void*)(intptr_t)COMMONSAF_INSERT_CLIENT);
    cxMapPut(var_names, cx_hash_key_str("insert-vars"), (void*)(intptr_t)COMMONSAF_INSERT_VARS);
    cxMapPut(var_names, cx_hash_key_str("insert-reqpb"), (void*)(intptr_t)COMMONSAF_INSERT_REQPB);
    cxMapPut(var_names, cx_hash_key_str("insert-headers"), (void*)(intptr_t)COMMONSAF_INSERT_HEADERS);
    cxMapPut(var_names, cx_hash_key_str("insert-srvhdrs"), (void*)(intptr_t)COMMONSAF_INSERT_SRVHDRS);
    
    cxMapPut(var_names, cx_hash_key_str("set-client"), (void*)(intptr_t)COMMONSAF_SET_CLIENT);
    cxMapPut(var_names, cx_hash_key_str("set-vars"), (void*)(intptr_t)COMMONSAF_SET_VARS);
    cxMapPut(var_names, cx_hash_key_str("set-reqpb"), (void*)(intptr_t)COMMONSAF_SET_REQPB);
    cxMapPut(var_names, cx_hash_key_str("set-headers"), (void*)(intptr_t)COMMONSAF_SET_HEADERS);
    cxMapPut(var_names, cx_hash_key_str("set-srvhdrs"), (void*)(intptr_t)COMMONSAF_SET_SRVHDRS);
    
    cxMapPut(var_names, cx_hash_key_str("remove-client"), (void*)(intptr_t)COMMONSAF_REMOVE_CLIENT);
    cxMapPut(var_names, cx_hash_key_str("remove-vars"), (void*)(intptr_t)COMMONSAF_REMOVE_VARS);
    cxMapPut(var_names, cx_hash_key_str("remove-reqpb"), (void*)(intptr_t)COMMONSAF_REMOVE_REQPB);
    cxMapPut(var_names, cx_hash_key_str("remove-headers"), (void*)(intptr_t)COMMONSAF_REMOVE_HEADERS);
    cxMapPut(var_names, cx_hash_key_str("remove-srvhdrs"), (void*)(intptr_t)COMMONSAF_REMOVE_SRVHDRS);
    
    cxMapPut(var_names, cx_hash_key_str("abort"), (void*)(intptr_t)COMMONSAF_ABORT);
    cxMapPut(var_names, cx_hash_key_str("noaction"), (void*)(intptr_t)COMMONSAF_NOACTION);
    cxMapPut(var_names, cx_hash_key_str("error"), (void*)(intptr_t)COMMONSAF_ERROR);
    cxMapPut(var_names, cx_hash_key_str("escape"), (void*)(intptr_t)COMMONSAF_ESCAPE);
    cxMapPut(var_names, cx_hash_key_str("find-pathinfo-forward"), (void*)(intptr_t)COMMONSAF_FIND_PATHINFO_FORWARD);
    cxMapPut(var_names, cx_hash_key_str("http-downgrade"), (void*)(intptr_t)COMMONSAF_HTTP_DOWNGRADE);
    cxMapPut(var_names, cx_hash_key_str("http-upgrade"), (void*)(intptr_t)COMMONSAF_HTTP_UPGRADE);
    cxMapPut(var_names, cx_hash_key_str("keep-alive"), (void*)(intptr_t)COMMONSAF_KEEP_ALIVE);
    cxMapPut(var_names, cx_hash_key_str("name"), (void*)(intptr_t)COMMONSAF_NAME);
}

int print_message(pblock *pb, Session *sn, Request *rq) {
    char *msg = pblock_findval("msg", pb);
    if(msg) {
        log_ereport(LOG_INFORM, "%s", msg);
    }    
    
    return REQ_NOACTION;
}

static void var_set(char *value, pblock *pb, WSBool insert) {
    cxstring n;
    cxstring v;
    v.ptr = NULL;
    
    n.ptr = value;
    int i;
    int len = strlen(value);
    for(i=1;i<len;i++) {
        if(value[i] == '=') {
            n.length = i;
            v = cx_strsubs(cx_strn(value, len), i + 1);
            break;
        }
    }
    if(!v.ptr || v.length == 0) {
        log_ereport(
                LOG_MISCONFIG,
                "set-variable: string '%s' has not name=value format",
                value);
        return;
    }
    
    if(!insert) {
        // TODO
    }
    pblock_nvlinsert(n.ptr, n.length, v.ptr, v.length, pb);
}

static int set_var(Session *sn, Request *rq, const char *var, char *value) {
    intptr_t v = (intptr_t)cxMapGet(var_names, cx_hash_key_str(var));
    switch(v) {
        default: break;
        case COMMONSAF_INSERT_CLIENT: var_set(value, sn->client, TRUE); break;
        case COMMONSAF_INSERT_VARS: var_set(value, rq->vars, TRUE); break;
        case COMMONSAF_INSERT_REQPB: var_set(value, rq->reqpb, TRUE); break;
        case COMMONSAF_INSERT_HEADERS: var_set(value, rq->headers, TRUE); break;
        case COMMONSAF_INSERT_SRVHDRS: var_set(value, rq->srvhdrs, TRUE); break;
        case COMMONSAF_SET_CLIENT: var_set(value, sn->client, FALSE); break;
        case COMMONSAF_SET_VARS: var_set(value, rq->vars, FALSE); break;
        case COMMONSAF_SET_REQPB: var_set(value, rq->reqpb, FALSE); break;
        case COMMONSAF_SET_HEADERS: var_set(value, rq->headers, FALSE); break;
        case COMMONSAF_SET_SRVHDRS: var_set(value, rq->srvhdrs, FALSE); break;
        case COMMONSAF_REMOVE_CLIENT: pblock_remove(value, sn->client); break;
        case COMMONSAF_REMOVE_VARS: pblock_remove(value, rq->vars); break;
        case COMMONSAF_REMOVE_HEADERS: pblock_remove(value, rq->headers);break;
        case COMMONSAF_REMOVE_SRVHDRS: pblock_remove(value, rq->srvhdrs); break;
        case COMMONSAF_ABORT: return COMMONSAF_REQ_ABORTED;
        case COMMONSAF_NOACTION: return COMMONSAF_RET_NOACTION;
        case COMMONSAF_ERROR: {
            int len = strlen(value);
            WSBool isnum = TRUE;
            int i;
            for(i=0;i<len;i++) {
                if(!isdigit(value[i])) {
                    isnum = FALSE;
                    break;
                }
            }
            
            int64_t status;
            int ret = util_strtoint(value, &status);
            if(status < 100 || ret > 999 || !ret) {
                log_ereport(
                        LOG_MISCONFIG,
                        "set-variable: error value must contain a 3-digit http status code");
                protocol_status(sn, rq, 500, NULL);
                return COMMONSAF_RET_ERROR;
            }
            
            const char *msg = isnum ? NULL : cx_strtrim(cx_str(value + i)).ptr;
            protocol_status(sn, rq, (int)status, msg);
            
            return COMMONSAF_REQ_ABORTED;
        }
        case COMMONSAF_ESCAPE: break;
        case COMMONSAF_FIND_PATHINFO_FORWARD: break;
        case COMMONSAF_HTTP_DOWNGRADE: break;
        case COMMONSAF_HTTP_UPGRADE: break;
        case COMMONSAF_KEEP_ALIVE: {
            rq->rq_attr.keep_alive = util_getboolean(var, 0);
            break;
        }
        case COMMONSAF_NAME: {
            pblock_kvinsert(pb_key_name, value, strlen(value), rq->vars);
            break;
        }
        case COMMONSAF_SENTHDRS: break;
        case COMMONSAF_STOP: return COMMONSAF_RET_STOP;
        case COMMONSAF_URL: break;
    }
    return COMMONSAF_RET_DEF;
}

int set_variable(pblock *pb, Session *sn, Request *rq) {
    int ret = REQ_NOACTION;
    int set = 0;
    
    for(int i=0;i<pb->hsize;i++) {
        pb_entry *entry = pb->ht[i];
        while(entry) {
            int r = set_var(sn, rq, entry->param->name, entry->param->value);
            switch(r) {
                default:
                case COMMONSAF_RET_DEF: break;
                case COMMONSAF_RET_NOACTION: set = 1; ret = REQ_NOACTION; break;
                case COMMONSAF_RET_STOP: set = 1; ret = REQ_PROCEED; break;
                case COMMONSAF_REQ_ABORTED: ret = set ? ret : REQ_ABORTED; break;
                case COMMONSAF_RET_ERROR: return REQ_ABORTED;
            }
            entry = entry->next;
        }
    }
    
    return ret;
}

mercurial