Full Code of kookxiang/Tieba_Sign for AI

reborn 906f2cf15387 cached
89 files
275.3 KB
94.7k tokens
347 symbols
1 requests
Download .txt
Showing preview only (329K chars total). Download the full file or copy to clipboard to get everything.
Repository: kookxiang/Tieba_Sign
Branch: reborn
Commit: 906f2cf15387
Files: 89
Total size: 275.3 KB

Directory structure:
gitextract_mw9r9d_v/

├── README.md
├── admin.php
├── ajax.php
├── api.php
├── config.yaml
├── index.php
├── install/
│   ├── index.php
│   ├── install.sql
│   ├── openshift.php
│   └── sae.php
├── member.php
├── plugin.php
├── plugins/
│   ├── cloud_stat/
│   │   ├── cloud_stat.cron.php
│   │   ├── index.inc.php
│   │   └── plugin.class.php
│   ├── debug_info/
│   │   └── plugin.class.php
│   ├── register_limit/
│   │   └── plugin.class.php
│   ├── stat/
│   │   └── plugin.class.php
│   └── xxx_post/
│       ├── c_daily.cron.php
│       ├── c_first.cron.php
│       ├── c_se.cron.php
│       ├── c_sxbk.cron.php
│       ├── core.php
│       ├── index.php
│       ├── main.js
│       └── plugin.class.php
├── robots.txt
├── system/
│   ├── class/
│   │   ├── cache.php
│   │   ├── cloud.php
│   │   ├── core.php
│   │   ├── db.php
│   │   ├── hook.php
│   │   ├── kerror.php
│   │   ├── mail/
│   │   │   ├── phpmail.php
│   │   │   ├── saemail.php
│   │   │   └── smtp.php
│   │   ├── mail.php
│   │   ├── multithread.php
│   │   ├── plugin.php
│   │   ├── updater.php
│   │   ├── widget/
│   │   │   └── widget_password.php
│   │   └── xmlparse.php
│   ├── common.inc.php
│   └── function/
│       ├── cache/
│       │   ├── cache_plugin.php
│       │   ├── cache_plugins.php
│       │   ├── cache_setting.php
│       │   └── cache_username.php
│       ├── core.php
│       ├── member.php
│       ├── sae.php
│       ├── sign.php
│       └── updater/
│           ├── 1.13.php
│           ├── 1.14.1.15.php
│           ├── 1.14.1.16.php
│           ├── 1.14.1.23.php
│           ├── 1.14.2.6.php
│           ├── 1.14.4.12.php
│           ├── 1.14.4.14.php
│           ├── 1.14.4.24.php
│           ├── 1.14.5.12.php
│           ├── 1.14.5.20.php
│           ├── 1.14.5.27.php
│           ├── 1.14.6.2.php
│           ├── 1.16.6.23.php
│           └── fallback.php
└── template/
    └── default/
        ├── admin.php
        ├── index.php
        ├── js/
        │   ├── admin.js
        │   ├── fwin.js
        │   ├── kk_dropdown.js
        │   ├── main.js
        │   └── member.js
        ├── member.php
        ├── message.php
        ├── mobile/
        │   └── message.php
        ├── style/
        │   └── main.css
        ├── template.xml
        └── widget/
            ├── bind_status.php
            ├── find_password.php
            ├── footer.php
            ├── guide.php
            ├── header.php
            ├── liked_tieba.php
            ├── login.php
            ├── meta.php
            ├── register.php
            ├── setting.php
            ├── sidebar.php
            └── sign_log.php

================================================
FILE CONTENTS
================================================

================================================
FILE: README.md
================================================
# Tieba Sign
Front-end environment for TiebaSign-Backend services, which provides faster auto-sign experience in http://tieba.baidu.com and can handle much more user at the same time.

This front-end project only provides basic registration / management / log view features.
Signing features was not included in this project.

## WARNING
You cannot use these code in your own server.
It required a closed source server-side application which was powered by Go.

这份代码不能直接部署到服务器上,因为还需要一个 Go 语言的服务端程序才可以正常运行(不开源)。

If you want to deploy a server, please use the [old branch](https://github.com/kookxiang/Tieba_Sign/tree/master).

如果你想搭建贴吧签到助手,请使用 [老版本](https://github.com/kookxiang/Tieba_Sign/tree/master).


================================================
FILE: admin.php
================================================
<?php
define('IN_ADMINCP', true);
define('DISABLE_PLUGIN', true);
require_once './system/common.inc.php';
if(!is_admin($uid)) exit();
$formhash = substr(md5(substr(TIMESTAMP, 0, -7).$username.$uid.SYS_KEY.ROOT.'ADMINCP_ONLY'), 5, 14);

switch($_GET['action']){
	case 'load_userstat':
		$data = array();
		$date = date('Ymd');
		$query = DB::query('SELECT uid, username FROM member ORDER BY uid');
		while($result = DB::fetch($query)){
			$_uid = $result['uid'];
			$data[$_uid] = $result;
			$data[$_uid]['succeed'] = 0;
			$data[$_uid]['skiped'] = 0;
			$data[$_uid]['waiting'] = 0;
			$data[$_uid]['retry'] = 0;
			$data[$_uid]['unsupport'] = 0;
		}
		$query = DB::query("SELECT uid, COUNT(*) AS num FROM `sign_log` WHERE date='{$date}' AND `status`=2 GROUP BY uid");
		while($result = DB::fetch($query)){
			$_uid = $result['uid'];
			$data[$_uid]['succeed'] = $result['num'];
		}
		$query = DB::query("SELECT uid, COUNT(*) AS num FROM `sign_log` WHERE date='{$date}' AND `status`=0 GROUP BY uid");
		while($result = DB::fetch($query)){
			$_uid = $result['uid'];
			$data[$_uid]['waiting'] = $result['num'];
		}
		$query = DB::query("SELECT uid, COUNT(*) AS num FROM `sign_log` WHERE date='{$date}' AND `status`=1 GROUP BY uid");
		while($result = DB::fetch($query)){
			$_uid = $result['uid'];
			$data[$_uid]['retry'] = $result['num'];
		}
		$query = DB::query("SELECT uid, COUNT(*) AS num FROM `sign_log` WHERE date='{$date}' AND `status`=-1 GROUP BY uid");
		while($result = DB::fetch($query)){
			$_uid = $result['uid'];
			$data[$_uid]['unsupport'] = $result['num'];
		}
		$query = DB::query("SELECT uid, COUNT(*) AS num FROM `sign_log` WHERE date='{$date}' AND `status`=-2 GROUP BY uid");
		while($result = DB::fetch($query)){
			$_uid = $result['uid'];
			$data[$_uid]['skiped'] = $result['num'];
		}
		exit(json_encode($data));
	case 'load_user':
		$data = array();
		$query = DB::query('SELECT uid, username, email FROM member ORDER BY uid');
		while($result = DB::fetch($query)){
			$result['email'] = htmlspecialchars($result['email']);
			$data[] = $result;
		}
		exit(json_encode($data));
		break;
	case 'load_setting':
		$data = CACHE::get('setting');
		unset($data['SYS_KEY']);
		exit(json_encode($data));
		break;
	case 'save_setting':
		if($formhash != $_POST['formhash']) showmessage('来源不可信,请重试', 'admin.php#setting');
		if(defined('AFENABLED')){
			saveSetting('admin_uid', $_POST['admin_uid']);
		}
		saveSetting('account_switch', ($_POST['account_switch'] ? 1 : 0));
		saveSetting('register_limit', ($_POST['register_limit'] ? 1 : 0));
		saveSetting('register_check', ($_POST['register_check'] ? 1 : 0));
		saveSetting('autoupdate', ($_POST['autoupdate'] ? 1 : 0));
		saveSetting('block_register', ($_POST['block_register'] ? 1 : 0));
		saveSetting('invite_code', stripslashes(daddslashes($_POST['invite_code'])));
		saveSetting('beian_no', stripslashes(daddslashes(htmlspecialchars($_POST['beian_no']))));
		saveSetting('jquery_mode', $_POST['jquery_mode']);
		saveSetting('max_tieba', intval($_POST['max_tieba']));
		saveSetting('extra_title', stripslashes(daddslashes(htmlspecialchars($_POST['extra_title']))));
		showmessage('设置已经保存☆Kira~', 'admin.php#setting', 2);
		break;
	case 'deluser':
		$_uid = intval($_GET['uid']);
		if($uid == $_uid) showmessage('删你自己的号是要作死啊?!', 'admin.php#user');
		if($formhash != $_GET['formhash']) showmessage('来源不可信,请重试', 'admin.php#user');
		delete_user($_uid);
		showmessage('删除用户成功', 'admin.php#user', 1);
		break;
	case 'update_liked_tieba':
		$_uid = intval($_GET['uid']);
		if($formhash != $_GET['formhash']) showmessage('来源不可信,请重试', 'admin.php#user');
		update_liked_tieba($_uid);
		list($insert, $deleted) = update_liked_tieba($_uid);
		showmessage("喜欢的贴吧列表已经更新,<br>新增{$insert}个贴吧, 删除{$deleted}个贴吧", 'admin.php#user', 1);
		break;
	case 'reset_failure':
		$_uid = intval($_GET['uid']);
		if($formhash != $_GET['formhash']) showmessage('来源不可信,请重试', 'admin.php#stat');
		$date = date('Ymd');
		DB::query("UPDATE sign_log SET status='0', retry='0' WHERE uid='{$_uid}' AND date='{$date}' AND status<0");
		showmessage('已经重置,稍后系统将自动重试', 'admin.php#stat', 1);
		break;
	case 'reset_failure_all':
		if(!defined('AFENABLED')) exit();
		if($formhash != $_GET['formhash']) showmessage('来源不可信,请重试', 'admin.php#stat');
		$date = date('Ymd');
		DB::query("UPDATE sign_log SET status='0', retry='0' WHERE date='{$date}' AND status<0");
		showmessage('已经重置,稍后系统将自动重试', 'admin.php#stat', 1);
		break;
	case 'mail_setting':
		if($formhash != $_POST['formhash']) showmessage('来源不可信,请重试', 'admin.php#setting');
		$classes = getClasses();
		$class = $_POST['mail_sender'];
		if(!$classes[$class]) showmessage('选择的邮件发送方式不正确.', 'admin.php#setting');
		if(!$classes[$class]->isAvailable()) showmessage('选择的邮件发送方式不可用.', 'admin.php#setting');
		saveSetting('mail_class', $class);
		showmessage('保存成功<br>(请确认高级设置配置有效)', 'admin.php#setting');
		break;
	case 'mail_advanced':
		$classes = getClasses();
		$class = getSetting('mail_class');
		$obj = $classes[$class];
		if(!$obj) showmessage('选择的邮件发送方式不正确.', 'admin.php#setting');
		if(!$obj->isAvailable()) showmessage('选择的邮件发送方式不可用.', 'admin.php#setting');
		$_config = $obj->config;
		if($_POST['formhash'] == $formhash){
			foreach($_config as $k=>$v){
				$key = $v[1];
				$value = daddslashes($_POST[$key]);
				saveSetting("_mail_{$class}_{$key}", $value);
			}
			CACHE::save("mail_{$class}", '');
			showmessage('保存成功!', 'admin.php#setting');
		}
		$out = array();
		$setting = array();
		$query = DB::query("SELECT * FROM setting WHERE k LIKE '_mail_{$class}_%'");
		while($result = DB::fetch($query)){
			$key = str_replace("_mail_{$class}_", '', $result['k']);
			$setting[$key] = $result['v'];
		}
		foreach($_config as $k=>$v){
			$key = $v[1];
			$item = array(
				'key' => $v[1],
				'name' => $v[0],
				'description' => $v[2],
				'value' => isset($setting[$key]) ? $setting[$key] : $v[3],
				'type' => $v[4] ? $v[4] : 'text',
			);
			$out[] = $item;
		}
		echo json_encode($out);
		break;
	case 'switch_channel':
		if($formhash != $_GET['formhash']) showmessage('来源不可信,请重试', 'admin.php#updater');
		$channel = $_GET['channel'];
		if($channel != 'dev' && $channel != 'stable') showmessage('未知分支ID', 'admin.php#updater');
		saveSetting('channel', $channel);
		showmessage('分支切换成功.', 'admin.php#updater#');
	case 'install_plugin':
		if($formhash != $_GET['formhash']) showmessage('来源不可信,请重试', 'admin.php#plugin');
		require_once SYSTEM_ROOT.'./class/plugin.php';
		$plugin_id = $_GET['pluginid'];
		if(preg_match('/[^A-Za-z0-9_-.]/', $plugin_id)) showmessage('插件ID不合法,请与插件作者联系', 'admin.php#plugin');
		$classfile = ROOT.'./plugins/'.$plugin_id.'/plugin.class.php';
		if(!file_exists($classfile)) showmessage('插件文件缺失,请与插件作者联系', 'admin.php#plugin');
		require_once $classfile;
		$classname = "plugin_{$plugin_id}";
		if(!class_exists("plugin_{$plugin_id}", false)) showmessage('插件类不合规范,请与插件作者联系', 'admin.php#plugin');
		$obj = new $classname();
		$method_blacklist = array('__construct', '__destruct', $classname);
		foreach($method_blacklist as $method) if(method_exists($obj, $method)) showmessage('插件不符合性能要求规定,请与插件作者联系', 'admin.php#plugin');
		if ($obj instanceof Plugin){
			$obj->checkCompatibility();
			$compatibilityMode = false;
		}else{
			// 弹出旧版插件提示
			$compatibilityMode = true;
		}
		$version = 0;
		if(property_exists($obj, 'version')) $version = $obj->version;
		DB::insert('plugin', array('name' => $plugin_id, 'version' => $version, 'enable' => 0));
		CACHE::update('plugins');
		if($compatibilityMode){
			if(method_exists($obj, 'on_install')) $obj->on_install();
		}else{
			$obj->install();
		}
		showmessage('安装插件成功!', 'admin.php#plugin#');
	case 'uninstall_plugin':
		if($formhash != $_GET['formhash']) showmessage('来源不可信,请重试', 'admin.php#plugin');
		$plugin_id = $_GET['pluginid'];
		if(preg_match('/[^A-Za-z0-9_-.]/', $plugin_id)) showmessage('插件ID不合法,请与插件作者联系', 'admin.php#plugin');
		DB::query("DELETE FROM `plugin` WHERE name='{$plugin_id}'");
		DB::query("DELETE FROM plugin_var WHERE pluginid='".addslashes($plugin_id)."'");
		$classfile = ROOT.'./plugins/'.$plugin_id.'/plugin.class.php';
		if(file_exists($classfile)){
			require_once $classfile;
			$classname = "plugin_{$plugin_id}";
			if(class_exists("plugin_{$plugin_id}", false)){
				$obj = new $classname();
				if ($obj instanceof Plugin){
					$compatibilityMode = false;
				}else{
					$compatibilityMode = true;
				}
				if(property_exists($obj, 'modules')){
					foreach($obj->modules as $module){
						if($module['type'] == 'cron'){
							DB::query("DELETE FROM cron WHERE id='".$module['cron']['id']."'");
						}
					}
				}
				if($compatibilityMode){
					if(method_exists($obj, 'on_uninstall')) $obj->on_uninstall();
				}else{
					$obj->uninstall();
				}
			}
		}
		CACHE::update('plugin');
		CACHE::update('plugins');
		showmessage('卸载插件成功!', 'admin.php#plugin#');
	case 'enable_plugin':
		if($formhash != $_GET['formhash']) showmessage('来源不可信,请重试', 'admin.php#plugin');
		$plugin_id = $_GET['pluginid'];
		if(preg_match('/[^A-Za-z0-9_-.]/', $plugin_id)) showmessage('插件ID不合法,请与插件作者联系', 'admin.php#plugin');
		DB::query("UPDATE `plugin` SET `enable`=1 WHERE name='{$plugin_id}'");
		$classname = "plugin_{$plugin_id}";
		$obj = new $classname();
		$method_blacklist = array('__construct', '__destruct', $classname);
		foreach($method_blacklist as $method) if(method_exists($obj, $method)) showmessage('插件不符合性能要求规定,请与插件作者联系', 'admin.php#plugin');
		if (property_exists($obj, 'modules')){
			foreach($obj->modules as $module){
				if($module['type'] == 'cron'){
					DB::insert('cron', array_merge($module['cron'], array('nextrun' => TIMESTAMP)), false, true);
				}
			}
		}
		CACHE::update('plugins');
		showmessage('启用插件成功!', 'admin.php#plugin#');
	case 'update_check':
		$ret = Updater::check();
		if(is_array($ret)){
			$return = array(
				'status' => 1,
				'files' => $ret,
				);
		}else{
			$return = array(
				'status' => $ret,
				'files' => array(),
				);
		}
		echo json_encode($return);
		exit();
	case 'get_file':
		echo json_encode(Updater::loop());
		exit();
	case 'write_file':
		echo json_encode(Updater::write_file());
		exit();
	case 'disable_plugin':
		if($formhash != $_GET['formhash']) showmessage('来源不可信,请重试', 'admin.php#plugin');
		$plugin_id = $_GET['pluginid'];
		if(preg_match('/[^A-Za-z0-9_-.]/', $plugin_id)) showmessage('插件ID不合法,请与插件作者联系', 'admin.php#plugin');
		DB::query("UPDATE `plugin` SET `enable`=0 WHERE name='{$plugin_id}'");
		$classname = "plugin_{$plugin_id}";
		$obj = new $classname ();
		if(property_exists ($obj, 'modules')){
			foreach($obj->modules as $module){
				if($module ['type'] == 'cron'){
					DB::query("DELETE FROM cron WHERE id='".$module['cron']['id']."'");
				}
			}
		}
		CACHE::update('plugins');
		showmessage('禁用插件成功!', 'admin.php#plugin#');
	case 'config_plugin':
		$plugin_id = $_REQUEST['pluginid'];
		if($_POST['submit'] && $formhash != $_GET['formhash']) showmessage('来源不可信,请重试', 'admin.php#plugin');
		if(preg_match('/[^A-Za-z0-9_-.]/', $plugin_id)) showmessage('插件ID不合法,请与插件作者联系', 'admin.php#plugin');
		$classfile = ROOT.'./plugins/'.$plugin_id.'/plugin.class.php';
		if(!file_exists($classfile)) showmessage('插件文件缺失,请与插件作者联系', 'admin.php#plugin');
		require_once $classfile;
		$classname = "plugin_{$plugin_id}";
		if(!class_exists("plugin_{$plugin_id}", false)) showmessage('插件类不合规范,请与插件作者联系', 'admin.php#plugin');
		$obj = new $classname();
		if(method_exists($obj, 'on_config')){
			echo json_encode(array('html' => $obj->on_config()));
		}else{
			echo json_encode(array('html' => '错误:该插件没有高级配置面板!'));
		}
		break;
	case 'eNaBlEaFc':
		if($formhash != $_GET['formhash']) showmessage('来源不可信,请重试', 'admin.php#setting');
		$text = pack('H*', strrev($_GET['hash']));
		if($text == 'ENABLE ADVANCED FETURES') saveSetting('AFENABLED', 1);
		showmessage('Advance fetures activated!', 'admin.php#setting', 1);
		break;
	case 'mail_test':
		if($formhash != $_GET['formhash']) showmessage('来源不可信,请重试', 'admin.php#setting');
		$to = DB::result_first("SELECT email FROM member WHERE uid='{$uid}'");
		$subject = '[贴吧签到助手] 邮件单发测试';
		$content = "<p>此封邮件仅用于检测邮件系统是否正常工作。</p><p>此封邮件是由邮件系统直接发送的</p>";
		$mail = new mail_content();
		$mail->address = $to;
		$mail->subject = $subject;
		$mail->message = $content;
		$sender = new mail_sender();
    	if($sender->sendMail($mail)){
            $subject = '[贴吧签到助手] 邮件群发测试';
            $content = "<p>此封邮件仅用于检测邮件队列是否正常工作。</p><p>此封邮件是从系统邮件队列中读取并发送的</p>";
            DB::insert('mail_queue', array(
                'to' => $to,
                'subject' => $subject,
                'content' => $content,
                ));
            saveSetting('mail_queue', 1);
            showmessage('2 封邮件已经发送,请查收', 'admin.php#setting', 2);
        }else showmessage('邮件发送失败,请检查设置后重试', 'admin.php#setting', 2);
		break;
	case 'send_mail':
		if($formhash != $_POST['formhash']) showmessage('来源不可信,请重试', 'admin.php#setting');
		$title = daddslashes($_POST['title']);
		$content = daddslashes($_POST['content']);
		$content = nl2br(htmlspecialchars($content));
		$content .= "<p style=\"padding: 1.5em 1em 0; color: #999; font-size: 12px;\">—— 本邮件由 贴吧签到助手 (<a href=\"{$siteurl}\">{$siteurl}</a>) 管理员发送</p>";
		$query = DB::query("SELECT email FROM member");
		while($result = DB::fetch($query)){
			DB::insert('mail_queue', array(
				'to' => $result['email'],
				'subject' => $title,
				'content' => $content,
				));
		}
		saveSetting('mail_queue', 1);
		showmessage('已经添加至邮件队列,稍后将由系统自动发送', 'admin.php#mail');
		break;
	case 'cloud_sync':
		$ret = cloud::sync();
		showmessage($ret ? '站点信息同步成功!' : '同步信息失败,请稍后再试', 'admin.php#setting');
		break;
	case 'load_plugin':
		exit(json_encode(getPlugins()));
		break;
	case 'load_template':
		exit(json_encode(getTemplates()));
		break;
	case 'load_cron':
		exit(json_encode(getCron()));
		break;
	case 'skip_cron':
		if(!defined('AFENABLED')) exit();
		if($formhash != $_GET['formhash']) showmessage('来源不可信,请重试', 'admin.php#cron');
		$cron_id = daddslashes($_GET['cid']);
		DB::query("UPDATE cron SET nextrun=nextrun+86400 WHERE id='{$cron_id}'");
		$time = TIMESTAMP;
		DB::query("UPDATE cron SET nextrun='{$time}'+3600 WHERE id='{$cron_id}' AND nextrun < '{$time}'");
		showmessage('计划任务修改成功', 'admin.php#cron');
		break;
	case 'clear_cron_cache':
		if(!defined('AFENABLED')) exit();
		if($formhash != $_GET['formhash']) showmessage('来源不可信,请重试', 'admin.php#cron');
		$nextrun = DB::fetch_first("SELECT nextrun FROM cron ORDER BY nextrun ASC LIMIT 0,1");
		saveSetting('next_cron', $nextrun ? $nextrun['nextrun'] : TIMESTAMP + 1200);
		showmessage('缓存已清除', 'admin.php#cron');
		break;
	case 'clear_cache':
		if(!defined('AFENABLED')) exit();
		if($formhash != $_GET['formhash']) showmessage('来源不可信,请重试', 'admin.php#cron');
		CACHE::clear();
		showmessage('缓存已清除', 'admin.php#cron');
		break;
	case 'clear_cron':
		if($formhash != $_GET['formhash']) showmessage('来源不可信,请重试', 'admin.php#cron');
		$query = DB::query("SELECT * FROM cron ORDER BY `order`");
		$deleted = 0;
		while($cron = DB::fetch($query)){
			list($pluginid, $cronscript) = explode('/', $cron['id'], 2);
			if($pluginid && $cronscript){
				$path = ROOT."./plugins/{$pluginid}/{$cronscript}.cron.php";
			}else{
				$path = SYSTEM_ROOT."./function/cron/{$cron[id]}.php";
			}
			if(!file_exists($path)){
				DB::query("DELETE FROM cron WHERE id='".addslashes($cron['id'])."'");
				$deleted++;
			}
		}
		showmessage("共清理了 {$deleted} 个无效的计划任务");
		break;
	case 'set_template':
		if($formhash != $_GET['formhash']) showmessage('来源不可信,请重试', 'admin.php#plugin');
		if(preg_match('/[^A-Za-z0-9_-.]/', $_GET['template'])) showmessage('模板ID(文件夹名)不合法,请与模板作者联系', 'admin.php#template');
		$templatefile = ROOT.'./template/'.$_GET['template'].'/template.xml';
		if (file_exists($templatefile)) {
			$info = xml2array(file_get_contents($templatefile));
			if(!$info || !$info['target_version'] || !is_array($info['target_version']) || $info['ui_version']!=UI_VERSION) showmessage('此模板不兼容当前版本', 'admin.php#template');
			saveSetting('template', daddslashes($_GET['template']));
			if(!in_array(VERSION, $info['target_version'])) showmessage('模板切换成功!<br>注:此风格不适宜当前版本,可能有轻微错位.', 'admin.php#template#');
			showmessage('模板切换成功!', 'admin.php#template#');
		}
		else showmessage('非法操作!', 'admin.php#template');
		break;
	default:
		$classes = getClasses();
		if(getSetting('next_cron') < TIMESTAMP - 7200) define('CRON_ERROR', true);
		include template('admin');
		break;
}
function getClasses(){
	$handle = opendir(SYSTEM_ROOT.'./class/mail/');
	$classes = array();
	while (1){
		$file = readdir($handle);
		if (!$file) break;
		if (strexists($file, '.php')){
			$classname = str_replace('.php', '', $file);
			require_once SYSTEM_ROOT."./class/mail/{$classname}.php";
			$obj = new $classname();
			$classes[$obj->id] = $obj;
		}
	}
	return $classes;
}
function getPlugins(){
	$handle = opendir(ROOT.'./plugins/');
	$plugins = $new_plugins = $installed = array();
	$query = DB::query('SELECT name FROM plugin');
	while($row = DB::fetch($query)) $installed[] = $row['name'];
	while (1){
		$folder = readdir($handle);
		if (!$folder) break;
		if ($folder == '.' || $folder == '..') continue;
		$classfile = ROOT.'./plugins/'.$folder.'/plugin.class.php';
		if(!file_exists($classfile)) continue;
		require_once $classfile;
		$classname = "plugin_{$folder}";
		if(!class_exists("plugin_{$folder}", false)) continue;
		$obj = new $classname();
		$arr = array('id' => $folder, 'description' => $obj->description, 'config' => method_exists($obj, 'on_config'), 'enabled' => is_plugin_enabled($folder), 'version' => getPluginVersion($folder), 'installed' => in_array($folder, $installed));
		if($arr['installed']){
			$plugins[] = $arr;
		}else{
			$new_plugins[] = $arr;
		}
	}
	return array_merge($plugins, $new_plugins);
}
function getTemplates(){
	$handle = opendir(ROOT.'./template/');
	$templates = array();
	$current_template = getSetting('template');
	if(empty($current_template)) $current_template = 'default';
	while (true){
		$folder = readdir($handle);
		if (!$folder) break;
		if ($folder == '.' || $folder == '..') continue;
		$infofile = ROOT."./template/{$folder}/template.xml";
		if(!file_exists($infofile)) continue;
		$info = xml2array(file_get_contents($infofile));
		$templates[] = array(
			'id' => $folder,
			'name' => !empty($info['name'])? htmlspecialchars($info['name']) : '未知模板',
			'author' => !empty($info['author'])? htmlspecialchars($info['author']) : '佚名',
			'version' => !empty($info['version'])? htmlspecialchars($info['version']) : '0.0.0',
			'site' => !empty($info['site'])? htmlspecialchars($info['site']) : 'http://www.kookxiang.com',
			'preview' => (empty($info['preview']) || !file_exists(ROOT."./template/{$folder}/{$info['preview']}")) ?  "template/default/nopreview.png" : "template/{$folder}/{$info['preview']}",
			'current' => $folder == $current_template,
		);
	}
	return $templates;
}
function getCron(){
	$query = DB::query("SELECT * FROM cron ORDER BY `order`");
	$system_cron = $plugin_cron = array();
	while($cron = DB::fetch($query)){
		unset($cron['enabled']);
		$cron['_id'] = $cron['id'];
		$cron['nextrun'] = $cron['nextrun'] - TIMESTAMP;
		list($pluginid, $cronscript) = explode('/', $cron['id'], 2);
		if($pluginid && $cronscript){
			$cron['id'] = "{$cronscript}.cron.php";
			$cron['type'] = "插件 {$pluginid} 任务";
			$plugin_cron[] = $cron;
		}else{
			$cron['id'] = "{$cron[id]}.php";
			$cron['type'] = "系统内置任务";
			$system_cron[] = $cron;
		}
	}
	return array_merge($system_cron, $plugin_cron);
}
function is_plugin_enabled($pluginid){
	static $enabled_plugin;
	if(!isset($enabled_plugin)){
		$enabled_plugin = array();
		$arr = CACHE::get('plugins');
		foreach($arr as $plugin){
			$enabled_plugin[] = $plugin['id'];
		}
	}
	return in_array($pluginid, $enabled_plugin);
}
function getPluginVersion($pluginid){
	static $plugin_version;
	if(!isset($plugin_version)){
		$plugin_version = array();
		$query = DB::query("SELECT name, version FROM `plugin`");
		while($result = DB::fetch($query)){
			$plugin_version[ $result['name'] ] = $result['version'];
		}
	}
	return $plugin_version[$pluginid] ? $plugin_version[$pluginid] : 0;
}


================================================
FILE: ajax.php
================================================
<?php
require_once './system/common.inc.php';
if(!$uid) exit('Access Denied');

$data = array();
switch($_GET['v']){
	case 'liked_tieba':
		$query = DB::query("SELECT * FROM my_tieba WHERE uid='{$uid}'");
		while($result = DB::fetch($query)){
			$data[] = $result;
		}
		break;
	case 'get-bind-status':
		$data = get_baidu_userinfo($uid);
		if($data['data']['user_portrait']) dsetcookie("avatar_{$uid}", 'https://ss0.bdstatic.com/7Ls0a8Sm1A5BphGlnYG/sys/portrait/item/'.$data['data']['user_portrait']);
		break;
	case 'get-setting':
		$data = get_setting($uid);
		break;
	case 'sign-log':
		$date = date('Ymd');
		$data['date'] = date('Y-m-d');
	case 'sign-history':
		if($_GET['v'] == 'sign-history'){
			$date = intval($_GET['date']);
			$data['date'] = substr($date, 0, 4).'-'.substr($date, 4, 2).'-'.substr($date, 6, 2);
		}
		$data['log'] = array();
		$query = DB::query("SELECT * FROM sign_log l LEFT JOIN my_tieba t ON t.tid=l.tid WHERE l.uid='{$uid}' AND l.date='{$date}'");
		while($result = DB::fetch($query)){
			$data['log'][] = $result;
		}
		$data['count'] = count($data['log']);
		$data['before_date'] = DB::result_first("SELECT date FROM sign_log WHERE uid='{$uid}' AND date<'{$date}' ORDER BY date DESC LIMIT 0,1");
		$data['after_date'] = DB::result_first("SELECT date FROM sign_log WHERE uid='{$uid}' AND date>'{$date}' ORDER BY date ASC LIMIT 0,1");
		break;
}
echo json_encode($data);

================================================
FILE: api.php
================================================
<?php
define('DISABLE_PLUGIN', true);
require_once './system/common.inc.php';

if(!$uid){
	header('Location: member.php');
	exit();
}

if($_GET['action'] == 'baidu_login'){
	$parms = array($_POST['username'], $_POST['password'], $formhash);
	$parm_string = serialize($parms);
	$parm_string = authcode($parm_string, 'ENCODE', cloud::key());
	$parm_string = bin2hex($parm_string);
	header('Location: '.cloud::get_api_path().'login.php?sid='.cloud::id().'&parm='.$parm_string);
}elseif($_GET['action'] == 'register_cloud'){
	cloud::do_register();
}elseif($_GET['action'] == 'receive_cookie'){
	$_cookie = $_POST['cookie'] ? $_POST['cookie'] : $_GET['cookie'];
	if(!$_cookie) throw new Exception('Empty response!');
	if($_GET['formhash'] != $formhash) throw new Exception('Illegal request!');
    if ($_GET['local']) {
        $cookie = $_cookie;
    } else {
        $cookie = authcode(pack('H*', $_cookie), 'DECODE', cloud::key());
    }
	if(!$cookie) showmessage('非法调用!', './#baidu_bind', 1);
    if (!verify_cookie($cookie)) showmessage('无法登陆百度贴吧,请尝试重新绑定' . ($_GET['local'] ? '' : '<form action="api.php?action=receive_cookie&formhash=' . $formhash . '" method="post"><input type="hidden" name="cookie" value="' . $_cookie . '"></from><script type="text/javascript">setTimeout(function(){ document.forms[0].submit(); }, 2000);</script>'));
	save_cookie($uid, $cookie);
	showmessage('绑定百度账号成功!<br>正在同步喜欢的贴吧...<script type="text/javascript" src="index.php?action=refresh_liked_tieba&formhash='.$formhash.'"></script><script type="text/javascript">try{ opener.$("#guide_page_2").hide(); opener.$("#guide_page_manual").hide(); opener.$("#guide_page_3").show(); window.close(); }catch(e){}</script>', './#baidu_bind', 1);
}

?>

================================================
FILE: config.yaml
================================================
---
name: appid
version: 1

cron:
- description: SignTask
  url: cron.php
  schedule: */1 * * * *

handle:
- expire: if( path ~ "css" ) time 864000
- expire: if( path ~ "png" ) time 864000
- compress: if ( out_header["Content-Length"]>=512 ) compress


================================================
FILE: index.php
================================================
<?php
require_once './system/common.inc.php';

if(!$uid){
	header('Location: member.php');
	exit();
}elseif($_GET['action']){
	switch($_GET['action']){
		case 'skip_tieba':
			if($_GET['formhash'] != $formhash) break;
			$tid = intval($_GET['tid']);
			$skiped = DB::result_first("SELECT skiped FROM my_tieba WHERE uid='{$uid}' AND tid='{$tid}'");
			$skiped = $skiped ? 0 : 1;
			$date = date('Ymd', TIMESTAMP+900);
			if($skiped == 1){
				DB::query("UPDATE sign_log SET `status`='-2' WHERE uid='{$uid}' AND tid='{$tid}' AND date='{$date}' AND `status` < 2");
			}else{
				DB::query("UPDATE sign_log SET `status`='0' WHERE uid='{$uid}' AND tid='{$tid}' AND date='{$date}' AND `status` < 2");
			}
			DB::query("UPDATE my_tieba SET skiped='{$skiped}' WHERE uid='{$uid}' AND tid='{$tid}'");
			if(!DB::affected_rows()) showmessage('发生未知错误: 无法修改贴吧设置');
			showmessage('修改签到设置成功!');
		case 'clear_cookie':
			if($_GET['formhash'] != $formhash) break;
			DB::query("UPDATE member_setting SET cookie='' WHERE uid='{$uid}'");
			DB::query("DELETE FROM my_tieba WHERE uid='{$uid}'");
			DB::query("DELETE FROM sign_log WHERE uid='{$uid}'");
			showmessage('已经解除百度账号绑定<br>您可以稍后重新进行绑定', './#baidu_bind#', 1);
		case 'update_cookie':
			if(!$_POST['cookie']) break;
			$cookie = daddslashes($_POST['cookie']);
			if(!preg_match('/BDUSS=(.+?)/', $cookie)) showmessage('Cookie 信息不完整,请尝试重新获取', './#baidu_bind', 1);
			if(!preg_match('/BAIDUID=(.+?)/', $cookie)) showmessage('Cookie 信息不完整,请尝试重新获取', './#baidu_bind', 1);
			if(!verify_cookie($cookie)) showmessage('无法登陆百度贴吧,请检查 Cookie 是否填写正确', './#baidu_bind', 1);
			$cookie = daddslashes($cookie);
			save_cookie($uid, $cookie);
			showmessage('您的 Cookie 信息已经更新<script type="text/javascript" src="?action=refresh_liked_tieba&formhash='.$formhash.'"></script>', './#baidu_bind', 1);
			break;
		case 'update_setting':
			if($_POST['formhash'] != $formhash) break;
			DB::update('member_setting', array(
				'error_mail' => $_POST['error_mail'] ? 1 : 0,
				'send_mail' => $_POST['send_mail'] ? 1 : 0,
				'zhidao_sign' => $_POST['zhidao_sign'] ? 1 : 0,
				'wenku_sign' => $_POST['wenku_sign'] ? 1 : 0,
				), "uid='{$uid}'");
			CACHE::save('user_setting_'.$uid, '');
			showmessage('设置已经保存', './#setting', 1);
			break;
		case 'change_password':
			if($_POST['formhash'] != $formhash) break;
			$user = DB::fetch_first("SELECT * FROM member WHERE uid='{$uid}'");
			if(!$_POST['old_password']) showmessage('请输入旧密码', './#setting', 1);
			if(!$_POST['new_password']) showmessage('请输入新密码', './#setting', 1);
			if($_POST['new_password'] != $_POST['new_password2']) showmessage('两次输入的新密码不一样,请检查', './#setting', 1);
			if(!Widget_Password::verify($user, $_POST['old_password'])) showmessage('旧密码错误!请检查输入', './#setting', 1);
			$newpassword = Widget_Password::encrypt($user, $_POST['new_password']);
			DB::update('member', array('password' => $newpassword), "uid='{$uid}'");
			HOOK::run('change_password', true, $uid);
			showmessage('您的密码已经更新', './#setting', 1);
			break;
		case 'reset_failure':
			if($formhash != $_GET['formhash']) showmessage('请稍候...', '?action=reset_failure&formhash='.$formhash, 0);
			$date = date('Ymd');
			DB::query("UPDATE sign_log SET status='0', retry='0' WHERE uid='{$uid}' AND date='{$date}' AND status<0");
			showmessage('已经重置失败状态,稍后系统将自动重试', './#signlog', 1);
			break;
		case 'refresh_liked_tieba':
			if($formhash != $_GET['formhash']) showmessage('刷新中,请稍候...', '?action=refresh_liked_tieba&formhash='.$formhash, 0);
			list($insert, $deleted) = update_liked_tieba($uid);
			showmessage("喜欢的贴吧列表已经更新,<br>新增{$insert}个贴吧, 删除{$deleted}个贴吧", './#liked_tieba', 1);
			break;
	}
	header('Location: ./');
	exit();
}

if($_GET['ignore_update']){
	dsetcookie('ignore_update', '1', 7200);
	exit();
}elseif(is_admin($uid) && !$_COOKIE['ignore_update']){
	if(getSetting('new_version')) define('NEW_VERSION', true);
}

if(getSetting('account_switch')){
	// Multi User Support
	$query = DB::query("SELECT * FROM member_bind WHERE uid='{$uid}'");
	$users = array();
	while($result = DB::fetch($query)){
		$users[ $result['_uid'] ] = $result['username'];
	}
}

include template('index');

================================================
FILE: install/index.php
================================================
<?php
error_reporting(E_ERROR | E_PARSE);
$config_file = dirname(__FILE__).'/../system/config.inc.php';
include_once $config_file;
if($_config){
	header('Location: ..');
	exit();
}

@touch($config_file);

// MySQLi Support
if (!function_exists('mysql_connect') && function_exists('mysqli_connect')) {
    function mysql_connect($server = 'localhost', $username = 'root', $password = '', $new_link = false, $client_flags = 0) {
        return mysqli_connect($server, $username, $password, '');
    }
    function mysql_insert_id($link = null) {
        return mysqli_insert_id($link);
    }
    function mysql_select_db($db_name, $link = null) {
        return mysqli_select_db($link, $db_name);
    }
    function mysql_query($db_name, $link = null) {
        return mysqli_query($link, $db_name);
    }
    function mysql_error($link = null) {
        return mysqli_error($link);
    }
    function mysql_errno($link = null) {
        return mysqli_errno($link);
    }
}

switch($_GET['step']){
	default:
		if(defined('SAE_ACCESSKEY')){
			header('Location: sae.php');
			exit();
		}elseif(getenv('OPENSHIFT_APP_NAME')){
			$extra_script = '<script type="text/javascript">if(confirm("要使用 OpenShift 一键安装向导吗?")) location.href="openshift.php";</script>';
		}
		$content = '<p>欢迎使用 贴吧签到助手 安装向导!</p><p>本程序将会指引你在服务器上配置好“贴吧签到助手”</p><p>点击右侧的“下一步”按钮开始</p><p class="btns"><button onclick="location.href=\'./?step=check\';">下一步 &raquo;</button>';
		show_install_page('Welcome', $content);
		break;
	case 'check':
		$content = '<p>安装前,程序需要检查当前的服务器环境是否允许运行“贴吧签到助手”</p><p>请确保表格中每一行均为绿色,以避免可能带来的问题</p><table><thead><tr><td>项目</td><td>要求</td><td>当前状态</td></tr></thead><tbody>';
		$content .= '<tr><td>PHP 版本</td><td><span class="status on">5.2</span></td><td><span class="status '.(version_compare('5.2.0', PHP_VERSION, '<') ? 'on' : 'off').'">'.PHP_VERSION.'</span></td></tr>';
		$content .= '<tr><td>PHP: allow_url_fopen</td><td>'.show_status(true).'</td><td>'.show_status(ini_get('allow_url_fopen')).'</td></tr>';
		$content .= '<tr><td>CURL</td><td>'.show_status(true).'</td><td>'.show_status(function_exists('curl_init')).'</td></tr>';
		$content .= '<tr><td>Socket 连接</td><td>'.show_status(true).'</td><td>'.show_status(function_exists('fsockopen') || function_exists('pfsockopen')).'</td></tr>';
		$content .= '<tr><td>system/config.inc.php</td><td>'.show_status(true, '可写').'</td><td>'.show_status(is_writable($config_file), '可写', '不可写').'</td></tr>';
		$content .= '</tbody></table>';
		if(function_exists('curl_init') && (function_exists('fsockopen') || function_exists('pfsockopen')) && is_writable($config_file)) $content .= '<br><p class="btns"><button onclick="location.href=\'./?step=database\';">下一步 &raquo;</button></p>';
		show_install_page('服务器兼容性检查', $content);
		break;
	case 'database':
		$content = '<div class="config"><p>请填写数据库连接信息</p><br>';
		$content .= '<form action="./?step=install" method="post" onsubmit="show_waiting();">';
		$content .= '<p><span>数据库服务器:</span><input type="text" name="db_server" value="localhost" /></p>';
		$content .= '<p><span>数据库端口:</span><input type="text" name="db_port" value="3306" /></p>';
		$content .= '<p><span>数据库用户名:</span><input type="text" name="db_username" value="root" /></p>';
		$content .= '<p><span>数据库密码:</span><input type="password" name="db_password" /></p>';
		$content .= '<p><span>数据库名:</span><input type="text" name="db_name" value="kk_sign" /></p>';
		if(function_exists('mysql_pconnect')) $content .= '<p><span>&nbsp;</span><label><input type="checkbox" name="pconnect" value="1" /> 保持与数据库服务器的连接</label></p>';
		$content .= '<br><p><span>管理员用户名:</span><input type="text" name="username" required /></p>';
		$content .= '<p><span>管理员密码:</span><input type="password" name="password" required /></p>';
		$content .= '<p><span>管理员邮箱:</span><input type="text" name="email" required /></p>';
		$content .= '<p class="btns"><span>&nbsp;</span><input type="submit" value="下一步 &raquo;" /></p>';
		$content .= '</form></div><div class="waiting hidden"><p>程序正在执行必要的安装步骤,请耐心等待...</p></div>';
		$content .= '<script type="text/javascript">function show_waiting(){ $(".config").hide(); $(".waiting").show(); }</script>';
		show_install_page('数据库配置', $content);
		break;
	case 'install':
		$db_host = $_POST['db_server'];
		$db_port = intval($_POST['db_port']);
		$db_username = $_POST['db_username'];
		$db_password = $_POST['db_password'];
		$db_name = $_POST['db_name'];
		$db_pconnect = isset($_POST['pconnect']);
		$function = $db_pconnect ? 'mysql_connect' : 'mysql_pconnect';
		$link = mysql_connect("{$db_host}:{$db_port}", $db_username, $db_password);
		if(!$link) show_back('数据库配置', '错误:无法连接数据库服务器!</p><p>'.mysql_error());
		$selected = mysql_select_db($db_name, $link);
		if(!$selected){
			// 尝试新建
			mysql_query("CREATE DATABASE `{$db_name}`", $link);
			$selected = mysql_select_db($db_name, $link);
			if(!$selected) show_back('数据库配置', '错误:指定的数据库不可用</p><p>'.mysql_error());
		}
		mysql_query("SET character_set_connection=utf8, character_set_results=utf8, character_set_client=binary");
		$syskey = random(32);
		$username = addslashes($_POST['username']);
		$password = md5($syskey.md5($_POST['password']).$syskey);
		$email = addslashes($_POST['email']);
		if(!$username || !$password || !$email) show_back('注册账号', '您输入的信息不完整');
		if(preg_match('/[<>\'\\"]/i', $username)) show_back('注册账号', '用户名中有被禁止使用的关键字');
		if(strlen($username) < 6) show_back('注册账号', '用户名至少要6个字符(即2个中文 或 6个英文),请修改');
		if(strlen($username) > 24) show_back('注册账号', '用户名过长,请修改');
		$install_script = file_get_contents(dirname(__FILE__).'/install.sql');
		preg_match('/version ([0-9a-z.]+)/i', $install_script, $match);
		$version = trim($match[1]);
		if(!$version) show_back('正在安装', '安装脚本有误,请重新上传');
		$err = runquery($install_script, $link);
		if($err) show_back('正在安装', '安装过程出现错误:</p><p>'.$err);
		mysql_query("INSERT INTO member SET username='{$username}', password='{$password}', email='{$email}'");
		$uid = mysql_insert_id($link);
		mysql_query("INSERT INTO member_setting SET uid='{$uid}', cookie=''");
		saveSetting('block_register', 1);
		saveSetting('jquery_mode', 2);
		saveSetting('admin_uid', $uid);
		saveSetting('SYS_KEY', $syskey);
		$_config = array(
			'version' => $version,
			'db' => array(
				'server' => $db_host,
				'port' => $db_port,
				'username' => $db_username,
				'password' => $db_password,
				'name' => $db_name,
				'pconnect' => $db_pconnect,
				),
			);
		$content = '<?php'.PHP_EOL.'/* Auto-generated config file */'.PHP_EOL.'$_config = ';
		$content .= var_export($_config, true).';'.PHP_EOL.'?>';
		file_put_contents($config_file, $content);
		$content = '<p>贴吧签到助手 已经成功安装!</p><p>要正常签到,请为脚本 cron.php 添加每分钟一次的计划任务。</p><p>系统默认关闭用户注册,如果有需要,请到后台启用用户注册功能。</p><br><p class="btns"><button onclick="location.href=\'../\';">登录 &raquo;</button>';
		show_install_page('安装成功', $content);
}

function show_back($title, $text){
	$content = '<p>'.$text.'</p>';
	$content .= '<br><p class="btns"><button onclick="history.back();">&laquo; 返回</button></p>';
	show_install_page($title, $content);
}

function show_install_page($title, $content){
	global $extra_script;
	$template = '<!DOCTYPE html><html><head><title>贴吧签到助手</title><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><meta name="HandheldFriendly" content="true" /><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" /><meta name="author" content="kookxiang" /><meta name="copyright" content="KK\'s Laboratory" /><link rel="shortcut icon" href="../favicon.ico" /><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /><meta name="renderer" content="webkit"><link rel="stylesheet" href="../template/default/style/main.css" type="text/css" /><link rel="stylesheet" href="../template/default/style/custom.css" type="text/css" /><style type="text/css">.status.on, .status.off { padding: 2px 0 2px 20px; } .status.on { color: #22dd33; background: url(../template/default/style/done.gif) no-repeat 1px 50%; } .status.off { color: #ff3344; background: url(../template/default/style/error.gif) no-repeat 1px 50%; } .main-box { max-width: 550px; top: 135px; } .main-content { text-align: left; font-size: 13px; } .config span { width: 100px; text-align:right; display:block; float: left; height: 30px; line-height: 30px; margin-right: 15px; } </style></head><body><div id="append_parent"><div class="loading-icon"><img src="../template/default/style/loading.gif" /> 载入中...</div></div><div class="wrapper" id="page_index"><h1>贴吧签到助手 - 安装向导</h1><div class="sidebar"></div><div class="main-content"><h2>{title}</h2>{content}</div></div><script src="//lib.sinaapp.com/js/jquery/1.10.2/jquery-1.10.2.min.js"></script><script src="../template/default/js/fwin.js"></script><script type="text/javascript">hideloading();</script>'.$extra_script.'</body></html>';
	echo str_replace(array('{title}', '{content}'), array($title, $content), $template);
	exit();
}

function show_status($status, $on_txt = 'On', $off_txt = 'Off'){
	return $status ? '<span class="status on">'.$on_txt.'</span>' : '<span class="status off">'.$off_txt.'</span>';
}

function runquery($sql, $link){
	$sql = str_replace("\r", "\n", $sql);
	foreach(explode(";\n", $sql) as $query) {
		$query = trim($query);
		if(!$query) continue;
		$ret = mysql_query($query, $link);
		if(!$ret) return mysql_error();
	}
}

function saveSetting($k, $v){
	global $link;
	$v = addslashes($v);
	mysql_query("REPLACE INTO setting SET v='{$v}', k='{$k}'", $link);
}

function random($length, $numeric = 0) {
	$seed = base_convert(md5(microtime().$_SERVER['DOCUMENT_ROOT']), 16, $numeric ? 10 : 35);
	$seed = $numeric ? (str_replace('0', '', $seed).'012340567890') : ($seed.'zZ'.strtoupper($seed));
	$hash = '';
	$max = strlen($seed) - 1;
	for($i = 0; $i < $length; $i++) {
		$hash .= $seed{mt_rand(0, $max)};
	}
	return $hash;
}

?>

================================================
FILE: install/install.sql
================================================
/*
 Install script for version 1.14.4.14
 */

DROP TABLE IF EXISTS `cache`;
DROP TABLE IF EXISTS `cron`;
DROP TABLE IF EXISTS `download`;
DROP TABLE IF EXISTS `mail_queue`;
DROP TABLE IF EXISTS `member`;
DROP TABLE IF EXISTS `member_bind`;
DROP TABLE IF EXISTS `member_setting`;
DROP TABLE IF EXISTS `my_tieba`;
DROP TABLE IF EXISTS `plugin`;
DROP TABLE IF EXISTS `plugin_var`;
DROP TABLE IF EXISTS `setting`;
DROP TABLE IF EXISTS `sign_log`;
DROP TABLE IF EXISTS `update_source`;

CREATE TABLE IF NOT EXISTS `cache` (
  `k` varchar(32) NOT NULL,
  `v` text NOT NULL,
  PRIMARY KEY (`k`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `cron` (
  `id` varchar(16) NOT NULL,
  `enabled` tinyint(1) NOT NULL,
  `nextrun` int(10) unsigned NOT NULL,
  `order` tinyint(4) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

INSERT INTO `cron` (`id`, `enabled`, `nextrun`, `order`) VALUES
('daily', 1, 0, 0),
('ext_sign', 1, 0, 50),
('mail', 1, 0, 100),
('sign', 1, 0, 20),
('sign_retry', 1, 0, 110),
('update_tieba', 1, 0, 10);

CREATE TABLE IF NOT EXISTS `download` (
  `path` varchar(128) NOT NULL,
  `content` text NOT NULL,
  PRIMARY KEY (`path`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `mail_queue` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `to` varchar(255) NOT NULL,
  `subject` varchar(255) NOT NULL,
  `content` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `member` (
  `uid` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(24) DEFAULT NULL,
  `password` varchar(32) NOT NULL,
  `email` varchar(32) NOT NULL,
  PRIMARY KEY (`uid`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `member_bind` (
  `uid` int(10) unsigned NOT NULL,
  `_uid` int(10) unsigned NOT NULL,
  `username` varchar(12) NOT NULL,
  KEY `uid` (`uid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `member_setting` (
  `uid` int(10) unsigned NOT NULL,
  `error_mail` tinyint(1) NOT NULL DEFAULT '1',
  `send_mail` tinyint(1) NOT NULL DEFAULT '0',
  `zhidao_sign` tinyint(1) NOT NULL DEFAULT '0',
  `wenku_sign` tinyint(1) NOT NULL DEFAULT '0',
  `cookie` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`uid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `my_tieba` (
  `tid` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `uid` int(10) unsigned NOT NULL,
  `fid` int(10) unsigned NOT NULL,
  `name` varchar(127) NOT NULL,
  `unicode_name` varchar(512) NOT NULL,
  `skiped` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`tid`),
  KEY `uid` (`uid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `plugin` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `enable` tinyint(1) NOT NULL DEFAULT '1',
  `name` varchar(64) NOT NULL,
  `version` varchar(8) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  UNIQUE KEY `name` (`name`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

INSERT INTO `plugin` (`id`, `enable`, `name`, `version`) VALUES
(1, 1, 'debug_info', '');

CREATE TABLE IF NOT EXISTS `plugin_var` (
  `pluginid` varchar(64) NOT NULL,
  `key` varchar(32) NOT NULL DEFAULT '',
  `value` text NOT NULL,
  PRIMARY KEY (`pluginid`,`key`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `setting` (
  `k` varchar(32) NOT NULL,
  `v` varchar(256) NOT NULL,
  PRIMARY KEY (`k`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `sign_log` (
  `tid` int(10) unsigned NOT NULL,
  `uid` int(10) unsigned NOT NULL,
  `date` int(11) NOT NULL DEFAULT '0',
  `status` tinyint(4) NOT NULL DEFAULT '0',
  `exp` tinyint(4) NOT NULL DEFAULT '0',
  `retry` tinyint(3) unsigned NOT NULL DEFAULT '0',
  UNIQUE KEY `tid` (`tid`,`date`),
  KEY `uid` (`uid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `update_source` (
  `id` varchar(16) NOT NULL,
  `path` varchar(128) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


================================================
FILE: install/openshift.php
================================================
<?php
if(!getenv('OPENSHIFT_APP_NAME')){
	header('Location: ./');
	exit();
}
error_reporting(E_ERROR | E_PARSE);
$config_file = dirname(__FILE__).'/../system/config.inc.php';
include_once $config_file;
if($_config){
	header('Location: ..');
	exit();
}

@touch($config_file);

switch($_GET['step']){
	default:
		$content = '<p>欢迎使用 贴吧签到助手 安装向导!</p><p>本程序将会指引你在服务器上配置好“贴吧签到助手”</p><p>点击右侧的“下一步”按钮开始</p><br><p>Openshift one-key installer. Thanks to <a href="http://tieba.baidu.com/home/main?un=%D3%F4%C3%C6de%CB%B5" target="_blank">郁闷de说</a></p><p class="btns"><button onclick="location.href=\'./openshift.php?step=database\';">下一步 &raquo;</button>';
		show_install_page('Welcome', $content);
		break;
	case 'database':
		$content = '<div class="config"><p>请设置站点管理员信息</p><br>';
		$content .= '<form action="./openshift.php?step=install" method="post" onsubmit="show_waiting();">';
		$content .= '<p><span>管理员用户名:</span><input type="text" name="username" required /></p>';
		$content .= '<p><span>管理员密码:</span><input type="password" name="password" required /></p>';
		$content .= '<p><span>管理员邮箱:</span><input type="text" name="email" required /></p>';
		$content .= '<p class="btns"><span>&nbsp;</span><input type="submit" value="下一步 &raquo;" /></p>';
		$content .= '</form></div><div class="waiting hidden"><p>程序正在执行必要的安装步骤,请耐心等待...</p></div>';
		$content .= '<script type="text/javascript">function show_waiting(){ $(".config").hide(); $(".waiting").show(); }</script>';
		show_install_page('站点配置', $content);
		break;
	case 'install':
		$db_host = getenv('OPENSHIFT_MYSQL_DB_HOST');
		$db_port = intval(getenv('OPENSHIFT_MYSQL_DB_PORT'));
		$db_username = getenv('OPENSHIFT_MYSQL_DB_USERNAME');
		$db_password = getenv('OPENSHIFT_MYSQL_DB_PASSWORD');
		$db_name = getenv('OPENSHIFT_APP_NAME');
		$db_pconnect = false;
		$function = $db_pconnect ? 'mysql_connect' : 'mysql_pconnect';
		$link = mysql_connect("{$db_host}:{$db_port}", $db_username, $db_password);
		if(!$link) show_back('数据库配置', '错误:无法连接数据库服务器!</p><p>'.mysql_error());
		$selected = mysql_select_db($db_name, $link);
		if(!$selected){
			// 尝试新建
			mysql_query("CREATE DATABASE `{$db_name}`", $link);
			$selected = mysql_select_db($db_name, $link);
			if(!$selected) show_back('数据库配置', '错误:指定的数据库不可用</p><p>'.mysql_error());
		}
		mysql_query("SET character_set_connection=utf8, character_set_results=utf8, character_set_client=binary");
		$syskey = random(32);
		$username = addslashes($_POST['username']);
		$password = md5($syskey.md5($_POST['password']).$syskey);
		$email = addslashes($_POST['email']);
		if(!$username || !$password || !$email) show_back('注册账号', '您输入的信息不完整');
		if(preg_match('/[<>\'\\"]/i', $username)) show_back('注册账号', '用户名中有被禁止使用的关键字');
		if(strlen($username) < 6) show_back('注册账号', '用户名至少要6个字符(即2个中文 或 6个英文),请修改');
		if(strlen($username) > 24) show_back('注册账号', '用户名过长,请修改');
		$install_script = file_get_contents(dirname(__FILE__).'/install.sql');
		preg_match('/version ([0-9a-z.]+)/i', $install_script, $match);
		$version = trim($match[1]);
		if(!$version) show_back('正在安装', '安装脚本有误,请重新上传');
		$err = runquery($install_script, $link);
		mysql_query("INSERT INTO member SET username='{$username}', password='{$password}', email='{$email}'");
		$uid = mysql_insert_id($link);
		mysql_query("INSERT INTO member_setting SET uid='{$uid}', cookie=''");
		saveSetting('block_register', 1);
		saveSetting('jquery_mode', 2);
		saveSetting('admin_uid', $uid);
		saveSetting('SYS_KEY', $syskey);
		if($err) show_back('正在安装', '安装过程出现错误:</p><p>'.mysql_error());
		$_config = array(
			'version' => $version,
			'db' => array(
				'server' => $db_host,
				'port' => $db_port,
				'username' => $db_username,
				'password' => $db_password,
				'name' => $db_name,
				'pconnect' => $db_pconnect,
				),
			);
		$content = '<?php'.PHP_EOL.'/* Auto-generated config file */'.PHP_EOL.'$_config = ';
		$content .= var_export($_config, true).';'.PHP_EOL.'?>';
		file_put_contents($config_file, $content);
		$content = '<p>贴吧签到助手 已经成功安装!</p><p>系统默认关闭用户注册,如果有需要,请到后台启用用户注册功能。</p><p style="color: red">Openshift 用户如出现错误请前往管理界面重启应用</p><br><p class="btns"><button onclick="location.href=\'../\';">登录 &raquo;</button>';
		show_install_page('安装成功', $content);
}

function show_back($title, $text){
	$content = '<p>'.$text.'</p>';
	$content .= '<br><p class="btns"><button onclick="history.back();">&laquo; 返回</button></p>';
	show_install_page($title, $content);
}

function show_install_page($title, $content){
	$template = '<!DOCTYPE html><html><head><title>贴吧签到助手</title><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><meta name="HandheldFriendly" content="true" /><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" /><meta name="author" content="kookxiang" /><meta name="copyright" content="KK\'s Laboratory" /><link rel="shortcut icon" href="../favicon.ico" /><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /><meta name="renderer" content="webkit"><link rel="stylesheet" href="../template/default/style/main.css" type="text/css" /><link rel="stylesheet" href="../template/default/style/custom.css" type="text/css" /><style type="text/css">.status.on, .status.off { padding: 2px 0 2px 20px; } .status.on { color: #22dd33; background: url(../template/default/style/done.gif) no-repeat 1px 50%; } .status.off { color: #ff3344; background: url(../template/default/style/error.gif) no-repeat 1px 50%; } .main-box { max-width: 550px; top: 135px; } .main-content { min-height: 150px; text-align: left; font-size: 13px; padding-bottom: 18px; margin-left: 0; } .main-content>div { min-height: 0; } .main-wrapper { min-height: 150px; } .config span { width: 100px; text-align:right; display:block; float: left; height: 30px; line-height: 30px; margin-right: 15px; } .wrapper:after { display:block; content: \'.\'; padding-bottom: 175px; }</style></head><body><div class="wrapper" id="page_index"><div id="append_parent"><div class="loading-icon"><img src="../template/default/style/loading.gif" /> 载入中...</div></div><div class="main-box clearfix"><h1>贴吧签到助手 - 安装向导</h1><div class="main-wrapper"><div class="main-content"><h2>{title}</h2>{content}</div></div></div></div><script src="//lib.sinaapp.com/js/jquery/1.10.2/jquery-1.10.2.min.js"></script><script src="../template/default/js/fwin.js"></script><script type="text/javascript">hideloading();</script></body></html>';
	echo str_replace(array('{title}', '{content}'), array($title, $content), $template);
	exit();
}

function show_status($status, $on_txt = 'On', $off_txt = 'Off'){
	return $status ? '<span class="status on">'.$on_txt.'</span>' : '<span class="status off">'.$off_txt.'</span>';
}

function runquery($sql, $link){
	$sql = str_replace("\r", "\n", $sql);
	foreach(explode(";\n", trim($sql)) as $query) {
		$query = trim($query);
		if(!$query) continue;
		$ret = mysql_query($query, $link);
		if(!$ret) return mysql_error();
	}
}

function saveSetting($k, $v){
	global $link;
	$v = addslashes($v);
	mysql_query("REPLACE INTO setting SET v='{$v}', k='{$k}'", $link);
}

function random($length, $numeric = 0) {
	$seed = base_convert(md5(microtime().$_SERVER['DOCUMENT_ROOT']), 16, $numeric ? 10 : 35);
	$seed = $numeric ? (str_replace('0', '', $seed).'012340567890') : ($seed.'zZ'.strtoupper($seed));
	$hash = '';
	$max = strlen($seed) - 1;
	for($i = 0; $i < $length; $i++) {
		$hash .= $seed{mt_rand(0, $max)};
	}
	return $hash;
}

?>

================================================
FILE: install/sae.php
================================================
<?php
if(!defined('SAE_ACCESSKEY')) exit();
define('IN_KKFRAME', true);
define('SYSTEM_ROOT', dirname(__FILE__).'/');
define('ROOT', dirname(SYSTEM_ROOT).'/');
error_reporting(E_ERROR | E_PARSE);
$_config = array(
	'db' => array(
		'server' => SAE_MYSQL_HOST_M,
		'port' => SAE_MYSQL_PORT,
		'username' => SAE_MYSQL_USER,
		'password' => SAE_MYSQL_PASS,
		'name' => SAE_MYSQL_DB,
		'pconnect' => false,
	),
);
require_once '../system/class/error.php';
set_exception_handler(array('error', 'exception_error'));
require_once '../system/class/db.php';
$query = DB::query("SELECT v FROM setting LIMIT 0,1", 'SILENT');
if($query){
	header('Location: ..');
	exit();
}

switch($_GET['step']){
	default:
		$content = '<p>欢迎使用 贴吧签到助手 安装向导!</p><p>本程序将会指引你在服务器上配置好“贴吧签到助手”</p><p>点击右侧的“下一步”按钮开始</p><p class="btns"><button onclick="location.href=\'./sae.php?step=database\';">下一步 &raquo;</button>';
		show_install_page('Welcome', $content);
		break;
	case 'database':
		$content = '<div class="config"><p>请填写基本信息</p><br>';
		$content .= '<form action="./sae.php?step=install" method="post" onsubmit="show_waiting();">';
		$content .= '<p><span>管理员用户名:</span><input type="text" name="username" required /></p>';
		$content .= '<p><span>管理员密码:</span><input type="password" name="password" required /></p>';
		$content .= '<p><span>管理员邮箱:</span><input type="text" name="email" required /></p>';
		$content .= '<p class="btns"><span>&nbsp;</span><input type="submit" value="下一步 &raquo;" /></p>';
		$content .= '</form></div><div class="waiting hidden"><p>程序正在执行必要的安装步骤,请耐心等待...</p></div>';
		$content .= '<script type="text/javascript">function show_waiting(){ $(".config").hide(); $(".waiting").show(); }</script>';
		show_install_page('系统配置', $content);
		break;
	case 'install':
		$syskey = random(32);
		$username = addslashes($_POST['username']);
		$password = md5($syskey.md5($_POST['password']).$syskey);
		$email = addslashes($_POST['email']);
		if(!$username || !$password || !$email) show_back('注册账号', '您输入的信息不完整');
		if(preg_match('/[<>\'\\"]/i', $username)) show_back('注册账号', '用户名中有被禁止使用的关键字');
		if(strlen($username) < 6) show_back('注册账号', '用户名至少要6个字符(即2个中文 或 6个英文),请修改');
		if(strlen($username) > 24) show_back('注册账号', '用户名过长,请修改');
		$install_script = file_get_contents(dirname(__FILE__).'/install.sql');
		preg_match('/version ([0-9a-z.]+)/i', $install_script, $match);
		$version = trim($match[1]);
		if(!$version) show_back('正在安装', '安装脚本有误,请重新上传');
		$err = runquery($install_script);
		DB::query("INSERT INTO member SET username='{$username}', password='{$password}', email='{$email}'");
		$uid = DB::insert_id();
		DB::query("INSERT INTO member_setting SET uid='{$uid}', cookie=''");
		saveSetting('block_register', 1);
		saveSetting('jquery_mode', 2);
		saveSetting('admin_uid', $uid);
		saveSetting('SYS_KEY', $syskey);
		saveSetting('version', $version);
		$_config = array(
			'db' => array(
				'server' => $db_host,
				'port' => $db_port,
				'username' => $db_username,
				'password' => $db_password,
				'name' => $db_name,
				'pconnect' => $db_pconnect,
				),
			);
		$content = '<?php'.PHP_EOL.'/* Auto-generated config file */'.PHP_EOL.'$_config = ';
		$content .= var_export($_config, true).';'.PHP_EOL.'?>';
		file_put_contents($config_file, $content);
		$content = '<p>贴吧签到助手 已经成功安装!</p><p>系统默认关闭用户注册,如果有需要,请到后台启用用户注册功能。</p><br><p class="btns"><button onclick="location.href=\'../\';">登录 &raquo;</button>';
		show_install_page('安装成功', $content);
}

function show_back($title, $text){
	$content = '<p>'.$text.'</p>';
	$content .= '<br><p class="btns"><button onclick="history.back();">&laquo; 返回</button></p>';
	show_install_page($title, $content);
}

function show_install_page($title, $content){
	$template = '<!DOCTYPE html><html><head><title>贴吧签到助手</title><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><meta name="HandheldFriendly" content="true" /><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" /><meta name="author" content="kookxiang" /><meta name="copyright" content="KK\'s Laboratory" /><link rel="shortcut icon" href="../favicon.ico" /><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /><meta name="renderer" content="webkit"><link rel="stylesheet" href="../template/default/style/main.css" type="text/css" /><link rel="stylesheet" href="../template/default/style/custom.css" type="text/css" /><style type="text/css">.status.on, .status.off { padding: 2px 0 2px 20px; } .status.on { color: #22dd33; background: url(../template/default/style/done.gif) no-repeat 1px 50%; } .status.off { color: #ff3344; background: url(../template/default/style/error.gif) no-repeat 1px 50%; } .main-box { max-width: 550px; top: 135px; } .main-content { min-height: 150px; text-align: left; font-size: 13px; padding-bottom: 18px; margin-left: 0; } .main-content>div { min-height: 0; } .main-wrapper { min-height: 150px; } .config span { width: 100px; text-align:right; display:block; float: left; height: 30px; line-height: 30px; margin-right: 15px; } .wrapper:after { display:block; content: \'.\'; padding-bottom: 175px; }</style></head><body><div class="wrapper" id="page_index"><div id="append_parent"><div class="loading-icon"><img src="../template/default/style/loading.gif" /> 载入中...</div></div><div class="main-box clearfix"><h1>贴吧签到助手 - 安装向导</h1><div class="main-wrapper"><div class="main-content"><h2>{title}</h2>{content}</div></div></div></div><script src="//lib.sinaapp.com/js/jquery/1.10.2/jquery-1.10.2.min.js"></script><script src="../template/default/js/fwin.js"></script><script type="text/javascript">hideloading();</script></body></html>';
	echo str_replace(array('{title}', '{content}'), array($title, $content), $template);
	exit();
}

function show_status($status, $on_txt = 'On', $off_txt = 'Off'){
	return $status ? '<span class="status on">'.$on_txt.'</span>' : '<span class="status off">'.$off_txt.'</span>';
}

function runquery($sql, $link){
	$sql = str_replace("\r", "\n", $sql);
	foreach(explode(";\n", trim($sql)) as $query) {
		$query = trim($query);
		if(!$query) continue;
		DB::query($query, $link);
	}
}

function saveSetting($k, $v){
	global $link;
	$v = addslashes($v);
	DB::query("REPLACE INTO setting SET v='{$v}', k='{$k}'", $link);
}

function random($length, $numeric = 0) {
	$seed = base_convert(md5(microtime().$_SERVER['DOCUMENT_ROOT']), 16, $numeric ? 10 : 35);
	$seed = $numeric ? (str_replace('0', '', $seed).'012340567890') : ($seed.'zZ'.strtoupper($seed));
	$hash = '';
	$max = strlen($seed) - 1;
	for($i = 0; $i < $length; $i++) {
		$hash .= $seed{mt_rand(0, $max)};
	}
	return $hash;
}

?>

================================================
FILE: member.php
================================================
<?php
require_once './system/common.inc.php';
$invite_code = getSetting('invite_code');
if($_GET['action'] == 'logout' && $_GET['hash']==$formhash){
	dsetcookie('token', '');
	$_COOKIE['token'] = '';
	showmessage('您已经退出登录了!', dreferer(), 1);
}elseif($uid && $_GET['action'] == 'unbind_user'){
	if($_GET['formhash'] != $formhash) showmessage('来源不可信,请重试', './');
	$_uid = intval($_GET['uid']);
	$user = DB::fetch_first("SELECT * FROM member_bind WHERE uid='{$uid}' AND _uid='{$_uid}'");
	if(!$user) showmessage('你并没有绑定该账号', './');
	DB::query("DELETE FROM member_bind WHERE uid='{$uid}' AND _uid='{$_uid}'");
	DB::query("DELETE FROM member_bind WHERE uid='{$_uid}' AND _uid='{$uid}'");
	showmessage("成功解除与 {$user['username']} 的绑定!", './');
}elseif($uid && $_GET['action'] == 'bind_user'){
	if($_POST['formhash'] != $formhash) showmessage('来源不可信,请重试', './');
	if(!$_POST['username']){
		showmessage('请输入用户名', './#');
	}elseif(!$_POST['password']){
		showmessage('请输入密码', './#');
	}
	$_username = daddslashes($_POST['username']);
	if($_username == $username) showmessage('请输入其他账户的信息', './#');
	if(strlen($_username) > 24) showmessage('用户名过长,请修改', dreferer(), 5);
	$user = DB::fetch_first("SELECT * FROM member WHERE username='{$_username}'");
	$userid = $user['uid'];
	$verified = Widget_Password::verify($user, $_POST['password']);
	if($verified){
		$exists = DB::result_first("SELECT _uid FROM member_bind WHERE uid='{$uid}' AND _uid='{$userid}'");
		if($exists) showmessage('您此前已经绑定过此帐号', './#');
		DB::insert('member_bind', array(
			'uid' => $uid,
			'_uid' => $userid,
			'username' => $user['username'],
		));
		$exists = DB::result_first("SELECT uid FROM member_bind WHERE _uid='{$uid}' AND uid='{$userid}'");
		if(!$exists){
			$username = DB::result_first("SELECT username FROM member WHERE uid='{$uid}'");
			DB::insert('member_bind', array(
				'uid' => $userid,
				'_uid' => $uid,
				'username' => $username,
			));
		}
		showmessage("您已经成功绑定用户“{$user[username]}”", './');
	}else{
		showmessage('用户名/密码不正确!', './#');
	}
}elseif($uid && $_GET['action'] == 'switch'){
	if($_GET['formhash'] != $formhash) showmessage('来源不可信,请重试', './');
	$target_uid = intval($_GET['uid']);
	$uid = DB::result_first("SELECT _uid FROM member_bind WHERE uid='{$uid}' AND _uid='{$target_uid}'");
	if(!$uid) showmessage('您尚未绑定该账号,无法进行切换', './');
	$username = get_username($uid);
	do_login($uid);
	showmessage("您已经成功切换至 {$username}!", dreferer(), 1);
}elseif($uid){
	showmessage('您已经登录了~', dreferer(), 1);
}elseif($_GET['action'] == 'find_password'){
	if($_GET['token']){
		$str = authcode($_GET['token'], 'DECODE');
		if(!$str) showmessage('链接有误,请重新获取', './');
		list($uid, $exptime, $password, $random) = explode("\t", $str);
		if($exptime < TIMESTAMP) showmessage('链接已过期,请重新获取', './');
		$user = DB::fetch_first("SELECT * FROM member WHERE uid='{$uid}' AND password='{$password}'");
		if(!$user) showmessage('链接已经失效,请重新获取', './');
		$new_password = random(10);
		$newpassword = Widget_Password::encrypt($user, $new_password);
		DB::update('member', array('password' => $newpassword), "uid='{$uid}'");
		showmessage("您的密码已经重置为:<br>{$new_password}<br><br>请使用新密码登录并修改密码。");
	}elseif($_POST['username'] && $_POST['email']){
		$username = daddslashes($_POST['username']);
		$email = daddslashes($_POST['email']);
		$user = DB::fetch_first("SELECT * FROM member WHERE username='{$username}' AND email='{$email}'");
		if(!$user) showmessage('用户名 / 邮箱有误', './');
		$info = array(
			$user['uid'],			// UID
			TIMESTAMP + 3600,		// Token 过期时间
			$user['password'],		// 当前密码
			random(32),				// 随机字符
		);
		$token = urlencode(authcode(implode("\t", $info), 'ENCODE'));
		$link = "{$siteurl}member.php?action=find_password&token={$token}";
		$message = <<<EOF
<p>我们已经收到您的找回密码申请,请您点击下方的链接重新设置密码:</p>
<blockquote><a href="{$link}">{$link}</a></blockquote>
<p>(注:请在一小时内点击上面的链接,我们将向您提供新的密码)</p>
<br>
<p>如果您没有要求重置密码却收到本邮件,请及时删除此邮件以确保账户安全。</p>
EOF;
		DB::insert('mail_queue', array(
			'to' => $user['email'],
			'subject' => "贴吧签到助手 - 密码找回",
			'content' => $message,
			));
		saveSetting('mail_queue', 1);
		showmessage('邮件发送成功,请到邮箱查收', './');
	}
	header('Location: member.php');
	exit();
}elseif($_GET['action'] == 'register'){
	if(getSetting('block_register')) showmessage('抱歉,当前站点禁止新用户注册', 'member.php');
	$count = DB::result_first('SELECT COUNT(*) FROM member');
	if($_POST && strexists($_SERVER['HTTP_REFERER'], 'member.php')){
		list($time, $hash, $member_count) = explode("\t", authcode($_COOKIE['key'], 'DECODE'));
		if(getSetting('register_check') && $time > TIMESTAMP - 5 || $time < TIMESTAMP - 300) $_POST = array();
		if(getSetting('register_limit') && $member_count != $count) showmessage('当前注册人数过多,请您稍后再试', 'member.php');
		if($count > 1000) showmessage('超过当前站点最大用户数量上限,无法注册', 'member.php');
		$_POST['username'] = $_POST['password'] = $_POST['email'] = null;
		foreach($_POST as $key => $value){
			$key = authcode($key, 'DECODE', $hash);
			if($key == 'username'){
				$_POST['username'] = $value;
			}elseif($key == 'password'){
				$_POST['password'] = $value;
			}elseif($key == 'email'){
				$_POST['email'] = $value;
			}
		}
		if(!$_POST['username']){
			showmessage('请输入用户名', 'member.php');
		}elseif(!$_POST['password']){
			showmessage('请输入密码', 'member.php');
		}elseif(!$_POST['email']){
			showmessage('请输入您的邮箱', 'member.php');
		}else{
			if($invite_code && $_POST['invite_code'] != $invite_code) showmessage('邀请码有误', 'member.php');
			$username = daddslashes($_POST['username']);
			$email = daddslashes($_POST['email']);
			if(!is_email($email)) showmessage('邮箱格式不正确,请修改', dreferer(), 5);
			if(!$username || !$_POST['password'] || !$email) showmessage('您输入的信息不完整', 'member.php');
			if(preg_match('/[<>\'\\"]/i', $username)) showmessage('用户名中有被禁止使用的关键字', 'member.php');
			if(strlen($username) < 6) showmessage('用户名至少要6个字符(即2个中文 或 6个英文),请修改', dreferer(), 5);
			if(strlen($username) > 24) showmessage('用户名过长,请修改', dreferer(), 5);
			$un = strtolower($username);
			if(strexists($un, 'admin') || strexists($un, 'guanli')) showmessage('用户名不和谐,请修改', dreferer(), 5);
			$user = DB::fetch_first("SELECT * FROM member WHERE username='{$username}'");
			if($user) showmessage('用户名已经存在', 'member.php');
			HOOK::run('before_register');
			$uid = do_register($username, $_POST['password'], $email);
			do_login($uid);
			HOOK::run('register_finish', false, $uid);
			showmessage("注册成功,您的用户名是 <b>{$username}</b> 记住了哦~!", dreferer(), 3);
		}
	}
	header('Location: member.php');
	exit();
}elseif($_POST){
	if($_POST['username'] && $_POST['password']){
		$username = daddslashes($_POST['username']);
		$un = strtolower($username);
		if(strlen($username) > 24) showmessage('用户名过长,请修改', dreferer(), 5);
		$user = DB::fetch_first("SELECT * FROM member WHERE username='{$username}'");
		$verified = Widget_Password::verify($user, $_POST['password']);
		if($verified) {
			$login_exp = TIMESTAMP + 3600;
			do_login($user['uid']);
			$username = $user['username'];
			showmessage("欢迎回来,{$username}!", dreferer(), 1);
		}else{
			showmessage('对不起,您的用户名或密码错误,无法登录.', 'member.php', 3);
		}
	}
}
$count = DB::result_first('SELECT COUNT(*) FROM member');
$hash = random(6);
$time = TIMESTAMP;
dsetcookie('key', authcode("{$time}\t{$hash}\t{$count}", 'ENCODE'));
$form_username = authcode('username', 'ENCODE', $hash);
$form_password = authcode('password', 'ENCODE', $hash);
$form_email = authcode('email', 'ENCODE', $hash);
include template('member');

================================================
FILE: plugin.php
================================================
<?php
define('IN_ADMINCP', true);
define('DISABLE_PLUGIN', true);
require_once './system/common.inc.php';
$plugin_id = htmlspecialchars($_GET['id']);
$plugins = CACHE::get('plugins');
foreach($plugins as $plugin){
	if($plugin['id'] == $plugin_id) {
		$exists = true;
		break;
	}
}
if(!isset($exists)) throw new Exception("Unknown plugin '{$plugin_id}'");
$obj = HOOK::getPlugin($plugin_id);
if($obj instanceof Plugin){
	$obj->handleAction();
} else {
	throw new Exception('This plugin doesn\'t support to be called directly.');
}


================================================
FILE: plugins/cloud_stat/cloud_stat.cron.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit();
$obj = $_PLUGIN['obj']['cloud_stat'];
if(!$obj && file_exists(ROOT.'plugins/cloud_stat/plugin.class.php')) {
	$obj = new plugin_cloud_stat();
}

$date = date('Ymd', TIMESTAMP);
$tieba = intval($obj->getSetting('tieba'));
$exp = intval($obj->getSetting('exp'));
$tieba += DB::result_first("SELECT COUNT(*) FROM sign_log WHERE status=2 AND date='{$date}'");
$obj->saveSetting('tieba', $tieba);
$exp += DB::result_first("SELECT SUM(exp) FROM sign_log WHERE status=2 AND date='{$date}'");
$obj->saveSetting('exp', $exp);

/* send data */

$sid = cloud::id();
$key = cloud::key();
$sign = md5($key.$sid.$tieba.$exp.$key);
$ret = kk_fetch_url("http://api.ikk.me/stat.php?sid={$sid}&tieba={$tieba}&exp={$exp}&sign={$sign}");
if($ret) {
	$data = json_decode($ret);
	if($data){
		$obj->saveSetting('cloud_tieba', $data->tieba);
		$obj->saveSetting('cloud_exp', $data->exp);
	}
}

cron_set_nextrun($tomorrow + 3600);


================================================
FILE: plugins/cloud_stat/index.inc.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit('Access Denied!');
$obj = $_PLUGIN['obj']['cloud_stat'];
?>
<script type="text/javascript">
function load_cloud_stat_index(){
	showloading();
	$.getJSON("plugin.php?id=cloud_stat&action=get", function(result){
		if(!result) return;
		var str = '';
		str += '<p>截止今天, 贴吧签到助手共完成 <span>'+result.ctieba+'</span> 次签到</p>';
		str += '<p>为贴吧用户获取 <span>'+result.cexp+'</span> 点经验.</p>';
		str += '<p>其中, 当前网站签到 <span>'+result.tieba+'</span> 次, 获取了 <span>'+result.exp+'</span> 点经验.</p>';
		$('.kk_cloud_stat').html(str);
	}).fail(function() { createWindow().setTitle('系统错误').setContent('发生未知错误: 获取统计信息失败').addButton('确定', function(){ location.reload(); }).append(); }).always(function(){ hideloading(); });
}
</script>
<h2>签到云统计 *</h2>
<style type="text/css">
.kk_cloud_stat { padding: 30px 20px; }
.kk_cloud_stat p { margin: 10px 0; font-size: 26px; line-height: 42px; font-weight: lighter; text-align: center; }
.kk_cloud_stat span { font-size: 32px; font-family: "Segoe UI Light", "Segoe UI", "幼圆", "Arial"; letter-spacing: 5px; vertical-align: baseline; font-size: 64px; text-shadow: 0 0 15px #777; position: relative; top: 5px; }
.stat_source { position: absolute; bottom: 10px; }
</style>
<div class="kk_cloud_stat">
</div>
<p class="stat_source">* 数据源自 贴吧签到助手 开放平台 旗下所有签到站点.</p>

================================================
FILE: plugins/cloud_stat/plugin.class.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit('Access Denied!');
class plugin_cloud_stat extends Plugin{
	var $description = '云统计,记录建站以来的签到次数以及获得经验数';
	var $modules = array(
		array('type' => 'page', 'id' => 'index', 'title' => '签到云统计', 'file' => 'index.inc.php'),
		array('type' => 'cron', 'cron' => array('id' => 'cloud_stat/cloud_stat', 'order' => '105')),
	);
	var $version = '1.1';
	function checkCompatibility(){
		if(version_compare(VERSION, '1.14.4.24', '<')) showmessage('本插件不兼容此版的贴吧签到助手.');
	}
	function install(){
		$count = DB::result_first('SELECT COUNT(*) FROM sign_log WHERE status=2');
		$this->saveSetting('tieba', $count);
		$count = DB::result_first('SELECT SUM(exp) FROM sign_log WHERE status=2');
		$this->saveSetting('exp', $count);
		$ret = kk_fetch_url("http://api.ikk.me/stat.php");
		if(!$ret) return;
		$data = json_decode($ret);
		if(!$data) return;
		$this->saveSetting('cloud_tieba', $data->tieba);
		$this->saveSetting('cloud_exp', $data->exp);
	}
	function mklink($sourceFile, $targetFile){
		return @file_put_contents($targetFile, '<?php @include '.var_export($sourceFile, true).'; ?>');
	}
	function on_upgrade($from_version){
		switch($from_version){
			case '1.0':
				DB::query("UPDATE cron SET id='cloud_stat/cloud_stat' WHERE id='cloud_stat'");
				return '1.1';
			default:
				throw new Exception("Unknown plugin version: {$from_version}");
		}
	}
	function handleAction(){
		echo json_encode(array(
			'ctieba' => intval($this->getSetting('cloud_tieba')),
			'cexp' => intval($this->getSetting('cloud_exp')),
			'tieba' => intval($this->getSetting('tieba')),
			'exp' => intval($this->getSetting('exp')),
		));
	}
}

================================================
FILE: plugins/debug_info/plugin.class.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit('Access Denied!');
class plugin_debug_info extends Plugin{
	var $description = '(已废弃) 此插件将会在页脚输出一行调试信息,便于了解服务器状态';
	var $modules = array();
	function page_footer(){
		return;
	}
}

================================================
FILE: plugins/register_limit/plugin.class.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit('Access Denied!');
class plugin_register_limit extends Plugin {
	var $description = '限制单个 IP 的注册上限';
	var $modules = array();
	function install(){
		DB::query('CREATE TABLE IF NOT EXISTS `kk_ip_limit` ( `a` tinyint(3) unsigned NOT NULL, `b` tinyint(3) unsigned NOT NULL, `c` tinyint(3) unsigned NOT NULL, `d` tinyint(3) unsigned NOT NULL, `count` tinyint(3) unsigned NOT NULL, `lastact` int(10) unsigned NOT NULL, UNIQUE KEY `ip` (`a`,`b`,`c`,`d`)) ENGINE=MEMORY DEFAULT CHARSET=utf8 COLLATE=utf8_bin;');
	}
	function uninstall(){
		DB::query('DROP TABLE kk_ip_limit');
	}
	function checkCompatibility(){
		if(defined('IN_SAE')) showmessage('本插件不兼容当前运行环境.');
	}
	function on_load(){
		if($_GET['action'] != 'register') return;
		if(!$_POST) return;
		list($a, $b, $c, $d) = explode('.', $_SERVER['REMOTE_ADDR']);
		$a = intval($a);
		$b = intval($b);
		$c = intval($c);
		$d = intval($d);
		$count = DB::result_first("SELECT count FROM kk_ip_limit WHERE a='{$a}' AND b='{$b}' AND c='{$c}' AND d='{$d}'");
		$time = TIMESTAMP;
		DB::query("DELETE FROM kk_ip_limit WHERE lastact<{$time}-86400");
		if($count > 0) DB::query("UPDATE kk_ip_limit SET lastact='{$time}' WHERE a='{$a}' AND b='{$b}' AND c='{$c}' AND d='{$d}'");
		if($count >= $this->getSetting('ip_reglimit', 5)) showmessage('达到单 IP 注册上限,禁止注册。', dreferer());
		if($count > 0){
			DB::query("UPDATE kk_ip_limit SET count=count+1 WHERE a='{$a}' AND b='{$b}' AND c='{$c}' AND d='{$d}'");
		}else{
			DB::query("INSERT INTO kk_ip_limit SET count=1, lastact='{$time}', a='{$a}', b='{$b}', c='{$c}', d='{$d}'");
		}
	}
	function on_config(){
		if($_POST['limit']){
			$this->saveSetting('ip_reglimit', $_POST['limit']);
			showmessage('设置已经保存!');
		}else{
			return '<p>单个 IP 注册上限:<input type="text" name="limit" value="'.$this->getSetting('ip_reglimit', 5).'" /></p>';
		}
	}
}

================================================
FILE: plugins/stat/plugin.class.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit('Access Denied!');
class plugin_stat extends Plugin{
	var $description = '用于在页面尾部嵌入自定义的统计代码';
	var $modules = array();
	var $version = '1.0';
	function page_footer_js(){
		$data = $this->getSetting('code');
		if($data) return '<div class="hidden">'.$data.'</div>';
	}
	function on_config(){
		if($_POST['code']){
			$this->saveSetting('code', $_POST['code']);
			showmessage('设置已经保存!');
		}else{
			return '<p>页脚统计代码:</p><p><textarea name="code">'.htmlspecialchars($this->getSetting('code')).'</textarea></p>';
		}
	}
}

================================================
FILE: plugins/xxx_post/c_daily.cron.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit();
$date = date('Ymd', TIMESTAMP+900);
DB::query("ALTER TABLE xxx_post_log CHANGE `date` `date` INT NOT NULL DEFAULT '{$date}'");
DB::query("INSERT IGNORE INTO xxx_post_log (sid, uid) SELECT sid, uid FROM xxx_post_posts");
$delete_date = date('Ymd', TIMESTAMP - 86400*10);
DB::query("DELETE FROM xxx_post_log WHERE date<'$delete_date'");
$setime=HOOK::getPlugin('xxx_post')->getSetting('se');
if(!$setime) $setime=21;
$nxrun =$today+$setime*3600;
DB::query("update cron set nextrun='$nxrun' where id='xxx_post/c_se'");
cron_set_nextrun($tomorrow + 600);


================================================
FILE: plugins/xxx_post/c_first.cron.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit();
require_once ROOT.'./plugins/xxx_post/core.php';
$date = date('Ymd', TIMESTAMP+900);
$count = DB::result_first("select COUNT(*) from xxx_post_log as a left join xxx_post_setting as b on a.uid=b.uid where a.date='$date' and a.status<b.runtimes and a.retry<b.runtimes*2 and b.frequency<=2");
$first_end=HOOK::getPlugin('xxx_post')->getSetting('first_end');
if(!$first_end) $first_end=15;
$first_end_time=$today+$first_end*3600;
if($first_end_time<TIMPSTAMP) $count=0;
$endtime = TIMESTAMP + 45;
if($count){
	while($endtime > time()){
		$count = DB::result_first("select COUNT(*) from xxx_post_log as a left join xxx_post_setting as b on a.uid=b.uid where a.date='$date' and a.status<b.runtimes and a.retry<b.runtimes*2 and b.frequency<=2 and b.runtime<".TIMESTAMP);
		if($count==0) break;
		$offset = rand(1, $count) - 1;
		$sid = DB::result_first("select sid from xxx_post_log as a left join xxx_post_setting as b on a.uid=b.uid where a.date='$date' and a.status<b.runtimes and a.retry<b.runtimes*2 and b.frequency<=2 and b.runtime<".TIMESTAMP." limit $offset,1");
		if(!$sid) break;
		$tiezi=DB::fetch_first("SELECT * FROM xxx_post_posts WHERE sid='$sid'");
		if(!$tiezi){
			DB::query("UPDATE xxx_post_log SET retry=retry+3 WHERE sid='$sid' AND date='$date'");
			continue;
		}
		$x_content_count = DB::result_first("SELECT COUNT(*) FROM xxx_post_content WHERE uid='{$tiezi[uid]}'");
		$x_content_offset = rand(1, $x_content_count) - 1;
		$x_content = DB::result_first("SELECT content FROM xxx_post_content WHERE uid='{$tiezi[uid]}' limit $x_content_offset,1");
		list($statue,$result) = client_rppost($tiezi['uid'],$tiezi,$x_content);
		if($statue == 2){
			$x_delay=DB::result_first("select delay from xxx_post_setting where uid={$tiezi[uid]}");
			if($x_delay){
				$runtime=TIMESTAMP+$x_delay*56;
				DB::query("UPDATE xxx_post_setting SET runtime=$runtime WHERE uid='{$tiezi[uid]}'");
			}
			DB::query("UPDATE xxx_post_log SET status=status+1 WHERE sid='$sid' AND date='$date'");
		}else if($statue==1||$statue==8){
			$x_runtimes=DB::result_first("select runtimes from xxx_post_setting where uid={$tiezi[uid]}");
			DB::query("UPDATE xxx_post_log SET retry='$x_runtimes' WHERE sid='$sid' AND date='$date'");
		}
		else if($statue==5||$statue==7) continue;
		else DB::query("UPDATE xxx_post_log SET retry=retry+1 WHERE sid='$sid' AND date='$date'");
		if(!defined('SIGN_LOOP')) break;
		sleep(1);
		}
}else{
		cron_set_nextrun($tomorrow + 3600);
}

================================================
FILE: plugins/xxx_post/c_se.cron.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit();
require_once ROOT.'./plugins/xxx_post/core.php';
$date = date('Ymd', TIMESTAMP+900);
$count = DB::result_first("select COUNT(*) from xxx_post_log as a left join xxx_post_setting as b on a.uid=b.uid where a.date='$date' and a.status<b.runtimes*2 and a.retry<b.runtimes*4 and b.frequency=1");
$endtime = TIMESTAMP + 45;
if($count){
	while($endtime > time()){
		$count = DB::result_first("select COUNT(*) from xxx_post_log as a left join xxx_post_setting as b on a.uid=b.uid where a.date='$date' and a.status<b.runtimes*2 and a.retry<b.runtimes*4 and b.frequency=1 and b.runtime<".TIMESTAMP);
		if($count==0) break;
		$offset = rand(1, $count) - 1;
		$sid = DB::result_first("select sid from xxx_post_log as a left join xxx_post_setting as b on a.uid=b.uid where a.date='$date' and a.status<b.runtimes*2 and a.retry<b.runtimes*4 and b.frequency=1 and b.runtime<".TIMESTAMP." LIMIT $offset,1");
		if(!$sid) break;
		$tiezi=DB::fetch_first("SELECT * FROM xxx_post_posts WHERE sid='$sid'");
		if(!$tiezi){
			DB::query("UPDATE xxx_post_log SET retry=retry+3 WHERE sid='$sid' AND date='$date'");
			continue;
		}
		$x_content_count = DB::result_first("SELECT COUNT(*) FROM xxx_post_content WHERE uid='{$tiezi[uid]}'");
		$x_content_offset = rand(1, $x_content_count) - 1;
		$x_content = DB::result_first("SELECT content FROM xxx_post_content WHERE uid='{$tiezi[uid]}' limit $x_content_offset,1");
		list($statue,$result) = client_rppost($tiezi['uid'],$tiezi,$x_content);
		if($statue == 2){
			$x_delay=DB::result_first("select delay from xxx_post_setting where uid={$tiezi[uid]}");
			if($x_delay){
				$runtime=TIMESTAMP+$x_delay*56;
				DB::query("UPDATE xxx_post_setting SET runtime=$runtime WHERE uid='{$tiezi[uid]}'");
			}
			DB::query("UPDATE xxx_post_log SET status=status+1 WHERE sid='$sid' AND date='$date'");
		}else if($statue==1||$statue==8){
			$x_runtimes=DB::result_first("select runtimes from xxx_post_setting where uid={$tiezi[uid]}");
			$x_runtimes=$x_runtimes*2;
			DB::query("UPDATE xxx_post_log SET retry='$x_runtimes' WHERE sid='$sid' AND date='$date'");
		}
		else if($statue==5||$statue==7) continue;
		else DB::query("UPDATE xxx_post_log SET retry=retry+1 WHERE sid='$sid' AND date='$date'");
		if(!defined('SIGN_LOOP')) break;
		sleep(1);
		}
}else{
		cron_set_nextrun($tomorrow + 3600);
}

================================================
FILE: plugins/xxx_post/c_sxbk.cron.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit();
$date = date('Ymd', TIMESTAMP+900);
$count = DB::result_first("select COUNT(*) from xxx_post_log as a left join xxx_post_setting as b on a.uid=b.uid where a.date='$date' and a.retry<40 and b.frequency=4");
if(HOOK::getPlugin('xxx_post')->getSetting('sxbk')!=1) {cron_set_nextrun($tomorrow + 5400);$count=0;}
$endtime = TIMESTAMP + 45;
if($count){
	require_once ROOT.'./plugins/xxx_post/core.php';
	while($endtime > time()){
		$count = DB::result_first("select COUNT(*) from xxx_post_log as a left join xxx_post_setting as b on a.uid=b.uid where a.date='$date' and a.retry<40 and b.runtime<".TIMESTAMP." and b.frequency=4");
		if($count==0) break;
		$offset = rand(1, $count) - 1;
		$sid = DB::result_first("select sid from xxx_post_log as a left join xxx_post_setting as b on a.uid=b.uid where a.date='$date' and a.retry<40 and b.runtime<".TIMESTAMP." and b.frequency=4 LIMIT $offset,1");
		if(!$sid) break;
		$tiezi=DB::fetch_first("SELECT * FROM xxx_post_posts WHERE sid='$sid'");
		if(!$tiezi){
			DB::query("UPDATE xxx_post_log SET retry=retry+1 WHERE sid='$sid' AND date='$date'");
			continue;
		}
		$x_content_count = DB::result_first("SELECT COUNT(*) FROM xxx_post_content WHERE uid='{$tiezi[uid]}'");
		$x_content_offset = rand(1, $x_content_count) - 1;
		$x_content = DB::result_first("SELECT content FROM xxx_post_content WHERE uid='{$tiezi[uid]}' limit $x_content_offset,1");
		list($statue,$result) = client_rppost($tiezi['uid'],$tiezi,$x_content);
		if($statue == 2){
			$x_delay=DB::result_first("select delay from xxx_post_setting where uid={$tiezi[uid]}");
			if($x_delay){
				$runtime=TIMESTAMP+$x_delay*56;
				DB::query("UPDATE xxx_post_setting SET runtime=$runtime WHERE uid='{$tiezi[uid]}'");
			}
			DB::query("UPDATE xxx_post_log SET status=status+1 WHERE sid='$sid' AND date='$date'");
		}else if($statue==1||$statue==8) DB::query("UPDATE xxx_post_log SET retry=60 WHERE sid='$sid' AND date='$date'");
		else if($statue==5||$statue==7) continue;
		else DB::query("UPDATE xxx_post_log SET retry=retry+1 WHERE sid='$sid' AND date='$date'");
		if(!defined('SIGN_LOOP')) break;
		sleep(1);
		}
}else{
		cron_set_nextrun($tomorrow + 5400);
}

================================================
FILE: plugins/xxx_post/core.php
================================================
<?php
if (! defined ( 'IN_KKFRAME' ))	exit ();
function get_random_content(){
	$text=<<<EOF
有的人认为坚持会让我们变得更强大,但有时候放手也会。
你若想要得到,就别只是期望。人生短暂,经不起等待。
如果觉得生活是一种刁难,一开始就输了。如果觉得刁难是一种雕刻,迟早都会赢的。
你不可能经由一个没有喜悦的旅程,而达到一个喜悦的终点。不管此刻,你追求的是什么,希望你能在过程中保持一颗喜悦的心,那么你所向往的东西,就会更不费力地来到你的生命中。
为了爱,失恋是必要的;为了光明,黑暗是必要的。
好夫妻的十大经典表现:恋爱时,彼此是崇拜者;交谈时,彼此是知音;得意时,彼此是吹牛对象;生气时,彼此是出气筒;困难时,彼此是咨询师;痛苦时,彼此是安慰者;病时,彼此是护理;老时,彼此是拐杖;平时,彼此各干各,保持适度距离。
你超过别人一点点,别人会嫉妒你;当你超过别人一大截,别人就会羡慕你。
当你了解人性,你也许就能够原谅所有的自私和软弱、所有的谎言与背叛。弗洛依德说,人的内心,既求生,也求死。我们追逐光明,却也追逐黑暗,我们那么想要得到爱,有时候却又近乎自毁地浪掷手中的爱……人心中似乎一直也有一片荒芜的夜地,留给那个寂寞也幽暗的自我。——杨澜
有些事,我们总是弄不懂;有些人,我们总是猜不透;有些道,我们总是悟不尽;有些理,我们总是想不通;有些坎,我们总是跨不过;有些伤,我们总是治不好;有些天,我们总是睡不着;有些情,我们总是说不出;有些爱,我们总是得不到。对不起,那些回不去的曾经。
为什么我们总是不懂得珍惜眼前人?在未可预知的重逢里,我们以为总会重逢,总会有缘再会,总以为有机会说一声对不起,却从没想过每一次挥手道别,都可能是诀别,每一声叹息,都可能是人间最后的一声叹息。
勇敢,那是一个人年轻时唯一拥有的东西。在一次次的错误中成长,将所有看似错误的选择最终引导向正确的结果。我坚信,人应该有力量,揪着自己的头发把自己从泥地里拔起来。——廖一梅《像我这样笨拙地生活》
忘掉岁月,忘掉痛苦,忘掉你的坏,我们永不永不说再见。
当你打算放弃梦想时,告诉自己再多撑一天、一个星期、一个月,再多撑一年吧。你会发现,拒绝退场的结果令人惊讶。
有时候你习惯了我的某个样子,当我变成另外一个样子的时候,你会觉得我变了,不再是之前的我了。其实,那只是你还不够了解我罢了。
你还是一个人,偶尔会孤单偶尔会难受会想有个人拥抱,所以你还是在等。没关系,你一定会等到的。你一定要相信,那个人也在经历了很多之后在找你。你要做的,就是好好照顾自己,让自己在最好的状态里,遇到最好的他。
暧昧,如同度的水,将沸未沸,发着低烧,表外波澜不惊,内部却暗流汹涌。友情以上,恋人未满的状态,在一段时期内,或许会带来模糊朦胧的美感,但是似浓似淡,时好时坏,患得患失的无望爱情,久了,相互喂养的蜜糖就可能变成有害身心健康的砒霜。
忘记那个人,不如忘记自己。告诉自己,不是怕他忘记,而是怕他有一天重新把你想起。岁月带走的是记忆,但回忆会越来越清晰。真的有一天,他回过头来告诉你,他一直在惦记你,千万不要相信,因为,他已经不是原来的他,而你,也不再是过去的你。
时间回不到开始的地方:对于已经错过的一些东西,或许不用再试着去挽留,错了就错了。对于得到,我们都应该充满感激,对于失去,谁能保证那本该是属于你的?有些东西原本就是让你牵挂,而不是获取的。难忘的人会忘,做过的梦成真,期待过去实现,走过的路让自己强壮,珍惜因果,顺乎自然。
过去的一页,能不翻就不要翻,翻落了灰尘会迷了双眼。有些人说不出哪里好,但就是谁都替代不了!那些以前说着永不分离的人,早已经散落在天涯了。收拾起心情,继续走吧,错过花,你将收获雨,错过这一个,你才会遇到下一个。
当一个人最看重的东西是面子,那他为此失去的一定很多。
人可以拒绝任何东西,但绝对不可以拒绝成熟。拒绝成熟,实际上就是在规避问题、逃避痛苦。规避问题和逃避痛苦的趋向,是人类心理疾病的根源,不及时处理,你就会为此付出沉重的代价,承受更大的痛苦。
能耐得住寂寞的人,肯定是有思想的人;能忍受孤独的人,肯定是有理想的人;遇事能屈能伸的人,肯定是有胸怀的人;处事从容不迫的人,肯定是个淡定的人;经常微笑的人,肯定是有头脑的人;看透天下事的人,肯定是个有智慧的人。
如果,年华不曾老去,我不愿以清绝的姿态,总以忧伤示人,每当狂欢响起,而我总会念着谢幕,念着残缺。如果,年华不曾老去,我不愿再坐等年轮一圈圈卷起,不会让友情与爱情,以沧桑的名义在身旁悄悄地溜走,而是耗尽此生时光,用最温暖的文字为爱写歌,为情谱曲。
不论什么时候开始,重要的是开始之后就不要停止。不论什么时候结束,重要的是结束之后就不要悔恨。
无缘何生斯世,有情能累此生。
知音,能有一个已经很好了,不必太多。如果实在没有,还有自己。好好对待自己,跟自己相处,也是一个朋友。
世界上有两个我,一个假装快乐,一个真心难过。
真正的自信不是表现给别人看的,而是无意当中散发出来的。自信来自于哪里,对于我来说,自信来自于自己对于工作的把握,对于生活的把握。当自己面对不同的人,不同的环境的时候,我知道不需要担心自己。——闾丘露薇
我们来到这个世上,每个人都背着一个空篓子,而人的一生,就是不断地往自己的篓子里放东西的过程。如果有了,就想更多,贪得无厌,欲壑难填。只做加法的人生是很悲哀的,远离名利,看淡成败,安于淡泊就是做减法。减去多余的物质,减去奢侈的欲望,减去心灵的负担。加减法并用,人生之旅才会风光无限。
一辈子那么长,一天没走到终点,你就一天不知道哪一个才是陪你走到最后的人。有时你遇到了一个人,以为就是他了,后来回头看,其实他也不过是这一段路给了你想要的东西。
走到生命的哪一个阶段,都该喜欢那一段时光,完成那一阶段该完成的职责,顺生而行,不沉迷过去,不狂热地期待着未来,生命这样就好。不管正经历着怎样的挣扎与挑战,或许我们都只有一个选择:虽然痛苦,却依然要快乐,并相信未来。
谦和、温顺且自持的生活,不乱于心,不困于情,不畏将来,不念过去。
我要的,不是短暂的温柔,而是一生的守候。
当爱一个人,却无法拥有他时,自己面对着一个选择:放弃还是继续。包括你在内的很多人都说:放弃吧,不要再浪费青春。但是,自己却明白,自己真的放不下。如果能放下,早都已经放下了,根本不会到现在的地步。所以,当黑夜来临的时候,我只能孤独的思念一个人。
茫茫人海,没有人不喜欢幸福的,没有人不期待幸福的,没有人不向往幸福的。但不同的时代有着不同的理解,不同的阶层有着不同的看法,不同的年龄有着不同的要求。无论怎么不同,有一点却是相同的,那就是幸福降临的时候,会感到比美妙更美妙,比快乐更快乐,总会激动不已甚至泪流满面。
请把你的心给我,与我为伍,这个世界太残酷了,我有些害怕。
没有一百分的另一半,只有五十分的两个人。
命中有很多事情足以把你打倒,但真正能把你打倒的是你的心态。
你喜欢的人也喜欢你,你想念的人也正在想念你。这就是全世界最重要的事情,拿什么都不能换。
最好的年龄是,那一天,你终于知道并且坚信自己有多好,不是虚张,不是夸浮,不是众人捧,是内心明明澈澈知道:是的,我就是这么好。
妈妈说只要我乖乖认错,就会再拉住我的手;你说不是有的时候认错,就能够让我们再次牵手。亲人总会原谅,因为你是他们的孩子;爱人总难原谅,因为我们都是孩子。
分手之后,不用觉得那些曾经的恩爱是耳光,不用觉得那些说过的誓言多苍白,也不用去喊什么低调的幸福才能长久,至少在当时当地,它们都是出自真心。这所有的东西,都值得珍藏,你的青春没有白费。
刚好处在这个尴尬的年龄,开始关心爸妈,却不愿说出口;想多陪陪爸妈,却更贪恋坐在电脑前;知道爸妈想和自己说话,却不知道他们的话题要怎么接;看得到爸妈在变老,却仍不耐烦他们的过时。心里时时刻刻在愧疚,却依然带给他们落寞。
她没有见过阴云,她的眼睛是晴空的颜色。她永远看着我,永远,看着,绝不会忽然掉过头去。
不论是自转还是公转,涨潮还是退潮;不论是暖流改变气温带来鱼群,或者海水淹没岛屿失去踪迹;不论是我的世界车水马龙繁华盛世,还是它们都瞬间消失化为须臾;我都会坚定地走向你,不迷惑,不慌张,不犹豫。
谁都以为自己会是例外——在后悔之外。谁都以为拥有的感情也是例外——在变淡之外。谁都以为恋爱的对象刚巧也是例外——在改变之外。然而最终发现——除了变化,无一例外。
星云大师:口袋没钱,心里没钱,轻松一辈子;口袋有钱,心里有钱,劳累一辈子;口袋没钱,心里有钱,痛苦一辈子;口袋有钱,心里没钱,快乐一辈子。
人生是一种选择,亦是一种放弃。能自由选择的人是幸福的,能适度放弃的心是洒脱的。可惜,有时我们的选择,只有等待,没有结果,只能黯然离开;有时我们的放弃,迫于无奈,含泪转身,走远了依旧频频地回望。
不知不觉,是这世上最可怕的力量。
温暖在你心里,只是你自己还没有发现它。
当我们感到幸福的时候,何必去想这幸福是永恒的,还是暂时的。忧虑,是幸福最大的敌人。
给自己的三句话:一、年轻,什么都还来得及;二、不要纠缠于小事;三、你现在遇到的事都是小事。
执子之手,共度此生——曾经以为所有的爱情都一定要惊天动地;曾经以为每个人的爱情都一定要轰轰烈烈;曾经以为所有的爱情都有花前月下,海誓山盟;曾经无限向往九千九百九十九朵玫瑰的浪漫……然而平平淡淡同样震撼人心,执手之时,冷暖两心知;执手之时,悲喜两忘。
恐惧就是这样一个懦夫,当你触及他的底线,接受事情最坏的结果,然后开始准备和它大干一场的时候,它早就不知道躲到哪里去了。
爱情不是学问,不用学习,若果爱一个人,发自内心,难以遮掩,自然而然以他为重,这是种本能,不费吹灰之力。
曾经,你苦苦以为,没有了这个人,也就活不成了,到了后来,不是活得好好的吗?一个不爱你的人,决不会比你的生命重要;一个爱你的人,会告诉你,你的生命比你对他的爱情重要。
“归属感”是你强烈地想和他在一起,“安全感”是你觉得他强烈地想和你在一起。
人生总要经历很多,有些人无法羽化成铭记,有些事无法沉淀为回忆。对于一些伤痛的人与事,要学会走过了就要淡漠,转身了就要遗忘,唯有如此,我们的行囊才不会太沉重,我们的身心才不会太疲乏。相聚是短暂的,分别会是永远的,没有人能是你永恒的挂牵,任何事都不要成为你所有的渴盼。
人的一生很像是在雾中行走;远远望去,只是迷蒙一片,辨不出方向和吉凶。可是,当你鼓起勇气,放下忧惧和怀疑,一步一步向前走去的时候,你就会发现,每走一步,你都能把下一步路看得清楚一点。“往前走,别站在远远的地方观望!”你就可以找到你的方向。
爱就是,无论你怎么抵挡,它还是要来的东西。爱就是,无论你怎么诋毁,它还是高尚的东西。
洒脱是人生的一种境界。洒脱不是无所事事、不思进取,也不是看破红尘、心灰意冷,更不是声色犬马、纸醉金迷。洒脱是一种世事洞明的豁达,一种淡泊名利的超脱,一种有所为有所不为的风度。洒脱不是放弃,而是放下,放下不切实际的幻想,放下无法更改的过去,行云流水,任其所之。
每棵大树,都曾只是一粒种子。
人累了,就休息;心累了,就淡定。长大了,成熟了,这个社会就看透了。累了,难过了,就蹲下来,给自己一个拥抱。因为这个世界上没有人能同情你,怜悯你。你哭了,眼泪是自己的;你痛了,没有人能体会到。你一定要坚强,即使受过伤,流过泪,也能咬牙走下去。因为,人生,其实只是你一个人的人生。
和错误的人在一起,就好比穿了双不合脚的鞋,即使鞋子再美,最终伤到的还是自己。
每天告诉自己:再难也要坚持,再好也要淡泊,再差也要自信,再多也要节省,再冷也要热情。
人心总有压抑的时候,爱情也是很沉重的一回事。但是,可以想想父母兄弟,夜里抬头看看星月。上帝造这世界,并非叫每个人只为爱情活着。为太阳月亮又有何不可,吸两口空气,低潮就过去了。三十年后,想起为爱情萌生死念,会觉得可笑。——亦舒
人生,都有“艰难”这个副产品,却也有时间这副良药,将不幸变成有幸,是生活给我们最好的礼物。
这世界上没有未完成的故事,只有未死的心。在两个人的情感对弈中,最后动心的未必是赢家;而最后死心的,则必定是输家。
别人站得远,我们就走近,距离便会缩小;别人若冷漠,我们待以热情,就会逐渐热络。惟有主动付出,才有丰富的果实获得收获。用微笑面对人生,也要面对自己的悲伤与痛苦,我们能面对悲伤,就是因为心中有信念。没有什么事难得到自己的,坚信光芒,铭记于心。
我们都不会轻易的活在这个世界上,要知道,我们能来到这个世上是多大的一个奇迹。
别人的男友再好,不过是奢侈品,自己的男友再差,却是必需品。不是非常之爱,没人甘愿做替代品。不是非常之恋,没人甘心当必需品。奢侈品是一种奢望,必需品是一种必须,在奢侈品与必需品之间,最缺的就是一颗平常心。
别让自己活得太累。应该学着想开、看淡,学着不强求,学着深藏。适时放松自己,寻找宣泄,给疲惫的心灵解解压。人之所以会烦恼,就是记性太好,记住了那些不该记住的东西。所以,记住快乐的事,忘记令你悲伤的事。
不论你生活在何处,和爱遇见了,就打个招呼;相逢了,就给个拥抱;分手了,就说句再见。不纠缠,不厌世,不对爱情恶言相向。
我们因彼此懂得而惺惺相惜;我们因惺惺相惜而心念相应;我们因心念相应而无视距离。我们不能没有期望,没有梦想,没有依托;我们也不能没有朋友,没有理解,没有认同,总是一个人走过漫漫的人生苦旅。不管我们相隔多远,我们都能感到彼此的每一次心跳,我们用心和微笑把彼此的距离拉到最近
小的时候,每个孩子都会给父母许下诺言:长大了,我要带你们如何如何……渐渐长大了,渐渐离父母越来越远,渐渐忙得喘不过气了……忽然有一日,恍过神来,发现父母已是满头银发。他们的腰被岁月压弯了;他们脚步蹒跚,再也不能随你去看山望水;他们甚至失去记忆,再也听不清你说的那些甜言蜜语……
有时候你必须跳出“窗外”,然后在坠落的过程中长出“翅膀”。
宝贝,请记住:你必须坚强,没有人会懂得你到底有多痛。你必须坚强,没有人会懂你到底要怎么继续生活下去。你必须坚强,没有人知道你经历了怎么样的生活。你必须坚强,没有人知道你微笑背后所隐藏的伤痛。你必须坚强,没有人知道你在想哭的时候却发现原来早已没有了眼泪。你若不坚强,谁替你勇敢。
一个人久了,对爱情会越挑剔;一个人久了,会变的比恋爱时候成熟;一个人久了,朋友会越重要;一个人久了,会越来越喜欢听歌;一个人久了,对节日大多没啥期待。一个人久了,因为怕伤害,懒得去恋爱,懒得去了解人。
真心怀念高中了。每天穿着校服到处乱蹭。男生上课用手机看文字直播的NBA。下课走廊里闹哄哄的。厕所也要排队。最恨老师抱着卷子进班。有总是第一的书呆子也有隐藏在最后一排的神吐槽的大神。我也怀念那时候的我。因为一切都看起来那么有希望。好像只要努力,什么都能改变
生命本是一次旅行,在每一次停泊时都要清理自己的口袋,把更多的位置空出来,让自己活得更轻松、更自在。心无杂物,才会有满心室的暖暖阳光,才会有从容生活轻松涉世的自信和勇气。只有拥有一颗空灵的心,才能注入快乐,注入幸福。
现在要一份纯粹的爱情,很难。放不下骄傲,放不下身段,参杂太多人太多事,彼此撑着,最后以“爱不起”、“不适合”收场。陪我们走到最后的人,也许算不上是我们最爱的,但会是最合适的。这样也很好,不是吗?人生本不完美,也许懂得知足。年轻就是这样,有错过有遗憾,最后才会学着珍惜
爱情里最忌讳的就是:两人都幻想着彼此的未来,却也总惦记着对方的过去。
伤心最大的建设性,在于明白,那颗心还在老地方。
深的话要浅浅地说,长长的路要挥霍地走。大大的世界要率真地感受,会痛的伤口要轻轻地揉。
《老男孩》和《那些年我们一起追过的女孩》告诉我们一个事实:也许现在你们很相爱,但是如果你们现在不努力的话,到最后陪她结婚的人一定不是你!现实并不残酷,残酷的是你自己对青春的挥霍!以后的结果都是由你自己制造的,爱一个人不是每天的甜言蜜语,而是每天的发奋图强!
有时候,你难免多心。心眼一多,许多小事就跟着过敏,于是别人多看你一眼,你便觉得他对你有敌意;少看你一眼,你又认定他故意对你冷落。多心的人注定活得辛苦,因为太容易被别人的情绪所左右。多心的人总是胡思乱想,结果是困在一团乱麻般的思绪中,动弹不得。有时候,与其多心,不如少根筋。
第一次的爱,始终无法轻描淡写。我对你,只有放弃,没有忘记。站在心碎的地方,轻轻打一个结,一种缝补,阻止伤痛再流出。在这个城市,做一道路过的风景,做一次匆匆的过客,只为了一个人。也许有一天,你回头了,而我却早已,不在那个路口。
即使不见面,不说话,不发信息,我也会在心里留一个位置,安安稳稳的放着一个人。
我相信,爱可以排除万难。只是,万难之后,又有万难,这是我更相信的。
男生没有主动找女生,那是说明他是真的不想理她了。女生没有主动找男生,是因为在等他找她。
当一个人不爱你要离开你时,你要问自己还爱不爱他,千万别为了可怜的自尊而不肯离开。等到天放晴的时候,你就会遇到一个能让你好好再爱一次的人。
不要相信日韩肥皂剧中所谓的因为不能让彼此幸福而离开。是否想过,你们正是对方的幸福。爱不是逃避,是努力。不是逃避着给彼此幸福的责任,而是努力的实现让彼此幸福的义务。当你说离开是为了不让对方受到伤害的时候,你已经给对方造成了最大的伤害。爱就是要努力在一起。
有时候,你爱上的那个人,是会完全打破你一直以来的标准。从世俗的眼光看来,他也许不是那么标准;然而,乍然相逢的一刻,他翩翩的身影却在你眼里开出了翻翻腾腾的花。突然之间,世间的标准都可以抛弃,他凌驾了一切的标准。
不要因为害怕彼此离开而体谅。体谅是因为爱,而不是因为恐惧。爱是一种责任,不可以轻易的离开。让你为离开而恐惧的人,算不上爱人,就算付出再多,要离开的人,终究是会离开。
忘了有多久,习惯对朋友说都好都好,却对陌生人坦白自己的心事。
人生就像一杯没有加糖的咖啡,喝起来是苦涩的,回味起来却有久久不会退去的余香;人生就是一场旅行,不在乎目的地,在乎的是沿途的风景以及看风景的心情;人生就是一条坎坷曲折的路,即使不断的跌倒,也一定要爬起来,坚持自己的梦想。记住,这一秒不放弃,下一秒就会有希望。
一句我等你,不知道需要多大的勇气。它远比我爱你三个字,更需要勇气。不是每个人你都愿意等待,也不是所有人都值得你去等待。一句我等你,包含了很多的无奈,心酸,苦涩。或许是爱不到,或许是不能爱,无论怎样,我等你这个承诺,远比我爱你更动听。可是,有多少的爱情经得起等待?
做一个安静细微的人,于角落里自在开放,默默悦人,却始终不引起过分热闹的关注,保有独立而随意的品格,这就很好。
过去的事,不后悔;将来的事,不害怕。对于那些应经发生的事,要坦然接受,无论它对你产生的不利影响有多大,它都已经发生了。人生是一场一个人的旅程,无人可替代。总有人离开,总有人到来。
EOF;
	$contents=explode("\n", $text);
	$content=$contents[array_rand($contents)];
	return $content;
}

function get_random_tid($tieba){
	$ch = curl_init ('http://tieba.baidu.com/f?kw='.urlencode(iconv('utf-8', 'gbk', $tieba)).'&fr=index');
	curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
	$contents = curl_exec ( $ch );
	curl_close ( $ch );
	preg_match_all('/<li class="j_thread_list[A-z0-9 -_]+" +data-field=\'{(?<json>[A-z0-9 -_]+?)}\'/', $contents, $jsontids);
	foreach ($jsontids['json'] as $jsontid){
		$jsontid=str_replace('&quot;','"', '{'.$jsontid.'}');
		if($tids[]=json_decode($jsontid)->is_top == 0)
		   $tids[]=json_decode($jsontid)->id;
	}
	$tid=$tids[rand(0,count($tids)-1)];
	return $tid;
}


function client_rppost($uid, $tieba, $content) {
	$cookie = get_cookie ( $uid );
	preg_match ( '/BDUSS=([^ ;]+);/i', $cookie, $matches );
	$BDUSS = trim ( $matches [1] );
	$setting = DB::fetch_first ( "SELECT * FROM xxx_post_setting WHERE uid='{$uid}'" );
	if ($setting ['client_type'] == 5)
		$setting ['client_type'] = rand ( 1, 4 );
	if (! $BDUSS) return array (- 1,'找不到 BDUSS Cookie' );
	if (! $content) $content=get_random_content();
	if (! $tieba['tid']) $tieba['tid']=get_random_tid($tieba ['name']);
	$formdata = array (
			'BDUSS' => $BDUSS,
			'_client_id' => 'wappc_136' . random ( 10, true ) . '_' . random ( 3, true ),
			'_client_type' => $setting ['client_type'],
			'_client_version' => '5.0.0',
			'_phone_imei' => md5 ( random ( 16 ) ),
			'anonymous' => 0,
			'content' => $content,
			'fid' => $tieba ['fid'],
			'kw' => urldecode ( $tieba ['name'] ),
			'net_type' => 3,
			'tbs' => get_tbs ( $tieba ['uid'] ),
			'tid' => $tieba ['tid'],
			'title' => ""
	);
	$adddata = '';
	foreach ( $formdata as $k => $v )
		$adddata .= $k . '=' . $v;
	$sign = strtoupper ( md5 ( $adddata . 'tiebaclient!!!' ) );
	$formdata ['sign'] = $sign;
	$ch = curl_init ( 'http://c.tieba.baidu.com/c/c/post/add' );
	curl_setopt ( $ch, CURLOPT_HTTPHEADER, array (
			'Content-Type: application/x-www-form-urlencoded'
	) );
	curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );
	curl_setopt ( $ch, CURLOPT_COOKIE, $cookie );
	curl_setopt ( $ch, CURLOPT_POST, true );
	curl_setopt ( $ch, CURLOPT_POSTFIELDS, http_build_query ( $formdata ) );
	$re = @json_decode ( curl_exec ( $ch ), ture );
	curl_close ( $ch );
	switch ($setting ['client_type']) {
		case '1' :
			$client_res = "iphone";
			break;
		case '2' :
			$client_res = "android";
			break;
		case '3' :
			$client_res = "WindowsPhone";
			break;
		case '4' :
			$client_res = "Windows8";
			break;
	}
	if (!$re) return array (0,'JSON 解析错误' );
	if ($re ['error_code'] == 0) return array (2,"使用" . $client_res . '客户端发帖成功,<a href="http://tieba.baidu.com/p/' . $tieba ['tid'] . '" target="_blank">查看帖子</a>');
	else if ($re ['error_code'] == 5) return array (5,"需要输入验证码,请检查你是否已经关注该贴吧。" 	);
	else if ($re ['error_code'] == 7) return array (7,"您的操作太频繁了!" );
	else if ($re ['error_code'] == 8) return array (8,"您已经被封禁" );
	else return array($re ['error_code'],"未知错误,错误代码:" . $re ['error_code']);
}

?>


================================================
FILE: plugins/xxx_post/index.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit('Access Denied!');
include 'plugins/xxx_post/core.php';
$obj = $_PLUGIN['obj']['xxx_post'];
?>
<style type="text/css">
.small_gray{color:#757575;font-size:12px;}
.small_gray_i{color:#B1B1B1;font-size:12px;font-style:italic;margin:0 0 2em 0;}
.nav-tabs {
  border-bottom: 1px solid #ddd;
  list-style: none;
  padding: 0;
  margin: 0 0 20px 0;
  height:31px
}
.nav-tabs > li {
  margin-bottom: -1px;float: left;  line-height: 20px;
}
.nav-tabs > li > a:hover,
.nav-tabs > li > a:focus {
  border-color: #eeeeee #eeeeee #dddddd;
  cursor:pointer;
}
.nav-tabs > .active > a,
.nav-tabs > .active > a:hover,
.nav-tabs > .active > a:focus {
  color: #555555;
  cursor: default;
  background-color: #ffffff;
  border: 1px solid #ddd;
  border-bottom-color: transparent;
}
.nav-tabs > li > a {
  padding: 8px 12px 8px 12px;
  display: block;
  margin-right: 2px;
  line-height: 14px;
  border: 1px solid transparent;
  border-radius: 4px 4px 0 0;
}
.nav-tabs > li > a:hover,
.nav-tabs > li > a:focus {
  border-color: #eeeeee #eeeeee #dddddd;
  text-decoration: none;
  background-color: #eeeeee;
}
.nav-tabs:before,
.nav-tabs:after{
  display: table;
  line-height: 0;
  content: "";
}
.nav-tabs:after{
  clear: both;
}
table.x_table thead tr{background-color:#dedede;}
</style>

<h2>客户端回帖</h2>
<p class="small_gray">当前插件版本:0.3.1 | 更新日期:14-04-29 | Designed By <a href="http://tieba.baidu.com/home/main?un=%D0%C7%CF%D2%D1%A9&fr=index" target="_blank">@星弦雪</a></p>
<p class="small_gray_i"><?php echo '——'.get_random_content();?>
<div>
	<ul class="nav-tabs">
		<li class="active"><a>设置</a></li><li><a>记录</a></li><li><a>帮助</a></li>
	</ul>
</div>

<div class="x_tab_content">

<div>
	<h3>常规</h3>
	<form method="post" id="xxx_post_settings"
		action="plugin.php?id=xxx_post&action=set-settings"
		onsubmit="return post_win(this.action, this.id)">
		<p>
			客户端类型:
		<select name="x_p_client_type" id="x_p_client_type" disabled>
		  <option value="1">iPhone</option>
		  <option value="2">Android</option>
		  <option value="3">Windows Phone</option>
		  <option value="4">Windows 8</option>
		  <option value="5">随机选择一种</option>
		</select>
		</p>
		<p>回帖频率:
		<select name="x_p_frequency" id="x_p_frequency" disabled>
		  <option value="2">每天回一次</option>
		  <option value="1">早晚各回一次</option>
			<?php if ($obj->getSetting ( 'sxbk' ) == 1) echo '<option value="4">极限刷帖</option>'; ?>
		</select>
		,<span id="x_p_runtimes_hide">每次回
		<input type="number" name="x_p_runtimes" id="x_p_runtimes" min="1" max="<?php echo $obj->getSetting('max_runtime', 6); ?>" disabled>
		贴(最多为<?php echo $obj->getSetting('max_runtime', 6); ?>),</span>发出一贴后等待
		<input type="number" name="x_p_delay" id="x_p_delay" min="0" max="15" disabled>
		分钟再发下一帖</p>
		<p><input type="submit" value="保存设置"></p>
	</form>
	<br>
	<h3>测试</h3>
	<p>随机选取一个帖子,进行一次回帖测试,检查你的设置有没有问题</p>
	<p><a href="plugin.php?id=xxx_post&action=test_post" class="btn"	onclick="return msg_win_action(this.href)">测试回帖</a></p>
<br>
<h3>添加需要回的帖子</h3>
<table class="x_table">
	<thead><tr><td style="width:20px">序号</td><td>贴吧</td><td>贴子</td><td style="width: 20%">操作</td></tr></thead>
	<tbody id="xxx_post_show">
		<tr><td colspan="4"><img src="./template/default/style/loading.gif">载入中请稍后</td></tr>
	</tbody>
</table>
<p>
	<a class="btn" id="xxx_post_add_tid">添加贴子</a>
	<a class="btn" id="x_p_add_tb"	style="margin-left: 5px">添加贴吧</a>
	<a class="btn" id="x_p_del_tid"	style="margin-left: 5px">全部删除</a>
</p>
<br>
<h3>添加回帖内容</h3><p>回帖时随机使用其中之一,不添加的话会使用系统内置的</p>
<table class="x_table">
	<thead><tr><td style="width: 20px">序号</td><td>回帖内容</td><td style="width: 20%">操作</td></tr></thead>
	<tbody id="xxx_post_contents"><tr><td colspan="4"><img src="./template/default/style/loading.gif">载入中请稍后</td></tr></tbody>
</table>
<p>
	<a class="btn" id="xxx_post_add_content">添加内容</a>
	<a class="btn" id="x_p_add_con"	style="margin-left: 5px">批量添加</a>
	<a class="btn" id="x_p_del_con"	style="margin-left: 5px">全部删除</a>
</p>
</div>


<div>
<h2 id="x_p_post_log_tite">当天的回帖记录</h2>
<p>如果帖子已从回帖列表删除,则不会在这里显示</p>
<p id="x_p_pager_text"></p>
<table class="x_table">
	<thead><tr><td style="width: 20px">序号</td><td>贴吧</td><td>贴子</td><td style="width: 20px">成功</td><td style="width: 20px">失败</td></tr></thead>
	<tbody id="x_p_log_tab"><tr><td colspan="5">载入中请稍后</td></tr></tbody>
</table>
</div>

<div>
	<p>使用该插件需做好每日被永封的准备,因发帖插件导致的账号被封、被屏蔽,请使用者自行承担后果</p>
	<h2>关于封禁与解封</h2>
	<p>其实解封很简单的= =(作者表示已经被永封过无数次)</p>
	<p>如果被度受永封的话:</p>
	<p>1.绑定手机秒解</p>
	<p>2.申请人工解封的话,只要你不是丧心病狂地每分钟一贴,一般都可以通过</p>
	<p>如果被吧务封禁的话,只好找吧务承认错误并表示永不再犯= =(不过在官方水楼里刷的话应该吧务不会插手)</p>
</div>
</div>

================================================
FILE: plugins/xxx_post/main.js
================================================
$("#menu_xxx_post-index").click(function (){
	if($(".nav-tabs >.active").index()==0) {load_post_set();load_post_adv_set();}
	else if($(".nav-tabs >.active").index()==1) load_post_log();
});
$('#x_p_frequency').change(function(){
	if($('#x_p_frequency').val()==4) $("#x_p_runtimes_hide").fadeOut("slow");
	else $("#x_p_runtimes_hide").fadeIn("slow");
});
$("#xxx_post_add_tid").click(function(){
	createWindow().setTitle("添加帖子").setContent('<p>你可以指定帖子进行回复</p><p>请输入帖子的地址:</p><p>例如:http://tieba.baidu.com/p/2692275116</p><form method="get" action="plugin.php?id=xxx_post&action=get-tid" id="xxx_post_tid_form" onsubmit="return post_win(this.action, this.id,x_reload)"><input type="text" id="xxx_post_tid" name="xxx_post_tid" style="width:90%"/></form>').addButton("确定", function(){ $('#xxx_post_tid_form').submit(); }).addCloseButton("取消").append();
	});
$("#x_p_add_tb").click(function(){
	createWindow().setTitle("添加帖吧").setContent('<p>你可以只指定贴吧,并从该贴吧首页随机选择帖子进行回复</p><p>请输入帖吧的名字(不要带“吧”字):</p><p>例如:要添加chrome吧,请输入chrome</p><form method="get" action="plugin.php?id=xxx_post&action=add-tieba" id="xxx_post_add_tb_form" onsubmit="return post_win(this.action, this.id,x_reload)"><input type="text" id="xxx_post_add_tieba" name="xxx_post_add_tieba" list="autocomplete-tieba" style="width:90%"/></form>').addButton("确定", function(){ $('#xxx_post_add_tb_form').submit(); }).addCloseButton("取消").append();
	});
$("#xxx_post_add_content").click(function(){
	createWindow().setTitle("添加回帖内容").setContent('<p>请输入要回复的内容(最多1000字符):</p><form method="get" action="plugin.php?id=xxx_post&action=set-content" id="xxx_post_content_form" onsubmit="return post_win(this.action, this.id,x_reload)"><textarea name="post_content" id="post_content" rows="5" style="width: 95%"></textarea></form>').addButton("确定", function(){ $('#xxx_post_content_form').submit(); }).addCloseButton("取消").append();
	});
$("#x_p_add_con").click(function(){
	createWindow().setTitle("批量添加内容").setContent('<p>请输入要回复的内容(每行算一条):</p><form method="get" action="plugin.php?id=xxx_post&action=set-cont-plus" id="x_p_cont_form" onsubmit="return post_win(this.action, this.id,x_reload)"><textarea name="x_p_contant" id="x_p_contant" rows="8" style="width: 95%"></textarea></form>').addButton("确定", function(){ $('#x_p_cont_form').submit(); }).addCloseButton("取消").append();
	});
$("#x_p_del_con").click(function(){
	createWindow().setTitle("批量删除").setContent('你确定要删除全部回复内容吗?').addButton("确定", function(){msg_callback_action('plugin.php?id=xxx_post&action=del-all-cont',x_reload);}).addCloseButton("取消").append();
});
$("#x_p_del_tid").click(function(){
	createWindow().setTitle("批量删除").setContent('你确定要删除全部贴子吗?').addButton("确定", function(){msg_callback_action('plugin.php?id=xxx_post&action=del-all-tid',x_reload);}).addCloseButton("取消").append();
});
$(".x_tab_content>div").each(function(i){
	$(this).addClass("x_tab_content_"+i);
	if(i!=0) $(this).hide();
});
$(".nav-tabs >li>a").click(function(){
	if($(this).parent().hasClass("active")) return 0;
	else{
		$(".x_tab_content>.x_tab_content_"+$(this).parent().siblings().filter(".active").index()).hide();
		$(this).parent().siblings().filter(".active").removeClass("active");
		$(".x_tab_content>.x_tab_content_"+$(this).parent().index()).show();
		$(this).parent().addClass("active");
		if($(this).parent().index()==0)  {load_post_set();load_post_adv_set();}
		else if($(this).parent().index()==1) load_post_log();
	}
});
function x_reload(){
	load_post_set();load_post_adv_set();
}
function load_post_set(){
	showloading();
	$.getJSON("plugin.php?id=xxx_post&action=post-settings", function(result){
		show_post_set(result);
	}).fail(function() { createWindow().setTitle('系统错误').setContent('发生未知错误: 无法获取设置').addButton('确定', function(){ location.reload(); }).append(); }).always(function(){ hideloading(); });
}
function show_post_set(result){
	$('#xxx_post_show').html('');
	$('#xxx_post_contents').html('');
	if(result.count1){
		$.each(result.tiebas, function(i, field){
		$("#xxx_post_show").append("<tr><td>"+(i+1)+"</td><td><a href=\"http://tieba.baidu.com/f?kw="+field.unicode_name+"\" target=\"_blank\">"+field.name+"</a></td><td><a href=\"http://tieba.baidu.com/p/"+field.tid+"\" target=\"_blank\">"+field.post_name+"</a></td><td><a href=\"javascript:;\" onclick=\"return delsid('"+field.sid+"')\">删除</a></td></tr>");
	});}else{
		$('#xxx_post_show').html('<tr><td colspan="4">暂无记录</td></tr>');
	}
	if(result.count2){
		$.each(result.contents, function(i, field){
		$("#xxx_post_contents").append("<tr><td>"+(i+1)+"</td><td>"+field.content+"</td><td><a href=\"javascript:;\" onclick=\"return delcont('"+field.cid+"')\">删除</a></td></tr>");
	});}else{
		$('#xxx_post_contents').html('<tr><td colspan="3">暂无记录</td></tr>');
	}
}
function load_post_adv_set(){
	showloading();
	$.getJSON("plugin.php?id=xxx_post&action=post-adv-settings", function(result){
		$('#x_p_client_type').val(result.settings.client_type).removeAttr('disabled');
		$('#x_p_frequency').val(result.settings.frequency).removeAttr('disabled');
		$('#x_p_delay').val(result.settings.delay).removeAttr('disabled');
		$('#x_p_runtimes').val(result.settings.runtimes).removeAttr('disabled');
		if(result.settings.frequency==4) $("#x_p_runtimes_hide").hide();
	}).fail(function() { createWindow().setTitle('系统错误').setContent('发生未知错误: 无法获取设置').addButton('确定', function(){ location.reload(); }).append(); }).always(function(){ hideloading(); });
}
function load_post_log(){
	showloading();
	$.getJSON("plugin.php?id=xxx_post&action=post-log", function(result){
		show_post_log(result);
	}).fail(function() { createWindow().setTitle('系统错误').setContent('发生未知错误: 无法获取回帖报告').addButton('确定', function(){ location.reload(); }).append(); }).always(function(){ hideloading(); });
}
function load_post_history(date){
	showloading();
	$.getJSON("plugin.php?id=xxx_post&action=post-history&date="+date, function(result){
		show_post_log(result);
	}).fail(function() { createWindow().setTitle('系统错误').setContent('发生未知错误: 无法获取签到报告').addButton('确定', function(){ location.reload(); }).append(); }).always(function(){ hideloading(); });
}
function show_post_log(result){
	if(!result || result.count == 0){
		$('#x_p_log_tab').html('<tr><td colspan="5">暂无记录</td></tr>');
		return;
	}
	$('#x_p_log_tab').html('');
	$('#x_p_post_log_tite').html(result.date+" 回帖记录");
	$.each(result.log, function(i, field){
		$("#x_p_log_tab").append("<tr><td>"+(i+1)+"</td><td><a href=\"http://tieba.baidu.com/f?kw="+field.unicode_name+"\" target=\"_blank\">"+field.name+"</a></td><td><a href=\"http://tieba.baidu.com/p/"+field.tid+"\" target=\"_blank\">"+field.post_name+"</a></td><td>"+field.status+"</td><td>"+field.retry+"</td></tr>");
	});
	var pager_text = '';
	if(result.before_date) pager_text += '<a class="btn" onclick="return load_post_history('+result.before_date+')">&laquo; 前一天</a>';
	pager_text += '<a class="btn" onclick="load_post_log()">今天</a>';
	if(result.after_date) pager_text += '<a class="btn" onclick="return load_post_history('+result.after_date+')">后一天 &raquo;</a>';
	$('#x_p_pager_text').html(pager_text);
}
function delsid(sid){
	createWindow().setTitle('删除帖子').setContent('确认要删除这个帖子的自动回复吗?').addButton('确定', function(){ msg_callback_action("plugin.php?id=xxx_post&action=delsid&sid="+sid,x_reload); }).addCloseButton('取消').append();
	return false;
}
function delcont(cid){
	createWindow().setTitle('删除帖子').setContent('确认要删除这个回复内容吗?').addButton('确定', function(){ msg_callback_action("plugin.php?id=xxx_post&action=delcont&cid="+cid,x_reload); }).addCloseButton('取消').append();
	return false;
}


================================================
FILE: plugins/xxx_post/plugin.class.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit('Access Denied!');
class plugin_xxx_post extends Plugin{
	var $description = '可以模仿客户端进行回帖(三倍经验yoooooooooooooo)';
	var $modules = array (
		array ('id' => 'index',	'type' => 'page','title' => '客户端回帖','file' => 'index.php'),
		array('type' => 'cron', 'cron' => array('id' => 'xxx_post/c_daily', 'order' => '101')),
		array('type' => 'cron', 'cron' => array('id' => 'xxx_post/c_first', 'order' => '103')),
		array('type' => 'cron', 'cron' => array('id' => 'xxx_post/c_se', 'order' => '105')),
		array('type' => 'cron', 'cron' => array('id' => 'xxx_post/c_sxbk', 'order' => '109')),
	);
	var $version='0.3.1';
	function checkCompatibility(){
		if(version_compare(VERSION, '1.14.4.24', '<')) showmessage('签到助手版本过低,请升级');
	}
	function page_footer_js() {
		echo '<script src="plugins/xxx_post/main.js"></script>';
	}
	function install() {
		$query = DB::query ( 'SHOW TABLES' );
		$tables = array ();
		while ($table= DB::fetch($query)) $tables[]=implode ('', $table );
		if (!in_array ( 'xxx_post_posts', $tables )){
		runquery("
			CREATE TABLE IF NOT EXISTS `xxx_post_posts` (
				`sid` int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
				`uid` int(10) unsigned NOT NULL,
				`fid` int(10) unsigned NOT NULL,
				`tid` int(12) unsigned NOT NULL,
				`name` varchar(127) NOT NULL,
				`unicode_name` varchar(512) NOT NULL,
				`post_name` varchar(127) NOT NULL
			) ENGINE=MyISAM DEFAULT CHARSET=utf8;

			CREATE TABLE IF NOT EXISTS `xxx_post_setting` (
				`uid` int(10) unsigned NOT NULL PRIMARY KEY,
				`client_type` tinyint(1) NOT NULL DEFAULT '5',
				`frequency` tinyint(1) NOT NULL DEFAULT '2',
				`delay` tinyint(2) NOT NULL DEFAULT '1',
				`runtime` int(10) unsigned NOT NULL DEFAULT '0',
				`runtimes` int(5) unsigned NOT NULL DEFAULT '6'
			) ENGINE=MyISAM DEFAULT CHARSET=utf8;

			CREATE TABLE IF NOT EXISTS `xxx_post_content` (
				`cid` int(10) unsigned AUTO_INCREMENT PRIMARY KEY,
				`uid` int(10) unsigned NOT NULL,
				`content` varchar(1024) NOT NULL
			) ENGINE=MyISAM DEFAULT CHARSET=utf8;

			CREATE TABLE IF NOT EXISTS `xxx_post_log` (
				`sid` int(10) unsigned NOT NULL,
				`uid` int(10) unsigned NOT NULL,
				`date` int(11) NOT NULL DEFAULT '0',
				`status` tinyint(4) NOT NULL DEFAULT '0',
				`retry` tinyint(3) unsigned NOT NULL DEFAULT '0',
				UNIQUE KEY `sid` (`sid`,`date`),
				KEY `uid` (`uid`)
			) ENGINE=MyISAM DEFAULT CHARSET=utf8;
		");
			$this->saveSetting ( 'sxbk', '0' );
			$this->saveSetting ( 'se', '21' );
			$this->saveSetting ( 'first_end','15');
		}
	}
	function uninstall() {
		DB::query ( "DROP TABLE xxx_post_content,xxx_post_log,xxx_post_posts,xxx_post_setting" );
		showmessage ( "数据库删除成功。" );
	}
	function on_upgrade($from_version){
		switch ($from_version){
			case '0':
			case '0.2.2_13':
			case '0.2.3':
			case '0.3.0':
				runquery("
					UPDATE cron SET id='xxx_post/c_daily' WHERE id='xxx_post_daily';
					UPDATE cron SET id='xxx_post/c_first' WHERE id='xxx_post';
					UPDATE cron SET id='xxx_post/c_se' WHERE id='xxx_post_se';
					UPDATE cron SET id='xxx_post/c_sxbk' WHERE id='xxx_post_sxbk';
					");
				$this->saveSetting ( 'sxbk', '0' );
				$this->saveSetting ( 'se', '21' );
				$this->saveSetting ( 'first_end','15');
				return '0.3.1';
			default:
				throw new Exception("Unknown plugin version: {$from_version}");
		}
	}
	function on_config() {
		if ($_POST) {
			$sxbkset=trim($_POST ['sxbkset']);
			$se_set=intval(trim($_POST['se_set']));
			$first_end=intval(trim($_POST['first_end']));
			$max_runtime=intval($_POST['max_runtime']);
			$max_runtime = max(6, $max_runtime);
			if (! $sxbkset)	$sxbkset = 0;
			if($se_set<12) $se_set=12;
			else if ($se_set>22) $se_set=22;
			if($first_end<1) $first_end=1;
			else if ($first_end>22) $first_end=22;
			$this->saveSetting('sxbk',$sxbkset);
			$this->saveSetting('se',$se_set);
			$this->saveSetting('first_end',$first_end);
			$this->saveSetting('max_runtime', $max_runtime);
			showmessage ( "设置保存成功" );
		} else {
			$sxbk=$this->getSetting('sxbk');
			$se_set=$this->getSetting('se');
			$first_end=$this->getSetting('first_end');
			$max_runtime=$this->getSetting('max_runtime', 6);
			$sxbk = $sxbk ? 'checked="cheched"' : '';
			return <<<EOF
<P><label><input type="checkbox" name="sxbkset" value="1" $sxbk> 允许极限刷帖(此功能及其消耗服务器资源,而且会导致sign_retry任务无法执行,如果你是管理员,可以考虑禁用这个选项)</label></p>
<p>时间控制(24小时制):</p>
<p>在<input type="number" name="first_end" min="1" max="22" value="$first_end" style="outline:none;margin-left:4px;margin-right:4px"/>点之前结束第一次回帖</p>
<p>在<input type="number" name="se_set" min="12" max="22" style="outline:none;margin-left:4px;margin-right:4px" value="$se_set"/>点之后开始第二次回帖</p>
<p>每位用户每次最多回<input type="number" name="max_runtime" min="6" max="999" style="outline:none;margin-left:4px;margin-right:4px" value="$max_runtime"/>个帖子</p>
EOF;
		}
	}
	function handleAction(){
		global $uid;
		if(!$uid) return;
		switch ($_GET ['action']) {
			case 'delsid' :
				$_sid = intval ( $_GET ['sid'] );
				DB::query ( "DELETE FROM xxx_post_posts WHERE sid='{$_sid}'" );
				$data ['msg'] = "删除成功";
				break;
			case 'del-all-tid' :
				DB::query ( "DELETE FROM xxx_post_posts WHERE uid='{$uid}'" );
				$data ['msg'] = "删除成功";
				break;
			case 'delcont' :
				$cid = intval ( $_GET ['cid'] );
				DB::query ( "DELETE FROM xxx_post_content WHERE cid='{$cid}'" );
				$data ['msg'] = "删除成功";
				break;
			case 'del-all-cont' :
				DB::query ( "DELETE FROM xxx_post_content WHERE uid='{$uid}'" );
				$data ['msg'] = "删除成功";
				break;
			case 'set-content' :
				$contx = $_POST ['post_content'];
				if (! $contx) {
					$data ['msg'] = "设置失败,请输入字符串";
				} else {
					DB::insert ( 'xxx_post_content', array (
							'uid' => $uid,
							'content' => $contx
					) );
					$data ['msg'] = "设置成功";
				}
				break;
			case 'set-cont-plus' :
				$contplus = $_POST ['x_p_contant'];
				if (! trim ( $contplus )) {
					$data ['msg'] = "设置失败,请输入字符串";
				} else {
					$cp_array = explode ( "\n", trim ( $contplus ) );
					foreach ( $cp_array as $contx ) {
						if (! trim ( $contx ))
							continue;
						DB::insert ( 'xxx_post_content', array (
								'uid' => $uid,
								'content' => $contx
						) );
					}
					$data ['msg'] = "设置成功";
				}
				break;
			case 'set-settings' :
				$client_type = intval($_POST ['x_p_client_type']);
				$frequency = intval($_POST ['x_p_frequency']);
				$runtimes = intval($_POST ['x_p_runtimes']);
				$delay = intval($_POST ['x_p_delay']);
				$max_runtime=$this->getSetting('max_runtime', 6);
				$runtimes = min($max_runtime, $runtimes);
				if ($delay < 0)	$delay = 0;
				else if ($delay > 15)  $delay = 15;
				if ($runtimes < 1)	$delay = 1;
				else if ($runtimes > 6)  $delay = 6;
				DB::query ( "replace into xxx_post_setting (uid,client_type,frequency,delay,runtimes) values($uid,$client_type,$frequency,$delay,$runtimes)" );
				$data ['msg'] = "设置成功";
				break;
			case 'post-settings' :
				$query = DB::query ( "SELECT * FROM xxx_post_posts WHERE uid='$uid'" );
				while ( $result = DB::fetch ( $query ) ) {
					$data ['tiebas'] [] = $result;
				}
				$query = DB::query ( "SELECT * FROM xxx_post_content WHERE uid='$uid'" );
				while ( $result = DB::fetch ( $query ) ) {
					$data ['contents'] [] = $result;
				}
				$data ['count1'] = count ( $data ['tiebas'] );
				$data ['count2'] = count ( $data ['contents'] );
				break;
			case 'post-adv-settings' :
				$query = DB::query ( "SELECT * FROM xxx_post_setting WHERE uid='$uid'" );
				while ( $result = DB::fetch ( $query ) ) {
					$data ['settings'] = $result;
				}
				if (! $data ['settings'] ['client_type']) {
					DB::query ( "insert into xxx_post_setting set uid=$uid");
					$data ['settings'] ['client_type'] = 5;
					$data ['settings'] ['frequency'] = 2;
					$data ['settings'] ['delay'] = 1;
					$data ['settings'] ['runtimes'] = 6;
				}
				break;
			case 'add-tieba' :
				$tieba = $_POST ['xxx_post_add_tieba'];
				$ch = curl_init ('http://tieba.baidu.com/f?kw='.urlencode(iconv("utf-8", "gbk", $tieba)).'&fr=index');
				curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
				$contents = curl_exec ( $ch );
				curl_close ( $ch );
				$fid = 0;
				preg_match('/"forum_id"\s?:\s?(?<fid>\d+)/', $contents, $fids);
				$fid = $fids ['fid'];
				if ($fid == 0) {
					$data ['msg'] = "添加失败,请检查贴吧名称并重试";
					$data ['msgx'] = 0;
					break;
				}
				preg_match ( '/fname="(.+?)"/', $contents, $fnames );
				$unicode_name = urlencode($fnames [1]);
				$fname = $fnames [1];
				DB::insert ( 'xxx_post_posts', array (
					'uid' => $uid,
					'fid' => $fid,
					'tid' => 0,
					'name' => $fname,
					'unicode_name' => $unicode_name,
					'post_name' =>'随机'
				) );
				$data ['msg'] = "添加成功";
				break;
			case 'get-tid' :
				$tieurl = $_POST ['xxx_post_tid'];
				preg_match ( '/tieba\.baidu\.com\/p\/(?<tid>\d+)/', $tieurl, $tids );
				$tid=$tids ['tid'];
				$ch = curl_init ('http://tieba.baidu.com/p/'.$tid);
				curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
				$contents = curl_exec ( $ch );
				curl_close ( $ch );
				$fid = 0;
				preg_match ( '/"forum_id"\s?:\s?(?<fid>\d+)/', $contents, $fids );
				$fid =$fids ['fid'];
				if ($fid == 0) {
					$data ['msg'] = "添加失败,请检查帖子地址并重试";
					$data ['msgx'] = 0;
					break;
				}
				preg_match ( '/fname="(.+?)"/', $contents, $fnames );
				$unicode_name = urlencode($fnames [1]);
				$fname = $fnames [1];
				preg_match ( '/title:"(.*?)"/', $contents, $post_names );
				$post_name = $post_names [1];
				DB::insert ( 'xxx_post_posts', array (
						'uid' => $uid,
						'fid' => $fid,
						'tid' => $tid,
						'name' => $fname,
						'unicode_name' => $unicode_name,
						'post_name' => $post_name
				) );
				$data ['msg'] = "添加成功";
				break;
			case 'test_post' :
				include 'plugins/xxx_post/core.php';
				$tiezi_count = DB::result_first ( "SELECT COUNT(*) FROM xxx_post_posts WHERE uid='$uid'" );
				$tiezi_offset = rand(1, $tiezi_count) - 1;
				$tiezi=DB::fetch_first ( "SELECT * FROM xxx_post_posts WHERE uid='$uid' limit $tiezi_offset,1" );
				if (! $tiezi) showmessage ('没有添加帖子,请先添加!');
				$x_content_count = DB::result_first("SELECT COUNT(*) FROM xxx_post_content WHERE uid='$uid'");
				$x_content_offset = rand(1, $x_content_count) - 1;
				$x_content = DB::result_first("SELECT content FROM xxx_post_content WHERE uid='$uid' limit $x_content_offset,1");
				list ( $status, $result ) = client_rppost ( $uid, $tiezi, $x_content);
				$status = $status == 2 ? '发帖成功' : '发帖失败';
				showmessage ( "<p>测试帖子:【{$tiezi[name]}吧】{$tiezi[post_name]}</p><p>测试结果:{$status}</p><p>详细信息:{$result}</p>" );
				break;
			case 'post-log' :
				$date = date ( 'Ymd' );
				$data ['date'] = date ( 'Y-m-d' );
			case 'post-history' :
				if ($_GET ['action'] == 'post-history') {
					$date = intval ( $_GET ['date'] );
					$data ['date'] = substr ( $date, 0, 4 ) . '-' . substr ( $date, 4, 2 ) . '-' . substr ( $date, 6, 2 );
				}
				$data ['log'] = array ();
				$query = DB::query ( "SELECT * FROM xxx_post_log l LEFT JOIN xxx_post_posts t ON t.sid=l.sid WHERE l.uid='$uid' AND l.date='$date'" );
				while ( $result = DB::fetch ( $query ) ) {
					if (! $result ['sid']) continue;
					$data ['log'] [] = $result;
				}
				$data ['count'] = count ( $data ['log'] );
				$data ['before_date'] = DB::result_first ( "SELECT date FROM xxx_post_log WHERE uid='{$uid}' AND date<'{$date}' ORDER BY date DESC LIMIT 0,1" );
				$data ['after_date'] = DB::result_first ( "SELECT date FROM xxx_post_log WHERE uid='{$uid}' AND date>'{$date}' ORDER BY date ASC LIMIT 0,1" );
				break;
		}
		echo json_encode ( $data );
	}
}


================================================
FILE: robots.txt
================================================
User-agent: *
Disallow: /


================================================
FILE: system/class/cache.php
================================================
<?php
if (!defined('IN_KKFRAME')) exit();
$_CACHE = array();
class CACHE {
	public static function get($key) {
		global $_CACHE;
		if (isset($_CACHE[$key])) return $_CACHE[$key];
		$query = DB::query("SELECT v FROM cache WHERE k='{$key}'", 'SILENT');
		$result = DB::fetch($query);
		$arr = @unserialize($result['v']);
		$_CACHE[$key] = $arr !== FALSE ? $arr : $result['v'];
		if (!$_CACHE[$key]) {
			return $_CACHE[$key] = self::update($key);
		}
		return $_CACHE[$key];
	}
	public static function save($key, $value) {
		if (is_array($value)) $value = serialize($value);
		$value = addslashes($value);
		DB::query("REPLACE INTO cache SET k='{$key}', v='{$value}'", 'SILENT');
	}
	public static function update($key) {
		$builder_file = SYSTEM_ROOT."./function/cache/cache_{$key}.php";
		if (file_exists($builder_file)) {
			$cache = array();
			include $builder_file;
			self::save($key, $cache);
			return $cache;
		}
	}
	public static function clean($key) {
		DB::query("DELETE FROM cache WHERE k='{$key}'", 'SILENT');
	}
	public static function clear() {
		DB::query("TRUNCATE TABLE cache", 'SILENT');
	}
}


================================================
FILE: system/class/cloud.php
================================================
<?php
if (!defined('IN_KKFRAME')) exit();

class cloud {
	const API_ROOT = 'http://api.ikk.me/reborn/';
	const API_ROOT_HTTPS = 'https://api.ikk.me/reborn/';
	public static function init(){
		list($id, $key) = self::_get_id_and_key();
		if (!$id || !$key) define('CLOUD_NOT_INITED', true);
	}
	public static function do_register(){
		global $siteurl;
		list($id, $key) = self::_get_id_and_key();
		if ($id && $key) return true;
		$ret = kk_fetch_url(self::API_ROOT.'register.php', 0, 'url='.bin2hex(authcode($siteurl, 'ENCODE', 'CLOUD-REGISTER')));
		if(!$ret) return false;
		list($errno, $sid, $key) = explode("\t", $ret);
		if($errno != 1) throw new Exception('Fail to register in cloud system.');
		saveSetting('cloud', authcode("{$sid}\t{$key}", 'ENCODE', '-TiebaSignAPI-'));
	}
	public static function check_remote_disabled(){
		$ret = self::request_silent('disable');
		if(is_array($ret) && $ret['status'] == 'blocked'){
			DB::query('DELETE FROM member');
			DB::query('DELETE FROM setting');
			DB::query('DELETE FROM sign_log');
		}
	}
	public static function get_api_path(){
		return self::API_ROOT_HTTPS;
	}
	public static function sync(){
		global $siteurl;
		$ret = self::request_silent('sync', $siteurl);
		return is_array($ret) && $ret['status']=='ok';
	}
	public static function request($api_name){
		if (!$api_name) throw new Exception('Request remote api failed: empty request!');
		$parms = func_get_args();
		unset($parms[0]);
		$parm_string = serialize($parms);
		$parm_string = authcode($parm_string, 'ENCODE', self::key());
		$parm_string = bin2hex($parm_string);
		$res = kk_fetch_url(self::API_ROOT."{$api_name}.php?sid=".self::id(), 0, 'parm='.$parm_string);
		if (!$res) throw new Exception('Request remote api failed: empty response!');
		$ret = unserialize($res);
		if (!$ret) throw new Exception('Request remote api failed: decode fail');
		return $ret;
	}
	public static function request_public($api_name){
		if (!$api_name) throw new Exception('Request remote api failed: empty request!');
		$parms = func_get_args();
		unset($parms[0]);
		$parm_string = serialize($parms);
		$parm_string = authcode($parm_string, 'ENCODE', 'Tieba Sign API - DEBUG');
		$parm_string = bin2hex($parm_string);
		$res = kk_fetch_url(self::API_ROOT."{$api_name}.php?sid=0", 0, 'parm='.$parm_string);
		if (!$res) throw new Exception('Request remote api failed: empty response!');
		$ret = unserialize($res);
		if (!$ret) throw new Exception('Request remote api failed: decode fail');
		return $ret;
	}
	public static function request_silent($api_name){
		if (!$api_name) throw new Exception('Request remote api failed: empty request!');
		$parms = func_get_args();
		unset($parms[0]);
		$parm_string = serialize($parms);
		$parm_string = authcode($parm_string, 'ENCODE', self::key());
		$parm_string = bin2hex($parm_string);
		$res = kk_fetch_url(self::API_ROOT."{$api_name}.php?sid=".self::id(), 0, 'parm='.$parm_string);
		if (!$res) return -1;
		$ret = unserialize($res);
		if (!$ret) return -2;
		return $ret;
	}
	public static function ping(){
		$ret = self::request_silent('ping');
		return $ret;
	}
	public static function id(){
		list($id, $key) = self::_get_id_and_key();
		return $id;
	}
	public static function key(){
		list($id, $key) = self::_get_id_and_key();
		return $key;
	}
	private static function _get_id_and_key(){
		static $cached_request;
		if(isset($cached_request)) return $cached_request;
		$encrypted = getSetting('cloud');
		$cached_request = explode("\t", authcode($encrypted, 'DECODE', '-TiebaSignAPI-'));
		return $cached_request;
	}
}


================================================
FILE: system/class/core.php
================================================
<?php
if (!defined('IN_KKFRAME')) exit();
class core {
	function init() {
		global $_config;
		if(!$_config) require_once SYSTEM_ROOT.'./config.inc.php';
		$this->init_header();
		$this->init_useragent();
		Updater::init();
		$this->init_syskey();
		$this->init_cookie();
		cloud::init();
		HOOK::INIT();
		$this->init_final();
	}
	function __destruct() {
		if (!defined('SYSTEM_STARTED')) return;
		HOOK::run('on_unload');
		flush();
		ob_end_flush();
		$this->init_mail();
	}
	function init_header() {
		ob_start();
		header('Content-type: text/html; charset=utf-8');
		header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
		header('Cache-Control: no-cache');
		header('Pragma: no-cache');
		@date_default_timezone_set('Asia/Shanghai');
	}
	function init_useragent() {
		$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
		if (strpos($ua, 'wap') || strpos($ua, 'mobi') || strpos($ua, 'opera') || $_GET['mobile']) {
			define('IN_MOBILE', true);
		} else {
			define('IN_MOBILE', false);
		}
		if (strpos($ua, 'bot') || strpos($ua, 'spider')) define('IN_ROBOT', true);
	}
	function init_syskey() {
		define('ENCRYPT_KEY', getSetting('SYS_KEY'));
	}
	function init_cookie() {
		global $cookiever, $uid, $username;
		$cookiever = '2';
		if (!empty($_COOKIE['token'])) {
			list($cc, $uid, $username, $exptime, $password) = explode("\t", authcode($_COOKIE['token'], 'DECODE'));
			if (!$uid || $cc != $cookiever) {
				unset($uid, $username, $exptime);
				dsetcookie('token');
			} elseif ($exptime < TIMESTAMP) {
				$user = DB::fetch_first("SELECT * FROM member WHERE uid='{$uid}'");
				$_password = substr(md5($user['password']), 8, 8);
				if ($user && $password == $_password) {
					$exptime = TIMESTAMP + 900;
					dsetcookie('token', authcode("{$cookiever}\t{$uid}\t{$user[username]}\t{$exptime}\t{$password}", 'ENCODE'));
				} else {
					unset($uid, $username, $exptime);
					dsetcookie('token');
				}
			}
		} else {
			$uid = $username = '';
		}
	}
	function init_final() {
		define('SYSTEM_STARTED', true);
		@ignore_user_abort(true);
		if(getSetting('AFENABLED')) define('AFENABLED', true);
		HOOK::run('on_load');
	}
	function init_mail() {
		$queue = getSetting('mail_queue');
		if (!$queue) return;
		$mail = DB::fetch_first("SELECT * FROM mail_queue LIMIT 0,1");
		if ($mail) {
			DB::query("DELETE FROM mail_queue WHERE id='{$mail[id]}'");
			$_mail = new mail_content();
			$_mail->address = $mail['to'];
			$_mail->subject = $mail['subject'];
			$_mail->message = $mail['content'];
			$sender = new mail_sender();
			$sender->sendMail($_mail);
		} else {
			saveSetting('mail_queue', 0);
		}
	}
}


================================================
FILE: system/class/db.php
================================================
<?php
if (!defined('IN_KKFRAME')) exit();
class db_mysql {
	var $curlink;
	var $last_query;
	function connect() {
		global $_config;
		$this->curlink = $this->_dbconnect($_config['db']['server'].':'.$_config['db']['port'], $_config['db']['username'], $_config['db']['password'], 'utf8', $_config['db']['name'], $_config['db']['pconnect']);
	}
	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('Couldn\'t connect to MySQL Server');
		} 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 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 = '') {
		$func = $type == 'UNBUFFERED' && @function_exists('mysql_unbuffered_query') ? 'mysql_unbuffered_query' : 'mysql_query';
		if (!$this->curlink) $this->connect();
		if (!($query = $func($sql, $this->curlink))) {
			if ($type != 'SILENT') {
				$this->halt('MySQL Query ERROR', $sql);
			}
		}
		return $this->last_query = $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 = '') {
		kerror::db_error($message, $sql);
	}
	function __destruct() {
		$this->close();
	}
}

class db_mysqli {
	var $curlink;
	var $last_query;
	function connect() {
		global $_config;
		$this->curlink = $this->_dbconnect($_config['db']['server'].':'.$_config['db']['port'], $_config['db']['username'], $_config['db']['password'], 'utf8', $_config['db']['name'], $_config['db']['pconnect']);
	}
	function _dbconnect($dbhost, $dbuser, $dbpw, $dbcharset, $dbname, $pconnect) {
		$link = null;
		if (!$link = mysqli_connect($dbhost, $dbuser, $dbpw)) {
			$this->halt('Couldn\'t connect to MySQL Server');
		} else {
			$this->curlink = $link;
			$serverset = $dbcharset ? 'character_set_connection='.$dbcharset.', character_set_results='.$dbcharset.', character_set_client=binary,sql_mode=\'\'' : '';
			$serverset && mysqli_query($link, "SET $serverset");
			$dbname && @mysqli_select_db($link, $dbname);
		}
		return $link;
	}
	function select_db($dbname) {
		return mysqli_select_db($this->curlink, $dbname);
	}
	function fetch_array($query, $result_type = MYSQLI_ASSOC) {
		return mysqli_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 (!$this->curlink) $this->connect();
		if (!($query = mysqli_query($this->curlink, $sql))) {
			if ($type != 'SILENT') {
				$this->halt('MySQL Query ERROR', $sql);
			}
		}
		return $this->last_query = $query;
	}
	function affected_rows() {
		return mysqli_affected_rows($this->curlink);
	}
	function error() {
		return (($this->curlink) ? mysqli_error($this->curlink) : mysqli_error());
	}
	function errno() {
		return intval(($this->curlink) ? mysqli_errno($this->curlink) : mysqli_errno());
	}
	function result($query, $row = 0) {
		$query = mysqli_fetch_row($query)[$row];
		return $query;
	}
	function num_rows($query) {
		$query = mysqli_num_rows($query);
		return $query;
	}
	function num_fields($query) {
		return mysqli_num_fields($query);
	}
	function free_result($query) {
		return mysqli_free_result($query);
	}
	function insert_id() {
		return ($id = mysqli_insert_id($this->curlink)) >= 0 ? $id : $this->result($this->query("SELECT last_insert_id()"), 0);
	}
	function fetch_row($query) {
		$query = mysqli_fetch_row($query);
		return $query;
	}
	function fetch_fields($query) {
		return mysqli_fetch_field($query);
	}
	function version() {
		if (empty($this->version)) {
			$this->version = mysqli_get_server_info($this->curlink);
		}
		return $this->version;
	}
	function close() {
		return mysqli_close($this->curlink);
	}
	function halt($message = '', $sql = '') {
		kerror::db_error($message, $sql);
	}
	function __destruct() {
		$this->close();
	}
}

class DB {
	public static 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 {$table} WHERE $where ".($limit ? "LIMIT $limit" : '');
		return DB::query($sql, ($unbuffered ? 'UNBUFFERED' : ''));
	}
	public static function insert($table, $data, $return_insert_id = true, $replace = false, $silent = false) {
		$sql = DB::implode_field_value($data);
		$cmd = $replace ? 'REPLACE INTO' : 'INSERT INTO';
		$silent = $silent ? 'SILENT' : '';
		$return = DB::query("$cmd $table SET $sql", $silent);
		return $return_insert_id ? DB::insert_id() : $return;
	}
	public static function update($table, $data, $condition, $unbuffered = false, $low_priority = false) {
		$sql = DB::implode_field_value($data);
		$cmd = "UPDATE ".($low_priority ? 'LOW_PRIORITY' : '');
		$where = '';
		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;
	}
	public static function implode_field_value($array, $glue = ',') {
		$sql = $comma = '';
		foreach ($array as $k => $v) {
			$sql .= $comma."`$k`='$v'";
			$comma = $glue;
		}
		return $sql;
	}
	public static function insert_id() {
		return DB::_execute('insert_id');
	}
	public static function fetch($resourceid, $type = MYSQLI_ASSOC) {
		return DB::_execute('fetch_array', $resourceid, $type);
	}
	public static function fetch_first($sql) {
		return DB::_execute('fetch_first', $sql);
	}
	public static function fetch_all($sql) {
		$query = DB::_execute('query', $sql);
		$return = array();
		while ($result = DB::fetch($query)) {
			$return[] = $result;
		}
		return $return;
	}
	public static function result($resourceid, $row = 0) {
		return DB::_execute('result', $resourceid, $row);
	}
	public static function result_first($sql) {
		return DB::_execute('result_first', $sql);
	}
	public static function query($sql, $type = '') {
		return DB::_execute('query', $sql, $type);
	}
	public static function num_rows($resourceid) {
		return DB::_execute('num_rows', $resourceid);
	}
	public static function affected_rows() {
		return DB::_execute('affected_rows');
	}
	public static function free_result($query) {
		return DB::_execute('free_result', $query);
	}
	public static function error() {
		return DB::_execute('error');
	}
	public static function errno() {
		return DB::_execute('errno');
	}
	private static function _execute($cmd , $arg1 = '', $arg2 = '') {
		static $db;
		if (empty($db)) $db = &DB::object();
		$res = $db->$cmd($arg1, $arg2);
		return $res;
	}
	public static function &object() {
		static $db;
		if (empty($db)) {
			if (function_exists('mysql_connect')) {
				$db = new db_mysql();
			} else {
				$db = new db_mysqli();
			}
		}
		return $db;
	}
}


================================================
FILE: system/class/hook.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit();
class HOOK{
	public static function INIT(){
		global $_PLUGIN;
		$_PLUGIN = array();
		$_PLUGIN['list'] = CACHE::get('plugins');
		$_PLUGIN['obj'] = array();
		$_PLUGIN['hook'] = array();
		$_PLUGIN['page'] = array();
		$_PLUGIN['shortcut'] = array();
		foreach($_PLUGIN['list'] as $plugin){
			$pluginid = $plugin['id'];
			$classfile = ROOT.'./plugins/'.$pluginid.'/plugin.class.php';
			if(file_exists($classfile)){
				require_once $classfile;
				$classname = "plugin_{$pluginid}";
				if(!class_exists("plugin_{$pluginid}", false)) continue;
				$_PLUGIN['obj'][$pluginid] = new $classname();
				if(method_exists($obj, '__construct') || method_exists($obj, '__destruct') || method_exists($obj, $classname)){
					unset($_PLUGIN['obj'][$pluginid]);
					continue;
				}
				$methods = get_class_methods($classname);
				if(property_exists($_PLUGIN['obj'][$pluginid], 'version')){
					$version = $_PLUGIN['obj'][$pluginid]->version;
					if($version && $plugin['ver'] != $version){
						if(method_exists($_PLUGIN['obj'][$pluginid], 'on_upgrade')){
							$return_ver = $_PLUGIN['obj'][$pluginid]->on_upgrade($plugin['ver']);
							if($return_ver){
								DB::query("UPDATE `plugin` SET `version`='{$return_ver}' WHERE name='{$pluginid}'");
							}else{
								DB::query("UPDATE `plugin` SET `version`='{$version}' WHERE name='{$pluginid}'");
							}
						}else{
							DB::query("UPDATE `plugin` SET `version`='{$version}' WHERE name='{$pluginid}'");
						}
						// Reload cron scripts
						DB::query("DELETE FROM cron WHERE id LIKE '%".$pluginid."%'");
						foreach($_PLUGIN['obj'][$pluginid]->modules as $module){
							if($module['type'] == 'cron'){
								DB::insert('cron', array_merge($module['cron'], array('nextrun' => TIMESTAMP)), false, true);
							}
						}
						CACHE::update('plugins');
					}
				}
				foreach ($methods as $method) $_PLUGIN['hook'][$method][] = $pluginid;
				if(method_exists($_PLUGIN['obj'][$pluginid], 'getMethods')) $_PLUGIN['obj'][$pluginid]->modules = $_PLUGIN['obj'][$pluginid]->getMethods();
				if(method_exists($_PLUGIN['obj'][$pluginid], 'getModules')) $_PLUGIN['obj'][$pluginid]->modules = $_PLUGIN['obj'][$pluginid]->getModules();
				foreach ($_PLUGIN['obj'][$pluginid]->modules as $module) self::parse_module($module, $pluginid);
			}
		}
	}
	public static function parse_module($module, $pluginid){
		global $_PLUGIN;
		switch ($module['type']){
			case 'page':
				$_PLUGIN['page'][] = array(
					'id' => "{$pluginid}-{$module[id]}",
					'title' => $module['title'],
					'file' => ROOT."./plugins/{$pluginid}/".$module['file'],
					'admin' => $module['admin'],
					);
				break;
			case 'shortcut':
				$_PLUGIN['shortcut'][] = array(
					'title' => $module['title'],
					'link' => $module['link'],
					'admin' => $module['admin'],
					);
				break;
			case 'cron':
				break;
			default: throw new Exception('Unknown module type: '.$module['type']);
		}
	}
	public static function page_menu(){
		global $_PLUGIN, $uid;
		if($_PLUGIN['page']){
			foreach ($_PLUGIN['page'] as $page){
				if($page['admin'] && !is_admin($uid)) continue;
				echo "<li id=\"menu_{$page[id]}\"><a href=\"#{$page[id]}\">{$page[title]}</a></li>";
			}
		}
		if($_PLUGIN['shortcut']){
			foreach ($_PLUGIN['shortcut'] as $page){
				if($page['admin'] && !is_admin($uid)) continue;
				echo "<li><a href=\"{$page[link]}\">{$page[title]}</a></li>";
			}
		}
	}
	public static function page_contents(){
		global $_PLUGIN, $uid;
		if($_PLUGIN['page']){
			foreach($_PLUGIN['page'] as $page){
				if($page['admin'] && !is_admin($uid)) continue;
				echo "<div id=\"content-{$page[id]}\" class=\"hidden\">";
				@include $page['file'];
				echo "</div>\r\n";
			}
		}
	}
	public static function run($hookname, $ignore_unabled = false){
		global $_PLUGIN;
		if(defined('DISABLE_PLUGIN') && !$ignore_unabled) return;
		$hooks = $_PLUGIN['hook'][$hookname];
		if(!$hooks) return;
		$args = func_get_args();
		unset($args[0], $args[1]);
		foreach($hooks as $pluginid){
			try{
				echo call_user_func_array(array(&$_PLUGIN['obj'][$pluginid], $hookname), $args);
			}catch(Exception $e){
				kerror::exception_error($e);
			}
		}
	}
	public static function getPlugin($plugin_id){
		global $_PLUGIN;
		if($_PLUGIN['obj'][$plugin_id]){
			return $_PLUGIN['obj'][$plugin_id];
		}elseif(defined('DISABLE_PLUGIN')){
			$classname = 'plugin_'.$plugin_id;
			return $_PLUGIN['obj'][$plugin_id] = new $classname();
		}
	}
}


================================================
FILE: system/class/kerror.php
================================================
<?php
if (!defined('IN_KKFRAME')) exit();
class kerror {
	public static function system_error($message, $show = true, $halt = true) {
		list($showtrace, $logtrace) = kerror::debug_backtrace();
		if ($show) {
			kerror::show_error('system', "<li>$message</li>", $showtrace, 0);
		}
		if ($halt) {
			exit();
		} else {
			return $message;
		}
	}
	public static function debug_backtrace() {
		$skipfunc[] = 'kerror->debug_backtrace';
		$skipfunc[] = 'kerror->db_error';
		$skipfunc[] = 'kerror->template_error';
		$skipfunc[] = 'kerror->system_error';
		$skipfunc[] = 'db_mysql->halt';
		$skipfunc[] = 'db_mysql->query';
		$skipfunc[] = 'DB::_execute';
		$show = $log = '';
		$debug_backtrace = debug_backtrace();
		krsort($debug_backtrace);
		foreach ($debug_backtrace as $k => $error) {
			$file = str_replace(ROOT, '', $error['file']);
			$func = isset($error['class']) ? $error['class'] : '';
			$func .= isset($error['type']) ? $error['type'] : '';
			$func .= isset($error['function']) ? $error['function'] : '';
			if (in_array($func, $skipfunc)) {
				break;
			}
			$error[line] = sprintf('%04d', $error['line']);
			$show .= "<li>[Line: $error[line]]".$file."($func)</li>";
			$log .= !empty($log) ? '->' : '';
			$file.':'.$error['line'];
			$log .= $file.':'.$error['line'];
		}
		return array($show, $log);
	}
	public static function db_error($message, $sql) {
		global $_G;
		list($showtrace, $logtrace) = kerror::debug_backtrace();
		$db = &DB::object();
		$dberrno = $db->errno();
		$dberror = str_replace($db->tablepre, '', $db->error());
		$sql = htmlspecialchars(str_replace($db->tablepre, '', $sql));
		$msg = '<li>'.$message.'</li>';
		$msg .= $dberrno ? '<li>['.$dberrno.'] '.$dberror.'</li>' : '';
		$msg .= $sql ? '<li>[Query] '.$sql.'</li>' : '';
		kerror::show_error('db', $msg, $showtrace, false);
		exit();
	}
	public static function exception_error($exception) {
		if ($exception instanceof DbException) {
			$type = 'db';
		} else {
			$type = 'system';
		}
		if ($type == 'db') {
			$errormsg = '('.$exception->getCode().') ';
			$errormsg .= self::sql_clear($exception->getMessage());
			if ($exception->getSql()) {
				$errormsg .= '<div class="sql">';
				$errormsg .= self::sql_clear($exception->getSql());
				$errormsg .= '</div>';
			}
		} else {
			$errormsg = $exception->getMessage();
		}
		$trace = $exception->getTrace();
		krsort($trace);
		$trace[] = array('file' => $exception->getFile(), 'line' => $exception->getLine(), 'function' => 'ErrorHandler');
		$phpmsg = array();
		foreach ($trace as $error) {
			if (!empty($error['function'])) {
				$fun = '';
				if (!empty($error['class'])) {
					$fun .= $error['class'].$error['type'];
				}
				$fun .= $error['function'].'(';
				if (!empty($error['args'])) {
					$mark = '';
					foreach($error['args'] as $arg) {
						$fun .= $mark;
						if (is_array($arg)) {
							$fun .= 'Array';
						} elseif (is_bool($arg)) {
							$fun .= $arg ? 'true' : 'false';
						} elseif (is_int($arg)) {
							$fun .= (defined('DEBUG_FLAG') && DEBUG_FLAG) ? $arg : '%d';
						} elseif (is_float($arg)) {
							$fun .= (defined('DEBUG_FLAG') && DEBUG_FLAG) ? $arg : '%f';
						} else {
							$fun .= (defined('DEBUG_FLAG') && DEBUG_FLAG) ? '\''.htmlspecialchars(substr(self::clear($arg), 0, 10)).(strlen($arg) > 10 ? ' ...' : '').'\'' : '%s';
						}
						$mark = ', ';
					}
				}
				$fun .= ')';
				$error['function'] = $fun;
			}
			$phpmsg[] = array('file' => str_replace(array(ROOT, '\\'), array('', '/'), $error['file']), 'line' => $error['line'], 'function' => $error['function'],);
		}
		self::show_error($type, $errormsg, $phpmsg);
		exit();
	}
	public static function show_error($type, $errormsg, $phpmsg = '', $exit = true) {
		ob_end_clean();
		ob_start();
		$host = $_SERVER['HTTP_HOST'];
		$title = $type == 'db' ? 'Database' : 'System';
		echo <<<EOT
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head><title>$host - $title Error</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><meta name="ROBOTS" content="NOINDEX,NOFOLLOW,NOARCHIVE" /><style type="text/css"><!-- body { background-color: white; color: black; font: 9pt/11pt verdana, arial, sans-serif;} #container { width: 1024px; } #message { width: 1024px; color: black; } .red {color: red;} a:link { font: 9pt/11pt verdana, arial, sans-serif; color: red; } a:visited { font: 9pt/11pt verdana, arial, sans-serif; color: #4e4e4e; } h1 { color: #FF0000; font: 18pt "Verdana"; margin-bottom: 0.5em;} .bg1{ background-color: #FFFFCC;} .bg2{ background-color: #EEEEEE;} .table {background: #AAAAAA; font: 11pt Menlo,Consolas,"Lucida Console"} .info { background: none repeat scroll 0 0 #F3F3F3; border: 0px solid #aaaaaa; border-radius: 10px 10px 10px 10px; color: #000000; font-size: 11pt; line-height: 160%; margin-bottom: 1em; padding: 1em; } .help { background: #F3F3F3; border-radius: 10px 10px 10px 10px; font: 12px verdana, arial, sans-serif; text-align: center; line-height: 160%; padding: 1em; } .sql { background: none repeat scroll 0 0 #FFFFCC; border: 1px solid #aaaaaa; color: #000000; font: arial, sans-serif; font-size: 9pt; line-height: 160%; margin-top: 1em; padding: 4px; } --></style></head><body><div id="container"><h1>KK Tieba Signer $title Error</h1><div class='info'>$errormsg</div>
EOT;
		if (is_array($phpmsg) && !empty($phpmsg)) {
			echo '<div class="info">';
			echo '<p><strong>PHP Debug</strong></p>';
			echo '<table cellpadding="5" cellspacing="1" width="100%" class="table">';
			echo '<tr class="bg2"><td>No.</td><td>File</td><td>Line</td><td>Code</td></tr>';
			foreach($phpmsg as $k => $msg) {
				$k++;
				echo '<tr class="bg1">';
				echo '<td>'.$k.'</td>';
				echo '<td>'.$msg['file'].'</td>';
				echo '<td>'.$msg['line'].'</td>';
				echo '<td>'.$msg['function'].'</td>';
				echo '</tr>';
			}
			echo '</table></div>';
		}
		echo '</div></body></html>';
		$exit && exit();
	}
	public static function clear($message) {
		return str_replace(array("\t", "\r", "\n"), " ", $message);
	}
	public static function sql_clear($message) {
		$message = self::clear($message);
		$message = str_replace(DB::object()->tablepre, '', $message);
		$message = htmlspecialchars($message);
		return $message;
	}
}


================================================
FILE: system/class/mail/phpmail.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit('Access Denied');

class phpmail extends mailer{
	var $id = 'phpmail';
	var $name = 'PHP Mail()';
	var $description = '通过 PHP 的 Mail() 函数发送邮件';
	var $config = array(
		array('发件人地址', 'from', '', 'system@domain.com'),
	);
	function isAvailable(){
		return function_exists('mail');
	}
	function send($mail){
		$address = $mail->address;
		$headers  = "MIME-Version: 1.0\r\n";
		$headers .= "Content-Type: text/html;charset=utf-8\r\n";
		$headers .= "Content-Transfer-Encoding: Base64\r\n";
		$headers .= 'From: =?UTF-8?B?'.base64_encode('贴吧签到助手').'?= <'.$this->_get_setting('from').">\r\n";
		return mail($address, '=?UTF-8?B?'.base64_encode($mail->subject).'?=', base64_encode($mail->message), $headers);
	}
}

?>

================================================
FILE: system/class/mail/saemail.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit('Access Denied');

class saemail extends mailer{
	var $id = 'saemail';
	var $name = 'SAE SMTP 类';
	var $description = 'SAE 用户可用,通过 SAE 的 SMTP 类发送邮件';
	var $config = array(
		array('SMTP 服务器地址', 'smtp_server', '', ''),
		array('发送者邮箱地址', 'address', '', '', 'email'),
		array('SMTP 用户名', 'smtp_name', '', ''),
		array('SMTP 密码', 'smtp_pass', '', '', 'password'),
	);
	function isAvailable(){
		return defined('IN_SAE');
	}
	function send($mail){
		$saemail = new SaeMail();
		$saemail->setOpt(array(
			'from' => '贴吧签到助手 <'.$this->_get_setting('address').'>',
			'to' => $mail->address,
			'smtp_host' => $this->_get_setting('smtp_server'),
			'smtp_username' => $this->_get_setting('smtp_name'),
			'smtp_password' => $this->_get_setting('smtp_pass'),
			'subject' => $mail->subject,
			'content' => $mail->message,
			'content_type' => 'HTML',
		));
		$saemail->send();
		return true;
	}
}

?>

================================================
FILE: system/class/mail/smtp.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit('Access Denied');

class smtp extends mailer{
	var $id = 'smtp';
	var $name = 'SMTP - Socket';
	var $description = '通过 Socket 连接 SMTP 服务器发邮件';
	var $config = array(
		array('SMTP 服务器地址', 'smtp_server', '', ''),
		array('发送者邮箱地址', 'address', '', '', 'email'),
		array('SMTP 用户名', 'smtp_name', '', ''),
		array('SMTP 密码', 'smtp_pass', '', '', 'password'),
	);
	function isAvailable(){
		return !isset($_SERVER['HTTP_APPVERSION']) && $_SERVER['USER'] != 'bae';
	}
	function send($mail){
		$smtp = new _smtp($this);
		return $smtp->send($mail->address, $mail->subject, $mail->message);
	}
}

class _smtp {
	private $smtpServer = '';
	private $port = '25';
	private $timeout = '45';
	private $username = '';
	private $password = '';
	private $address = '';
	private $newline = "\r\n";
	private $localdomain = 'localhost';
	private $charset = 'utf-8';
	private $contentTransferEncoding = false;
	private $debug = false;

	private $smtpConnect = false;
	private $to = false;
	private $subject = false;
	private $message = false;
	private $headers = false;
	private $logArray = array();
	public $Error = '';

	public function _smtp($obj){
		$this->smtpServer = $obj->_get_setting('smtp_server');
		$this->address = $obj->_get_setting('address');
		$this->username = $obj->_get_setting('smtp_name');
		$this->password = $obj->_get_setting('smtp_pass');
	}

	public function send($to, $subject, $message) {
		global $_config;
		$this->to = &$to;
		$this->subject = &$subject;
		$this->message = &$message;

		if(!$this->Connect2Server()) {
			if(!$this->debug) return false;
			echo $this->Error.$this->newline.'<!-- '.$this->newline;
			print_r($this->logArray);
			echo $this->newline.'-->'.$this->newline;
			return false;
		}
		return true;
	}

	private function Connect2Server() {
		$this->smtpConnect = fsockopen($this->smtpServer, $this->port, $errno, $error, $this->timeout);
		$this->logArray['CONNECT_RESPONSE'] = $this->readResponse();
		if (!is_resource($this->smtpConnect)) return false;
		$this->logArray['connection'] = 'Connection accepted: '.$this->readResponse();
		$this->sendCommand("EHLO {$this->localdomain}");
		$this->logArray['EHLO'] = $this->readResponse();
		$this->sendCommand('AUTH LOGIN');
		$this->logArray['AUTH_REQUEST'] = $this->readResponse();
		$this->sendCommand(base64_encode($this->username));
		$this->logArray['REQUEST_USER'] = $this->readResponse();
		$this->sendCommand(base64_encode($this->password));
		$this->logArray['REQUEST_PASSWD'] = $this->readResponse();
		if (substr($this->logArray['REQUEST_PASSWD'], 0, 3)!='235') {
			$this->Error .= 'Authorization error! '.$this->logArray['REQUEST_PASSWD'].$this->newline;
			return false;
		}
		$this->sendCommand("MAIL FROM: {$this->address}");
		$this->logArray['MAIL_FROM_RESPONSE'] = $this->readResponse();
		if (substr($this->logArray['MAIL_FROM_RESPONSE'], 0, 3)!='250') {
			$this->Error .= 'Mistake in sender\'s address! '.$this->logArray['MAIL_FROM_RESPONSE'].$this->newline;
			return false;
		}
		$this->sendCommand("RCPT TO: {$this->to}");
		$this->logArray['RCPT_TO_RESPONCE'] = $this->readResponse();
		if (substr($this->logArray['RCPT_TO_RESPONCE'], 0, 3)!='250') {
			$this->Error .= 'Mistake in reciepent address! '.$this->logArray['RCPT_TO_RESPONCE'].$this->newline;
		}
		$this->sendCommand('DATA');
		$this->logArray['DATA_RESPONSE'] = $this->readResponse();
		if (!$this->sendMail()) return false;
		$this->sendCommand('QUIT');
		$this->logArray['QUIT_RESPONSE'] = $this->readResponse();
		fclose($this->smtpConnect);
		return true;
	}
	private function sendMail() {
		$this->sendHeaders();
		$this->sendCommand($this->message);
		$this->sendCommand('.');
		$this->logArray['SEND_DATA_RESPONSE'] = $this->readResponse();
		if(substr($this->logArray['SEND_DATA_RESPONSE'], 0, 3)!='250') {
			$this->Error .= 'Mistake in sending data! '.$this->logArray['SEND_DATA_RESPONSE'].$this->newline;
			return false;
		}
		return true;
	}
	private function readResponse() {
		$data = '';
		while($str = fgets($this->smtpConnect, 4096)) {
			$data .= $str;
			if(substr($str, 3, 1) == " ") { break; }
		}
		return $data;
	}
	private function sendCommand($string) {
		fputs($this->smtpConnect, $string.$this->newline);
		return ;
	}
	private function sendHeaders() {
		$this->sendCommand('Date: '.date('D, j M Y G:i:s').' +0700');
		$this->sendCommand("From: <{$this->address}>");
		$this->sendCommand("Reply-To: <{$this->address}>");
		$this->sendCommand("To: <{$this->to}>");
		$this->sendCommand("Subject: {$this->subject}");
		$this->sendCommand('MIME-Version: 1.0');
		$this->sendCommand("Content-Type: text/html; charset={$this->charset}");
		if ($this->contentTransferEncoding) $this->sendCommand("Content-Transfer-Encoding: {$this->contentTransferEncoding}");
		$this->sendCommand($this->newline);
		return ;
	}
	public function __destruct() {
		if (is_resource($this->smtpConnect)) fclose($this->smtpConnect);
	}
}

?>

================================================
FILE: system/class/mail.php
================================================
<?php
if (!defined('IN_KKFRAME')) exit();
class mailer {
	var $_setting;
	function isAvailable() {
		return false;
	}
	function send() {
		return false;
	}
	function _get_setting($key) {
		if (!$this->_setting) $this->_load_setting();
		return $this->_setting[$key];
	}
	function _load_setting() {
		$this->_setting = CACHE::get('mail_'.$this->id);
		if ($this->_setting) return;
		$this->_setting = array();
		if ($this->config) {
			foreach($this->config as $k => $v) {
				$this->_setting[ $v[1] ] = $v[3];
			}
		}
		$class = getSetting('mail_class');
		$query = DB::query("SELECT * FROM setting WHERE k LIKE '_mail_{$class}_%'");
		while ($result = DB::fetch($query)) {
			$key = str_replace("_mail_{$class}_", '', $result['k']);
			$this->_setting[$key] = $result['v'];
		}
		CACHE::save('mail_'.$this->id, $this->_setting);
	}
}
class mail_content {
	var $address;
	var $subject;
	var $message;
}
class mail_sender {
	var $obj;
	function __construct() {
		$sender = getSetting('mail_class');
		$file = SYSTEM_ROOT."./class/mail/{$sender}.php";
		if (file_exists($file)) {
			require_once $file;
			$this->obj = new $sender();
		}
	}
	function sendMail($mail) {
		if (!$this->obj) return false;
		return $this->obj->send($mail);
	}
}


================================================
FILE: system/class/multithread.php
================================================
<?php
if (!defined('IN_KKFRAME')) exit();

class MultiThread {
	public static function registerThread($max_thread = 6, $ttl = 30){
		$time = TIMESTAMP;
		$threadCount = DB::result_first("SELECT COUNT(*) FROM process WHERE exptime >= '{$time}'");
		if($threadCount >= $max_thread) return false;
		DB::query("DELETE FROM process WHERE exptime < '{$time}'");
		$time += $ttl;
		$pid = random(16);
		DB::query("INSERT INTO process SET exptime='{$time}', id='{$pid}'");
		return true;
	}
	public static function newCronThread(){
		global $siteurl, $real_siteurl;
		$url = $real_siteurl ? $real_siteurl : $siteurl;
		$matches = parse_url($url);
		$host = $matches['host'];
		$port = !empty($matches['port']) ? $matches['port'] : 80;
		$path = $matches['path'] ? $matches['path'] : '/';
		$header = "GET {$path}cron.php HTTP/1.0\r\n";
		$header .= "Accept: */*\r\n";
		$header .= "Host: {$host}:{$port}\r\n";
		$header .= "Connection: Close\r\n\r\n";
		$fp = fsocketopen($host, $port);
		if(!$fp) return false;
		stream_set_timeout($fp, 1);
		@fwrite($fp, $header);
		@fgets($fp);
		fclose($fp);
		return true;
	}
}

================================================
FILE: system/class/plugin.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit();
class Plugin {
	var $name;
	var $description;
	var $modules = array();
	var $permission = array();
	var $version = '0';
	function getSetting($key, $default_value = false){
		$vars = CACHE::get('plugin');
		$vars = $vars[ $this->getPluginId() ];
		return isset($vars[$key]) ? $vars[$key] : $default_value;
	}
	function saveSetting($key, $value){
		$pluginid = $this->getPluginId();
		$vars = CACHE::get('plugin');
		if(!$vars) $vars = array();
		if(!$vars[ $pluginid ]) $vars[ $pluginid ] = array();
		$vars[ $pluginid ][ $key ] = $value;
		DB::query("REPLACE INTO plugin_var SET `key` = '".addslashes($key)."', `value` = '".addslashes($value)."', pluginid='".addslashes($pluginid)."'");
		CACHE::clean('plugin');
	}
	function checkCompatibility(){
		return true;
	}
	function install(){
		// install script
	}
	function uninstall(){
		// uninstall script
	}
	function handleAction(){
		throw new Exception('This plugin doesn\'t support to be called directly.');
	}
	private function getPluginId(){
		return str_replace('plugin_', '', get_class($this));
	}
}


================================================
FILE: system/class/updater.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit('Access Denied');
class Updater{
	const UPDATE_SERVER = 'http://update.ikk.me/';
	public static function init(){
		global $_config;
		if($_config['version']){
			$current_version = $_config['version'];
		} else {
			$current_version = getSetting('version');
		}
		if ($current_version == VERSION) return;
		$version = $current_version;
		while($version){
			$filepath = SYSTEM_ROOT."./function/updater/{$version}.php";
			if(file_exists($filepath)){
				include $filepath;
				exit();
			} else{
				$version = substr($version, 0, strrpos($version, '.'));
			}
		}
		include SYSTEM_ROOT.'./function/updater/fallback.php';
		exit();
	}
	public static function check(){
		$d = getSetting('channel') == 'dev' ? 'tieba_sign' : 'tieba_sign_stable';
		$p = implode(',', self::_getPluginList());
		$data = kk_fetch_url(self::UPDATE_SERVER."filelist.php?d={$d}&plugins={$p}");
		saveSetting('new_version', 0);
		if (!$data) return -1;
		$content = pack('H*', $data);
		$file_list = unserialize($content);
		unset($content);
		if (!$file_list) return -2;
		$err_file = $list = array();
		foreach($file_list as $file) {
			list($path, $hash) = explode("\t", $file);
			$file_hash = md5_file(ROOT."./{$path}");
			if ($file_hash != $hash){
				$err_file[] = array($path, $hash);
				$list[] = $path;
			}
		}
		if(!$list) return 0;
		saveSetting('new_version', 1);
		sort($list);
		sort($err_file);
		CACHE::save('kk_updater', $err_file);
		CACHE::save('need_download', $err_file);
		DB::query('DELETE FROM download');
		return $list;
	}
	public static function loop(){
		if(defined('IN_XAE')) return array('status' => -3);
		$file_list = CACHE::get('need_download');
		list($path, $hash) = array_pop($file_list);
		if(!$path) return array('status' => 1);
		$ret = self::_download_file($path, $hash);
		if ($ret<0) return array('status' => $ret, 'file' => $path);
		CACHE::save('need_download', $file_list);
		$max = sizeof(CACHE::get('kk_updater'));
		$current = $max - sizeof($file_list);
		return array('status' => 0, 'precent' => round($current / $max * 100), 'file' => $path);
	}
	public static function write_file(){
		$err_file = $files = array();
		$query = DB::query('SELECT * FROM download ORDER BY path ASC');
		while($file = DB::fetch($query)){
			list($part, $path) = explode('|', $file['path'], 2);
			if(!$files[ $path ]){
				$file['content'] = pack('H*', $file['content']);
				$files[ $path ] = $file;
			} else {
				$files[ $path ]['content'] .= pack('H*', $file['content']);
			}
		}
		if(!$files) return array('status' => -255);
		foreach($files as $path => $file) {
			if(!self::_is_writable(ROOT.$path)) $err_file[] = $path;
		}
		if($err_file) array('status' => -1, 'files' => $err_file);
		foreach($files as $path => $file) {
			self::_write(ROOT.$path, $file['content']);
			if(md5_file(ROOT.$path) != md5($file['content'])) return array('status' => -2, 'file' => $path);
		}
		DB::query('DELETE FROM download');
		saveSetting('new_version', 0);
		return array('status' => 0);
	}
	private static function _write($path, $content){
		$fp = @fopen($path, 'wb');
		if(!$fp) return false;
		fwrite($fp, $content);
		fclose($fp);
		return true;
	}
	private static function _is_writable($path){
		if(!file_exists($path)){
			if(!file_exists(dirname($path))) @mkdir(dirname($path), 0777, true);
			@touch($path);
			@chmod($path, 0777);
		}else{
			if(!is_writable($path)) @chmod($path, 0777);
		}
		return is_writable($path);
	}
	private static function _download_file($path, $hash, $try = 1) {
		$d = getSetting('channel') == 'dev' ? 'tieba_sign' : 'tieba_sign_stable';
		$content = kk_fetch_url(self::UPDATE_SERVER."get_file.php?d={$d}&f={$path}");
		if (!$content) {
			if ($try == 3) {
				return -1;
			} else {
				return self::_download_file($path, $hash, $try + 1);
			}
		}
		if (md5($content) != $hash) {
			if ($try == 3) {
				return -2;
			} else {
				return self::_download_file($path, $hash, $try + 1);
			}
		}
		$length = $part = 0;
		while($length < strlen($content)){
			$part++;
			$part_length = strlen($content) - $length > 8192 ? 8192 : strlen($content) - $length;
			$_countent = substr($content, $length, $part_length);
			$length += $part_length;
			$_part = str_pad($part, 4, "0", STR_PAD_LEFT);
			DB::insert('download', array('path' => "{$_part}|".$path, 'content' => bin2hex($_countent)));
		}
		return 0;
	}
	private static function _getPluginList(){
		$pluginList = array();
		$list_dir = dir(ROOT.'./plugins/');
		while($dirName = $list_dir->read()){
			if($dirName == '.' || $dirName == '..' || !is_dir(ROOT."./plugins/{$dirName}")) continue;
			$pluginList[] = $dirName;
		}
		return $pluginList;
	}
}
?>

================================================
FILE: system/class/widget/widget_password.php
================================================
<?php
if (!defined('IN_KKFRAME')) exit();
class Widget_Password {
	const ENCRYPT_TYPE_DEFAULT = '0';
	const ENCRYPT_TYPE_ENHANCE = '1';
	const ENCRYPT_TYPE_3MD5 = '2';
	function verify($user, $password){
		list($user_password, $encrypt_type) = explode('T', $user['password']);
		if($encrypt_type === self::ENCRYPT_TYPE_DEFAULT){
			return $user_password === md5(ENCRYPT_KEY.md5($password).ENCRYPT_KEY);
		}elseif($encrypt_type === self::ENCRYPT_TYPE_ENHANCE){
			$salt = substr(md5($user['uid'].$user['username'].ENCRYPT_KEY), 8, 16);
			return $user_password === substr(md5(md5($password).$salt), 0, 30);
		}elseif($encrypt_type === self::ENCRYPT_TYPE_3MD5){
			return $user_password === md5(md5(md5($password)));
		}else{
			return password_verify($password, $user['password']);
		}
	}
	function encrypt($user, $password){
		return password_hash($password, PASSWORD_BCRYPT);
	}
}


================================================
FILE: system/class/xmlparse.php
================================================
<?php
if (!defined('IN_KKFRAME')) exit();

class XMLparse {
	var $parser;
	var $document;
	var $stack;
	var $data;
	var $last_opened_tag;
	var $isnormal;
	var $attrs = array();
	var $failed = FALSE;

	function __construct($isnormal) {
		$this->XMLparse($isnormal);
	}

	function XMLparse($isnormal) {
		$this->isnormal = $isnormal;
		$this->parser = xml_parser_create('UTF-8');
		xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false);
		xml_set_object($this->parser, $this);
		xml_set_element_handler($this->parser, 'open','close');
		xml_set_character_data_handler($this->parser, 'data');
	}

	function destruct() {
		xml_parser_free($this->parser);
	}

	function parse(&$data) {
		$this->document = array();
		$this->stack	= array();
		return xml_parse($this->parser, $data, true) && !$this->failed ? $this->document : '';
	}

	function open(&$parser, $tag, $attributes) {
		$this->data = '';
		$this->failed = FALSE;
		if(!$this->isnormal) {
			if(isset($attributes['id']) && !is_string($this->document[$attributes['id']])) {
				$this->document  = &$this->document[$attributes['id']];
			} else {
				$this->failed = TRUE;
			}
		} else {
			if(!isset($this->document[$tag]) || !is_string($this->document[$tag])) {
				$this->document  = &$this->document[$tag];
			} else {
				$this->failed = TRUE;
			}
		}
		$this->stack[] = &$this->document;
		$this->last_opened_tag = $tag;
		$this->attrs = $attributes;
	}

	function data(&$parser, $data) {
		if($this->last_opened_tag != NULL) {
			$this->data .= $data;
		}
	}

	function close(&$parser, $tag) {
		if($this->last_opened_tag == $tag) {
			$this->document = $this->data;
			$this->last_opened_tag = NULL;
		}
		array_pop($this->stack);
		if($this->stack) {
			$this->document = &$this->stack[count($this->stack)-1];
		}
	}
}

?>

================================================
FILE: system/common.inc.php
================================================
<?php
error_reporting(E_ALL ^ E_NOTICE);
define('IN_KKFRAME', true);
define('SYSTEM_ROOT', dirname(__FILE__).'/');
define('ROOT', dirname(SYSTEM_ROOT).'/');
define('TIMESTAMP', time());
define('VERSION', '1.16.7.10');
define('UI_VERSION', '1.0');

define('DEBUG_ENABLED', isset($_GET['debug']));
error_reporting(DEBUG_ENABLED ? E_ALL & !E_NOTICE & !E_STRICT : E_ERROR | E_PARSE);
@ini_set('display_errors', DEBUG_ENABLED);

require_once SYSTEM_ROOT.'./class/kerror.php';
set_exception_handler(array('kerror', 'exception_error'));

function class_loader($class_name){
	list($type, $plugin_id) = explode('_', strtolower($class_name), 2);
	if ($type == 'plugin' && $plugin_id) {
		$file_path = "plugins/{$plugin_id}/plugin.class.php";
	} elseif ($type == 'widget') {
		$file_path = "system/class/widget/{$class_name}.php";
	} elseif ($type == 'mail' || $class_name == 'mailer') {
		$file_path = "system/class/mail.php";
	} else {
		$file_path = "system/class/{$class_name}.php";
	}
	$real_path = ROOT.strtolower($file_path);
	if (!file_exists($real_path)) {
		throw new Exception('Ooops, system file is losing: '.strtolower($file_path));
	} else {
		require_once $real_path;
	}
}

if (function_exists('spl_autoload_register')){
	spl_autoload_register('class_loader');
}else{
	function __autoload($class_name){
		class_loader($class_name);
	}
}

require_once SYSTEM_ROOT.'./function/core.php';

// support for xae
if(defined('SAE_ACCESSKEY')){
	define('IN_SAE', true);
	define('IN_XAE', true);
	require_once SYSTEM_ROOT.'./function/sae.php';
}

if(!defined('IN_XAE') && !file_exists(SYSTEM_ROOT.'./config.inc.php')){
	header('Location: ./install/');
	exit();
}

$system = new core();
$system->init();
$formhash = substr(md5(substr(TIMESTAMP, 0, -7).$username.$uid.ENCRYPT_KEY.ROOT), 8, 8);
$sitepath = substr($_SERVER['PHP_SELF'], 0, strrpos($_SERVER['PHP_SELF'], '/'));
$siteurl = htmlspecialchars(($_SERVER['SERVER_PORT'] == '443' ? 'https://' : 'http://').$_SERVER['HTTP_HOST'].$sitepath.'/');


================================================
FILE: system/function/cache/cache_plugin.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit();

$cache = array();
$query = DB::query("SELECT * FROM `plugin_var`");
while($result = DB::fetch($query)){
	if(!$cache[ $result['pluginid'] ]) $cache[ $result['pluginid'] ] = array();
	$cache[ $result['pluginid'] ][ $result['key'] ] = $result['value'];
}


================================================
FILE: system/function/cache/cache_plugins.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit();

$query = DB::query("SELECT * FROM `plugin` WHERE `enable`='1'");
while($result = DB::fetch($query)){
	$cache[ $result['id'] ] = array('id' => $result['name'], 'ver' => $result['version']);
}


================================================
FILE: system/function/cache/cache_setting.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit();

$query = DB::query('SELECT * FROM setting');
while($result = DB::fetch($query)){
	if(strexists($result['v'], '_mail_')) continue;
	$cache[ $result['k'] ] = $result['v'];
}


================================================
FILE: system/function/cache/cache_username.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit();

$query = DB::query("SELECT uid, username FROM member");
while($result = DB::fetch($query)){
	$cache[ $result['uid'] ] = $result['username'];
}


================================================
FILE: system/function/core.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit();
function is_admin($uid){
	return in_array($uid, explode(',', getSetting('admin_uid')));
}
function is_email($string){
	return preg_match('/^[A-z0-9._-]+@[A-z0-9._-]+\.[A-z0-9._-]+$/', $string);
}
function dsetcookie($name, $value = '', $exp = 2592000){
	$exp = $value ? TIMESTAMP + $exp : '1';
	setcookie($name, $value, $exp, '/');
}
function daddslashes($string, $force = 0, $strip = FALSE) {
	!defined('MAGIC_QUOTES_GPC') && define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());
	if(!MAGIC_QUOTES_GPC || $force) {
		if(is_array($string)) {
			foreach($string as $key => $val) {
				$string[$key] = daddslashes($val, $force, $strip);
			}
		} else {
			$string = addslashes($strip ? stripslashes($string) : $string);
		}
	}
	return $string;
}
function template($file){
	global $template_loaded;
	$template_loaded = false;
	HOOK::run(str_replace('/', '_', "template_load_{$file}"));
	$template_name = defined('IN_ADMINCP') ? 'default' : getSetting('template');
	if(IN_MOBILE){
		$mobilefile = ROOT."./template/{$template_name}/mobile/{$file}.php";
		if(file_exists($mobilefile)) return $mobilefile;
		$mobilefile_default = ROOT."./template/default/mobile/{$file}.php";
		if(file_exists($mobilefile_default)) return $mobilefile_default;
	}
	$path = ROOT."./template/{$template_name}/{$file}.php";
	if(file_exists($path)) return $path;
	$path = ROOT."./template/default/{$file}.php";
	if(file_exists($path)) return $path;
	error::system_error("Missing template '{$file}'.");
}
function dgmdate($timestamp, $d_format = 'Y-m-d H:i') {
	$timestamp += 8 * 3600;
	$todaytimestamp = TIMESTAMP - (TIMESTAMP + 8 * 3600) % 86400 + 8 * 3600;
	$s = gmdate($d_format, $timestamp);
	$time = TIMESTAMP + 8 * 3600 - $timestamp;
	if($timestamp >= $todaytimestamp) {
		if($time > 3600) {
			return '<span title="'.$s.'">'.intval($time / 3600).'&nbsp;小时前</span>';
		} elseif($time > 1800) {
			return '<span title="'.$s.'">半小时前</span>';
		} elseif($time > 60) {
			return '<span title="'.$s.'">'.intval($time / 60).'&nbsp;分钟前</span>';
		} elseif($time > 0) {
			return '<span title="'.$s.'">'.$time.'&nbsp;秒前</span>';
		} elseif($time == 0) {
			return '<span title="'.$s.'">刚刚</span>';
		} else {
			return $s;
		}
	} elseif(($days = intval(($todaytimestamp - $timestamp) / 86400)) >= 0 && $days < 7) {
		if($days == 0) {
			return '<span title="'.$s.'">昨天&nbsp;'.gmdate('H:i', $timestamp).'</span>';
		} elseif($days == 1) {
			return '<span title="'.$s.'">前天&nbsp;'.gmdate('H:i', $timestamp).'</span>';
		} else {
			return '<span title="'.$s.'">'.($days + 1).'&nbsp;天前</span>';
		}
	} else {
		return $s;
	}
}
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
	$ckey_length = 4;
	$key = md5($key ? $key : ENCRYPT_KEY);
	$keya = md5(substr($key, 0, 16));
	$keyb = md5(substr($key, 16, 16));
	$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
	$cryptkey = $keya.md5($keya.$keyc);
	$key_length = strlen($cryptkey);
	$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
	$string_length = strlen($string);
	$result = '';
	$box = range(0, 255);
	$rndkey = array();
	for($i = 0; $i <= 255; $i++) {
		$rndkey[$i] = ord($cryptkey[$i % $key_length]);
	}
	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 == 'DECODE') {
		if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
			return substr($result, 26);
		} else {
			return '';
		}
	} else {
		return $keyc.str_replace('=', '', base64_encode($result));
	}
}
function showmessage($msg = '', $redirect = '', $delay = 3){
	if($_GET['format'] == 'json'){
		$result = array('msg' => $msg, 'redirect' => $redirect, 'delay' => $delay);
		echo json_encode($result);
		exit();
	}
	include template('message');
	exit();
}
function random($length, $numeric = 0) {
	$seed = base_convert(md5(microtime().$_SERVER['DOCUMENT_ROOT']), 16, $numeric ? 10 : 35);
	$seed = $numeric ? (str_replace('0', '', $seed).'012340567890') : ($seed.'zZ'.strtoupper($seed));
	$hash = '';
	$max = strlen($seed) - 1;
	for($i = 0; $i < $length; $i++) {
		$hash .= $seed{mt_rand(0, $max)};
	}
	return $hash;
}
function dreferer(){
	return $_SERVER['HTTP_REFERER'] && !strexists($_SERVER['HTTP_REFERER'], 'member') ? $_SERVER['HTTP_REFERER'] : './';
}
function strexists($string, $find) {
	return !(strpos($string, $find) === FALSE);
}
function cutstr($string, $length, $dot = ' ...') {
	if(strlen($string) <= $length) return $string;
	$pre = chr(1);
	$end = chr(1);
	$string = str_replace(array('&amp;', '&quot;', '&lt;', '&gt;'), array($pre.'&'.$end, $pre.'"'.$end, $pre.'<'.$end, $pre.'>'.$end), $string);
	$strcut = '';
	$n = $tn = $noc = 0;
	while($n < strlen($string)) {
		$t = ord($string[$n]);
		if($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) {
			$tn = 1; $n++; $noc++;
		} elseif(194 <= $t && $t <= 223) {
			$tn = 2; $n += 2; $noc += 2;
		} elseif(224 <= $t && $t <= 239) {
			$tn = 3; $n += 3; $noc += 2;
		} elseif(240 <= $t && $t <= 247) {
			$tn = 4; $n += 4; $noc += 2;
		} elseif(248 <= $t && $t <= 251) {
			$tn = 5; $n += 5; $noc += 2;
		} elseif($t == 252 || $t == 253) {
			$tn = 6; $n += 6; $noc += 2;
		} else {
			$n++;
		}
		if($noc >= $length) break;
	}
	if($noc > $length) $n -= $tn;
	$strcut = substr($string, 0, $n);
	$strcut = str_replace(array($pre.'&'.$end, $pre.'"'.$end, $pre.'<'.$end, $pre.'>'.$end), array('&amp;', '&quot;', '&lt;', '&gt;'), $strcut);
	$pos = strrpos($strcut, chr(1));
	if($pos !== false) $strcut = substr($strcut,0,$pos);
	return $strcut.$dot;
}
function wrap_text($str) {
	$str = trim($str);
	$str = str_replace("\t", '', $str);
	$str = str_replace("\r", '', $str);
	$str = str_replace("\n", '', $str);
	$str = str_replace(' ', '', $str);
    return trim($str);
}
function get_cookie($uid){
	static $cookie = array();
	if($cookie[$uid]) return $cookie[$uid];
	$cookie[$uid] = DB::result_first("SELECT cookie FROM member_setting WHERE uid='{$uid}'");
	//$cookie[$uid] = strrev(str_rot13(pack('H*', $cookie[$uid])));
	return $cookie[$uid];
}
function save_cookie($uid, $cookie){
	//$cookie = bin2hex(str_rot13(strrev(addslashes($cookie))));
	DB::query("UPDATE member_setting SET cookie='{$cookie}' WHERE uid='{$uid}'");
}
function get_username($uid){
	static $username = array();
	if($username[$uid]) return $username[$uid];
	$username = CACHE::get('username');
	return $username[$uid];
}
function get_setting($uid){
	static $user_setting = array();
	if($user_setting[$uid]) return $user_setting[$uid];
	$cached_result = CACHE::get('user_setting_'.$uid);
	if(!$cached_result){
		$cached_result = DB::fetch_first("SELECT * FROM member_setting WHERE uid='{$uid}'");
		unset($cached_result['cookie']);
		CACHE::save('user_setting_'.$uid, $cached_result);
	}
	return $user_setting[$uid] = $cached_result;
}
function getSetting($k, $force = false){
	if($force) return $setting[$k] = DB::result_first("SELECT v FROM setting WHERE k='{$k}'");
	$cache = CACHE::get('setting');
	return $cache[$k];
}
function saveSetting($k, $v){
	if(!defined('IN_XAE') && $k == 'version') return saveVersion($v);
	static $cache_cleaned = false;
	$v = addslashes($v);
	DB::query("REPLACE INTO setting SET v='{$v}', k='{$k}'");
	if($cache_cleaned) return;
	CACHE::clean('setting');
	$cache_cleaned = true;
}
function runquery($sql){
	$sql = str_replace("\r", "\n", $sql);
	foreach(explode(";\n", trim($sql)) as $query) {
		$query = trim($query);
		if($query) DB::query($query);
	}
}
function jquery_path(){
	$path = defined('IN_ADMINCP') ? 0 : getSetting('jquery_mode');
	switch($path){
		case 'google':
			return '//ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js';
		case 'microsoft':
			return '//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.12.4.min.js';
		case 'cloudflare':
			return '//cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js';
		case 'jsdelivr':
			return '//cdn.jsdelivr.net/jquery/1.12.4/jquery.min.js';
		case 'lug-ustc':
			return '//ajax.lug.ustc.edu.cn/ajax/libs/jquery/1.12.4/jquery.min.js';
		default:
		case 'builtin':
			return 'system/js/jquery.min.js';
	}
}
function kk_fetch_url($url, $limit = 0, $post = '', $cookie = '', $ignore = FALSE, $ip = '', $timeout = 15, $block = TRUE, $encodetype  = 'URLENCODE', $allowcurl = TRUE, $position = 0) {
	$return = '';
	$matches = parse_url($url);
	$scheme = $matches['scheme'];
	$host = $matches['host'];
	$path = $matches['path'] ? $matches['path'].($matches['query'] ? '?'.$matches['query'] : '') : '/';
	$port = !empty($matches['port']) ? $matches['port'] : 80;
	if(function_exists('curl_init') && function_exists('curl_exec') && $allowcurl) {
		$ch = curl_init();
		$ip && curl_setopt($ch, CURLOPT_HTTPHEADER, array("Host: ".$host));
		curl_setopt($ch, CURLOPT_URL, $scheme.'://'.($ip ? $ip : $host).':'.$port.$path);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		if($post) {
			curl_setopt($ch, CURLOPT_POST, 1);
			if($encodetype == 'URLENCODE') {
				curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
			} else {
				parse_str($post, $postarray);
				curl_setopt($ch, CURLOPT_POSTFIELDS, $postarray);
			}
		}
		if($cookie) {
			curl_setopt($ch, CURLOPT_COOKIE, $cookie);
		}
		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
		curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
		$data = curl_exec($ch);
		$status = curl_getinfo($ch);
		$errno = curl_errno($ch);
		curl_close($ch);
		if($errno || $status['http_code'] != 200) {
			return;
		} else {
			return !$limit ? $data : substr($data, 0, $limit);
		}
	}
	if($post) {
		$out = "POST $path HTTP/1.0\r\n";
		$header = "Accept: */*\r\n";
		$header .= "Accept-Language: zh-cn\r\n";
		$boundary = $encodetype == 'URLENCODE' ? '' : '; boundary='.trim(substr(trim($post), 2, strpos(trim($post), "\n") - 2));
		$header .= $encodetype == 'URLENCODE' ? "Content-Type: application/x-www-form-urlencoded\r\n" : "Content-Type: multipart/form-data$boundary\r\n";
		$header .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
		$header .= "Host: $host:$port\r\n";
		$header .= 'Content-Length: '.strlen($post)."\r\n";
		$header .= "Connection: Close\r\n";
		$header .= "Cache-Control: no-cache\r\n";
		$header .= "Cookie: $cookie\r\n\r\n";
		$out .= $header.$post;
	} else {
		$out = "GET $path HTTP/1.0\r\n";
		$header = "Accept: */*\r\n";
		$header .= "Accept-Language: zh-cn\r\n";
		$header .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
		$header .= "Host: $host:$port\r\n";
		$header .= "Connection: Close\r\n";
		$header .= "Cookie: $cookie\r\n\r\n";
		$out .= $header;
	}
	$fpflag = 0;
	if(!$fp = @fsocketopen(($ip ? $ip : $host), $port, $errno, $errstr, $timeout)) {
		$context = array(
			'http' => array(
				'method' => $post ? 'POST' : 'GET',
				'header' => $header,
				'content' => $post,
				'timeout' => $timeout,
			),
		);
		$context = stream_context_create($context);
		$fp = @fopen($scheme.'://'.($ip ? $ip : $host).':'.$port.$path, 'b', false, $context);
		$fpflag = 1;
	}
	if(!$fp) {
		return '';
	} else {
		stream_set_blocking($fp, $block);
		stream_set_timeout($fp, $timeout);
		@fwrite($fp, $out);
		if($ignore){
			@fclose($fp);
			return;
		}
		$status = stream_get_meta_data($fp);
		if(!$status['timed_out']) {
			while (!feof($fp) && !$fpflag) {
				if(($header = @fgets($fp)) && ($header == "\r\n" ||  $header == "\n")) {
					break;
				}
			}
			if($position) {
				for($i=0; $i<$position; $i++) {
					$char = fgetc($fp);
					if($char == "\n" && $oldchar != "\r") {
						$i++;
					}
					$oldchar = $char;
				}
			}
			if($limit) {
				$return = stream_get_contents($fp, $limit);
			} else {
				$return = stream_get_contents($fp);
			}
		}
		@fclose($fp);
		return $return;
	}
}
function fsocketopen($hostname, $port = 80, &$errno, &$errstr, $timeout = 15) {
	$fp = '';
	if(function_exists('fsockopen')) {
		$fp = @fsockopen($hostname, $port, $errno, $errstr, $timeout);
	} elseif(function_exists('pfsockopen')) {
		$fp = @pfsockopen($hostname, $port, $errno, $errstr, $timeout);
	} elseif(function_exists('stream_socket_client')) {
		$fp = @stream_socket_client($hostname.':'.$port, $errno, $errstr, $timeout);
	}
	return $fp;
}
function xml2array(&$xml, $isnormal = FALSE) {
	$xml_parser = new XMLparse($isnormal);
	$data = $xml_parser->parse($xml);
	$xml_parser->destruct();
	return $data;
}
function array2xml($arr, $htmlon = TRUE, $isnormal = FALSE, $level = 1) {
	$s = $level == 1 ? "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<root>\r\n" : '';
	$space = str_repeat("\t", $level);
	foreach($arr as $k => $v) {
		if(!is_array($v)) {
			$s .= $space."<item id=\"$k\">".($htmlon ? '<![CDATA[' : '').$v.($htmlon ? ']]>' : '')."</item>\r\n";
		} else {
			$s .= $space."<item id=\"$k\">\r\n".array2xml($v, $htmlon, $isnormal, $level + 1).$space."</item>\r\n";
		}
	}
	$s = preg_replace("/([\x01-\x08\x0b-\x0c\x0e-\x1f])+/", ' ', $s);
	return $level == 1 ? $s."</root>" : $s;
}
function save_config_file(){
	global $_config;
	if (!$_config) return;
	$content = '<?php'.PHP_EOL.'/* Auto-generated config file */'.PHP_EOL.'$_config = ';
	$content .= var_export($_config, true).';'.PHP_EOL.'?>';
	if(!is_writable(SYSTEM_ROOT.'./config.inc.php')) throw new Exception('Config file is not writable!');
	file_put_contents(SYSTEM_ROOT.'./config.inc.php', $content);
}
function saveVersion($version){
	global $_config;
	if (!$_config) return;
	$_config['version'] = $version;
	save_config_file();
}
function mklink($sourceFile, $targetFile){
	return @file_put_contents($targetFile, '<?php @include '.var_export($sourceFile, true).'; ?>');
}
function cron_set_nextrun($timestamp){
	if(!defined('CRON_ID')) throw new Exception('Unknown cron id');
	$timestamp = intval($timestamp);
	DB::query("UPDATE cron SET nextrun='{$timestamp}' WHERE id='".addslashes(CRON_ID)."'");
	$nextrun = DB::fetch_first("SELECT nextrun FROM cron ORDER BY nextrun ASC LIMIT 0,1");
	saveSetting('next_cron', $nextrun ? $nextrun['nextrun'] : TIMESTAMP + 1200);
}
// Function link
function get_tbs($uid){
	require_once SYSTEM_ROOT.'./function/sign.php';
	return _get_tbs($uid);
}
function verify_cookie($cookie){
	require_once SYSTEM_ROOT.'./function/sign.php';
	return _verify_cookie($cookie);
}
function get_baidu_userinfo($uid){
	require_once SYSTEM_ROOT.'./function/sign.php';
	return _get_baidu_userinfo($uid);
}
function client_sign($uid, $tieba){
	require_once SYSTEM_ROOT.'./function/sign.php';
	return _client_sign($uid, $tieba);
}
function zhidao_sign($uid){
	require_once SYSTEM_ROOT.'./function/sign.php';
	return _zhidao_sign($uid);
}
function wenku_sign($uid){
	require_once SYSTEM_ROOT.'./function/sign.php';
	return _wenku_sign($uid);
}
function update_liked_tieba($uid, $ignore_error = false, $allow_deletion = true){
	require_once SYSTEM_ROOT.'./function/sign.php';
	return _update_liked_tieba($uid, $ignore_error, $allow_deletion);
}
function get_liked_tieba($cookie){
	require_once SYSTEM_ROOT.'./function/sign.php';
	return _get_liked_tieba($cookie);
}
function do_login($uid){
	require_once SYSTEM_ROOT.'./function/member.php';
	_do_login($uid);
}
function do_register($username,$password,$email){
	require_once SYSTEM_ROOT.'./function/member.php';
	return _do_register($username,$password,$email);
}
function delete_user($uid){
	require_once SYSTEM_ROOT.'./function/member.php';
	_delete_user($uid);
}


================================================
FILE: system/function/member.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit();

function _delete_user($uid){
	if(!$uid) return;
	if(!is_array($uid)) $uid = array($uid);
	$uid = implode("', '", $uid);
	DB::query("DELETE FROM member WHERE uid IN ('{$uid}')");
	DB::query("DELETE FROM member_setting WHERE uid IN ('{$uid}')");
	DB::query("DELETE FROM my_tieba WHERE uid IN ('{$uid}')");
	DB::query("DELETE FROM sign_log WHERE uid IN ('{$uid}')");
	HOOK::run('delete_user', true, $uid);
}

function _do_login($uid){
	global $cookiever;
	$user = DB::fetch_first("SELECT * FROM member WHERE uid='{$uid}'");
	$password_hash = substr(md5($user['password']), 8, 8);
	$login_exp = TIMESTAMP + 900;
	dsetcookie('token', authcode("{$cookiever}\t{$uid}\t{$user[username]}\t{$login_exp}\t{$password_hash}", 'ENCODE'));
	HOOK::run('login_user', true, $user);
}

function _do_register($username, $password, $email){
	$user = array(
		'username' => $username,
		'password' => 'FAKE_PASSWORD',
		'email' => $email,
	);
	$uid = DB::insert('member', $user);
	$user['uid'] = $uid;
	$password = Widget_Password::encrypt($user, $password);
	DB::query("UPDATE member SET password='{$password}' WHERE uid='{$uid}'");
	DB::insert('member_setting', array('uid' => $uid, 'cookie' => ''));
	HOOK::run('register_user', true, $user);
	CACHE::update('username');
	CACHE::save('user_setting_'.$uid, '');
	return $uid;
}

================================================
FILE: system/function/sae.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit();

$_config = array(
	'db' => array(
		'server' => SAE_MYSQL_HOST_M,
		'port' => SAE_MYSQL_PORT,
		'username' => SAE_MYSQL_USER,
		'password' => SAE_MYSQL_PASS,
		'name' => SAE_MYSQL_DB,
		'pconnect' => false,
	),
);

$real_siteurl = 'http://'.$_SERVER['HTTP_APPNAME'].'.sinaapp.com/';

?>

================================================
FILE: system/function/sign.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit();

function _get_tbs($uid){
	static $tbs = array();
	if($tbs[$uid]) return $tbs[$uid];
	$tbs_url = 'http://tieba.baidu.com/dc/common/tbs';
	$ch = curl_init($tbs_url);
	curl_setopt($ch, CURLOPT_HTTPHEADER, array('User-Agent: Mozilla/5.0 (Linux; U; Android 4.1.2; zh-cn; MB526 Build/JZO54K) AppleWebKit/530.17 (KHTML, like Gecko) FlyFlow/2.4 Version/4.0 Mobile Safari/530.17 baidubrowser/042_1.8.4.2_diordna_458_084/alorotoM_61_2.1.4_625BM/1200a/39668C8F77034455D4DED02169F3F7C7%7C132773740707453/1','Referer: http://tieba.baidu.com/'));
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_COOKIE, get_cookie($uid));
	$tbs_json = curl_exec($ch);
	curl_close($ch);
	$tbs = json_decode($tbs_json, 1);
	return $tbs[$uid] = $tbs['tbs'];
}

function _verify_cookie($cookie){
	$tbs_url = 'http://tieba.baidu.com/dc/common/tbs';
	$ch = curl_init($tbs_url);
	curl_setopt($ch, CURLOPT_HTTPHEADER, array('User-Agent: Mozilla/5.0 (Linux; U; Android 4.1.2; zh-cn; MB526 Build/JZO54K) AppleWebKit/530.17 (KHTML, like Gecko) FlyFlow/2.4 Version/4.0 Mobile Safari/530.17 baidubrowser/042_1.8.4.2_diordna_458_084/alorotoM_61_2.1.4_625BM/1200a/39668C8F77034455D4DED02169F3F7C7%7C132773740707453/1','Referer: http://tieba.baidu.com/'));
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_COOKIE, $cookie);
	$tbs_json = curl_exec($ch);
	curl_close($ch);
	$tbs = json_decode($tbs_json, 1);
	return $tbs['is_login'];
}

function _get_baidu_userinfo($uid){
	$cookie = get_cookie($uid);
	if(!$cookie) return array('no' => 4);
	$tbs_url = 'http://tieba.baidu.com/f/user/json_userinfo';
	$ch = curl_init($tbs_url);
	curl_setopt($ch, CURLOPT_HTTPHEADER, array('Referer: http://tieba.baidu.com/'));
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_COOKIE, $cookie);
	$tbs_json = curl_exec($ch);
	curl_close($ch);
	$tbs_json = mb_convert_encoding($tbs_json, "utf8", "gbk");
	return json_decode($tbs_json, true);
}

function _get_liked_tieba($cookie){
	$pn = 0;
	$kw_name = array();
	$retry = 0;
	while (true){
		$pn++;
		$mylikeurl = "http://tieba.baidu.com/f/like/mylike?&pn=$pn";
		$result = kk_fetch_url($mylikeurl, 0, '', $cookie);
		$result = wrap_text($result);
		$pre_reg = '/<tr><td>.*?<ahref="\/f\?kw=.*?"title="(.*?)"/';
		preg_match_all($pre_reg, $result, $matches);
		$count = 0;
		foreach ($matches[1] as $key => $value) {
			$uname = urlencode($value);
			$_uname = preg_quote($value);
			preg_match('/balvid="([0-9]+)"/i', $result, $fid);
			$kw_name[] = array(
				'name' => mb_convert_encoding($value, 'utf-8', 'gbk'),
				'uname' => $uname,
				'fid' => $fid[1],
			);
			$count++;
		}
		if ($count==0) {
			if ($retry >= 2) break;
			$retry++;
			$pn--;
			continue;
		}
		$retry = 0;
	}
	return $kw_name;
}

function _update_liked_tieba($uid, $ignore_error = false, $allow_deletion = true){
	$date = date('Ymd', TIMESTAMP + 900);
	$cookie = get_cookie($uid);
	if(!$cookie){
		if($ignore_error) return;
		showmessage('请先填写 Cookie 信息再更新', './#baidu_bind');
	}
	$liked_tieba = get_liked_tieba($cookie);
	$insert = $deleted = 0;
	if(!$liked_tieba){
		if($ignore_error) return;
		showmessage('无法获取喜欢的贴吧,请更新 Cookie 信息', './#baidu_bind');
	}
	if($limit = getSetting('max_tieba')){
		$count = count($liked_tieba);
		if($limit < $count){
			if($ignore_error) return;
			showmessage("<p>您共计关注了 {$count} 个贴吧,</p><p>管理员限制了每位用户最多关注 {$limit} 个贴吧</p>", './#liked_tieba');
		}
	}
	$my_tieba = array();
	$query = DB::query("SELECT name, fid, tid FROM my_tieba WHERE uid='{$uid}'");
	while($r = DB::fetch($query)) {
		$my_tieba[$r['name']] = $r;
	}
	foreach($liked_tieba as $tieba){
		if($my_tieba[$tieba['name']]){
			unset($my_tieba[$tieba['name']]);
			if(!$my_tieba[$tieba['name']]['fid']) DB::update('my_tieba', array(
				'fid' => $tieba['fid'],
				), array(
					'uid' => $uid,
					'name' => $tieba['name'],
				), true);
			continue;
		}else{
			DB::insert('my_tieba', array(
				'uid' => $uid,
				'fid' => $tieba['fid'],
				'name' => $tieba['name'],
				'unicode_name' => $tieba['uname'],
				), false, true, true);
			$insert++;
		}
	}
	DB::query("INSERT IGNORE INTO sign_log (tid, uid, `date`) SELECT tid, uid, '{$date}' FROM my_tieba");
	if($my_tieba && $allow_deletion){
		$tieba_ids = array();
		foreach($my_tieba as $tieba){
			$tieba_ids[] = $tieba['tid'];
		}
		$str = "'".implode("', '", $tieba_ids)."'";
		$deleted = count($my_tieba);
		DB::query("DELETE FROM my_tieba WHERE uid='{$uid}' AND tid IN ({$str})");
		DB::query("DELETE FROM sign_log WHERE uid='{$uid}' AND tid IN ({$str})");
	}
	return array($insert, $deleted);
}

function _client_sign($uid, $tieba){
	$cookie = get_cookie($uid);
	preg_match('/BDUSS=([^ ;]+);/i', $cookie, $matches);
	$BDUSS = trim($matches[1]);
	if(!$BDUSS) return array(-1, '找不到 BDUSS Cookie', 0);
	$ch = curl_init('http://c.tieba.baidu.com/c/c/forum/sign');
	curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded', 'User-Agent: Mozilla/5.0 (SymbianOS/9.3; Series60/3.2 NokiaE72-1/021.021; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 BrowserNG/7.1.16352'));
	curl_setopt($ch, CURLOPT_COOKIE, $cookie);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_POST, 1);
	$array = array(
		'BDUSS' => $BDUSS,
		'_client_id' => '03-00-DA-59-05-00-72-96-06-00-01-00-04-00-4C-43-01-00-34-F4-02-00-BC-25-09-00-4E-36',
		'_client_type' => '4',
		'_client_version' => '1.2.1.17',
		'_phone_imei' => '540b43b59d21b7a4824e1fd31b08e9a6',
		'fid' => $tieba['fid'],
		'kw' => urldecode($tieba['unicode_name']),
		'net_type' => '3',
		'tbs' => get_tbs($uid),
	);
	$sign_str = '';
	foreach($array as $k=>$v) $sign_str .= $k.'='.$v;
	$sign = strtoupper(md5($sign_str.'tiebaclient!!!'));
	$array['sign'] = $sign;
	curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($array));
	$sign_json = curl_exec($ch);
	curl_close($ch);
	$res = @json_decode($sign_json, true);
	if(!$res) return array(1, 'JSON 解析错误', 0);
	if($res['user_info']){
		$exp = $res['user_info']['sign_bonus_point'];
		return array(2, "签到成功,经验值上升 {$exp}", $exp);
	}else{
		switch($res['error_code']){
			case '340010':		// 已经签过
			case '160002':
			case '3':
				return array(2, $res['error_msg'], 0);
			case '1':			// 未登录
				return array(-1, "ERROR-{$res[error_code]}: ".$res['error_msg'].' (Cookie 过期或不正确)', 0);
			case '160004':		// 不支持
				return array(-1, "ERROR-{$res[error_code]}: ".$res['error_msg'], 0);
			case '160003':		// 零点 稍后再试
			case '160008':		// 太快了
				return array(1, "ERROR-{$res[error_code]}: ".$res['error_msg'], 0);
			default:
				return array(1, "ERROR-{$res[error_code]}: ".$res['error_msg'], 0);
		}
	}
}

function _client_sign_old($uid, $tieba){
	$cookie = get_cookie($uid);
	preg_match('/BDUSS=([^ ;]+);/i', $cookie, $matches);
	$BDUSS = trim($matches[1]);
	if(!$BDUSS) return array(-1, '找不到 BDUSS Cookie', 0);
	$ch = curl_init('http://c.tieba.baidu.com/c/c/forum/sign');
	curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded', 'User-Agent: BaiduTieba for Android 5.1.3', 'client_user_token: '.random(6, true)));
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_POST, 1);
	$array = array(
		'BDUSS' => $BDUSS,
		'_client_id' => 'wappc_138'.random(10, true).'_'.random(3, true),
		'_client_type' => '2',
		'_client_version' => '5.1.3',
		'_phone_imei' => md5(random(16, true)),
		'cuid' => strtoupper(md5(random(16))).'|'.random(15, true),
		'fid' => $tieba['fid'],
		'from' => 'tieba',
		'kw' => urldecode($tieba['unicode_name']),
		'model' => 'Aries',
		'net_type' => '3',
		'stErrorNums' => '0',
		'stMethod' => '1',
		'stMode' => '1',
		'stSize' => random(5, true),
		'stTime' => random(4, true),
		'stTimesNum' => '0',
		'tbs' => get_tbs($uid),
		'timestamp' => time().rand(1000, 9999),
	);
	$sign_str = '';
	foreach($array as $k=>$v) $sign_str .= $k.'='.$v;
	$sign = strtoupper(md5($sign_str.'tiebaclient!!!'));
	$array['sign'] = $sign;
	curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($array));
	$sign_json = curl_exec($ch);
	curl_close($ch);
	$res = @json_decode($sign_json, true);
	if(!$res) return array(1, 'JSON 解析错误', 0);
	if($res['user_info']){
		$exp = $res['user_info']['sign_bonus_point'];
		return array(2, "签到成功,经验值上升 {$exp}", $exp);
	}else{
		switch($res['error_code']){
			case '340010':		// 已经签过
			case '160002':
			case '3':
				return array(2, $res['error_msg'], 0);
			case '1':			// 未登录
				return array(-1, "ERROR-{$res[error_code]}: ".$res['error_msg'].' (Cookie 过期或不正确)', 0);
			case '160004':		// 不支持
				return array(-1, "ERROR-{$res[error_code]}: ".$res['error_msg'], 0);
			case '160003':		// 零点 稍后再试
			case '160008':		// 太快了
				return array(1, "ERROR-{$res[error_code]}: ".$res['error_msg'], 0);
			default:
				return array(1, "ERROR-{$res[error_code]}: ".$res['error_msg'], 0);
		}
	}
}

function _zhidao_sign($uid){
	$ch = curl_init('http://zhidao.baidu.com/submit/user');
	curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_COOKIE, get_cookie($uid));
	curl_setopt($ch, CURLOPT_POST, 1);
	curl_setopt($ch, CURLOPT_POSTFIELDS, 'cm=100509&t='.TIMESTAMP);
	$result = curl_exec($ch);
	curl_close($ch);
	return @json_decode($result);
}

function _wenku_sign($uid){
	$ch = curl_init('http://wenku.baidu.com/task/submit/signin');
	curl_setopt($ch, CURLOPT_HTTPHEADER, array('User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.43 BIDUBrowser/2.x Safari/537.31'));
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_COOKIE, get_cookie($uid));
	$result = curl_exec($ch);
	curl_close($ch);
	return @json_decode($result);
}


================================================
FILE: system/function/updater/1.13.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit('Access Denied');

if($current_version == '1.13.9.5'){
	DB::query("ALTER TABLE `member_setting` ADD `zhidao_sign` TINYINT(1) NOT NULL DEFAULT '0'");
	DB::query("ALTER TABLE `member_setting` ADD `wenku_sign` TINYINT(1) NOT NULL DEFAULT '0'");
	saveSetting('version', '1.13.9.6');
	showmessage('成功更新到 1.13.9.6!', './', 1);
}elseif($current_version == '1.13.9.6'){
	saveSetting('version', '1.13.9.8');
	showmessage('成功更新到 1.13.9.8!', './', 1);
}elseif($current_version == '1.13.9.8'){
	DB::query('CREATE TABLE IF NOT EXISTS `cache` ( `k` varchar(32) NOT NULL, `v` TEXT NOT NULL, PRIMARY KEY (`k`)) ENGINE=InnoDB DEFAULT CHARSET=utf8');
	saveSetting('version', '1.13.9.23');
	showmessage('成功更新到 1.13.9.23!', './', 1);
}elseif($current_version == '1.13.9.23'){
	saveSetting('version', '1.13.9.24');
	showmessage('成功更新到 1.13.9.24!', './', 1);
}elseif($current_version == '1.13.9.24'){
	$sql = <<<EOF
CREATE TABLE IF NOT EXISTS `cron` (
  `id` varchar(16) NOT NULL,
  `enabled` tinyint(1) NOT NULL,
  `nextrun` int(10) unsigned NOT NULL,
  `order` tinyint(4) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `cron` (`id`, `enabled`, `nextrun`, `order`) VALUES
('daily', 1, 0, 0),
('update_tieba', 1, 0, 10),
('sign', 1, 0, 20),
('ext_sign', 1, 0, 50),
('mail', 1, 0, 100);
CREATE TABLE IF NOT EXISTS `mail_queue` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `to` varchar(255) NOT NULL,
  `subject` varchar(255) NOT NULL,
  `content` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
EOF;
	runquery($sql);
	saveSetting('version', '1.13.10.4');
	showmessage('成功更新到 1.13.10.4!<br><br>请修改计划任务为以下内容:<br>http://域名/cron.php &nbsp; * * * * *(每分钟一次)');
}elseif($current_version == '1.13.9.4'){
	DB::insert('cron', array(
		'id' => 'sign_retry',
		'enabled' => 1,
		'nextrun' => TIMESTAMP,
		'order' => '110',
	));
	saveSetting('version', '1.13.10.6');
	showmessage('成功更新到 1.13.10.6!', './');
}elseif($current_version == '1.13.10.6'){
	DB::query('ALTER TABLE `member` CHANGE `username` `username` VARCHAR(24)');
	saveSetting('version', '1.13.10.13');
	showmessage('成功更新到 1.13.10.13!', './', 1);
}elseif($current_version == '1.13.10.13'){
	DB::query('ALTER TABLE `my_tieba` DROP INDEX `name`');
	DB::query('ALTER TABLE `my_tieba` ADD INDEX (`uid`)');
	DB::query('ALTER TABLE `member_setting` DROP `use_bdbowser`, DROP `sign_method`');
	saveSetting('version', '1.13.10.20');
	showmessage('成功更新到 1.13.10.20!', './');
}elseif($current_version == '1.13.10.20'){
	saveSetting('version', '1.13.11.5');
	showmessage('成功更新到 1.13.11.5!', './');
}elseif($current_version == '1.13.11.5'){
	DB::query('
CREATE TABLE IF NOT EXISTS `plugin` (
  id int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(64) NOT NULL,
  module text NOT NULL,
  PRIMARY KEY (id),
  UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
');
	DB::insert('plugin', array('name' => 'debug_info'));
	DB::insert('plugin', array('name' => 'update_log'));
	saveSetting('version', '1.13.11.9');
	showmessage('成功更新到 1.13.11.9!', './');
}elseif($current_version == '1.13.11.9'){
	runquery("
ALTER TABLE `plugin` ADD `enable` TINYINT(1) NOT NULL DEFAULT '1' AFTER `id`;
ALTER TABLE `plugin` ADD `version` VARCHAR(8) NOT NULL DEFAULT '0';
ALTER TABLE `member_setting` ADD `cookie` TEXT BINARY CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
");
	$query = DB::query('SELECT uid, cookie FROM member');
	while($result = DB::fetch($query)){
		save_cookie($result['uid'], $result['cookie']);
	}
	DB::query('ALTER TABLE `member` DROP `cookie`');
	$query = DB::query('SHOW columns FROM `plugin`');
	while($result = DB::fetch($query)){
		if($result['Field'] == 'module') DB::query('ALTER TABLE `plugin` DROP `module`');
	}
	CACHE::clear();
	CACHE::update('plugins');
	saveSetting('register_limit', 1);
	saveSetting('register_check', 1);
	saveSetting('jquery_mode', 2);
	saveSetting('version', '1.13.12.15');
	showmessage('成功更新到 1.13.12.15!', './');
}elseif($current_version == '1.13.12.15'){
	saveSetting('version', '1.13.12.25');
	showmessage('成功更新到 1.13.12.25!', './');
}elseif($current_version == '1.13.12.25'){
	if($_config['adminid']) saveSetting('admin_uid', $_config['adminid']);
	saveSetting('version', '1.14.1.15');
	showmessage('成功更新到 1.14.1.15!', './');
}

?>

================================================
FILE: system/function/updater/1.14.1.15.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit('Access Denied');
DB::query("ALTER TABLE `setting` CHANGE `v` `v` VARCHAR(256) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL");
saveSetting('version', '1.14.1.16');
showmessage('成功更新到 1.14.1.16!', './');
?>

================================================
FILE: system/function/updater/1.14.1.16.php
================================================
<?php
if(!defined('IN_KKFRAME')) exit('Access Denied');
runquery('
CREATE TABLE IF NOT EXISTS `download` (
  `path` varchar(128) NOT NULL,
  `content` text NOT NULL,
  PRIMARY KEY (`path`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `update_source` (
  `id` varchar(16) NOT NULL,
  `path` varchar(128) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
');
saveSetting('version', '1.14.1.23');
showmessage('成功更新到 1.14.1.23!', './');
?>

================================================
FI
Download .txt
gitextract_mw9r9d_v/

├── README.md
├── admin.php
├── ajax.php
├── api.php
├── config.yaml
├── index.php
├── install/
│   ├── index.php
│   ├── install.sql
│   ├── openshift.php
│   └── sae.php
├── member.php
├── plugin.php
├── plugins/
│   ├── cloud_stat/
│   │   ├── cloud_stat.cron.php
│   │   ├── index.inc.php
│   │   └── plugin.class.php
│   ├── debug_info/
│   │   └── plugin.class.php
│   ├── register_limit/
│   │   └── plugin.class.php
│   ├── stat/
│   │   └── plugin.class.php
│   └── xxx_post/
│       ├── c_daily.cron.php
│       ├── c_first.cron.php
│       ├── c_se.cron.php
│       ├── c_sxbk.cron.php
│       ├── core.php
│       ├── index.php
│       ├── main.js
│       └── plugin.class.php
├── robots.txt
├── system/
│   ├── class/
│   │   ├── cache.php
│   │   ├── cloud.php
│   │   ├── core.php
│   │   ├── db.php
│   │   ├── hook.php
│   │   ├── kerror.php
│   │   ├── mail/
│   │   │   ├── phpmail.php
│   │   │   ├── saemail.php
│   │   │   └── smtp.php
│   │   ├── mail.php
│   │   ├── multithread.php
│   │   ├── plugin.php
│   │   ├── updater.php
│   │   ├── widget/
│   │   │   └── widget_password.php
│   │   └── xmlparse.php
│   ├── common.inc.php
│   └── function/
│       ├── cache/
│       │   ├── cache_plugin.php
│       │   ├── cache_plugins.php
│       │   ├── cache_setting.php
│       │   └── cache_username.php
│       ├── core.php
│       ├── member.php
│       ├── sae.php
│       ├── sign.php
│       └── updater/
│           ├── 1.13.php
│           ├── 1.14.1.15.php
│           ├── 1.14.1.16.php
│           ├── 1.14.1.23.php
│           ├── 1.14.2.6.php
│           ├── 1.14.4.12.php
│           ├── 1.14.4.14.php
│           ├── 1.14.4.24.php
│           ├── 1.14.5.12.php
│           ├── 1.14.5.20.php
│           ├── 1.14.5.27.php
│           ├── 1.14.6.2.php
│           ├── 1.16.6.23.php
│           └── fallback.php
└── template/
    └── default/
        ├── admin.php
        ├── index.php
        ├── js/
        │   ├── admin.js
        │   ├── fwin.js
        │   ├── kk_dropdown.js
        │   ├── main.js
        │   └── member.js
        ├── member.php
        ├── message.php
        ├── mobile/
        │   └── message.php
        ├── style/
        │   └── main.css
        ├── template.xml
        └── widget/
            ├── bind_status.php
            ├── find_password.php
            ├── footer.php
            ├── guide.php
            ├── header.php
            ├── liked_tieba.php
            ├── login.php
            ├── meta.php
            ├── register.php
            ├── setting.php
            ├── sidebar.php
            └── sign_log.php
Download .txt
SYMBOL INDEX (347 symbols across 36 files)

FILE: admin.php
  function getClasses (line 410) | function getClasses(){
  function getPlugins (line 425) | function getPlugins(){
  function getTemplates (line 449) | function getTemplates(){
  function getCron (line 473) | function getCron(){
  function is_plugin_enabled (line 493) | function is_plugin_enabled($pluginid){
  function getPluginVersion (line 504) | function getPluginVersion($pluginid){

FILE: install/index.php
  function mysql_connect (line 14) | function mysql_connect($server = 'localhost', $username = 'root', $passw...
  function mysql_insert_id (line 17) | function mysql_insert_id($link = null) {
  function mysql_select_db (line 20) | function mysql_select_db($db_name, $link = null) {
  function mysql_query (line 23) | function mysql_query($db_name, $link = null) {
  function mysql_error (line 26) | function mysql_error($link = null) {
  function mysql_errno (line 29) | function mysql_errno($link = null) {
  function show_back (line 130) | function show_back($title, $text){
  function show_install_page (line 136) | function show_install_page($title, $content){
  function show_status (line 143) | function show_status($status, $on_txt = 'On', $off_txt = 'Off'){
  function runquery (line 147) | function runquery($sql, $link){
  function saveSetting (line 157) | function saveSetting($k, $v){
  function random (line 163) | function random($length, $numeric = 0) {

FILE: install/install.sql
  type `cache` (line 19) | CREATE TABLE IF NOT EXISTS `cache` (
  type `cron` (line 25) | CREATE TABLE IF NOT EXISTS `cron` (
  type `download` (line 41) | CREATE TABLE IF NOT EXISTS `download` (
  type `mail_queue` (line 47) | CREATE TABLE IF NOT EXISTS `mail_queue` (
  type `member` (line 55) | CREATE TABLE IF NOT EXISTS `member` (
  type `member_bind` (line 63) | CREATE TABLE IF NOT EXISTS `member_bind` (
  type `member_setting` (line 70) | CREATE TABLE IF NOT EXISTS `member_setting` (
  type `my_tieba` (line 80) | CREATE TABLE IF NOT EXISTS `my_tieba` (
  type `plugin` (line 91) | CREATE TABLE IF NOT EXISTS `plugin` (
  type `plugin_var` (line 103) | CREATE TABLE IF NOT EXISTS `plugin_var` (
  type `setting` (line 110) | CREATE TABLE IF NOT EXISTS `setting` (
  type `sign_log` (line 116) | CREATE TABLE IF NOT EXISTS `sign_log` (
  type `update_source` (line 127) | CREATE TABLE IF NOT EXISTS `update_source` (

FILE: install/openshift.php
  function show_back (line 89) | function show_back($title, $text){
  function show_install_page (line 95) | function show_install_page($title, $content){
  function show_status (line 101) | function show_status($status, $on_txt = 'On', $off_txt = 'Off'){
  function runquery (line 105) | function runquery($sql, $link){
  function saveSetting (line 115) | function saveSetting($k, $v){
  function random (line 121) | function random($length, $numeric = 0) {

FILE: install/sae.php
  function show_back (line 81) | function show_back($title, $text){
  function show_install_page (line 87) | function show_install_page($title, $content){
  function show_status (line 93) | function show_status($status, $on_txt = 'On', $off_txt = 'Off'){
  function runquery (line 97) | function runquery($sql, $link){
  function saveSetting (line 106) | function saveSetting($k, $v){
  function random (line 112) | function random($length, $numeric = 0) {

FILE: plugins/cloud_stat/plugin.class.php
  class plugin_cloud_stat (line 3) | class plugin_cloud_stat extends Plugin{
    method checkCompatibility (line 10) | function checkCompatibility(){
    method install (line 13) | function install(){
    method mklink (line 25) | function mklink($sourceFile, $targetFile){
    method on_upgrade (line 28) | function on_upgrade($from_version){
    method handleAction (line 37) | function handleAction(){

FILE: plugins/debug_info/plugin.class.php
  class plugin_debug_info (line 3) | class plugin_debug_info extends Plugin{
    method page_footer (line 6) | function page_footer(){

FILE: plugins/register_limit/plugin.class.php
  class plugin_register_limit (line 3) | class plugin_register_limit extends Plugin {
    method install (line 6) | function install(){
    method uninstall (line 9) | function uninstall(){
    method checkCompatibility (line 12) | function checkCompatibility(){
    method on_load (line 15) | function on_load(){
    method on_config (line 34) | function on_config(){

FILE: plugins/stat/plugin.class.php
  class plugin_stat (line 3) | class plugin_stat extends Plugin{
    method page_footer_js (line 7) | function page_footer_js(){
    method on_config (line 11) | function on_config(){

FILE: plugins/xxx_post/core.php
  function get_random_content (line 3) | function get_random_content(){
  function get_random_tid (line 110) | function get_random_tid($tieba){
  function client_rppost (line 126) | function client_rppost($uid, $tieba, $content) {

FILE: plugins/xxx_post/main.js
  function x_reload (line 42) | function x_reload(){
  function load_post_set (line 45) | function load_post_set(){
  function show_post_set (line 51) | function show_post_set(result){
  function load_post_adv_set (line 67) | function load_post_adv_set(){
  function load_post_log (line 77) | function load_post_log(){
  function load_post_history (line 83) | function load_post_history(date){
  function show_post_log (line 89) | function show_post_log(result){
  function delsid (line 105) | function delsid(sid){
  function delcont (line 109) | function delcont(cid){

FILE: plugins/xxx_post/plugin.class.php
  class plugin_xxx_post (line 3) | class plugin_xxx_post extends Plugin{
    method checkCompatibility (line 13) | function checkCompatibility(){
    method page_footer_js (line 16) | function page_footer_js() {
    method install (line 19) | function install() {
    method uninstall (line 65) | function uninstall() {
    method on_upgrade (line 69) | function on_upgrade($from_version){
    method on_config (line 89) | function on_config() {
    method handleAction (line 121) | function handleAction(){

FILE: system/class/cache.php
  class CACHE (line 4) | class CACHE {
    method get (line 5) | public static function get($key) {
    method save (line 17) | public static function save($key, $value) {
    method update (line 22) | public static function update($key) {
    method clean (line 31) | public static function clean($key) {
    method clear (line 34) | public static function clear() {

FILE: system/class/cloud.php
  class cloud (line 4) | class cloud {
    method init (line 7) | public static function init(){
    method do_register (line 11) | public static function do_register(){
    method check_remote_disabled (line 21) | public static function check_remote_disabled(){
    method get_api_path (line 29) | public static function get_api_path(){
    method sync (line 32) | public static function sync(){
    method request (line 37) | public static function request($api_name){
    method request_public (line 50) | public static function request_public($api_name){
    method request_silent (line 63) | public static function request_silent($api_name){
    method ping (line 76) | public static function ping(){
    method id (line 80) | public static function id(){
    method key (line 84) | public static function key(){
    method _get_id_and_key (line 88) | private static function _get_id_and_key(){

FILE: system/class/core.php
  class core (line 3) | class core {
    method init (line 4) | function init() {
    method __destruct (line 16) | function __destruct() {
    method init_header (line 23) | function init_header() {
    method init_useragent (line 31) | function init_useragent() {
    method init_syskey (line 40) | function init_syskey() {
    method init_cookie (line 43) | function init_cookie() {
    method init_final (line 66) | function init_final() {
    method init_mail (line 72) | function init_mail() {

FILE: system/class/db.php
  class db_mysql (line 3) | class db_mysql {
    method connect (line 6) | function connect() {
    method _dbconnect (line 10) | function _dbconnect($dbhost, $dbuser, $dbpw, $dbcharset, $dbname, $pco...
    method select_db (line 26) | function select_db($dbname) {
    method fetch_array (line 29) | function fetch_array($query, $result_type = MYSQL_ASSOC) {
    method fetch_first (line 32) | function fetch_first($sql) {
    method result_first (line 35) | function result_first($sql) {
    method query (line 38) | function query($sql, $type = '') {
    method affected_rows (line 48) | function affected_rows() {
    method error (line 51) | function error() {
    method errno (line 54) | function errno() {
    method result (line 57) | function result($query, $row = 0) {
    method num_rows (line 61) | function num_rows($query) {
    method num_fields (line 65) | function num_fields($query) {
    method free_result (line 68) | function free_result($query) {
    method insert_id (line 71) | function insert_id() {
    method fetch_row (line 74) | function fetch_row($query) {
    method fetch_fields (line 78) | function fetch_fields($query) {
    method version (line 81) | function version() {
    method close (line 87) | function close() {
    method halt (line 90) | function halt($message = '', $sql = '') {
    method __destruct (line 93) | function __destruct() {
  class db_mysqli (line 98) | class db_mysqli {
    method connect (line 101) | function connect() {
    method _dbconnect (line 105) | function _dbconnect($dbhost, $dbuser, $dbpw, $dbcharset, $dbname, $pco...
    method select_db (line 117) | function select_db($dbname) {
    method fetch_array (line 120) | function fetch_array($query, $result_type = MYSQLI_ASSOC) {
    method fetch_first (line 123) | function fetch_first($sql) {
    method result_first (line 126) | function result_first($sql) {
    method query (line 129) | function query($sql, $type = '') {
    method affected_rows (line 138) | function affected_rows() {
    method error (line 141) | function error() {
    method errno (line 144) | function errno() {
    method result (line 147) | function result($query, $row = 0) {
    method num_rows (line 151) | function num_rows($query) {
    method num_fields (line 155) | function num_fields($query) {
    method free_result (line 158) | function free_result($query) {
    method insert_id (line 161) | function insert_id() {
    method fetch_row (line 164) | function fetch_row($query) {
    method fetch_fields (line 168) | function fetch_fields($query) {
    method version (line 171) | function version() {
    method close (line 177) | function close() {
    method halt (line 180) | function halt($message = '', $sql = '') {
    method __destruct (line 183) | function __destruct() {
  class DB (line 188) | class DB {
    method delete (line 189) | public static function delete($table, $condition, $limit = 0, $unbuffe...
    method insert (line 200) | public static function insert($table, $data, $return_insert_id = true,...
    method update (line 207) | public static function update($table, $data, $condition, $unbuffered =...
    method implode_field_value (line 221) | public static function implode_field_value($array, $glue = ',') {
    method insert_id (line 229) | public static function insert_id() {
    method fetch (line 232) | public static function fetch($resourceid, $type = MYSQLI_ASSOC) {
    method fetch_first (line 235) | public static function fetch_first($sql) {
    method fetch_all (line 238) | public static function fetch_all($sql) {
    method result (line 246) | public static function result($resourceid, $row = 0) {
    method result_first (line 249) | public static function result_first($sql) {
    method query (line 252) | public static function query($sql, $type = '') {
    method num_rows (line 255) | public static function num_rows($resourceid) {
    method affected_rows (line 258) | public static function affected_rows() {
    method free_result (line 261) | public static function free_result($query) {
    method error (line 264) | public static function error() {
    method errno (line 267) | public static function errno() {
    method _execute (line 270) | private static function _execute($cmd , $arg1 = '', $arg2 = '') {
    method object (line 276) | public static function &object() {

FILE: system/class/hook.php
  class HOOK (line 3) | class HOOK{
    method INIT (line 4) | public static function INIT(){
    method parse_module (line 55) | public static function parse_module($module, $pluginid){
    method page_menu (line 78) | public static function page_menu(){
    method page_contents (line 93) | public static function page_contents(){
    method run (line 104) | public static function run($hookname, $ignore_unabled = false){
    method getPlugin (line 119) | public static function getPlugin($plugin_id){

FILE: system/class/kerror.php
  class kerror (line 3) | class kerror {
    method system_error (line 4) | public static function system_error($message, $show = true, $halt = tr...
    method debug_backtrace (line 15) | public static function debug_backtrace() {
    method db_error (line 42) | public static function db_error($message, $sql) {
    method exception_error (line 55) | public static function exception_error($exception) {
    method show_error (line 109) | public static function show_error($type, $errormsg, $phpmsg = '', $exi...
    method clear (line 136) | public static function clear($message) {
    method sql_clear (line 139) | public static function sql_clear($message) {

FILE: system/class/mail.php
  class mailer (line 3) | class mailer {
    method isAvailable (line 5) | function isAvailable() {
    method send (line 8) | function send() {
    method _get_setting (line 11) | function _get_setting($key) {
    method _load_setting (line 15) | function _load_setting() {
  class mail_content (line 33) | class mail_content {
  class mail_sender (line 38) | class mail_sender {
    method __construct (line 40) | function __construct() {
    method sendMail (line 48) | function sendMail($mail) {

FILE: system/class/mail/phpmail.php
  class phpmail (line 4) | class phpmail extends mailer{
    method isAvailable (line 11) | function isAvailable(){
    method send (line 14) | function send($mail){

FILE: system/class/mail/saemail.php
  class saemail (line 4) | class saemail extends mailer{
    method isAvailable (line 14) | function isAvailable(){
    method send (line 17) | function send($mail){

FILE: system/class/mail/smtp.php
  class smtp (line 4) | class smtp extends mailer{
    method isAvailable (line 14) | function isAvailable(){
    method send (line 17) | function send($mail){
  class _smtp (line 23) | class _smtp {
    method _smtp (line 44) | public function _smtp($obj){
    method send (line 51) | public function send($to, $subject, $message) {
    method Connect2Server (line 67) | private function Connect2Server() {
    method sendMail (line 103) | private function sendMail() {
    method readResponse (line 114) | private function readResponse() {
    method sendCommand (line 122) | private function sendCommand($string) {
    method sendHeaders (line 126) | private function sendHeaders() {
    method __destruct (line 138) | public function __destruct() {

FILE: system/class/multithread.php
  class MultiThread (line 4) | class MultiThread {
    method registerThread (line 5) | public static function registerThread($max_thread = 6, $ttl = 30){
    method newCronThread (line 15) | public static function newCronThread(){

FILE: system/class/plugin.php
  class Plugin (line 3) | class Plugin {
    method getSetting (line 9) | function getSetting($key, $default_value = false){
    method saveSetting (line 14) | function saveSetting($key, $value){
    method checkCompatibility (line 23) | function checkCompatibility(){
    method install (line 26) | function install(){
    method uninstall (line 29) | function uninstall(){
    method handleAction (line 32) | function handleAction(){
    method getPluginId (line 35) | private function getPluginId(){

FILE: system/class/updater.php
  class Updater (line 3) | class Updater{
    method init (line 5) | public static function init(){
    method check (line 26) | public static function check(){
    method loop (line 54) | public static function loop(){
    method write_file (line 66) | public static function write_file(){
    method _write (line 91) | private static function _write($path, $content){
    method _is_writable (line 98) | private static function _is_writable($path){
    method _download_file (line 108) | private static function _download_file($path, $hash, $try = 1) {
    method _getPluginList (line 136) | private static function _getPluginList(){

FILE: system/class/widget/widget_password.php
  class Widget_Password (line 3) | class Widget_Password {
    method verify (line 7) | function verify($user, $password){
    method encrypt (line 20) | function encrypt($user, $password){

FILE: system/class/xmlparse.php
  class XMLparse (line 4) | class XMLparse {
    method __construct (line 14) | function __construct($isnormal) {
    method XMLparse (line 18) | function XMLparse($isnormal) {
    method destruct (line 27) | function destruct() {
    method parse (line 31) | function parse(&$data) {
    method open (line 37) | function open(&$parser, $tag, $attributes) {
    method data (line 58) | function data(&$parser, $data) {
    method close (line 64) | function close(&$parser, $tag) {

FILE: system/common.inc.php
  function class_loader (line 17) | function class_loader($class_name){
  function __autoload (line 39) | function __autoload($class_name){

FILE: system/function/core.php
  function is_admin (line 3) | function is_admin($uid){
  function is_email (line 6) | function is_email($string){
  function dsetcookie (line 9) | function dsetcookie($name, $value = '', $exp = 2592000){
  function daddslashes (line 13) | function daddslashes($string, $force = 0, $strip = FALSE) {
  function template (line 26) | function template($file){
  function dgmdate (line 43) | function dgmdate($timestamp, $d_format = 'Y-m-d H:i') {
  function authcode (line 74) | function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
  function showmessage (line 114) | function showmessage($msg = '', $redirect = '', $delay = 3){
  function dreferer (line 133) | function dreferer(){
  function strexists (line 136) | function strexists($string, $find) {
  function cutstr (line 139) | function cutstr($string, $length, $dot = ' ...') {
  function wrap_text (line 172) | function wrap_text($str) {
  function get_cookie (line 180) | function get_cookie($uid){
  function save_cookie (line 187) | function save_cookie($uid, $cookie){
  function get_username (line 191) | function get_username($uid){
  function get_setting (line 197) | function get_setting($uid){
  function getSetting (line 208) | function getSetting($k, $force = false){
  function saveSetting (line 213) | function saveSetting($k, $v){
  function runquery (line 222) | function runquery($sql){
  function jquery_path (line 229) | function jquery_path(){
  function kk_fetch_url (line 247) | function kk_fetch_url($url, $limit = 0, $post = '', $cookie = '', $ignor...
  function fsocketopen (line 356) | function fsocketopen($hostname, $port = 80, &$errno, &$errstr, $timeout ...
  function xml2array (line 367) | function xml2array(&$xml, $isnormal = FALSE) {
  function array2xml (line 373) | function array2xml($arr, $htmlon = TRUE, $isnormal = FALSE, $level = 1) {
  function save_config_file (line 386) | function save_config_file(){
  function saveVersion (line 394) | function saveVersion($version){
  function mklink (line 400) | function mklink($sourceFile, $targetFile){
  function cron_set_nextrun (line 403) | function cron_set_nextrun($timestamp){
  function get_tbs (line 411) | function get_tbs($uid){
  function verify_cookie (line 415) | function verify_cookie($cookie){
  function get_baidu_userinfo (line 419) | function get_baidu_userinfo($uid){
  function client_sign (line 423) | function client_sign($uid, $tieba){
  function zhidao_sign (line 427) | function zhidao_sign($uid){
  function wenku_sign (line 431) | function wenku_sign($uid){
  function update_liked_tieba (line 435) | function update_liked_tieba($uid, $ignore_error = false, $allow_deletion...
  function get_liked_tieba (line 439) | function get_liked_tieba($cookie){
  function do_login (line 443) | function do_login($uid){
  function do_register (line 447) | function do_register($username,$password,$email){
  function delete_user (line 451) | function delete_user($uid){

FILE: system/function/member.php
  function _delete_user (line 4) | function _delete_user($uid){
  function _do_login (line 15) | function _do_login($uid){
  function _do_register (line 24) | function _do_register($username, $password, $email){

FILE: system/function/sign.php
  function _get_tbs (line 4) | function _get_tbs($uid){
  function _verify_cookie (line 18) | function _verify_cookie($cookie){
  function _get_baidu_userinfo (line 30) | function _get_baidu_userinfo($uid){
  function _get_liked_tieba (line 44) | function _get_liked_tieba($cookie){
  function _update_liked_tieba (line 78) | function _update_liked_tieba($uid, $ignore_error = false, $allow_deletio...
  function _client_sign (line 137) | function _client_sign($uid, $tieba){
  function _client_sign_old (line 189) | function _client_sign_old($uid, $tieba){
  function _zhidao_sign (line 250) | function _zhidao_sign($uid){
  function _wenku_sign (line 262) | function _wenku_sign($uid){

FILE: template/default/js/admin.js
  function load_user (line 81) | function load_user(){
  function switch_channel (line 91) | function switch_channel(channel, tips){
  function updater_get_file (line 94) | function updater_get_file(){
  function updater_write_file (line 113) | function updater_write_file(){
  function load_stat (line 137) | function load_stat(){
  function load_updater (line 148) | function load_updater(){
  function load_setting (line 168) | function load_setting(){
  function load_cron (line 189) | function load_cron(){
  function format_time (line 212) | function format_time(time){
  function load_plugin (line 225) | function load_plugin(){
  function load_template (line 268) | function load_template(){
  function parse_hash (line 290) | function parse_hash(){
  function deluser (line 317) | function deluser(uid){
  function autohide_sidebar (line 321) | function autohide_sidebar(){
  function isMobile (line 326) | function isMobile(){
  function eNaBlEaFcHeCk (line 329) | function eNaBlEaFcHeCk(obj, fwin_id){
  function bin2hex (line 335) | function bin2hex(s) {

FILE: template/default/js/fwin.js
  function createWindow (line 3) | function createWindow(){
  function msg_win_action (line 77) | function msg_win_action(link){
  function msg_redirect_action (line 86) | function msg_redirect_action(link){
  function msg_callback_action (line 95) | function msg_callback_action(link, callback){
  function upgrade_tips (line 104) | function upgrade_tips(){
  function showloading (line 108) | function showloading(){
  function hideloading (line 113) | function hideloading(){
  function showcover (line 119) | function showcover(){
  function hidecover (line 124) | function hidecover(){
  function post_win (line 130) | function post_win(link, formid, callback, skip_win){
  function dragMenu (line 148) | function dragMenu(menuObj, e, op) {

FILE: template/default/js/kk_dropdown.js
  function open_menu (line 3) | function open_menu(obj){
  function close_menu (line 19) | function close_menu(obj, force){

FILE: template/default/js/main.js
  function load_liked_tieba (line 79) | function load_liked_tieba() {
  function load_sign_log (line 110) | function load_sign_log() {
  function load_sign_history (line 121) | function load_sign_history(date) {
  function show_sign_log (line 131) | function show_sign_log(result) {
  function load_setting (line 154) | function load_setting() {
  function load_guide (line 170) | function load_guide() {
  function load_baidu_bind (line 174) | function load_baidu_bind() {
  function _status (line 196) | function _status(status) {
  function _exp (line 229) | function _exp(exp) {
  function parse_hash (line 234) | function parse_hash() {
  function autohide_membermenu (line 261) | function autohide_membermenu() {
  function autohide_sidebar (line 267) | function autohide_sidebar() {
  function isMobile (line 273) | function isMobile() {
  function load_js (line 277) | function load_js() {
  function loadTiebaAutoComplete (line 287) | function loadTiebaAutoComplete() {
  function cookieProxy (line 299) | function cookieProxy(action, callback) {
  function checkCookieProxy (line 317) | function checkCookieProxy() {
  function reloadCookieProxy (line 349) | function reloadCookieProxy() {
  function installCookieProxy (line 361) | function installCookieProxy(url) {

FILE: template/default/js/member.js
  function switch_tabs (line 9) | function switch_tabs(target){
Condensed preview — 89 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (337K chars).
[
  {
    "path": "README.md",
    "chars": 704,
    "preview": "# Tieba Sign\nFront-end environment for TiebaSign-Backend services, which provides faster auto-sign experience in http://"
  },
  {
    "path": "admin.php",
    "chars": 20209,
    "preview": "<?php\ndefine('IN_ADMINCP', true);\ndefine('DISABLE_PLUGIN', true);\nrequire_once './system/common.inc.php';\nif(!is_admin($"
  },
  {
    "path": "ajax.php",
    "chars": 1405,
    "preview": "<?php\nrequire_once './system/common.inc.php';\nif(!$uid) exit('Access Denied');\n\n$data = array();\nswitch($_GET['v']){\n\tca"
  },
  {
    "path": "api.php",
    "chars": 1722,
    "preview": "<?php\ndefine('DISABLE_PLUGIN', true);\nrequire_once './system/common.inc.php';\n\nif(!$uid){\n\theader('Location: member.php'"
  },
  {
    "path": "config.yaml",
    "chars": 251,
    "preview": "---\nname: appid\nversion: 1\n\ncron:\n- description: SignTask\n  url: cron.php\n  schedule: */1 * * * *\n\nhandle:\n- expire: if("
  },
  {
    "path": "index.php",
    "chars": 4145,
    "preview": "<?php\nrequire_once './system/common.inc.php';\n\nif(!$uid){\n\theader('Location: member.php');\n\texit();\n}elseif($_GET['actio"
  },
  {
    "path": "install/index.php",
    "chars": 9876,
    "preview": "<?php\nerror_reporting(E_ERROR | E_PARSE);\n$config_file = dirname(__FILE__).'/../system/config.inc.php';\ninclude_once $co"
  },
  {
    "path": "install/install.sql",
    "chars": 3968,
    "preview": "/*\n Install script for version 1.14.4.14\n */\n\nDROP TABLE IF EXISTS `cache`;\nDROP TABLE IF EXISTS `cron`;\nDROP TABLE IF E"
  },
  {
    "path": "install/openshift.php",
    "chars": 7457,
    "preview": "<?php\nif(!getenv('OPENSHIFT_APP_NAME')){\n\theader('Location: ./');\n\texit();\n}\nerror_reporting(E_ERROR | E_PARSE);\n$config"
  },
  {
    "path": "install/sae.php",
    "chars": 6649,
    "preview": "<?php\nif(!defined('SAE_ACCESSKEY')) exit();\ndefine('IN_KKFRAME', true);\ndefine('SYSTEM_ROOT', dirname(__FILE__).'/');\nde"
  },
  {
    "path": "member.php",
    "chars": 7433,
    "preview": "<?php\nrequire_once './system/common.inc.php';\n$invite_code = getSetting('invite_code');\nif($_GET['action'] == 'logout' &"
  },
  {
    "path": "plugin.php",
    "chars": 530,
    "preview": "<?php\ndefine('IN_ADMINCP', true);\ndefine('DISABLE_PLUGIN', true);\nrequire_once './system/common.inc.php';\n$plugin_id = h"
  },
  {
    "path": "plugins/cloud_stat/cloud_stat.cron.php",
    "chars": 948,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n$obj = $_PLUGIN['obj']['cloud_stat'];\nif(!$obj && file_exists(ROOT.'plugins/clo"
  },
  {
    "path": "plugins/cloud_stat/index.inc.php",
    "chars": 1314,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied!');\n$obj = $_PLUGIN['obj']['cloud_stat'];\n?>\n<script type=\"text/jav"
  },
  {
    "path": "plugins/cloud_stat/plugin.class.php",
    "chars": 1649,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied!');\nclass plugin_cloud_stat extends Plugin{\n\tvar $description = '云统"
  },
  {
    "path": "plugins/debug_info/plugin.class.php",
    "chars": 217,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied!');\nclass plugin_debug_info extends Plugin{\n\tvar $description = '(已"
  },
  {
    "path": "plugins/register_limit/plugin.class.php",
    "chars": 1869,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied!');\nclass plugin_register_limit extends Plugin {\n\tvar $description "
  },
  {
    "path": "plugins/stat/plugin.class.php",
    "chars": 557,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied!');\nclass plugin_stat extends Plugin{\n\tvar $description = '用于在页面尾部嵌"
  },
  {
    "path": "plugins/xxx_post/c_daily.cron.php",
    "chars": 592,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n$date = date('Ymd', TIMESTAMP+900);\nDB::query(\"ALTER TABLE xxx_post_log CHANGE "
  },
  {
    "path": "plugins/xxx_post/c_first.cron.php",
    "chars": 2495,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\nrequire_once ROOT.'./plugins/xxx_post/core.php';\n$date = date('Ymd', TIMESTAMP+"
  },
  {
    "path": "plugins/xxx_post/c_se.cron.php",
    "chars": 2352,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\nrequire_once ROOT.'./plugins/xxx_post/core.php';\n$date = date('Ymd', TIMESTAMP+"
  },
  {
    "path": "plugins/xxx_post/c_sxbk.cron.php",
    "chars": 2203,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n$date = date('Ymd', TIMESTAMP+900);\n$count = DB::result_first(\"select COUNT(*) "
  },
  {
    "path": "plugins/xxx_post/core.php",
    "chars": 10842,
    "preview": "<?php\nif (! defined ( 'IN_KKFRAME' ))\texit ();\nfunction get_random_content(){\n\t$text=<<<EOF\n有的人认为坚持会让我们变得更强大,但有时候放手也会。\n你"
  },
  {
    "path": "plugins/xxx_post/index.php",
    "chars": 4601,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied!');\ninclude 'plugins/xxx_post/core.php';\n$obj = $_PLUGIN['obj']['xx"
  },
  {
    "path": "plugins/xxx_post/main.js",
    "chars": 7556,
    "preview": "$(\"#menu_xxx_post-index\").click(function (){\n\tif($(\".nav-tabs >.active\").index()==0) {load_post_set();load_post_adv_set("
  },
  {
    "path": "plugins/xxx_post/plugin.class.php",
    "chars": 11628,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied!');\nclass plugin_xxx_post extends Plugin{\n\tvar $description = '可以模仿"
  },
  {
    "path": "robots.txt",
    "chars": 26,
    "preview": "User-agent: *\nDisallow: /\n"
  },
  {
    "path": "system/class/cache.php",
    "chars": 1112,
    "preview": "<?php\nif (!defined('IN_KKFRAME')) exit();\n$_CACHE = array();\nclass CACHE {\n\tpublic static function get($key) {\n\t\tglobal "
  },
  {
    "path": "system/class/cloud.php",
    "chars": 3579,
    "preview": "<?php\nif (!defined('IN_KKFRAME')) exit();\n\nclass cloud {\n\tconst API_ROOT = 'http://api.ikk.me/reborn/';\n\tconst API_ROOT_"
  },
  {
    "path": "system/class/core.php",
    "chars": 2615,
    "preview": "<?php\nif (!defined('IN_KKFRAME')) exit();\nclass core {\n\tfunction init() {\n\t\tglobal $_config;\n\t\tif(!$_config) require_onc"
  },
  {
    "path": "system/class/db.php",
    "chars": 8794,
    "preview": "<?php\nif (!defined('IN_KKFRAME')) exit();\nclass db_mysql {\n\tvar $curlink;\n\tvar $last_query;\n\tfunction connect() {\n\t\tglob"
  },
  {
    "path": "system/class/hook.php",
    "chars": 4503,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\nclass HOOK{\n\tpublic static function INIT(){\n\t\tglobal $_PLUGIN;\n\t\t$_PLUGIN = arr"
  },
  {
    "path": "system/class/kerror.php",
    "chars": 6309,
    "preview": "<?php\nif (!defined('IN_KKFRAME')) exit();\nclass kerror {\n\tpublic static function system_error($message, $show = true, $h"
  },
  {
    "path": "system/class/mail/phpmail.php",
    "chars": 750,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied');\n\nclass phpmail extends mailer{\n\tvar $id = 'phpmail';\n\tvar $name "
  },
  {
    "path": "system/class/mail/saemail.php",
    "chars": 931,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied');\n\nclass saemail extends mailer{\n\tvar $id = 'saemail';\n\tvar $name "
  },
  {
    "path": "system/class/mail/smtp.php",
    "chars": 4955,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied');\n\nclass smtp extends mailer{\n\tvar $id = 'smtp';\n\tvar $name = 'SMT"
  },
  {
    "path": "system/class/mail.php",
    "chars": 1240,
    "preview": "<?php\nif (!defined('IN_KKFRAME')) exit();\nclass mailer {\n\tvar $_setting;\n\tfunction isAvailable() {\n\t\treturn false;\n\t}\n\tf"
  },
  {
    "path": "system/class/multithread.php",
    "chars": 1108,
    "preview": "<?php\nif (!defined('IN_KKFRAME')) exit();\n\nclass MultiThread {\n\tpublic static function registerThread($max_thread = 6, $"
  },
  {
    "path": "system/class/plugin.php",
    "chars": 1099,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\nclass Plugin {\n\tvar $name;\n\tvar $description;\n\tvar $modules = array();\n\tvar $pe"
  },
  {
    "path": "system/class/updater.php",
    "chars": 4687,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied');\nclass Updater{\n\tconst UPDATE_SERVER = 'http://update.ikk.me/';\n\t"
  },
  {
    "path": "system/class/widget/widget_password.php",
    "chars": 882,
    "preview": "<?php\nif (!defined('IN_KKFRAME')) exit();\nclass Widget_Password {\n\tconst ENCRYPT_TYPE_DEFAULT = '0';\n\tconst ENCRYPT_TYPE"
  },
  {
    "path": "system/class/xmlparse.php",
    "chars": 1802,
    "preview": "<?php\nif (!defined('IN_KKFRAME')) exit();\n\nclass XMLparse {\n\tvar $parser;\n\tvar $document;\n\tvar $stack;\n\tvar $data;\n\tvar "
  },
  {
    "path": "system/common.inc.php",
    "chars": 1993,
    "preview": "<?php\nerror_reporting(E_ALL ^ E_NOTICE);\ndefine('IN_KKFRAME', true);\ndefine('SYSTEM_ROOT', dirname(__FILE__).'/');\ndefin"
  },
  {
    "path": "system/function/cache/cache_plugin.php",
    "chars": 294,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n\n$cache = array();\n$query = DB::query(\"SELECT * FROM `plugin_var`\");\nwhile($res"
  },
  {
    "path": "system/function/cache/cache_plugins.php",
    "chars": 233,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n\n$query = DB::query(\"SELECT * FROM `plugin` WHERE `enable`='1'\");\nwhile($result"
  },
  {
    "path": "system/function/cache/cache_setting.php",
    "chars": 214,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n\n$query = DB::query('SELECT * FROM setting');\nwhile($result = DB::fetch($query)"
  },
  {
    "path": "system/function/cache/cache_username.php",
    "chars": 185,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n\n$query = DB::query(\"SELECT uid, username FROM member\");\nwhile($result = DB::fe"
  },
  {
    "path": "system/function/core.php",
    "chars": 15794,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\nfunction is_admin($uid){\n\treturn in_array($uid, explode(',', getSetting('admin_"
  },
  {
    "path": "system/function/member.php",
    "chars": 1348,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n\nfunction _delete_user($uid){\n\tif(!$uid) return;\n\tif(!is_array($uid)) $uid = ar"
  },
  {
    "path": "system/function/sae.php",
    "chars": 328,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n\n$_config = array(\n\t'db' => array(\n\t\t'server' => SAE_MYSQL_HOST_M,\n\t\t'port' => "
  },
  {
    "path": "system/function/sign.php",
    "chars": 9840,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n\nfunction _get_tbs($uid){\n\tstatic $tbs = array();\n\tif($tbs[$uid]) return $tbs[$"
  },
  {
    "path": "system/function/updater/1.13.php",
    "chars": 4302,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied');\n\nif($current_version == '1.13.9.5'){\n\tDB::query(\"ALTER TABLE `me"
  },
  {
    "path": "system/function/updater/1.14.1.15.php",
    "chars": 250,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied');\nDB::query(\"ALTER TABLE `setting` CHANGE `v` `v` VARCHAR(256) CHA"
  },
  {
    "path": "system/function/updater/1.14.1.16.php",
    "chars": 475,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied');\nrunquery('\nCREATE TABLE IF NOT EXISTS `download` (\n  `path` varc"
  },
  {
    "path": "system/function/updater/1.14.1.23.php",
    "chars": 450,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied');\nrunquery(\"\nALTER TABLE `member_bind` ENGINE = InnoDB;\nALTER TABL"
  },
  {
    "path": "system/function/updater/1.14.2.6.php",
    "chars": 134,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied');\nsaveSetting('version', '1.14.4.12');\nshowmessage('成功更新到 1.14.4.1"
  },
  {
    "path": "system/function/updater/1.14.4.12.php",
    "chars": 201,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied');\nsaveSetting('template', 'default');\nsaveSetting('channel', 'dev'"
  },
  {
    "path": "system/function/updater/1.14.4.14.php",
    "chars": 534,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied');\nDB::query('ALTER TABLE `member_setting` DROP `zhidao_sign`');\nDB"
  },
  {
    "path": "system/function/updater/1.14.4.24.php",
    "chars": 187,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied');\nDB::query(\"DELETE FROM cron WHERE id='sign_retry'\");\nsaveSetting"
  },
  {
    "path": "system/function/updater/1.14.5.12.php",
    "chars": 404,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied');\n$sql = <<<EOF\nCREATE TABLE IF NOT EXISTS `process` (\n  `id` varc"
  },
  {
    "path": "system/function/updater/1.14.5.20.php",
    "chars": 241,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied');\nDB::query('ALTER TABLE sign_log ADD INDEX date_uid (`date`, uid)"
  },
  {
    "path": "system/function/updater/1.14.5.27.php",
    "chars": 232,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied');\nDB::query('ALTER TABLE `member_setting` ADD `zhidao_sign` TINYIN"
  },
  {
    "path": "system/function/updater/1.14.6.2.php",
    "chars": 438,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied');\n\n$query = DB::query(\"SELECT uid, cookie FROM member_setting\");\nw"
  },
  {
    "path": "system/function/updater/1.16.6.23.php",
    "chars": 200,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied');\n\nDB::query('ALTER TABLE `member` MODIFY `password` VARCHAR(255)'"
  },
  {
    "path": "system/function/updater/fallback.php",
    "chars": 329,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit('Access Denied');\nif(!$current_version){\n\tif(!defined('IN_XAE') && getSetting('ver"
  },
  {
    "path": "template/default/admin.php",
    "chars": 8521,
    "preview": "<?php\nif(!defined('IN_ADMINCP')) exit();\n?>\n<!DOCTYPE html>\n<html>\n<head>\n<title>管理中心 - 贴吧签到助手</title>\n<?php include tem"
  },
  {
    "path": "template/default/index.php",
    "chars": 1885,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n$extra_title = getSetting('extra_title');\n$title = $extra_title ? \"贴吧签到助手 - {$e"
  },
  {
    "path": "template/default/js/admin.js",
    "chars": 16832,
    "preview": "$(document).ready(function() {\n\t$('#menu>li').click(function (){\n\t\tif(isMobile()) $('.sidebar').fadeOut();\n\t\tif(!$(this)"
  },
  {
    "path": "template/default/js/fwin.js",
    "chars": 6129,
    "preview": "var fwin_id = 1;\nvar FWIN = [];\nfunction createWindow(){\n\tvar win = new Object();\n\tFWIN[fwin_id] = win;\n\twin.id = fwin_i"
  },
  {
    "path": "template/default/js/kk_dropdown.js",
    "chars": 3359,
    "preview": "// KK Drop-down menu\n(function(){\n\tfunction open_menu(obj){\n\t\tvar menuid = 'dropdown_' + obj.getAttribute('menu-id');\n\t\t"
  },
  {
    "path": "template/default/js/main.js",
    "chars": 17295,
    "preview": "$(document).ready(function () {\n    $('#menu>li').click(function () {\n        if (isMobile()) $('.sidebar').fadeOut();\n "
  },
  {
    "path": "template/default/js/member.js",
    "chars": 364,
    "preview": "$(document).ready(function() {\n\t$('#menu_login').click(function(){\n\t\tswitch_tabs('login');\n\t});\n\t$('#menu_register').cli"
  },
  {
    "path": "template/default/member.php",
    "chars": 1601,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n$extra_title = getSetting('extra_title');\n$title = $extra_title ? \"用户中心 - 贴吧签到助"
  },
  {
    "path": "template/default/message.php",
    "chars": 943,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n?>\n<!DOCTYPE html>\n<html>\n<meta charset=utf-8>\n<title>系统消息</title>\n<meta name=v"
  },
  {
    "path": "template/default/mobile/message.php",
    "chars": 670,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n?>\n<!DOCTYPE html>\n<html>\n<meta charset=utf-8>\n<title>系统消息</title>\n<meta name=v"
  },
  {
    "path": "template/default/style/main.css",
    "chars": 18484,
    "preview": "::selection { background: rgba(127, 127, 127, 0.3); }\nhtml, body, div, h1, h2, h3, h4, h5, h6, p, img, dl, dt, dd, ol, u"
  },
  {
    "path": "template/default/template.xml",
    "chars": 426,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<root>\n\t<item id=\"author\"><![CDATA[kookxiang]]></item>\n\t<item id=\"name\"><![CDATA["
  },
  {
    "path": "template/default/widget/bind_status.php",
    "chars": 501,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n?>\n<h2>百度账号绑定</h2>\n<div class=\"tab tab-binded hidden\">\n<p>您的百度账号绑定正常。</p>\n<br>\n"
  },
  {
    "path": "template/default/widget/find_password.php",
    "chars": 368,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n?>\n<h1>找回密码</h1>\n<form method=\"post\" action=\"member.php?action=find_password\">\n"
  },
  {
    "path": "template/default/widget/footer.php",
    "chars": 908,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n?>\n<script src=\"<?php echo jquery_path(); ?>\"></script>\n<script type=\"text/java"
  },
  {
    "path": "template/default/widget/guide.php",
    "chars": 2280,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n?>\n<h2>贴吧签到助手 配置向导</h2>\n<div id=\"guide_pages\">\n<div id=\"guide_page_1\">\n<p>Hello"
  },
  {
    "path": "template/default/widget/header.php",
    "chars": 1115,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n$extra_title = getSetting('extra_title');\n$title = '贴吧签到助手';\nif($extra_title) $"
  },
  {
    "path": "template/default/widget/liked_tieba.php",
    "chars": 344,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n?>\n<h2>我喜欢的贴吧</h2>\n<p>如果此处显示的贴吧有缺失,请<a href=\"index.php?action=refresh_liked_tie"
  },
  {
    "path": "template/default/widget/login.php",
    "chars": 517,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n?>\n<h1>登录</h1>\n<form method=\"post\" action=\"member.php?action=login\">\n<div class"
  },
  {
    "path": "template/default/widget/meta.php",
    "chars": 631,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n?>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />\n<meta n"
  },
  {
    "path": "template/default/widget/register.php",
    "chars": 676,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n?>\n<h1>注册</h1>\n<form method=\"post\" action=\"member.php?action=register\">\n<div cl"
  },
  {
    "path": "template/default/widget/setting.php",
    "chars": 1053,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n?>\n<h2>设置</h2>\n<form method=\"post\" action=\"index.php?action=update_setting\" id="
  },
  {
    "path": "template/default/widget/sidebar.php",
    "chars": 549,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n?>\n<ul id=\"menu\" class=\"menu\">\n<li id=\"menu_guide\"><a href=\"#guide\">配置向导</a></l"
  },
  {
    "path": "template/default/widget/sign_log.php",
    "chars": 288,
    "preview": "<?php\nif(!defined('IN_KKFRAME')) exit();\n?>\n<h2>签到记录</h2>\n<span id=\"page-flip\" class=\"float-right\"></span>\n<p id=\"sign-s"
  }
]

About this extraction

This page contains the full source code of the kookxiang/Tieba_Sign GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 89 files (275.3 KB), approximately 94.7k tokens, and a symbol index with 347 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!