<?php
/* =================================================================================
 * License: GPL-2.0 license
 * Author: 众产®  https://ciy.cn/code
 * Version: 0.6.7
====================================================================================*/
/*
 * 用户相关函数
 * verifyfast   校验用户自动响应
 * verifyuser   校验用户登录状态，超时用户自动续期
 * nopower      访问数据库判断用户是否有权限
 * filerecord   文件记录/短链
 * savelog              log信息记录到数据库log表
 * savelogdb            增删改数据变更记录到数据库log表
 * getcatas             从字典中读取 代码数组
 * get/set config       从SaaS配置表中读写配置项
 * get/set/del memvar   从SaaS内存表中读写变量
 */
$_token = array();
$_token['type'] = 'localstorage'; //cookie(更安全) 、 localstorage(兼容性好)   微信小程序不支持cookie
$_token['swapsec'] = 3600; //更换JWT时间
$_token['expsec'] = 86400; //过期退出时间
$_token['field'] = 'ciyap';
$_token['salt'] = 'ast34h$3'; //做数据加解密时的加密因子，每个项目都不要相同。
$_token['maindomain'] = 'https://ciyon.ciy.cn/ajax/ambap/'; //一般用于api回调

function verifyfast() {
    $rsuser = verifyuser();
    if ($rsuser == null)
        ciy_ouputJSON(errjson('请重新登录', 2));
    return $rsuser;
}
function verifyuser() {
    global $db;
    global $_token;
    if (isset($_COOKIE[$_token['field']]))
        $ciyauth = $_COOKIE[$_token['field']];
    else if (isset($_SERVER['HTTP_CIYAUTH']))
        $ciyauth = $_SERVER['HTTP_CIYAUTH'];
    else
        $ciyauth = get('_ciyauth');
    $auth = json_decode(encrypt($ciyauth, 'D', $_token['salt']), true);
    if ($auth == null)
        return null;
    $csql = new \ciy\sql('ap_user'); //弃用redis集群
    $csql->where('id', $auth['id']);
    $userrow = $db->getone($csql);
    if (!is_array($userrow))
        return null;
    if ($userrow['sid'] != $auth['_s'])
        return null;
    if ($userrow['stpstatus'] != 10)
        return null;
    if ($userrow['exptimes'] < time() - $_token['expsec'])
        return null;
    if ($userrow['exptimes'] > time())
        return $userrow;
    $exp = time() + $_token['swapsec'];
    $sid = randstr(10);
    $auth['_s'] = $sid;
    if ($db->execute('update ap_user set exptimes=?,sid=? where id=?', array($exp, $sid, $auth['id'])) === false)
        return null;
    $authstr = json_encode($auth, JSON_PARTIAL_OUTPUT_ON_ERROR);
    $enauth = encrypt($authstr, 'E', $_token['salt']);
    if ($_token['type'] == 'cookie') {
        $headercookie = 'Set-Cookie: ' . $_token['field'] . '=' . $enauth . '; expires=' . gmdate('D, d-M-Y H:i:s T', $exp + $_token['swapsec'] + $_token['expsec']) . '; path=/; SameSite=None; Secure; httponly';
        header($headercookie);
    } else {
        //header($_token['field'] . ': ' . $enauth);
        $_token['__ciyauth'] = $enauth;
    }
    //header($_token['field'] . ': ' . $enauth);
    return $userrow;
}
//true无权限，false有权限
function nopower($db, $userid, $chkpower) {
    $csql = new \ciy\sql('ap_user');
    $csql->where('id', $userid);
    $csql->column('power');
    $mepower = $db->get1($csql);
    if (empty($mepower))
        return true;
    if (strlen($chkpower) < 3)
        return true;
    if ($mepower == '.*.') //超级管理员
        return false;
    $pows = explode('.', $mepower);
    foreach ($pows as $p) {
        if (empty($p))
            continue;
        if (strpos($chkpower, $p) !== 0)
            continue;
        return false;
    }
    return true;
}

function savelog($db, $userid, $types, $msg, $isrequest = false, $time = 0) {
    if ($isrequest) {
        $msg .= ' GET:';
        foreach ($_GET as $key => $value)
            $msg .= $key . '=' . $value . '&';
        $msg .= ' POST:';
        foreach ($_POST as $key => $value)
            $msg .= $key . '=' . $value . '&';
        $msg .= ' SERVER:';
        foreach ($_SERVER as $key => $value)
            $msg .= "\n" . $key . '=' . $value;
        $msg .= ' JSON:' . file_get_contents('php://input');
    }
    $updata = array();
    $updata['types'] = $types;
    $updata['loguser'] = $userid;
    $updata['logs'] = $msg;
    $updata['readuser'] = 0;
    $updata['addtimes'] = $time == 0 ? tostamp() : $time;
    $updata['ip'] = getip();
    $csql = new \ciy\sql('ap_log');
    $db->insert($csql, $updata);
    return false;
}
function savelogdb($db, $userid, $types, $oldrow, $newrow) {
    savelog($db, $userid, $types, logdbstr($oldrow, $newrow), false);
}
function gettoken($db, $id) {
    $csql = new \ciy\sql('zc_token');
    $csql->where('id', $id);
    $tokenrow = $db->getone($csql);
    if (!is_array($tokenrow))
        return '获取数据库token失败:' . $id;
    $cfgtoken = str_replace('{PATH_ROOT}', PATH_ROOT, $tokenrow['cfgtoken']);
    $cfg = getstrparam($cfgtoken, "\n");
    $cfg['accesstoken'] = $tokenrow['accesstoken'];
    $cfg['exptimes'] = $tokenrow['exptimes'];
    return $cfg;
}
function settoken($db, $id, $access) {
    $csql = new \ciy\sql('zc_token');
    $csql->where('id', $id);
    if ($db->update($csql, $access) === false)
        return '操作数据库失败:' . $db->error;
    return true;
}
function getconfig($db, $types, $defvalue = '') {
    $csql = new \ciy\sql('zc_config');
    $csql->where('types', $types);
    $row = $db->getone($csql);
    if (is_array($row))
        return $row['params'];
    return $defvalue;
}
function setconfig($db, $types, $value) {
    $updata = array();
    $updata['types'] = $types;
    $updata['params'] = $value;
    $csql = new \ciy\sql('zc_config');
    $csql->where('types', $types);
    if ($db->update($csql, $updata) === false)
        return '操作数据库失败:' . $db->error;
    return true;
}
function getcatas($db, $cbid) {
    if (is_numeric($cbid)) {
        $cbid = toint($cbid);
    } else {
        $csql = new \ciy\sql('zc_cata');
        $csql->where('codeid', $cbid);
        $csql->where('cbid=0');
        $csql->column('id');
        $cbid = toint($db->get1($csql));
        if ($cbid == 0)
            return array();
    }
    $csql = new \ciy\sql('zc_cata');
    $csql->where('cbid', $cbid)->order('csort,id');
    $csql->column('codeid as id,name,upid,name,extdata');
    $catarows = $db->get($csql);
    return $catarows;
}
function getmemvar($db, $types, $defvalue = '') {
    $csql = new \ciy\sql('zc_zmem_var');
    $csql->where('types', $types);
    $row = $db->getone($csql);
    if (is_array($row))
        return $row['params'];
    return $defvalue;
}
function setmemvar($db, $types, $value) {
    if (!$db)
        return false;
    $updata = array();
    $updata['types'] = $types;
    $updata['params'] = $value;
    $csql = new \ciy\sql('zc_zmem_var');
    $csql->where('types', $types);
    $row = $db->getone($csql);
    if (is_array($row)) {
        $csql = new \ciy\sql('zc_zmem_var');
        $csql->where('id', $row['id']);
        if ($db->update($csql, $updata) === false)
            return '操作数据库失败:' . $db->error;
    } else {
        if (is_array($value)) {
            $ind = strpos($value[0], '+');
            if ($ind === false) {
                $updata['params'] = 1;
            } else {
                $updata['params'] = (int)substr($value[0], $ind + 1);
            }
        }
        if ($db->insert($csql, $updata) === false)
            return '操作数据库失败:' . $db->error;
    }
    return true;
}
function delmemvar($db, $types) {
    $csql = new \ciy\sql('zc_zmem_var');
    $csql->where('types', $types);
    $db->delete($csql);
}
function ciy_api($enter, $param) {
    $cfg = webini('ciyapi');
    if (is_string($cfg))
        return errjson($cfg);
    $time = time();
    $payload = json_encode($param);
    $sign = hash_hmac("SHA256", $cfg['appid'] . $time . $payload, $cfg['apikey']);
    $http = new \ciy\http();
    $http->set_headeronce('ciy-apiid', $cfg['appid']);
    $http->set_headeronce('ciy-stamp', $time);
    $http->set_headeronce('ciy-sign', $sign);
    $http->request('https://tob.ciy.cn/api/?' . $enter, $payload);
    $datastr = $http->get_data();
    $data = json_decode($datastr, true);
    if ($data === null)
        return 'API返回错误:' . $datastr;
    if (isset($data['errmsg']))
        return $data['errmsg'];
    return true;
}
