src/server/safs/nametrans.c

Sun, 01 May 2022 10:48:20 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 01 May 2022 10:48:20 +0200
branch
webdav
changeset 319
a9b9344875aa
parent 277
7608af69739f
child 325
2d14055c3543
permissions
-rw-r--r--

add WebdavNSList <-> string converting functions

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2016 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 "nametrans.h"

#include "../daemon/log.h"
#include "../daemon/request.h"
#include "../util/pblock.h"
#include "../util/util.h"

#include "../public/vfs.h"

static int nametrans_set_vfs(pblock *pb, Session *sn, Request *rq) {
    char *vfsclass = pblock_findkeyval(pb_key_vfsclass, pb);
    if(!vfsclass) return 0;
    
    VFS *vfs = vfs_create(sn, rq, vfsclass, pb);
    if(!vfs) {
        return 1;
    }
    rq->vfs = vfs;
    return 0;
}

/*
 * assign_name
 *
 * Assigns the name specified by the name parameter if the uri has the
 * specified prefix.
 *
 * pblock parameter:
 * name     object name
 * from     optional uri prefix
 */
int assign_name(pblock *pb, Session *sn, Request *rq) {
    /* TODO: expression instead of simple prefix */

    char *name = pblock_findkeyval(pb_key_name, pb);
    char *from = pblock_findkeyval(pb_key_from, pb);

    if(!name) {
        log_ereport(LOG_MISCONFIG, "assign-name: missing name parameter");
        protocol_status(sn, rq, 500, NULL);
        return REQ_ABORTED;
    }
    
    if(from) {
        char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb);
        char c;
        int i = 0;
        while((c = from[i]) != 0) {
            if(c != uri[i]) {
                return REQ_NOACTION;
            }
            i++;
        }
    }
    
    if(nametrans_set_vfs(pb, sn, rq)) {
        log_ereport(LOG_FAILURE, "assign-name: cannot create VFS: name=%s from=%s", name, from);
        return REQ_ABORTED;
    }

    // add object to rq->vars
    pblock_kvinsert(pb_key_name, name, strlen(name), rq->vars);

    return REQ_NOACTION;
}

/*
 * document_root
 * 
 * Specifies the document root directory.
 * 
 * pblock parameter:
 * root   path to document root
 */
int document_root(pblock *pb, Session *sn, Request *rq) {
    char *root = pblock_findkeyval(pb_key_root, pb);
    if(!root) {
        log_ereport(LOG_MISCONFIG, "document-root: missing root parameter");
        protocol_status(sn, rq, 500, NULL);
        return REQ_ABORTED;
    }
    
    if(nametrans_set_vfs(pb, sn, rq)) {
        log_ereport(LOG_FAILURE, "document-root: cannot create VFS");
        return REQ_ABORTED;
    }
    
    sstr_t root_str = sstr(root);
    sstr_t uri_str = sstr(pblock_findkeyval(pb_key_uri, rq->reqpb));  
    
    request_set_path(root_str, uri_str, rq->vars);
    
    return REQ_PROCEED;
}

/*
 * pfx2dir
 * 
 * ...
 * 
 * pblock parameter:
 * from     prefix
 * dir      file system directory
 * name     (optional) object name
 * 
 */
int pfx2dir(pblock *pb, Session *sn, Request *rq) {
    char *from = pblock_findkeyval(pb_key_from, pb);
    char *dir = pblock_findkeyval(pb_key_dir, pb);
    char *name = pblock_findkeyval(pb_key_name, pb);
    
    if(!from || !dir) {
        if(!from && dir) {
            log_ereport(LOG_MISCONFIG, "pfx2dir: missing from parameter");
        } else if(!dir && from) {
            log_ereport(LOG_MISCONFIG, "pfx2dir: missing dir parameter");
        } else {
            log_ereport(
                    LOG_MISCONFIG,
                    "pfx2dir: missing from and dir parameter");
        }
        protocol_status(sn, rq, 500, NULL);
        return REQ_ABORTED;
    }
    
    // check prefix
    char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb);
    char fc;
    char uc;
    int i = 0;
    while((fc = from[i]) != 0) {
        uc = uri[i];
        if(fc != uc) {
            return REQ_NOACTION;
        }
        i++;
    }
    
    // url has the specified prefix
    
    uri = uri + i;
    if(uri[0] == '/') {
        uri++;
    }
    
    if(nametrans_set_vfs(pb, sn, rq)) {
        log_ereport(LOG_FAILURE, "pfx2dir: cannot create VFS: from=%s dir=%s name=%s", from, dir, name);
        return REQ_ABORTED;
    }
    
    request_set_path(sstr(dir), sstr(uri), rq->vars);
    
    if(name) {
        // add object to rq->vars
        pblock_kvinsert(pb_key_name, name, strlen(name), rq->vars);
    }
    
    return REQ_PROCEED;
}


int redirect(pblock *pb, Session *sn, Request *rq) {
    char *from = pblock_findval("from", pb);
    char *url = pblock_findval("url", pb);
    
    if(!from || !url) {
        log_ereport(LOG_MISCONFIG, "redirect: missing parameter (from, url)");
        return REQ_ABORTED;
    }
    
    char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb);
    if(!strcmp(uri, from)) {
        pblock_nvinsert("location", url, rq->srvhdrs);
        
        protocol_status(sn, rq, 302, NULL); 
        return REQ_ABORTED;
    }
    
    return REQ_NOACTION;
}

/*
 * provisional rewrite saf
 */
int simple_rewrite(pblock *pb, Session *sn, Request *rq) {
    char *from = pblock_findval("from", pb);
    char *root = pblock_findval("root", pb);
    char *path = pblock_findval("path", pb);
    char *name = pblock_findval("name", pb);
    
    if(!from || !path || !root) {
        log_ereport(LOG_MISCONFIG, "simple-rewrite: missing parameter (from, root, path)");
        return REQ_ABORTED;
    }
    
    if(nametrans_set_vfs(pb, sn, rq)) {
        log_ereport(LOG_FAILURE, "simple-rewrite: cannot create VFS: from=%s root=%s path=%s name=%s", from, root, path, name);
        return REQ_ABORTED;
    }
    
    char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb);
    sstr_t u = sstr(uri);
    sstr_t f = sstr(from);
    if(sstrprefix(u, f)) {
        sstr_t suf = sstrsubs(u, f.length);
        sstr_t ppath = sstrcat(2, sstr(path), suf);
        
        request_set_path(sstr(root), ppath, rq->vars);
        free(ppath.ptr);
        
        if(name) {
            // add object to rq->vars
            pblock_kvinsert(pb_key_name, name, strlen(name), rq->vars);
        }
    }
    
    return REQ_NOACTION;
}

mercurial