src/server/util/util.c

Mon, 04 Nov 2013 10:55:27 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Mon, 04 Nov 2013 10:55:27 +0100
changeset 96
0185b13bf41f
parent 91
fac51f87def0
child 99
b9a6af0ae41a
permissions
-rw-r--r--

added document-root and pfx2dir nametrans safs

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
 *
 * THE BSD LICENSE
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer. 
 * 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. 
 *
 * Neither the name of the  nor the names of its contributors may be
 * used to endorse or promote products derived from this software without 
 * specific prior written permission. 
 *
 * 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 OWNER 
 * 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.
 */

/*
 * util.c: A hodge podge of utility functions and standard functions which 
 *         are unavailable on certain systems
 * 
 * Rob McCool
 */

#ifdef XP_UNIX
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#include "prthread.h"
#endif /* XP_UNIX */


//include "nspr.h"
#include <errno.h>

#include "../daemon/netsite.h"
#include "../public/nsapi.h"
#include <ucx/string.h>
#include <ucx/mempool.h>

#include "pblock.h"
#include "util.h"



/* ------------------------------ _uudecode ------------------------------- */

static const unsigned char pr2six[256] = {
    64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
    64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,62,64,64,64,63,
    52,53,54,55,56,57,58,59,60,61,64,64,64,64,64,64,64,0,1,2,3,4,5,6,7,8,9,
    10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,64,64,64,64,64,64,26,27,
    28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
    64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
    64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
    64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
    64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
    64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
    64,64,64,64,64,64,64,64,64,64,64,64,64
};

/** you MUST reserve at least 2 additional bytes for bufout */
size_t util_base64decode(char *bufcoded, size_t codedbytes, char *bufout) {
    register char *bufin = bufcoded;
    register int nprbytes;
    size_t nbytesdecoded;

    /* Find the length */
    nprbytes = (int) codedbytes;
    while(pr2six[(int)(bufin[nprbytes-1])] >= 64) {
      nprbytes--;
    }
    nbytesdecoded = ((nprbytes+3)/4) * 3;

    while (nprbytes > 0) {
        *(bufout++) = (unsigned char)
            (pr2six[(int)(*bufin)] << 2 | pr2six[(int)bufin[1]] >> 4);
        *(bufout++) = (unsigned char)
            (pr2six[(int)bufin[1]] << 4 | pr2six[(int)bufin[2]] >> 2);
        *(bufout++) = (unsigned char)
            (pr2six[(int)bufin[2]] << 6 | pr2six[(int)bufin[3]]);
        bufin += 4;
        nprbytes -= 4;
    }

    if(nprbytes & 03) {
        if(pr2six[(int)bufin[-2]] > 63)
            nbytesdecoded -= 2;
        else
            nbytesdecoded -= 1;
    }

    return nbytesdecoded;
}


/* --------------------------- util_env_create ---------------------------- */


NSAPI_PUBLIC char **util_env_create(char **env, int n, int *pos)
{
    int x;

    if(!env) {
        *pos = 0;
        return (char **) MALLOC((n + 1)*sizeof(char *));
    }
    else {
        for(x = 0; (env[x]); x++);
        env = (char **) REALLOC(env, (n + x + 1)*(sizeof(char *)));
        *pos = x;
        return env;
    }
}


/* ---------------------------- util_env_free ----------------------------- */


NSAPI_PUBLIC void util_env_free(char **env)
{
    register char **ep = env;

    for(ep = env; *ep; ep++)
        FREE(*ep);
    FREE(env);
}

/* ----------------------------- util_env_str ----------------------------- */


NSAPI_PUBLIC char *util_env_str(const char *name, const char *value) {
    char *t;

    t = (char *) MALLOC(strlen(name)+strlen(value)+2); /* 2: '=' and '\0' */

    sprintf(t, "%s=%s", name, value);

    return t;
}


/* --------------------------- util_env_replace --------------------------- */


NSAPI_PUBLIC void util_env_replace(char **env, const char *name, const char *value)
{
    int x, y, z;
    char *i;

    for(x = 0; env[x]; x++) {
        i = strchr(env[x], '=');
        *i = '\0';
        if(!strcmp(env[x], name)) {
            y = strlen(env[x]);
            z = strlen(value);

            env[x] = (char *) REALLOC(env[x], y + z + 2);
            util_sprintf(&env[x][y], "=%s", value);
            return;
        }
        *i = '=';
    }
}


/* ---------------------------- util_env_find ----------------------------- */


NSAPI_PUBLIC char *util_env_find(char **env, const char *name)
{
    char *i;
    int x, r;

    for(x = 0; env[x]; x++) {
        i = strchr(env[x], '=');
        *i = '\0';
        r = !strcmp(env[x], name);
        *i = '=';
        if(r)
            return i + 1;
    }
    return NULL;
}


/* ---------------------------- util_env_copy ----------------------------- */


NSAPI_PUBLIC char **util_env_copy(char **src, char **dst)
{
    char **src_ptr;
    int src_cnt;
    int index;

    if (!src)
        return NULL;

    for (src_cnt = 0, src_ptr = src; *src_ptr; src_ptr++, src_cnt++);

    if (!src_cnt)
        return NULL;

    dst = util_env_create(dst, src_cnt, &index);

    for (src_ptr = src; *src_ptr; index++, src_ptr++)
        dst[index] = STRDUP(*src_ptr);
    dst[index] = NULL;
    
    return dst;
}

/* ----------------------------- util_sprintf ----------------------------- */

NSAPI_PUBLIC int util_vsnprintf(char *s, int n, register const char *fmt, 
                                va_list args)
{
    return vsnprintf(s, n, fmt, args);
}

NSAPI_PUBLIC int util_snprintf(char *s, int n, const char *fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    return vsnprintf(s, n, fmt, args);
}

NSAPI_PUBLIC int util_vsprintf(char *s, register const char *fmt, va_list args)
{
    return vsprintf(s, fmt, args);
}

NSAPI_PUBLIC int util_sprintf(char *s, const char *fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    return vsprintf(s, fmt, args);
}

// TODO: asprintf



/* -------------------------- util_uri_unescape --------------------------- */

NSAPI_PUBLIC void util_uri_unescape(char *s)
{
    char *t, *u;

    for(t = s, u = s; *t; ++t, ++u) {
        if((*t == '%') && t[1] && t[2]) {
            *u = ((t[1] >= 'A' ? ((t[1] & 0xdf) - 'A')+10 : (t[1] - '0'))*16) +
                  (t[2] >= 'A' ? ((t[2] & 0xdf) - 'A')+10 : (t[2] - '0'));
            t += 2;
        }
        else
            if(u != t)
                *u = *t;
    }
    *u = *t;
}

/*
 * Same as util_uri_unescape, but returns success/failure
 */
NSAPI_PUBLIC int util_uri_unescape_strict(char *s)
{
    char *t, *u, t1, t2;
    int rv = 1;

    for(t = s, u = s; *t; ++t, ++u) {
        if (*t == '%') {
            t1 = t[1] & 0xdf; /* [a-f] -> [A-F] */
            if ((t1 < 'A' || t1 > 'F') && (t[1] < '0' || t[1] > '9'))
                rv = 0;

            t2 = t[2] & 0xdf; /* [a-f] -> [A-F] */
            if ((t2 < 'A' || t2 > 'F') && (t[2] < '0' || t[2] > '9'))
                rv = 0;

            *u = ((t[1] >= 'A' ? ((t[1] & 0xdf) - 'A')+10 : (t[1] - '0'))*16) +
                  (t[2] >= 'A' ? ((t[2] & 0xdf) - 'A')+10 : (t[2] - '0'));
            t += 2;
        }
        else if (u != t)
            *u = *t;
    }
    *u = *t;

    return rv;
}


NSAPI_PUBLIC int
util_uri_unescape_plus (const char *src, char *trg, int len)
{
    const char *t = src;
    char *u = trg == NULL ? (char *)src : trg;
    int	rlen = 0;

    if (len == -1)
        len = strlen (src);

    for( ; len && *t; ++t, ++u, len--, rlen++)
    {
        if((*t == '%') && t[1] && t[2])
        {
            *u = ((t[1] >= 'A' ? ((t[1] & 0xdf) - 'A') + 10 : (t[1] - '0')) * 16) +
                  (t[2] >= 'A' ? ((t[2] & 0xdf) - 'A') + 10 : (t[2] - '0'));
            t  += 2;
            len-= 2;
        }
        else
            if (*t == '+')
                *u = ' ';
            else
                *u = *t;
    }
    *u = 0;
    return rlen;
}


NSAPI_PUBLIC int INTutil_getboolean(const char *v, int def) {
    if(v[0] == 'T' || v[0] == 't') {
        return 1;
    }
    if(v[0] == 'F' || v[0] == 'f') {
        return 0;
    }
    return def;
}


/* ------------------------------ util_itoa ------------------------------- */
/*
NSAPI_PUBLIC int util_itoa(int i, char *a)
{
    int len = util_i64toa(i, a);

    PR_ASSERT(len < UTIL_ITOA_SIZE);

    return len;
}
*/
NSAPI_PUBLIC int INTutil_itoa(int i, char *a) {
    return INTutil_i64toa(i, a);
}


/* ----------------------------- util_i64toa ------------------------------ */

/*
 * Assumption: Reversing the digits will be faster in the general case
 * than doing a log10 or some nasty trick to find the # of digits.
 */

NSAPI_PUBLIC int INTutil_i64toa(int64_t i, char *a)
{
    register int x, y, p;
    register char c;
    int negative;

    negative = 0;
    if(i < 0) {
        *a++ = '-';
        negative = 1;
        i = -i;
    }
    p = 0;
    while(i > 9) {
        a[p++] = (i%10) + '0';
        i /= 10;
    }
    a[p++] = i + '0';

    if(p > 1) {
        for(x = 0, y = p - 1; x < y; ++x, --y) {
            c = a[x];
            a[x] = a[y];
            a[y] = c;
        }
    }
    a[p] = '\0';

    //PR_ASSERT(p + negative < UTIL_I64TOA_SIZE);

    return p + negative;
}



#ifndef XP_WIN32
NSAPI_PUBLIC struct passwd *
util_getpwnam(const char *name, struct passwd *result, char *buffer, 
	int buflen)
{
    struct passwd *rv;

#if defined(AIX) || defined(LINUX) || defined(HPUX) || defined(OSX)
    errno = getpwnam_r(name, result, buffer, buflen, &rv);
    if (errno != 0)
        rv = NULL;
#else
    rv = getpwnam_r(name, result, buffer, buflen);
#endif

    return rv;
}
#endif


#ifndef XP_WIN32
NSAPI_PUBLIC struct passwd *
util_getpwuid(uid_t uid, struct passwd *result, char *buffer, int buflen)
{
    struct passwd *rv;

#if defined(AIX) || defined(LINUX) || defined(HPUX) || defined(OSX)
    errno = getpwuid_r(uid, result, buffer, buflen, &rv);
    if (errno != 0)
        rv = NULL;
#else
    rv = getpwuid_r(uid, result, buffer, buflen);
#endif

    return rv;
}
#endif


NSAPI_PUBLIC int util_errno2status(int errno_value) {
    switch(errno_value) {
        case 0: {
            return 200;
        }
        case EACCES: {
            return 403;
        }
        case ENOENT: {
            return 404;
            break;
        }
    }
    return 500;
}



NSAPI_PUBLIC
sstr_t util_path_append(pool_handle_t *pool, char *path, char *ch) {
    sstr_t parent = sstr(path);
    sstr_t child = sstr(ch);
    sstr_t newstr;
    sstr_t s;
    
    s.length = 0;
    s.ptr = NULL;
    newstr.length = parent.length + child.length;
    if(parent.ptr[parent.length - 1] != '/') {
        s = sstrn("/", 1);
        newstr.length++;
    }
    
    newstr.ptr = pool_malloc(pool, newstr.length + 1);
    if(!newstr.ptr) {
        // TODO: error
        newstr.length = 0;
        return newstr;
    }
    if(s.length == 1) {
        newstr = sstrncat(newstr, 3, parent, s, child);
    } else {
        newstr = sstrncat(newstr, 2, parent, child);
    }
    newstr.ptr[newstr.length] = '\0';
    
    return newstr;
}

sstr_t util_path_remove_last(sstr_t path) {
    int i;
    for(i=path.length-1;i>=0;i--) {
        char c = path.ptr[i];
        if(c == '/') {
            path.ptr[i] = 0;
            path.length = i;
            break;
        }
    }
    if(i < 0) {
        path.ptr = NULL;
        path.length = 0;
    }
    return path;
}

void util_add_ppath(sstr_t root, sstr_t path, pblock *vars) {
    // concat path
    sstr_t translated_path;
    translated_path.length = root.length + path.length;
    translated_path.ptr = alloca(translated_path.length);
    
    translated_path = sstrncat(translated_path, 2, root, path);
    
    // add path to specified pblock
    pblock_kvinsert(
            pb_key_ppath,
            translated_path.ptr,
            translated_path.length,
            vars);
}


// new - code in parts from params.cpp
NSAPI_PUBLIC pblock* util_parse_param(pool_handle_t *pool, char *query) {
    pblock *pb = pblock_create_pool(pool, 32);
    if(!pb) {
        return NULL;
    }
    if(!query || !(*query)) {
        return pb;
    }
    
    int loopFlag = 1;
    int nl = 0;	// size of the name substring
    int vl = 0;	// size of the value substring
    int state = 0;
    const char *np = query;
    const char *vp = NULL;
    
    while (loopFlag) {
        char delim = *query++;
        switch (delim) {
            case '&':
            case '\0': {
                if(!delim) {
                    loopFlag = 0;
                }
                
                state = 0;
                
                if(nl > 0) {
                    util_uri_unescape_plus(np, NULL, nl);
                    util_uri_unescape_plus(vp, NULL, vl);
                    pblock_nvlinsert(np, nl, vp, vl, pb);
                }
                
                nl = 0;
                vl = 0;
                vp = NULL;
                np = query;
                break;
            }
            case '=': {
                state = 1;
                vp = query;
                break;
            }
            default: {
                if(state) {
                    vl++;
                } else {
                    nl++;
                }
            }
        } /* switch */
    } /* while */

    return pb;
}

// TODO: remove
sstr_t sstrdup_mp(UcxMempool *pool, sstr_t s) {
    sstr_t newstring;
    newstring.ptr = (char*)ucx_mempool_malloc(pool, s.length + 1);
    if (newstring.ptr != NULL) {
        newstring.length = s.length;
        newstring.ptr[newstring.length] = 0;

        memcpy(newstring.ptr, s.ptr, s.length);
    }

    return newstring;
}

mercurial