<?php
/**
 * -----------------------------------------------------------------------
 * vBSSO is a solution which helps you connect to different software platforms
 * via secure Single Sign-On.
 *
 * Copyright (c) 2011-2017 vBSSO. All Rights Reserved.
 * This software is the proprietary information of vBSSO.
 *
 * Author URI: http://www.vbsso.com
 * License: GPL version 2 or later -
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * -----------------------------------------------------------------------
 */

/**
 * Report error
 *
 * @param mixed $error error message
 *
 * @return array
 */
function vbsso_listener_report_error($error) {
    $message = !is_string($error) ? $error[0] : $error;

    return array(SHAREDAPI_EVENT_FIELD_ERROR_CODE => '', SHAREDAPI_EVENT_FIELD_ERROR_MESSAGE => $message,
        SHAREDAPI_EVENT_FIELD_ERROR_DATA => '');
}

/**
 * Verify listener
 *
 * @param array $json array
 *
 * @return array
 */
function vbsso_listener_verify($json) {
    global $conf;
    $vbsso = new action_plugin_vbsso();
    if (!$conf['useacl']) {
        return array(SHAREDAPI_EVENT_FIELD_ERROR => $vbsso->getLang('acl_is_off'));
    }

    $supported = vbsso_get_supported_api_properties();
    $settings = array();

    foreach ($supported as $key => $item) {
        $settings[$key] = $json[$item['field']];
    }

    vbsso_save_platform_settings($settings);

    return array(SHAREDAPI_EVENT_FIELD_DATA => array(SHAREDAPI_EVENT_FIELD_VERIFY => TRUE));
}


/**
 * User load
 *
 * @param array $json        array
 * @param bool  $create_user flag
 *
 * @return bool
 */
function vbsso_listener_user_load($json, $create_user = FALSE) {
    global $vbsso_settings;
    $auth = (class_exists('auth_plugin_authplain')) ? new auth_plugin_authplain() : new auth_plain();

    $usergroups = array();
    $plugin_ugs = json_decode($vbsso_settings[VBSSO_NAMED_EVENT_FIELD_USERGROUPS_ASSOC]);

    foreach (explode(',', $json[SHAREDAPI_EVENT_FIELD_USERGROUPS]) as $ug) {
        $usergroups[] = (isset($plugin_ugs->$ug)) ? $plugin_ugs->$ug : 'user';
    }

    if (!$user = $auth->getUserData($json[SHAREDAPI_EVENT_FIELD_USERNAME]) and $create_user) {
        if ($auth->createUser($json[SHAREDAPI_EVENT_FIELD_USERNAME], '', $json[SHAREDAPI_EVENT_FIELD_USERNAME],
            $json[SHAREDAPI_EVENT_FIELD_EMAIL], array_unique($usergroups))) {
            $user = $auth->getUserData($json[SHAREDAPI_EVENT_FIELD_USERNAME]);
        }
    }

    return ($user and $user['mail'] == $json[SHAREDAPI_EVENT_FIELD_EMAIL]) ? $user : FALSE;
}

/**
 * Listener register
 *
 * @param array $json array
 *
 * @return array
 */
function vbsso_listener_register($json) {
    $u = vbsso_listener_user_load($json, TRUE);

    if (is_array($u)) {
        return array(SHAREDAPI_EVENT_FIELD_DATA => 'User ' . $json[SHAREDAPI_EVENT_FIELD_USERNAME]
            . ' successfully created');
    } else {
        return array(SHAREDAPI_EVENT_FIELD_ERROR => $u);
    }
}

/**
 * Listener logout
 *
 * @return void
 */
function vbsso_listener_logout() {
    auth_logoff(TRUE);
}

/**
 * Listener auth
 *
 * @param array $json array
 *
 * @return void
 */
function vbsso_listener_authentication($json) {
    if (vbsso_listener_user_load($json, TRUE)) {
        $_SERVER['REMOTE_USER'] = $json[SHAREDAPI_EVENT_FIELD_USERNAME];
        $secret = auth_cookiesalt(TRUE); //always sticky
        vbsso_auth_setCookie($json[SHAREDAPI_EVENT_FIELD_USERNAME], PMA_blowfish_encrypt('', $secret),
            $json[SHAREDAPI_EVENT_FIELD_REMEMBERME], $json[SHAREDAPI_EVENT_FIELD_TIMEOUT]);
    }
}

/**
 * Listener credentials
 *
 * @param array $json array
 *
 * @return array
 */
function vbsso_listener_credentials($json) {
    global $vbsso_settings;
    if ($u = vbsso_listener_user_load($json)) {
        $update = FALSE;
        $changes = array();

        if (isset($json[SHAREDAPI_EVENT_FIELD_EMAIL2])) {
            $changes['mail'] = $json[SHAREDAPI_EVENT_FIELD_EMAIL2];
            $update = TRUE;
        }

        if (isset($json[SHAREDAPI_EVENT_FIELD_USERNAME2])) {
            $changes['name'] = $json[SHAREDAPI_EVENT_FIELD_USERNAME2];
            $update = TRUE;
        }

        if (isset($json[SHAREDAPI_EVENT_FIELD_USERGROUPS2])) {
            $usergroups = array();
            $plugin_ugs = json_decode($vbsso_settings[VBSSO_NAMED_EVENT_FIELD_USERGROUPS_ASSOC]);

            foreach (explode(',', $json[SHAREDAPI_EVENT_FIELD_USERGROUPS2]) as $ug) {
                $usergroups[] = (isset($plugin_ugs->$ug)) ? $plugin_ugs->$ug : 'user';
            }
            $changes['grps'] = array_unique($usergroups);
            $update = TRUE;
        }

        if ($update) {
            $auth = (class_exists('auth_plugin_authplain')) ? new auth_plugin_authplain() : new auth_plain();
            $auth->modifyUser($json[SHAREDAPI_EVENT_FIELD_USERNAME], $changes);
        }

        return array(SHAREDAPI_EVENT_FIELD_DATA => 'User ' . $json[SHAREDAPI_EVENT_FIELD_USERNAME]
            . ' successfully modified');
    } else {
        return array(SHAREDAPI_EVENT_FIELD_ERROR => vbsso_listener_report_error('Unable to update user login: '
            . $json[SHAREDAPI_EVENT_FIELD_USERNAME]));
    }
}

/**
 * Generate password
 *
 * @return string
 */
function vbsso_generate_password() {
    $password = "";
    $possible = "1234567890abcdefghjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    for ($i = 0; $i < 20; $i++) {
        $password .= substr($possible, mt_rand(0, strlen($possible) - 1), 1);
    }

    return $password;
}

/**
 * Save platform settings
 *
 * @param mixed $settings settinhs
 *
 * @return void
 */
function vbsso_save_platform_settings($settings) {
    file_put_contents(VBSSO_PLATFORM_CONFIG_FILE, base64_encode(serialize($settings)));
}

/**
 * Get platform settings
 *
 * @return mixed
 */
function vbsso_get_platform_settings() {
    if (!file_exists(VBSSO_PLATFORM_CONFIG_FILE)) {
        file_put_contents(VBSSO_PLATFORM_CONFIG_FILE, '');
    }

    return unserialize(base64_decode(file_get_contents(VBSSO_PLATFORM_CONFIG_FILE)));
}

/**
 * Get vB user groups
 *
 * @return array|mixed
 */
function vbsso_get_vb_usergroups() {
    global $vbsso_platform_settings, $vbsso_settings;

    $baa_username = sharedapi_decode_data($vbsso_settings[VBSSO_NAMED_EVENT_FIELD_API_KEY],
        $vbsso_platform_settings[VBSSO_NAMED_EVENT_FIELD_BAA_USERNAME]);

    $baa_password = sharedapi_decode_data($vbsso_settings[VBSSO_NAMED_EVENT_FIELD_API_KEY],
        $vbsso_platform_settings[VBSSO_NAMED_EVENT_FIELD_BAA_PASSWORD]);

    $vbug = sharedapi_post($vbsso_platform_settings[VBSSO_NAMED_EVENT_FIELD_USERGROUPS_URL], FALSE, $baa_username,
        $baa_password);

    return ($vbug['error_string']) ? $vbug : json_decode($vbug['response']);
}

/**
 * Get alc groups
 *
 * @return array
 */
function vbsso_get_acl_groups() {
    $groups = array();
    foreach (auth_loadACL() as $a) {
        // Don't parse comments
        if (preg_match('/^#/', $a)) {
            continue;
        }
        if (preg_match('/^[^\s]+\s@([^\s]+)/', $a, $matches)) {
            $groups[urldecode($matches[1])] = $matches[1];
        }
    }

    return $groups;
}

/**
 * Set cookie
 *
 * @param object  $user            user
 * @param string  $pass            password
 * @param integer $sticky          glue
 * @param integer $session_timeout timeout
 *
 * @return bool
 */
function vbsso_auth_setCookie($user, $pass, $sticky, $session_timeout) {
    global $conf, $auth, $USERINFO;

    if (!$auth) {
        return FALSE;
    }
    $USERINFO = $auth->getUserData($user);

    // set cookie
    $cookie = base64_encode($user) . '|' . ((int)$sticky) . '|' . base64_encode($pass);
    $cookieDir = empty($conf['cookiedir']) ? DOKU_REL : $conf['cookiedir'];
    $time = $sticky ? (time() + 60 * 60 * 24 * 365) : (time() + $session_timeout); //one year
    if (version_compare(PHP_VERSION, '5.2.0', '>')) {
        setcookie(DOKU_COOKIE, $cookie, $time, $cookieDir, '', ($conf['securecookie'] && is_ssl()), TRUE);
    } else {
        setcookie(DOKU_COOKIE, $cookie, $time, $cookieDir, '', ($conf['securecookie'] && is_ssl()));
    }
    // set session
    $_SESSION[DOKU_COOKIE]['auth']['user'] = $user;
    $_SESSION[DOKU_COOKIE]['auth']['pass'] = sha1($pass);
    $_SESSION[DOKU_COOKIE]['auth']['buid'] = auth_browseruid();
    $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO;
    //If an administrator was registered NOT by vBSSO,
    //we don't know his pass, so he will logout every period, set in "auth_security_timeout".
    //We will just increase this parameter
    $_SESSION[DOKU_COOKIE]['auth']['time'] = time() + $time;

    return TRUE;
}

/**
 * Get Platform settings
 *
 * @return mixed
 */
function vbsso_get_dokuwiki_settings() {
    if (!file_exists(VBSSO_VBSSO_CONFIG_FILE)) {
        file_put_contents(VBSSO_VBSSO_CONFIG_FILE, '');
    }

    $settings = unserialize(base64_decode(file_get_contents(VBSSO_VBSSO_CONFIG_FILE)));

    if (!isset($settings[VBSSO_NAMED_EVENT_FIELD_LOGIN_THROUGH_VB_PAGE])) {
        $settings[VBSSO_NAMED_EVENT_FIELD_LOGIN_THROUGH_VB_PAGE] = TRUE;
    }

    if (!isset($settings[VBSSO_PLATFORM_FOOTER_LINK_PROPERTY])) {
        $settings[VBSSO_PLATFORM_FOOTER_LINK_PROPERTY] = VBSSO_PLATFORM_FOOTER_LINK_SHOW_EVERYWHERE;
    }
    if (!isset($settings[VBSSO_NAMED_EVENT_FIELD_API_KEY])) {
        $settings[VBSSO_NAMED_EVENT_FIELD_API_KEY] = SHAREDAPI_DEFAULT_API_KEY;
    }

    if (!isset($settings[VBSSO_NAMED_EVENT_FIELD_USERGROUPS_ASSOC])) {
        $settings[VBSSO_NAMED_EVENT_FIELD_USERGROUPS_ASSOC] = FALSE;
    }

    return $settings;
}

/**
 * Save platform settings
 *
 * @return void
 */
function vbsso_save_mediawiki_settings() {
    global $vbsso_settings, $vbsso_platform_settings;

    $settings = array();
    $settings[VBSSO_PLATFORM_FOOTER_LINK_PROPERTY] =
        (isset($_POST[VBSSO_PLATFORM_FOOTER_LINK_PROPERTY])) ? $_POST[VBSSO_PLATFORM_FOOTER_LINK_PROPERTY] : '1';
    $settings[VBSSO_NAMED_EVENT_FIELD_API_KEY] =
        (isset($_POST[VBSSO_NAMED_EVENT_FIELD_API_KEY]) && !empty($_POST[VBSSO_NAMED_EVENT_FIELD_API_KEY]))
            ? $_POST[VBSSO_NAMED_EVENT_FIELD_API_KEY] : SHAREDAPI_DEFAULT_API_KEY;
    $settings[VBSSO_NAMED_EVENT_FIELD_LOGIN_THROUGH_VB_PAGE] =
        (isset($_POST[VBSSO_NAMED_EVENT_FIELD_LOGIN_THROUGH_VB_PAGE]))
            ? $_POST[VBSSO_NAMED_EVENT_FIELD_LOGIN_THROUGH_VB_PAGE] : '0';

    if ($vbsso_platform_settings[VBSSO_NAMED_EVENT_FIELD_USERGROUPS_URL]) {
        $vb_usergroups = vbsso_get_vb_usergroups();
        $vbsso_usergroups_assoc = array();

        foreach ($vb_usergroups as $vb_usergroup) {
            $vbsso_usergroups_assoc[$vb_usergroup->usergroupid] =
                $_POST[VBSSO_NAMED_EVENT_FIELD_USERGROUPS_ASSOC . '_' . $vb_usergroup->usergroupid];
        }

        $settings[VBSSO_NAMED_EVENT_FIELD_USERGROUPS_ASSOC] = json_encode($vbsso_usergroups_assoc);
    }

    file_put_contents(VBSSO_VBSSO_CONFIG_FILE, base64_encode(serialize($settings)));
    $vbsso_settings = $settings;
}