c5_labsci/zciyphp/comm.php
2026-01-27 00:52:00 +08:00

1184 lines
39 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/* =================================================================================
* License: GPL-2.0 license
* Author: 众产® https://ciy.cn/code
* Version: 0.7.9
====================================================================================*/
/*
* common.php 常用公共函数库
*
* 功能函数相关
* clog/var_dump PHP调试变量界面打印
* fixmonth/todate 日期月份增减函数/数字时间转字符串
* locinzone 当前经纬度是否在围栏中
* timems 获取当前微秒数
* totimepoint 数字时钟转字符串
* ismobile 判断手机号是否合法
* isweixin 判断客户端是否在微信中
* idcard 判断身份证号合法
* iduscc 判断统一社会信用代码合法
* locdistance 计算两经纬度之间的距离(毫米METRE)
*
* 加解密相关
* encrypt 字符串加解密
* enid/deid ID数字加解密
* conv33_10/conv10_33 数字转33进制
*
* 字符串/数组相关
* arrayrand 随机抽取数组元素并删除
* startwith/endwith 首字符/尾字符匹配
* strpos_first 字符数组优先匹配,一般匹配 ' "
* gb_substr/gb_strlen/gb_haschinese 中文字符串处理函数
* getstrparam/setstrparam 比json还简化的数据保存方式一般用于数据字典保存。例: name=AAA|age=12|cc=CCTT
*
* 数据库相关
* fieldadd 手动增加列表显示字段,并返回排序字段字符串
* getrelation 获取表内关联数据用于大数据量表的所属ID转文字
* tran_delcheck/tran_delall/me 事务删除前确认/删除相关数据
*
* 字典相关
* id2map 将 id/name代码数组对 转换为 键值对
* ccode 代码数组中,通过代码值找代码名
* mcode 代码数组中,通过代码值找代码名,多级
* scode 代码数组中,查找多个代码值,返回数组
* dcode 代码数组中,通过代码名找代码值
*
* LOG相关
* savelogfile 保存log信息写入到本地文件
* logdbstr 将数据变化格式化成字符串
*
* 输入输出相关
* \ciy\post{} payload json参数处理类 is/get/getint/getfloat/getdate/getbool/getraw/safehtml
* getstr/getint/post/request/cookie 获取用户输入数据(不能信任任何用户输入包括cookie)
* getip IP的快捷函数支持数字和字符串返回
*
* 文件相关
* dirmake/filedel/copy/save/load 创建多层新文件夹/文件静默删除/拷贝/保存/读取
* file_down URL文件下载保存
* fileext 获取文件扩展名如jpg
*/
if (substr(__DIR__, 0, 1) == '/')
error_reporting(0); //0禁用错误输出E_ALL打开错误输出
else
error_reporting(E_ALL); //0禁用错误输出E_ALL打开错误输出
date_default_timezone_set('Asia/Shanghai');
if (!isset($path))
$path = $_SERVER['DOCUMENT_ROOT'];
defined('PATH_ROOT') || define('PATH_ROOT', substr($path, 0, strrpos($path, '/') + 1)); //web根目录。
defined('PATH_WEB') || define('PATH_WEB', PATH_ROOT . 'web/'); //web根目录。
defined('NAME_SELF') || define('NAME_SELF', substr($_SERVER['PHP_SELF'], strrpos($_SERVER['PHP_SELF'], '/') + 1, -4));
defined('MAXTIMES') || define('MAXTIMES', 9999999999999);
$logpath = PATH_ROOT . 'log/';
spl_autoload_register(function ($class) {
if (substr($class, 0, 4) == 'ciy\\') //将zciyphp简写成ciyz开头的目录通常排在最下不过影响找业务目录。
$class = 'zciyphp\\' . substr($class, 4);
$file = PATH_ROOT . $class . '.php';
$file = str_replace('\\', '/', $file);
if (is_file($file)) {
require_once $file;
return;
}
});
class emptyclass {
}
function clog() {
echo "\n" . '<pre>';
$first = true;
foreach (func_get_args() as $var) {
if (is_null($var))
echo 'null';
else if (is_long($var))
echo 'long:' . $var;
else if (is_integer($var))
echo 'int:' . $var;
else if (is_string($var)) {
if (strlen($var) == 0)
echo 'str:---空字符串----';
else {
if ($first && func_num_args() > 1)
echo '<kbd>' . $var . '</kbd>';
else
echo 'str:' . $var;
}
} else if (is_bool($var))
echo 'bool:' . ($var ? 'true' : 'false');
else {
echo 'Type:' . gettype($var) . "\n";
print_r($var);
}
$first = false;
echo "\n";
}
echo '</pre>' . "\n";
@ob_flush();
flush();
}
function fixmonth($num, $dt) { //php +n months 修复在28号之后产生的错误
$day = date('d', $dt);
if ($day < 29)
return strtotime(($num > 0 ? '+' : '-') . $num . ' month', $dt);
$lastday = date('d', strtotime('last day of this month', $dt));
$nextdt = strtotime(($num > 0 ? '+' : '-') . $num . ' month', strtotime(date('Y-m-1', $dt)));
$nextlastday = date('d', strtotime('last day of this month', $nextdt));
if ($day <= $nextlastday)
return strtotime(date('Y-m-', $nextdt) . $day);
return strtotime(date('Y-m-', $nextdt) . ($nextlastday - $lastday + $day));
}
function tostr($str = '') {
if (!$str)
return '';
return $str . '';
}
function toint($str = 0) {
if (!$str)
return 0;
if (!is_numeric($str))
return 0;
return intval(round($str));
}
function todate($time, $format = 'i') {
if ($time == 0)
return '--';
if ($format == 'H')
return date('Y-m-d H', $time);
if ($format == 'd')
return date('Y-m-d', $time);
if ($format == 'hi')
return date('H:i', $time);
if ($format == 'm')
return date('Y-m', $time);
if ($format == 's')
return date('Y-m-d H:i:s', $time);
return date('Y-m-d H:i', $time);
}
function totimepoint($time, $bsecond = false) {
$time = toint($time);
if ($time <= 0 || $time > 86400)
return '';
$time--;
$hour = toint($time / 3600);
$minute = toint((($time - $hour * 3600) / 60));
$ret = str_pad($hour, 2, '0', STR_PAD_LEFT) . ':' . str_pad($minute, 2, '0', STR_PAD_LEFT);
if ($bsecond)
return $ret;
$second = toint($time - $hour * 3600 - $minute * 60);
return $ret . ':' . str_pad($second, 2, '0', STR_PAD_LEFT);
}
function tounit($val) {
$us = explode('|', $val);
$vals = array();
if (count($us) == 5)
$vals[] = '1' . $us[4] . $us[3] . $us[2];
if (count($us) > 2)
$vals[] = '1' . $us[2] . $us[1] . $us[0];
if (count($vals) == 0 && !empty($us[0]))
$vals[] = $us[0];
return $vals;
}
function tocyc($val) {
if ($val < 0)
return -$val . '月';
else if ($val >= 86400)
return toint($val / 86400) . '天';
else
return $val . '秒';
}
function tostamp($str = 'now') {
if ($str == 'now')
return time();
$time = strtotime($str);
if ($time === false)
return 0;
return $time;
}
function locinzone($paths, $zlat, $zlng) {
//30.434272 120.274938,30.433977 120.277270,30.432403 120.277957,30.431764 120.276340,30.432270 120.273358,30.433997 120.273283
$fences = explode(',', $paths);
$nvert = count($fences);
$vertx = [];
$verty = [];
foreach ($fences as $r) {
list($lat, $lng) = explode(' ', $r);
$vertx[] = $lat;
$verty[] = $lng;
}
$i = $j = 0;
$c = false;
for ($i = 0, $j = $nvert - 1; $i < $nvert; $j = $i++) {
if ((($verty[$i] > $zlng) != ($verty[$j] > $zlng)) &&
($zlat < ($vertx[$j] - $vertx[$i]) * ($zlng - $verty[$i]) / ($verty[$j] - $verty[$i]) + $vertx[$i])
)
$c = !$c;
}
return $c;
}
function timems() {
$microtime = microtime();
$comps = explode(' ', $microtime);
return toint(sprintf('%d%03d', $comps[1], $comps[0] * 1000));
}
function ismobile($mob) {
return preg_match('/^1\d{10}$/', $mob);
}
function ismail($str) {
return filter_var($str, FILTER_VALIDATE_EMAIL);
}
function isweixin() {
$useragent = strtolower($_SERVER["HTTP_USER_AGENT"]);
$is_weixin = strripos($useragent, 'micromessenger');
if ($is_weixin > 0)
return true;
return false;
}
function getcciycheck($num) {
$checksum = 0;
for ($i = 15; $i > 0; $i--) {
$nibble = ($num >> (4 * $i)) & 0xF;
$checksum ^= $nibble;
}
return $checksum;
}
function iscciy($num) {
return getcciycheck($num) == ($num & 0xf);
}
function idcard($str) {
$str = strtoupper(trim($str));
if (empty($str))
return '身份证未输入';
if (strlen($str) != 18)
return '身份证长度错误';
$province = ['11', '12', '13', '14', '15', '21', '22', '23', '31', '32', '33', '34', '35', '36', '37', '41', '42', '43', '44', '45', '46', '50', '51', '52', '53', '54', '61', '62', '63', '64', '65', '71', '81', '82', '91'];
if (!in_array(substr($str, 0, 2), $province))
return '身份证地区不合法';
$birth_year = substr($str, 6, 4);
$birth_month = substr($str, 10, 2);
$birth_day = substr($str, 12, 2);
$birth = strtotime($birth_year . '-' . $birth_month . '-' . $birth_day);
if ($birth === false)
return '身份证生日错误';
if ($birth > time())
return '身份证生日不能超过今天';
$ahead17_char = substr($str, 0, 17);
$last_char = substr($str, -1);
$factor = array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
$c = array(1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2);
$t_res = 0;
for ($i = 0; $i < 17; $i++) {
$t_res += intval($ahead17_char[$i]) * $factor[$i];
}
$calc_last_char = $c[$t_res % 11];
if (strtolower($last_char) != strtolower($calc_last_char))
return '身份证校验位错误'; // . $calc_last_char;
$sex = substr($str, -2, 1);
if ($sex % 2 == 0)
$sex = 2;
else
$sex = 1;
//$age = toint(date('Y')) - toint($birth_year);
return ['code' => $str, 'birth' => $birth_year . '-' . $birth_month . '-' . $birth_day, 'sex' => $sex, 'area' => substr($str, 0, 6)];
}
function iduscc($uscc) {
$uscc = strtoupper(trim($uscc));
if (empty($uscc))
return '统一社会信用代码未输入';
if (strlen($uscc) != 18)
return '统一社会信用代码不是18位';
$province = ['11', '12', '13', '14', '15', '21', '22', '23', '31', '32', '33', '34', '35', '36', '37', '41', '42', '43', '44', '45', '46', '50', '51', '52', '53', '54', '61', '62', '63', '64', '65', '71', '81', '82', '91'];
if (!in_array(substr($uscc, 2, 2), $province))
return '统一社会信用代码地区不合法';
$lcrc = _tsucc(substr($uscc, 0, 17));
if (substr($uscc, -1, 1) != $lcrc)
return '统一社会信用代码校验位错误';
return ['code' => $uscc, 'area' => substr($uscc, 2, 6), 'pn' => substr($uscc, 0, 2)];
}
function _tsucc($usc) {
$list = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'A' => 10, 'B' => 11, 'C' => 12, 'D' => 13, 'E' => 14, 'F' => 15, 'G' => 16, 'H' => 17, 'J' => 18, 'K' => 19, 'L' => 20, 'M' => 21, 'N' => 22, 'P' => 23, 'Q' => 24, 'R' => 25, 'T' => 26, 'U' => 27, 'W' => 28, 'X' => 29, 'Y' => 30);
$listf = array_flip($list);
$wi = array(1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28);
$num = 0;
for ($i = 0; $i < 17; $i++) {
$num += $list[$usc[$i]] * $wi[$i];
}
switch ($num % 31) {
case '0':
$result = 0;
break;
default:
$result = 31 - $num % 31;
break;
}
return $listf[$result];
}
function locdistance($lat1, $lng1, $lat2, $lng2) {
$earthRadius = 6367000;
$lat1 = ($lat1 * pi()) / 180;
$lng1 = ($lng1 * pi()) / 180;
$lat2 = ($lat2 * pi()) / 180;
$lng2 = ($lng2 * pi()) / 180;
$calcLongitude = $lng2 - $lng1;
$calcLatitude = $lat2 - $lat1;
$stepOne = pow(sin($calcLatitude / 2), 2) + cos($lat1) * cos($lat2) * pow(sin($calcLongitude / 2), 2);
$stepTwo = 2 * asin(min(1, sqrt($stepOne)));
$Distance = $earthRadius * $stepTwo;
return $Distance * 1000;
}
function str2bin($str) {
$bytes = [];
for ($i = 0; $i < strlen($str); $i++) {
$bytes[] = ord($str[$i]);
}
return $bytes;
}
function ciysign($str, $key) {
$sign = hash_hmac('sha256', $str, $key, false);
$sign = substr($sign, 0, 16);
$sign = str_replace($sign, 'd', 'p');
$sign = str_replace($sign, 'e', 'z');
$sign = str_replace($sign, 'f', 'm');
return $sign;
}
/* * *******************************************************************
* 函数名称:encrypt
* 函数作用:加密解密字符串
* 安全函数,建议有能力自行修改一些
* 使用方法:
* 加密 :encrypt('str','E','nowamagic');
* 解密 :encrypt('被加密过的字符串','D','nowamagic');
* 参数说明:
* $string :需要加密解密的字符串
* $operation:判断是加密还是解密:E:加密 D:解密
* $key :加密的钥匙(密匙);
* ******************************************************************* */
function encrypt($string, $operation, $key = '') {
$key = md5($key, true);
$key_length = strlen($key);
if ($operation == 'D')
$string = base64_decode(substr(str_replace('_', '/', str_replace('-', '+', str_replace('*', '=', $string))), 1));
else {
$string = substr(md5($string . $key, true), 0, 8) . $string;
}
$string_length = strlen($string);
$rndkey = $box = array();
$result = '';
for ($i = 0; $i < 256; $i++) {
$rndkey[$i] = ord($key[$i % $key_length]);
$box[$i] = $i;
}
for ($j = $i = 0; $i < 256; $i++) {
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for ($a = $j = $i = 0; $i < $string_length; $i++) {
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
if ($operation == 'D') {
if (substr($result, 0, 8) == substr(md5(substr($result, 8) . $key, true), 0, 8)) {
return substr($result, 8);
} else {
return '';
}
} else {
return '1' . str_replace('/', '_', str_replace('+', '-', str_replace('=', '*', base64_encode($result))));
}
}
/* * *******************************************************************
* 函数名称:enid/deid
* 函数作用:id加密函数/id解密函数。
* 安全函数,建议有能力自行修改一些
* 参数说明:
* $id 两位数的数字idid>=10
* 返回值:加密后的数字
* 例enid(8245) = 872435
* 例deid(872435) = 8245
* ******************************************************************* */
function enid($id, $key = 253) {
$id = toint($id);
if ($id <= 0)
return 0;
if ($id < 10)
$strid = '0' . $id;
else
$strid = $id . '';
$fx = _calnumber($id, $key);
$ulen = strlen($strid);
return substr($strid, 0, 1) . $fx[0] . substr($strid, 1, $ulen - 2) . $fx[1] . substr($strid, -1, 1);
}
function deid($id, $key = 253) {
$strid = $id . '';
$ulen = strlen($strid);
$fx = substr($strid, 1, 1) . substr($strid, -2, 1);
$id = toint(substr($strid, 0, 1) . substr($strid, 2, $ulen - 4) . substr($strid, -1, 1));
if ($fx == _calnumber($id, $key))
return $id;
return 0;
}
/* * *******************************************************************
* 函数名称:calnumber
* 函数作用:换算id的加密校验数被enid、deid函数调用。
* 参数说明:
* $key 默认加密因子可以自行修改。尽量用奇数100-1000
* $len 返回校验数位数。
* 返回值len位数字字符串
* 例calnumber(8245,224,2) = 73
* ******************************************************************* */
function _calnumber($num, $key, $len = 2) {
if ($num > 250600)
$num %= 250600;
$n = $num % 8566;
if ($n < 100)
$n += 100;
$xx = abs($num * $n + $key);
if ($xx % 13 > 8)
$xx += $key;
if ($xx % 13 > 4)
$xx += $key + $key + $key;
if ($len < 1)
$len = 2;
$ret = abs($xx % pow(10, $len));
return sprintf('%0' . $len . 'd', $ret);
}
function sha256($str) {
return hash('sha256', $str);
}
function sha512($str) {
return hash('sha512', $str);
}
function conv33_10($num) {
$from = 33;
$dict = 'abcdefghijkmnpqrstuvwxyz123456789';
$len = strlen($num);
$dec = 0;
for ($i = 0; $i < $len; $i++) {
$pos = strpos($dict, $num[$i]);
$dec = bcadd(bcmul(bcpow($from, $len - $i - 1), $pos), $dec);
}
return $dec;
}
function conv10_33($num) {
$to = 33;
$dict = 'abcdefghijkmnpqrstuvwxyz123456789';
$ret = '';
do {
$ret = $dict[bcmod($num, $to)] . $ret;
$num = bcdiv($num, $to);
} while ($num > 0);
return $ret;
}
function arrayrand($arr, $num = 1) {
$retarr = array();
if (count($arr) < $num)
$num = count($arr);
for ($i = 0; $i < $num; $i++) {
$ind = array_rand($arr);
$retarr[] = array_splice($arr, $ind, 1)[0];
}
return $retarr;
}
function startwith($str, $suffix) {
return strpos($str, $suffix) === 0;
}
function endwith($str, $suffix) {
return substr($str, -strlen($suffix)) === $suffix;
}
function strpos_first($search, $findstrs, $offset = 0) { //返回第一个char位置第一个char内部位置
if (strlen($search) < $offset)
return [-1, '', ''];
if (is_string($findstrs))
$findstrs = array($findstrs);
$f_str = '';
$f_ind = 2147483647;
foreach ($findstrs as $findstr) {
$ind = strpos($search, $findstr, $offset);
if ($ind === false)
continue;
if ($ind < $f_ind) {
$f_str = $findstr;
$f_ind = $ind;
}
}
if ($f_ind == 2147483647)
return [-1, '', ''];
$ind2 = strpos($search, $f_str, $f_ind + 1);
if ($ind2 > 0)
return [$f_ind, $f_str, substr($search, $f_ind + 1, $ind2 - $f_ind - 1)];
return [$f_ind, $f_str, ''];
}
/**
* 类似substr主要用于显示字符限制。支持中文2个半角算一个字符占位。超过部分用$dot代替。
* 建议能用css实现超出汉字隐藏尽量不要用此函数。
* 例gb_substr('CHN中华人民共和国',10)='CHN中华...' gb_substr('CHN中华人民共和国',9)='CHN中华...'
*/
function gb_substr($str, $len, $dot = '...') {
$i = 0;
$l = 0;
$c = 0;
$a = array();
while ($l < $len) {
$t = substr($str, $i, 1);
if (ord($t) >= 224) {
$c = 3;
$t = substr($str, $i, $c);
$l += 2;
} elseif (ord($t) >= 192) {
$c = 2;
$t = substr($str, $i, $c);
$l += 2;
} else {
$c = 1;
$l++;
}
$i += $c;
if ($l > $len)
break;
$a[] = $t;
}
$re = implode('', $a);
if (substr($str, $i, 1) !== false) {
array_pop($a);
($c == 1) and array_pop($a);
$re = implode('', $a);
$re .= $dot;
}
return $re;
}
function dbstr($str, $len) {
if (mb_strlen($str, 'UTF-8') > $len)
return mb_substr($str, 0, $len, 'UTF-8');
return $str;
}
/**
* 类似strlen英文算1个中文算2个字符。
* 例gb_strlen('CHN中华人民共和国')=17
*/
function gb_strlen($str) {
return (strlen($str) + mb_strlen($str, 'UTF8')) / 2;
}
function gb_haschinese($str) {
return preg_match("/([\x81-\xfe][\x40-\xfe])/", $str);
}
/**
* 比json还简化的多数据保存方式。该方式有一定的限制请熟悉后使用。
* 例getstrparam('Skey=10392|Pid=33|Memo=其他备注文字') = Array([Skey] => 10392[Pid] => 33[Memo] => 其他备注文字);
* $sparam = getstrparam('Skey=10392|Pid=33|Memo=其他备注文字');
* $val = @$sparam['Memo'];
* $sparam['Memo'] = 'xxx';
* $retval = setstrparam($sparam); 值: 'Skey=10392|Pid=33|Memo=xxx'
*/
function getstrparam($pstr, $split = '|') {
$strs = explode($split, $pstr);
$data = array();
foreach ($strs as $str) {
$ind = strpos($str, '=');
if ($ind !== false)
$data[substr($str, 0, $ind)] = trim(substr($str, $ind + 1));
}
return $data;
}
function setstrparam($parr, $split = '|') {
$pstr = '';
foreach ($parr as $p => $a)
$pstr .= $p . '=' . $a . $split;
return trim($pstr, $split);
}
function split($sp, $str) {
return explode($sp, trim($str, $sp));
}
function fieldadd($fshow, &$field, $pos, $key, $val) {
$field[$key] = array('c' => $val);
$fshows = explode(',', $fshow);
if ($pos == -1) {
if (empty($fshows[0]))
$fshows[0] = $key;
else
$fshows[] = $key;
} else if ($pos == 0)
array_unshift($fshows, $key);
else
array_splice($fshows, $pos, 0, $key);
return implode(',', $fshows);
}
function getrelation($cdb, $rows, $table, $fieldstr, $column = 'id,name', $queryid = 'id') {
$ids = array();
$fields = explode(',', $fieldstr);
foreach ($fields as $field) {
foreach ($rows as $row) {
if (isset($row[$field]) && !in_array($row[$field], $ids))
$ids[] = $row[$field];
}
}
if (count($ids) == 0)
return array();
$csql = new \ciy\sql($table);
$csql->where($queryid . ' in ', implode(',', $ids));
$csql->column($column);
return $cdb->get($csql);
}
function delcheck($db, $delid, $table, $field, $msg = '', $where = '') {
$csql = new \ciy\sql($table);
if (!empty($where))
$csql->where($where);
$csql->where($field, $delid);
$cnt = $db->get1($csql);
if ($cnt > 0)
throw new \Exception('CIYIGN存在' . $cnt . '个' . $msg . ',不能删除');
}
function delall($db, $delid, $table, $field, $msg = '') {
$csql = new \ciy\sql($table);
$csql->where($field, $delid);
if ($db->delete($csql) === false)
throw new \Exception($msg . '删除失败:' . $db->error);
}
function delme($db, $delid, $table) {
$csql = new \ciy\sql($table);
$csql->where('id', $delid);
if ($db->delete($csql) === false)
throw new \Exception('删除失败:' . $db->error);
}
function deltimeall($db, $delid, $table, $field, $msg = '') {
if ($db->execute('update ' . $table . ' set deltimes=' . time() . ' where ' . $field . '=' . $delid) === false)
throw new \Exception($msg . '标记删除失败:' . $db->error);
}
function deltimeme($db, $delid, $table) {
if ($db->execute('update ' . $table . ' set deltimes=' . time() . ' where id=' . $delid) === false)
throw new \Exception('标记删除失败:' . $db->error);
}
function mapid2data($datas) {
$ret = array();
foreach ($datas as $data) {
$ret[$data['id']] = $data;
}
return $ret;
}
function mapid2any($datas) {
$ret = array();
foreach ($datas as $data) {
$ret[$data['id']] = $data;
}
return $ret;
}
function ccode($rows, $code, $showcode = 'id', $showtitle = 'name') {
foreach ($rows as $row) {
if ($code == $row[$showcode]) {
if (empty($showtitle))
return $row;
return $row[$showtitle];
}
}
if (empty($showtitle))
return null;
return '--';
}
function mcode($rows, $code, $showcode = 'id', $showtitle = 'name', $upcode = 'upid') {
$codes = array();
for ($i = 0; $i < 10; $i++) {
if ($code <= 0)
break;
$bfind = false;
foreach ($rows as $row) {
if ($code == $row[$showcode]) {
if (empty($showtitle))
array_unshift($codes, $row);
else
array_unshift($codes, $row[$showtitle]);
$code = toint(@$row[$upcode]);
$bfind = true;
break;
}
}
if (!$bfind)
break;
}
return $codes;
}
function scode($rows, $code, $showcode = 'id', $showtitle = 'name') {
$rets = array();
$codes = explode(',', $code);
foreach ($codes as $c) {
if (empty($c))
continue;
foreach ($rows as $row) {
if ($c == $row[$showcode]) {
if (empty($showtitle))
$rets[] = $row;
else
$rets[] = $row[$showtitle];
}
}
}
return $rets;
}
function bcode($rows, $val) {
$rets = array();
$val = toint($val);
foreach ($rows as $cod) {
if (($val & (1 << (toint($cod['id']) - 1))) != 0)
$rets[] = $cod['name'];
}
return $rets;
}
function dcode($rows, $codename, $showcode = 'id', $showtitle = 'name') {
foreach ($rows as $row) {
if ($codename == $row[$showtitle]) {
if (empty($showcode))
return $row;
return $row[$showcode];
}
}
return -1;
}
function logdbstr($oldrow, $newrow) {
$msg = '';
if (is_array($oldrow) && is_array($newrow)) {
$msg .= 'Upd=' . @$oldrow['id'];
$modify = false;
foreach ($newrow as $f => $v) {
if (!isset($oldrow[$f]))
continue;
if ($oldrow[$f] != $v) {
$msg .= '_|@|_' . $f . '=' . $oldrow[$f] . '→' . $v;
$modify = true;
}
}
if (!$modify)
return "";
} else if (is_array($newrow)) {
$msg .= 'Ins=' . @$newrow['id'];
foreach ($newrow as $f => $v) {
if ($f == 'id')
continue;
$msg .= '_|@|_' . $f . '=' . $v;
}
} else if (is_array($oldrow)) {
$msg .= 'Del=' . @$oldrow['id'];
foreach ($oldrow as $f => $v) {
if ($f == 'id')
continue;
$msg .= '_|@|_' . $f . '=' . $v;
}
} else {
return "";
}
return $msg;
}
function savelogfile($types, $msg, $isrequest = false) {
global $logpath;
if (substr($msg, 0, 6) == 'CIYIGN')
return true;
$filename = $logpath . $types . '.log';
$dir = dirname($filename);
dirmake($dir);
$fp = fopen($filename, 'a');
if (!$fp)
return false;
if ($isrequest) {
$msg .= ' GET:';
foreach ($_GET as $key => $value)
$msg .= $key . '=' . $value . '&';
$msg .= ' POST:' . file_get_contents('php://input');
}
$msg .= "\r\n";
if (@fwrite($fp, date('Y-m-d H:i:s') . "\t" . $msg)) {
fclose($fp);
return true;
}
fclose($fp);
return false;
}
/**
* JSON函数调用组件用于界面Ajax请求在本页处理。
* isform 用于页面form提交刷新的直接请求。非ajax请求。为兼容传统更新方式不建议使用
* ?func=函数名
* 将调用json_函数名(){}
* 函数返回array数组。
*/
function _setmemvar($db, $types, $value) {
// if (function_exists('setmemvar'))
// return setmemvar($db, $types, $value);
return false;
}
function ciy_ouputJSON($retarr, $ms = 0, $uri = '') {
global $db;
global $_token;
if ($db) {
if ($ms > 0) {
_setmemvar($db, 'func_runms', array('params+' . $ms));
if ($ms > 500 && !empty($uri)) {
$updata = array();
$updata['uri'] = $uri;
$updata['posts'] = file_get_contents('php://input');
$updata['ms'] = $ms;
$updata['addtimes'] = tostamp();
$csql = new \ciy\sql('zc_funcslow');
$db->insert($csql, $updata);
}
}
if (isset($retarr['code']) && $retarr['code'] == 1)
_setmemvar($db, 'func_succ', array('params+1'));
else
_setmemvar($db, 'func_fail', array('params+1'));
}
if (isset($_token['__ciyauth']))
$retarr['_ciyauth'] = $_token['__ciyauth'];
$jsonstr = json_encode($retarr, JSON_PARTIAL_OUTPUT_ON_ERROR | JSON_UNESCAPED_UNICODE);
if ($jsonstr === false) {
$retarr['errmsg'] = mb_convert_encoding($retarr['errmsg'], 'UTF-8', 'ISO-8859-1');
$jsonstr = json_encode($retarr);
if ($jsonstr === false) {
$retarr['errmsg'] = json_last_error_msg();
$jsonstr = json_encode($retarr);
}
}
if (isset($_GET['jsonp'])) {
$callback = $_GET['jsonp'];
if (strlen($callback) < 128 && preg_match('/^[A-Za-z_][A-Za-z0-9_]*$/', $callback)) {
header('Content-Type: application/javascript; charset=utf-8');
die($callback . '(' . $jsonstr . ')');
}
}
header('Content-Type: application/json; charset=utf-8');
die($jsonstr);
}
//code=2 未登录3 未授权9 函数未加载
function errjson($error, $errcode = 0, $ext = null) {
if (is_array($ext))
$ret = $ext;
else
$ret = array();
if ($errcode == 1)
$errcode = -1;
$ret['code'] = $errcode;
if (substr($error, 0, 6) == 'CIYIGN')
$error = substr($error, 6);
$ret['errmsg'] = $error;
return $ret;
}
function succjson($ext = null) {
if (is_array($ext))
$ret = $ext;
else
$ret = array();
$ret['code'] = 1;
return $ret;
}
function memadd($key) {
}
function randstr($num, $letter = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890') {
$b = [];
for ($i = 0; $i < $num; $i++) {
$b[] = $letter[rand(0, strlen($letter) - 1)];
}
return implode('', $b);
}
function objstr($obj, $name, $defvalue = '', $allow = 'text') { //text:仅文本all:都可以
if (!isset($obj[$name]))
return $defvalue;
$val = $obj[$name];
if (empty($val))
return $defvalue;
if ($allow == 'text')
return strip_tags($val);
return $val;
}
function objint($obj, $name, $defvalue = 0) {
if (!isset($obj[$name]) || $obj[$name] === '')
return $defvalue;
return toint($obj[$name]);
}
function objfloat($obj, $name, $defvalue = 0.0) {
if (!isset($obj[$name]))
return $defvalue;
return (float)$obj[$name];
}
function objdate($obj, $name, $defvalue = 0) {
if (!isset($obj[$name]))
return $defvalue;
$val = $obj[$name];
if (strpos($val, '-') !== false)
return strtotime($val);
return toint($val);
}
function get($name, $defvalue = '', $allow = 'text') { //text:仅文本all:都可以
if (!isset($_GET[$name]))
return $defvalue;
$val = $_GET[$name];
if ($allow == 'text')
return strip_tags($val . '');
return $val;
}
function getint($name, $defvalue = 0) {
if (!isset($_GET[$name]))
return $defvalue;
return toint($_GET[$name]);
}
function post($name, $defvalue = '', $allow = 'text') { //text:仅文本all:都可以
if (!isset($_POST[$name]))
return $defvalue;
$val = $_POST[$name];
if ($allow == 'text')
return strip_tags($val);
return $val;
}
function request($name, $defvalue = '', $allow = 'text') { //text:仅文本all:都可以
if (!isset($_REQUEST[$name]))
return $defvalue;
$val = $_REQUEST[$name];
if ($allow == 'text')
return strip_tags($val);
return $val;
}
function cookie($name, $defvalue = '', $allow = 'text') { //text:仅文本all:都可以
if (!isset($_COOKIE[$name]))
return $defvalue;
$val = $_COOKIE[$name];
if ($allow == 'text')
return strip_tags($val);
return $val;
}
/**
* 返回32位int真实IP地址。显示时请用long2ip()函数。
* $real = true 时返回字符串ip地址。
* 数据库ip字段建议设置int有符号类型建议varchar(15)兼容IPv6 varchar(40)
* 例getip() = 1343193298 getip(true) = '80.15.128.210'
* 例getip() = -765170305 getip(true) = '210.100.109.127'
* 提示真实IP地址访问方法有很多种有些用户会用header伪造真实IP。请根据您的实际服务器集群部署调整本函数。特别是CDN和反向代理部分。
*/
function getip() {
$headers = [
'HTTP_CF_CONNECTING_IP',
'HTTP_TRUE_CLIENT_IP',
'HTTP_X_FORWARDED_FOR',
'HTTP_FORWARDED',
'HTTP_X_REAL_IP',
'HTTP_FORWARDED_FOR',
'HTTP_X_FORWARDED',
];
$ips = array();
foreach ($headers as $header) {
if (!empty($_SERVER[$header]))
$ips[] = strtolower($_SERVER[$header]);
}
foreach ($ips as $ip) {
$ind = strpos($ip, ',');
if ($ind !== false)
$ip = substr($ip, 0, $ind);
$ind = strpos($ip, 'for=');
if ($ind !== false) {
$ip = substr($ip, $ind + 4);
if ($ip[0] == '"') {
$ip = substr($ip, 1, strpos($ip, '"', 1) - 1);
$ind = strpos($ip, ']');
if ($ind !== false)
$ip = substr($ip, 1, $ind - 1);
} else if ($ip[0] == '[') {
$ip = substr($ip, 1, strpos($ip, ']') - 1);
} else {
$ind = strpos($ip, ';');
if ($ind !== false)
$ip = substr($ip, 0, $ind);
if (strpos($ip, '.') !== false) {
$ind = strpos($ip, ':');
if ($ind !== false)
$ip = substr($ip, 0, $ind);
}
}
} else {
if (strpos($ip, '.') !== false) {
$ind = strpos($ip, ':');
if ($ind !== false)
$ip = substr($ip, 0, $ind);
}
}
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE))
return $ip;
}
if (isset($_SERVER['REMOTE_ADDR']))
return $_SERVER['REMOTE_ADDR'];
return '0.0.0.0';
}
//循环建立新文件夹
function dirmake($dir, $power = 0777) {
if (!$dir)
return false;
if (!is_dir($dir)) {
$ret = mkdir($dir, $power, true);
if ($ret === false)
savelogfile('err_file', 'dir make err:' . $dir);
return $ret;
}
return true;
}
//静默删除文件
function filedel($file) {
try {
unlink($file);
} catch (Exception $ex) {
savelogfile('err_file', 'file del err:' . $file . ':' . $ex->getMessage());
}
}
//静默拷贝文件
function filecopy($srcfile, $dstfile) {
try {
copy($srcfile, $dstfile);
} catch (Exception $ex) {
savelogfile('err_file', 'file copy err:' . $srcfile . '->' . $dstfile . ':' . $ex->getMessage());
}
}
//存储文本到文件
function filesave($filename, $text) {
if (!$filename || !$text)
return false;
if (!dirmake(dirname($filename)))
return false;
try {
if ($fp = fopen($filename, 'w')) {
if (@fwrite($fp, $text)) {
fclose($fp);
return true;
} else {
fclose($fp);
return false;
}
}
} catch (Exception $ex) {
savelogfile('err_file', 'file save err:' . $filename . ':' . $ex->getMessage());
}
return false;
}
//读取文本文件
function fileload($dfile) {
if (!file_exists($dfile))
return '';
try {
return file_get_contents($dfile);
} catch (Exception $ex) {
savelogfile('err_file', 'file load err:' . $dfile . ':' . $ex->getMessage());
}
return '';
}
//存储文本到文件
function storsave($filename, $text) {
if (!$filename || !$text)
return false;
$filename = str_replace('{Y}', date('Y'), $filename);
$filename = str_replace('{m}', date('m'), $filename);
$filename = str_replace('{d}', date('d'), $filename);
if (substr($filename, 0, 1) == '/')
$filename = PATH_WEB . 'ud' . $filename;
return filesave($filename, $text);
}
function webini($section) {
if (!file_exists(PATH_ROOT . 'web.ini'))
return 'INI file nofind:' . PATH_ROOT . 'web.ini';
try {
$inis = explode("\n", file_get_contents(PATH_ROOT . 'web.ini'));
$vars = null;
foreach ($inis as $ini) {
if (empty($ini))
continue;
if (strpos($ini, '[') === 0) {
$sec = substr($ini, 1, strpos($ini, ']') - 1);
if ($sec == $section) {
$vars = array();
} else if (is_array($vars))
return $vars;
} else {
if (!is_array($vars))
continue;
$pos = strpos($ini, '=');
if ($pos === false)
continue;
$key = substr($ini, 0, $pos);
$val = substr($ini, $pos + 1);
$vars[$key] = trim($val);
}
}
return 'INI section nofind:' . $section;
} catch (Exception $ex) {
return 'INI catch:' . $ex->getMessage();
}
return 'INI error';
}
/**
* 下载音视频图片文件到本地
* url 下载链接地址
* savepath 保存相对路径。如ud/
* filename 保存文件名。默认日期文件名
* timeout 下载超时时间 秒
*/
function file_down($url, $savepath, $filename = '', $timeout = 60, $defext = '.jpg') {
if (!dirmake(PATH_WEB . $savepath))
return 'ERR:保存目录建立失败';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, urldecode($url));
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
@curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
$data = curl_exec($ch);
if ($data === false || empty($data)) {
return 'ERR:下载失败';
}
$info = curl_getinfo($ch);
curl_close($ch);
if (empty($filename))
$filename = date('Ymd_His_') . rand(1000, 9999);
$fileext = $defext;
if ($info['content_type'] == 'image/jpeg')
$fileext = '.jpg';
else if ($info['content_type'] == 'image/jpg')
$fileext = '.jpg';
else if ($info['content_type'] == 'image/png')
$fileext = '.png';
else if ($info['content_type'] == 'image/gif')
$fileext = '.gif';
else if ($info['content_type'] == 'audio/amr')
$fileext = '.amr';
else if ($info['content_type'] == 'audio/wav')
$fileext = '.wav';
else if ($info['content_type'] == 'audio/mpeg')
$fileext = '.mp3';
else if ($info['content_type'] == 'audio/ogg')
$fileext = '.ogg';
else if ($info['content_type'] == 'image/svg+xml')
$fileext = '.svg';
else if ($info['content_type'] == 'image/webp')
$fileext = '.webp';
$fp = fopen(PATH_WEB . $savepath . $filename . $fileext, 'w');
fwrite($fp, $data);
@fclose($fp);
return $savepath . $filename . $fileext;
}
//文件扩展名 jpg
function file_ext($file) {
$ind = strrpos($file, '.');
if ($ind === false)
return '';
return substr($file, $ind + 1);
}
function file_stor($url) {
if (!$url)
return '';
if (strtolower(substr($url, 0, 4)) === 'http')
return $url;
$cfg = webini('s3' . substr($url, 0, 1));
return $cfg['url'] . substr($url, 1);
}