ホームページ バックエンド開発 PHPチュートリアル [zz]discuzX1 コア データ class_core.php 分析

[zz]discuzX1 コア データ class_core.php 分析

Jun 13, 2016 pm 01:03 PM
array function gt return this

[zz]discuzX1核心文件class_core.php分析

/*Discuz!X 核心文件class_core.php分析
ログイン後にコピー
2010-08-24 10:20
在研究DISCUZ!X核心文件class_core.php时作的DISCUZ!X产品相较之前版本的底层机制上的变化分析及源码部分注释。
___________________________________________
ログイン後にコピー
我今天花了1个多小时,阅读了下class_core.php,DB数据库和cron任务计划没看。总体感觉,比起dz72来说,各项机制和体系都有所增强,变化相当大。
【1】最明显的一点是,核心体系基本都用类进行封装了,架构清晰,使用起来相对简易,基本的架构类似Ucenter,但略有增强。
【2】安全机制进一步加强,特别是GLOBALS超级全局变量的注销,及各变量的初始化,让人印象深刻。
【3】原来的GPC和session机制,大体变化不算很大,但进行了一些优化和增强,考虑得更全面了。不过新版清晰与普通变量进行了区隔,如get、 post用 gp_,而cookie用$cookie数组,而session用$session。
【4】功能上,基本上原有的客户端ip、机器人判断、转义、gzhandler、对xss跨站攻击的基本防御、缓存丢失判断等基本上差别不算太大。
【5】增加了memory内存读写引擎,支持memcache、xcache,eAccelerator。
【6】在原有session机制处理逻辑基础上,精简了一部分实现,重新自定义并增强了SESSION机制,代码的写法与结构与memory写法类似。但具体效果有待验证。
ログイン後にコピー
附随笔作的注释大家将就看吧
*/
ログイン後にコピー
<?php

/**
 *      [Discuz!] (C)2001-2099 Comsenz Inc.
 *      This is NOT a freeware, use is subject to license terms
 *
 *      $Id: class_core.php 6914 2010-03-26 12:52:36Z cnteacher $
 */

///TODO 是将要完成的功能,包括禁止ip和禁止访问
//TODO 禁止ip
//TODO 禁止访问

///和DZ72一样,确保所有文件需要先加载核心文件
define('IN_DISCUZ', true);

/**
 * Discuz 核心引擎
 * 其他处理代码当中用到的变量不要在本核心 new 之前设置, 否则会自动清空
 *
 */
class discuz_core {

    // 数据库存储引擎
    var $db = null;

    // 内存缓冲object
    var $mem = null;

    // 会话 object
    var $session = null;

    // 程序配置
    var $config = array();

    // $_G 数组的映射
    var $var = array();

    // 加载缓存的数组
    var $cachelist = array();

    // 是否初始化
    var $init_setting = true; //设置
    var $init_user = true;//用户
    var $init_session = true;//会话
    var $init_cron = true;//任务计划
    var $init_misc = true;//其他功能
    var $init_memory = true;//内存

    // 是否已经初始化
    var $initated = false;

    var $superglobal = array(
        'GLOBALS' => 1,
        '_GET' = 1,
        '_POST' = 1,
        '_REQUEST' = 1,
        '_COOKIE' = 1,
        '_SERVER' = 1,
        '_ENV' = 1,
        '_FILES' = 1,
    );

    function &instance() {
        static $object;
        if(empty($object)) {
            $object = new discuz_core();
        }
        return $object;
    }

    function discuz_core() {
        $this->_init_env();
        $this->_init_config();
        $this->_init_input();
        $this->_init_output();
    }

    function init() {
        if(!$this->initated) {
            $this->_init_db();
            $this->_init_memory();
            $this->_init_user();
            $this->_init_session();
            $this->_init_setting();
            $this->_init_cron();
            $this->_init_misc();
        }
        $this->initated = true;
    }

    function _init_env() {

        error_reporting(E_ALL ^ E_NOTICE);
//        error_reporting(E_ALL);
        ///php 5.3前则关闭魔法引号匹配(自动转义)
        if(phpversion() < '5.3.0') {
            set_magic_quotes_runtime(0);
        }

        ///程序主目录,根据核心文件确定,原来是-7 代表在include下,现在是12代表在source/class下
        define('DISCUZ_ROOT', substr(dirname(__FILE__), 0, -12));
        ///和dz72一样,设置魔法引用(自动转义,单双引号反斜线)
        define('MAGIC_QUOTES_GPC', function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc());
        ///判断字符编码转换函数是否存在
        define('ICONV_ENABLE', function_exists('iconv'));
        ///亚洲字符转码函数是否存在, 因为mb_开头字符处理亚洲字符会比较高效,初步判断用于转码时先用mb_来处理:
        define('MB_ENABLE', function_exists('mb_convert_encoding'));
        ///是否存在输出缓存压缩函数,这个函数的目的,是在确认浏览器支持页面压缩后,才用该函数来压缩所有输出内容,否则直接传输
        define('EXT_OBGZIP', function_exists('ob_gzhandler'));

        ///和DZ72一样,不过当前时间戳被定义为一个常量,效率更高吧,也不用global了。
        define('TIMESTAMP', time());
        ///获取默认时区
        discuz_core::timezone_set();

        ///加载function_core.php,作用推测类似global.func.php
        if(!defined('DISCUZ_CORE_FUNCTION') && !@include(DISCUZ_ROOT.'./source/function/function_core.php')) {
            $this->error('function_core.php is missing');
        }

        //判断浏览器是否是蜘蛛
        define('IS_ROBOT', checkrobot());

        //清理全局变量
        ///全清理了,真是彻底把所有变量都从内存中注销了
        foreach ($GLOBALS as $key = $value) {
            if (!isset($this->superglobal[$key])) {
                $GLOBALS[$key] = null; unset($GLOBALS[$key]);
            }
        }

        // 配置全局变量
        ///和上一步结合,只留下自己需要的变量,并初始化。
        ///这么做够狠,只要稍微小心点,就不会出现因为变量未初始化而出现的安全问题
        global $_G;
        $_G = array(
            //公用全局定义
            'uid' = 0,
            'username' = '',
            'adminid' = 0,
            'groupid' = 1,
            'sid' = '',
            'formhash' = '',
            'timestamp' = TIMESTAMP,
            'starttime' = dmicrotime(),
            'clientip' = $this->_get_client_ip(),
            'referer' = '',
            'charset' = '',
            'gzipcompress' = '',
            'authkey' = '',
            'timenow' = array(),

            'PHP_SELF' = '',
            'siteurl' = '',

            //公用全局数组定义
            'config' = array(),
            'setting' = array(),
            'member' = array(),
            'group' = array(),
            'cookie' = array(),
            'style' = array(),
            'cache' = array(),
            'session' = array(),
            'lang' = array(),
            'my_app' = array(),//默认应用
            'my_userapp' = array(),//用户自添加应用

            //论坛全局定义
            'fid' = 0,
            'tid' = 0,
            'forum' = array(),
            'rssauth' = '',

            //uch 全局定义
            'home' = array(),
            'space' = array(),

            //portal 全局定义
            'block' = array(),
            'article' = array(),

            //Action
            'action' = array(
                'action' = APPTYPEID,
                'fid' = 0,
                'tid' = 0,
            )
        );
        //相对主目录的相对地址及文件名
        $_G['PHP_SELF'] = htmlspecialchars($_SERVER['PHP_SELF'] ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME']);
        //基本脚本名,每个功能脚本首页前都会定义
        //比如forum.php,则定义CURSCRIPT为forum,而forum_forumdisplay.php则不定义,因为属于forum
        $_G['basescript'] = CURSCRIPT;
        //站点网址
        $_G['siteurl'] = htmlspecialchars('http://'.$_SERVER['HTTP_HOST'].preg_replace("/\/+(api)?\/*$/i", '', substr($_G['PHP_SELF'], 0, strrpos($_G['PHP_SELF'], '/'))).'/');

        ///$_G的映射,也即超级全局变量
        $this->var = & $_G;

    }

    function _init_input() {

        //note 禁止对全局变量注入
        ///和dz72类似,禁止GLOBALS=xxx的方式注入
        if (isset($_REQUEST['GLOBALS']) || isset($_FILES['GLOBALS'])) {
            error('request_tainting');
        }

        if(!empty($_GET['rewrite'])) {
            $query_string = '?mod=';
            $param = explode('-', $_GET['rewrite']);
            $query_string .= $_GET['mod'] = $param[0];
            array_shift($param);
            $paramc = count($param);
            for($i = 0;$i < $paramc;$i+=2) {
                $_REQUEST[$param[$i]] = $_GET[$param[$i]] = $param[$i + 1];
                $query_string .= '&'.$param[$i].'='.$param[$i + 1];
            }
            $_SERVER['QUERY_STRING'] = $query_string;
            unset($param, $paramc, $query_string);
        }

        // slashes 处理,如果没有魔法引号处理(自动转义),则手动转义GET/POST/COOKIE/FILES中的单双引号、null反斜线\
        if(!MAGIC_QUOTES_GPC) {
            $_GET = daddslashes($_GET);
            $_POST = daddslashes($_POST);
            $_COOKIE = daddslashes($_COOKIE);
            $_FILES = daddslashes($_FILES);
        }

        //cookie 处理
        ///验证cookie前缀与config中的设置值是否一致,一致则转为$cookie数组中的值
        $prelength = strlen($this->config['cookie']['cookiepre']);
        foreach($_COOKIE as $key = $val) {
            if(substr($key, 0, $prelength) == $this->config['cookie']['cookiepre']) {
                $this->var['cookie'][substr($key, $prelength)] = $val;
            }
        }

        $_GET['diy'] = empty($_GET['diy']) ? '' : $_GET['diy'];

        ///$_GET和$_POST转成与索引同名加"gp_"前缀的变量
        ///如$_GET['username']直接用$gp_username来访问
        foreach(array_merge($_POST, $_GET) as $k = $v) {
            $this->var['gp_'.$k] = $v;
        }

        ///根据$_GET['mod']来确定m的值,$this->var为全局数组,gp_为上个语句的附加前缀
        $this->var['mod'] = empty($this->var['gp_mod']) ? '' : htmlspecialchars($this->var['gp_mod']);
        ///如果使用ajax,再判断是post传值或get和xmlhttprequest同时有效
        $this->var['inajax'] = empty($this->var['gp_inajax']) ? 0 : ($_SERVER['REQUEST_METHOD'] == 'GET' && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' || $_SERVER['REQUEST_METHOD'] == 'POST' ? 1 : 0);
        ///当前页码
        $this->var['page'] = empty($this->var['gp_page']) ? 1 : max(1, intval($this->var['gp_page']));
        ///确定cookie中的sid值
        $this->var['sid'] = $this->var['cookie']['sid'] = isset($this->var['cookie']['sid']) ? htmlspecialchars($this->var['cookie']['sid']) : '';
    }

    ///初始化设置
    function _init_config() {
        ///加载设置文件
        $_config = array();
        @include DISCUZ_ROOT.'./config/config_global.php';
        if(empty($_config)) {
            error('config_notfound');
        }
        ///确定密钥,如果值为空,则密钥默认为cookie前缀与数据库名拼接的md5值,否则为配置文件中的值
        ///authkey密钥是sid等参数加解密的重要参数
        $_config['security']['authkey'] = empty($config['security']['authkey']) ? md5($_config['cookie']['cookiepre'].$_config['db'][1]['dbname']) : ($config['security']['authkey']);

        $this->config = & $_config;
        ///Discuz的调试
        if(empty($this->config['debug']) || !file_exists(libfile('function/debug'))) {
            define('DISCUZ_DEBUG', false);
        } elseif($this->config['debug'] === 1 || $this->config['debug'] === 2 || !empty($_REQUEST['debug']) && $_REQUEST['debug'] === $this->config['debug']) {
            define('DISCUZ_DEBUG', true);
            if($this->config['debug'] == 2) {
                error_reporting(E_ALL);
            }
        }

        $GLOBALS['_G']['config'] = & $this->config;
        ///以浏览器版本为参考,进行密钥的二次md5加密
        $GLOBALS['_G']['authkey'] = md5($this->config['security']['authkey'].$_SERVER['HTTP_USER_AGENT']);
    }

    function _init_output() {
        ///如果设置中打开xss跨站脚本的防御模式,且网址中存在"<"和"""等非法字符,则拒绝请求
        if($this->config['security']['urlxssdefend'] && !empty($_SERVER['REQUEST_URI'])) {
            $temp = urldecode($_SERVER['REQUEST_URI']);
            if(strpos($temp, '<') !== false || strpos($temp, '"') !== false) {
                error('request_tainting');
            }
        }

        ///存在ob_gzhandler则启用输出缓存压缩
        if($this->config['output']['gzip'] && EXT_OBGZIP) {
            ob_start('ob_gzhandler');
            setglobal('gzipcompress', true);
        } else {
            ob_start();
            setglobal('gzipcompress', false);
        }

        ///确定HTML页面编码,及其他编码
        if($this->config['output']['forceheader']) {
            @header('Content-Type: text/html; charset='.$this->config['output']['charset']);
        }

        setglobal('charset', $this->config['output']['charset']);
        define('CHARSET', $this->config['output']['charset']);
    }

    ///拒绝机器人访问
    function reject_robot() {
        if(IS_ROBOT) {
            exit(header("HTTP/1.1 403 Forbidden"));
        }
    }

    ///获取客户端ip,
    function _get_client_ip() {
        $clientip = '';
        ///环境变量客户端ip有值且字符长度大于unknown,则说明该变量有效,确定为客户端ip
        if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
            $clientip = getenv('HTTP_CLIENT_IP');
        ///否则取当前浏览用户的网关ip地址
        } elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
            $clientip = getenv('HTTP_X_FORWARDED_FOR');
        ///用户计算机的ip地址
        } elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
            $clientip = getenv('REMOTE_ADDR');
        } elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
            $clientip = $_SERVER['REMOTE_ADDR'];
        }

        ///判断是否是数字与点组成的7-15位字符
        preg_match("/[\d\.]{7,15}/", $clientip, $clientipmatches);
        $clientip = $clientipmatches[0] ? $clientipmatches[0] : 'unknown';
        return $clientip;
    }

    function _init_db() {
        ///生成数据库对象
        $this->db = & DB::object();
        ///加载设置文件并连接数据库
        $this->db->set_config($this->config['db']);
        $this->db->connect();
    }

    function _init_session() {

        $this->session = new discuz_session();

        if($this->init_session)
        {
            ///传入sid,客户端ip与uid作为session判断机制,分新老用户,老用户则查session表,否则创建
            $this->session->init($this->var['cookie']['sid'], $this->var['clientip'], $this->var['uid']);
            $this->var['sid'] = $this->session->sid;
            $this->var['session'] = $this->session->var;

            if($this->var['sid'] != $this->var['cookie']['sid']) {
                dsetcookie('sid', $this->var['sid'], 86400);
            }

            // 首次登陆更新最后访问时间,每隔 10 分钟更新用户最后动作时间
            if($this->var['uid'] && ($this->session->isnew || ($this->session->get('lastactivity') + 600) < TIMESTAMP)) {

                $this->session->set('lastactivity', TIMESTAMP);

                $update = array('lastip' = $this->var['clientip'], 'lastactivity' = TIMESTAMP);
                if($this->session->isnew) {
                    $update['lastvisit'] = TIMESTAMP;
                }
                更新会员状态
                DB::update('common_member_status', $update, "uid='".$this->var['uid']."'");
            }
        }
    }

    function _init_user() {

        if($this->init_user) {
            if($auth = getglobal('auth', 'cookie')) {
                $auth = daddslashes(explode("\t", authcode($auth, 'DECODE')));
            }
            list($discuz_pw, $discuz_uid) = empty($auth) || count($auth) < 2 ? array('', '') : $auth;

            if($discuz_uid) {
                $user = getuserbyuid($discuz_uid);
            }

            if(!empty($user) && $user['password'] == $discuz_pw) {
                $this->var['member'] = $user;
            } else {
                $user = array();
                $this->_init_guest();
            }

            $this->cachelist[] = 'usergroup_'.$this->var['member']['groupid'];
            if($user && $user['adminid']  0 && $user['groupid'] != $user['adminid']) {
                $this->cachelist[] = 'admingroup_'.$this->var['member']['adminid'];
            }

        } else {
            $this->_init_guest();
        }

        if(empty($this->var['cookie']['lastvisit'])) {
            $this->var['member']['lastvisit'] = TIMESTAMP - 3600;
            dsetcookie('lastvisit', TIMESTAMP - 3600, 86400 * 30);
        } else {
            $this->var['member']['lastvisit'] = empty($this->var['cookie']['lastvisit']);
        }

        setglobal('uid', getglobal('uid', 'member'));
        setglobal('username', addslashes(getglobal('username', 'member')));
        setglobal('adminid', getglobal('adminid', 'member'));
        setglobal('groupid', getglobal('groupid', 'member'));
    }

    function _init_guest() {
        setglobal('member', array( 'uid' = 0, 'username' = '', 'groupid' = 7, 'credits' = 0, 'timeoffset' = 9999));
    }

    function _init_cron() {
        if($this->init_cron && $this->init_setting) {
            if($this->var['cache']['cronnextrun'] <= TIMESTAMP) {
                discuz_cron::run();
            }
        }
    }

    function _init_misc() {

        if(!$this->init_misc) {
            return false;
        }
        // 调入核心语言包
        lang('core');

        //处理全局时区设置
        if($this->init_setting && $this->init_user) {
            if(!isset($this->var['member']['timeoffset']) || $this->var['member']['timeoffset'] == 9999 || $this->var['member']['timeoffset'] === '') {
                $this->var['member']['timeoffset'] = $this->var['setting']['timeoffset'];
            }
        }

        $timeoffset = $this->init_setting ? $this->var['member']['timeoffset'] : $this->var['setting']['timeoffset'];
        $this->var['timenow'] = array(
            'time' = dgmdate(TIMESTAMP),
            'offset' = $timeoffset = 0 ? ($timeoffset == 0 ? '' : '+'.$timeoffset) : $timeoffset
        );
        $this->timezone_set($timeoffset);

        $this->var['formhash'] = formhash();
        define('FORMHASH', $this->var['formhash']);

        // 定义风格常量
        if(is_array($this->var['style'])) {
            foreach ($this->var['style'] as $key = $val) {
                $key = strtoupper($key);
                if(!defined($key) && !is_array($val)) {
                    define($key, $val);
                }
            }
        }

        //论坛开关检查
        if($this->var['setting']['**losed'] && !(in_array($this->var['mod'], array('logging', 'seccode')) || getglobal('adminid', 'member') == 1)) {
            $closedreason = DB::result_first("SELECT svalue FROM ".DB::table('common_setting')." WHERE skey='closedreason'");
            showmessage($closedreason ? $closedreason : 'board_closed', NULL, array(), array('login' = 1));
        }

        $this->var['tpp'] = $this->var['setting']['topicperpage'] ? intval($this->var['setting']['topicperpage']) : 20;
        $this->var['ppp'] = $this->var['setting']['postperpage'] ? intval($this->var['setting']['postperpage']) : 10;

        if($this->var['setting']['nocacheheaders']) {
            @header("Expires: -1");
            @header("Cache-Control: no-store, private, post-check=0, pre-check=0, max-age=0", FALSE);
            @header("Pragma: no-cache");
        }

        $lastact = TIMESTAMP."\t".htmlspecialchars(basename($this->var['PHP_SELF']))."\t".htmlspecialchars($this->var['mod']);
        dsetcookie('lastact', $lastact, 86400);

    }

    function _init_setting() {

        if($this->init_setting) {

            if(empty($this->var['setting'])) {
                $this->cachelist[] = 'setting';
            }

            if(empty($this->var['style'])) {
                $this->cachelist[] = 'style_default';
            }

            if(!isset($this->var['cache']['cronnextrun'])) {
                $this->cachelist[] = 'cronnextrun';
            }
        }

        !empty($this->cachelist) && loadcache($this->cachelist);

        if(!is_array($this->var['setting'])) {
            $this->var['setting'] = array();
        }
        if($this->var['member'] && $this->var['member']['adminid']  0 && $this->var['member']['groupid'] != $this->var['member']['adminid'] && !empty($this->var['cache']['admingroup_'.$this->var['member']['adminid']])) {
            $this->var['group'] = array_merge($this->var['group'], $this->var['cache']['admingroup_'.$this->var['member']['adminid']]);
        }
    }

    function _init_memory() {
        $this->mem = new discuz_memory();
        if($this->init_memory) {
            $this->mem->init($this->config['memory']);
        }
        $this->var['memory'] = $this->mem->type;
    }

    function timezone_set($timeoffset = 0) {
        if(function_exists('date_default_timezone_set')) {
            @date_default_timezone_set('Etc/GMT'.($timeoffset  0 ? '-' : '+').(abs($timeoffset)));
        }
    }

    function error($msg, $halt = true) {
        $this->error_log($msg);
        echo $msg;
        $halt && exit();
    }

    function error_log($message) {
        $time = date("Y-m-d H:i:s", TIMESTAMP);
        $file =  DISCUZ_ROOT.'./data/log/errorlog_'.date("Ym").'.txt';
        $message = "\n#{$time}:\t".str_replace(array("\t", "\r", "\n"), " ", $message);
        error_log($message, 3, $file);
    }

}

/**
 * Discuz MySQL 类的支持
 *
 */
class db_mysql
{
    var $tablepre;
    var $version = '';
    var $querynum = 0;
    var $curlink;
    var $link = array();
    var $config = array();
    var $sqldebug = array();

    function db_mysql($config = array()) {
        if(!empty($config)) {
            $this->set_config($config);
        }
    }

    function set_config($config) {
        $this->config = &$config;
        $this->tablepre = $config['1']['tablepre'];
    }

    function connect() {

        if(empty($this->config) || empty($this->config[1])) {
            $this->halt('notfound_config');
        }

        foreach ($this->config as $id = $config) {
            $this->link[$id] = $this->_dbconnect(
            $config['dbhost'],
            $config['dbuser'],
            $config['dbpw'],
            $config['dbcharset'],
            $config['dbname'],
            $config['pconnect']
            );
        }
        $this->curlink = $this->link[1];
    }

    function _dbconnect($dbhost, $dbuser, $dbpw, $dbcharset, $dbname, $pconnect) {
        $link = null;
        $func = empty($pconnect) ? 'mysql_connect' : 'mysql_pconnect';
        if(!$link = @$func($dbhost, $dbuser, $dbpw, 1)) {
            $this->halt('notconnect');
        } else {
            $this->curlink = $link;
            if($this->version()  '4.1') {
                $serverset = $dbcharset ? 'character_set_connection='.$dbcharset.', character_set_results='.$dbcharset.', character_set_client=binary' : '';
                $serverset .= $this->version()  '5.0.1' ? ((empty($serverset) ? '' : ',').'sql_mode=\'\'') : '';
                $serverset && mysql_query("SET $serverset", $link);
            }
            $dbname && @mysql_select_db($dbname, $link);
        }
        return $link;
    }

    function table_name($tablename) {
        return $this->tablepre.$tablename;
    }

    function select_db($dbname) {
        return mysql_select_db($dbname, $this->curlink);
    }

    function fetch_array($query, $result_type = MYSQL_ASSOC) {
        return mysql_fetch_array($query, $result_type);
    }

    function fetch_first($sql) {
        return $this->fetch_array($this->query($sql));
    }

    function result_first($sql) {
        return $this->result($this->query($sql), 0);
    }

    function query($sql, $type = '') {

        if(defined('DISCUZ_DEBUG') && DISCUZ_DEBUG) {
            $starttime = dmicrotime();
        }
        $func = $type == 'UNBUFFERED' && @function_exists('mysql_unbuffered_query') ?
        'mysql_unbuffered_query' : 'mysql_query';
        if(!($query = $func($sql, $this->curlink))) {
            if(in_array($this->errno(), array(2006, 2013)) && substr($type, 0, 5) != 'RETRY') {
                $this->connect();
                return $this->query($sql, 'RETRY'.$type);
            }
            if($type != 'SILENT' && substr($type, 5) != 'SILENT') {
                $this->halt('query_error', $sql);
            }
        }

        if(defined('DISCUZ_DEBUG') && DISCUZ_DEBUG) {
            $this->sqldebug[] = array($sql, number_format((dmicrotime() - $starttime), 6), debug_backtrace());
        }

        $this->querynum++;
        return $query;
    }

    function affected_rows() {
        return mysql_affected_rows($this->curlink);
    }

    function error() {
        return (($this->curlink) ? mysql_error($this->curlink) : mysql_error());
    }

    function errno() {
        return intval(($this->curlink) ? mysql_errno($this->curlink) : mysql_errno());
    }

    function result($query, $row = 0) {
        $query = @mysql_result($query, $row);
        return $query;
    }

    function num_rows($query) {
        $query = mysql_num_rows($query);
        return $query;
    }

    function num_fields($query) {
        return mysql_num_fields($query);
    }

    function free_result($query) {
        return mysql_free_result($query);
    }

    function insert_id() {
        return ($id = mysql_insert_id($this->curlink)) = 0 ? $id : $this->result($this->query("SELECT last_insert_id()"), 0);
    }

    function fetch_row($query) {
        $query = mysql_fetch_row($query);
        return $query;
    }

    function fetch_fields($query) {
        return mysql_fetch_field($query);
    }

    function version() {
        if(empty($this->version)) {
            $this->version = mysql_get_server_info($this->curlink);
        }
        return $this->version;
    }

    function close() {
        return mysql_close($this->curlink);
    }

    function halt($message = '', $sql = '') {
        global $_G;
        $dberror = $this->error();
        $dberrno = $this->errno();
        $phperror = '<table style="font-size:11px" cellpadding="0"><tr><td width="270">File</td><td width="80">Line</td><td>Function</td></tr>';
        foreach (debug_backtrace() as $error) {
            $error['file'] = str_replace(DISCUZ_ROOT, '', $error['file']);
            $error['class'] = isset($error['class']) ? $error['class'] : '';
            $error['type'] = isset($error['type']) ? $error['type'] : '';
            $error['function'] = isset($error['function']) ? $error['function'] : '';
            $phperror .= "<tr><td>$error[file]</td><td>$error[line]</td><td>$error[class]$error[type]$error[function]()</td></tr>";
        }
        $phperror .= '</table>';
        $helplink = "http://faq.comsenz.com/?type=mysql&dberrno=".rawurlencode($dberrno)."&dberror=".rawurlencode($dberror);
        @header('Content-Type: text/html; charset='.$_G['config']['output']['charset']);
        echo '<div style="position:absolute;font-size:11px;font-family:verdana,arial;background:#EBEBEB;padding:0.5em;line-height:1.5em">'.
        error('db_error', array(
            '$message' = error('db_'.$message, array(), true),
            '$info' = $dberror ? error('db_error_message', array('$dberror' = $dberror), true) : '',
            '$sql' = $sql ? error('db_error_sql', array('$sql' = $sql), true) : '',
            '$errorno' = $dberrno ? error('db_error_no', array('$dberrno' = $dberrno), true) : '',
            '$helplink' = $helplink,
            ), true);
        echo "<b>PHP Backtrace</b><br />$phperror<br /></div>";
        exit();
    }

}

/**
 * 对Discuz CORE 中 DB Object中的主要方法进行二次封装,方便程序调用
 *
 */
class DB
{

    /**
     * 返回表名(pre_$table)
     *
     * @param 原始表名 $table
     * @return 增加pre之后的名字
     */
    function table($table) {
        $a = & DB::object();
        return $a->table_name($table);
    }

    /**
     * 删除一条或者多条记录
     *
     * @param string $table 原始表名
     * @param string $condition 条件语句,不需要写WHERE
     * @param int $limit 删除条目数
     * @param boolean $unbuffered 立即返回?
     */
    function delete($table, $condition, $limit = 0, $unbuffered = true) {
        if(empty($condition)) {
            $where = '1';
        } elseif(is_array($condition)) {
            $where = DB::implode_field_value($condition, ' AND ');
        } else {
            $where = $condition;
        }
        $sql = "DELETE FROM ".DB::table($table)." WHERE $where ".($limit ? "LIMIT $limit" : '');
        return DB::query($sql, ($unbuffered ? 'UNBUFFERED' : ''));
    }

    /**
     * 插入一条记录
     *
     * @param string $table 原始表名
     * @param array $data 数组field->vlaue 对
     * @param boolen $return_insert_id 返回 InsertID?
     * @param boolen $replace 是否是REPLACE模式
     * @param boolen $silent 屏蔽错误?
     * @return InsertID or Result
     */
    function insert($table, $data, $return_insert_id = false, $replace = false, $silent = false) {

        $sql = DB::implode_field_value($data);

        $cmd = $replace ? 'REPLACE INTO' : 'INSERT INTO';

        $table = DB::table($table);
        $silent = $silent ? 'SILENT' : '';

        $return = DB::query("$cmd $table SET $sql", $silent);

        return $return_insert_id ? DB::insert_id() : $return;

    }

    /**
     * 更新一条或者多条数据记录
     *
     * @param string $table 原始表名
     * @param array $data 数据field-value
     * @param string $condition 条件语句,不需要写WHERE
     * @param boolean $unbuffered 迅速返回?
     * @param boolan $low_priority 延迟更新?
     * @return result
     */
    function update($table, $data, $condition, $unbuffered = false, $low_priority = false) {
        $sql = DB::implode_field_value($data);
        $cmd = "UPDATE ".($low_priority ? 'LOW_PRIORITY' : '');
        $table = DB::table($table);
        $where = $comma = '';
        if(empty($condition)) {
            $where = '1';
        } elseif(is_array($condition)) {
            $where = DB::implode_field_value($condition, ' AND ');
        } else {
            $where = $condition;
        }
        $res = DB::query("$cmd $table SET $sql WHERE $where", $unbuffered ? 'UNBUFFERED' : '');
        return $res;
    }

    /**
     * 格式化field字段和value,并组成一个字符串
     *
     * @param array $array 格式为 key=value 数组
     * @param 分割符 $glue
     * @return string
     */
    function implode_field_value($array, $glue = ',') {
        //print_r(debug_backtrace());
        $sql = $comma = '';
        foreach ($array as $k = $v) {
            $sql .= $comma."`$k`='$v'";
            $comma = $glue;
        }
        return $sql;
    }

    /**
     * 返回插入的ID
     *
     * @return int
     */
    function insert_id() {
        $db = & DB::object();
        return $db->insert_id();
    }

    /**
     * 依据查询结果,返回一行数据
     *
     * @param resourceID $resourceid
     * @return array
     */
    function fetch($resourceid) {
        $db = & DB::object();
        return $db->fetch_array($resourceid);
    }

    /**
     * 依据SQL文,返回一条查询结果
     *
     * @param string $query 查询语句
     * @return array
     */
    function fetch_first($sql) {
        $db = & DB::object();
        return $db->fetch_first($sql);
    }

    /**
     * 依据查询结果,返回结果数值
     *
     * @param resourceid $resourceid
     * @return string or int
     */
    function result($resourceid, $row = 0) {
        $db = & DB::object();
        return $db->result($resourceid, $row);
    }

    /**
     * 依据查询语句,返回结果数值
     *
     * @param string $query SQL查询语句
     * @return unknown
     */
    function result_first($sql) {
        $db = & DB::object();
        return $db->result_first($sql);
    }

    /**
     * 执行查询
     *
     * @param string $sql
     * @param 类型定义 $type UNBUFFERED OR SILENT
     * @return Resource OR Result
     */
    function query($sql, $type = '') {
        $db = & DB::object();
        return $db->query($sql, $type);
    }

    /**
     * 返回select的结果行数
     *
     * @param resource $resourceid
     * @return int
     */
    function num_rows($resourceid) {
        $db = & DB::object();
        return $db->num_rows($resourceid);
    }

    /**
     * 返回sql语句所影响的记录行数
     *
     * @return int
     */
    function affected_rows() {
        $db = & DB::object();
        return $db->affected_rows();
    }

    function free_result($query) {
        $db = & DB::object();
        return $db->free_result($query);
    }

    function error() {
        $db = & DB::object();
        return $db->error();
    }

    function errno() {
        $db = & DB::object();
        return $db->errno();
    }

    /**
     * 返回 DB object 指针
     *
     * @return pointer of db object from discuz core
     */
    function &object() {
        static $db;
        if(empty($db)) {
            $db = new db_mysql();
        }
        return $db;
    }
}

class discuz_session {

    ///sid,ip1-4, uid, username, groupid组id, invisible隐身与否,action行为,上次活动lastactivity,fid板块id,tid帖子id
    var $sid = null;
    var $var;
    var $isnew = false;
    var $newguest = array('sid' = 0, 'ip1' = 0, 'ip2' = 0, 'ip3' = 0, 'ip4' = 0,
    'uid' = 0, 'username' = '', 'groupid' = 7, 'invisible' = 0, 'action' = 0,
    'lastactivity' = 0, 'fid' = 0, 'tid' = 0);

    var $old =  array('sid' =  '', 'ip' =  '', 'uid' =  0);

    ///与类同名的函数,构造函数,初始化session各值
    function discuz_session($sid = '', $ip = '', $uid = 0) {
        $this->old = array('sid' =  $sid, 'ip' =  $ip, 'uid' =  $uid);
        $this->var = $this->newguest;
        if(!empty($ip)) {
            $this->init($sid, $ip, $uid);
        }
    }
    ///设置$newguest各项值
    function set($key, $value) {
        if(isset($this->newguest[$key])) {
            $this->var[$key] = $value;
        } elseif ($key == 'ip') {
            $ips = explode('.', $value);
            $this->set('ip1', $ips[0]);
            $this->set('ip2', $ips[1]);
            $this->set('ip3', $ips[2]);
            $this->set('ip4', $ips[3]);
        }
    }

    ///获取
    function get($key) {
        if(isset($this->newguest[$key])) {
            return $this->var[$key];
        } elseif ($key == 'ip') {
            return $this->get('ip1').'.'.$this->get('ip2').'.'.$this->get('ip3').'.'.$this->get('ip4');
        }
    }

    ///初始化,sid有值则可能是老用户,去读session表,判断sid,ip符合的值是否存在,存在则赋值给$sid
    function init($sid, $ip, $uid) {
        $this->old = array('sid' =  $sid, 'ip' =  $ip, 'uid' =  $uid);
        $session = array();
        if($sid) {
            $session = DB::fetch_first("SELECT * FROM ".DB::table('common_session').
                " WHERE sid='$sid' AND CONCAT_WS('.', ip1,ip2,ip3,ip4)='$ip'");
        }

        if(empty($session) || $session['uid'] != $uid) {
            $session = $this->create($ip, $uid);
        }

        $this->var = $session;
        $this->sid = $session['sid'];
    }

    ///新用户
    function create($ip, $uid) {

        $this->isnew = true;
        $this->var = $this->newguest;
        $this->set('sid', random(6));
        $this->set('uid', $uid);
        $this->set('ip', $ip);
        $this->set('lastactivity', time());
        $this->sid = $this->var['sid'];

        return $this->var;
    }

    function delete() {

        $onlinehold = 1800; //此数值应当取自全局变量
        $guestspan = 60; //避免游客重复激活sid

        $onlinehold = time() - $onlinehold;
        $guestspan = time() - $guestspan;

        //当前用户的sid
        $condition = " sid='{$this->sid}' ";
        //过期的 session
        $condition .= " OR lastactivity<$onlinehold ";
        //频繁的同一ip游客
        $condition .= " OR (uid='0' AND ip1='{$this->var['ip1']}' AND ip2='{$this->var['ip2']}' AND ip3='{$this->var['ip3']}' AND ip4='{$this->var['ip4']}' AND lastactivity$guestspan) ";
        //当前用户的uid
        $condition .= $this->var['uid'] ? " OR (uid='{$this->var['uid']}') " : '';
        DB::delete('common_session', $condition);
    }

    function update() {
        if($this->sid !== null) {

            $data = daddslashes($this->var);

            if($this->isnew) {
                $this->delete();
                DB::insert('common_session', $data, false, false, true);
            } else {
                DB::update('common_session', $data, "sid='$data[sid]'");
            }
            dsetcookie('sid', $this->sid, 86400);
        }
    }

    /**
     * 取在线用户数量
     *
     * @param int $type 0=全部 1=会员 2=游客
     */
    function onlinecount($type = 0) {
        $condition = $type == 1 ? ' WHERE uid0 ' : ($type == 2 ? ' WHERE invisible=1 ' : '');
        return DB::result_first("SELECT count(*) FROM ".DB::table('common_session').$condition);
    }

}

class discuz_cron
{

    /**
     * 运行cron
     *
     * @param int $cronid 执行某个cron,如果不指定则运行当前需要运行的
     * @return true
     */
    function run($cronid = 0) {

        $timestamp = TIMESTAMP;
        $cron = DB::fetch_first("SELECT * FROM ".DB::table('common_cron')."
                WHERE ".($cronid ? "cronid='$cronid'" : "available'0' AND nextrun<='$timestamp'")."
                ORDER BY nextrun LIMIT 1");

        $processname ='DZ_CRON_'.(empty($cron) ? 'CHECKER' : $cron['cronid']);

        if(!discuz_process::create($processname, 600)) {
            return false;
        }

        if($cron) {

            $cron['filename'] = str_replace(array('..', '/', '\\'), '', $cron['filename']);
            $cronfile = DISCUZ_ROOT.'./source/include/cron/'.$cron['filename'];

            $cron['minute'] = explode("\t", $cron['minute']);
            discuz_cron::setnextime($cron);

            @set_time_limit(1000);
            @ignore_user_abort(TRUE);

            if(!@include $cronfile) {
                //debug('CRON', $cron['name'].' : Cron script('.$cron['filename'].') not found or syntax error', 0);
            }
        }

        discuz_cron::nextcron();
        discuz_process::delete($processname);
        return true;
    }

    /**
     * 设定下一个计划任务将要执行的时间 here...
     *
     */
    function nextcron() {
        $nextrun = DB::result_first("SELECT nextrun FROM ".DB::table('common_cron')." WHERE available>'0' ORDER BY nextrun LIMIT 1");
        if($nextrun !== FALSE) {
            save_syscache('cronnextrun', $nextrun);
        } else {
            save_syscache('cronnextrun', TIMESTAMP + 86400 * 365);
        }
        return true;
    }

    /**
     * 设定某个计划任务下次执行时间
     *
     * @param array $cron
     * @return true
     */
    function setnextime($cron) {

        global $_G;

        if(empty($cron)) return FALSE;

        list($yearnow, $monthnow, $daynow, $weekdaynow, $hournow, $minutenow) = explode('-', gmdate('Y-m-d-w-H-i', TIMESTAMP + $_G['setting']['timeoffset'] * 3600));

        if($cron['weekday'] == -1) {
            if($cron['day'] == -1) {
                $firstday = $daynow;
                $secondday = $daynow + 1;
            } else {
                $firstday = $cron['day'];
                $secondday = $cron['day'] + gmdate('t', TIMESTAMP + $_G['setting']['timeoffset'] * 3600);
            }
        } else {
            $firstday = $daynow + ($cron['weekday'] - $weekdaynow);
            $secondday = $firstday + 7;
        }

        if($firstday < $daynow) {
            $firstday = $secondday;
        }

        if($firstday == $daynow) {
            $todaytime = discuz_cron::todaynextrun($cron);
            if($todaytime['hour'] == -1 && $todaytime['minute'] == -1) {
                $cron['day'] = $secondday;
                $nexttime = discuz_cron::todaynextrun($cron, 0, -1);
                $cron['hour'] = $nexttime['hour'];
                $cron['minute'] = $nexttime['minute'];
            } else {
                $cron['day'] = $firstday;
                $cron['hour'] = $todaytime['hour'];
                $cron['minute'] = $todaytime['minute'];
            }
        } else {
            $cron['day'] = $firstday;
            $nexttime = discuz_cron::todaynextrun($cron, 0, -1);
            $cron['hour'] = $nexttime['hour'];
            $cron['minute'] = $nexttime['minute'];
        }

        $nextrun = @gmmktime($cron['hour'], $cron['minute'] > 0 ? $cron['minute'] : 0, 0, $monthnow, $cron['day'], $yearnow) - $_G['setting']['timeoffset'] * 3600;

        $availableadd = $nextrun  TIMESTAMP ? '' : ', available=\'0\'';
        DB::query("UPDATE ".DB::table('common_cron')." SET lastrun='$_G[timestamp]', nextrun='$nextrun' $availableadd WHERE cronid='$cron[cronid]'");

        return true;
    }

    /**
     * 计算计划任务今日执行状态
     *
     * @param int $cron
     * @param int $hour
     * @param int $minute
     * @return int
     */
    function todaynextrun($cron, $hour = -2, $minute = -2) {
        global $_G;

        $hour = $hour == -2 ? gmdate('H', TIMESTAMP + $_G['setting']['timeoffset'] * 3600) : $hour;
        $minute = $minute == -2 ? gmdate('i', TIMESTAMP + $_G['setting']['timeoffset'] * 3600) : $minute;

        $nexttime = array();
        if($cron['hour'] == -1 && !$cron['minute']) {
            $nexttime['hour'] = $hour;
            $nexttime['minute'] = $minute + 1;
        } elseif($cron['hour'] == -1 && $cron['minute'] != '') {
            $nexttime['hour'] = $hour;
            if(($nextminute = discuz_cron::nextminute($cron['minute'], $minute)) === false) {
                ++$nexttime['hour'];
                $nextminute = $cron['minute'][0];
            }
            $nexttime['minute'] = $nextminute;
        } elseif($cron['hour'] != -1 && $cron['minute'] == '') {
            if($cron['hour'] < $hour) {
                $nexttime['hour'] = $nexttime['minute'] = -1;
            } elseif($cron['hour'] == $hour) {
                $nexttime['hour'] = $cron['hour'];
                $nexttime['minute'] = $minute + 1;
            } else {
                $nexttime['hour'] = $cron['hour'];
                $nexttime['minute'] = 0;
            }
        } elseif($cron['hour'] != -1 && $cron['minute'] != '') {
            $nextminute = discuz_cron::nextminute($cron['minute'], $minute);
            if($cron['hour'] &lt; $hour || ($cron['hour'] == $hour && $nextminute === false)) {
                $nexttime['hour'] = -1;
                $nexttime['minute'] = -1;
            } else {
                $nexttime['hour'] = $cron['hour'];
                $nexttime['minute'] = $nextminute;
            }
        }

        return $nexttime;
    }

    /**
     * 计算计划任务执行时刻
     *
     * @param int $nextminutes
     * @param int $minutenow
     * @return int
     */
    function nextminute($nextminutes, $minutenow) {
        foreach($nextminutes as $nextminute) {
            if($nextminute > $minutenow) {
                return $nextminute;
            }
        }
        return false;
    }
}

/**
 * 功能进程管理
 * 通常用于某些功能禁止?⒎⒃诵?
 *
 */

class discuz_process
{

    /**
     * 获取某进程信息
     *
     * @param string $name 进程名字
     * @return array
     */
    function get($name) {
        $name5 = md5($name);
        $res = DB::fetch_first("SELECT * FROM ".DB::table('common_process')." WHERE processid='$name5'");

        if(empty($res)) {
            $res = array();
        } elseif($res['expiry'] < TIMESTAMP) {
            discuz_process::delete($name);
            $res = array();
        }
        return $res;
    }

    /**
     * 创建进程
     *
     * @param string $name 进程名
     * @param int $lifespan 进程过期时间
     * @param int $extra 进程附属信息
     * @return boolean
     */
    function create($name, $lifespan = 0, $extra = 0) {
        $check = discuz_process::get($name);
        if(empty($check)) {
            $lifespan = empty($lifespan) ? 600 : $lifespan;
            DB::insert('common_process', array(
                'processid' => md5($name),
                'expiry' = TIMESTAMP + $lifespan,
                'extra' =$extra), false, true);
            return true;
        }
        else {
            return false;
        }
    }

    /**
     * 删除某个进程或过期进程
     *
     * @param string $name 进程名
     */
    function delete($name = '') {
        $name = md5($name);
        DB::delete('common_process', "processid='$name' OR expiry<".TIMESTAMP);
    }

}

/**
 * Discuz 内存读写引擎
 * 支持 memcache, eAccelerator, XCache
 *
 * 使用的时候建议直接利用函数 memory()
 */
class discuz_memory
{
    var $config;
    var $extension = array();
    var $memory;
    var $prefix;
    var $type;
    var $keys;
    var $enable = false;

    /**
     * 确认当前系统支持的内存读写接口
     * @return discuz_memory
     */
    function discuz_memory() {
        $this->extension['eaccelerator'] = extension_loaded('eAccelerator');
        $this->extension['xcache'] = extension_loaded('XCache');
        $this->extension['memcache'] = extension_loaded('memcache');
    }

    /**
     * 依据config当中设置,初始化内存引擎
     * @param unknown_type $config
     */
    function init($config) {

        $this->config = $config;<span ><span style="color: #007700;">?</span><span style="color: #ff8000;">//这里的$config能追溯到discuz_core的构造函数,就是把config_global.php的数据加载进来</span></span>
        $this->prefix = empty($config['prefix']) ? substr(md5($_SERVER['HTTP_HOST']), 0, 6).'_' : $config['prefix'];
        $this->keys = array();

        // memcache 接口
        if($this->extension['memcache'] && !empty($config['memcache']['server'])) {
            require_once libfile('class/memcache');
            $this->memory = new discuz_memcache();
            $this->memory->init($this->config['memcache']);
            if(!$this->memory->enable) {
                $this->memory = null;
            }
        }

        // eaccelerator 接口
        if(!is_object($this->memory) && $this->extension['eaccelerator'] && $this->config['eaccelerator']) {
            require_once libfile('class/eaccelerator');
            $this->memory = new discuz_eaccelerator();
            $this->memory->init(null);
        }

        // xcache 接口
        if(!is_object($this->memory) && $this->extension['xcache'] && $this->config['xcache']) {
            require_once libfile('class/xcache');
            $this->memory = new discuz_xcache();
            $this->memory->init(null);
        }

        // 当接口正常,引入当前已经缓存的变量数组
        if(is_object($this->memory)) {
            $this->enable = true;
            $this->type = str_replace('discuz_', '', get_class($this->memory));
            $this->keys = $this->get('memory_system_keys');
            $this->keys = !is_array($this->keys) ? array() : $this->keys;
        }

    }

    /**
     * 读取内存
     *
     * @param string $key
     * @return mix
     */
    function get($key) {
        $ret = null;
        if($this->enable && (isset($this->keys[$key]) || $key == 'memory_system_keys')) {
            $ret = $this->memory->get($this->_key($key));
            if(!is_array($ret)) {
                $ret = null;
            } else {
                return $ret[0];
            }
        }
        return $ret;
    }

    /**
     * 写入内存
     *
     * @param string $key
     * @param array_string_number $value
     * @param int过期时间 $ttl
     * @return boolean
     */
    function set($key, $value, $ttl = 0) {

        $ret = null;
        if($this->enable) {
            $ret = $this->memory->set($this->_key($key), array($value), $ttl);
            if($ret) {
                $this->keys[$key] = true;
                $this->memory->set($this->_key('memory_system_keys'), array($this->keys));
            }
        }
        return $ret;
    }

    /**
     * 删除一个内存单元
     * @param 键值string $key
     * @return boolean
     */
    function rm($key) {
        $ret = null;
        if($this->enable) {
            $ret = $this->memory->rm($this->_key($key));
            if($ret) {
                unset($this->keys[$key]);
                $this->memory->set($this->_key('memory_system_keys'), array($this->keys));
            }
        }
        return $ret;
    }

    /**
     * 清除当前使用的所有内存
     */
    function clear() {
        if($this->enable && is_array($this->keys)) {
            $this->keys['memory_system_keys'] = true;
            foreach ($this->keys as $k = $v) {
                $this->memory->rm($this->_key($k));
            }
        }
        $this->keys = array();
        return true;
    }

    /**
     * 内部函数 追加键值前缀
     * @param string $str
     * @return boolean
     */
    function _key($str) {
        return ($this->prefix).$str;
    }

}
ログイン後にコピー

?

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Huawei GT3 ProとGT4の違いは何ですか? Huawei GT3 ProとGT4の違いは何ですか? Dec 29, 2023 pm 02:27 PM

多くのユーザーはスマートウォッチを選ぶときにファーウェイブランドを選択しますが、その中でもファーウェイ GT3pro と GT4 は非常に人気のある選択肢であり、多くのユーザーはファーウェイ GT3pro と GT4 の違いに興味を持っています。 Huawei GT3pro と GT4 の違いは何ですか? 1. 外観 GT4: 46mm と 41mm、材質はガラスミラー + ステンレススチールボディ + 高解像度ファイバーバックシェルです。 GT3pro: 46.6mm および 42.9mm、材質はサファイアガラス + チタンボディ/セラミックボディ + セラミックバックシェルです。 2. 健全な GT4: 最新の Huawei Truseen5.5+ アルゴリズムを使用すると、結果はより正確になります。 GT3pro: ECG 心電図と血管と安全性を追加

C言語のreturnの使い方を詳しく解説 C言語のreturnの使い方を詳しく解説 Oct 07, 2023 am 10:58 AM

C 言語における return の使い方は、 1. 戻り値の型が void の関数については、return 文を使用して関数の実行を早期に終了することができます; 2. 戻り値の型が void ではない関数については、 return ステートメントは、関数の実行を終了するためのものです。結果は呼び出し元に返されます。 3. 関数の実行を早期に終了します。関数内で return ステートメントを使用して、関数の実行を早期に終了することもできます。関数が値を返さない場合。

機能とはどういう意味ですか? 機能とはどういう意味ですか? Aug 04, 2023 am 10:33 AM

ファンクションとは、関数を意味します。これは、特定の関数を備えた再利用可能なコード ブロックです。プログラムの基本コンポーネントの 1 つです。入力パラメータを受け取り、特定の操作を実行し、結果を返すことができます。その目的は、再利用可能なコード ブロックをカプセル化することです。コードの再利用性と保守性を向上させるコード。

修正: Windows 11 で Snipping ツールが機能しない 修正: Windows 11 で Snipping ツールが機能しない Aug 24, 2023 am 09:48 AM

Windows 11 で Snipping Tool が機能しない理由 問題の根本原因を理解すると、適切な解決策を見つけるのに役立ちます。 Snipping Tool が正しく動作しない主な理由は次のとおりです。 フォーカス アシスタントがオンになっている: これにより、Snipping Tool が開かなくなります。破損したアプリケーション: 起動時にスニッピング ツールがクラッシュする場合は、破損している可能性があります。古いグラフィック ドライバー: 互換性のないドライバーは、スニッピング ツールに干渉する可能性があります。他のアプリケーションからの干渉: 実行中の他のアプリケーションが Snipping Tool と競合する可能性があります。証明書の有効期限が切れています: アップグレード プロセス中のエラーにより、この問題が発生する可能性があります。これらの簡単な解決策は、ほとんどのユーザーに適しており、特別な技術知識は必要ありません。 1. Windows および Microsoft Store アプリを更新する

Javaのreturn文とfinally文の実行順序は何ですか? Javaのreturn文とfinally文の実行順序は何ですか? Apr 25, 2023 pm 07:55 PM

ソースコード: publicclassReturnFinallyDemo{publicstaticvoidmain(String[]args){System.out.println(case1());}publicstaticintcase1(){intx;try{x=1;returnx;}finally{x=3;}}}#出力 上記のコードの出力は、単純に次のように結論付けることができます:finally の前に return が実行されます。バイトコード レベルで何が起こるかを見てみましょう。以下は、case1 メソッドのバイトコードの一部をインターセプトし、ソース コードを比較して、各命令の意味に注釈を付けます。

C# の Array.Sort 関数を使用して配列を並べ替える C# の Array.Sort 関数を使用して配列を並べ替える Nov 18, 2023 am 10:37 AM

タイトル: Array.Sort 関数を使用して C# で配列を並べ替える例 本文: C# では、配列は一般的に使用されるデータ構造であり、多くの場合、配列を並べ替える必要があります。 C# には Array クラスが用意されており、このクラスには配列を簡単に並べ替えるための Sort メソッドがあります。この記事では、C# で Array.Sort 関数を使用して配列を並べ替える方法を示し、具体的なコード例を示します。まず、Array.Sort 関数の基本的な使用法を理解する必要があります。 Array.So

iPhoneでApp Storeに接続できないエラーを修正する方法 iPhoneでApp Storeに接続できないエラーを修正する方法 Jul 29, 2023 am 08:22 AM

パート 1: 最初のトラブルシューティング手順 Apple のシステムステータスを確認する: 複雑な解決策を掘り下げる前に、基本から始めましょう。問題はデバイスにあるのではなく、Apple のサーバーがダウンしている可能性があります。 Apple のシステム ステータス ページにアクセスして、AppStore が適切に動作しているかどうかを確認してください。問題があれば、Apple が修正してくれるのを待つしかありません。インターネット接続を確認します。「AppStore に接続できません」問題は接続不良が原因である場合があるため、安定したインターネット接続があることを確認してください。 Wi-Fi とモバイル データを切り替えるか、ネットワーク設定をリセットしてみてください ([一般] > [リセット] > [ネットワーク設定のリセット] > [設定])。 iOS バージョンを更新します。

php提交表单通过后,弹出的对话框怎样在当前页弹出,该如何解决 php提交表单通过后,弹出的对话框怎样在当前页弹出,该如何解决 Jun 13, 2016 am 10:23 AM

php提交表单通过后,弹出的对话框怎样在当前页弹出php提交表单通过后,弹出的对话框怎样在当前页弹出而不是在空白页弹出?想实现这样的效果:而不是空白页弹出:------解决方案--------------------如果你的验证用PHP在后端,那么就用Ajax;仅供参考:HTML code

See all articles