/*
 * Copyright 2014 Cloud Linux Zug GmbH
 *
 * Licensed under CLOUD LINUX LICENSE AGREEMENT
 * http://cloudlinux.com/docs/LICENSE.TXT
 *
 * The part the support library for lsapi & proxy_lsapi Apache modules
 * author Alexander Demeshko <ademeshko@cloudlinux.com>
 *
 */
 
#include <lscapi_util.h>

#include <unistd.h>

#include <mod_core.h>

//#pragma GCC visibility push(default)

const char* lscapi_php_value_handler(cmd_parms* cmd, void *cfg,
                                    const char *name, const char *value,
                                    int isAdmin) {
    php_param_t *eptr = apr_palloc(cmd->pool, sizeof(php_param_t));

    if(!strncasecmp(value, "none", 4)) {
        value = "";
    }

    eptr->valueLen = strlen(value);
    eptr->value = apr_pmemdup(cmd->pool, value, eptr->valueLen+1);
    eptr->isAdmin = isAdmin;
	//eptr->htaccess = ((cmd->override & (RSRC_CONF|ACCESS_CONF)) == 0);

	//ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, LSCAPI_APLOGNO
    //             "LSCAPI_PhpValueHandler: (%s)->(%s) isAdmin:%d", name, eptr->value, eptr->isAdmin);
    apr_hash_t* phpParams = ((lsapi_dir_conf_t*)cfg)->phpParams;

    apr_hash_set(phpParams, name, APR_HASH_KEY_STRING, eptr);

    return NULL;
}

const char *lscapi_php_flag_handler(cmd_parms *cmd, void *cfg,
                                    const char *name, const char *value, int isAdmin) {
    char boolVal[2];

    boolVal[0] = (!strcasecmp(value, "On") || (value[0] == '1' && value[1] == '\0')) ? '1' : '0';
	boolVal[1] = '\0';
    return lscapi_php_value_handler(cmd, cfg, name, boolVal, isAdmin);
}

void *lscapi_create_dir_config(apr_pool_t *pool, char *x) {
    lsapi_dir_conf_t *cfg = apr_palloc(pool, sizeof(lsapi_dir_conf_t));
    cfg->phpParams = apr_hash_make(pool);
    return cfg;
}

void *lscapi_merge_dir_config(apr_pool_t *pool, void *BASE, void *CUR) {
    lsapi_dir_conf_t *base = BASE;
    lsapi_dir_conf_t *cur = CUR;
    apr_hash_t *curH = cur->phpParams;
    apr_hash_t *baseH = base->phpParams;

    // initially lets create new config as a copy of the base one
    apr_hash_t *newH = apr_hash_copy(pool, baseH);

    // iterate over current config to check its values against values of the base config
    for(apr_hash_index_t *hi = apr_hash_first(pool, curH); hi; hi = apr_hash_next(hi)) {
        const char *key;
        apr_ssize_t keyLen;
        php_param_t *curVal;
        apr_hash_this(hi, (const void**)(&key), &keyLen, (void**)(&curVal));

        if(curVal->isAdmin) { // new admin value will beat even old admin one
            apr_hash_set(newH, key, keyLen, curVal);
            continue;
        }

        php_param_t *baseVal = apr_hash_get(baseH, key, keyLen);
        if(!baseVal                  // there is no such key in the base config
           || !baseVal->isAdmin)  {  // old value is not admin so new one will beat it

            apr_hash_set(newH, key, keyLen, curVal);
        }

    } // for


    lsapi_dir_conf_t *cfg = apr_palloc(pool, sizeof(lsapi_dir_conf_t));
    cfg->phpParams = newH;

    return cfg;
}

void *lscapi_create_svr_config(apr_pool_t *pool, server_rec *s) {
    //ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, LSCAPI_APLOGNO
    //                  "entering lsapi_create_svr_config" );
    lsapi_svr_conf_t *cfg = apr_pcalloc(pool, sizeof(lsapi_svr_conf_t));
#if MODULE_MAGIC_NUMBER_MAJOR > 20081212
    cfg->default_uid = ap_unixd_config.user_id;
    cfg->default_gid = ap_unixd_config.group_id;
#else
    cfg->default_uid = unixd_config.user_id;
    cfg->default_gid = unixd_config.group_id;
#endif
    cfg->terminate_backends_on_exit = 1;
    
    lscapi_init_backend_info(&cfg->backend_info);
    return cfg;
}

/*
    char *socket_path;
    uint32_t ruid;
    uint32_t rgid;
    uint32_t itk_uid;
    uint32_t itk_gid;

*/

void *lscapi_merge_svr_config(apr_pool_t *pool, void *BASE, void *CUR) {
    lsapi_svr_conf_t *base = BASE;
    lsapi_svr_conf_t *cur = CUR;

    lsapi_svr_conf_t *cfg = apr_palloc(pool, sizeof(lsapi_svr_conf_t));
    cfg->default_uid = cur->default_uid;
    cfg->default_gid = cur->default_gid;

    if(cur->suphp_uid > 0) {
        cfg->suphp_uid = cur->suphp_uid;
        cfg->suphp_gid = cur->suphp_gid;
    } else {
        cfg->suphp_uid = base->suphp_uid;
        cfg->suphp_gid = base->suphp_gid;
    }

    if(cur->ruid > 0) {
        cfg->ruid = cur->ruid;
        cfg->rgid = cur->rgid;
    } else {
        cfg->ruid = base->ruid;
        cfg->rgid = base->rgid;
    }

    if(cur->itk_uid > 0) {
        cfg->itk_uid = cur->itk_uid;
        cfg->itk_gid = cur->itk_gid;
    } else {
        cfg->itk_uid = base->itk_uid;
        cfg->itk_gid = base->itk_gid;
    }

    if(cur->socket_path) {
        cfg->socket_path = cur->socket_path;
    } else {
        cfg->socket_path = base->socket_path;
    }

    if(cur->terminate_backends_was_set) {
        cfg->terminate_backends_on_exit = cur->terminate_backends_on_exit;
    } else if(base->terminate_backends_was_set) {
        cfg->terminate_backends_on_exit = base->terminate_backends_on_exit;
    }
    
    if(cur->debug_enabled_was_set) {
        cfg->debug_enabled = cur->debug_enabled;
    } else if(base->debug_enabled_was_set) {
        cfg->debug_enabled = base->debug_enabled;
    }

    lscapi_merge_backend_info(&base->backend_info, &cur->backend_info, &cfg->backend_info);

    return cfg;
}

//#pragma GCC visibility pop
