This commit is contained in:
gangwen.lv 2023-10-23 15:51:36 +08:00
commit 3bafbffd9a
1653 changed files with 289723 additions and 0 deletions

1
VERSION Normal file
View File

@ -0,0 +1 @@
7.2.1

175
config/config.php Executable file
View File

@ -0,0 +1,175 @@
<?php
/**
* ZenTaoPHP的config文件。如果更改配置不要直接修改该文件复制到my.php修改相应的值。
* The config file of zentaophp. Don't modify this file directly, copy the item to my.php and change it.
*
* The author disclaims copyright to this source code. In place of
* a legal notice, here is a blessing:
*
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
*/
/* 保证在命令行环境也能运行。Make sure to run in ztcli env. */
if(!class_exists('config')){class config{}}
if(!function_exists('getWebRoot')){function getWebRoot(){}}
if(!isset($config)) $config = new stdclass();
/* 基本设置。Basic settings. */
$config->version = '3.1'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
$config->charset = 'UTF-8'; // ZenTaoPHP的编码。 The encoding of ZenTaoPHP.
$config->cookieLife = time() + 2592000; // Cookie的生存时间。The cookie life time.
$config->timezone = 'Asia/Shanghai'; // 时区设置。 The time zone setting, for more see http://www.php.net/manual/en/timezones.php.
$config->webRoot = getWebRoot(); // URL根目录。 The root path of the url.
/* 框架路由相关设置。Routing settings. */
$config->requestType = 'PATH_INFO'; // 请求类型PATH_INFO|PATHINFO2|GET。 The request type: PATH_INFO|PATH_INFO2|GET.
$config->requestFix = '-'; // PATH_INFO和PATH_INFO2模式的分隔符。 The divider in the url when PATH_INFO|PATH_INFO2.
$config->moduleVar = 'm'; // 请求类型为GET模块变量名。 requestType=GET: the module var name.
$config->methodVar = 'f'; // 请求类型为GET模块变量名。 requestType=GET: the method var name.
$config->viewVar = 't'; // 请求类型为GET视图变量名。 requestType=GET: the view var name.
$config->sessionVar = 'rid'; // 请求类型为GETsession变量名。 requestType=GET: the session var name.
$config->views = ',html,json,mhtml,xhtml,'; // 支持的视图类型。 Supported view formats.
/* 支持的主题和语言。Supported thems and languages. */
$config->themes['default'] = 'default';
$config->langs['zh-cn'] = '简体';
$config->langs['zh-tw'] = '繁體';
$config->langs['en'] = 'English';
/* 设备类型视图文件前缀。The prefix for view file for different device. */
$config->devicePrefix['mhtml'] = 'm.';
$config->devicePrefix['xhtml'] = 'x.';
/* 默认值设置。Default settings. */
$config->default = new stdclass();
$config->default->view = 'html'; //默认视图。 Default view.
$config->default->lang = 'en'; //默认语言。 Default language.
$config->default->theme = 'default'; //默认主题。 Default theme.
$config->default->module = 'index'; //默认模块。 Default module.
$config->default->method = 'index'; //默认方法。 Default method.
/* 数据库设置。Database settings. */
$config->db = new stdclass();
$config->slaveDB = new stdclass();
$config->db->persistant = false; // 是否为持续连接。 Pconnect or not.
$config->db->driver = 'mysql'; // 目前只支持MySQL数据库。Must be MySQL. Don't support other database server yet.
$config->db->encoding = 'UTF8'; // 数据库编码。 Encoding of database.
$config->db->strictMode = false; // 关闭MySQL的严格模式。 Turn off the strict mode of MySQL.
$config->db->prefix = ''; // 数据库表名前缀。 The prefix of the table name.
$config->slaveDB->persistant = false;
$config->slaveDB->driver = 'mysql';
$config->slaveDB->encoding = 'UTF8';
$config->slaveDB->strictMode = false;
/* 可用域名后缀列表。Domain postfix lists. */
$config->domainPostfix = "|com|com.cn|com.hk|com.tw|com.vc|edu.cn|es|";
$config->domainPostfix .= "|eu|fm|gov.cn|gs|hk|im|in|info|jp|kr|la|me|";
$config->domainPostfix .= "|mobi|my|name|net|net.cn|org|org.cn|pk|pro|";
$config->domainPostfix .= "|sg|so|tel|tk|to|travel|tv|tw|uk|us|ws|";
$config->domainPostfix .= "|ac.cn|bj.cn|sh.cn|tj.cn|cq.cn|he.cn|sn.cn|";
$config->domainPostfix .= "|sx.cn|nm.cn|ln.cn|jl.cn|hl.cn|js.cn|zj.cn|";
$config->domainPostfix .= "|ah.cn|fj.cn|jx.cn|sd.cn|ha.cn|hb.cn|hn.cn|";
$config->domainPostfix .= "|gd.cn|gx.cn|hi.cn|sc.cn|gz.cn|yn.cn|gs.cn|pub|pw|";
$config->domainPostfix .= "|qh.cn|nx.cn|xj.cn|tw.cn|hk.cn|mo.cn|xz.cn|xyz|wang|";
$config->domainPostfix .= "|ae|asia|biz|cc|cd|cm|cn|co|co.jp|co.kr|co.uk|";
$config->domainPostfix .= "|top|ren|club|space|tm|website|cool|company|city|email|";
$config->domainPostfix .= "|market|software|ninja|bike|today|life|co.il|io|";
$config->domainPostfix .= "|mn|ph|ps|tl|uz|vn|co.nz|cz|gg|gl|gr|je|md|me.uk|org.uk|pl|si|sx|vg|ag|";
$config->domainPostfix .= "|bz|cl|ec|gd|gy|ht|lc|ms|mx|pe|tc|vc|ac|bi|mg|mu|sc|as|com.sb|cx|ki|nf|sh|";
$config->domainPostfix .= "|rocks|social|co.com|bio|reviews|link|sexy|us.com|consulting|moda|desi|";
$config->domainPostfix .= "|menu|info|events|webcam|dating|vacations|flights|cruises|global|ca|guru|";
$config->domainPostfix .= "|futbol|rentals|dance|lawyer|attorney|democrat|republican|actor|condos|immobilien|";
$config->domainPostfix .= "|villas|foundation|expert|works|tools|watch|zone|bargains|agency|best|solar|";
$config->domainPostfix .= "|farm|pics|photo|marketing|holiday|gift|buzz|guitars|trade|construction|";
$config->domainPostfix .= "|international|house|coffee|florist|rich|ceo|camp|education|repair|win|site|";
/* 系统框架配置。Framework settings. */
$config->framework = new stdclass();
$config->framework->autoConnectDB = true; // 是否自动连接数据库。 Whether auto connect database or not.
$config->framework->multiLanguage = true; // 是否启用多语言功能。 Whether enable multi lanuage or not.
$config->framework->multiTheme = true; // 是否启用多风格功能。 Whether enable multi theme or not.
$config->framework->multiSite = false; // 是否启用多站点模式。 Whether enable multi site mode or not.
$config->framework->extensionLevel = 1; // 0=>无扩展,1=>公共扩展,2=>站点扩展 0=>no extension, 1=> common extension, 2=> every site has it's extension.
$config->framework->jsWithPrefix = true; // js::set()输出的时候是否增加前缀。 When us js::set(), add prefix or not.
$config->framework->filterBadKeys = true; // 是否过滤不合要求的键值。 Whether filter bad keys or not.
$config->framework->filterTrojan = true; // 是否过滤木马攻击代码。 Whether strip trojan code or not.
$config->framework->filterXSS = true; // 是否过滤XSS攻击代码。 Whether strip xss code or not.
$config->framework->filterParam = 2; // 1=>默认过滤2=>开启过滤参数功能。0=>default filter 2=>Whether strip param.
$config->framework->purifier = false; // 是否对数据做purifier处理。 Whether purifier data or not.
$config->framework->logDays = 14; // 日志文件保存的天数。 The days to save log files.
$config->framework->detectDevice['zh-cn'] = true; // 在zh-cn语言情况下是否启用设备检测功能。 Whether enable device detect or not.
$config->framework->detectDevice['zh-tw'] = true; // 在zh-tw语言情况下是否启用设备检测功能。 Whether enable device detect or not.
$config->framework->detectDevice['en'] = true; // 在en语言情况下是否启用设备检测功能。 Whether enable device detect or not.
/* 文件上传设置。 Upload settings. */
$config->file = new stdclass();
$config->file->dangers = 'php,php3,php4,phtml,php5,jsp,py,rb,asp,aspx,ashx,asa,cer,cdx,aspl,shtm,shtml,html,htm';
$config->file->allowed = 'txt,doc,docx,dot,wps,wri,pdf,ppt,pptx,xls,xlsx,ett,xlt,xlsm,csv,jpg,jpeg,png,psd,gif,ico,bmp,swf,avi,rmvb,rm,mp3,mp4,3gp,flv,mov,movie,rar,zip,bz,bz2,tar,gz';
/* 前端input标签属性设置。Html input tag settings. */
$config->inputTag = new stdclass();
$config->inputTag->disableAutocomplete = ',hours,money,workingHours,normal,late,early,absent,trip,egress,paidLeave,unpaidLeave,timeOvertime,restOvertime,holidayOvertime,lieu,deserve,actual,amount,saveDays,m,h,dom,mon,dow,consumed,estimate,left,teamEstimate,teamConsumed,teamLeft,teamEstimate,teamConsumed,teamLeft,reserveDays,values,width,height,investMoney,';// 涉及到数字的输入框禁用自带填充功能,避免造成干扰。 Disable the autocomplete function of html input tag to avoid interference.
/* 配置参数过滤。Filter param settings. */
$filterConfig = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'filter.php';
if(file_exists($filterConfig)) include $filterConfig;
/* 引用自定义的配置。 Include the custom config file. */
$myConfig = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'my.php';
if(file_exists($myConfig)) include $myConfig;
/* 处理加密的自定义配置 $config->security。Handle security。Handle custom config in $config->security */
if(isset($config->security))
{
$security = trim(base64_decode($config->security));
if(strpos($security, '<?php') === 0)
{
eval(substr($security, 5));
}
else if(strpos($security, '$') === 0)
{
eval($security);
}
else
{
$security = json_decode($security, true);
if(is_array($security))
{
foreach($security as $key => $value)
{
$parent = $config;
if(strpos($key, '.') < 0)
{
$keyPath = explode('.', $key);
$keyPathCount = count($keyPath);
$key = $keyPath[$keyPathCount - 1];
if($keyPathCount < 2) continue;
for($i = 0; $i < $keyPathCount - 1; $i++)
{
$subKey = $keyPath[$i];
$parent = $parent->$subKey;
}
}
$parent->$key = $value;
}
}
}
}
/* 喧喧配置文件。 xxb settings. */
$xxbConfig = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'xxb.php';
if(file_exists($xxbConfig)) include $xxbConfig;
$rightsConfig = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'rights.php';
if(file_exists($rightsConfig)) include $rightsConfig;
/* Include extension config files. */
$extConfigFiles = glob(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'ext/*.php');
if($extConfigFiles) foreach($extConfigFiles as $extConfigFile) include $extConfigFile;
if(!isset($config->debug)) $config->debug = true;

114
config/ext/_0_xuanxuan.php Executable file
View File

@ -0,0 +1,114 @@
<?php
$config->minClientVerson = '5.0'; // 最低支持的客户端版本。The min client version of XXB support for
$config->xuanxuan = new stdclass();
$config->xuanxuan->version = '7.2.1';
$config->xuanxuan->backend = 'xxb';
$config->xuanxuan->backendLang = 'zh-cn';
$config->xuanxuan->key = ''; //Set a 32 byte string as your key.
$config->maps = array();
$config->xxd = new stdclass();
if(!defined('TABLE_IM_CHAT')) define('TABLE_IM_CHAT', '`' . $config->db->prefix . 'im_chat`');
if(!defined('TABLE_IM_CHATUSER')) define('TABLE_IM_CHATUSER', '`' . $config->db->prefix . 'im_chatuser`');
if(!defined('TABLE_IM_CLIENT')) define('TABLE_IM_CLIENT', '`' . $config->db->prefix . 'im_client`');
if(!defined('TABLE_IM_MESSAGE')) define('TABLE_IM_MESSAGE', '`' . $config->db->prefix . 'im_message`');
if(!defined('TABLE_IM_MESSAGESTATUS')) define('TABLE_IM_MESSAGESTATUS', '`' . $config->db->prefix . 'im_messagestatus`');
if(!defined('TABLE_IM_QUEUE')) define('TABLE_IM_QUEUE', '`' . $config->db->prefix . 'im_queue`');
if(!defined('TABLE_IM_CONFERENCE')) define('TABLE_IM_CONFERENCE', '`' . $config->db->prefix . 'im_conference`');
if(!defined('TABLE_IM_CONFERENCEACTION')) define('TABLE_IM_CONFERENCEACTION', '`' . $config->db->prefix . 'im_conferenceaction`');
if(!defined('TABLE_IM_CONFERENCEUSER')) define('TABLE_IM_CONFERENCEUSER', '`' . $config->db->prefix . 'im_conferenceuser`');
if(!defined('TABLE_IM_USERDEVICE')) define('TABLE_IM_USERDEVICE', '`' . $config->db->prefix . 'im_userdevice`');
if(!defined('TABLE_IM_MESSAGE_BACKUP')) define('TABLE_IM_MESSAGE_BACKUP', '`' . $config->db->prefix . 'im_message_backup`');
if(!defined('TABLE_IM_MESSAGE_INDEX')) define('TABLE_IM_MESSAGE_INDEX', '`' . $config->db->prefix . 'im_message_index`');
if(!defined('TABLE_IM_CHAT_MESSAGE_INDEX')) define('TABLE_IM_CHAT_MESSAGE_INDEX', '`' . $config->db->prefix . 'im_chat_message_index`');
$config->xuanxuan->enabledMethods['im']['sysserverstart'] = 'sysServerStart';
$config->xuanxuan->enabledMethods['im']['sysgetserverinfo'] = 'sysGetServerInfo';
$config->xuanxuan->enabledMethods['im']['sysgetdepts'] = 'sysGetDepts';
$config->xuanxuan->enabledMethods['im']['userlogin'] = 'userLogin';
$config->xuanxuan->enabledMethods['im']['userlogout'] = 'userLogout';
$config->xuanxuan->enabledMethods['im']['usergetlist'] = 'userGetList';
$config->xuanxuan->enabledMethods['im']['usergetlistbydept'] = 'userGetListByDept';
$config->xuanxuan->enabledMethods['im']['usergetdeleted'] = 'userGetDeleted';
$config->xuanxuan->enabledMethods['im']['usersearch'] = 'userSearch';
$config->xuanxuan->enabledMethods['im']['userupdate'] = 'userUpdate';
$config->xuanxuan->enabledMethods['im']['usersyncsettings'] = 'userSyncSettings';
$config->xuanxuan->enabledMethods['im']['usersetdevicetoken'] = 'userSetDeviceToken';
$config->xuanxuan->enabledMethods['im']['usergetauthtoken'] = 'userGetAuthToken';
$config->xuanxuan->enabledMethods['im']['userrenewauthtoken'] = 'userRenewAuthToken';
$config->xuanxuan->enabledMethods['im']['chatgetpubliclist'] = 'chatGetPublicList';
$config->xuanxuan->enabledMethods['im']['chatgetlist'] = 'chatGetList';
$config->xuanxuan->enabledMethods['im']['chatgetmembers'] = 'chatGetMembers';
$config->xuanxuan->enabledMethods['im']['chatgetmemberdetails'] = 'chatGetMemberDetails';
$config->xuanxuan->enabledMethods['im']['chatgetmessageinfo'] = 'chatGetMessageInfo';
$config->xuanxuan->enabledMethods['im']['chatcreate'] = 'chatCreate';
$config->xuanxuan->enabledMethods['im']['chataddadmins'] = 'chatAddAdmins';
$config->xuanxuan->enabledMethods['im']['chatremoveadmins'] = 'chatRemoveAdmins';
$config->xuanxuan->enabledMethods['im']['chatjoin'] = 'chatJoin';
$config->xuanxuan->enabledMethods['im']['chatleave'] = 'chatLeave';
$config->xuanxuan->enabledMethods['im']['chatrename'] = 'chatRename';
$config->xuanxuan->enabledMethods['im']['chatarchive'] = 'chatArchive';
$config->xuanxuan->enabledMethods['im']['chatdismiss'] = 'chatDismiss';
$config->xuanxuan->enabledMethods['im']['chatsetcommitters'] = 'chatSetCommitters';
$config->xuanxuan->enabledMethods['im']['chatsetvisibility'] = 'chatSetVisibility';
$config->xuanxuan->enabledMethods['im']['chatsetconfig'] = 'chatSetConfig';
$config->xuanxuan->enabledMethods['im']['chatsearch'] = 'chatSearch';
$config->xuanxuan->enabledMethods['im']['chatsetavatar'] = 'chatSetAvatar';
$config->xuanxuan->enabledMethods['im']['chatstar'] = 'chatStar';
$config->xuanxuan->enabledMethods['im']['chathide'] = 'chatHide';
$config->xuanxuan->enabledMethods['im']['chatmute'] = 'chatMute';
$config->xuanxuan->enabledMethods['im']['chatfreeze'] = 'chatFreeze';
$config->xuanxuan->enabledMethods['im']['chatsetcategory'] = 'chatSetCategory';
$config->xuanxuan->enabledMethods['im']['chatinvite'] = 'chatInvite';
$config->xuanxuan->enabledMethods['im']['chatkick'] = 'chatKick';
$config->xuanxuan->enabledMethods['im']['chatchangeownership'] = 'chatChangeOwnership';
$config->xuanxuan->enabledMethods['im']['chatpinmessages'] = 'chatPinMessages';
$config->xuanxuan->enabledMethods['im']['chatunpinmessages'] = 'chatUnpinMessages';
$config->xuanxuan->enabledMethods['im']['chatgethistory'] = 'chatGetHistory';
$config->xuanxuan->enabledMethods['im']['chatsetlastreadmessage'] = 'chatSetLastReadMessage';
$config->xuanxuan->enabledMethods['im']['chatsetlastreadmessagebyindex'] = 'chatSetLastReadMessageByIndex';
$config->xuanxuan->enabledMethods['im']['chatmerge'] = 'chatMerge';
$config->xuanxuan->enabledMethods['im']['chatgetbygid'] = 'chatGetByGid';
$config->xuanxuan->enabledMethods['im']['messageretract'] = 'messageRetract';
$config->xuanxuan->enabledMethods['im']['messagesend'] = 'messageSend';
$config->xuanxuan->enabledMethods['im']['conferencegetbychat'] = 'conferenceGetByChat';
$config->xuanxuan->enabledMethods['im']['conferencegetbynumber'] = 'conferenceGetByNumber';
$config->xuanxuan->enabledMethods['im']['conferencegetbycondition'] = 'conferenceGetByCondition';
$config->xuanxuan->enabledMethods['im']['conferencecreate'] = 'conferenceCreate';
$config->xuanxuan->enabledMethods['im']['conferencecreatedetached'] = 'conferenceCreateDetached';
$config->xuanxuan->enabledMethods['im']['conferencejoin'] = 'conferenceJoin';
$config->xuanxuan->enabledMethods['im']['conferenceinvite'] = 'conferenceInvite';
$config->xuanxuan->enabledMethods['im']['conferenceleave'] = 'conferenceLeave';
$config->xuanxuan->enabledMethods['im']['conferenceclose'] = 'conferenceClose';
$config->xuanxuan->enabledMethods['im']['conferencehide'] = 'conferenceHide';
$config->xuanxuan->enabledMethods['im']['conferencecancelscheduled'] = 'conferencecancelscheduled';
$config->xuanxuan->enabledMethods['im']['conferencesyncaction'] = 'conferenceSyncAction';
$config->xuanxuan->enabledMethods['im']['conferenceclean'] = 'conferenceClean';
$config->xuanxuan->enabledMethods['im']['conferenceedit'] = 'conferenceEdit';
$config->xuanxuan->enabledMethods['im']['extensiongetlist'] = 'extensionGetList';
$config->xuanxuan->enabledMethods['im']['syncofflinemessages'] = 'syncOfflineMessages';
$config->xuanxuan->enabledMethods['im']['syncnotifications'] = 'syncNotifications';
$config->xuanxuan->enabledMethods['im']['syncconferences'] = 'syncConferences';
$config->xuanxuan->enabledMethods['im']['syncusers'] = 'syncUsers';
$config->xuanxuan->enabledMethods['im']['syncdepts'] = 'syncDepts';
$config->xuanxuan->enabledMethods['im']['syncconfig'] = 'syncConfig';
$config->xuanxuan->enabledMethods['im']['fileupload'] = 'fileUpload';
$config->xuanxuan->enabledMethods['im']['todoupsert'] = 'todoUpsert';
$config->xuanxuan->enabledMethods['im']['todogetlist'] = 'todoGetList';
$config->xuanxuan->enabledMethods['im']['updatelastpoll'] = 'updateLastPoll';
$config->xuanxuan->enabledMethods['im']['checkpasswordchanges'] = 'checkpasswordchanges';
$config->xuanxuan->enabledMethods['im']['messagesyncsinceoffline'] = 'messageSyncSinceOffline';
$config->xuanxuan->enabledMethods['im']['messagesyncmissed'] = 'messageSyncMissed';
$config->xuanxuan->enabledMethods['im']['chatgetlastmessage'] = 'chatGetLastMessage';
$config->xuanxuan->enabledMethods['im']['messagesync'] = 'messageSync';
$config->xuanxuan->enabledMethods['im']['messagesyncbyindexes'] = 'messageSyncByIndexes';
$config->xuanxuan->enabledMethods['im']['messagegetlist'] = 'messageGetList';
$config->xuanxuan->enabledMethods['im']['messagegetlistbyindexes'] = 'messageGetListByIndexes';
$config->xuanxuan->enabledMethods['im']['maintenance'] = 'maintenance';
$config->xuanxuan->enabledMethods['im']['checkuserstobekicked'] = 'checkUsersToBeKicked';
$config->xuanxuan->enabledMethods['entry']['visit'] = 'visit';
// Please use lowercase keys in enabledMethods.

346
config/ext/_1_maps.php Executable file
View File

@ -0,0 +1,346 @@
<?php
$config->maps['$version'] = '7.2.0';
$config->maps['pager'] = array('type' => 'object', 'name' => 'pager');
$config->maps['pager']['dataType'][] = array('name' => 'gid', 'type' => 'basic');
$config->maps['pager']['dataType'][] = array('name' => 'recTotal', 'type' => 'basic');
$config->maps['pager']['dataType'][] = array('name' => 'pageID', 'type' => 'basic');
$config->maps['pager']['dataType'][] = array('name' => 'recPerPage', 'type' => 'basic');
$config->maps['pager']['dataType'][] = array('name' => 'data', 'type' => 'basic');
$config->maps['memberStatus'] = array('name' => 'memberStatus', 'type' => 'basic', 'options' => array('','offline','online','busy','away','meeting'), 'dataType' => array());
$config->maps['basicMember'] = array('type' => 'object', 'name' => 'basicMember');
$config->maps['basicMember']['dataType'][] = array('name' => 'id', 'type' => 'basic');
$config->maps['basicMember']['dataType'][] = array('name' => 'account', 'type' => 'basic');
$config->maps['basicMember']['dataType'][] = array('name' => 'status', 'type' => $config->maps['memberStatus']['type'], 'options' => $config->maps['memberStatus']['options'], 'dataType' => &$config->maps['memberStatus']['dataType']);
$config->maps['basicMember']['dataType'][] = array('name' => 'realname', 'type' => 'basic');
$config->maps['basicMember']['dataType'][] = array('name' => 'dept', 'type' => 'basic');
$config->maps['member'] = array('type' => 'object', 'name' => 'member');
$config->maps['member']['dataType'][] = array('name' => 'id', 'type' => 'basic');
$config->maps['member']['dataType'][] = array('name' => 'account', 'type' => 'basic');
$config->maps['member']['dataType'][] = array('name' => 'status', 'type' => $config->maps['memberStatus']['type'], 'options' => $config->maps['memberStatus']['options'], 'dataType' => &$config->maps['memberStatus']['dataType']);
$config->maps['member']['dataType'][] = array('name' => 'realname', 'type' => 'basic');
$config->maps['member']['dataType'][] = array('name' => 'avatar', 'type' => 'basic');
$config->maps['member']['dataType'][] = array('name' => 'gender', 'type' => 'basic');
$config->maps['member']['dataType'][] = array('name' => 'dept', 'type' => 'basic');
$config->maps['member']['dataType'][] = array('name' => 'role', 'type' => 'basic');
$config->maps['member']['dataType'][] = array('name' => 'signed', 'type' => 'basic');
$config->maps['member']['dataType'][] = array('name' => 'email', 'type' => 'basic');
$config->maps['member']['dataType'][] = array('name' => 'mobile', 'type' => 'basic');
$config->maps['member']['dataType'][] = array('name' => 'phone', 'type' => 'basic');
$config->maps['member']['dataType'][] = array('name' => 'site', 'type' => 'basic');
$config->maps['member']['dataType'][] = array('name' => 'admin', 'type' => 'basic');
$config->maps['member']['dataType'][] = array('name' => 'realnames', 'type' => 'basic');
$config->maps['member']['dataType'][] = array('name' => 'deleted', 'type' => 'basic');
$config->maps['member']['dataType'][] = array('name' => 'weixin', 'type' => 'basic');
$config->maps['member']['dataType'][] = array('name' => 'address', 'type' => 'basic');
$config->maps['member']['dataType'][] = array('name' => 'qq', 'type' => 'basic');
$config->maps['userUpdateData'] = array('type' => 'object', 'name' => 'userUpdateData');
$config->maps['userUpdateData']['dataType'][] = array('name' => 'account', 'type' => 'basic');
$config->maps['userUpdateData']['dataType'][] = array('name' => 'status', 'type' => $config->maps['memberStatus']['type'], 'options' => $config->maps['memberStatus']['options'], 'dataType' => &$config->maps['memberStatus']['dataType']);
$config->maps['userUpdateData']['dataType'][] = array('name' => 'password', 'type' => 'basic');
$config->maps['userUpdateData']['dataType'][] = array('name' => 'address', 'type' => 'basic');
$config->maps['userUpdateData']['dataType'][] = array('name' => 'gender', 'type' => 'basic');
$config->maps['userUpdateData']['dataType'][] = array('name' => 'mobile', 'type' => 'basic');
$config->maps['userUpdateData']['dataType'][] = array('name' => 'phone', 'type' => 'basic');
$config->maps['userUpdateData']['dataType'][] = array('name' => 'qq', 'type' => 'basic');
$config->maps['userUpdateData']['dataType'][] = array('name' => 'realname', 'type' => 'basic');
$config->maps['userUpdateData']['dataType'][] = array('name' => 'weixin', 'type' => 'basic');
$config->maps['userUpdateData']['dataType'][] = array('name' => 'email', 'type' => 'basic');
$config->maps['extension'] = array('type' => 'object', 'name' => 'extension');
$config->maps['extension']['dataType'][] = array('name' => 'name', 'type' => 'basic');
$config->maps['extension']['dataType'][] = array('name' => 'entryID', 'type' => 'basic');
$config->maps['extension']['dataType'][] = array('name' => 'md5', 'type' => 'basic');
$config->maps['extension']['dataType'][] = array('name' => 'download', 'type' => 'basic');
$config->maps['extension']['dataType'][] = array('name' => 'displayName', 'type' => 'basic');
$config->maps['extension']['dataType'][] = array('name' => 'abbrName', 'type' => 'basic');
$config->maps['extension']['dataType'][] = array('name' => 'webViewUrl', 'type' => 'basic');
$config->maps['extension']['dataType'][] = array('name' => 'logo', 'type' => 'basic');
$config->maps['extension']['dataType'][] = array('name' => 'data', 'type' => 'basic');
$config->maps['extension']['dataType'][] = array('name' => 'optional', 'type' => 'basic');
$config->maps['extension']['dataType'][] = array('name' => 'enable', 'type' => 'basic');
$config->maps['extensionList'] = array('name' => 'extensionList', 'type' => 'list', 'dataType' => &$config->maps['extension']);
$config->maps['notification'] = array('type' => 'object', 'name' => 'notification');
$config->maps['notification']['dataType'][] = array('name' => 'id', 'type' => 'basic');
$config->maps['notification']['dataType'][] = array('name' => 'gid', 'type' => 'basic');
$config->maps['notification']['dataType'][] = array('name' => 'title', 'type' => 'basic');
$config->maps['notification']['dataType'][] = array('name' => 'date', 'type' => 'basic');
$config->maps['notification']['dataType'][] = array('name' => 'sender', 'type' => 'basic');
$config->maps['notification']['dataType'][] = array('name' => 'actions', 'type' => 'basic');
$config->maps['notification']['dataType'][] = array('name' => 'url', 'type' => 'basic');
$config->maps['notification']['dataType'][] = array('name' => 'cgid', 'type' => 'basic');
$config->maps['notification']['dataType'][] = array('name' => 'content', 'type' => 'basic');
$config->maps['notification']['dataType'][] = array('name' => 'subtitle', 'type' => 'basic');
$config->maps['notification']['dataType'][] = array('name' => 'contentType', 'type' => 'basic', 'options' => array('text','plain'));
$config->maps['notification']['dataType'][] = array('name' => 'type', 'type' => 'basic', 'options' => array('notification'));
$config->maps['chatMessage'] = array('type' => 'object', 'name' => 'chatMessage');
$config->maps['chatMessage']['dataType'][] = array('name' => 'gid', 'type' => 'basic');
$config->maps['chatMessage']['dataType'][] = array('name' => 'cgid', 'type' => 'basic');
$config->maps['chatMessage']['dataType'][] = array('name' => 'user', 'type' => 'basic');
$config->maps['chatMessage']['dataType'][] = array('name' => 'date', 'type' => 'basic');
$config->maps['chatMessage']['dataType'][] = array('name' => 'content', 'type' => 'basic');
$config->maps['chatMessage']['dataType'][] = array('name' => 'id', 'type' => 'basic');
$config->maps['chatMessage']['dataType'][] = array('name' => 'index', 'type' => 'basic');
$config->maps['chatMessage']['dataType'][] = array('name' => 'data', 'type' => 'basic');
$config->maps['chatMessage']['dataType'][] = array('name' => 'type', 'type' => 'basic', 'options' => array('','normal','broadcast','notification'));
$config->maps['chatMessage']['dataType'][] = array('name' => 'contentType', 'type' => 'basic', 'options' => array('','text','plain','image','file','emoticon','code','object'));
$config->maps['chatMessage']['dataType'][] = array('name' => 'deleted', 'type' => 'basic');
$config->maps['chatMembers'] = array('type' => 'object', 'name' => 'chatMembers');
$config->maps['chatMembers']['dataType'][] = array('name' => 'gid', 'type' => 'basic');
$config->maps['chatMembers']['dataType'][] = array('name' => 'members', 'type' => 'basic');
$config->maps['chatMemberDetail'] = array('type' => 'object', 'name' => 'chatMemberDetail');
$config->maps['chatMemberDetail']['dataType'][] = array('name' => 'id', 'type' => 'basic');
$config->maps['chatMemberDetail']['dataType'][] = array('name' => 'account', 'type' => 'basic');
$config->maps['chatMemberDetail']['dataType'][] = array('name' => 'join', 'type' => 'basic');
$config->maps['chatMemberDetail']['dataType'][] = array('name' => 'lastSeen', 'type' => 'basic');
$config->maps['chatMemberDetail']['dataType'][] = array('name' => 'lastPost', 'type' => 'basic');
$config->maps['chatMemberDetail']['dataType'][] = array('name' => 'isOwner', 'type' => 'basic');
$config->maps['chatMemberDetail']['dataType'][] = array('name' => 'isAdmin', 'type' => 'basic');
$config->maps['chatstar'] = array('type' => 'object', 'name' => 'chatstar');
$config->maps['chatstar']['dataType'][] = array('name' => 'gid', 'type' => 'basic');
$config->maps['chatstar']['dataType'][] = array('name' => 'star', 'type' => 'basic');
$config->maps['chatMessageList'] = array('name' => 'chatMessageList', 'type' => 'list', 'dataType' => &$config->maps['chatMessage']);
$config->maps['sendingChatMessage'] = array('type' => 'object', 'name' => 'sendingChatMessage');
$config->maps['sendingChatMessage']['dataType'][] = array('name' => 'gid', 'type' => 'basic');
$config->maps['sendingChatMessage']['dataType'][] = array('name' => 'cgid', 'type' => 'basic');
$config->maps['sendingChatMessage']['dataType'][] = array('name' => 'user', 'type' => 'basic');
$config->maps['sendingChatMessage']['dataType'][] = array('name' => 'content', 'type' => 'basic');
$config->maps['sendingChatMessage']['dataType'][] = array('name' => 'data', 'type' => 'basic');
$config->maps['sendingChatMessage']['dataType'][] = array('name' => 'type', 'type' => 'basic', 'options' => array('','normal','broadcast','notification'));
$config->maps['sendingChatMessage']['dataType'][] = array('name' => 'contentType', 'type' => 'basic', 'options' => array('','text','plain','image','file','emoticon','code','object'));
$config->maps['sendingChatMessage']['dataType'][] = array('name' => 'date', 'type' => 'basic');
$config->maps['sendingChatMessage']['dataType'][] = array('name' => 'deleted', 'type' => 'basic');
$config->maps['sendingChatMessageList'] = array('name' => 'sendingChatMessageList', 'type' => 'list', 'dataType' => &$config->maps['sendingChatMessage']);
$config->maps['basicChat'] = array('type' => 'object', 'name' => 'basicChat');
$config->maps['basicChat']['dataType'][] = array('name' => 'gid', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'createdDate', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'createdBy', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'ownedBy', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'id', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'name', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'lastActiveTime', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'lastMessage', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'public', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'archiveDate', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'star', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'freeze', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'mute', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'hide', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'editedDate', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'type', 'type' => 'basic', 'options' => array('group','one2one','system','robot'));
$config->maps['basicChat']['dataType'][] = array('name' => 'dismissDate', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'committers', 'type' => 'basic', 'options' => array('','$ADMINS','$ALL'));
$config->maps['basicChat']['dataType'][] = array('name' => 'admins', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'pinnedMessages', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'lastReadMessage', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'mergedDate', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'mergedChats', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'lastReadMessageIndex', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'lastMessageInfo', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'adminInvite', 'type' => 'basic');
$config->maps['basicChat']['dataType'][] = array('name' => 'avatar', 'type' => 'basic');
$config->maps['chat'] = $config->maps['basicChat'];
$config->maps['chat']['dataType'][] = array('name' => 'members', 'type' => 'basic');
$config->maps['basicChatList'] = array('name' => 'basicChatList', 'type' => 'list', 'dataType' => &$config->maps['basicChat']);
$config->maps['chatList'] = array('name' => 'chatList', 'type' => 'list', 'dataType' => &$config->maps['chat']);
$config->maps['basicPack'] = array('type' => 'object', 'name' => 'basicPack');
$config->maps['basicPack']['dataType'][] = array('name' => 'rid', 'type' => 'basic');
$config->maps['basicPack']['dataType'][] = array('name' => 'method', 'type' => 'basic', 'options' => array('messagesend','syssessionid','usergetlist','chatgetlist','userlogin','userlogout','userupdate','usersyncsettings','userkickoff','messageretract','messageupdate','chattyping','chatcreate','chatrename','chatinvite','chatkick','chatjoin','chatleave','chatstar','chatunstar','chatmute','chatunmute','chatfreeze','chatunfreeze','chathide','chatarchive','chatdismiss','chatgethistory','chatgetpubliclist','chatsetcategory','chatrenamecategory','chatdeletecategory','chataddadmins','chatremoveadmins','chatsetcommitters','chatsetvisibility','chatsetconfig','chatsearch','chatsetavatar','chatsetlastreadmessage','chatsetlastreadmessagebyindex','syncusers','syncnotifications','syncofflinemessages','extensiongetlist','fileupload','filedownload','usersetdevicetoken','sysgetserverinfo','sysserverstart','ping'));
$config->maps['basicPack']['dataType'][] = array('name' => 'module', 'type' => 'basic', 'options' => array('','im','server','sys','chat','entry','user','extension'));
$config->maps['basicPack']['dataType'][] = array('name' => 'device', 'type' => 'basic', 'options' => array('desktop','mobile'));
$config->maps['requestPack'] = $config->maps['basicPack'];
$config->maps['requestPack']['dataType'][] = array('name' => 'params', 'type' => 'basic');
$config->maps['requestPack']['dataType'][] = array('name' => 'userID', 'type' => 'basic');
$config->maps['requestPack']['dataType'][] = array('name' => 'lang', 'type' => 'basic', 'options' => array('zh-cn','zh-tw','en'));
$config->maps['requestPack']['dataType'][] = array('name' => 'version', 'type' => 'basic', 'options' => array('4.0.beta3','4.0'));
$config->maps['responsePack'] = $config->maps['basicPack'];
$config->maps['responsePack']['dataType'][] = array('name' => 'data', 'type' => 'basic');
$config->maps['responsePack']['dataType'][] = array('name' => 'result', 'type' => 'basic', 'options' => array('success','fail'));
$config->maps['responsePack']['dataType'][] = array('name' => 'message', 'type' => 'basic');
$config->maps['messageResponsePack'] = $config->maps['responsePack'];
$config->maps['messageResponsePack']['dataType'][] = array('name' => 'code', 'type' => 'basic');
$config->maps['memberResponsePack'] = $config->maps['responsePack'];
$config->maps['memberResponsePack']['dataType'][4] = array('name' => 'data', 'type' => $config->maps['member']['type'], 'dataType' => &$config->maps['member']['dataType']);
$config->maps['chatResponsePack'] = $config->maps['responsePack'];
$config->maps['chatResponsePack']['dataType'][4] = array('name' => 'data', 'type' => $config->maps['chat']['type'], 'dataType' => &$config->maps['chat']['dataType']);
$config->maps['chatListResponsePack'] = $config->maps['responsePack'];
$config->maps['chatListResponsePack']['dataType'][4] = array('name' => 'data', 'type' => $config->maps['basicChatList']['type'], 'dataType' => &$config->maps['basicChatList']['dataType']);
$config->maps['messageListRequestPack'] = $config->maps['requestPack'];
$config->maps['messageListRequestPack']['dataType'][4] = array('name' => 'params', 'type' => 'list', 'dataType' => &$config->maps['sendingChatMessageList']);
$config->maps['messageListResponsePack'] = $config->maps['responsePack'];
$config->maps['messageListResponsePack']['dataType'][4] = array('name' => 'data', 'type' => $config->maps['chatMessageList']['type'], 'dataType' => &$config->maps['chatMessageList']['dataType']);
$config->maps['sysgetdeptsResponse'] = $config->maps['responsePack'];
$config->maps['sysgetdeptsResponse']['dataType'][] = array('name' => 'roles', 'type' => 'basic');
$config->maps['userloginResponse'] = $config->maps['memberResponsePack'];
$config->maps['userloginResponse']['name'] = 'userloginResponse';
$config->maps['userlogoutResponse'] = $config->maps['memberResponsePack'];
$config->maps['userlogoutResponse']['name'] = 'userlogoutResponse';
$config->maps['usergetlistResponse'] = $config->maps['responsePack'];
$config->maps['usergetlistResponse']['dataType'][4] = array('name' => 'data', 'type' => 'list', 'dataType' => &$config->maps['member']);
$config->maps['chatSearchResult'] = array('type' => 'object', 'name' => 'chatSearchResult');
$config->maps['chatSearchResult']['dataType'][] = array('name' => 'id', 'type' => 'basic');
$config->maps['chatSearchResult']['dataType'][] = array('name' => 'gid', 'type' => 'basic');
$config->maps['chatSearchResult']['dataType'][] = array('name' => 'name', 'type' => 'basic');
$config->maps['chatSearchResult']['dataType'][] = array('name' => 'public', 'type' => 'basic');
$config->maps['chatSearchResult']['dataType'][] = array('name' => 'groupOwner', 'type' => 'basic');
$config->maps['chatSearchResult']['dataType'][] = array('name' => 'createdDate', 'type' => 'basic');
$config->maps['chatSearchResult']['dataType'][] = array('name' => 'archiveDate', 'type' => 'basic');
$config->maps['chatSearchResult']['dataType'][] = array('name' => 'lastActiveTime', 'type' => 'basic');
$config->maps['chatSearchResult']['dataType'][] = array('name' => 'userCount', 'type' => 'basic');
$config->maps['chatsearchResponse'] = $config->maps['responsePack'];
$config->maps['chatsearchResponse']['dataType'][4] = array('name' => 'data', 'type' => 'list', 'dataType' => &$config->maps['chatSearchResult']);
$config->maps['chatsearchResponse']['dataType'][] = array('name' => 'pager', 'type' => $config->maps['pager']['type'], 'dataType' => &$config->maps['pager']['dataType']);
$config->maps['usergetbasiclistResponse'] = $config->maps['responsePack'];
$config->maps['usergetbasiclistResponse']['dataType'][4] = array('name' => 'data', 'type' => 'list', 'dataType' => &$config->maps['basicMember']);
$config->maps['usergetbasiclistResponse']['dataType'][] = array('name' => 'roles', 'type' => 'basic');
$config->maps['usergetbasiclistResponse']['dataType'][] = array('name' => 'depts', 'type' => 'basic');
$config->maps['usergetbasiclistResponse']['dataType'][] = array('name' => 'basic', 'type' => 'basic');
$config->maps['usergetdeletedRequest'] = array('type' => 'object', 'name' => 'usergetdeletedRequest');
$config->maps['usergetdeletedResponse'] = $config->maps['usergetlistResponse'];
$config->maps['usergetdeletedResponse']['name'] = 'usergetdeletedResponse';
$config->maps['usersearchResponse'] = $config->maps['usergetlistResponse'];
$config->maps['usersearchResponse']['dataType'][] = array('name' => 'pager', 'type' => $config->maps['pager']['type'], 'dataType' => &$config->maps['pager']['dataType']);
$config->maps['usersearchidResponse'] = $config->maps['responsePack'];
$config->maps['usersearchidResponse']['dataType'][4] = array('name' => 'data', 'type' => 'basic');
$config->maps['usersearchidResponse']['dataType'][] = array('name' => 'pager', 'type' => $config->maps['pager']['type'], 'dataType' => &$config->maps['pager']['dataType']);
$config->maps['chatgetlistResponse'] = $config->maps['chatListResponsePack'];
$config->maps['chatgetlistResponse']['name'] = 'chatgetlistResponse';
$config->maps['chatgetmembersResponse'] = $config->maps['responsePack'];
$config->maps['chatgetmembersResponse']['dataType'][4] = array('name' => 'data', 'type' => $config->maps['chatMembers']['type'], 'dataType' => &$config->maps['chatMembers']['dataType']);
$config->maps['chatgetmemberdetailsResponse'] = $config->maps['responsePack'];
$config->maps['chatgetmemberdetailsResponse']['dataType'][4] = array('name' => 'data', 'type' => 'list', 'dataType' => &$config->maps['chatMemberDetail']);
$config->maps['chatgetmemberdetailsResponse']['dataType'][] = array('name' => 'pager', 'type' => $config->maps['pager']['type'], 'dataType' => &$config->maps['pager']['dataType']);
$config->maps['chatstarResponse'] = $config->maps['responsePack'];
$config->maps['chatstarResponse']['dataType'][4] = array('name' => 'data', 'type' => $config->maps['chatstar']['type'], 'dataType' => &$config->maps['chatstar']['dataType']);
$config->maps['chatgetlastmessageResponse'] = $config->maps['messageListResponsePack'];
$config->maps['chatgetlastmessageResponse']['name'] = 'chatgetlastmessageResponse';
$config->maps['chatMessageInfoPack'] = array('type' => 'object', 'name' => 'chatMessageInfoPack');
$config->maps['chatMessageInfoPack']['dataType'][] = array('name' => 'lastMessage', 'type' => 'basic');
$config->maps['chatMessageInfoPack']['dataType'][] = array('name' => 'messageCount', 'type' => 'basic');
$config->maps['chatgetmessageinfoResponse'] = $config->maps['responsePack'];
$config->maps['chatgetmessageinfoResponse']['dataType'][4] = array('name' => 'data', 'type' => $config->maps['chatMessageInfoPack']['type'], 'dataType' => &$config->maps['chatMessageInfoPack']['dataType']);
$config->maps['usergetlistbydeptResponse'] = $config->maps['responsePack'];
$config->maps['usergetlistbydeptResponse']['dataType'][] = array('name' => 'pager', 'type' => $config->maps['pager']['type'], 'dataType' => &$config->maps['pager']['dataType']);
$config->maps['messagesendRequest'] = $config->maps['messageListRequestPack'];
$config->maps['messagesendRequest']['name'] = 'messagesendRequest';
$config->maps['messagesendResponse'] = $config->maps['messageListResponsePack'];
$config->maps['messagesendResponse']['name'] = 'messagesendResponse';
$config->maps['messageretractRequest'] = $config->maps['messageListRequestPack'];
$config->maps['messageretractRequest']['name'] = 'messageretractRequest';
$config->maps['messageretractResponse'] = $config->maps['messageListResponsePack'];
$config->maps['messageretractResponse']['name'] = 'messageretractResponse';
$config->maps['messagegetlistResponse'] = $config->maps['messageListResponsePack'];
$config->maps['messagegetlistResponse']['name'] = 'messagegetlistResponse';
$config->maps['messagegetlistbyindexesResponse'] = $config->maps['messageListResponsePack'];
$config->maps['messagegetlistbyindexesResponse']['name'] = 'messagegetlistbyindexesResponse';
$config->maps['messagesyncResponse'] = $config->maps['messageListResponsePack'];
$config->maps['messagesyncResponse']['name'] = 'messagesyncResponse';
$config->maps['messagesyncidResponse'] = $config->maps['responsePack'];
$config->maps['messagesyncidResponse']['dataType'][4] = array('name' => 'data', 'type' => 'basic');
$config->maps['messagesyncmissedResponse'] = $config->maps['messageListResponsePack'];
$config->maps['messagesyncmissedResponse']['name'] = 'messagesyncmissedResponse';
$config->maps['messagesyncsinceofflineResponse'] = $config->maps['messageListResponsePack'];
$config->maps['messagesyncsinceofflineResponse']['name'] = 'messagesyncsinceofflineResponse';
$config->maps['syncofflinemessagesResponse'] = $config->maps['messageListResponsePack'];
$config->maps['syncofflinemessagesResponse']['name'] = 'syncofflinemessagesResponse';
$config->maps['syncnotificationsResponse'] = $config->maps['responsePack'];
$config->maps['syncnotificationsResponse']['dataType'][4] = array('name' => 'data', 'type' => 'list', 'dataType' => &$config->maps['notification']);
$config->maps['userupdateRequest'] = $config->maps['requestPack'];
$config->maps['userupdateRequest']['dataType'][4] = array('name' => 'params', 'type' => 'list', 'dataType' => &$config->maps['userUpdateData']);
$config->maps['chatcreateResponse'] = $config->maps['chatResponsePack'];
$config->maps['chatcreateResponse']['name'] = 'chatcreateResponse';
$config->maps['chatjoinResponse'] = $config->maps['chatResponsePack'];
$config->maps['chatjoinResponse']['name'] = 'chatjoinResponse';
$config->maps['chatleaveResponse'] = $config->maps['chatResponsePack'];
$config->maps['chatleaveResponse']['name'] = 'chatleaveResponse';
$config->maps['chatrenameResponse'] = $config->maps['chatResponsePack'];
$config->maps['chatrenameResponse']['name'] = 'chatrenameResponse';
$config->maps['chatinviteResponse'] = $config->maps['chatResponsePack'];
$config->maps['chatinviteResponse']['name'] = 'chatinviteResponse';
$config->maps['chatkickResponse'] = $config->maps['chatResponsePack'];
$config->maps['chatkickResponse']['name'] = 'chatkickResponse';
$config->maps['chatchangeownershipResponse'] = $config->maps['chatResponsePack'];
$config->maps['chatchangeownershipResponse']['name'] = 'chatchangeownershipResponse';
$config->maps['chatsetvisibilityResponse'] = $config->maps['chatResponsePack'];
$config->maps['chatsetvisibilityResponse']['name'] = 'chatsetvisibilityResponse';
$config->maps['chatsetconfigResponse'] = $config->maps['chatResponsePack'];
$config->maps['chatsetconfigResponse']['name'] = 'chatsetconfigResponse';
$config->maps['chataddadminsResponse'] = $config->maps['chatResponsePack'];
$config->maps['chataddadminsResponse']['name'] = 'chataddadminsResponse';
$config->maps['chatremoveadminsResponse'] = $config->maps['chatResponsePack'];
$config->maps['chatremoveadminsResponse']['name'] = 'chatremoveadminsResponse';
$config->maps['chatsetcommittersResponse'] = $config->maps['chatResponsePack'];
$config->maps['chatsetcommittersResponse']['name'] = 'chatsetcommittersResponse';
$config->maps['chatarchiveResponse'] = $config->maps['chatResponsePack'];
$config->maps['chatarchiveResponse']['name'] = 'chatarchiveResponse';
$config->maps['chatdismissResponse'] = $config->maps['chatResponsePack'];
$config->maps['chatdismissResponse']['name'] = 'chatdismissResponse';
$config->maps['chatsetavatarResponse'] = $config->maps['chatResponsePack'];
$config->maps['chatsetavatarResponse']['name'] = 'chatsetavatarResponse';
$config->maps['chatgetbygidResponse'] = $config->maps['chatResponsePack'];
$config->maps['chatgetbygidResponse']['name'] = 'chatgetbygidResponse';
$config->maps['chatgethistoryResponse'] = $config->maps['messageListResponsePack'];
$config->maps['chatgethistoryResponse']['dataType'][] = array('name' => 'pager', 'type' => $config->maps['pager']['type'], 'dataType' => &$config->maps['pager']['dataType']);
$config->maps['chatgetpubliclistResponse'] = $config->maps['chatListResponsePack'];
$config->maps['chatgetpubliclistResponse']['name'] = 'chatgetpubliclistResponse';
$config->maps['extensiongetlistResponse'] = $config->maps['responsePack'];
$config->maps['extensiongetlistResponse']['dataType'][4] = array('name' => 'data', 'type' => $config->maps['extensionList']['type'], 'dataType' => &$config->maps['extensionList']['dataType']);
$config->maps['entry/visitRequest'] = $config->maps['requestPack'];
$config->maps['entry/visitRequest']['dataType'][4] = array('name' => 'params', 'type' => 'basic');
$config->maps['errormessageResponse'] = $config->maps['messageResponsePack'];
$config->maps['errormessageResponse']['name'] = 'errormessageResponse';
$config->maps['conferenceAction'] = array('type' => 'object', 'name' => 'conferenceAction');
$config->maps['conferenceAction']['dataType'][] = array('name' => 'room', 'type' => 'basic');
$config->maps['conferenceAction']['dataType'][] = array('name' => 'type', 'type' => 'basic', 'options' => array('create','join','close','leave','invite','publish'));
$config->maps['conferenceAction']['dataType'][] = array('name' => 'invitee', 'type' => 'basic');
$config->maps['conferenceAction']['dataType'][] = array('name' => 'participants', 'type' => 'basic');
$config->maps['conferenceAction']['dataType'][] = array('name' => 'date', 'type' => 'basic');
$config->maps['conferenceAction']['dataType'][] = array('name' => 'user', 'type' => 'basic');
$config->maps['conferenceAction']['dataType'][] = array('name' => 'device', 'type' => 'basic');
$config->maps['conferenceAction']['dataType'][] = array('name' => 'data', 'type' => 'basic');
$config->maps['conferenceAction']['dataType'][] = array('name' => 'actions', 'type' => 'list', 'dataType' => &$config->maps['conferenceAction']);
$config->maps['conferenceAction']['dataType'][] = array('name' => 'number', 'type' => 'basic');
$config->maps['conference'] = array('type' => 'object', 'name' => 'conference');
$config->maps['conference']['dataType'][] = array('name' => 'cgid', 'type' => 'basic');
$config->maps['conference']['dataType'][] = array('name' => 'room', 'type' => 'basic');
$config->maps['conference']['dataType'][] = array('name' => 'status', 'type' => 'basic', 'options' => array('closed','open','notStarted'));
$config->maps['conference']['dataType'][] = array('name' => 'openedBy', 'type' => 'basic');
$config->maps['conference']['dataType'][] = array('name' => 'openedDate', 'type' => 'basic');
$config->maps['conference']['dataType'][] = array('name' => 'participants', 'type' => 'basic');
$config->maps['conference']['dataType'][] = array('name' => 'invitee', 'type' => 'basic');
$config->maps['conference']['dataType'][] = array('name' => 'actions', 'type' => 'list', 'dataType' => &$config->maps['conferenceAction']);
$config->maps['conference']['dataType'][] = array('name' => 'topic', 'type' => 'basic');
$config->maps['conference']['dataType'][] = array('name' => 'startTime', 'type' => 'basic');
$config->maps['conference']['dataType'][] = array('name' => 'endTime', 'type' => 'basic');
$config->maps['conference']['dataType'][] = array('name' => 'password', 'type' => 'basic');
$config->maps['conference']['dataType'][] = array('name' => 'type', 'type' => 'basic');
$config->maps['conference']['dataType'][] = array('name' => 'number', 'type' => 'basic');
$config->maps['conference']['dataType'][] = array('name' => 'subscribers', 'type' => 'basic');
$config->maps['conference']['dataType'][] = array('name' => 'note', 'type' => 'basic');
$config->maps['conference']['dataType'][] = array('name' => 'reminderTime', 'type' => 'basic');
$config->maps['conferencecreateResponse'] = $config->maps['responsePack'];
$config->maps['conferencecreateResponse']['dataType'][4] = array('name' => 'data', 'type' => $config->maps['conference']['type'], 'dataType' => &$config->maps['conference']['dataType']);
$config->maps['conferencecreatedetachedResponse'] = $config->maps['responsePack'];
$config->maps['conferencecreatedetachedResponse']['dataType'][4] = array('name' => 'data', 'type' => $config->maps['conference']['type'], 'dataType' => &$config->maps['conference']['dataType']);
$config->maps['conferenceactionResponse'] = $config->maps['responsePack'];
$config->maps['conferenceactionResponse']['dataType'][4] = array('name' => 'data', 'type' => $config->maps['conferenceAction']['type'], 'dataType' => &$config->maps['conferenceAction']['dataType']);
$config->maps['conferenceinviteResponse'] = $config->maps['conferenceactionResponse'];
$config->maps['conferenceinviteResponse']['name'] = 'conferenceinviteResponse';
$config->maps['conferencejoinResponse'] = $config->maps['conferenceactionResponse'];
$config->maps['conferencejoinResponse']['name'] = 'conferencejoinResponse';
$config->maps['conferenceleaveResponse'] = $config->maps['conferenceactionResponse'];
$config->maps['conferenceleaveResponse']['name'] = 'conferenceleaveResponse';
$config->maps['conferencecloseResponse'] = $config->maps['conferenceactionResponse'];
$config->maps['conferencecloseResponse']['name'] = 'conferencecloseResponse';
$config->maps['conferencesyncactionResponse'] = $config->maps['conferenceactionResponse'];
$config->maps['conferencesyncactionResponse']['name'] = 'conferencesyncactionResponse';
$config->maps['syncconferencesResponse'] = $config->maps['responsePack'];
$config->maps['syncconferencesResponse']['dataType'][4] = array('name' => 'data', 'type' => 'list', 'dataType' => &$config->maps['conference']);
$config->maps['conferenceGetByNumberResponse'] = $config->maps['responsePack'];
$config->maps['conferenceGetByNumberResponse']['dataType'][4] = array('name' => 'data', 'type' => 'list', 'dataType' => &$config->maps['conference']);
$config->maps['conferenceGetByConditionResponse'] = $config->maps['responsePack'];
$config->maps['conferenceGetByConditionResponse']['dataType'][4] = array('name' => 'data', 'type' => 'list', 'dataType' => &$config->maps['conference']);
$config->maps['conferenceGetByConditionResponse']['dataType'][] = array('name' => 'pager', 'type' => $config->maps['pager']['type'], 'dataType' => &$config->maps['pager']['dataType']);
$config->maps['usersubscribeRequest'] = array('type' => 'object', 'name' => 'usersubscribeRequest');
$config->maps['usersubscribeRequest']['dataType'][] = array('name' => 'rid', 'type' => 'basic');
$config->maps['usersubscribeRequest']['dataType'][] = array('name' => 'type', 'type' => 'basic');
$config->maps['usersubscribeRequest']['dataType'][] = array('name' => 'objects', 'type' => 'basic');
$config->maps['usersubscribeRequest']['dataType'][] = array('name' => 'userID', 'type' => 'basic');

0
config/ext/index.html Executable file
View File

85
config/filter.php Executable file
View File

@ -0,0 +1,85 @@
<?php
$filter = new stdclass();
$filter->rules = new stdclass();
$filter->default = new stdclass();
$filter->block = new stdclass();
$filter->entry = new stdclass();
$filter->file = new stdclass();
$filter->sso = new stdclass();
$filter->upgrade = new stdclass();
$filter->user = new stdclass();
$filter->rules->any = '/./';
$filter->rules->base64 = '/^[a-zA-Z0-9\+\/\=]+$/';
$filter->rules->browseType = '/^by[a-z]+$/';
$filter->rules->callback = '/^[a-zA-Z0-9=\&\%\.\/\-\:\?]+$/';
$filter->rules->character = '/^[a-zA-Z_\-]+$/';
$filter->rules->checked = '/^[0-9,]+$/';
$filter->rules->common = '/^[a-zA-Z0-9_]+$/';
$filter->rules->idList = '/^[0-9\|]+$/';
$filter->rules->key = '/^[a-z0-9]{32}+$/';
$filter->rules->lang = '/^[a-zA-Z_\-]+$/';
$filter->rules->md5 = '/^[a-z0-9]{32}$/';
$filter->rules->number = '/^[0-9]+$/';
$filter->rules->orderBy = '/^\w+_(desc|asc)$/i';
$filter->rules->paramName = '/^[a-zA-Z0-9_\.]+$/';
$filter->rules->paramValue = '/^[a-zA-Z0-9=_,:\-\?\&`#+\^\/\.%\|\x7f-\xff]+$/';
$filter->rules->path = '/(^//.|^/|^[a-zA-Z])?:?/.+(/$)?/';
$filter->rules->word = '/^\w+$/';
$filter->default->moduleName = 'code';
$filter->default->methodName = 'code';
$filter->default->paramName = 'reg::paramName';
$filter->default->paramValue = 'reg::paramValue';
$filter->default->get['onlybody'] = 'equal::yes';
$filter->default->get['lang'] = 'reg::lang';
$filter->default->get['HTTP_X_REQUESTED_WITH'] = 'equal::XMLHttpRequest';
$filter->default->cookie['lang'] = 'reg::lang';
$filter->default->cookie['theme'] = 'reg::common';
$filter->default->cookie['device'] = 'reg::common';
$filter->default->cookie['ra'] = 'reg::common';
$filter->default->cookie['rp'] = 'reg::common';
$filter->default->cookie['keepLogin'] = 'equal::on';
$filter->block->default = new stdclass();
$filter->block->default->get['mode'] = 'reg::character';
$filter->block->default->get['blockid'] = 'reg::character';
$filter->block->default->get['hash'] = 'reg::md5';
$filter->block->default->get['sso'] = 'reg::word';
$filter->block->default->get['app'] = 'reg::character';
$filter->block->default->get['param'] = 'reg::base64';
$filter->entry->depts = new stdclass();
$filter->entry->users = new stdclass();
$filter->entry->visit = new stdclass();
$filter->entry->depts->get['key'] = 'reg::key';
$filter->entry->users->get['key'] = 'reg::key';
$filter->entry->visit->get['referer'] = 'reg::base64';
$filter->file->ajaxueditorupload = new stdclass();
$filter->file->filemanager = new stdclass();
$filter->file->download = new stdclass();
$filter->file->ajaxueditorupload->get['action'] = 'equal::config';
$filter->file->filemanager->get['path'] = 'reg::path';
$filter->file->filemanager->get['order'] = 'reg::common';
$filter->file->download->cookie[$config->sessionVar] = 'reg::common';
$filter->sso->check = new stdclass();
$filter->sso->leaveusers = new stdclass();
$filter->sso->check->get['callback'] = 'reg::callback';
$filter->sso->check->get['referer'] = 'reg::base64';
$filter->sso->check->get['token'] = 'reg::key';
$filter->sso->check->get['auth'] = 'reg::key';
$filter->sso->check->get['userIP'] = 'ip';
$filter->sso->leaveusers->get['code'] = 'code';
$filter->sso->leaveusers->get['key'] = 'reg::key';
$filter->upgrade->upgradelicense = new stdclass();
$filter->upgrade->upgradelicense->get['agree'] = 'equal::true';
$filter->user->admin = new stdclass();
$filter->user->login = new stdclass();
$filter->user->admin->paramValue['query'] = 'reg::any';
$filter->user->login->get['lang'] = 'reg::lang';

0
config/index.html Executable file
View File

52
config/license/callback.php Executable file
View File

@ -0,0 +1,52 @@
<?php
function ioncube_event_handler($errCode, $params)
{
$company = "%company%";
$expireDate = "%expiredate%";
$ip = "%ip%";
$mac = "%mac%";
$users = "%users%";
$email = "%email%";
$mobile = "%mobile%";
$qq = "%qq%";
$version = "%version%";
if(empty($email) or strpos($email, '%email') === 0) $email = 'co@zentao.net';
if(empty($mobile) or strpos($mobile, '%mobile') === 0) $mobile = '4006 889923';
if(empty($qq) or strpos($qq, '%qq') === 0) $qq = 'co@zentao.net(1492153927)';
$errType = '';
if($errCode == ION_LICENSE_EXPIRED)
{
$errType = 'expired';
}
elseif($errCode == ION_LICENSE_SERVER_INVALID)
{
$errType = 'serverInvalid';
}
elseif($errCode == ION_LICENSE_NOT_FOUND)
{
$errType = 'notFound';
}
elseif($errCode == ION_LICENSE_CORRUPT)
{
$errType = 'corrupt';
}
$licenseData = new stdClass();
$licenseData->errCode = $errCode;
$licenseData->errType = $errType;
$licenseData->company = $company;
$licenseData->expireDate = $expireDate;
$licenseData->ip = $ip;
$licenseData->mac = $mac;
$licenseData->users = $users;
$licenseData->mobile = $mobile;
$licenseData->email = $email;
$licenseData->qq = $qq;
$licenseData->version = $version;
$licenseData->params = $params;
include '../www/license.php';
exit;
}

0
config/license/index.html Executable file
View File

53
config/license/xuancallback.php Executable file
View File

@ -0,0 +1,53 @@
<?php
function ioncube_event_handler($errCode, $params)
{
$company = "try";
$expireDate = "2024-01-11";
$ip = "";
$mac = "";
$users = "20";
$email = "%email%";
$mobile = "%mobile%";
$qq = "%qq%";
$version = "%version%";
if(empty($email) or strpos($email, '%email') === 0) $email = 'co@zentao.net';
if(empty($mobile) or strpos($mobile, '%mobile') === 0) $mobile = '4006 889923';
if(empty($qq) or strpos($qq, '%qq') === 0) $qq = 'co@zentao.net(1492153927)';
$errType = '';
if($errCode == ION_LICENSE_EXPIRED)
{
$errType = 'expired';
}
elseif($errCode == ION_LICENSE_SERVER_INVALID)
{
$errType = 'serverInvalid';
}
elseif($errCode == ION_LICENSE_NOT_FOUND)
{
$errType = 'notFound';
}
elseif($errCode == ION_LICENSE_CORRUPT)
{
$errType = 'corrupt';
}
$licenseData = new stdClass();
$licenseData->errCode = $errCode;
$licenseData->errType = $errType;
$licenseData->company = $company;
$licenseData->expireDate = $expireDate;
$licenseData->ip = $ip;
$licenseData->mac = $mac;
$licenseData->users = $users;
$licenseData->mobile = $mobile;
$licenseData->email = $email;
$licenseData->qq = $qq;
$licenseData->version = $version;
$licenseData->params = $params;
include dirname(dirname(dirname(__FILE__))) . '/www/license.php';
exit;
}

20
config/license/xxb.php Executable file
View File

@ -0,0 +1,20 @@
<?php die(''); ?>
------ LICENSE FILE DATA -------
345VU301aUrT3tBRlugg7rCijFUhK3ky
yuwt2PAkrw5WTN2SagbBJZ6glZSVZLe+
QO0GeudOwxqbSclY7YFxLViARVto7sQl
ESkrbQg+DxC97FWUKxjI/BBsJPo6IFtA
YPOadkJXTfHy1urXKzG6MMAy6KmCGV7i
kjnjiiOIn/qGrhe8LdV7jBoM47HeE91a
JAosU8PEU6vmWbSEwC7P5z+eXufUSi+g
3wrbn2NX/5kj+nnD53EQvFYs+MrVKXSU
u0gXomFJMCHJnY60aHGiDNYh7gl4ayFe
z8YJPXiRdIQM5rbhS8XYAUkjdXlWYTbi
y4cK3lmoOIsZKME40IyeNfojc/QW5b7G
OfxT7cmQ0O6kP4Awso2uZuZNdLVeU3gl
3x7UeG5BbtTnBv2jA0umAh+VQEZAVRX2
gCj8uy+tQAnPI5iKBLLn7wuRWcqhdgE5
/Tlvy6S0BoD0XoEPoaZFC8yVy206YLf=
--------------------------------

70
config/rights.php Executable file
View File

@ -0,0 +1,70 @@
<?php
/**
* The config items for rights.
*
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd., www.zentao.net)
* @license ZOSL (https://zpl.pub/page/zoslv1.html)
* @author Tingting Dai <daitingting@xirangit.com>
* @package config
* @version $Id$
* @link https://xuanim.com
*/
/* Init the rights. */
$config->rights = new stdclass();
$config->rights->guest = array();
$config->rights->member['index']['index'] = 'index';
$config->rights->member['entry']['visit'] = 'visit';
$config->rights->member['entry']['blocks'] = 'blocks';
$config->rights->member['entry']['setblock'] = 'setblock';
$config->rights->member['entry']['printblock'] = 'printblock';
$config->rights->member['entry']['customsort'] = 'customsort';
$config->rights->member['entry']['updateentrymenu'] = 'updateentrymenu';
$config->rights->member['user']['profile'] = 'profile';
$config->rights->member['user']['thread'] = 'thread';
$config->rights->member['user']['reply'] = 'reply';
$config->rights->member['user']['message'] = 'message';
$config->rights->member['user']['setreferer'] = 'setreferer';
$config->rights->member['user']['changepassword'] = 'changepassword';
$config->rights->member['user']['vcard'] = 'vcard';
$config->rights->member['user']['uploadavatar'] = 'uploadavatar';
$config->rights->member['file']['uploadchatavatar'] = 'uploadchatavatar';
$config->rights->member['user']['cropavatar'] = 'cropavatar';
$config->rights->member['user']['changeavatar'] = 'changeavatar';
$config->rights->member['user']['editself'] = 'editself';
$config->rights->member['search']['buildform'] = 'buildform';
$config->rights->member['search']['buildquery'] = 'buildquery';
$config->rights->member['search']['savequery'] = 'savequery';
$config->rights->member['search']['deletequery'] = 'deletequery';
$config->rights->member['misc']['qrcode'] = 'qrcode';
$config->rights->member['misc']['about'] = 'about';
$config->rights->member['tree']['redirect'] = 'redirect';
$config->rights->member['action']['createrecord'] = 'createrecord';
$config->rights->member['action']['editrecord'] = 'editrecord';
$config->rights->member['action']['history'] = 'history';
$config->rights->member['action']['editcomment'] = 'editcomment';
$config->rights->member['action']['read'] = 'read';
$config->rights->member['file']['buildform'] = 'buildform';
$config->rights->member['file']['buildlist'] = 'buildlist';
$config->rights->member['file']['printfiles'] = 'printfiles';
$config->rights->member['file']['ajaxupload'] = 'ajaxupload';
$config->rights->member['file']['browse'] = 'browse';
$config->rights->member['file']['senddownheader'] = 'senddownheader';
$config->rights->member['file']['ajaxpasteimage'] = 'ajaxpasteimage';
$config->rights->member['file']['filemanager'] = 'filemanager';
$config->rights->member['file']['sort'] = 'sort';
$config->rights->member['client']['downloadclient'] = 'downloadclient';
$config->rights->member['client']['ajaxgetclientpackage'] = 'ajaxgetclientpackage';
$config->rights->member['client']['ajaxgetpackagesize'] = 'ajaxgetpackagesize';
$config->rights->member['client']['ajaxsetclientconfig'] = 'ajaxsetclientconfig';
$config->rights->member['device']['browse'] = 'browse';
$config->rights->member['device']['remove'] = 'remove';

57
config/xxb.php Executable file
View File

@ -0,0 +1,57 @@
<?php
/**
* The config file of XXB.
*
* Don't modify this file directly, copy the item to my.php and change it.
*
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd., www.zentao.net)
* @license ZOSL (https://zpl.pub/page/zoslv1.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package config
* @version $Id: config.php 4211 2017-06-20 14:30:10Z pengjx $
* @link https://xuanim.com
*/
$config->product = 'xxb';
$config->version = '7.2.1'; // 喧喧的版本。 The version of XXB. Don't change it.
$config->buildDate = "build at Sun Jul 9 00:49:31 PDT 2023";
/* 基本设置。Rangerteam basic settings. */
$config->sessionVar = 'xid'; // 请求类型为GETsession变量名。 requestType=GET: the session var name.
$config->cookiePath = '/'; // cookies路径分隔符。 The path of cookies.
$config->checkVersion = true; // 是否自动检测新版本。 Auto check for new version or not.
$config->timeout = 30 * 1000; // ajax请求超时时间单位毫秒。 The timeout of ajax request.
$config->pingInterval = 60; // 心跳请求发送间隔,单位秒。 The interval of ping request, seconds.
$config->customerLimit = 50; // 页面加载时载入客户的最大数量。 The maximum number of customers that are loaded when the page loads.
$config->searchLimit = 50; // 使用ajax搜索客户时页面显示的最大条目数量。The maximum number of customers displays in search customer page.
/* Supported charsets. */
$config->charsets['zh-cn']['utf-8'] = 'UTF-8';
$config->charsets['zh-cn']['gbk'] = 'GBK';
$config->charsets['zh-tw']['utf-8'] = 'UTF-8';
$config->charsets['zh-tw']['big5'] = 'BIG5';
$config->charsets['en']['utf-8'] = 'UTF-8';
/* IP white list settings.*/
$config->ipWhiteList = '*';
$config->allowedTags = '<p><span><h1><h2><h3><h4><h5><em><u><strong><br><ol><ul><li><img><a><b><font><hr><pre><div><table><td><th><tr><tbody><embed><style>';
/* Tables for basic system. */
if(!defined('TABLE_ACTION')) define('TABLE_ACTION', '`' . $config->db->prefix . 'action`');
if(!defined('TABLE_BLOCK')) define('TABLE_BLOCK', '`' . $config->db->prefix . 'block`');
if(!defined('TABLE_CATEGORY')) define('TABLE_CATEGORY', '`' . $config->db->prefix . 'category`');
if(!defined('TABLE_CONFIG')) define('TABLE_CONFIG', '`' . $config->db->prefix . 'config`');
if(!defined('TABLE_CRON')) define('TABLE_CRON', '`' . $config->db->prefix . 'cron`');
if(!defined('TABLE_ENTRY')) define('TABLE_ENTRY', '`' . $config->db->prefix . 'entry`');
if(!defined('TABLE_FILE')) define('TABLE_FILE', '`' . $config->db->prefix . 'file`');
if(!defined('TABLE_GROUP')) define('TABLE_GROUP', '`' . $config->db->prefix . 'group`');
if(!defined('TABLE_GROUPPRIV')) define('TABLE_GROUPPRIV', '`' . $config->db->prefix . 'grouppriv`');
if(!defined('TABLE_HISTORY')) define('TABLE_HISTORY', '`' . $config->db->prefix . 'history`');
if(!defined('TABLE_LANG')) define('TABLE_LANG', '`' . $config->db->prefix . 'lang`');
if(!defined('TABLE_SSO')) define('TABLE_SSO', '`' . $config->db->prefix . 'sso`');
if(!defined('TABLE_USER')) define('TABLE_USER', '`' . $config->db->prefix . 'user`');
if(!defined('TABLE_USERGROUP')) define('TABLE_USERGROUP', '`' . $config->db->prefix . 'usergroup`');
if(!defined('TABLE_USERQUERY')) define('TABLE_USERQUERY', '`' . $config->db->prefix . 'userquery`');
/* The mapping list of object and tables. */
$config->objectTables['cron'] = TABLE_CRON;
$config->objectTables['user'] = TABLE_USER;

130
db/demo.zh-cn.sql Normal file
View File

@ -0,0 +1,130 @@
INSERT INTO `xxb_category` (`id`, `name`, `alias`, `desc`, `keywords`, `root`, `parent`, `path`, `grade`, `order`, `type`, `readonly`, `moderators`, `threads`, `posts`, `postedBy`, `postedDate`, `postID`, `replyID`, `users`, `rights`, `refund`, `major`, `deleted`) VALUES
(1, '研发', '', '', '', 0, 0, ',1,', 1, 10, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:27:56', 0, 0, '', '', '0', '0', '0'),
(2, '行政', '', '', '', 0, 0, ',2,', 1, 20, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:27:56', 0, 0, '', '', '0', '0', '0'),
(3, '市场', '', '', '', 0, 0, ',3,', 1, 30, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:27:56', 0, 0, '', '', '0', '0', '0'),
(4, '财务', '', '', '', 0, 0, ',4,', 1, 40, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:27:56', 0, 0, '', '', '0', '0', '0'),
(5, '技术支持', '', '', '', 0, 0, ',5,', 1, 50, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:27:56', 0, 0, '', '', '0', '0', '0'),
(6, '禅道开发', '', '', '', 0, 1, ',1,6,', 2, 20, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:28:31', 0, 0, '', '', '0', '0', '0'),
(7, '蝉知开发', '', '', '', 0, 1, ',1,7,', 2, 30, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:28:31', 0, 0, '', '', '0', '0', '0'),
(8, '然之开发', '', '', '', 0, 1, ',1,8,', 2, 40, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:28:31', 0, 0, '', '', '0', '0', '0'),
(19, '国内市场部', '', '', '', 0, 3, ',3,19,', 2, 10, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:44:21', 0, 0, '', '', '0', '0', '0'),
(9, '喧喧开发', '', '', '', 0, 1, ',1,9,', 2, 10, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:28:31', 0, 0, '', '', '0', '0', '0'),
(10, '云禅道项目组', '', '', '', 0, 6, ',1,6,10,', 3, 10, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:30:20', 0, 0, '', '', '0', '0', '1'),
(11, '云禅道项目组', '', '', '', 0, 6, ',1,6,11,', 3, 10, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:30:20', 0, 0, '', '', '0', '0', '0'),
(12, '专业版项目组', '', '', '', 0, 6, ',1,6,12,', 3, 20, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:30:20', 0, 0, '', '', '0', '0', '0'),
(13, '企业版项目组', '', '', '', 0, 6, ',1,6,13,', 3, 30, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:30:20', 0, 0, '', '', '0', '0', '0'),
(14, '集群版项目组', '', '', '', 0, 6, ',1,6,14,', 3, 40, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:30:20', 0, 0, '', '', '0', '0', '1'),
(15, '产品设计组', '', '', '', 0, 9, ',1,9,15,', 3, 10, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:35:25', 0, 0, '', '', '0', '0', '0'),
(16, 'UI设计组', '', '', '', 0, 9, ',1,9,16,', 3, 20, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:35:25', 0, 0, '', '', '0', '0', '0'),
(17, '研发组', '', '', '', 0, 9, ',1,9,17,', 3, 30, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:35:25', 0, 0, '', '', '0', '0', '0'),
(18, '测试组', '', '', '', 0, 9, ',1,9,18,', 3, 40, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:35:25', 0, 0, '', '', '0', '0', '0'),
(20, '国际市场部', '', '', '', 0, 3, ',3,20,', 2, 20, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:44:21', 0, 0, '', '', '0', '0', '0'),
(21, '售前技术支持', '', '', '', 0, 5, ',5,21,', 2, 10, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:44:39', 0, 0, '', '', '0', '0', '0'),
(22, '售后技术支持', '', '', '', 0, 5, ',5,22,', 2, 20, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:44:39', 0, 0, '', '', '0', '0', '0');
INSERT INTO `xxb_im_chat` (`id`, `gid`, `name`, `type`, `admins`, `committers`, `subject`, `public`, `createdBy`, `createdDate`, `ownedBy`, `editedBy`, `editedDate`, `lastActiveTime`, `dismissDate`, `lastMessageIndex`, `lastMessage`) VALUES
(1, '58113bb5-6a66-e94f-eb12-fb94271f6f7c', '系统', 'system', '', '', 0, '0', 'system', '2019-08-08 17:10:52', '', '', '0000-00-00 00:00:00', '2019-08-09 09:31:46', '0000-00-00 00:00:00', 9, 22),
(2, '3b320201-52e1-4061-90b2-23e750e8b6e0', '禅道研发组', 'group', '', '', 0, '0', 'sxm', '2019-08-09 09:06:26', 'sxm', '', '0000-00-00 00:00:00', '2019-08-09 09:06:26', '0000-00-00 00:00:00', 1, 1),
(3, 'c8e328cb-399f-4999-8524-32bdc6cc4629', '研发部', 'group', '', '', 0, '0', 'lsx', '2019-08-09 09:09:29', 'lsx', '', '0000-00-00 00:00:00', '2019-08-09 09:22:00', '0000-00-00 00:00:00', 6, 18),
(4, '326bb771-3f23-4ecb-a907-b3b223575d37', '喧喧开发组', 'group', '', '', 0, '0', 'lijuan', '2019-08-09 09:20:46', 'lijuan', '', '0000-00-00 00:00:00', '2019-08-09 09:45:58', '0000-00-00 00:00:00', 18, 48),
(5, '16&8', '', 'one2one', '', '', 0, '0', 'lsx', '2019-08-09 09:32:33', '', '', '0000-00-00 00:00:00', '2019-08-09 09:33:50', '0000-00-00 00:00:00', 4, 26),
(6, '2&5', '', 'one2one', '', '', 0, '0', 'lijuan', '2019-08-09 09:37:55', '', '', '0000-00-00 00:00:00', '2019-08-09 09:40:50', '0000-00-00 00:00:00', 7, 33),
(7, '4&5', '', 'one2one', '', '', 0, '0', 'lhj', '2019-08-09 09:43:29', '', '', '0000-00-00 00:00:00', '2019-08-09 09:43:45', '0000-00-00 00:00:00', 3, 39);
INSERT INTO `xxb_im_chatuser` (`id`, `cgid`, `user`, `order`, `star`, `hide`, `mute`, `freeze`, `join`, `quit`, `category`) VALUES
(1, '3b320201-52e1-4061-90b2-23e750e8b6e0', 17, 1, '0', '0', '0', '0', '2019-08-09 09:06:26', '0000-00-00 00:00:00', ''),
(2, '3b320201-52e1-4061-90b2-23e750e8b6e0', 18, 2, '0', '0', '0', '0', '2019-08-09 09:06:26', '0000-00-00 00:00:00', ''),
(3, '3b320201-52e1-4061-90b2-23e750e8b6e0', 19, 3, '0', '0', '0', '0', '2019-08-09 09:06:26', '0000-00-00 00:00:00', ''),
(4, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 17, 4, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(5, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 18, 5, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(6, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 19, 6, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(7, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 15, 7, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(8, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 14, 8, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(9, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 2, 9, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(10, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 3, 10, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(11, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 4, 11, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(12, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 7, 12, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(13, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 5, 13, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(14, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 16, 14, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(15, '326bb771-3f23-4ecb-a907-b3b223575d37', 2, 15, '0', '0', '0', '0', '2019-08-09 09:20:46', '0000-00-00 00:00:00', ''),
(16, '326bb771-3f23-4ecb-a907-b3b223575d37', 3, 16, '0', '0', '0', '0', '2019-08-09 09:20:46', '0000-00-00 00:00:00', ''),
(17, '326bb771-3f23-4ecb-a907-b3b223575d37', 4, 17, '0', '0', '0', '0', '2019-08-09 09:20:46', '0000-00-00 00:00:00', ''),
(18, '326bb771-3f23-4ecb-a907-b3b223575d37', 7, 18, '0', '0', '0', '0', '2019-08-09 09:20:46', '0000-00-00 00:00:00', ''),
(19, '326bb771-3f23-4ecb-a907-b3b223575d37', 5, 19, '0', '0', '0', '0', '2019-08-09 09:20:46', '0000-00-00 00:00:00', ''),
(20, '16&8', 16, 20, '0', '0', '0', '0', '2019-08-09 09:32:33', '0000-00-00 00:00:00', ''),
(21, '16&8', 8, 21, '0', '0', '0', '0', '2019-08-09 09:32:33', '0000-00-00 00:00:00', ''),
(22, '2&5', 2, 22, '0', '0', '0', '0', '2019-08-09 09:37:55', '0000-00-00 00:00:00', ''),
(23, '2&5', 5, 23, '0', '0', '0', '0', '2019-08-09 09:37:55', '0000-00-00 00:00:00', ''),
(24, '4&5', 4, 24, '0', '0', '0', '0', '2019-08-09 09:43:29', '0000-00-00 00:00:00', ''),
(25, '4&5', 5, 25, '0', '0', '0', '0', '2019-08-09 09:43:29', '0000-00-00 00:00:00', '');
INSERT INTO `xxb_im_message` (`id`, `gid`, `cgid`, `user`, `date`, `index`, `type`, `content`, `contentType`, `data`, `deleted`) VALUES
(1, '5c7276f5-fff5-bf63-f8e5-282b38a80004', '3b320201-52e1-4061-90b2-23e750e8b6e0', '19', '2019-08-09 09:06:26', 1, 'broadcast', '@sxm 创建了讨论组 **[禅道研发组](#/chats/groups/3b320201-52e1-4061-90b2-23e750e8b6e0)**。', 'text', '', '0'),
(2, '7110e4cc-4db1-3dd4-32df-1c59cb475bd4', 'c8e328cb-399f-4999-8524-32bdc6cc4629', '16', '2019-08-09 09:09:29', 1, 'broadcast', '@lsx 创建了讨论组 **[研发部](#/chats/groups/c8e328cb-399f-4999-8524-32bdc6cc4629)**。', 'text', '', '0'),
(3, 'a3f763d8-c40d-4c7c-a323-9ce4e78a60b3', '58113bb5-6a66-e94f-eb12-fb94271f6f7c', '8', '2019-08-09 09:11:06', 1, 'normal', '本月考勤的统计已结束,公布在内网,有异议的同学请小窗我。', 'plain', '', '0'),
(4, '1f47920d-520f-4c22-8b14-2382b90419f6', '58113bb5-6a66-e94f-eb12-fb94271f6f7c', '2', '2019-08-09 09:12:51', 2, 'normal', '已查看,我的没有问题。', 'plain', '', '0'),
(5, 'ba27fac1-9ac4-4567-a171-badfa078e4b7', '58113bb5-6a66-e94f-eb12-fb94271f6f7c', '16', '2019-08-09 09:13:21', 3, 'normal', '我的请假是休年假,需要改一下,看小窗。', 'plain', '', '0'),
(6, '909ca70c-dfe0-4b27-ad3b-d53192f11c2b', '58113bb5-6a66-e94f-eb12-fb94271f6f7c', '5', '2019-08-09 09:14:02', 4, 'normal', '我的考勤统计,没问题。', 'plain', '', '0'),
(7, '70c1264b-5115-47c6-b8f5-18f337ae665b', '58113bb5-6a66-e94f-eb12-fb94271f6f7c', '19', '2019-08-09 09:14:19', 5, 'normal', '全勤的路过~', 'plain', '', '0'),
(8, 'ba1b7bf1-5e50-4eba-8e5b-8284caf4c3d3', '58113bb5-6a66-e94f-eb12-fb94271f6f7c', '8', '2019-08-09 09:15:04', 6, 'normal', '@刘双喜,好的,已修改过来了。', 'plain', '', '0'),
(9, 'dd1cc560-f3e4-4fbe-9f66-f92a17132b9d', 'c8e328cb-399f-4999-8524-32bdc6cc4629', '16', '2019-08-09 09:17:07', 2, 'normal', '周五下午17点例会各开发组提前准备好工作周报。\n列好本周工作内容和下周工作计划。把本周工作遇到的问题也列一下把问题抛出来看大家有什么好的解决办法。\n', 'plain', '', '0'),
(10, 'aa691502-52a6-4ef1-bade-3300760e2ba0', 'c8e328cb-399f-4999-8524-32bdc6cc4629', '2', '2019-08-09 09:17:51', 3, 'normal', '好的,收到。', 'plain', '', '0'),
(11, 'e7309457-7834-4507-bd2b-072724aade2b', 'c8e328cb-399f-4999-8524-32bdc6cc4629', '2', '2019-08-09 09:18:16', 4, 'normal', '整理完工作周报需要发送给你吗?@刘双喜', 'plain', '', '0'),
(12, '1f09839f-6fc0-439c-85ad-069144e62301', '58113bb5-6a66-e94f-eb12-fb94271f6f7c', '2', '2019-08-09 09:18:38', 7, 'normal', '{\"type\":\"emoji\",\"content\":\":handshake:\"}', 'image', '', '1'),
(13, 'c39e48bd-b2d2-4744-b55a-9bad3a6da885', '58113bb5-6a66-e94f-eb12-fb94271f6f7c', '16', '2019-08-09 09:19:02', 8, 'normal', '{\"type\":\"emoji\",\"content\":\":handshake:\"}', 'image', '', '0'),
(14, 'b5610e39-dadf-4c98-9b36-3fde9877d347', 'c8e328cb-399f-4999-8524-32bdc6cc4629', '5', '2019-08-09 09:19:56', 5, 'normal', '喧喧开发的同学们,记得把工作周报都写好,发我汇总一下。', 'plain', '', '0'),
(15, '42225687-f5ce-88ea-c770-eec2a65b7bcd', '326bb771-3f23-4ecb-a907-b3b223575d37', '5', '2019-08-09 09:20:46', 1, 'broadcast', '@lijuan 创建了讨论组 **[喧喧开发组](#/chats/groups/326bb771-3f23-4ecb-a907-b3b223575d37)**。', 'text', '', '0'),
(16, '9f090a5c-126f-4013-bfcd-f6698447bcc7', '326bb771-3f23-4ecb-a907-b3b223575d37', '2', '2019-08-09 09:21:22', 2, 'normal', '本周的工作周报,需要大家都写一下,按要求写完,然后发送我汇总。', 'plain', '', '0'),
(17, '41b43b61-94a8-46af-a834-a2fe393cf261', '326bb771-3f23-4ecb-a907-b3b223575d37', '2', '2019-08-09 09:21:38', 3, 'normal', '今天15点前别忘记了。', 'plain', '', '0'),
(18, '2c83f1aa-be62-4724-bf5f-c15091a6d2c6', 'c8e328cb-399f-4999-8524-32bdc6cc4629', '19', '2019-08-09 09:22:00', 6, 'normal', '收到~', 'plain', '', '0'),
(19, '92a7af02-5f5a-4791-9f67-8e2b7de86dad', '326bb771-3f23-4ecb-a907-b3b223575d37', '5', '2019-08-09 09:26:17', 4, 'normal', '{\"name\":\"clipboard-image-16475982.png\",\"size\":1028,\"send\":true,\"type\":\"base64\",\"time\":1565313978413,\"content\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACkAAAAYCAYAAABnRtT+AAADy0lEQVRYCb2Xy08bRxzHP7teB2NvgGKb9YMEjKCpgwSHopx6xDR93Hto+etoD703EXVSJekxUg64at0qAvO0cf2IIF7Hj31Uu8vagKC1YdWRVrM7v9f3952Z38wKpmmaeNQsRwfFCltvJxAFkQ/NGjMzU8Qi4JNAvGEkySN8tpsuUCybYIpousHDuSZTU00kOk4Y4WbRxJuZXW+lqqotbLfbhMOT1ysOIfGUSSuuYVh5ixg6jPgMcFkcAtRlVc+ZvBzAi2/ph+9/5KhUdnwJVuYDNNPJLRlX+Pa7bwYwcFQMRDY2Nnj06SPS6TQI2tW2pkQ+n+f1m9esr68jlUolvvzqayLhCAwBslqrsvnkp6uD/MvoysoK2Z+ztkb64cKVmhbAbDbL6uertlwyBIhEx4hFJ640uHZQ7GDZDtNEDBbTDxBN0QZh2V5g9IxBC+Da2hrptJWEgecbZxDQNjDoAz1j1GXQAZgGnOUwGEgN9v6s2PFnPoly69QEDXeqLdbcGXnuMmiD7q/XgUBWD1RarRaartGsRQkqg/D13zouo5tZZ40+tqe4z6Dr4WIJasO7/S5GC7COMB0aFY3jSpG5j++Rmk1R2C2gNcGvBVwfA/dW7bDrhymB9VxqgikhGBJSV7YfV3xBc+9tjUajQb3hIzU3jd6B3UKB2VQKfwj8QZArMvt7B4xPjLs+huqbTZXn2ReUiiUmw5PUa3V7k1hOXv7yEr/kp3XaIiTLKLPjjI6OOqvL3xmjevgBtVtnYXGe4o7K/l8N2t13xKIJ5Gg/l9jCGAe7TYxBy9W5FERTsgGagsHaF2vktn7no3CERXsXw7gehS7EFxTKx2XKhffMzyv0prtYKpKaS3FHFpidk23XgUCAyL3QuTAwMjLC/IOZC2PDfFgMLi0tk0qlWFpeplav98ytWVQUhbvyXZSYgqo2bJlkXZ9KJ4dM3Y9w0j7lxNnEBOKW3MfxOSc9b6ZItV4d+uplCBqxZJRc7jf7fM/ltkgk+rtQlgOUy0coJKmXVYJjEqavhRSPx3n65KkTf9Ap7B2LdiY97IO8ZDIZnj17webmJolEnMxqpmeWnE5ydHjE9vY2siwzPZ20ZYKXl17r1vjq1z1axn3Uhsrjz/q1rofkBi+9NXkD2//NxHOQouhUQ9EHbV1E486tk/EcZCjkVAOrCtRq/Z17G6T9AngbL2e2fiChCFRODSRJ5I+dIKoeJBYJ3upHzNON4/4MvnoD7xtdfEIHXdcwOiV0wxi6ZLm8eQrSddpoQz6/w98nUXvIMJ3DwZUP2/8DMfFqbQG4d1sAAAAASUVORK5CYII=\",\"isImage\":false}', 'image', '', '0'),
(20, '3b29578e-4649-476b-bf55-590fc4472841', '326bb771-3f23-4ecb-a907-b3b223575d37', '5', '2019-08-09 09:26:45', 5, 'normal', '喧喧编辑器的图标间距确定了么?', 'plain', '', '0'),
(21, '0d29d0f0-2751-4056-8316-e8bd629d8324', '326bb771-3f23-4ecb-a907-b3b223575d37', '5', '2019-08-09 09:27:08', 6, 'normal', '图标是不是也确定下来,接下来不坐更改了?', 'plain', '', '0'),
(22, '7b2002c7-04ff-4a38-88ce-42f0eaec04c2', '58113bb5-6a66-e94f-eb12-fb94271f6f7c', '8', '2019-08-09 09:31:46', 9,'normal', '备注本月统计的是上月的考勤大家有疑问的如果是8月的先不用着急小窗我。', 'plain', '', '0'),
(23, 'f545a250-49bb-4b4e-8828-dd3fec1a5aee', '16&8', '16', '2019-08-09 09:32:33', 1, 'normal', '我7月31日的请假不算事假休的是年假。\n请帮忙修改过来谢谢~', 'plain', '', '0'),
(24, '1ef9d150-a096-4b38-88c2-bc7efc96548b', '16&8', '8', '2019-08-09 09:33:23', 2, 'normal', '好的你的年假还剩2天7月31日使用1天那么你2019年的年假还剩1天。', 'plain', '', '0'),
(25, 'f903d42e-6244-4ed4-bf17-fa806097a1cd', '16&8', '8', '2019-08-09 09:33:26', 3, 'normal', '确认一下。', 'plain', '', '0'),
(26, 'eea18ec9-8231-45ff-8a49-ff3990b19c95', '16&8', '16', '2019-08-09 09:33:50', 4, 'normal', '嗯,已确认,没有问题。', 'plain', '', '0'),
(27, 'eb4dad55-0e15-4983-b6e8-6b41117696c2', '2&5', '5', '2019-08-09 09:37:55', 1, 'normal', '启动喧喧时,登录窗口默认最小尺寸显示会比较好。', 'plain', '', '0'),
(28, 'f8326459-e8a8-4af1-b54c-82d70f76ec12', '2&5', '5', '2019-08-09 09:38:39', 2, 'normal', '目前是间于最小尺寸和最大尺寸显示的大小,用户登录时,尤其是小屏幕,', 'plain', '', '0'),
(29, 'f20a985e-493f-482a-9200-c6fa26a73da6', '2&5', '5', '2019-08-09 09:38:48', 3, 'normal', '用户体验不大好。', 'plain', '', '0'),
(30, 'd64761da-b5cb-443b-9879-a72cc5bb36e5', '2&5', '5', '2019-08-09 09:38:59', 4, 'normal', '希望确定下来。', 'plain', '', '0'),
(31, 'dcb5c788-d160-4566-8fb7-2fff9c8d1d3b', '2&5', '2', '2019-08-09 09:39:45', 5, 'normal', '设计时,启动时窗口显示的大小就是默认显示为最小尺寸的。', 'plain', '', '0'),
(32, 'dc205035-471c-4bd3-8475-3ee5dd55f13a', '2&5', '2', '2019-08-09 09:40:41', 6, 'normal', '你给兰华杰说明一下,赶紧把这个显示尺寸改一下。', 'plain', '', '0'),
(33, 'c328dbe9-13ef-44fa-bd49-954b566234aa', '2&5', '5', '2019-08-09 09:40:50', 7, 'normal', '好的,收到。', 'plain', '', '0'),
(34, '830ed5f8-ac41-418c-97b6-9cd68112543b', '326bb771-3f23-4ecb-a907-b3b223575d37', '2', '2019-08-09 09:41:36', 7, 'normal', '这个设计稿里明确有,拿着设计稿对比确认一下。', 'plain', '', '0'),
(35, '0d7499f1-38ad-454d-b060-8a2df00bcf5d', '326bb771-3f23-4ecb-a907-b3b223575d37', '2', '2019-08-09 09:42:00', 8, 'normal', '还有问题问一下@兰华杰@潘登', 'plain', '', '0'),
(36, '48c33fa3-7d6d-4495-aa81-c1023fed9e37', '326bb771-3f23-4ecb-a907-b3b223575d37', '5', '2019-08-09 09:42:13', 9, 'normal', '好的,收到。', 'plain', '', '0'),
(37, '10096e33-f34d-49f8-b2be-cd469002730d', '4&5', '4', '2019-08-09 09:43:29', 1, 'normal', '喧喧登录时,显示尺寸已改为最小尺寸。', 'plain', '', '0'),
(38, '8e8f1734-5925-4c81-ae60-af36ddbb5794', '4&5', '4', '2019-08-09 09:43:35', 2, 'normal', '请再测试确认一下。', 'plain', '', '0'),
(39, '9a0c2a29-c6f3-4cd8-97d4-e38dfdd5b36b', '4&5', '5', '2019-08-09 09:43:45', 3, 'normal', '嗯,稍等,一会测试。', 'plain', '', '0'),
(40, 'b1530efe-4f64-4863-a1b9-c61ddf57aab9', '326bb771-3f23-4ecb-a907-b3b223575d37', '7', '2019-08-09 09:44:13', 10, 'normal', '@lijuan', 'plain', '', '0'),
(41, 'b2f1166a-51de-417c-a883-4700db570f92', '326bb771-3f23-4ecb-a907-b3b223575d37', '7', '2019-08-09 09:44:38', 11, 'normal', '编辑器的图标都是最新的,间距已都是调整后的。', 'plain', '', '0'),
(42, '66c68391-17f3-4c0e-8441-cd07a0d4ed72', '326bb771-3f23-4ecb-a907-b3b223575d37', '7', '2019-08-09 09:44:44', 12, 'normal', '还有什么问题吗?', 'plain', '', '0'),
(43, '5d696d4a-7e9c-48a7-8d1b-36696381202e', '326bb771-3f23-4ecb-a907-b3b223575d37', '4', '2019-08-09 09:45:27', 13, 'normal', '好的,我一会再确认一下。', 'plain', '', '0'),
(44, '3992d661-563f-445c-8dbf-60f266917196', '326bb771-3f23-4ecb-a907-b3b223575d37', '4', '2019-08-09 09:45:35', 14, 'normal', '有问题再联系你。', 'plain', '', '0'),
(45, '08f6dbcb-a772-4c3f-be9d-c489280b62a7', '326bb771-3f23-4ecb-a907-b3b223575d37', '7', '2019-08-09 09:45:58', 15, 'normal', '{\"type\":\"emoji\",\"content\":\":ok_hand:\"}', 'image', '', '0'),
(46, 'c9d7a6af-0b58-432e-800a-b037f7bdc954', '326bb771-3f23-4ecb-a907-b3b223575d37', '4', '2019-08-09 10:36:20', 16, 'normal', '{\"type\":\"url\",\"url\":\"https://cdn.zsite.com/data/source/x/xuanxuan/default/blank/f1.png\"}', 'object', '', '0'),
(47, '8a696d4a-700c-48a7-8d1b-adf96381202e', '326bb771-3f23-4ecb-a907-b3b223575d37', '4', '2019-08-09 10:36:28', 17, 'normal', '官网上的图片应该换了,这是上一个版本的截图。', 'plain', '', '0'),
(48, 'abda6d4a-789c-48a7-8a1b-88888881202e', '326bb771-3f23-4ecb-a907-b3b223575d37', '7', '2019-08-09 10:40:08', 18, 'normal', '已经换好了。', 'plain', '', '0');
INSERT INTO `xxb_user` (`id`, `dept`, `account`, `password`, `realname`, `role`, `deviceToken`, `deviceType`, `nickname`, `admin`, `avatar`, `birthday`, `gender`, `email`, `skype`, `qq`, `weixin`, `yahoo`, `gtalk`, `wangwang`, `site`, `mobile`, `phone`, `address`, `zipcode`, `visits`, `ip`, `last`, `ping`, `fails`, `join`, `locked`, `deleted`, `clientStatus`, `clientLang`) VALUES
(2, 15, 'lilei', 'ad290bd992f0657b1ee74e518d38a9ee', '李磊', 'dev', '', '', '', 'no', '', '0000-00-00', 'm', 'lilei@xuanxuan.im', '', '567891234', '134 6666 8888', '', '', '', '', '13466668888', '0532-86893032', '山东省青岛市黄岛区长江西路118号青铁广场18楼', '266555', 6, '10.0.2.2', '2019-08-09 08:57:51', '2019-08-09 08:57:51', 0, '2019-08-08 15:52:29', '0000-00-00 00:00:00', '0', 'online', 'zh-cn'),
(3, 16, 'hmm', 'b4086b8b8bcc7f113f8244d4d00d1f98', '韩梅梅', 'dev', '', '', '', 'no', '', '0000-00-00', 'f', 'hanmeimei@xuanxuan.im', '', '', 'hanmeimei', '', '', '', '', '13566450077', '', '', '', 0, '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, '2019-08-08 15:53:41', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(4, 17, 'lhj', '3d04f95821258f8870fa9572d942c89e', '兰华杰', 'dev', '', '', '', 'no', '', '0000-00-00', 'm', 'lanhuajie@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 2, '10.0.2.2', '2019-08-09 09:42:39', '2019-08-09 09:42:39', 0, '2019-08-08 15:54:52', '0000-00-00 00:00:00', '0', 'online', 'zh-cn'),
(5, 18, 'lijuan', '43dec70b007e418deeef53971c0f63e9', '李娟', 'dev', '', '', '', 'no', '', '0000-00-00', 'f', 'lijuan@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 2, '10.0.2.2', '2019-08-09 09:08:44', '2019-08-09 09:08:44', 0, '2019-08-08 16:00:22', '0000-00-00 00:00:00', '0', 'online', 'zh-cn'),
(6, 18, 'lilan', '6455ab518b82762c1c6b5778aaedf852', '李兰', 'dev', '', '', '', 'no', '', '0000-00-00', 'f', 'lilan@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 2, '10.0.2.2', '2019-08-09 09:08:45', '2019-08-09 09:08:45', 0, '2019-08-08 16:00:23', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(7, 17, 'pandeng', '4026095495c98f5719c94f3c8d083c9f', '潘登', 'dev', '', '', '', 'no', '', '0000-00-00', 'm', 'pandeng@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 2, '10.0.2.2', '2019-08-09 09:44:03', '2019-08-09 09:44:03', 0, '2019-08-08 16:03:09', '0000-00-00 00:00:00', '0', 'online', 'zh-cn'),
(8, 2, 'lgl', '681982392713d007c411a80335a15899', '李桂兰', 'adminmgr', '', '', '', 'no', '', '0000-00-00', 'f', 'liguilan@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 2, '10.0.2.2', '2019-08-09 09:10:11', '2019-08-09 09:10:11', 0, '2019-08-08 16:04:29', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(9, 4, 'wxp', '80296174667cc703307d5a62077d6429', '王秀萍', '', '', '', '', 'no', '', '0000-00-00', 'f', 'wangxiuping@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 0, '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, '2019-08-08 16:05:26', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(10, 21, 'wuguang', 'd7413316addd36dc68ddd2c1c604361f', '吴广', 'support', '', '', '', 'no', '', '0000-00-00', 'm', 'wuguang@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 0, '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, '2019-08-08 16:06:34', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(11, 22, 'chensheng', '7c30b40a0056b4f6b8a96472762c0c73', '陈胜', 'support', '', '', '', 'no', '', '0000-00-00', 'm', 'chensheng@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 0, '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, '2019-08-08 16:07:20', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(12, 20, 'lnn', 'fc0b670de1be695c59dd41f6367fe419', '李娜娜', 'marketmgr', '', '', '', 'no', '', '0000-00-00', 'f', 'linana@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 0, '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, '2019-08-08 16:14:09', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(13, 19, 'zjj', 'a8c3a815d4f395b346bca08991b06d71', '张静静', '', '', '', '', 'no', '', '0000-00-00', 'f', 'zhangjingjing@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 0, '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, '2019-08-08 16:14:58', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(14, 8, 'wangwei', '142d1469f6aa01d2def5db43dc5379cd', '王伟', 'dev', '', '', '', 'no', '', '0000-00-00', 'm', 'wangwei@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 0, '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, '2019-08-08 16:26:33', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(15, 7, 'lgq', '9f71028561c8be7cf176dcd1432a63e9', '李国庆', 'dev', '', '', '', 'no', '', '0000-00-00', 'm', 'liguoqing@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 0, '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, '2019-08-08 16:48:26', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(16, 1, 'lsx', 'cacc7bef2e83b1b959fec1361bf4202e', '刘双喜', 'pm', '', '', '', 'no', '', '0000-00-00', 'm', 'liushuangxi@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 2, '10.0.2.2', '2019-08-09 08:58:21', '2019-08-09 08:58:21', 0, '2019-08-08 16:49:33', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(17, 11, 'qsx', 'f55b6eb9b385caf2fabed05a62727c7c', '綦水秀', 'dev', '', '', '', 'no', '', '0000-00-00', 'f', 'qishuixiu@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 0, '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, '2019-08-08 16:51:23', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(18, 12, 'wjj', '364114d58a10acac82f79956b9f09fdc', '王俊杰', 'dev', '', '', '', 'no', '', '0000-00-00', 'm', 'wangjunjie@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 0, '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, '2019-08-08 16:58:19', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(19, 13, 'sxm', '0021dc91d75ddbc84dc10db310bfe05c', '孙小明', 'dev', '', '', '', 'no', '', '0000-00-00', 'm', 'sunxiaoming@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 2, '10.0.2.2', '2019-08-09 09:05:52', '2019-08-09 09:05:52', 0, '2019-08-08 16:59:19', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn');

130
db/demo.zh-tw.sql Normal file
View File

@ -0,0 +1,130 @@
INSERT INTO `xxb_category` (`id`, `name`, `alias`, `desc`, `keywords`, `root`, `parent`, `path`, `grade`, `order`, `type`, `readonly`, `moderators`, `threads`, `posts`, `postedBy`, `postedDate`, `postID`, `replyID`, `users`, `rights`, `refund`, `major`, `deleted`) VALUES
(1, '研發', '', '', '', 0, 0, ',1,', 1, 10, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:27:56', 0, 0, '', '', '0', '0', '0'),
(2, '行政', '', '', '', 0, 0, ',2,', 1, 20, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:27:56', 0, 0, '', '', '0', '0', '0'),
(3, '市場', '', '', '', 0, 0, ',3,', 1, 30, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:27:56', 0, 0, '', '', '0', '0', '0'),
(4, '財務', '', '', '', 0, 0, ',4,', 1, 40, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:27:56', 0, 0, '', '', '0', '0', '0'),
(5, '技術支持', '', '', '', 0, 0, ',5,', 1, 50, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:27:56', 0, 0, '', '', '0', '0', '0'),
(6, '禪道開發', '', '', '', 0, 1, ',1,6,', 2, 20, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:28:31', 0, 0, '', '', '0', '0', '0'),
(7, '蟬知開發', '', '', '', 0, 1, ',1,7,', 2, 30, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:28:31', 0, 0, '', '', '0', '0', '0'),
(8, '然之開發', '', '', '', 0, 1, ',1,8,', 2, 40, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:28:31', 0, 0, '', '', '0', '0', '0'),
(19, '國內市場部', '', '', '', 0, 3, ',3,19,', 2, 10, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:44:21', 0, 0, '', '', '0', '0', '0'),
(9, '喧喧開發', '', '', '', 0, 1, ',1,9,', 2, 10, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:28:31', 0, 0, '', '', '0', '0', '0'),
(10, '雲禪道項目組', '', '', '', 0, 6, ',1,6,10,', 3, 10, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:30:20', 0, 0, '', '', '0', '0', '1'),
(11, '雲禪道項目組', '', '', '', 0, 6, ',1,6,11,', 3, 10, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:30:20', 0, 0, '', '', '0', '0', '0'),
(12, '專業版項目組', '', '', '', 0, 6, ',1,6,12,', 3, 20, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:30:20', 0, 0, '', '', '0', '0', '0'),
(13, '企業版項目組', '', '', '', 0, 6, ',1,6,13,', 3, 30, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:30:20', 0, 0, '', '', '0', '0', '0'),
(14, '集群版項目組', '', '', '', 0, 6, ',1,6,14,', 3, 40, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:30:20', 0, 0, '', '', '0', '0', '1'),
(15, '產品設計組', '', '', '', 0, 9, ',1,9,15,', 3, 10, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:35:25', 0, 0, '', '', '0', '0', '0'),
(16, 'UI設計組', '', '', '', 0, 9, ',1,9,16,', 3, 20, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:35:25', 0, 0, '', '', '0', '0', '0'),
(17, '研發組', '', '', '', 0, 9, ',1,9,17,', 3, 30, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:35:25', 0, 0, '', '', '0', '0', '0'),
(18, '測試組', '', '', '', 0, 9, ',1,9,18,', 3, 40, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:35:25', 0, 0, '', '', '0', '0', '0'),
(20, '國際市場部', '', '', '', 0, 3, ',3,20,', 2, 20, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:44:21', 0, 0, '', '', '0', '0', '0'),
(21, '售前技術支持', '', '', '', 0, 5, ',5,21,', 2, 10, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:44:39', 0, 0, '', '', '0', '0', '0'),
(22, '售後技術支持', '', '', '', 0, 5, ',5,22,', 2, 20, 'dept', '0', '', 0, 0, 'admin', '2019-08-07 14:44:39', 0, 0, '', '', '0', '0', '0');
INSERT INTO `xxb_im_chat` (`id`, `gid`, `name`, `type`, `admins`, `committers`, `subject`, `public`, `createdBy`, `createdDate`, `ownedBy`, `editedBy`, `editedDate`, `lastActiveTime`, `dismissDate`, `lastMessageIndex`, `lastMessage`) VALUES
(1, '58113bb5-6a66-e94f-eb12-fb94271f6f7c', '系統', 'system', '', '', 0, '0', 'system', '2019-08-08 17:10:52', '', '', '0000-00-00 00:00:00', '2019-08-09 09:31:46', '0000-00-00 00:00:00', 9, 22),
(2, '3b320201-52e1-4061-90b2-23e750e8b6e0', '禪道研發組', 'group', '', '', 0, '0', 'sxm', '2019-08-09 09:06:26', 'sxm', '', '0000-00-00 00:00:00', '2019-08-09 09:06:26', '0000-00-00 00:00:00', 1, 1),
(3, 'c8e328cb-399f-4999-8524-32bdc6cc4629', '研發部', 'group', '', '', 0, '0', 'lsx', '2019-08-09 09:09:29', 'lsx', '', '0000-00-00 00:00:00', '2019-08-09 09:22:00', '0000-00-00 00:00:00', 6, 18),
(4, '326bb771-3f23-4ecb-a907-b3b223575d37', '喧喧開發組', 'group', '', '', 0, '0', 'lijuan', '2019-08-09 09:20:46', 'lijuan', '', '0000-00-00 00:00:00', '2019-08-09 09:45:58', '0000-00-00 00:00:00', 18, 48),
(5, '16&8', '', 'one2one', '', '', 0, '0', 'lsx', '2019-08-09 09:32:33', '', '', '0000-00-00 00:00:00', '2019-08-09 09:33:50', '0000-00-00 00:00:00', 4, 26),
(6, '2&5', '', 'one2one', '', '', 0, '0', 'lijuan', '2019-08-09 09:37:55', '', '', '0000-00-00 00:00:00', '2019-08-09 09:40:50', '0000-00-00 00:00:00', 7, 33),
(7, '4&5', '', 'one2one', '', '', 0, '0', 'lhj', '2019-08-09 09:43:29', '', '', '0000-00-00 00:00:00', '2019-08-09 09:43:45', '0000-00-00 00:00:00', 3, 39);
INSERT INTO `xxb_im_chatuser` (`id`, `cgid`, `user`, `order`, `star`, `hide`, `mute`, `freeze`, `join`, `quit`, `category`) VALUES
(1, '3b320201-52e1-4061-90b2-23e750e8b6e0', 17, 1, '0', '0', '0', '0', '2019-08-09 09:06:26', '0000-00-00 00:00:00', ''),
(2, '3b320201-52e1-4061-90b2-23e750e8b6e0', 18, 2, '0', '0', '0', '0', '2019-08-09 09:06:26', '0000-00-00 00:00:00', ''),
(3, '3b320201-52e1-4061-90b2-23e750e8b6e0', 19, 3, '0', '0', '0', '0', '2019-08-09 09:06:26', '0000-00-00 00:00:00', ''),
(4, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 17, 4, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(5, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 18, 5, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(6, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 19, 6, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(7, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 15, 7, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(8, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 14, 8, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(9, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 2, 9, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(10, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 3, 10, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(11, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 4, 11, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(12, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 7, 12, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(13, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 5, 13, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(14, 'c8e328cb-399f-4999-8524-32bdc6cc4629', 16, 14, '0', '0', '0', '0', '2019-08-09 09:09:29', '0000-00-00 00:00:00', ''),
(15, '326bb771-3f23-4ecb-a907-b3b223575d37', 2, 15, '0', '0', '0', '0', '2019-08-09 09:20:46', '0000-00-00 00:00:00', ''),
(16, '326bb771-3f23-4ecb-a907-b3b223575d37', 3, 16, '0', '0', '0', '0', '2019-08-09 09:20:46', '0000-00-00 00:00:00', ''),
(17, '326bb771-3f23-4ecb-a907-b3b223575d37', 4, 17, '0', '0', '0', '0', '2019-08-09 09:20:46', '0000-00-00 00:00:00', ''),
(18, '326bb771-3f23-4ecb-a907-b3b223575d37', 7, 18, '0', '0', '0', '0', '2019-08-09 09:20:46', '0000-00-00 00:00:00', ''),
(19, '326bb771-3f23-4ecb-a907-b3b223575d37', 5, 19, '0', '0', '0', '0', '2019-08-09 09:20:46', '0000-00-00 00:00:00', ''),
(20, '16&8', 16, 20, '0', '0', '0', '0', '2019-08-09 09:32:33', '0000-00-00 00:00:00', ''),
(21, '16&8', 8, 21, '0', '0', '0', '0', '2019-08-09 09:32:33', '0000-00-00 00:00:00', ''),
(22, '2&5', 2, 22, '0', '0', '0', '0', '2019-08-09 09:37:55', '0000-00-00 00:00:00', ''),
(23, '2&5', 5, 23, '0', '0', '0', '0', '2019-08-09 09:37:55', '0000-00-00 00:00:00', ''),
(24, '4&5', 4, 24, '0', '0', '0', '0', '2019-08-09 09:43:29', '0000-00-00 00:00:00', ''),
(25, '4&5', 5, 25, '0', '0', '0', '0', '2019-08-09 09:43:29', '0000-00-00 00:00:00', '');
INSERT INTO `xxb_im_message` (`id`, `gid`, `cgid`, `user`, `date`, `index`, `type`, `content`, `contentType`, `data`, `deleted`) VALUES
(1, '5c7276f5-fff5-bf63-f8e5-282b38a80004', '3b320201-52e1-4061-90b2-23e750e8b6e0', '19', '2019-08-09 09:06:26', 1, 'broadcast', '@sxm 創建了討論組 **[禪道研發組](#/chats/groups/3b320201-52e1-4061-90b2-23e750e8b6e0)**。', 'text', '', '0'),
(2, '7110e4cc-4db1-3dd4-32df-1c59cb475bd4', 'c8e328cb-399f-4999-8524-32bdc6cc4629', '16', '2019-08-09 09:09:29', 1, 'broadcast', '@lsx 創建了討論組 **[研發部](#/chats/groups/c8e328cb-399f-4999-8524-32bdc6cc4629)**。', 'text', '', '0'),
(3, 'a3f763d8-c40d-4c7c-a323-9ce4e78a60b3', '58113bb5-6a66-e94f-eb12-fb94271f6f7c', '8', '2019-08-09 09:11:06', 1, 'normal', '本月考勤的統計已結束,公佈在內網,有異議的同學請小窗我。', 'plain', '', '0'),
(4, '1f47920d-520f-4c22-8b14-2382b90419f6', '58113bb5-6a66-e94f-eb12-fb94271f6f7c', '2', '2019-08-09 09:12:51', 2, 'normal', '已查看,我的沒有問題。', 'plain', '', '0'),
(5, 'ba27fac1-9ac4-4567-a171-badfa078e4b7', '58113bb5-6a66-e94f-eb12-fb94271f6f7c', '16', '2019-08-09 09:13:21', 3, 'normal', '我的請假是休年假,需要改一下,看小窗。', 'plain', '', '0'),
(6, '909ca70c-dfe0-4b27-ad3b-d53192f11c2b', '58113bb5-6a66-e94f-eb12-fb94271f6f7c', '5', '2019-08-09 09:14:02', 4, 'normal', '我的考勤統計,沒問題。', 'plain', '', '0'),
(7, '70c1264b-5115-47c6-b8f5-18f337ae665b', '58113bb5-6a66-e94f-eb12-fb94271f6f7c', '19', '2019-08-09 09:14:19', 5, 'normal', '全勤的路過~', 'plain', '', '0'),
(8, 'ba1b7bf1-5e50-4eba-8e5b-8284caf4c3d3', '58113bb5-6a66-e94f-eb12-fb94271f6f7c', '8', '2019-08-09 09:15:04', 6, 'normal', '@劉雙喜,好的,已修改過來了。', 'plain', '', '0'),
(9, 'dd1cc560-f3e4-4fbe-9f66-f92a17132b9d', 'c8e328cb-399f-4999-8524-32bdc6cc4629', '16', '2019-08-09 09:17:07', 2, 'normal', '周五下午17點例會各開發組提前準備好工作周報。\n列好本週工作內容和下周工作計劃。把本週工作遇到的問題也列一下把問題拋出來看大家有什麼好的解決辦法。\n', 'plain', '', '0'),
(10, 'aa691502-52a6-4ef1-bade-3300760e2ba0', 'c8e328cb-399f-4999-8524-32bdc6cc4629', '2', '2019-08-09 09:17:51', 3, 'normal', '好的,收到。', 'plain', '', '0'),
(11, 'e7309457-7834-4507-bd2b-072724aade2b', 'c8e328cb-399f-4999-8524-32bdc6cc4629', '2', '2019-08-09 09:18:16', 4, 'normal', '整理完工作周報需要發送給你嗎?@劉雙喜', 'plain', '', '0'),
(12, '1f09839f-6fc0-439c-85ad-069144e62301', '58113bb5-6a66-e94f-eb12-fb94271f6f7c', '2', '2019-08-09 09:18:38', 7, 'normal', '{\"type\":\"emoji\",\"content\":\":handshake:\"}', 'image', '', '1'),
(13, 'c39e48bd-b2d2-4744-b55a-9bad3a6da885', '58113bb5-6a66-e94f-eb12-fb94271f6f7c', '16', '2019-08-09 09:19:02', 8, 'normal', '{\"type\":\"emoji\",\"content\":\":handshake:\"}', 'image', '', '0'),
(14, 'b5610e39-dadf-4c98-9b36-3fde9877d347', 'c8e328cb-399f-4999-8524-32bdc6cc4629', '5', '2019-08-09 09:19:56', 5, 'normal', '喧喧開發的同學們,記得把工作周報都寫好,發我彙總一下。', 'plain', '', '0'),
(15, '42225687-f5ce-88ea-c770-eec2a65b7bcd', '326bb771-3f23-4ecb-a907-b3b223575d37', '5', '2019-08-09 09:20:46', 1, 'broadcast', '@lijuan 創建了討論組 **[喧喧開發組](#/chats/groups/326bb771-3f23-4ecb-a907-b3b223575d37)**。', 'text', '', '0'),
(16, '9f090a5c-126f-4013-bfcd-f6698447bcc7', '326bb771-3f23-4ecb-a907-b3b223575d37', '2', '2019-08-09 09:21:22', 2, 'normal', '本週的工作周報,需要大家都寫一下,按要求寫完,然後發送我彙總。', 'plain', '', '0'),
(17, '41b43b61-94a8-46af-a834-a2fe393cf261', '326bb771-3f23-4ecb-a907-b3b223575d37', '2', '2019-08-09 09:21:38', 3, 'normal', '今天15點前別忘記了。', 'plain', '', '0'),
(18, '2c83f1aa-be62-4724-bf5f-c15091a6d2c6', 'c8e328cb-399f-4999-8524-32bdc6cc4629', '19', '2019-08-09 09:22:00', 6, 'normal', '收到~', 'plain', '', '0'),
(19, '92a7af02-5f5a-4791-9f67-8e2b7de86dad', '326bb771-3f23-4ecb-a907-b3b223575d37', '5', '2019-08-09 09:26:17', 4, 'normal', '{\"name\":\"clipboard-image-16475982.png\",\"size\":1028,\"send\":true,\"type\":\"base64\",\"time\":1565313978413,\"content\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACkAAAAYCAYAAABnRtT+AAADy0lEQVRYCb2Xy08bRxzHP7teB2NvgGKb9YMEjKCpgwSHopx6xDR93Hto+etoD703EXVSJekxUg64at0qAvO0cf2IIF7Hj31Uu8vagKC1YdWRVrM7v9f3952Z38wKpmmaeNQsRwfFCltvJxAFkQ/NGjMzU8Qi4JNAvGEkySN8tpsuUCybYIpousHDuSZTU00kOk4Y4WbRxJuZXW+lqqotbLfbhMOT1ysOIfGUSSuuYVh5ixg6jPgMcFkcAtRlVc+ZvBzAi2/ph+9/5KhUdnwJVuYDNNPJLRlX+Pa7bwYwcFQMRDY2Nnj06SPS6TQI2tW2pkQ+n+f1m9esr68jlUolvvzqayLhCAwBslqrsvnkp6uD/MvoysoK2Z+ztkb64cKVmhbAbDbL6uertlwyBIhEx4hFJ640uHZQ7GDZDtNEDBbTDxBN0QZh2V5g9IxBC+Da2hrptJWEgecbZxDQNjDoAz1j1GXQAZgGnOUwGEgN9v6s2PFnPoly69QEDXeqLdbcGXnuMmiD7q/XgUBWD1RarRaartGsRQkqg/D13zouo5tZZ40+tqe4z6Dr4WIJasO7/S5GC7COMB0aFY3jSpG5j++Rmk1R2C2gNcGvBVwfA/dW7bDrhymB9VxqgikhGBJSV7YfV3xBc+9tjUajQb3hIzU3jd6B3UKB2VQKfwj8QZArMvt7B4xPjLs+huqbTZXn2ReUiiUmw5PUa3V7k1hOXv7yEr/kp3XaIiTLKLPjjI6OOqvL3xmjevgBtVtnYXGe4o7K/l8N2t13xKIJ5Gg/l9jCGAe7TYxBy9W5FERTsgGagsHaF2vktn7no3CERXsXw7gehS7EFxTKx2XKhffMzyv0prtYKpKaS3FHFpidk23XgUCAyL3QuTAwMjLC/IOZC2PDfFgMLi0tk0qlWFpeplav98ytWVQUhbvyXZSYgqo2bJlkXZ9KJ4dM3Y9w0j7lxNnEBOKW3MfxOSc9b6ZItV4d+uplCBqxZJRc7jf7fM/ltkgk+rtQlgOUy0coJKmXVYJjEqavhRSPx3n65KkTf9Ap7B2LdiY97IO8ZDIZnj17webmJolEnMxqpmeWnE5ydHjE9vY2siwzPZ20ZYKXl17r1vjq1z1axn3Uhsrjz/q1rofkBi+9NXkD2//NxHOQouhUQ9EHbV1E486tk/EcZCjkVAOrCtRq/Z17G6T9AngbL2e2fiChCFRODSRJ5I+dIKoeJBYJ3upHzNON4/4MvnoD7xtdfEIHXdcwOiV0wxi6ZLm8eQrSddpoQz6/w98nUXvIMJ3DwZUP2/8DMfFqbQG4d1sAAAAASUVORK5CYII=\",\"isImage\":false}', 'image', '', '0'),
(20, '3b29578e-4649-476b-bf55-590fc4472841', '326bb771-3f23-4ecb-a907-b3b223575d37', '5', '2019-08-09 09:26:45', 5, 'normal', '喧喧編輯器的表徵圖間距確定了麼?', 'plain', '', '0'),
(21, '0d29d0f0-2751-4056-8316-e8bd629d8324', '326bb771-3f23-4ecb-a907-b3b223575d37', '5', '2019-08-09 09:27:08', 6, 'normal', '表徵圖是不是也確定下來,接下來不坐更改了?', 'plain', '', '0'),
(22, '7b2002c7-04ff-4a38-88ce-42f0eaec04c2', '58113bb5-6a66-e94f-eb12-fb94271f6f7c', '8', '2019-08-09 09:31:46', 9,'normal', '備註本月統計的是上月的考勤大家有疑問的如果是8月的先不用着急小窗我。', 'plain', '', '0'),
(23, 'f545a250-49bb-4b4e-8828-dd3fec1a5aee', '16&8', '16', '2019-08-09 09:32:33', 1, 'normal', '我7月31日的請假不算事假休的是年假。\n請幫忙修改過來謝謝~', 'plain', '', '0'),
(24, '1ef9d150-a096-4b38-88c2-bc7efc96548b', '16&8', '8', '2019-08-09 09:33:23', 2, 'normal', '好的你的年假還剩2天7月31日使用1天那麼你2019年的年假還剩1天。', 'plain', '', '0'),
(25, 'f903d42e-6244-4ed4-bf17-fa806097a1cd', '16&8', '8', '2019-08-09 09:33:26', 3, 'normal', '確認一下。', 'plain', '', '0'),
(26, 'eea18ec9-8231-45ff-8a49-ff3990b19c95', '16&8', '16', '2019-08-09 09:33:50', 4, 'normal', '嗯,已確認,沒有問題。', 'plain', '', '0'),
(27, 'eb4dad55-0e15-4983-b6e8-6b41117696c2', '2&5', '5', '2019-08-09 09:37:55', 1, 'normal', '啟動喧喧時,登錄窗口預設最小尺寸顯示會比較好。', 'plain', '', '0'),
(28, 'f8326459-e8a8-4af1-b54c-82d70f76ec12', '2&5', '5', '2019-08-09 09:38:39', 2, 'normal', '目前是間于最小尺寸和最大尺寸顯示的大小,用戶登錄時,尤其是小屏幕,', 'plain', '', '0'),
(29, 'f20a985e-493f-482a-9200-c6fa26a73da6', '2&5', '5', '2019-08-09 09:38:48', 3, 'normal', '用戶體驗不大好。', 'plain', '', '0'),
(30, 'd64761da-b5cb-443b-9879-a72cc5bb36e5', '2&5', '5', '2019-08-09 09:38:59', 4, 'normal', '希望確定下來。', 'plain', '', '0'),
(31, 'dcb5c788-d160-4566-8fb7-2fff9c8d1d3b', '2&5', '2', '2019-08-09 09:39:45', 5, 'normal', '設計時,啟動時窗口顯示的大小就是預設顯示為最小尺寸的。', 'plain', '', '0'),
(32, 'dc205035-471c-4bd3-8475-3ee5dd55f13a', '2&5', '2', '2019-08-09 09:40:41', 6, 'normal', '你給蘭華傑說明一下,趕緊把這個顯示尺寸改一下。', 'plain', '', '0'),
(33, 'c328dbe9-13ef-44fa-bd49-954b566234aa', '2&5', '5', '2019-08-09 09:40:50', 7, 'normal', '好的,收到。', 'plain', '', '0'),
(34, '830ed5f8-ac41-418c-97b6-9cd68112543b', '326bb771-3f23-4ecb-a907-b3b223575d37', '2', '2019-08-09 09:41:36', 7, 'normal', '這個設計稿裡明確有,拿着設計稿對比確認一下。', 'plain', '', '0'),
(35, '0d7499f1-38ad-454d-b060-8a2df00bcf5d', '326bb771-3f23-4ecb-a907-b3b223575d37', '2', '2019-08-09 09:42:00', 8, 'normal', '還有問題問一下@蘭華傑@潘登', 'plain', '', '0'),
(36, '48c33fa3-7d6d-4495-aa81-c1023fed9e37', '326bb771-3f23-4ecb-a907-b3b223575d37', '5', '2019-08-09 09:42:13', 9, 'normal', '好的,收到。', 'plain', '', '0'),
(37, '10096e33-f34d-49f8-b2be-cd469002730d', '4&5', '4', '2019-08-09 09:43:29', 1, 'normal', '喧喧登錄時,顯示尺寸已改為最小尺寸。', 'plain', '', '0'),
(38, '8e8f1734-5925-4c81-ae60-af36ddbb5794', '4&5', '4', '2019-08-09 09:43:35', 2, 'normal', '請再測試確認一下。', 'plain', '', '0'),
(39, '9a0c2a29-c6f3-4cd8-97d4-e38dfdd5b36b', '4&5', '5', '2019-08-09 09:43:45', 3, 'normal', '嗯,稍等,一會測試。', 'plain', '', '0'),
(40, 'b1530efe-4f64-4863-a1b9-c61ddf57aab9', '326bb771-3f23-4ecb-a907-b3b223575d37', '7', '2019-08-09 09:44:13', 10, 'normal', '@lijuan', 'plain', '', '0'),
(41, 'b2f1166a-51de-417c-a883-4700db570f92', '326bb771-3f23-4ecb-a907-b3b223575d37', '7', '2019-08-09 09:44:38', 11, 'normal', '編輯器的表徵圖都是最新的,間距已都是調整後的。', 'plain', '', '0'),
(42, '66c68391-17f3-4c0e-8441-cd07a0d4ed72', '326bb771-3f23-4ecb-a907-b3b223575d37', '7', '2019-08-09 09:44:44', 12, 'normal', '還有什麼問題嗎?', 'plain', '', '0'),
(43, '5d696d4a-7e9c-48a7-8d1b-36696381202e', '326bb771-3f23-4ecb-a907-b3b223575d37', '4', '2019-08-09 09:45:27', 13, 'normal', '好的,我一會再確認一下。', 'plain', '', '0'),
(44, '3992d661-563f-445c-8dbf-60f266917196', '326bb771-3f23-4ecb-a907-b3b223575d37', '4', '2019-08-09 09:45:35', 14, 'normal', '有問題再聯繫你。', 'plain', '', '0'),
(45, '08f6dbcb-a772-4c3f-be9d-c489280b62a7', '326bb771-3f23-4ecb-a907-b3b223575d37', '7', '2019-08-09 09:45:58', 15, 'normal', '{\"type\":\"emoji\",\"content\":\":ok_hand:\"}', 'image', '', '0'),
(46, 'c9d7a6af-0b58-432e-800a-b037f7bdc954', '326bb771-3f23-4ecb-a907-b3b223575d37', '4', '2019-08-09 10:36:20', 16, 'normal', '{\"type\":\"url\",\"url\":\"https://cdn.zsite.com/data/source/x/xuanxuan/default/blank/f1.png\"}', 'object', '', '0'),
(47, '8a696d4a-700c-48a7-8d1b-adf96381202e', '326bb771-3f23-4ecb-a907-b3b223575d37', '4', '2019-08-09 10:36:28', 17, 'normal', '官網上的圖片該換了,這是上一個版本的截圖。', 'plain', '', '0'),
(48, 'abda6d4a-789c-48a7-8a1b-88888881202e', '326bb771-3f23-4ecb-a907-b3b223575d37', '7', '2019-08-09 10:40:08', 18, 'normal', '已經換好了。', 'plain', '', '0');
INSERT INTO `xxb_user` (`id`, `dept`, `account`, `password`, `realname`, `role`, `deviceToken`, `deviceType`, `nickname`, `admin`, `avatar`, `birthday`, `gender`, `email`, `skype`, `qq`, `weixin`, `yahoo`, `gtalk`, `wangwang`, `site`, `mobile`, `phone`, `address`, `zipcode`, `visits`, `ip`, `last`, `ping`, `fails`, `join`, `locked`, `deleted`, `clientStatus`, `clientLang`) VALUES
(2, 15, 'lilei', 'ad290bd992f0657b1ee74e518d38a9ee', '李磊', 'dev', '', '', '', 'no', '', '0000-00-00', 'm', 'lilei@xuanxuan.im', '', '567891234', '134 6666 8888', '', '', '', '', '13466668888', '0532-86893032', '山東省青島市黃島區長江中路232號國貿大廈C座2單元2902', '266555', 6, '10.0.2.2', '2019-08-09 08:57:51', '2019-08-09 08:57:51', 0, '2019-08-08 15:52:29', '0000-00-00 00:00:00', '0', 'online', 'zh-cn'),
(3, 16, 'hmm', 'b4086b8b8bcc7f113f8244d4d00d1f98', '韓梅梅', 'dev', '', '', '', 'no', '', '0000-00-00', 'f', 'hanmeimei@xuanxuan.im', '', '', 'hanmeimei', '', '', '', '', '13566450077', '', '', '', 0, '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, '2019-08-08 15:53:41', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(4, 17, 'lhj', '3d04f95821258f8870fa9572d942c89e', '蘭華傑', 'dev', '', '', '', 'no', '', '0000-00-00', 'm', 'lanhuajie@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 2, '10.0.2.2', '2019-08-09 09:42:39', '2019-08-09 09:42:39', 0, '2019-08-08 15:54:52', '0000-00-00 00:00:00', '0', 'online', 'zh-cn'),
(5, 18, 'lijuan', '43dec70b007e418deeef53971c0f63e9', '李娟', 'dev', '', '', '', 'no', '', '0000-00-00', 'f', 'lijuan@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 2, '10.0.2.2', '2019-08-09 09:08:44', '2019-08-09 09:08:44', 0, '2019-08-08 16:00:22', '0000-00-00 00:00:00', '0', 'online', 'zh-cn'),
(6, 18, 'lilan', '6455ab518b82762c1c6b5778aaedf852', '李蘭', 'dev', '', '', '', 'no', '', '0000-00-00', 'f', 'lilan@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 2, '10.0.2.2', '2019-08-09 09:08:45', '2019-08-09 09:08:45', 0, '2019-08-08 16:00:23', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(7, 17, 'pandeng', '4026095495c98f5719c94f3c8d083c9f', '潘登', 'dev', '', '', '', 'no', '', '0000-00-00', 'm', 'pandeng@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 2, '10.0.2.2', '2019-08-09 09:44:03', '2019-08-09 09:44:03', 0, '2019-08-08 16:03:09', '0000-00-00 00:00:00', '0', 'online', 'zh-cn'),
(8, 2, 'lgl', '681982392713d007c411a80335a15899', '李桂蘭', 'adminmgr', '', '', '', 'no', '', '0000-00-00', 'f', 'liguilan@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 2, '10.0.2.2', '2019-08-09 09:10:11', '2019-08-09 09:10:11', 0, '2019-08-08 16:04:29', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(9, 4, 'wxp', '80296174667cc703307d5a62077d6429', '王秀萍', '', '', '', '', 'no', '', '0000-00-00', 'f', 'wangxiuping@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 0, '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, '2019-08-08 16:05:26', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(10, 21, 'wuguang', 'd7413316addd36dc68ddd2c1c604361f', '吳廣', 'support', '', '', '', 'no', '', '0000-00-00', 'm', 'wuguang@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 0, '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, '2019-08-08 16:06:34', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(11, 22, 'chensheng', '7c30b40a0056b4f6b8a96472762c0c73', '陳勝', 'support', '', '', '', 'no', '', '0000-00-00', 'm', 'chensheng@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 0, '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, '2019-08-08 16:07:20', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(12, 20, 'lnn', 'fc0b670de1be695c59dd41f6367fe419', '李娜娜', 'marketmgr', '', '', '', 'no', '', '0000-00-00', 'f', 'linana@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 0, '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, '2019-08-08 16:14:09', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(13, 19, 'zjj', 'a8c3a815d4f395b346bca08991b06d71', '張靜靜', '', '', '', '', 'no', '', '0000-00-00', 'f', 'zhangjingjing@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 0, '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, '2019-08-08 16:14:58', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(14, 8, 'wangwei', '142d1469f6aa01d2def5db43dc5379cd', '王偉', 'dev', '', '', '', 'no', '', '0000-00-00', 'm', 'wangwei@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 0, '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, '2019-08-08 16:26:33', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(15, 7, 'lgq', '9f71028561c8be7cf176dcd1432a63e9', '李國慶', 'dev', '', '', '', 'no', '', '0000-00-00', 'm', 'liguoqing@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 0, '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, '2019-08-08 16:48:26', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(16, 1, 'lsx', 'cacc7bef2e83b1b959fec1361bf4202e', '劉雙喜', 'pm', '', '', '', 'no', '', '0000-00-00', 'm', 'liushuangxi@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 2, '10.0.2.2', '2019-08-09 08:58:21', '2019-08-09 08:58:21', 0, '2019-08-08 16:49:33', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(17, 11, 'qsx', 'f55b6eb9b385caf2fabed05a62727c7c', '綦水秀', 'dev', '', '', '', 'no', '', '0000-00-00', 'f', 'qishuixiu@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 0, '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, '2019-08-08 16:51:23', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(18, 12, 'wjj', '364114d58a10acac82f79956b9f09fdc', '王俊傑', 'dev', '', '', '', 'no', '', '0000-00-00', 'm', 'wangjunjie@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 0, '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, '2019-08-08 16:58:19', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn'),
(19, 13, 'sxm', '0021dc91d75ddbc84dc10db310bfe05c', '孫小明', 'dev', '', '', '', 'no', '', '0000-00-00', 'm', 'sunxiaoming@xuanxuan.im', '', '', '', '', '', '', '', '', '', '', '', 2, '10.0.2.2', '2019-08-09 09:05:52', '2019-08-09 09:05:52', 0, '2019-08-08 16:59:19', '0000-00-00 00:00:00', '0', 'offline', 'zh-cn');

0
db/index.html Normal file
View File

14
db/upgrade1.2.sql Normal file
View File

@ -0,0 +1,14 @@
ALTER TABLE `xxb_entry` ADD `status` ENUM('online','offline') NOT NULL DEFAULT 'online' AFTER `category`;
ALTER TABLE `xxb_entry` ADD `version` VARCHAR(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL AFTER `buildin`;
ALTER TABLE `xxb_entry` ADD `platform` VARCHAR(255) NOT NULL DEFAULT 'ranzhi' AFTER `version`;
ALTER TABLE `xxb_entry` ADD `package` INT(11) NOT NULL DEFAULT '0' AFTER `platform`;
CREATE TABLE `xxb_sso` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`sid` char(32) NOT NULL,
`entry` mediumint(8) unsigned NOT NULL,
`token` char(32) NOT NULL,
`time` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `sid` (`sid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

1
db/upgrade2.4.0.sql Normal file
View File

@ -0,0 +1 @@
ALTER TABLE `xxb_category` ADD `deleted` enum('0', '1') NOT NULL DEFAULT '0';

14
db/upgrade2.5.0.sql Normal file
View File

@ -0,0 +1,14 @@
ALTER TABLE `xxb_block` DROP INDEX `accountAppOrder`;
ALTER TABLE `xxb_block` DROP INDEX `account`;
ALTER TABLE `xxb_config` DROP INDEX `unique`;
ALTER TABLE `xxb_lang` DROP INDEX `lang`;
ALTER TABLE `xxb_block` DROP `app`;
ALTER TABLE `xxb_config` DROP `app`;
ALTER TABLE `xxb_lang` DROP `app`;
ALTER TABLE `xxb_block` ADD UNIQUE INDEX `accountAppOrder` (`account`, `order`);
ALTER TABLE `xxb_block` ADD INDEX `account` (`account`);
ALTER TABLE `xxb_config` ADD UNIQUE INDEX `unique` (`owner`, `module`, `section`, `key`);
ALTER TABLE `xxb_lang` ADD INDEX `lang` (`lang`, `module`, `section`, `key`);

20
db/upgrade2.5.7.sql Normal file
View File

@ -0,0 +1,20 @@
-- DROP TABLE IF EXISTS `xxb_cron`;
CREATE TABLE IF NOT EXISTS `xxb_cron` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`m` varchar(20) NOT NULL,
`h` varchar(20) NOT NULL,
`dom` varchar(20) NOT NULL,
`mon` varchar(20) NOT NULL,
`dow` varchar(20) NOT NULL,
`command` text NOT NULL,
`remark` varchar(255) NOT NULL,
`type` varchar(20) NOT NULL,
`buildin` tinyint(1) NOT NULL DEFAULT '0',
`status` varchar(20) NOT NULL,
`lastTime` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `xxb_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type`, `buildin`, `status`, `lastTime`) VALUES
('*', '*', '*', '*', '*', '', '监控定时任务', 'xuanxuan', 1, 'normal', '0000-00-00 00:00:00'),
('*/1', '*', '*', '*', '*', 'moduleName=push&methodName=pushMessage', '异步推送', 'xuanxuan', 1, 'normal', '0000-00-00 00:00:00');

1
db/upgrade3.0-beta3.sql Normal file
View File

@ -0,0 +1 @@
ALTER TABLE `xxb_im_client` CHANGE `version` `version` char(30) NOT NULL DEFAULT '';

View File

@ -0,0 +1,2 @@
DELETE FROM `xxb_im_messagestatus` WHERE `status` = 'sent';
DELETE `xxb_im_messagestatus` FROM `xxb_im_messagestatus` LEFT JOIN `xxb_user` ON `xxb_im_messagestatus`.`user` = `xxb_user`.`id` WHERE `xxb_user`.`deleted` = '1'

21
db/upgrade3.1.1.sql Normal file
View File

@ -0,0 +1,21 @@
-- DROP TABLE IF EXISTS `xxb_im_conference`;
CREATE TABLE IF NOT EXISTS `im_conference` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
`rid` char(24) NOT NULL DEFAULT '',
`cgid` char(40) NOT NULL DEFAULT '',
`status` enum('closed','open') NOT NULL DEFAULT 'closed',
`participants` text NOT NULL,
`openedBy` mediumint(8) NOT NULL DEFAULT 0,
`openedDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `xxb_im_conferenceaction`;
CREATE TABLE IF NOT EXISTS `im_conferenceaction` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
`rid` char(24) NOT NULL DEFAULT '',
`type` enum('create','join','leave','close') NOT NULL DEFAULT 'create',
`user` mediumint(8) NOT NULL DEFAULT 0,
`date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

1
db/upgrade3.2.3.sql Normal file
View File

@ -0,0 +1 @@
ALTER TABLE `xxb_user` CHANGE `clientStatus` `clientStatus` enum('online', 'away', 'busy', 'offline', 'meeting') NOT NULL DEFAULT 'offline';

3
db/upgrade4.0.beta1.sql Normal file
View File

@ -0,0 +1,3 @@
ALTER TABLE `xxb_action` DROP `customer`, DROP `contact`, DROP `read`, DROP `reader`;
ALTER TABLE `xxb_action` ADD `ip` char(15) NOT NULL DEFAULT '' AFTER `objectID`;
ALTER TABLE `xxb_action` ADD `result` char(7) NOT NULL AFTER `action`;

1
db/upgrade4.4.1.sql Normal file
View File

@ -0,0 +1 @@
ALTER TABLE `xxb_entry` CHANGE `platform` `platform` varchar(255) NOT NULL DEFAULT 'xuanxuan';

2
db/upgrade5.3.1.sql Normal file
View File

@ -0,0 +1,2 @@
ALTER TABLE `xxb_entry` ADD `optional` tinyint(1) unsigned NOT NULL DEFAULT '0' AFTER `integration`;
ALTER TABLE `xxb_entry` ADD `enable` tinyint(1) unsigned NOT NULL DEFAULT '0' AFTER `optional`;

1
db/upgrade5.3.2.sql Normal file
View File

@ -0,0 +1 @@
ALTER TABLE `xxb_user` ADD `cidrs` text DEFAULT NULL AFTER `ip`;

1
db/upgrade5.4.sql Normal file
View File

@ -0,0 +1 @@
ALTER TABLE `xxb_file` MODIFY COLUMN `title` varchar(255);

2
db/upgrade6.0.sql Normal file
View File

@ -0,0 +1,2 @@
ALTER TABLE `xxb_sso` ADD `user` mediumint(8) DEFAULT NULL AFTER `time`;
ALTER TABLE `xxb_sso` ADD `ip` CHAR(50) DEFAULT NULL AFTER `user`;

1
db/upgrade6.2.sql Normal file
View File

@ -0,0 +1 @@
ALTER TABLE `xxb_sso` ADD `ip` CHAR(50) DEFAULT NULL AFTER `user`;

View File

@ -0,0 +1,29 @@
SET @@sql_mode= '';
alter table `xxb_user` add index idx_deleted_id(deleted,id);
alter table `xxb_category` add index idx_dele_type_id(deleted,type,id);
alter table `xxb_im_message` add index idx_date(date);
alter table `xxb_im_conference` add index idx_cgid(cgid);
alter table `xxb_im_conferenceaction` add index idx_rid_date(rid,date);
alter table `xxb_im_client` add index idx_strategy_status_id(strategy,status,id);
alter table xxb_action ENGINE=INNODB;
alter table xxb_block ENGINE=INNODB;
alter table xxb_category ENGINE=INNODB;
alter table xxb_config ENGINE=INNODB;
alter table xxb_cron ENGINE=INNODB;
alter table xxb_entry ENGINE=INNODB;
alter table xxb_file ENGINE=INNODB;
alter table xxb_group ENGINE=INNODB;
alter table xxb_grouppriv ENGINE=INNODB;
alter table xxb_history ENGINE=INNODB;
alter table xxb_im_chat ENGINE=INNODB;
alter table xxb_im_chatuser ENGINE=INNODB;
alter table xxb_im_client ENGINE=INNODB;
alter table xxb_im_conference ENGINE=INNODB;
alter table xxb_im_conferenceaction ENGINE=INNODB;
alter table xxb_im_message ENGINE=INNODB;
alter table xxb_im_messagestatus ENGINE=INNODB;
alter table xxb_im_queue ENGINE=INNODB;
alter table xxb_lang ENGINE=INNODB;
alter table xxb_sso ENGINE=INNODB;
alter table xxb_user ENGINE=INNODB;
alter table xxb_usergroup ENGINE=INNODB;

View File

@ -0,0 +1,9 @@
ALTER TABLE `xxb_file` CHANGE `pathname` `pathname` char(100) NOT NULL;
TRUNCATE `im_usermessage`;
ALTER TABLE `im_usermessage` DROP `module`;
ALTER TABLE `im_usermessage` DROP `method`;
ALTER TABLE `im_usermessage` CHANGE `data` `message` text not null;
DROP TABLE IF EXISTS `im_chatfile`;

View File

@ -0,0 +1,4 @@
ALTER TABLE `im_message` ADD `order` mediumint(8) unsigned NOT NULL AFTER `date`;
ALTER TABLE `im_message` ADD `data` text NOT NULL DEFAULT '' AFTER `contentType`;
ALTER TABLE `im_chatuser` ADD `category` varchar(40) NOT NULL DEFAULT '' AFTER `quit`;
ALTER TABLE `im_chat` ADD `dismissDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `lastActiveTime`;

View File

@ -0,0 +1 @@
ALTER TABLE `im_message` CHANGE `order` `order` BIGINT(8) UNSIGNED NOT NULL;

View File

@ -0,0 +1,10 @@
-- DROP TABLE IF EXISTS `im_messagestatus`;
CREATE TABLE `im_messagestatus` (
`user` mediumint(8) NOT NULL DEFAULT 0,
`gid` char(40) NOT NULL DEFAULT '',
`status` enum('waiting','sent','readed','deleted') NOT NULL DEFAULT 'waiting',
UNIQUE KEY `user` (`user`,`gid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
ALTER TABLE `im_message` CHANGE `type` `type` ENUM('normal','broadcast','notify') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'normal';
ALTER TABLE `im_message` CHANGE `contentType` `contentType` ENUM('text','emotion','image','file','object') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'text';

View File

@ -0,0 +1 @@
ALTER TABLE `im_message` CHANGE `contentType` `contentType` ENUM('text', 'plain', 'emotion', 'image', 'file', 'object') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'text';

View File

@ -0,0 +1 @@
ALTER TABLE `xxb_entry` ADD `sso` enum('0', '1') NOT NULL DEFAULT '0';

View File

@ -0,0 +1 @@
ALTER TABLE `xxb_user` ADD `clientLang` varchar(10) NOT NULL DEFAULT 'zh-cn';

View File

@ -0,0 +1 @@
ALTER TABLE `xxb_user` CHANGE `status` `clientStatus` enum('online', 'away', 'busy', 'offline') NOT NULL DEFAULT 'offline';

View File

@ -0,0 +1 @@
ALTER TABLE `im_message` ADD `deleted` enum('0','1') COLLATE 'utf8_general_ci' NOT NULL;

View File

@ -0,0 +1,15 @@
ALTER TABLE `im_messagestatus` ADD `message` INT(11) UNSIGNED NOT NULL AFTER `user`;
CREATE TABLE IF NOT EXISTS `im_xxcversion` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`version` char(10) NOT NULL DEFAULT '',
`desc` varchar(100) NOT NULL DEFAULT '',
`readme` text NOT NULL,
`strategy` varchar(10) NOT NULL DEFAULT '',
`downloads` text NOT NULL,
`createdDate` datetime NOT NULL,
`createdBy` varchar(30) NOT NULL DEFAULT '',
`editedDate` datetime NOT NULL,
`editedBy` varchar(30) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

View File

@ -0,0 +1,12 @@
UPDATE `xxb_config` SET `key` = 'https' WHERE `owner` = 'system' AND `module` = 'common' AND `section` = 'xuanxuan' AND `key` = 'isHttps';
UPDATE `xxb_config` SET `key` = 'backendLang' WHERE `owner` = 'system' AND `module` = 'common' AND `section` = 'xuanxuan' AND `key` = 'xxbLang';
UPDATE `xxb_grouppriv` SET `module` = 'client', `method` = 'browse' WHERE `module` = 'setting' AND `method` = 'xxcversion';
UPDATE `xxb_grouppriv` SET `module` = 'client', `method` = 'create' WHERE `module` = 'setting' AND `method` = 'createxxcversion';
UPDATE `xxb_grouppriv` SET `module` = 'client', `method` = 'edit' WHERE `module` = 'setting' AND `method` = 'editxxcversion';
UPDATE `xxb_grouppriv` SET `module` = 'client', `method` = 'delete' WHERE `module` = 'setting' AND `method` = 'deletexxcversion';
RENAME TABLE `im_xxcversion` TO `im_client`;
ALTER TABLE `im_client` CHANGE `readme` `changeLog` text NOT NULL;
ALTER TABLE `im_client` ADD `status` ENUM('released','wait') NOT NULL DEFAULT 'wait' AFTER `editedBy`;

View File

@ -0,0 +1,17 @@
ALTER TABLE `im_chatuser` ADD `freeze` ENUM('0', '1') NOT NULL DEFAULT '0' AFTER `mute`;
ALTER TABLE `im_message` CHANGE `contentType` `contentType` ENUM('text', 'plain', 'emotion', 'image', 'file', 'code', 'object') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'text';
ALTER TABLE `xxb_user` ADD `deviceToken` char(120) NOT NUll AFTER `role`;
ALTER TABLE `xxb_user` ADD `deviceType` char(20) NOT NUll AFTER `deviceToken`;
ALTER TABLE `im_client` CHANGE `version` `version` char(30) NOT NULL DEFAULT '';
-- DROP TABLE IF EXISTS `im_queue`;
CREATE TABLE IF NOT EXISTS `im_queue` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
`type` char(30) NOT NULL,
`content` text NOT NULL,
`addDate` datetime NOT NULL,
`processDate` datetime NOT NULL,
`result` text NOT NULL,
`status` char(30) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

View File

@ -0,0 +1 @@
ALTER TABLE `im_client` CHANGE `version` `version` char(30) NOT NULL DEFAULT '';

View File

@ -0,0 +1,2 @@
DELETE FROM `im_messagestatus` WHERE `status` = 'sent';
DELETE `im_messagestatus` FROM `im_messagestatus` LEFT JOIN `xxb_user` ON `im_messagestatus`.`user` = `xxb_user`.`id` WHERE `xxb_user`.`deleted` = '1'

View File

@ -0,0 +1,21 @@
-- DROP TABLE IF EXISTS `im_conference`;
CREATE TABLE IF NOT EXISTS `im_conference` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
`rid` char(24) NOT NULL DEFAULT '',
`cgid` char(40) NOT NULL DEFAULT '',
`status` enum('closed','open') NOT NULL DEFAULT 'closed',
`participants` text NOT NULL,
`openedBy` mediumint(8) NOT NULL DEFAULT 0,
`openedDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `im_conferenceaction`;
CREATE TABLE IF NOT EXISTS `im_conferenceaction` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
`rid` char(24) NOT NULL DEFAULT '',
`type` enum('create','join','leave','close') NOT NULL DEFAULT 'create',
`user` mediumint(8) NOT NULL DEFAULT 0,
`date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

View File

@ -0,0 +1 @@
ALTER TABLE `xxb_user` CHANGE `clientStatus` `clientStatus` enum('online', 'away', 'busy', 'offline', 'meeting') NOT NULL DEFAULT 'offline';

64
db/upgradexuanxuan3.3.sql Normal file
View File

@ -0,0 +1,64 @@
ALTER TABLE `xxb_user` ADD `pinyin` varchar(255) NOT NULL DEFAULT '' AFTER `realname`;
ALTER TABLE `im_chat` ADD `lastMessage` int(11) unsigned NOT NULL DEFAULT 0 AFTER `lastActiveTime`;
ALTER TABLE `im_conference` ADD `invitee` text NOT NULL AFTER `participants`;
ALTER TABLE `im_message` CHANGE `id` `id` int(11) unsigned NOT NULL AUTO_INCREMENT;
CREATE TABLE IF NOT EXISTS `im_message_backup` (
`id` int(11) unsigned NOT NULL,
`gid` char(40) NOT NULL DEFAULT '',
`cgid` char(40) NOT NULL DEFAULT '',
`user` varchar(30) NOT NULL DEFAULT '',
`date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`order` bigint(8) unsigned NOT NULL,
`type` enum('normal', 'broadcast', 'notify') NOT NULL DEFAULT 'normal',
`content` text NOT NULL DEFAULT '',
`contentType` enum('text', 'plain', 'emotion', 'image', 'file', 'object', 'code') NOT NULL DEFAULT 'text',
`data` text NOT NULL DEFAULT '',
`deleted` enum('0','1') NOT NULL DEFAULT '0'
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `im_message_index` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`tableName` char(64) NOT NULL,
`start` int(11) unsigned NOT NULL,
`end` int(11) unsigned NOT NULL,
`startDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`endDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`chats` text NOT NULL,
PRIMARY KEY (`id`),
KEY `tableName` (`tableName`),
KEY `start` (`start`),
KEY `end` (`end`),
KEY `startDate` (`startDate`),
KEY `endDate` (`endDate`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `im_chat_message_index` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`gid` char(40) NOT NULL,
`tableName` char(64) NOT NULL,
`start` int(11) unsigned NOT NULL,
`end` int(11) unsigned NOT NULL,
`startDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`endDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`count` mediumint(8) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `chattable` (`gid`,`tableName`),
KEY `start` (`start`),
KEY `end` (`end`),
KEY `startDate` (`startDate`),
KEY `endDate` (`endDate`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `im_userdevice` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
`user` mediumint(8) NOT NULL DEFAULT 0,
`device` char(40) NOT NULL DEFAULT 'default',
`lastLogin` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`lastLogout` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
KEY `user` (`user`),
KEY `lastLogin` (`lastLogin`),
KEY `lastLogout` (`lastLogout`),
UNIQUE KEY `userdevice` (`user`, `device`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

View File

@ -0,0 +1,2 @@
ALTER TABLE `im_chat` ADD `pinnedMessages` text NOT NULL DEFAULT '' AFTER `dismissDate`;
ALTER TABLE `im_message` CHANGE `type` `type` enum('normal', 'broadcast', 'notify', 'bulletin') NOT NULL DEFAULT 'normal';

View File

@ -0,0 +1,2 @@
ALTER TABLE `im_message` DROP COLUMN `order`;
ALTER TABLE `im_message_backup` DROP COLUMN `order`;

View File

@ -0,0 +1,2 @@
ALTER TABLE `im_userdevice` ADD `deviceID` char(40) NOT NULL DEFAULT '' AFTER `device`, ADD `token` char(64) NOT NULL DEFAULT '' AFTER `deviceID`, ADD `validUntil` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `token`;
ALTER TABLE `im_conferenceaction` ADD `device` char(40) NOT NULL DEFAULT 'default' AFTER `date`;

View File

@ -0,0 +1 @@
ALTER TABLE `im_chatuser` ADD `lastReadMessage` int(11) unsigned NOT NULL DEFAULT 0 AFTER `category`;

View File

@ -0,0 +1 @@
ALTER TABLE `im_conferenceaction` CHANGE `type` `type` ENUM('create','invite','join','leave','close') NOT NULL DEFAULT 'create';

View File

@ -0,0 +1 @@
ALTER TABLE `im_chat` ADD `ownedBy` varchar(30) NOT NULL DEFAULT '' AFTER `createdDate`;

View File

@ -0,0 +1,4 @@
ALTER TABLE `im_conference` CHANGE `rid` `rid` CHAR(40) NOT NULL DEFAULT '';
ALTER TABLE `im_conferenceaction` CHANGE `rid` `rid` CHAR(40) NOT NULL DEFAULT '';
ALTER TABLE `im_conferenceaction` CHANGE `type` `type` enum('create','invite','join','leave','close','publish') NOT NULL DEFAULT 'create';
ALTER TABLE `im_conferenceaction` ADD `data` text NOT NULL DEFAULT '' AFTER `type`;

View File

@ -0,0 +1,3 @@
ALTER TABLE `im_chat` ADD `mergedDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `editedDate`;
ALTER TABLE `im_chat` ADD `mergedChats` text NOT NULL DEFAULT '' AFTER `pinnedMessages`;

11
db/upgradexuanxuan5.6.sql Normal file
View File

@ -0,0 +1,11 @@
ALTER TABLE `im_chat` ADD `lastMessageIndex` int(11) unsigned NOT NULL DEFAULT 0 AFTER `lastMessage`;
ALTER TABLE `im_chatuser` ADD `lastReadMessageIndex` int(11) unsigned NOT NULL DEFAULT 0 AFTER `lastReadMessage`;
ALTER TABLE `im_message` ADD `index` int(11) unsigned NOT NULL DEFAULT 0 AFTER `date`;
ALTER TABLE `im_message_backup` ADD `index` int(11) unsigned NOT NULL DEFAULT 0 AFTER `date`;
ALTER TABLE `im_chat_message_index` ADD `startIndex` int(11) unsigned NOT NULL AFTER `end`;
ALTER TABLE `im_chat_message_index` ADD `endIndex` int(11) unsigned NOT NULL AFTER `startIndex`;
ALTER TABLE `im_chat_message_index` ADD KEY `chatstartindex` (`gid`,`startIndex`);
ALTER TABLE `im_chat_message_index` ADD KEY `chatendindex` (`gid`,`endIndex`);

View File

@ -0,0 +1 @@
ALTER TABLE `im_chat` ADD `adminInvite` enum('0','1') NOT NULL DEFAULT '0' AFTER `mergedChats`;

View File

@ -0,0 +1 @@
ALTER TABLE `im_chat` ADD `avatar` text NOT NULL DEFAULT '' AFTER `adminInvite`;

View File

@ -0,0 +1 @@
ALTER TABLE `im_chat` ADD `archiveDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `avatar`;

View File

@ -0,0 +1,2 @@
ALTER TABLE `im_message` MODIFY COLUMN `type` enum('normal','broadcast','notify','bulletin','botcommand') NOT NULL DEFAULT 'normal' AFTER `index`;
ALTER TABLE `im_message` DROP INDEX `unique_msg`;

10
db/upgradexuanxuan7.1.sql Normal file
View File

@ -0,0 +1,10 @@
ALTER TABLE `im_conference` ADD `topic` text NOT NULL AFTER `openedDate`;
ALTER TABLE `im_conference` ADD `startTime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `topic`;
ALTER TABLE `im_conference` ADD `endTime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `startTime`;
ALTER TABLE `im_conference` ADD `password` char(20) NOT NULL DEFAULT '' AFTER `endTime`;
ALTER TABLE `im_conference` ADD `type` enum('default', 'periodic', 'scheduled') NOT NULL DEFAULT 'default' AFTER `password`;
ALTER TABLE `im_conference` ADD `number` char(20) NOT NULL DEFAULT '' AFTER `type`;
ALTER TABLE `im_conference` ADD KEY `status` (`status`);
ALTER TABLE `im_userdevice` ADD `online` tinyint(1) DEFAULT 0 NOT NULL AFTER `lastLogout`;
ALTER TABLE `im_userdevice` ADD `version` char(10) DEFAULT '' NOT NULL AFTER `online`;

View File

@ -0,0 +1,15 @@
ALTER TABLE `im_conference` ADD `subscribers` text NOT NULL AFTER `participants`;
ALTER TABLE `im_conference` ADD `note` text NOT NULL AFTER `number`;
ALTER TABLE `im_conference` ADD `sentNotify` tinyint(1) NOT NULL DEFAULT 0 AFTER `note`;
ALTER TABLE `im_conference` ADD `reminderTime` int NOT NULL DEFAULT 0 AFTER `sentNotify`;
ALTER TABLE `im_conference` MODIFY `status` enum ('closed', 'open', 'notStarted') DEFAULT 'closed' NOT NULL;
-- DROP TABLE IF EXISTS `im_conferenceuser`;
CREATE TABLE IF NOT EXISTS `im_conferenceuser` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
`conference` mediumint(8) NOT NULL DEFAULT 0,
`user` mediumint(8) NOT NULL DEFAULT 0,
`hide` enum('0', '1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `conferenceuser` (`conference`, `user`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

237
db/xuanxuan.sql Normal file
View File

@ -0,0 +1,237 @@
-- DROP TABLE IF EXISTS `im_chat`;
CREATE TABLE IF NOT EXISTS `im_chat` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`gid` char(40) NOT NULL DEFAULT '',
`name` varchar(60) NOT NULL DEFAULT '',
`type` varchar(20) NOT NULL DEFAULT 'group',
`admins` varchar(255) NOT NULL DEFAULT '',
`committers` varchar(255) NOT NULL DEFAULT '',
`subject` mediumint(8) unsigned NOT NULL DEFAULT 0,
`public` enum('0', '1') NOT NULL DEFAULT '0',
`createdBy` varchar(30) NOT NULL DEFAULT '',
`createdDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`ownedBy` varchar(30) NOT NULL DEFAULT '',
`editedBy` varchar(30) NOT NULL DEFAULT '',
`editedDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`mergedDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`lastActiveTime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`lastMessage` int(11) unsigned NOT NULL DEFAULT 0,
`lastMessageIndex` int(11) unsigned NOT NULL DEFAULT 0,
`dismissDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`pinnedMessages` text NOT NULL DEFAULT '',
`mergedChats` text NOT NULL DEFAULT '',
`adminInvite` enum('0','1') NOT NULL DEFAULT '0',
`avatar` text NOT NULL DEFAULT '',
`archiveDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
KEY `gid` (`gid`),
KEY `name` (`name`),
KEY `type` (`type`),
KEY `public` (`public`),
KEY `createdBy` (`createdBy`),
KEY `editedBy` (`editedBy`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `im_chatuser`;
CREATE TABLE IF NOT EXISTS `im_chatuser` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`cgid` char(40) NOT NULL DEFAULT '',
`user` mediumint(8) NOT NULL DEFAULT 0,
`order` smallint(5) NOT NULL DEFAULT 0,
`star` enum('0', '1') NOT NULL DEFAULT '0',
`hide` enum('0', '1') NOT NULL DEFAULT '0',
`mute` enum('0', '1') NOT NULL DEFAULT '0',
`freeze` enum('0', '1') NOT NULL DEFAULT '0',
`join` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`quit` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`category` varchar(40) NOT NULL DEFAULT '',
`lastReadMessage` int(11) unsigned NOT NULL DEFAULT 0,
`lastReadMessageIndex` int(11) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
KEY `cgid` (`cgid`),
KEY `user` (`user`),
KEY `order` (`order`),
KEY `star` (`star`),
KEY `hide` (`hide`),
UNIQUE KEY `chatuser` (`cgid`, `user`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `im_client`;
CREATE TABLE IF NOT EXISTS `im_client` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`version` char(30) NOT NULL DEFAULT '',
`desc` varchar(100) NOT NULL DEFAULT '',
`changeLog` text NOT NULL,
`strategy` varchar(10) NOT NULL DEFAULT '',
`downloads` text NOT NULL,
`createdDate` datetime NOT NULL,
`createdBy` varchar(30) NOT NULL DEFAULT '',
`editedDate` datetime NOT NULL,
`editedBy` varchar(30) NOT NULL DEFAULT '',
`status` enum('released','wait') NOT NULL DEFAULT 'wait',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `im_message`;
CREATE TABLE IF NOT EXISTS `im_message` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`gid` char(40) NOT NULL DEFAULT '',
`cgid` char(40) NOT NULL DEFAULT '',
`user` varchar(30) NOT NULL DEFAULT '',
`date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`index` int(11) unsigned NOT NULL DEFAULT 0,
`type` enum('normal', 'broadcast', 'notify', 'bulletin', 'botcommand') NOT NULL DEFAULT 'normal',
`content` text NOT NULL DEFAULT '',
`contentType` enum('text', 'plain', 'emotion', 'image', 'file', 'object', 'code') NOT NULL DEFAULT 'text',
`data` text NOT NULL DEFAULT '',
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `mgid` (`gid`),
KEY `mcgid` (`cgid`),
KEY `muser` (`user`),
KEY `mtype` (`type`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `im_message_backup`;
CREATE TABLE IF NOT EXISTS `im_message_backup` (
`id` int(11) unsigned NOT NULL,
`gid` char(40) NOT NULL DEFAULT '',
`cgid` char(40) NOT NULL DEFAULT '',
`user` varchar(30) NOT NULL DEFAULT '',
`date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`index` int(11) unsigned NOT NULL DEFAULT 0,
`type` enum('normal', 'broadcast', 'notify') NOT NULL DEFAULT 'normal',
`content` text NOT NULL DEFAULT '',
`contentType` enum('text', 'plain', 'emotion', 'image', 'file', 'object', 'code') NOT NULL DEFAULT 'text',
`data` text NOT NULL DEFAULT '',
`deleted` enum('0','1') NOT NULL DEFAULT '0'
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `im_message_index`;
CREATE TABLE IF NOT EXISTS `im_message_index` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`tableName` char(64) NOT NULL,
`start` int(11) unsigned NOT NULL,
`end` int(11) unsigned NOT NULL,
`startDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`endDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`chats` text NOT NULL,
PRIMARY KEY (`id`),
KEY `tableName` (`tableName`),
KEY `start` (`start`),
KEY `end` (`end`),
KEY `startDate` (`startDate`),
KEY `endDate` (`endDate`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `im_chat_message_index`;
CREATE TABLE IF NOT EXISTS `im_chat_message_index` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`gid` char(40) NOT NULL,
`tableName` char(64) NOT NULL,
`start` int(11) unsigned NOT NULL,
`end` int(11) unsigned NOT NULL,
`startIndex` int(11) unsigned NOT NULL,
`endIndex` int(11) unsigned NOT NULL,
`startDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`endDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`count` mediumint(8) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `chattable` (`gid`,`tableName`),
KEY `start` (`start`),
KEY `end` (`end`),
KEY `startDate` (`startDate`),
KEY `endDate` (`endDate`),
KEY `chatstartindex` (`gid`,`startIndex`),
KEY `chatendindex` (`gid`,`endIndex`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `im_messagestatus`;
CREATE TABLE IF NOT EXISTS `im_messagestatus` (
`user` mediumint(8) NOT NULL DEFAULT 0,
`message` int(11) unsigned NOT NULL,
`status` enum('waiting','sent','readed','deleted') NOT NULL DEFAULT 'waiting',
UNIQUE KEY `user` (`user`,`message`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `im_queue`;
CREATE TABLE IF NOT EXISTS `im_queue` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
`type` char(30) NOT NULL,
`content` text NOT NULL,
`addDate` datetime NOT NULL,
`processDate` datetime NOT NULL,
`result` text NOT NULL,
`status` char(30) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `im_conference`;
CREATE TABLE IF NOT EXISTS `im_conference` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
`rid` char(40) NOT NULL DEFAULT '',
`cgid` char(40) NOT NULL DEFAULT '',
`status` enum ('closed', 'open', 'notStarted') NOT NULL DEFAULT 'closed',
`participants` text NOT NULL,
`subscribers` text NOT NULL,
`invitee` text NOT NULL,
`openedBy` mediumint(8) NOT NULL DEFAULT 0,
`openedDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`topic` text NOT NULL,
`startTime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`endTime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`password` char(20) NOT NULL DEFAULT '',
`type` enum('default','periodic','scheduled') NOT NULL DEFAULT 'default',
`number` char(20) NOT NULL DEFAULT '',
`note` text NOT NULL,
`sentNotify` tinyint(1) NOT NULL DEFAULT 0,
`reminderTime` int NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
KEY `status` (`status`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `im_conferenceaction`;
CREATE TABLE IF NOT EXISTS `im_conferenceaction` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
`rid` char(40) NOT NULL DEFAULT '',
`type` enum('create','invite','join','leave','close','publish') NOT NULL DEFAULT 'create',
`data` text NOT NULL DEFAULT '',
`user` mediumint(8) NOT NULL DEFAULT 0,
`date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`device` char(40) NOT NULL DEFAULT 'default',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `im_conferenceuser`;
CREATE TABLE IF NOT EXISTS `im_conferenceuser` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
`conference` mediumint(8) NOT NULL DEFAULT 0,
`user` mediumint(8) NOT NULL DEFAULT 0,
`hide` enum('0', '1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `conferenceuser` (`conference`, `user`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `im_userdevice`;
CREATE TABLE IF NOT EXISTS `im_userdevice` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
`user` mediumint(8) NOT NULL DEFAULT 0,
`device` char(40) NOT NULL DEFAULT 'default',
`deviceID` char(40) NOT NULL DEFAULT '',
`token` char(64) NOT NULL DEFAULT '',
`validUntil` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`lastLogin` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`lastLogout` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`online` tinyint(1) NOT NULL DEFAULT 0,
`version` char(10) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `user` (`user`),
KEY `lastLogin` (`lastLogin`),
KEY `lastLogout` (`lastLogout`),
UNIQUE KEY `userdevice` (`user`, `device`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
ALTER TABLE `xxb_entry` ADD `sso` enum('0', '1') NOT NULL DEFAULT '0';
ALTER TABLE `xxb_file` CHANGE `pathname` `pathname` char(100) NOT NULL;
ALTER TABLE `xxb_user` ADD `clientStatus` enum('online', 'away', 'busy', 'offline', 'meeting') NOT NULL DEFAULT 'offline';
ALTER TABLE `xxb_user` ADD `clientLang` varchar(10) NOT NULL DEFAULT 'zh-cn';

256
db/xxb.sql Normal file
View File

@ -0,0 +1,256 @@
-- DROP TABLE IF EXISTS `xxb_action`;
CREATE TABLE IF NOT EXISTS `xxb_action` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`objectType` varchar(30) NOT NULL DEFAULT '',
`objectID` mediumint(8) unsigned NOT NULL DEFAULT '0',
`ip` char(15) NOT NULL DEFAULT '',
`actor` varchar(30) NOT NULL DEFAULT '',
`action` varchar(30) NOT NULL DEFAULT '',
`result` char(7) NOT NULL,
`date` datetime NOT NULL,
`comment` text NOT NULL,
`extra` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `objectType` (`objectType`),
KEY `objectID` (`objectID`),
KEY `date` (`date`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `xxb_block`;
CREATE TABLE IF NOT EXISTS `xxb_block` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`account` char(30) NOT NULL,
`title` varchar(100) NOT NULL,
`source` varchar(20) NOT NULL,
`block` varchar(20) NOT NULL,
`params` text NOT NULL,
`order` tinyint(3) unsigned NOT NULL DEFAULT '0',
`grid` tinyint(3) unsigned NOT NULL DEFAULT '0',
`height` smallint(5) unsigned NOT NULL DEFAULT '0',
`hidden` tinyint(1) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `accountAppOrder` (`account`, `order`),
KEY `account` (`account`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `xxb_category`;
CREATE TABLE IF NOT EXISTS `xxb_category` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` char(30) NOT NULL DEFAULT '',
`alias` varchar(100) NOT NULL,
`desc` text NOT NULL,
`keywords` varchar(150) NOT NULL,
`root` mediumint(8) unsigned NOT NULL DEFAULT '0',
`parent` mediumint(8) unsigned NOT NULL DEFAULT '0',
`path` char(255) NOT NULL DEFAULT '',
`grade` tinyint(3) unsigned NOT NULL DEFAULT '0',
`order` smallint(5) unsigned NOT NULL DEFAULT '0',
`type` char(30) NOT NULL,
`readonly` enum('0','1') NOT NULL DEFAULT '0',
`moderators` varchar(255) NOT NULL,
`threads` smallint(5) NOT NULL,
`posts` smallint(5) NOT NULL,
`postedBy` varchar(30) NOT NULL,
`postedDate` datetime NOT NULL,
`postID` mediumint(8) unsigned NOT NULL,
`replyID` mediumint(8) unsigned NOT NULL,
`users` text NOT NULL,
`rights` varchar(255) NOT NULL,
`refund` enum('0','1') NOT NULL DEFAULT '0',
`major` enum('0','1','2','3','4','5','6','7','8') NOT NULL DEFAULT '0',
`deleted` enum('0', '1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `type` (`type`),
KEY `order` (`order`),
KEY `parent` (`parent`),
KEY `path` (`path`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `xxb_config`;
CREATE TABLE IF NOT EXISTS `xxb_config` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`owner` char(30) NOT NULL DEFAULT '',
`module` varchar(30) NOT NULL,
`section` char(30) NOT NULL DEFAULT '',
`key` char(30) DEFAULT NULL,
`value` text NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique` (`owner`,`module`,`section`,`key`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `xxb_entry`;
CREATE TABLE IF NOT EXISTS `xxb_entry` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`abbr` char(6) NOT NULL,
`code` varchar(20) NOT NULL,
`buildin` tinyint(1) unsigned NOT NULL DEFAULT '0',
`version` varchar(20) NOT NULL,
`platform` varchar(255) NOT NULL DEFAULT 'xuanxuan',
`package` int(11) NOT NULL DEFAULT 0,
`integration` tinyint(1) unsigned NOT NULL DEFAULT '0',
`optional` tinyint(1) unsigned NOT NULL DEFAULT '0',
`enable` tinyint(1) unsigned NOT NULL DEFAULT '0',
`open` varchar(20) NOT NULL,
`key` char(32) NOT NULL,
`ip` varchar(100) NOT NULL,
`logo` varchar(100) NOT NULL,
`login` varchar(255) NOT NULL,
`logout` varchar(255) NOT NULL,
`block` varchar(255) NOT NULL,
`control` varchar(10) NOT NULL DEFAULT 'simple',
`size` varchar(50) NOT NULL DEFAULT 'max',
`position` varchar(10) NOT NULL DEFAULT 'default',
`visible` tinyint(1) unsigned NOT NULL DEFAULT '0',
`order` tinyint(5) unsigned NOT NULL DEFAULT '0',
`zentao` enum('0', '1') NOT NULL DEFAULT '0',
`category` mediumint(8) unsigned NOT NULL DEFAULT '0',
`status` enum('online','offline') NOT NULL DEFAULT 'online',
PRIMARY KEY (`id`),
UNIQUE KEY `code` (`code`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `xxb_file`;
CREATE TABLE IF NOT EXISTS `xxb_file` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`pathname` char(50) NOT NULL,
`title` varchar(255) NOT NULL,
`extension` char(30) NOT NULL,
`size` mediumint(8) unsigned NOT NULL DEFAULT '0',
`objectType` char(30) NOT NULL,
`objectID` mediumint(8) unsigned NOT NULL,
`createdBy` char(30) NOT NULL DEFAULT '',
`createdDate` datetime NOT NULL,
`editor` enum('1','0') NOT NULL DEFAULT '0',
`primary` enum('1','0') DEFAULT '0',
`public` enum('1','0') NOT NULL DEFAULT '1',
`downloads` mediumint(8) unsigned NOT NULL DEFAULT '0',
`extra` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `object` (`objectType`,`objectID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `xxb_history`;
CREATE TABLE IF NOT EXISTS `xxb_history` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`action` mediumint(8) unsigned NOT NULL DEFAULT '0',
`field` varchar(30) NOT NULL DEFAULT '',
`old` text NOT NULL,
`new` text NOT NULL,
`diff` mediumtext NOT NULL,
PRIMARY KEY (`id`),
KEY `action` (`action`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `xxb_lang`;
CREATE TABLE IF NOT EXISTS `xxb_lang` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`lang` varchar(30) NOT NULL,
`module` varchar(30) NOT NULL,
`section` varchar(30) NOT NULL,
`key` varchar(60) NOT NULL,
`value` text NOT NULL,
`system` enum('0','1') NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
UNIQUE KEY `lang` (`lang`,`module`,`section`,`key`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `xxb_sso`;
CREATE TABLE IF NOT EXISTS `xxb_sso` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`sid` char(32) NOT NULL,
`entry` mediumint(8) unsigned NOT NULL,
`token` char(32) NOT NULL,
`time` datetime NOT NULL,
`user` mediumint(8) DEFAULT NULL,
`ip` char(50) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `sid` (`sid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `xxb_user`;
CREATE TABLE IF NOT EXISTS `xxb_user` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`dept` mediumint(8) unsigned NOT NULL,
`account` char(30) NOT NULL DEFAULT '',
`password` char(32) NOT NULL DEFAULT '',
`realname` char(30) NOT NULL DEFAULT '',
`pinyin` varchar(255) NOT NULL DEFAULT '',
`role` char(30) NOT NULL,
`deviceToken` char(120) NOT NULL,
`deviceType` char(20) NOT NULL,
`nickname` char(60) NOT NULL DEFAULT '',
`admin` enum('no','common','super') NOT NULL DEFAULT 'no',
`avatar` varchar(255) NOT NULL DEFAULT '',
`birthday` date NOT NULL,
`gender` enum('f','m','u') NOT NULL DEFAULT 'u',
`email` char(90) NOT NULL DEFAULT '',
`skype` char(90) NOT NULL,
`qq` char(20) NOT NULL DEFAULT '',
`weixin` char(50) NOT NULL,
`yahoo` char(90) NOT NULL DEFAULT '',
`gtalk` char(90) NOT NULL DEFAULT '',
`wangwang` char(90) NOT NULL DEFAULT '',
`site` varchar(100) NOT NULL,
`mobile` char(11) NOT NULL DEFAULT '',
`phone` char(20) NOT NULL DEFAULT '',
`address` char(120) NOT NULL DEFAULT '',
`zipcode` char(10) NOT NULL DEFAULT '',
`visits` mediumint(8) unsigned NOT NULL DEFAULT '0',
`ip` char(50) NOT NULL DEFAULT '',
`last` datetime NOT NULL,
`ping` datetime NOT NULL,
`fails` tinyint(3) unsigned NOT NULL DEFAULT '0',
`join` datetime NOT NULL,
`locked` datetime NOT NULL,
`deleted` enum('0','1') NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `account` (`account`),
KEY `admin` (`admin`),
KEY `accountPassword` (`account`,`password`),
KEY `dept` (`dept`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `xxb_group`;
CREATE TABLE IF NOT EXISTS `xxb_group` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
`name` char(30) NOT NULL,
`desc` char(255) NOT NULL default '',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `xxb_usergroup`;
CREATE TABLE IF NOT EXISTS `xxb_usergroup` (
`account` char(30) NOT NULL DEFAULT '',
`group` mediumint(8) unsigned NOT NULL DEFAULT '0',
UNIQUE KEY `account` (`account`,`group`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `xxb_grouppriv`;
CREATE TABLE IF NOT EXISTS `xxb_grouppriv` (
`group` mediumint(8) unsigned NOT NULL default '0',
`module` char(30) NOT NULL default '',
`method` char(30) NOT NULL default '',
UNIQUE KEY `group` (`group`,`module`,`method`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `xxb_cron`;
CREATE TABLE IF NOT EXISTS `xxb_cron` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`m` varchar(20) NOT NULL,
`h` varchar(20) NOT NULL,
`dom` varchar(20) NOT NULL,
`mon` varchar(20) NOT NULL,
`dow` varchar(20) NOT NULL,
`command` text NOT NULL,
`remark` varchar(255) NOT NULL,
`type` varchar(20) NOT NULL,
`buildin` tinyint(1) NOT NULL DEFAULT '0',
`status` varchar(20) NOT NULL,
`lastTime` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `xxb_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type`, `buildin`, `status`, `lastTime`) VALUES
('*', '*', '*', '*', '*', '', '监控定时任务', 'xuanxuan', 1, 'normal', '0000-00-00 00:00:00'),
('*/1', '*', '*', '*', '*', 'moduleName=push&methodName=pushMessage', '异步推送', 'xuanxuan', 1, 'normal', '0000-00-00 00:00:00');

1
doc/CHANGELOG Normal file
View File

@ -0,0 +1 @@
2018-01-01 1.0.beta版本发布

36
doc/INSTALL Normal file
View File

@ -0,0 +1,36 @@
1. system required
XXB needs apache or nginx, php(>5.2) and mysql.
2. install the allinone package on windows
We have build an allinone package for windows systems. This package comes from the xampp project which is a great AMP tool.
2.1 download our .exe package.
2.2 double click the .exe and extract it into c:\xampp or d:\xampp, keep it under the root directory.
2.3 start XXB
cd c:\xampp, there'is control panel tools. double click it, it will stay on the tray menu at the bottom of the window.
click the XXB icon, then the menu will show, you can choose the "start xuanxuan", waiting for a moment.
Then you can visit XXB through http://localhost/xxb/
3. install the allinone package on linux
We also build an allinone package for linux systems from the zbox tool.
3.1 download our .gz package, and save it to /opt/
3.2 cd /opt/ and chmod a+rx *.gz and then execute the gz file, which will self extrct.
3.3 after extract, the directory should be /opt/zbox
3.4 cd /opt/zbox, and execute sudo ./zbox start or sudo ./zbox start -ap 88 -mp 3308 to start apache in 88 port and mysql in 3308 port.
3.5 then you can visit XXB through http://localhost/xxb/
4. install the source code.
4.1 install one AMP package. you can install other AMP package. Make sure the version of apache, php and mysql meets the needs of xxb.
4.2 download our zip package.
4.3 unpack it.
after download our zip package, save it to the apache's htdocs path and unpack it to XXB. make sure the XXB path can be
visited through browse.
4.4 start the installation
open your browser and visit the XXB path, for example http://192.168.1.1/xxb/, then the install wizard will launch, you can install it
step by step.

250
doc/LICENSE Normal file
View File

@ -0,0 +1,250 @@
Background
Since Richard Matthew Stallmans Free Software Movement, free software and open source software have been booming. It has played
a huge role in human civilization. However, open source software is exploited by the rising To-Business companies,
especially cloud computing ones. They take more than what they give back, and even breach open source consensus, such as infringement.
Hence, some open source software teams have to take actions to stop this, e.g.
https://mariadb.com/bsl11/
https://redislabs.com/community/licenses/
https://www.confluent.io/confluent-community-license
https://www.mongodb.com/licensing/server-side-public-license
However, those licenses are condemned by the community who follow the lead of OSI(Open Source Initiative) for not being approved by OSI.
Only talking about being open source but ignoring the struggling open source developers will not solve the problem for those developers.
Only under the premised of their survival, can open source software developers keep maintaining open source software. Hence, we believe that,
Any software that helps others, no matter what its size, functions, license, or open source percentage is, should be respected;
Any behavior that helps the developers, no matter what its form, participation, succession, duration, should be encouraged and appreciated.
Therefore, ZENTAO OPEN SOFTWARE LICENSE 1.0, different from open source, is drafted to seek a balance between being open and being commercial.
ZENTAO OPEN SOFTWARE LICENSE 1.0
Authorization
ZENTAO OPEN SOFTWARE LICENSE, also known as ZOSL Agreement, is drafted by ZenTao Software (Qingdao) Co., Ltd. (ZenTao Software (Qingdao) Co., Ltd.).
Anyone can use the agreement to publish open software by editing the blank underlined part of the following text of the agreement accordingly.
No other text of the agreement shall be changed. ZenTao Software (Qingdao) Co., Ltd. has the final interpretation of the terms in the agreement.
Preface
Xuanxuan (Hereinafter referred to as "the software") developed by ZenTao Software (Qingdao) Co., Ltd. (ZenTao Software (Qingdao) Co., Ltd.) (hereinafter referred to "I"). I am entitled to all copyrights of the software.
The software is released as open source software. You are authorized to use the software as long as you are in compliance with this agreement.
By the installation of the software, you agree that a contractual relationship between you and me is automatically established.
You are obliged to fully comply with all the terms of this agreement unless you choose to stop using the software or you have signed additional contracts with me.
My Contact:
Contact: Mr. Xu
Phone: 4006-8899-23
Email: co@cnezsoft.com
QQ: 1492153927
Address: Room 2902, Unit 2, Block C, International Trade Center, Kai Fa Qu, Qingdao
You and I agree:
Indications of the software include:
Notes, texts, pictures and links showing copyright attribution of the software in the source code and related documentation.
and texts, picture and links on the interface of the software when running.
Excluding
texts, picture and links on the interface of the demo versions of the software.
1. Disclaimer
The software is open software, so you are authorized to use the software without paying a fee. Before you start to use it, please note:
1.1 I do not have any obligation to provide technical support for the software. You can contact me to purchase technical support.
1.2 I am not responsible for any liability caused by your using the software directly or indirectly.
1.3 Open software does not mean it is free of charge, neither does it mean the software does not have any copyright.
2. For personal use
2.1 You or your company/organization are authorized to use the software for your internal use for both commercial and non-commercial purposes.
2.2 You or your company/organization are authorized to run the software on any number of computers.
2.3 You or your company/organization are authorized to modify the source code available in the software to meet your requirements. You do not need to release the modified codes.
2.4 You or your company/organization must keep all the indications of the software when using it. None of the indications can be removed, hidden or obscured in any way.
3. For customized software
3.1 You are authorized to use the software to deploy various forms of application for your users in any way you like.
3.2 You are authorized to use the software to deploy any number of applications for your users.
3.3 You are authorized to modify the source code available in the software to meet your user's requirements without releasing the modified codes.
3.4 You are authorized to provide the modified codes to your users in either source code or binary.
3.5 You must keep all the indications of the software when providing applications to your users.
3.6 None of the indications of the software may be removed, hidden or obscured in any way when you provide applications to your users.
4. Online service
4.1 You are authorized to use the software to build your online service for your users in any way you like.
4.2 You are authorized to use the software to build your online service for any number of your users.
4.3 You are authorized to modify the source codes available in the software to meet your user's requirements on online service without releasing the modified codes.
4.4 You must notify your users clearly that your service is based on the software when you use it to build your online service.
4.5 You must keep all the indications of the software when providing online service to your users.
4.6 You must keep all the indications of the software in any application you make for your users. None of the indications can be hidden or obscured in any way.
4.7 You are forbidden from assisting your users by providing tools for your users to remove, hide or obscure any indication of the software when you use the software to build your online service.
5. Publish or integrate the software without modification
5.1 You are authorized to publish the software on your personal sites, cormpany official website or other third-party sites.
5.2 You are authorized to integrate the software with other systems, such as cloud virtual machine images, operating system images and so on.
5.3 Do not modify the source code available in the software when you publish or integrate it.
5.4 All indications of the software must be kept the same when you publish or integrate the software.
6. Publish derived work based on the software
6.1 You are authorized to develop derived work based on the software.
6.2 The modified codes of the software in your derived work must follow the following terms:
6.2.1 The source code available in the software must be released if you make any modification to the software.
6.2.2 All indications of the software must be kept the same.
6.2.3 You are entitled to add your indications to the modified codes.
6.2.4 You are entitled to charge fees for the derived work you developed based on the software.
6.2.5 You agree to authorize third party users to modify and release the derived work in compliance with 6.2.
6.3 If the codes of the work are independently developed by yourself, you are authorized to release the work in either source code form or binary. You are entitled to charge your users or make it free.
6.4 None of the indications of the software can be removed, hidden or obscured in any way in the derived work you developed.
7. Publish applications based on API of the software
7.1 You are authorized to develop your applications based on the API of the software, for example, client software.
7.2 You are authorized to publish applications you developed based on the API in either source code or binary.
7.3 You are authorized to use your license to release applications you developed based on the API.
7.4 You are entitled to release applications you developed based on the API either free or with a charge.
8. Exceptions
If the terms above do not meet your requirements when using the software, please contact me for a more flexible license.
9. Termination
9.1 Violation of any of the terms of the agreement will result in immediate termination of this license. I reserve all rights to take legal actions in case of any dispute.
背景:
自理查德·马修·斯托曼先生发起自由软件运动以来,自由软件及开源软件蓬勃发展,为人类文明发展起到
了巨大的作用。但时至今日以云计算厂商为代表的ToB类公司崛起利用开源软件多于回馈甚至不乏侵权等
各种破坏开源软件游戏规则的行为。为此诸多知名开源软件团队纷纷采用自己的方法来阻止这些行为,诸如:
https://mariadb.com/bsl11/
https://redislabs.com/community/licenses/
https://www.confluent.io/confluent-community-license
https://www.mongodb.com/licensing/server-side-public-license
但以上诸公司自拟的许可协议引起以OSI为马首是瞻的社区口诛笔伐攻击他们非开源软件协议因其未经过
OSI许可。但无视开源软件开发者生存维艰之事实空谈开源正确解决不了问题。唯有在解决自身生存前提下
方能持续更新维护软件。我们相信:
凡有助于他人的软件,无论其规模大小、功能完善程度、许可协议、源码开放程度,均值得肯定敬佩;
凡有助于作者完善软件的行为,无论其形式、参与度、先后、持续时间、贡献大小,均值得鼓励感谢;
藉此,我们拟定该开放软件(区别于开源软件)协议,以期抛砖引玉,寻求开放和商业之间的平衡点。
ZENTAO OPEN SOFTWARE LICENSE 1.0
许可:
ZENTAO OPEN SOFTWARE LICENSE 由禅道软件青岛有限公司ZenTao Software (Qingdao) Co., Ltd.起草简称ZOSL协议。
任何人均可使用该协议来发布软件,并可对下面协议正文中以下划线标注的空白部分做相应修改,
除此之外的任何内容不得做任何修改。禅道软件(青岛)有限公司拥有对该协议条款的最终解释权。
前言:
喧喧聊天软件(以下简称该软件)由 禅道软件青岛有限公司ZenTao Software (Qingdao) Co., Ltd.)开发(以下简称我)。我依法拥有该软件的所有版权。
本着共享开放的角度,我以开放软件的形式发布该软件。您可以在遵守该协议的前提下使用该软件。
自您安装该软件开始,您和我之间的合同关系自动成立。除非您停止使用该软件或与我有签署额外合同,
您须认真遵循该授权协议约定的每一条款。
我的联系方式:
联系人:徐先生
电话: 4006-8899-23
Email co@cnezsoft.com
QQ 1492153927
地址: 山东省青岛市黄岛区长江西路118号青铁广场18楼
约定:
下述条款中所指该软件的标志包括如下方面:
该软件源代码及文档中关于该软件的版权提示、文字、图片和链接。
该软件运行时界面上呈现出来的有关该软件的文字、图片和链接。
不包括如下方面:
该软件提供的演示数据中关于该软件的文字、图片和链接。
一、免责
该软件是以开放软件的方式发行,您使用该软件无需任何费用,因此在使用该软件前,您须知晓:
1.1 我没有对该软件提供任何技术支持的义务,您可联系我购买商业的技术支持。
1.2 我对因使用该软件而产生直接或间接的任何问题不负任何责任。
1.3 开放不等于免费,开放不等于无版权,开放软件的发展需要您我共同的努力。
二、自用该软件
2.1 您个人或您就职的公司(组织)可自由使用该软件,我不对您或您就职公司(组织)的性质做任何限制。
2.2 您可以在您个人或您就职公司(组织)任意数量的电脑上运行该软件,我不对电脑的数量做任何限制。
2.3 您可以对该软件开放的源代码进行修改以适应您个人或您所在公司(组织)使用的要求,您做的改动无需对外发布。
2.4 您个人或您就职公司(组织)使用该软件时,必须保留该软件的所有标志,不得以任何方式隐藏或遮掩任一标志。
三、为用户定制
3.1 您可以使用该软件为您的用户部署各种形式的应用,我不对应用的性质做任何限制。
3.2 您可以使用该软件为您的用户部署任意数量的应用,我不对应用的数量做任何限制。
3.3 您可以对该软件开放的源代码进行修改以适应您的用户的要求,您做的改动无需对外发布。
3.4 您对该软件开放的源代码所做的修改可以源代码或二进制的方式提供给您的用户。
3.5 您使用该软件为您的任一用户部署的任一应用都必须保留该软件所有的标志。
3.6 您使用该软件为您的任一用户部署的任一应用都不得以任何方式隐藏或遮掩该软件任一标志。
四、提供在线服务
4.1 您可以使用该软件搭建在线服务,为您的用户提供服务,我不对该服务及该服务用户的性质做任何限制。
4.2 您可以使用该软件搭建在线服务,为您的用户提供服务,我不对该服务的用户数量做任何限制。
4.3 您可以对该软件开放的源代码进行修改以适应在线服务的要求,您做的改动无需对外发布。
4.4 您使用该软件搭建在线服务时,必须以明确的方式告知您的用户该服务是基于该软件搭建的。
4.5 您使用该软件搭建在线服务为您的任一用户部署的任一应用必须保留该软件所有的标志。
4.6 您使用该软件搭建在线服务为您的任一用户部署的任一应用不得以任何方式隐藏或遮掩该软件任一标志。
4.7 您使用该软件搭建在线服务时,不得为您的用户提供去除、隐藏或遮掩该软件任一标志的功能。
五、无改动发布或集成该软件
5.1 我欢迎并感谢您将该软件发布在您的个人网站、企业官网或者其他的第三方网站。
5.2 我欢迎并感谢您将该软件集成在其他系统中一起发布,比如云服务镜像、操作系统发行版等。
5.3 您在发布或者集成该软件的时候,不得对该软件开放的源码做任何改动。
5.4 您在发布或者集成该软件的时候,须保留该软件的所有标志。
六、发布基于该软件的衍生作品
6.1 我欢迎并感谢您为该软件开发衍生作品。
6.2 您开发的衍生作品中涉及到对该软件开放的源代码改动的地方,须遵循如下条款:
6.2.1 如修改了该软件的源代码,须依据本协议发布修改后的源代码。
6.2.2 如修改了该软件的源代码,须保留代码里面该软件原有的所有标志。
6.2.3 您可以在代码中追加您自己的标志。
6.2.4 您可以对您开发的衍生作品进行收费。
6.2.5 第三方的用户可在遵循6.2所有条款下可继续在您开发的衍生作品基础上进行修改并发布。
6.3 您开发的衍生作品中独立于本软件开发的代码,可以源代码或二进制的方式进行发布,可免费或收费发布。
6.4 您开发的衍生作品不得以任何方式去除、隐藏或遮掩该软件的任一标志。
七、发布基于该软件API的应用
7.1 我欢迎并感谢您为该软件开发基于API的各种应用比如客户端软件等。
7.2 您基于该软件API机制开发的应用可以源代码或者二进制的方式进行发布我对此没有任何限制。
7.3 您基于该软件API机制开发的应用授权协议可以自行约定我对此没有任何限制。
7.4 您基于该软件API机制开发的应用可以免费或者收费发布我对此没有任何限制。
八、授权例外
如果上述条款无法满足您使用该软件的要求,可联系我签署额外的合同以获得更灵活的授权许可。
九、合同约束
9.1 如果您违反了该协议的任一条款,该授权协议将自动终止,我保留通过法律手段追究责任的权利。

249
doc/LICENSE.zh_CN Normal file
View File

@ -0,0 +1,249 @@
背景:
自理查德·马修·斯托曼先生发起自由软件运动以来,自由软件及开源软件蓬勃发展,为人类文明发展起到
了巨大的作用。但时至今日以云计算厂商为代表的ToB类公司崛起利用开源软件多于回馈甚至不乏侵权等
各种破坏开源软件游戏规则的行为。为此诸多知名开源软件团队纷纷采用自己的方法来阻止这些行为,诸如:
https://mariadb.com/bsl11/
https://redislabs.com/community/licenses/
https://www.confluent.io/confluent-community-license
https://www.mongodb.com/licensing/server-side-public-license
但以上诸公司自拟的许可协议引起以OSI为马首是瞻的社区口诛笔伐攻击他们非开源软件协议因其未经过
OSI许可。但无视开源软件开发者生存维艰之事实空谈开源正确解决不了问题。唯有在解决自身生存前提下
方能持续更新维护软件。我们相信:
凡有助于他人的软件,无论其规模大小、功能完善程度、许可协议、源码开放程度,均值得肯定敬佩;
凡有助于作者完善软件的行为,无论其形式、参与度、先后、持续时间、贡献大小,均值得鼓励感谢;
藉此,我们拟定该开放软件(区别于开源软件)协议,以期抛砖引玉,寻求开放和商业之间的平衡点。
ZENTAO OPEN SOFTWARE LICENSE 1.0
许可:
ZENTAO OPEN SOFTWARE LICENSE 由禅道软件青岛有限公司ZenTao Software (Qingdao) Co., Ltd.起草简称ZOSL协议。
任何人均可使用该协议来发布软件,并可对下面协议正文中以下划线标注的空白部分做相应修改,
除此之外的任何内容不得做任何修改。禅道软件(青岛)有限公司拥有对该协议条款的最终解释权。
前言:
喧喧聊天软件(以下简称该软件)由 禅道软件青岛有限公司ZenTao Software (Qingdao) Co., Ltd.)开发(以下简称我)。我依法拥有该软件的所有版权。
本着共享开放的角度,我以开放软件的形式发布该软件。您可以在遵守该协议的前提下使用该软件。
自您安装该软件开始,您和我之间的合同关系自动成立。除非您停止使用该软件或与我有签署额外合同,
您须认真遵循该授权协议约定的每一条款。
我的联系方式:
联系人:徐先生
电话: 4006-8899-23
Email co@cnezsoft.com
QQ 1492153927
地址: 山东省青岛市黄岛区长江西路118号青铁广场18楼
约定:
下述条款中所指该软件的标志包括如下方面:
该软件源代码及文档中关于该软件的版权提示、文字、图片和链接。
该软件运行时界面上呈现出来的有关该软件的文字、图片和链接。
不包括如下方面:
该软件提供的演示数据中关于该软件的文字、图片和链接。
一、免责
该软件是以开放软件的方式发行,您使用该软件无需任何费用,因此在使用该软件前,您须知晓:
1.1 我没有对该软件提供任何技术支持的义务,您可联系我购买商业的技术支持。
1.2 我对因使用该软件而产生直接或间接的任何问题不负任何责任。
1.3 开放不等于免费,开放不等于无版权,开放软件的发展需要您我共同的努力。
二、自用该软件
2.1 您个人或您就职的公司(组织)可自由使用该软件,我不对您或您就职公司(组织)的性质做任何限制。
2.2 您可以在您个人或您就职公司(组织)任意数量的电脑上运行该软件,我不对电脑的数量做任何限制。
2.3 您可以对该软件开放的源代码进行修改以适应您个人或您所在公司(组织)使用的要求,您做的改动无需对外发布。
2.4 您个人或您就职公司(组织)使用该软件时,必须保留该软件的所有标志,不得以任何方式隐藏或遮掩任一标志。
三、为用户定制
3.1 您可以使用该软件为您的用户部署各种形式的应用,我不对应用的性质做任何限制。
3.2 您可以使用该软件为您的用户部署任意数量的应用,我不对应用的数量做任何限制。
3.3 您可以对该软件开放的源代码进行修改以适应您的用户的要求,您做的改动无需对外发布。
3.4 您对该软件开放的源代码所做的修改可以源代码或二进制的方式提供给您的用户。
3.5 您使用该软件为您的任一用户部署的任一应用都必须保留该软件所有的标志。
3.6 您使用该软件为您的任一用户部署的任一应用都不得以任何方式隐藏或遮掩该软件任一标志。
四、提供在线服务
4.1 您可以使用该软件搭建在线服务,为您的用户提供服务,我不对该服务及该服务用户的性质做任何限制。
4.2 您可以使用该软件搭建在线服务,为您的用户提供服务,我不对该服务的用户数量做任何限制。
4.3 您可以对该软件开放的源代码进行修改以适应在线服务的要求,您做的改动无需对外发布。
4.4 您使用该软件搭建在线服务时,必须以明确的方式告知您的用户该服务是基于该软件搭建的。
4.5 您使用该软件搭建在线服务为您的任一用户部署的任一应用必须保留该软件所有的标志。
4.6 您使用该软件搭建在线服务为您的任一用户部署的任一应用不得以任何方式隐藏或遮掩该软件任一标志。
4.7 您使用该软件搭建在线服务时,不得为您的用户提供去除、隐藏或遮掩该软件任一标志的功能。
五、无改动发布或集成该软件
5.1 我欢迎并感谢您将该软件发布在您的个人网站、企业官网或者其他的第三方网站。
5.2 我欢迎并感谢您将该软件集成在其他系统中一起发布,比如云服务镜像、操作系统发行版等。
5.3 您在发布或者集成该软件的时候,不得对该软件开放的源码做任何改动。
5.4 您在发布或者集成该软件的时候,须保留该软件的所有标志。
六、发布基于该软件的衍生作品
6.1 我欢迎并感谢您为该软件开发衍生作品。
6.2 您开发的衍生作品中涉及到对该软件开放的源代码改动的地方,须遵循如下条款:
6.2.1 如修改了该软件的源代码,须依据本协议发布修改后的源代码。
6.2.2 如修改了该软件的源代码,须保留代码里面该软件原有的所有标志。
6.2.3 您可以在代码中追加您自己的标志。
6.2.4 您可以对您开发的衍生作品进行收费。
6.2.5 第三方的用户可在遵循6.2所有条款下可继续在您开发的衍生作品基础上进行修改并发布。
6.3 您开发的衍生作品中独立于本软件开发的代码,可以源代码或二进制的方式进行发布,可免费或收费发布。
6.4 您开发的衍生作品不得以任何方式去除、隐藏或遮掩该软件的任一标志。
七、发布基于该软件API的应用
7.1 我欢迎并感谢您为该软件开发基于API的各种应用比如客户端软件等。
7.2 您基于该软件API机制开发的应用可以源代码或者二进制的方式进行发布我对此没有任何限制。
7.3 您基于该软件API机制开发的应用授权协议可以自行约定我对此没有任何限制。
7.4 您基于该软件API机制开发的应用可以免费或者收费发布我对此没有任何限制。
八、授权例外
如果上述条款无法满足您使用该软件的要求,可联系我签署额外的合同以获得更灵活的授权许可。
九、合同约束
9.1 如果您违反了该协议的任一条款,该授权协议将自动终止,我保留通过法律手段追究责任的权利。
Background
Since Richard Matthew Stallmans Free Software Movement, free software and open source software have been booming. It has played
a huge role in human civilization. However, open source software is exploited by the rising To-Business companies,
especially cloud computing ones. They take more than what they give back, and even breach open source consensus, such as infringement.
Hence, some open source software teams have to take actions to stop this, e.g.
https://mariadb.com/bsl11/
https://redislabs.com/community/licenses/
https://www.confluent.io/confluent-community-license
https://www.mongodb.com/licensing/server-side-public-license
However, those licenses are condemned by the community who follow the lead of OSI(Open Source Initiative) for not being approved by OSI.
Only talking about being open source but ignoring the struggling open source developers will not solve the problem for those developers.
Only under the premised of their survival, can open source software developers keep maintaining open source software. Hence, we believe that,
Any software that helps others, no matter what its size, functions, license, or open source percentage is, should be respected;
Any behavior that helps the developers, no matter what its form, participation, succession, duration, should be encouraged and appreciated.
Therefore, ZENTAO OPEN SOFTWARE LICENSE 1.0, different from open source, is drafted to seek a balance between being open and being commercial.
ZENTAO OPEN SOFTWARE LICENSE 1.0
Authorization
ZENTAO OPEN SOFTWARE LICENSE, also known as ZOSL Agreement, is drafted by ZenTao Software (Qingdao) Co., Ltd. (ZenTao Software (Qingdao) Co., Ltd.).
Anyone can use the agreement to publish open software by editing the blank underlined part of the following text of the agreement accordingly.
No other text of the agreement shall be changed. ZenTao Software (Qingdao) Co., Ltd. has the final interpretation of the terms in the agreement.
Preface
Xuanxuan (Hereinafter referred to as "the software") developed by ZenTao Software (Qingdao) Co., Ltd. (ZenTao Software (Qingdao) Co., Ltd.) (hereinafter referred to "I"). I am entitled to all copyrights of the software.
The software is released as open source software. You are authorized to use the software as long as you are in compliance with this agreement.
By the installation of the software, you agree that a contractual relationship between you and me is automatically established.
You are obliged to fully comply with all the terms of this agreement unless you choose to stop using the software or you have signed additional contracts with me.
My Contact:
Contact: Mr. Xu
Phone: 4006-8899-23
Email: co@cnezsoft.com
QQ: 1492153927
Address: Room 2902, Unit 2, Block C, International Trade Center, Kai Fa Qu, Qingdao
You and I agree:
Indications of the software include:
Notes, texts, pictures and links showing copyright attribution of the software in the source code and related documentation.
and texts, picture and links on the interface of the software when running.
Excluding
texts, picture and links on the interface of the demo versions of the software.
1. Disclaimer
The software is open software, so you are authorized to use the software without paying a fee. Before you start to use it, please note:
1.1 I do not have any obligation to provide technical support for the software. You can contact me to purchase technical support.
1.2 I am not responsible for any liability caused by your using the software directly or indirectly.
1.3 Open software does not mean it is free of charge, neither does it mean the software does not have any copyright.
2. For personal use
2.1 You or your company/organization are authorized to use the software for your internal use for both commercial and non-commercial purposes.
2.2 You or your company/organization are authorized to run the software on any number of computers.
2.3 You or your company/organization are authorized to modify the source code available in the software to meet your requirements. You do not need to release the modified codes.
2.4 You or your company/organization must keep all the indications of the software when using it. None of the indications can be removed, hidden or obscured in any way.
3. For customized software
3.1 You are authorized to use the software to deploy various forms of application for your users in any way you like.
3.2 You are authorized to use the software to deploy any number of applications for your users.
3.3 You are authorized to modify the source code available in the software to meet your user's requirements without releasing the modified codes.
3.4 You are authorized to provide the modified codes to your users in either source code or binary.
3.5 You must keep all the indications of the software when providing applications to your users.
3.6 None of the indications of the software may be removed, hidden or obscured in any way when you provide applications to your users.
4. Online service
4.1 You are authorized to use the software to build your online service for your users in any way you like.
4.2 You are authorized to use the software to build your online service for any number of your users.
4.3 You are authorized to modify the source codes available in the software to meet your user's requirements on online service without releasing the modified codes.
4.4 You must notify your users clearly that your service is based on the software when you use it to build your online service.
4.5 You must keep all the indications of the software when providing online service to your users.
4.6 You must keep all the indications of the software in any application you make for your users. None of the indications can be hidden or obscured in any way.
4.7 You are forbidden from assisting your users by providing tools for your users to remove, hide or obscure any indication of the software when you use the software to build your online service.
5. Publish or integrate the software without modification
5.1 You are authorized to publish the software on your personal sites, cormpany official website or other third-party sites.
5.2 You are authorized to integrate the software with other systems, such as cloud virtual machine images, operating system images and so on.
5.3 Do not modify the source code available in the software when you publish or integrate it.
5.4 All indications of the software must be kept the same when you publish or integrate the software.
6. Publish derived work based on the software
6.1 You are authorized to develop derived work based on the software.
6.2 The modified codes of the software in your derived work must follow the following terms:
6.2.1 The source code available in the software must be released if you make any modification to the software.
6.2.2 All indications of the software must be kept the same.
6.2.3 You are entitled to add your indications to the modified codes.
6.2.4 You are entitled to charge fees for the derived work you developed based on the software.
6.2.5 You agree to authorize third party users to modify and release the derived work in compliance with 6.2.
6.3 If the codes of the work are independently developed by yourself, you are authorized to release the work in either source code form or binary. You are entitled to charge your users or make it free.
6.4 None of the indications of the software can be removed, hidden or obscured in any way in the derived work you developed.
7. Publish applications based on API of the software
7.1 You are authorized to develop your applications based on the API of the software, for example, client software.
7.2 You are authorized to publish applications you developed based on the API in either source code or binary.
7.3 You are authorized to use your license to release applications you developed based on the API.
7.4 You are entitled to release applications you developed based on the API either free or with a charge.
8. Exceptions
If the terms above do not meet your requirements when using the software, please contact me for a more flexible license.
9. Termination
9.1 Violation of any of the terms of the agreement will result in immediate termination of this license. I reserve all rights to take legal actions in case of any dispute.

1
doc/README Normal file
View File

@ -0,0 +1 @@
please see http://xuan.im

3
doc/README.zh_CN Normal file
View File

@ -0,0 +1,3 @@
关于喧喧
由然之协同推出的一款免费、开源、安全、跨平台的即时通信解决方案

0
doc/index.html Normal file
View File

View File

@ -0,0 +1,887 @@
<?php /**
* ZenTaoPHP的baseControl类。
* The baseControl class file of ZenTaoPHP framework.
*
* @package framework
*
* The author disclaims copyright to this source code. In place of
* a legal notice, here is a blessing:
*
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
*/
class baseControl
{
/**
* 全局对象 $app。
* The global $app object.
*
* @var object
* @access public
*/
public $app;
/**
* 应用名称 $appName
* The global $appName.
*
* @var string
* @access public
*/
public $appName;
/**
* 全局对象 $config。
* The global $config object.
*
* @var object
* @access public
*/
public $config;
/**
* 全局对象 $lang。
* The global $lang object.
*
* @var object
* @access public
*/
public $lang;
/**
* 全局对象 $dbh数据库连接句柄。
* The global $dbh object, the database connection handler.
*
* @var object
* @access public
*/
public $dbh;
/**
* $dao对象实现sql的拼装和执行。
* The $dao object, used to join sql and excute sql.
*
* @var object
* @access public
*/
public $dao;
/**
* $post对象用户可以通过$this->post->key来引用$_POST变量。
* The $post object, useer can access a post var by $this->post->key.
*
* @var object
* @access public
*/
public $post;
/**
* $get对象用户可以通过$this->get->key来引用$_GET变量。
* The $get object, useer can access a get var by $this->get->key.
*
* @var object
* @access public
*/
public $get;
/**
* $session对象用户可以通过$this->session->key来引用$_SESSION变量。
* The $session object, useer can access a session var by $this->session->key.
*
* @var object
* @access public
*/
public $session;
/**
* $server对象用户可以通过$this->server->key来引用$_SERVER变量。
* The $server object, useer can access a server var by $this->server->key.
*
* @var object
* @access public
*/
public $server;
/**
* $cookie对象用户可以通过$this->cookie->key来引用$_COOKIE变量。
* The $cookie object, useer can access a cookie var by $this->cookie->key.
*
* @var object
* @access public
*/
public $cookie;
/**
* 当前模块的名称。
* The name of current module.
*
* @var string
* @access public
*/
public $moduleName;
/**
* $view用于存放从control传到view视图的数据。
* The vars assigned to the view page.
*
* @var object
* @access public
*/
public $view;
/**
* 视图的类型比如html, json。
* The type of the view, such html, json.
*
* @var string
* @access public
*/
public $viewType;
/**
* 输出到浏览器的内容。
* The content to display.
*
* @var string
* @access public
*/
public $output;
/**
* 客户端设备。
* The client device.
*
* @var string
* @access public
*/
public $clientDevice;
/**
* 不同设备下视图文件的前缀。
* The prefix of view file for mobile or PC.
*
* @var string
* @access public
*/
public $devicePrefix;
/**
* 构造方法。
*
* 1. 将全局变量设为baseControl类的成员变量方便baseControl的派生类调用
* 2. 设置当前模块读取该模块的model类
* 3. 初始化$view视图类。
*
* The construct function.
*
* 1. global the global vars, refer them by the class member such as $this->app.
* 2. set the pathes of current module, and load it's model class.
* 3. auto assign the $lang and $config to the view.
*
* @param string $moduleName
* @param string $methodName
* @param string $appName
* @access public
* @return void
*/
public function __construct($moduleName = '', $methodName = '', $appName = '')
{
/*
* 将全局变量设为baseControl类的成员变量方便baseControl的派生类调用。
* Global the globals, and refer them as a class member.
*/
global $app, $config, $lang, $dbh, $common;
$this->app = $app;
$this->config = $config;
$this->lang = $lang;
$this->dbh = $dbh;
$this->viewType = $this->app->getViewType();
$this->appName = $appName ? $appName : $this->app->getAppName();
/**
* 设置当前模块读取该模块的model类。
* Load the model file auto.
*/
$this->setModuleName($moduleName);
$this->setMethodName($methodName);
$this->loadModel($this->moduleName, $appName);
/**
* 如果客户端是手机的话视图文件增加m.前缀。
* If the clent is mobile, add m. as prefix for view file.
*/
$this->setClientDevice();
$this->setDevicePrefix();
/**
* 初始化$view视图类。
* Init the view vars.
*/
$this->view = new stdclass();
$this->view->app = $app;
$this->view->lang = $lang;
$this->view->config = $config;
$this->view->common = $common;
$this->view->title = '';
/**
* 设置超级变量,从$app引用过来。
* Set super vars.
*/
$this->setSuperVars();
}
//-------------------- Model相关方法(Model related methods) --------------------//
/*
* 设置模块名。
* Set the module name.
*
* @param string $moduleName 模块名,如果为空,则从$app中获取. The module name, if empty, get it from $app.
* @access public
* @return void
*/
public function setModuleName($moduleName = '')
{
$this->moduleName = $moduleName ? strtolower($moduleName) : $this->app->getModuleName();
}
/**
* 设置方法名。
* Set the method name.
*
* @param string $methodName 方法名,如果为空,则从$app中获取。The method name, if empty, get it from $app.
* @access public
* @return void
*/
public function setMethodName($methodName = '')
{
$this->methodName = $methodName ? strtolower($methodName) : $this->app->getMethodName();
}
/**
* 加载指定模块的model文件。
* Load the model file of one module.
*
* @param string $moduleName 模块名如果为空使用当前模块。The module name, if empty, use current module's name.
* @param string $appName The app name, if empty, use current app's name.
* @access public
* @return object|bool 如果没有model文件返回false否则返回model对象。If no model file, return false, else return the model object.
*/
public function loadModel($moduleName = '', $appName = '')
{
if(empty($moduleName)) $moduleName = $this->moduleName;
if(empty($appName)) $appName = $this->appName;
global $loadedModels;
if(isset($loadedModels[$appName][$moduleName]))
{
$this->$moduleName = $loadedModels[$appName][$moduleName];
$this->dao = $this->$moduleName->dao;
return $this->$moduleName;
}
$modelFile = $this->app->setModelFile($moduleName, $appName);
/**
* 如果没有model文件尝试加载config配置信息。
* If no model file, try load config.
*/
if(!helper::import($modelFile))
{
$this->app->loadModuleConfig($moduleName, $appName);
$this->app->loadLang($moduleName, $appName);
$this->dao = new dao();
return false;
}
/**
* 如果没有扩展文件model类名是$moduleName + 'model'如果有扩展还需要增加ext前缀。
* If no extension file, model class name is $moduleName + 'model', else with 'ext' as the prefix.
*/
$modelClass = class_exists('ext' . $appName . $moduleName. 'model') ? 'ext' . $appName . $moduleName . 'model' : $appName . $moduleName . 'model';
if(!class_exists($modelClass))
{
$modelClass = class_exists('ext' . $moduleName. 'model') ? 'ext' . $moduleName . 'model' : $moduleName . 'model';
if(!class_exists($modelClass)) $this->app->triggerError(" The model $modelClass not found", __FILE__, __LINE__, $exit = true);
}
/**
* 初始化model对象在control对象中可以通过$this->$moduleName来引用。同时将dao对象赋为control对象的成员变量方便引用。
* Init the model object thus you can try $this->$moduleName to access it. Also assign the $dao object as a member of control object.
*/
$loadedModels[$appName][$moduleName] = new $modelClass($appName);
$this->$moduleName = $loadedModels[$appName][$moduleName];
$this->dao = $this->$moduleName->dao;
return $this->$moduleName;
}
/**
* 设置超级全局变量,方便直接引用。
* Set the super vars.
*
* @access public
* @return void
*/
public function setSuperVars()
{
$this->post = $this->app->post;
$this->get = $this->app->get;
$this->server = $this->app->server;
$this->session = $this->app->session;
$this->cookie = $this->app->cookie;
}
/**
* 设置客户端的设备类型。
* Set client device.
*
* @access public
* @return void
*/
public function setClientDevice()
{
$this->clientDevice = $this->app->clientDevice;
}
/**
* 如果客户端是手机的话视图文件增加m.前缀。
* If the clent is mobile, add m. as prefix for view file.
*
* @access public
* @return void
*/
public function setDevicePrefix()
{
$this->devicePrefix = zget($this->config->devicePrefix, $this->viewType, '');
}
//-------------------- 视图相关方法(View related methods) --------------------//
/**
* 设置视图文件:主视图文件,扩展视图文件, 站点扩展视图文件,以及钩子脚本。
* Set view files: the main file, extension view file, site extension view file and hook files.
*
* @param string $moduleName module name
* @param string $methodName method name
* @access public
* @return string the view file
*/
public function setViewFile($moduleName, $methodName)
{
$moduleName = strtolower(trim($moduleName));
$methodName = strtolower(trim($methodName));
$modulePath = $this->app->getModulePath($this->appName, $moduleName);
$viewExtPath = $this->app->getModuleExtPath($this->appName, $moduleName, 'view');
$viewType = $this->viewType == 'mhtml' ? 'html' : $this->viewType;
$mainViewFile = $modulePath . 'view' . DS . $this->devicePrefix . $methodName . '.' . $viewType . '.php';
$viewFile = $mainViewFile;
if(!empty($viewExtPath))
{
$commonExtViewFile = $viewExtPath['common'] . $this->devicePrefix . $methodName . ".{$viewType}.php";
$siteExtViewFile = empty($viewExtPath['site']) ? '' : $viewExtPath['site'] . $this->devicePrefix . $methodName . ".{$viewType}.php";
$viewFile = file_exists($commonExtViewFile) ? $commonExtViewFile : $mainViewFile;
$viewFile = (!empty($siteExtViewFile) and file_exists($siteExtViewFile)) ? $siteExtViewFile : $viewFile;
if(!is_file($viewFile)) $this->app->triggerError("the view file $viewFile not found", __FILE__, __LINE__, $exit = true);
$commonExtHookFiles = glob($viewExtPath['common'] . $this->devicePrefix . $methodName . ".*.{$viewType}.hook.php");
$siteExtHookFiles = empty($viewExtPath['site']) ? '' : glob($viewExtPath['site'] . $this->devicePrefix . $methodName . ".*.{$viewType}.hook.php");
$extHookFiles = array_merge((array) $commonExtHookFiles, (array) $siteExtHookFiles);
}
if(!empty($extHookFiles)) return array('viewFile' => $viewFile, 'hookFiles' => $extHookFiles);
return $viewFile;
}
/**
* 获取某一个视图文件的扩展。
* Get the extension file of an view.
*
* @param string $viewFile
* @access public
* @return string|bool If extension view file exists, return the path. Else return fasle.
*/
public function getExtViewFile($viewFile)
{
/**
* 首先找sitecode下的扩展文件如果没有再找ext下的扩展文件。
* Find extViewFile in ext/_$siteCode/view first, then try ext/view/.
*/
if($this->app->siteCode)
{
$extPath = dirname(dirname(realpath($viewFile))) . "/ext/_{$this->app->siteCode}/view";
$extViewFile = $extPath . basename($viewFile);
if(file_exists($extViewFile))
{
helper::cd($extPath);
return $extViewFile;
}
}
$extPath = dirname(dirname(realpath($viewFile))) . '/ext/view/';
$extViewFile = $extPath . basename($viewFile);
if(file_exists($extViewFile))
{
helper::cd($extPath);
return $extViewFile;
}
return false;
}
/**
* 获取适用于当前方法的css该模块公用的css + 当前方法的css + 扩展的css。
* Get css codes applied to current method: module common css + method css + extension css.
*
* @param string $moduleName
* @param string $methodName
* @access public
* @return string
*/
public function getCSS($moduleName, $methodName)
{
$moduleName = strtolower(trim($moduleName));
$methodName = strtolower(trim($methodName));
$modulePath = $this->app->getModulePath($this->appName, $moduleName);
$cssExtPath = $this->app->getModuleExtPath($this->appName, $moduleName, 'css') ;
$css = '';
$mainCssFile = $modulePath . 'css' . DS . $this->devicePrefix . 'common.css';
$methodCssFile = $modulePath . 'css' . DS . $this->devicePrefix . $methodName . '.css';
if(file_exists($mainCssFile)) $css .= file_get_contents($mainCssFile);
if(is_file($methodCssFile)) $css .= file_get_contents($methodCssFile);
if(!empty($cssExtPath))
{
$cssMethodExt = $cssExtPath['common'] . $methodName . DS;
$cssCommonExt = $cssExtPath['common'] . 'common' . DS;
$cssExtFiles = glob($cssCommonExt . $this->devicePrefix . '*.css');
if(!empty($cssExtFiles) and is_array($cssExtFiles)) foreach($cssExtFiles as $cssFile) $css .= file_get_contents($cssFile);
$cssExtFiles = glob($cssMethodExt . $this->devicePrefix . '*.css');
if(!empty($cssExtFiles) and is_array($cssExtFiles)) foreach($cssExtFiles as $cssFile) $css .= file_get_contents($cssFile);
if(!empty($cssExtPath['site']))
{
$cssMethodExt = $cssExtPath['site'] . $methodName . DS;
$cssCommonExt = $cssExtPath['site'] . 'common' . DS;
$cssExtFiles = glob($cssCommonExt . $this->devicePrefix . '*.css');
if(!empty($cssExtFiles) and is_array($cssExtFiles)) foreach($cssExtFiles as $cssFile) $css .= file_get_contents($cssFile);
$cssExtFiles = glob($cssMethodExt . $this->devicePrefix . '*.css');
if(!empty($cssExtFiles) and is_array($cssExtFiles)) foreach($cssExtFiles as $cssFile) $css .= file_get_contents($cssFile);
}
}
return $css;
}
/**
* 获取适用于当前方法的js该模块公用的js + 当前方法的js + 扩展的js。
* Get js codes applied to current method: module common js + method js + extension js.
*
* @param string $moduleName
* @param string $methodName
* @access public
* @return string
*/
public function getJS($moduleName, $methodName)
{
$moduleName = strtolower(trim($moduleName));
$methodName = strtolower(trim($methodName));
$modulePath = $this->app->getModulePath($this->appName, $moduleName);
$jsExtPath = $this->app->getModuleExtPath($this->appName, $moduleName, 'js');
$js = '';
$mainJsFile = $modulePath . 'js' . DS . $this->devicePrefix . 'common.js';
$methodJsFile = $modulePath . 'js' . DS . $this->devicePrefix . $methodName . '.js';
if(file_exists($mainJsFile)) $js .= file_get_contents($mainJsFile);
if(is_file($methodJsFile)) $js .= file_get_contents($methodJsFile);
if(!empty($jsExtPath))
{
$jsMethodExt = $jsExtPath['common'] . $methodName . DS;
$jsCommonExt = $jsExtPath['common'] . 'common' . DS;
$jsExtFiles = glob($jsCommonExt . $this->devicePrefix . '*.js');
if(!empty($jsExtFiles) and is_array($jsExtFiles)) foreach($jsExtFiles as $jsFile) $js .= file_get_contents($jsFile);
$jsExtFiles = glob($jsMethodExt . $this->devicePrefix . '*.js');
if(!empty($jsExtFiles) and is_array($jsExtFiles)) foreach($jsExtFiles as $jsFile) $js .= file_get_contents($jsFile);
if(!empty($jsExtPath['site']))
{
$jsMethodExt = $jsExtPath['site'] . $methodName . DS;
$jsCommonExt = $jsExtPath['site'] . 'common' . DS;
$jsExtFiles = glob($jsCommonExt . $this->devicePrefix . '*.js');
if(!empty($jsExtFiles) and is_array($jsExtFiles)) foreach($jsExtFiles as $jsFile) $js .= file_get_contents($jsFile);
$jsExtFiles = glob($jsMethodExt . $this->devicePrefix . '*.js');
if(!empty($jsExtFiles) and is_array($jsExtFiles)) foreach($jsExtFiles as $jsFile) $js .= file_get_contents($jsFile);
}
}
return $js;
}
/**
* $view传递一个变量。
* Assign one var to the view vars.
*
* @param string $name the name.
* @param mixed $value the value.
* @access public
* @return void
*/
public function assign($name, $value)
{
$this->view->$name = $value;
}
/**
* 清空$output。
* Clear the output.
*
* @access public
* @return void
*/
public function clear()
{
$this->output = '';
}
/**
* 渲染视图文件。
* Parse view file.
*
* @param string $moduleName module name, if empty, use current module.
* @param string $methodName method name, if empty, use current method.
* @access public
* @return string the parsed result.
*/
public function parse($moduleName = '', $methodName = '')
{
if(empty($moduleName)) $moduleName = $this->moduleName;
if(empty($methodName)) $methodName = $this->methodName;
if($this->viewType == 'json') $this->parseJSON($moduleName, $methodName);
if($this->viewType != 'json') $this->parseDefault($moduleName, $methodName);
return $this->output;
}
/**
* 渲染json格式。
* Parse json format.
*
* @param string $moduleName module name
* @param string $methodName method name
* @access public
* @return void
*/
public function parseJSON($moduleName, $methodName)
{
unset($this->view->app);
unset($this->view->config);
unset($this->view->lang);
unset($this->view->header);
unset($this->view->position);
unset($this->view->moduleTree);
unset($this->view->common);
unset($this->view->pager->app);
unset($this->view->pager->lang);
$output['status'] = is_object($this->view) ? 'success' : 'fail';
$output['data'] = json_encode($this->view);
$output['md5'] = md5(json_encode($this->view));
$this->output = json_encode($output);
}
/**
* 默认渲染方法适用于viewType = html的时候。
* Default parse method when viewType != json, like html.
*
* @param string $moduleName module name
* @param string $methodName method name
* @access public
* @return void
*/
public function parseDefault($moduleName, $methodName)
{
/**
* 设置视图文件。(PHP7有一个bug不能直接$viewFile = $this->setViewFile())
* Set viewFile. (Can't assign $viewFile = $this->setViewFile() directly because one php7's bug.)
*/
$results = $this->setViewFile($moduleName, $methodName);
$viewFile = $results;
if(is_array($results)) extract($results);
/**
* 获得当前页面的CSS和JS。
* Get css and js codes for current method.
*/
$css = $this->getCSS($moduleName, $methodName);
$js = $this->getJS($moduleName, $methodName);
if($css) $this->view->pageCSS = $css;
if($js) $this->view->pageJS = $js;
/**
* 切换到视图文件所在的目录以保证视图文件里面的include语句能够正常运行。
* Change the dir to the view file to keep the relative pathes work.
*/
$currentPWD = getcwd();
chdir(dirname($viewFile));
/**
* 使用extract安定ob方法渲染$viewFile里面的代码。
* Use extract and ob functions to eval the codes in $viewFile.
*/
extract((array)$this->view);
ob_start();
include $viewFile;
if(isset($hookFiles)) foreach($hookFiles as $hookFile) if(file_exists($hookFile)) include $hookFile;
$this->output .= ob_get_contents();
ob_end_clean();
/**
* 渲染完毕后,再切换回之前的路径。
* At the end, chang the dir to the previous.
*/
chdir($currentPWD);
}
/**
* 获取一个方法的输出内容,这样我们可以在一个方法里获取其他模块方法的内容。
* 如果模块名为空,则调用该模块、该方法;如果设置了模块名,调用指定模块指定方法。
*
* Get the output of one module's one method as a string, thus in one module's method, can fetch other module's content.
* If the module name is empty, then use the current module and method. If set, use the user defined module and method.
*
* @param string $moduleName module name.
* @param string $methodName method name.
* @param array $params params.
* @access public
* @return string the parsed html.
*/
public function fetch($moduleName = '', $methodName = '', $params = array(), $appName = '')
{
/**
* 如果模块名为空,则调用该模块、该方法。
* If the module name is empty, then use the current module and method.
*/
if($moduleName == '') $moduleName = $this->moduleName;
if($methodName == '') $methodName = $this->methodName;
if($appName == '') $appName = $this->appName;
if($moduleName == $this->moduleName and $methodName == $this->methodName)
{
$this->parse($moduleName, $methodName);
return $this->output;
}
$currentModuleName = $this->moduleName;
$currentMethodName = $this->methodName;
$currentAppName = $this->appName;
$currentParams = $this->app->getParams();
/**
* 设置调用指定模块的指定方法。
* chang the dir to the previous.
*/
$this->app->setModuleName($moduleName);
$this->app->setMethodName($methodName);
if(!is_array($params)) parse_str($params, $params);
$this->app->params = $params;
$currentPWD = getcwd();
/**
* 设置引用的文件和路径。
* Set the pathes and files to included.
*/
$modulePath = $this->app->getModulePath($appName, $moduleName);
$moduleControlFile = $modulePath . 'control.php';
$actionExtPath = $this->app->getModuleExtPath($appName, $moduleName, 'control');
$file2Included = $moduleControlFile;
if(!empty($actionExtPath))
{
/**
* 设置公共扩展。
* set common extension.
*/
$commonActionExtFile = $actionExtPath['common'] . strtolower($methodName) . '.php';
$file2Included = file_exists($commonActionExtFile) ? $commonActionExtFile : $moduleControlFile;
if(!empty($actionExtPath['site']))
{
/**
* 设置站点扩展。
* every site has it's extension.
*/
$siteActionExtFile = $actionExtPath['site'] . strtolower($methodName) . '.php';
$file2Included = file_exists($siteActionExtFile) ? $siteActionExtFile : $file2Included;
}
}
/**
* 加载控制器文件。
* Load the control file.
*/
if(!is_file($file2Included)) $this->app->triggerError("The control file $file2Included not found", __FILE__, __LINE__, $exit = true);
chdir(dirname($file2Included));
if($moduleName != $this->moduleName) helper::import($file2Included);
/**
* 设置调用的类名。
* Set the name of the class to be called.
*/
$className = class_exists("my$moduleName") ? "my$moduleName" : $moduleName;
if(!class_exists($className)) $this->app->triggerError(" The class $className not found", __FILE__, __LINE__, $exit = true);
/**
* 解析参数创建模块control对象。
* Parse the params, create the $module control object.
*/
$module = new $className($moduleName, $methodName, $appName);
/**
* 调用对应方法使用ob方法获取输出内容。
* Call the method and use ob function to get the output.
*/
ob_start();
call_user_func_array(array($module, $methodName), $params);
$output = ob_get_contents();
ob_end_clean();
unset($module);
/**
* 切换回之前的模块和方法。
* Chang the module、method to the previous.
*/
$this->app->setModuleName($currentModuleName);
$this->app->setMethodName($currentMethodName);
$this->app->params = $currentParams;
chdir($currentPWD);
/**
* 返回内容。
* Return the content.
*/
return $output;
}
/**
* 向浏览器输出内容。
* Print the content of the view.
*
* @param string $moduleName module name
* @param string $methodName method name
* @access public
* @return void
*/
public function display($moduleName = '', $methodName = '')
{
if(empty($this->output)) $this->parse($moduleName, $methodName);
echo $this->output;
}
/**
* 直接输出data数据通常用于ajax请求中。
* Send data directly, for ajax requests.
*
* @param misc $data
* @param string $type
* @access public
* @return void
*/
public function send($data, $type = 'json')
{
if($type != 'json') die();
$data = (array) $data;
if(helper::isAjaxRequest() or $this->viewType == 'json') print(json_encode($data)) and die(helper::removeUTF8Bom(ob_get_clean()));
/**
* 响应非ajax的请求。
* Response request not ajax.
*/
if(isset($data['result']) and $data['result'] == 'success')
{
if(!empty($data['message'])) echo js::alert($data['message']);
$locate = isset($data['locate']) ? $data['locate'] : (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '');
if(!empty($locate)) die(js::locate($locate));
die(isset($data['message']) ? $data['message'] : 'success');
}
if(isset($data['result']) and $data['result'] == 'fail')
{
if(!empty($data['message']))
{
$message = json_decode(json_encode((array)$data['message']));
foreach((array)$message as $item => $errors) $message->$item = implode(',', $errors);
echo js::alert(strip_tags(implode(" ", (array) $message)));
die(js::locate('back'));
}
die('fail');
}
}
/**
* 创建一个模块方法的链接。
* Create a link to one method of one module.
*
* @param string $moduleName module name
* @param string $methodName method name
* @param string|array $vars the params passed, can be array(key=>value) or key1=value1&key2=value2
* @param string $viewType the view type
* @access public
* @return string the link string.
*/
public function createLink($moduleName, $methodName = 'index', $vars = array(), $viewType = '', $onlybody = false)
{
if(empty($moduleName)) $moduleName = $this->moduleName;
return helper::createLink($moduleName, $methodName, $vars, $viewType, $onlybody);
}
/**
* 创建当前模块的一个方法链接。
* Create a link to the inner method of current module.
*
* @param string $methodName method name
* @param string|array $vars the params passed, can be array(key=>value) or key1=value1&key2=value2
* @param string $viewType the view type
* @access public
* @return string the link string.
*/
public function inlink($methodName = 'index', $vars = array(), $viewType = '', $onlybody = false)
{
return helper::createLink($this->moduleName, $methodName, $vars, $viewType, $onlybody);
}
/**
* 重定向到另一个页面。
* Location to another page.
*
* @param string $url the target url.
* @access public
* @return void
*/
public function locate($url)
{
header("location: $url");
exit;
}
}

View File

@ -0,0 +1,744 @@
<?php
/**
* ZenTaoPHP的baseHelper类。
* The baseHelper class file of ZenTaoPHP framework.
*
* @package framework
*
* The author disclaims copyright to this source code. In place of
* a legal notice, here is a blessing:
*
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
*/
class baseHelper
{
/**
* 设置一个对象的成员变量。
* Set the member's value of one object.
* <code>
* <?php
* $lang->db->user = 'wwccss';
* helper::setMember('lang', 'db.user', 'chunsheng.wang');
* ?>
* </code>
* @param string $objName the var name of the object.
* @param string $key the key of the member, can be parent.child.
* @param mixed $value the value to be set.
* @static
* @access public
* @return bool
*/
static public function setMember($objName, $key, $value)
{
global $$objName;
if(!is_object($$objName) or empty($key)) return false;
$key = str_replace('.', '->', $key);
$value = serialize($value);
$code = ("\$${objName}->{$key}=unserialize(<<<EOT\n$value\nEOT\n);");
eval($code);
return true;
}
/**
* 生成一个模块方法的链接。control类的createLink实际上调用的是这个方法。
* Create a link to a module's method, mapped in control class to call conveniently.
*
* <code>
* <?php
* helper::createLink('hello', 'index', 'var1=value1&var2=value2');
* helper::createLink('hello', 'index', array('var1' => 'value1', 'var2' => 'value2');
* ?>
* </code>
* @param string $moduleName module name, can pass appName like app.module.
* @param string $methodName method name
* @param string|array $vars the params passed to the method, can be array('key' => 'value') or key1=value1&key2=value2) or key1=value1&key2=value2
* @param string $viewType the view type
* @param bool $onlyBody pass onlyBody=yes to the link thus the app can control the header and footer hide or show..
* @static
* @access public
* @return string the link string.
*/
static public function createLink($moduleName, $methodName = 'index', $vars = '', $viewType = '', $onlyBody = false)
{
/* 设置$appName和$moduleName。Set appName and moduleName. */
global $app, $config;
if(strpos($moduleName, '.') !== false)
{
list($appName, $moduleName) = explode('.', $moduleName);
}
else
{
$appName = $app->getAppName();
}
if(!empty($appName)) $appName .= '/';
/* 处理$viewType和$vars。Set $viewType and $vars. */
if(empty($viewType)) $viewType = $app->getViewType();
if(!is_array($vars)) parse_str($vars, $vars);
/* 生成url链接的开始部分。Set the begin parts of the link. */
if($config->requestType == 'PATH_INFO') $link = $config->webRoot . $appName;
if($config->requestType != 'PATH_INFO') $link = $config->webRoot . $appName . basename($_SERVER['SCRIPT_NAME']);
if($config->requestType == 'PATH_INFO2') $link .= '/';
/**
* #1: RequestType为GET。When the requestType is GET.
* Input: moduleName=article&methodName=index&var1=value1. Output: ?m=article&f=index&var1=value1.
*
*/
if($config->requestType == 'GET')
{
$link .= "?{$config->moduleVar}=$moduleName&{$config->methodVar}=$methodName";
if($viewType != 'html') $link .= "&{$config->viewVar}=" . $viewType;
foreach($vars as $key => $value) $link .= "&$key=$value";
return self::processOnlyBodyParam($link, $onlyBody);
}
/**
* #2: 方法名不是默认值或者是默认值但有传参。MethodName equals the default method or vars not empty.
* Input: moduleName=article&methodName=view. Output: article-view.html
* Input: moduleName=article&methodName=view. Output: article-index-abc.html
*
*/
if($methodName != $config->default->method or !empty($vars))
{
$link .= "$moduleName{$config->requestFix}$methodName";
foreach($vars as $value) $link .= "{$config->requestFix}$value";
$link .= '.' . $viewType;
return self::processOnlyBodyParam($link, $onlyBody);
}
/**
* #3: 方法名为默认值且没有传参且模块名为默认值。MethodName is the default and moduleName is default and vars empty.
* Input: moduleName=index&methodName=index. Output: index.html
*
*/
if($moduleName == $config->default->module)
{
$link .= $config->default->method . '.' . $viewType;
return self::processOnlyBodyParam($link, $onlyBody);
}
/**
* #4: 方法名为默认值且没有传参且模块名不为默认值viewType和app指定的相等。MethodName is default but moduleName not and viewType equal app's viewType..
* Input: moduleName=article&methodName=index&viewType=html. Output: /article/
*
*/
if($viewType == $app->getViewType())
{
$link .= $moduleName . '/';
return self::processOnlyBodyParam($link, $onlyBody);
}
/**
* #5: 方法名为默认值且没有传参且模块名不为默认值viewType有另外指定。MethodName is default but moduleName not and viewType no equls app's viewType.
* Input: moduleName=article&methodName=index&viewType=json. Output: /article.json
*
*/
$link .= $moduleName . '.' . $viewType;
return self::processOnlyBodyParam($link, $onlyBody);
}
/**
* 处理onlyBody 参数。
* Process the onlyBody param in url.
*
* 如果传参的时候设定了$onlyBody为真或者当前页面请求中包含了onlybody=yes在生成链接的时候继续追加。
* If $onlyBody set to true or onlybody=yes in the url, append onlyBody param to the link.
*
* @param string $link
* @param bool $onlyBody
* @static
* @access public
* @return string
*/
public static function processOnlyBodyParam($link, $onlyBody = false)
{
global $config;
if(!$onlyBody and !self::inOnlyBodyMode()) return $link;
$onlybodyString = $config->requestType != 'GET' ? "?onlybody=yes" : "&onlybody=yes";
return $link . $onlybodyString;
}
/**
* 检查是否是onlybody模式。
* Check in only body mode or not.
*
* @access public
* @return void
*/
public static function inOnlyBodyMode()
{
return (isset($_GET['onlybody']) and $_GET['onlybody'] == 'yes');
}
/**
* 使用helper::import()来引入文件不要直接使用include或者require.
* Using helper::import() to import a file, instead of include or require.
*
* @param string $file the file to be imported.
* @static
* @access public
* @return bool
*/
static public function import($file)
{
$file = realpath($file);
if(!is_file($file)) return false;
static $includedFiles = array();
if(!isset($includedFiles[$file]))
{
include $file;
$includedFiles[$file] = true;
return true;
}
return true;
}
/**
* 将数组或者列表转化成 IN( 'a', 'b') 的形式。
* Convert a list to IN('a', 'b') string.
*
* @param string|array $idList 列表可以是数组或者用逗号隔开的列表。The id lists, can be a array or a string joined with comma.
* @static
* @access public
* @return string the string like IN('a', 'b').
*/
static public function dbIN($idList)
{
if(is_array($idList))
{
foreach ($idList as $key=>$value) $idList[$key] = addslashes($value);
return "IN ('" . join("','", $idList) . "')";
}
$idList = addslashes($idList);
return "IN ('" . str_replace(',', "','", str_replace(' ', '', $idList)) . "')";
}
/**
* 安全的Base64编码框架对'/'字符比较敏感,转换为'.'
* Create safe base64 encoded string for the framework.
*
* @param string $string the string to encode.
* @static
* @access public
* @return string encoded string.
*/
static public function safe64Encode($string)
{
return strtr(base64_encode($string), '/', '.');
}
/**
* 解码base64先将之前的'.' 转换回'/'
* Decode the string encoded by safe64Encode.
*
* @param string $string the string to decode
* @static
* @access public
* @return string decoded string.
*/
static public function safe64Decode($string)
{
return base64_decode(strtr($string, '.', '/'));
}
/**
* JSON编码自动处理转义的问题。
* JSON encode, process the slashes.
*
* @param mixed $data the object to encode
* @static
* @access public
* @return string decoded string.
*/
static public function jsonEncode($data)
{
return json_encode($data);
}
/**
* 判断是否是utf8编码
* Judge a string is utf-8 or not.
*
* @author hmdker@gmail.com
* @param string $string
* @see http://php.net/manual/en/function.mb-detect-encoding.php
* @static
* @access public
* @return bool
*/
static public function isUTF8($string)
{
$c = 0;
$b = 0;
$bits = 0;
$len = strlen($string);
for($i=0; $i<$len; $i++)
{
$c = ord($string[$i]);
if($c > 128)
{
if(($c >= 254)) return false;
elseif($c >= 252) $bits=6;
elseif($c >= 248) $bits=5;
elseif($c >= 240) $bits=4;
elseif($c >= 224) $bits=3;
elseif($c >= 192) $bits=2;
else return false;
if(($i+$bits) > $len) return false;
while($bits > 1)
{
$i++;
$b=ord($string[$i]);
if($b < 128 || $b > 191) return false;
$bits--;
}
}
}
return true;
}
/**
* 去掉UTF-8 Bom头。
* Remove UTF-8 Bom.
*
* @param string $string
* @access public
* @return string
*/
public static function removeUTF8Bom($string)
{
if(substr($string, 0, 3) == pack('CCC', 239, 187, 191)) return substr($string, 3);
return $string;
}
/**
* 增强substr方法支持多字节语言比如中文。
* Enhanced substr version: support multibyte languages like Chinese.
*
* @param string $string
* @param int $length
* @param string $append
* @return string
*/
public static function substr($string, $length, $append = '')
{
$rawString = $string;
if(function_exists('mb_substr')) $string = mb_substr($string, 0, $length, 'utf-8');
preg_match_all("/./su", $string, $data);
$string = join("", array_slice($data[0], 0, $length));
return ($string != $rawString) ? $string . $append : $string;
}
/**
* Get browser name and version.
*
* @access public
* @return array
*/
public static function getBrowser()
{
$browser = array('name'=>'unknown', 'version'=>'unknown');
if(empty($_SERVER['HTTP_USER_AGENT'])) return $browser;
$agent = $_SERVER["HTTP_USER_AGENT"];
/* Chrome should checked before safari.*/
if(strpos($agent, 'Firefox') !== false) $browser['name'] = "firefox";
if(strpos($agent, 'Opera') !== false) $browser['name'] = 'opera';
if(strpos($agent, 'Safari') !== false) $browser['name'] = 'safari';
if(strpos($agent, 'Chrome') !== false) $browser['name'] = "chrome";
// Check the name of browser
if(strpos($agent, 'MSIE') !== false || strpos($agent, 'rv:11.0')) $browser['name'] = 'ie';
if(strpos($agent, 'Edge') !== false) $browser['name'] = 'edge';
// Check the version of browser
if(preg_match('/MSIE\s(\d+)\..*/i', $agent, $regs)) $browser['version'] = $regs[1];
if(preg_match('/FireFox\/(\d+)\..*/i', $agent, $regs)) $browser['version'] = $regs[1];
if(preg_match('/Opera[\s|\/](\d+)\..*/i', $agent, $regs)) $browser['version'] = $regs[1];
if(preg_match('/Chrome\/(\d+)\..*/i', $agent, $regs)) $browser['version'] = $regs[1];
if((strpos($agent, 'Chrome') == false) && preg_match('/Safari\/(\d+)\..*$/i', $agent, $regs)) $browser['version'] = $regs[1];
if(preg_match('/rv:(\d+)\..*/i', $agent, $regs)) $browser['version'] = $regs[1];
if(preg_match('/Edge\/(\d+)\..*/i', $agent, $regs)) $browser['version'] = $regs[1];
return $browser;
}
/**
* Get client os from agent info.
*
* @static
* @access public
* @return string
*/
public static function getOS()
{
if(empty($_SERVER['HTTP_USER_AGENT'])) return 'unknow';
$osList = array();
$osList['/windows nt 10/i'] = 'Windows 10';
$osList['/windows nt 6.3/i'] = 'Windows 8.1';
$osList['/windows nt 6.2/i'] = 'Windows 8';
$osList['/windows nt 6.1/i'] = 'Windows 7';
$osList['/windows nt 6.0/i'] = 'Windows Vista';
$osList['/windows nt 5.2/i'] = 'Windows Server 2003/XP x64';
$osList['/windows nt 5.1/i'] = 'Windows XP';
$osList['/windows xp/i'] = 'Windows XP';
$osList['/windows nt 5.0/i'] = 'Windows 2000';
$osList['/windows me/i'] = 'Windows ME';
$osList['/win98/i'] = 'Windows 98';
$osList['/win95/i'] = 'Windows 95';
$osList['/win16/i'] = 'Windows 3.11';
$osList['/macintosh|mac os x/i'] = 'Mac OS X';
$osList['/mac_powerpc/i'] = 'Mac OS 9';
$osList['/linux/i'] = 'Linux';
$osList['/ubuntu/i'] = 'Ubuntu';
$osList['/iphone/i'] = 'iPhone';
$osList['/ipod/i'] = 'iPod';
$osList['/ipad/i'] = 'iPad';
$osList['/android/i'] = 'Android';
$osList['/blackberry/i'] = 'BlackBerry';
$osList['/webos/i'] = 'Mobile';
foreach ($osList as $regex => $value)
{
if(preg_match($regex, $_SERVER['HTTP_USER_AGENT'])) return $value;
}
return 'unknown';
}
/**
* 计算两个日期相差的天数,取整。
* Compute the diff days of two date.
*
* @param string $date1 the first date.
* @param string $date2 the sencond date.
* @access public
* @return int the diff of the two days.
*/
static public function diffDate($date1, $date2)
{
return round((strtotime($date1) - strtotime($date2)) / 86400, 0);
}
/**
* 获取当前时间使用common语言文件定义的DT_DATETIME1常量。
* Get now time use the DT_DATETIME1 constant defined in the lang file.
*
* @access public
* @return datetime now
*/
static public function now()
{
return date(DT_DATETIME1);
}
/**
* 获取当前日期使用common语言文件定义的DT_DATE1常量。
* Get today according to the DT_DATE1 constant defined in the lang file.
*
* @access public
* @return date today
*/
static public function today()
{
return date(DT_DATE1);
}
/**
* 获取当前日期使用common语言文件定义的DT_TIME1常量。
* Get now time use the DT_TIME1 constant defined in the lang file.
*
* @access public
* @return date today
*/
static public function time()
{
return date(DT_TIME1);
}
/**
* 判断日期是不是零。
* Judge a date is zero or not.
*
* @access public
* @return bool
*/
static public function isZeroDate($date)
{
return substr($date, 0, 4) == '0000';
}
/**
* 列出目录中符合该正则表达式的文件。
* Get files match the pattern under a directory.
*
* @access public
* @return array the files match the pattern
*/
static public function ls($dir, $pattern = '')
{
if(empty($dir)) return array();
$files = array();
$dir = realpath($dir);
if(is_dir($dir)) $files = glob($dir . DIRECTORY_SEPARATOR . '*' . $pattern);
return empty($files) ? array() : $files;
}
/**
* 切换目录。第一次调用的时候记录当前的路径,再次调用的时候切换回之前的路径。
* Change directory: first call, save the $cwd, secend call, change to $cwd.
*
* @param string $path
* @static
* @access public
* @return void
*/
static function cd($path = '')
{
static $cwd = '';
if($path) $cwd = getcwd();
!empty($path) ? chdir($path) : chdir($cwd);
}
/**
* 通过域名获取站点代号。
* Get siteCode for a domain.
*
* www.xirang.com => xirang
* xirang.com => xirang
* xirang.com.cn => xirang
* xirang.cn => xirang
* xirang => xirang
*
* @param string $domain
* @return string $siteCode
**/
public static function parseSiteCode($domain)
{
global $config;
/* 去除域名中的端口部分。Remove the port part of the domain. */
if(strpos($domain, ':') !== false) $domain = substr($domain, 0, strpos($domain, ':'));
$domain = strtolower($domain);
/* $config里面有定义或者是localhost直接返回。 Return directly if defined in $config or is localhost. */
if(isset($config->siteCodeList[$domain])) return $config->siteCodeList[$domain];
if($domain == 'localhost') return $domain;
/* 将域名中的-改为_。Replace '-' with '_' in the domain. */
$domain = str_replace('-', '_', $domain);
$items = explode('.', $domain);
/* 类似a.com的形式。 Domain like a.com. */
$postfix = str_replace($items[0] . '.', '', $domain);
if(isset($config->domainPostfix) and strpos($config->domainPostfix, "|$postfix|") !== false) return $items[0];
/* 类似www.a.com的形式。 Domain like www.a.com. */
$postfix = str_replace($items[0] . '.' . $items[1] . '.', '', $domain);
if(isset($config->domainPostfix) and strpos($config->domainPostfix, "|$postfix|") !== false) return $items[1];
/* 类似xxx.sub.a.com的形式。 Domain like xxx.sub.a.com. */
$postfix = str_replace($items[0] . '.' . $items[1] . '.' . $items[2] . '.', '', $domain);
if(isset($config->domainPostfix) and strpos($config->domainPostfix, "|$postfix|") !== false) return $items[0];
return '';
}
/**
* 检查是否是AJAX请求。
* Check is ajax request.
*
* @static
* @access public
* @return bool
*/
public static function isAjaxRequest()
{
if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') return true;
if(isset($_GET['HTTP_X_REQUESTED_WITH']) && $_GET['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') return true;
return false;
}
/**
* 301跳转。
* Header 301 Moved Permanently.
*
* @param string $locate
* @access public
* @return void
*/
public static function header301($locate)
{
header('HTTP/1.1 301 Moved Permanently');
die(header('Location:' . $locate));
}
/**
* 获取远程IP。
* Get remote ip.
*
* @access public
* @return string
*/
public static function getRemoteIp()
{
$ip = '';
if(!empty($_SERVER["REMOTE_ADDR"])) $ip = $_SERVER["REMOTE_ADDR"];
if(!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
if(!empty($_SERVER['HTTP_CLIENT_IP'])) $ip = $_SERVER['HTTP_CLIENT_IP'];
return $ip;
}
}
//------------------------------- 常用函数。Some tool functions.-------------------------------//
/**
* helper::createLink()的别名,方便创建本模块方法的链接。
* The short alias of helper::createLink() method to create link to control method of current module.
*
* @param string $methodName the method name
* @param string|array $vars the params passed to the method, can be array('key' => 'value') or key1=value1&key2=value2)
* @param string $viewType
* @return string the link string.
*/
function inLink($methodName = 'index', $vars = '', $viewType = '')
{
global $app;
return helper::createLink($app->getModuleName(), $methodName, $vars, $viewType);
}
/**
* 通过一个静态游标,可以遍历数组。
* Static cycle a array.
*
* @param array $items the array to be cycled.
* @return mixed
*/
function cycle($items)
{
static $i = 0;
if(!is_array($items)) $items = explode(',', $items);
if(!isset($items[$i])) $i = 0;
return $items[$i++];
}
/**
* 获取当前时间的Unix时间戳精确到微妙。
* Get current microtime.
*
* @access public
* @return float current time.
*/
function getTime()
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
/**
* 打印变量的信息
* dump a var.
*
* @param mixed $var
* @access public
* @return void
*/
function a($var)
{
echo "<xmp class='a-left'>";
print_r($var);
echo "</xmp>";
}
/**
* 判断是否内外IP。
* Judge the server ip is local or not.
*
* @access public
* @return void
*/
function isLocalIP()
{
global $config;
if(isset($config->islocalIP)) return $config->isLocalIP;
$serverIP = $_SERVER['SERVER_ADDR'];
if($serverIP == '127.0.0.1') return true;
if(strpos($serverIP, '10.70') !== false) return false;
return !filter_var($serverIP, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE);
}
/**
* 获取webRoot。
* Get web root.
*
* @access public
* @return string
*/
function getWebRoot($full = false)
{
$path = $_SERVER['SCRIPT_NAME'];
if(PHP_SAPI == 'cli')
{
if(isset($_SERVER['argv'][1]))
{
$url = parse_url($_SERVER['argv'][1]);
$path = empty($url['path']) ? '/' : rtrim($url['path'], '/');
}
$path = empty($path) ? '/' : preg_replace('/\/www$/', '/www/', $path);
}
if($full)
{
$http = (isset($_SERVER['HTTPS']) and strtolower($_SERVER['HTTPS']) != 'off') ? 'https://' : 'http://';
return $http . $_SERVER['HTTP_HOST'] . substr($path, 0, (strrpos($path, '/') + 1));
}
$path = substr($path, 0, (strrpos($path, '/') + 1));
$path = str_replace('\\', '/', $path);
return $path;
}
/**
* 当数组/对象变量$var存在$key项时返回存在的对应值或设定值否则返回$key或不存在的设定值。
* When the $var has the $key, return it, esle result one default value.
*
* @param array|object $var
* @param string|int $key
* @param mixed $valueWhenNone value when the key not exits.
* @param mixed $valueWhenExists value when the key exits.
* @access public
* @return string
*/
function zget($var, $key, $valueWhenNone = false, $valueWhenExists = false)
{
if(!is_array($var) and !is_object($var)) return false;
$type = is_array($var) ? 'array' : 'object';
$checkExists = $type == 'array' ? isset($var[$key]) : isset($var->$key);
if($checkExists)
{
if($valueWhenExists !== false) return $valueWhenExists;
return $type == 'array' ? $var[$key] : $var->$key;
}
if($valueWhenNone !== false) return $valueWhenNone;
return $key;
}

View File

View File

@ -0,0 +1,302 @@
<?php
/**
* ZenTaoPHP的baseModel类。
* The baseModel class file of ZenTaoPHP framework.
*
* @package framework
*
* The author disclaims copyright to this source code. In place of
* a legal notice, here is a blessing:
*
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
*/
class baseModel
{
/**
* 全局对象$app。
* The global $app object.
*
* @var object
* @access public
*/
public $app;
/**
* 应用名称$appName。
* The global appName.
*
* @var string
* @access public
*/
public $appName;
/**
* 全局对象$config。
* The global $config object.
*
* @var object
* @access public
*/
public $config;
/**
* 全局对象$lang。
* The global $lang object.
*
* @var object
* @access public
*/
public $lang;
/**
* 全局对象$dbh数据库连接句柄。
* The global $dbh object, the database connection handler.
*
* @var object
* @access public
*/
public $dbh;
/**
* $dao对象用于访问或者更新数据库。
* The $dao object, used to access or update database.
*
* @var object
* @access public
*/
public $dao;
/**
* $post对象用于访问$_POST变量。
* The $post object, used to access the $_POST var.
*
* @var object
* @access public
*/
public $post;
/**
* $get对象用于访问$_GET变量。
* The $get object, used to access the $_GET var.
*
* @var object
* @access public
*/
public $get;
/**
* $session对象用于访问$_SESSION变量。
* The $session object, used to access the $_SESSION var.
*
* @var object
* @access public
*/
public $session;
/**
* $server对象用于访问$_SERVER变量。
* The $server object, used to access the $_SERVER var.
*
* @var object
* @access public
*/
public $server;
/**
* $cookie对象用于访问$_COOKIE变量。
* The $cookie object, used to access the $_COOKIE var.
*
* @var object
* @access public
*/
public $cookie;
/**
* $global对象用于访问$_GLOBAL变量。
* The $global object, used to access the $_GLOBAL var.
*
* @var object
* @access public
*/
public $global;
/**
* 构造方法。
* 1. 将全局变量设为model类的成员变量方便model的派生类调用
* 2. 设置$config, $lang, $dbh, $dao。
*
* The construct function.
* 1. global the global vars, refer them by the class member such as $this->app.
* 2. set the pathes, config, lang of current module
*
* @param string $appName
* @access public
* @return void
*/
public function __construct($appName = '')
{
global $app, $config, $lang, $dbh;
$this->app = $app;
$this->config = $config;
$this->lang = $lang;
$this->dbh = $dbh;
$this->appName = empty($appName) ? $this->app->getAppName() : $appName;
$moduleName = $this->getModuleName();
if($this->config->framework->multiLanguage) $this->app->loadLang($moduleName, $this->appName);
if($moduleName != 'common') $this->app->loadModuleConfig($moduleName, $this->appName);
$this->loadDAO();
$this->setSuperVars();
}
/**
* 获取该model的模块名而不是用户请求的模块名。
*
* 这个方法通过去掉该model类名的'ext''model'字符串,来获取当前模块名。
* 不要使用$app->getModuleName(),因为其返回的是用户请求的模块名。
* 另一个model可以通过loadModel()加载进来,与请求的模块名不一致。
*
* Get the module name of this model. Not the module user visiting.
*
* This method replace the 'ext' and 'model' string from the model class name, thus get the module name.
* Not using $app->getModuleName() because it return the module user is visiting. But one module can be
* loaded by loadModel() so we must get the module name of this model.
*
* @access public
* @return string the module name.
*/
public function getModuleName()
{
$parentClass = get_parent_class($this);
$selfClass = get_class($this);
$className = $parentClass == 'model' ? $selfClass : $parentClass;
if($className == 'extensionModel') return 'extension';
return strtolower(str_ireplace(array('ext', 'Model'), '', $className));
}
/**
* 设置全局超级变量。
* Set the super vars.
*
* @access public
* @return void
*/
public function setSuperVars()
{
$this->post = $this->app->post;
$this->get = $this->app->get;
$this->server = $this->app->server;
$this->cookie = $this->app->cookie;
$this->session = $this->app->session;
}
/**
* 加载一个模块的model。加载完成后使用$this->$moduleName来访问这个model对象。
* 比如loadModel('user')引入user模块的model实例对象可以通过$this->user来访问它。
*
* Load the model of one module. After loaded, can use $this->$moduleName to visit the model object.
*
* @param string $moduleName
* @access public
* @return object|bool the model object or false if model file not exists.
*/
public function loadModel($moduleName, $appName = '')
{
if(empty($moduleName)) return false;
if(empty($appName)) $appName = $this->appName;
global $loadedModels;
if(isset($loadedModels[$appName][$moduleName]))
{
$this->$moduleName = $loadedModels[$appName][$moduleName];
return $this->$moduleName;
}
$modelFile = $this->app->setModelFile($moduleName, $appName);
if(!helper::import($modelFile)) return false;
$modelClass = class_exists('ext' . $appName . $moduleName. 'model') ? 'ext' . $appName . $moduleName . 'model' : $appName . $moduleName . 'model';
if(!class_exists($modelClass))
{
$modelClass = class_exists('ext' . $moduleName. 'model') ? 'ext' . $moduleName . 'model' : $moduleName . 'model';
if(!class_exists($modelClass)) $this->app->triggerError(" The model $modelClass not found", __FILE__, __LINE__, $exit = true);
}
$loadedModels[$appName][$moduleName] = new $modelClass($appName);
$this->$moduleName = $loadedModels[$appName][$moduleName];
return $this->$moduleName;
}
/**
* 加载model的class扩展主要是为了开发加密代码使用。
* 可以将主要的逻辑存放到$moduleName/ext/model/class/$extensionName.class.php中。
* 然后在ext/model/$extension.php的扩展里面使用$this->loadExtension()来调用相应的方法。
* ext/model/class/*.class.php代码可以加密。而ext/model/*.php可以不用加密。
* 因为框架对model的扩展是采取合并文件的方式ext/model/*.php文件不能加密。
*
* Load extension class of a model thus user can encrypt the code.
* You can put the main extension logic codes in $moduleName/ext/model/class/$extensionName.class.php.
* And call them by the ext/model/$extension.php like this: $this->loadExtension('myextension')->method().
* You can encrypt the code in ext/model/class/*.class.php.
* Because the framework will merge the extension files in ext/model/*.php to the module/model.php.
*
* @param string $extensionName
* @param string $moduleName
* @access public
* @return void
*/
public function loadExtension($extensionName, $moduleName = '')
{
if(empty($extensionName)) return false;
/* 设置扩展的名字和相应的文件。Set extenson name and extension file. */
$extensionName = strtolower($extensionName);
$moduleName = $moduleName ? $moduleName : $this->getModuleName();
$moduleExtPath = $this->app->getModuleExtPath($this->appName, $moduleName, 'model');
if(!empty($moduleExtPath['site'])) $extensionFile = $moduleExtPath['site'] . 'class/' . $extensionName . '.class.php';
if(!isset($extensionFile) or !file_exists($extensionFile)) $extensionFile = $moduleExtPath['common'] . 'class/' . $extensionName . '.class.php';
/* 载入父类。Try to import parent model file auto and then import the extension file. */
if(!class_exists($moduleName . 'Model')) helper::import($this->app->getModulePath($this->appName, $moduleName) . 'model.php');
if(!helper::import($extensionFile)) return false;
/* 设置扩展类的名字。Set the extension class name. */
$extensionClass = $extensionName . ucfirst($moduleName);
if(!class_exists($extensionClass)) return false;
/* 实例化扩展类。Create an instance of the extension class and return it. */
$extensionObject = new $extensionClass;
$extensionClass = str_replace('Model', '', $extensionClass);
$this->$extensionClass = $extensionObject;
return $extensionObject;
}
/**
* 加载DAO。
* Load DAO.
*
* @access public
* @return void
*/
public function loadDAO()
{
$this->dao = $this->app->loadClass('dao');
}
/**
* 删除记录。
* Delete one record.
*
* @param string $table the table name
* @param string $id the id value of the record to be deleted
* @access public
* @return void
*/
public function delete($table, $id)
{
$this->dao->delete()->from($table)->where('id')->eq($id)->exec();
}
}

File diff suppressed because it is too large Load Diff

226
framework/control.class.php Executable file
View File

@ -0,0 +1,226 @@
<?php
/**
* Control类从baseControl类继承而来每个模块的control对象从control类集成。
* 您可以对baseControl类进行扩展扩展的逻辑可以定义在这个文件中。
*
* This control class extends from the baseControl class and extened by every module's control.
* You can extend the baseControl class by change this file.
*
* @package framework
*
* The author disclaims copyright to this source code. In place of
* a legal notice, here is a blessing:
*
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
*/
include FRAME_ROOT . '/base/control.class.php';
class control extends baseControl
{
/**
* 设置视图文件:主视图文件,扩展视图文件, 站点扩展视图文件,以及钩子脚本。
* Set view files: the main file, extension view file, site extension view file and hook files.
*
* @param string $moduleName module name
* @param string $methodName method name
* @access public
* @return string the view file
*/
public function setViewFile($moduleName, $methodName)
{
$moduleName = strtolower(trim($moduleName));
$methodName = strtolower(trim($methodName));
$modulePath = $this->app->getModulePath($this->appName, $moduleName);
$viewExtPath = $this->app->getModuleExtPath($this->appName, $moduleName, 'view');
$viewType = ($this->viewType == 'mhtml' or $this->viewType == 'xhtml') ? 'html' : $this->viewType;
$mainViewFile = $modulePath . 'view' . DS . $this->devicePrefix . $methodName . '.' . $viewType . '.php';
/* If the main view file doesn't exist, set the device prefix to empty and reset the main view file. */
if($this->viewType == 'mhtml' or $this->viewType == 'xhtml')
{
if(!file_exists($mainViewFile))
{
if($this->viewType == 'xhtml') $this->app->viewType = 'html';
$this->devicePrefix = '';
$mainViewFile = $modulePath . 'view' . DS . $this->devicePrefix . $methodName . '.' . $viewType . '.php';
}
}
$viewFile = $mainViewFile;
if(!empty($viewExtPath))
{
$commonExtViewFile = $viewExtPath['common'] . $this->devicePrefix . $methodName . ".{$viewType}.php";
$siteExtViewFile = empty($viewExtPath['site']) ? '' : $viewExtPath['site'] . $this->devicePrefix . $methodName . ".{$viewType}.php";
$viewFile = file_exists($commonExtViewFile) ? $commonExtViewFile : $mainViewFile;
$viewFile = (!empty($siteExtViewFile) and file_exists($siteExtViewFile)) ? $siteExtViewFile : $viewFile;
if(!is_file($viewFile)) $this->app->triggerError("the view file $viewFile not found", __FILE__, __LINE__, $exit = true);
$commonExtHookFiles = glob($viewExtPath['common'] . $this->devicePrefix . $methodName . ".*.{$viewType}.hook.php");
$siteExtHookFiles = empty($viewExtPath['site']) ? '' : glob($viewExtPath['site'] . $this->devicePrefix . $methodName . ".*.{$viewType}.hook.php");
$extHookFiles = array_merge((array) $commonExtHookFiles, (array) $siteExtHookFiles);
}
if(!empty($extHookFiles)) return array('viewFile' => $viewFile, 'hookFiles' => $extHookFiles);
return $viewFile;
}
/**
* 默认渲染方法适用于viewType = html的时候。
* Default parse method when viewType != json, like html.
*
* @param string $moduleName module name
* @param string $methodName method name
* @access public
* @return void
*/
public function parseDefault($moduleName, $methodName)
{
/**
* 设置视图文件。(PHP7有一个bug不能直接$viewFile = $this->setViewFile())
* Set viewFile. (Can't assign $viewFile = $this->setViewFile() directly because one php7's bug.)
*/
$results = $this->setViewFile($moduleName, $methodName);
$viewFile = $results;
if(is_array($results)) extract($results);
/**
* 获得当前页面的CSS和JS。
* Get css and js codes for current method.
*/
$css = $this->getCSS($moduleName, $methodName);
$js = $this->getJS($moduleName, $methodName);
/* If the js or css file doesn't exist, set the device prefix to empty and reset the js or css file. */
if($this->viewType == 'xhtml')
{
if(!$css)
{
$this->devicePrefix = '';
$css = $this->getCSS($moduleName, $methodName);
}
if(!$js)
{
$this->devicePrefix = '';
$js = $this->getJS($moduleName, $methodName);
}
}
if($css) $this->view->pageCSS = $css;
if($js) $this->view->pageJS = $js;
/**
* 切换到视图文件所在的目录以保证视图文件里面的include语句能够正常运行。
* Change the dir to the view file to keep the relative pathes work.
*/
$currentPWD = getcwd();
chdir(dirname($viewFile));
/**
* 使用extract安定ob方法渲染$viewFile里面的代码。
* Use extract and ob functions to eval the codes in $viewFile.
*/
extract((array)$this->view);
ob_start();
include $viewFile;
if(isset($hookFiles)) foreach($hookFiles as $hookFile) if(file_exists($hookFile)) include $hookFile;
$this->output .= ob_get_contents();
ob_end_clean();
/**
* 渲染完毕后,再切换回之前的路径。
* At the end, chang the dir to the previous.
*/
chdir($currentPWD);
}
/**
* 获取一个方法的输出内容,这样我们可以在一个方法里获取其他模块方法的内容。
* 如果模块名为空,则调用该模块、该方法;如果设置了模块名,调用指定模块指定方法。
*
* Get the output of one module's one method as a string, thus in one module's method, can fetch other module's content.
* If the module name is empty, then use the current module and method. If set, use the user defined module and method.
*
* @param string $moduleName module name.
* @param string $methodName method name.
* @param array $params params.
* @access public
* @return string the parsed html.
*/
public function fetch($moduleName = '', $methodName = '', $params = array(), $appName = '')
{
if($moduleName == '') $moduleName = $this->moduleName;
if($methodName == '') $methodName = $this->methodName;
if($appName == '') $appName = $this->appName;
if($moduleName == $this->moduleName and $methodName == $this->methodName)
{
$this->parse($moduleName, $methodName);
return $this->output;
}
$currentPWD = getcwd();
/**
* 设置引用的文件和路径。
* Set the pathes and files to included.
**/
$modulePath = $this->app->getModulePath($appName, $moduleName);
$moduleControlFile = $modulePath . 'control.php';
$actionExtPath = $this->app->getModuleExtPath($appName, $moduleName, 'control');
$file2Included = $moduleControlFile;
if(!empty($actionExtPath))
{
$commonActionExtFile = $actionExtPath['common'] . strtolower($methodName) . '.php';
$file2Included = file_exists($commonActionExtFile) ? $commonActionExtFile : $moduleControlFile;
if(!empty($actionExtPath['site']))
{
$siteActionExtFile = $actionExtPath['site'] . strtolower($methodName) . '.php';
$file2Included = file_exists($siteActionExtFile) ? $siteActionExtFile : $file2Included;
}
}
/**
* 加载控制器文件。
* Load the control file.
*/
if(!is_file($file2Included)) $this->app->triggerError("The control file $file2Included not found", __FILE__, __LINE__, $exit = true);
chdir(dirname($file2Included));
if($moduleName != $this->moduleName) helper::import($file2Included);
/**
* 设置调用的类名。
* Set the name of the class to be called.
*/
$className = class_exists("my$moduleName") ? "my$moduleName" : $moduleName;
if(!class_exists($className)) $this->app->triggerError(" The class $className not found", __FILE__, __LINE__, $exit = true);
/**
* 解析参数创建模块control对象。
* Parse the params, create the $module control object.
*/
if(!is_array($params)) parse_str($params, $params);
$module = new $className($moduleName, $methodName, $appName);
/**
* 调用对应方法使用ob方法获取输出内容。
* Call the method and use ob function to get the output.
*/
ob_start();
call_user_func_array(array($module, $methodName), $params);
$output = ob_get_contents();
ob_end_clean();
/**
* 返回内容。
* Return the content.
*/
unset($module);
chdir($currentPWD);
return $output;
}
}

192
framework/helper.class.php Normal file
View File

@ -0,0 +1,192 @@
<?php
/**
* Helper类从baseHelper类继承而来您可以在这个文件中对其进行扩展。
* This helper class extends from the baseHelper class, and you can
* extend it by change this helper.class.php file.
*
* @package framework
*
* The author disclaims copyright to this source code. In place of
* a legal notice, here is a blessing:
*
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
*/
include dirname(__FILE__) . '/base/helper.class.php';
class helper extends baseHelper
{
/**
* Merge config items in database and config files.
*
* @param array $dbConfig
* @param string $moduleName
* @static
* @access public
* @return void
*/
public static function mergeConfig($dbConfig, $moduleName = 'common')
{
global $config;
$config2Merge = $config;
if($moduleName != 'common') $config2Merge = $config->$moduleName;
foreach($dbConfig as $item)
{
foreach($item as $record)
{
if(!is_object($record))
{
$config2Merge->{$item->key} = $item->value;
break;
}
if(!isset($config2Merge->{$record->section})) $config2Merge->{$record->section} = new stdclass();
if($record->key) $config2Merge->{$record->section}->{$record->key} = $record->value;
}
}
}
/**
* Encode json for $.parseJSON
*
* @param array $data
* @param int $options
* @static
* @access public
* @return string
*/
static public function jsonEncode4Parse($data, $options = 0)
{
$json = json_encode($data);
if($options) $json = str_replace(array("'", '"'), array('\u0027', '\u0022'), $json);
$escapers = array("\\", "/", "\"", "'", "\n", "\r", "\t", "\x08", "\x0c", "\\\\u");
$replacements = array("\\\\", "\\/", "\\\"", "\'", "\\n", "\\r", "\\t", "\\f", "\\b", "\\u");
return str_replace($escapers, $replacements, $json);
}
/**
* Unify string to standard chars.
*
* @param string $string
* @param string $to
* @static
* @access public
* @return string
*/
public static function unify($string, $to = ',')
{
$labels = array('_', '、', ' ', '-', '?', '@', '&', '%', '~', '`', '+', '*', '/', '\\', '', '。');
$string = str_replace($labels, $to, $string);
return preg_replace("/[{$to}]+/", $to, trim($string, $to));
}
/**
* Format version to semver formate.
*
* @param string $version
* @static
* @access public
* @return string
*/
public static function formatVersion($version)
{
return preg_replace_callback(
'/([0-9]+)((?:\.[0-9]+)?)((?:\.[0-9]+)?)(?:[\s\-\+\.]?)((?:[a-z]+)?)((?:\.?[0-9]+)?)/i',
function($matches)
{
$major = $matches[1];
$minor = $matches[2];
$patch = $matches[3];
$preRelease = $matches[4];
$build = $matches[5];
$versionStrs = array(
$major,
$minor ?: ".0",
$patch ?: ".0",
);
if($preRelease ?: $build) array_push($versionStrs, "-");
if($preRelease) array_push($versionStrs, $preRelease);
if($build)
{
if(!$preRelease) array_push($versionStrs, "build");
if(mb_substr($build, 0, 1) !== ".") array_push($versionStrs, ".");
array_push($versionStrs, $build);
}
return join("", $versionStrs);
},
$version
);
}
/**
* Trim version to xuanxuan version format.
*
* @param string $version
* @access public
* @return string
*/
public function trimVersion($version)
{
return preg_replace_callback(
'/([0-9]+)((?:\.[0-9]+)?)((?:\.[0-9]+)?)(?:[\s\-\+]?)((?:[a-z]+)?)((?:\.?[0-9]+)?)/i',
function($matches)
{
$major = $matches[1];
$minor = $matches[2];
$patch = $matches[3];
$preRelease = $matches[4];
$build = $matches[5];
$versionStrs = array(
$major,
$minor ?: ".0",
);
if($patch && $patch !== ".0" && $patch !== "0") array_push($versionStrs, $patch);
if($preRelease ?: $build) array_push($versionStrs, " ");
if($preRelease) array_push($versionStrs, $preRelease);
if($build)
{
if(!$preRelease) array_push($versionStrs, "build");
array_push($versionStrs, mb_substr($build, 0, 1) === "." ? substr($build, 1) : $build);
}
return join("", $versionStrs);
},
$version
);
}
}
/**
* Check exist onlybody param.
*
* @access public
* @return void
*/
function isonlybody()
{
return (isset($_GET['onlybody']) and $_GET['onlybody'] == 'yes');
}
/**
* Format time.
*
* @param int $time
* @param string $format
* @access public
* @return void
*/
function formatTime($time, $format = '')
{
$time = str_replace('0000-00-00', '', $time);
$time = str_replace('00:00:00', '', $time);
if(trim($time) == '') return ;
if($format) return date($format, strtotime($time));
return trim($time);
}

0
framework/index.html Normal file
View File

35
framework/model.class.php Executable file
View File

@ -0,0 +1,35 @@
<?php
/**
* model类从baseModel类继承而来每个模块的model对象从model类集成。
* 您可以对baseModel类进行扩展扩展的逻辑可以定义在这个文件中。
*
* This model class extends from the baseModel class and extened by every module's model.
* You can extend the baseModel class by change this file.
*
* @package framework
*
* The author disclaims copyright to this source code. In place of
* a legal notice, here is a blessing:
*
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
*/
include FRAME_ROOT . '/base/model.class.php';
class model extends baseModel
{
/**
* Delete one record.
*
* @param string $table the table name
* @param string $id the id value of the record to be deleted
* @access public
* @return void
*/
public function delete($table, $id)
{
$this->dao->update($table)->set('deleted')->eq(1)->where('id')->eq($id)->exec();
$object = trim(substr($table, strrpos($table, '_') + 1), '`');
$this->loadModel('action')->create($object, $id, 'deleted', 'success', json_encode(array('CAN_UNDELETED' => ACTIONMODEL::CAN_UNDELETED)));
}
}

148
framework/router.class.php Executable file
View File

@ -0,0 +1,148 @@
<?php
/**
* router类从baseRouter类集成而来您可以通过修改这个文件实现对baseRouter类的扩展。
* The router class extend from baseRouter class, you can extend baseRouter class by change this file.
*
* @package framework
*
* The author disclaims copyright to this source code. In place of
* a legal notice, here is a blessing:
*
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
*/
define('FRAME_ROOT', dirname(__FILE__));
include FRAME_ROOT . '/base/router.class.php';
class router extends baseRouter
{
/**
* 创建一个应用。
* Create an application.
*
* @param string $appName 应用名称。 The name of the app.
* @param string $appRoot 应用根路径。The root path of the app.
* @param string $className 应用类名如果对router类做了扩展需要指定类名。When extends router class, you should pass in the child router class name.
* @static
* @access public
* @return object the app object
*/
public static function createApp($appName = 'demo', $appRoot = '', $className = '')
{
if(empty($className)) $className = __CLASS__;
return new $className($appName, $appRoot);
}
/**
* 加载模块的config文件返回全局$config对象。
* 如果该模块是common加载$configRoot的配置文件其他模块则加载其模块的配置文件。
*
* Load config and return it as the global config object.
* If the module is common, search in $configRoot, else in $modulePath.
*
* @param string $moduleName module name
* @param string $appName app name
* @param bool $exitIfNone exit or not
* @access public
* @return object|bool the config object or false.
*/
public function loadModuleConfig($moduleName, $appName = '')
{
global $config;
if($config and (!isset($config->$moduleName) or !is_object($config->$moduleName))) $config->$moduleName = new stdclass();
/* 初始化数组。Init the variables. */
$extConfigFiles = array();
$commonExtConfigFiles = array();
$siteExtConfigFiles = array();
/* 先获得模块的主配置文件。Get the main config file for current module first. */
$mainConfigFile = $this->getModulePath($appName, $moduleName) . 'config.php';
/* 查找扩展配置文件。Get extension config files. */
if($config->framework->extensionLevel > 0) $extConfigPath = $this->getModuleExtPath($appName, $moduleName, 'config');
if($config->framework->extensionLevel >= 1 and !empty($extConfigPath['common'])) $commonExtConfigFiles = helper::ls($extConfigPath['common'], '.php');
if($config->framework->extensionLevel == 2 and !empty($extConfigPath['site'])) $siteExtConfigFiles = helper::ls($extConfigPath['site'], '.php');
$extConfigFiles = array_merge($commonExtConfigFiles, $siteExtConfigFiles);
/* 将主配置文件和扩展配置文件合并在一起。Put the main config file and extension config files together. */
$configFiles = array_merge(array($mainConfigFile), $extConfigFiles);
/* 加载每一个配置文件。Load every config file. */
static $loadedConfigs = array();
foreach($configFiles as $configFile)
{
if(in_array($configFile, $loadedConfigs)) continue;
if(file_exists($configFile)) include $configFile;
$loadedConfigs[] = $configFile;
}
if($moduleName != 'common' and isset($config->system->$moduleName))
{
helper::mergeConfig($config->system->$moduleName, $moduleName);
}
if($moduleName != 'common' and isset($config->personal->$moduleName))
{
helper::mergeConfig($config->personal->$moduleName, $moduleName);
}
}
/**
* 加载语言文件,返回全局$lang对象。
* Load lang and return it as the global lang object.
*
* @param string $moduleName the module name
* @access public
* @return bool|object the lang object or false.
*/
public function loadLang($moduleName, $appName = '')
{
$lang = parent::loadLang($moduleName, $appName);
$customLang = array();
if(isset($lang->db->custom[$moduleName])) $customLang += $lang->db->custom[$moduleName];
foreach($customLang as $section => $fields)
{
if(empty($section))
{
foreach($fields as $key => $value)
{
if($moduleName == 'common')
{
unset($lang->{$key});
$lang->{$key} = $value;
}
else
{
if(!isset($lang->{$moduleName})) $lang->{$moduleName} = new stdclass();
unset($lang->{$moduleName}->{$key});
$lang->{$moduleName}->{$key} = $value;
}
}
}
else
{
foreach($fields as $key => $value)
{
if($moduleName == 'common')
{
unset($lang->{$section}[$key]);
$lang->{$section}[$key] = $value;
}
else
{
unset($lang->{$moduleName}->{$section}[$key]);
$lang->{$moduleName}->{$section}[$key] = $value;
}
}
}
}
$this->lang = $lang;
return $lang;
}
}

View File

@ -0,0 +1,566 @@
<?php
include 'router.class.php';
class xuanxuan extends router
{
/**
* The input params.
*
* @var array
* @access public
*/
public $input = array();
/**
* The request params.
*
* @var array
* @access public
*/
public $params = array();
/**
* 构造方法, 设置路径,类,超级变量等。注意:
* 1.应该使用createApp()方法实例化router类
* 2.如果$appRoot为空框架会根据$appName计算应用路径。
*
* The construct function.
* Prepare all the paths, classes, super objects and so on.
* Notice:
* 1. You should use the createApp() method to get an instance of the router.
* 2. If the $appRoot is empty, the framework will compute the appRoot according the $appName
*
* @param string $appName the name of the app
* @param string $appRoot the root path of the app
* @access public
* @return void
*/
public function __construct($appName = 'sys', $appRoot = '')
{
parent::__construct($appName, $appRoot);
$this->setViewType();
$this->setXuanClientLang();
$this->setXuanDebug();
}
/**
* Set view type.
*
* @access public
* @return void
*/
public function setViewType()
{
$this->viewType = RUN_MODE == 'xuanxuan' ? 'json' : 'html';
}
/**
* 根据用户浏览器的语言设置和服务器配置,选择显示的语言。
* 优先级:$lang参数 > session > cookie > 浏览器 > 配置文件。
*
* Set the language.
* Using the order of method $lang param, session, cookie, browser and the default lang.
*
* @param string $lang zh-cn|zh-tw|zh-hk|en
* @access public
* @return void
*/
public function setXuanClientLang()
{
$row = $this->dbh->query('SELECT `value` FROM ' . TABLE_CONFIG . " WHERE `owner`='system' AND `module`='common' AND `section`='xuanxuan' AND `key`='backendLang'")->fetch();
$lang = empty($row) ? 'zh-cn' : $row->value;
parent::setClientLang($lang);
}
/**
* Set debug.
*
* @access public
* @return void
*/
public function setXuanDebug()
{
$row = $this->dbh->query('SELECT `value` FROM ' . TABLE_CONFIG . " WHERE `owner`='system' AND `module`='common' AND `section`='xuanxuan' AND `key`='debug'")->fetch();
$this->debug = empty($row) ? false : ($row->value == 1);
}
/**
* Set input params.
*
* @access public
* @return void
*/
public function setInput()
{
if(RUN_MODE == 'xuanxuan')
{
$input = empty($_POST) ? file_get_contents("php://input") : $_POST;
/* Decrypt only if AES is enabled. */
$enableAES = $this->dbh->query('SELECT `value` FROM ' . TABLE_CONFIG . " WHERE `owner`='system' AND `module`='common' AND `section`='xuanxuan' AND `key`='aes'")->fetch();
if(empty($enableAES) || $enableAES->value == 'on') $this->enableAES = true;
if(!empty($enableAES) && $enableAES->value == 'off') $this->enableAES = false;
if($this->enableAES) $this->initAES();
$input = $this->decrypt($input);
$this->input['rid'] = zget($input, 'rid' , '');
$this->input['userID'] = zget($input, 'userID' , '');
$this->input['client'] = zget($input, 'client' , '');
$this->input['module'] = zget($input, 'module' , 'im');
$this->input['method'] = zget($input, 'method' , '');
$this->input['lang'] = zget($input, 'lang' , 'zh-cn');
$this->input['params'] = zget($input, 'params' , array());
$this->input['version'] = zget($input, 'version', '');
$this->input['device'] = zget($input, 'device' , 'desktop');
}
else
{
$this->input['module'] = 'im';
$this->input['method'] = 'debug';
$this->input['params'] = array();
}
}
/**
* Init aes object.
*
* @access public
* @return void
*/
public function initAES()
{
$row = $this->dbh->query('SELECT `value` FROM ' . TABLE_CONFIG . " WHERE `owner`='system' AND `module`='common' AND `section`='xuanxuan' AND `key`='key'")->fetch();
$key = $row->value;
$iv = substr($key, 0, 16);
$this->aes = $this->loadClass('phpaes');
$this->aes->init($key, $iv);
if($this->debug)
{
$this->log("engine: " . $this->aes->getEngine());
}
}
/**
* Set params.
*
* @param array $params
* @access public
* @return void
*/
public function setParams($params = array())
{
$this->params = $params;
}
/**
* 解析本次请求的入口方法,根据请求的类型(PATH_INFO GET),调用相应的方法。
* The entrance of parseing request. According to the requestType, call related methods.
*
* @access public
* @return void
*/
public function parseRequest()
{
$this->setInput();
extract($this->input);
$module = strtolower($module);
$method = strtolower($method);
if(RUN_MODE == 'xuanxuan')
{
if(!isset($this->config->xuanxuan->enabledMethods[$module][$method]))
{
$data = new stdclass();
$data->module = 'im';
$data->method = 'error';
$data->data = 'Illegal Request.';
$this->output($this->encrypt($data));
return false;
}
/* Check for default parameters of the method if params is an object instead of an array. */
$filledWithDefaults = false;
if(is_object($params)) // cannot check ($params !== array_values($params)) for now because the decoder could not tell if data type name is needed and the name is always set.
{
$inputParams = (object)$params;
$defaultParams = $this->getDefaultParams($method, $module);
$filledParams = array();
foreach($defaultParams as $name => $defaultValue)
{
if(in_array($name, array('userID', 'version', 'device'))) continue;
$filledParams[] = isset($inputParams->$name) ? $inputParams->$name : $defaultValue;
}
$filledWithDefaults = true;
$params = $filledParams;
}
/* Unset servername param of handshake methods. */
$handshakeMethods = array('userlogin', 'sysgetserverinfo');
if(!$filledWithDefaults && $module == 'im' && in_array(strtolower($method), $handshakeMethods) && is_array($params)) unset($params[0]);
if(is_array($params))
{
$params[] = $userID;
$params[] = $version;
$params[] = $device;
}
$this->session->set('userID', $userID);
$this->session->set('clientIP', $client);
$this->session->set('clientLang', $lang);
}
elseif($module != 'im' or $method != 'debug')
{
$this->output('Access Denied');
return false;
}
$this->setModuleName($module);
$this->setMethodName($method);
$this->setParams($params);
$this->setControlFile();
return true;
}
/**
* 使用反射机制获取函数参数的默认值。
* Get the default settings of the method to be called using the reflecting.
*
* @param string $methodName
* @param string $moduleName
* @access public
* @return array
*/
public function getDefaultParams($methodName, $moduleName = 'im')
{
$control = $this->moduleRoot . $moduleName . DS . 'control.php';
$moduleExtPaths = $this->getModuleExtPath('', $moduleName, 'control');
if(!empty($moduleExtPaths))
{
$extActionFile = $moduleExtPaths['common'] . $methodName . '.php';
if(file_exists($extActionFile))
{
$control = $extActionFile;
}
elseif(isset($moduleExtPaths['xuan']))
{
$extActionFile = $moduleExtPaths['xuan'] . $methodName . '.php';
if(file_exists($extActionFile)) $control = $extActionFile;
}
}
helper::cd(dirname($control));
helper::import($control);
helper::cd();
$moduleName = class_exists("my$moduleName") ? "my$moduleName" : $moduleName;
$defaultParams = array();
$methodReflect = new reflectionMethod($moduleName, $methodName);
foreach($methodReflect->getParameters() as $param)
{
$name = $param->getName();
$default = '_NOT_SET';
if($param->isDefaultValueAvailable()) $default = $param->getDefaultValue();
$defaultParams[$name] = $default;
}
return $defaultParams;
}
/**
* 加载一个模块:
* 1. 引入控制器文件或扩展的方法文件;
* 2. 创建control对象
* 3. 解析url得到请求的参数
* 4. 使用call_user_function_array调用相应的方法。
*
* Load a module.
* 1. include the control file or the extension action file.
* 2. create the control object.
* 3. set the params passed in through url.
* 4. call the method by call_user_function_array
*
* @access public
* @return bool|object if the module object of die.
*/
public function loadModule()
{
$appName = $this->appName;
$moduleName = $this->moduleName;
$methodName = $this->methodName;
/*
* 引入该模块的control文件。
* Include the control file of the module.
**/
$file2Included = $this->setActionExtFile() ? $this->extActionFile : $this->controlFile;
chdir(dirname($file2Included));
helper::import($file2Included);
/*
* 设置control的类名。
* Set the class name of the control.
**/
$className = class_exists("my$moduleName") ? "my$moduleName" : $moduleName;
if(!class_exists($className))
{
$this->triggerError("the control $className not found", __FILE__, __LINE__);
return false;
}
/*
* 创建control类的实例。
* Create a instance of the control.
**/
$module = new $className();
if(!method_exists($module, $methodName))
{
$this->triggerError("the module $moduleName has no $methodName method", __FILE__, __LINE__);
return false;
}
/* If the db server restarted, must reset dbh. */
$this->control = $module;
/* include default value for module*/
$defaultValueFiles = glob($this->getTmpRoot() . "defaultvalue/*.php");
if($defaultValueFiles) foreach($defaultValueFiles as $file) include $file;
/*
* 使用反射机制获取函数参数的默认值。
* Get the default settings of the method to be called using the reflecting.
*
* */
$defaultParams = array();
$methodReflect = new reflectionMethod($className, $methodName);
foreach($methodReflect->getParameters() as $param)
{
$name = $param->getName();
$default = '_NOT_SET';
if(isset($paramDefaultValue[$appName][$className][$methodName][$name]))
{
$default = $paramDefaultValue[$appName][$className][$methodName][$name];
}
elseif(isset($paramDefaultValue[$className][$methodName][$name]))
{
$default = $paramDefaultValue[$className][$methodName][$name];
}
elseif($param->isDefaultValueAvailable())
{
$default = $param->getDefaultValue();
}
$defaultParams[$name] = $default;
}
/* Merge params. */
$mergedParams = array();
if(isset($this->params))
{
$mergedParams = $this->mergeParams($defaultParams, (array)$this->params);
}
else
{
$this->triggerError("param error: {$this->request->raw}", __FILE__, __LINE__);
return false;
}
/* Call the method. */
$this->response = call_user_func_array(array($module, $methodName), $mergedParams);
return true;
}
/**
* 合并请求的参数和默认参数,这样就可以省略已经有默认值的参数了。
* Merge the params passed in and the default params. Thus the params which have default values needn't pass value, just like a function.
*
* @param array $defaultParams the default params defined by the method.
* @param array $passedParams the params passed in through url.
* @access public
* @return array the merged params.
*/
public function mergeParams($defaultParams, $passedParams)
{
/* Remove these two params. */
unset($passedParams['HTTP_X_REQUESTED_WITH']);
/* Check params from URL. */
foreach($passedParams as $param => $value)
{
if(preg_match('/[^a-zA-Z0-9_\.]/', $param))
{
$this->output('Bad Request!');
return array();
}
}
$passedParams = array_values($passedParams);
$i = 0;
foreach($defaultParams as $key => $defaultValue)
{
if(isset($passedParams[$i]))
{
$defaultParams[$key] = $passedParams[$i];
}
else
{
if($defaultValue === '_NOT_SET') $this->triggerError("The param '$key' should pass value. ", __FILE__, __LINE__, $exit = true);
}
$i++;
}
return $defaultParams;
}
/**
* Decrypt an input string.
*
* @param string $input
* @access public
* @return object
*/
public function decrypt($input = '')
{
if($this->enableAES) $input = $this->aes->decrypt($input);
if($this->debug) $this->log("decrypt: " . $input);
$input = json_decode($input);
if(!$input) $this->triggerError('Input data is not json.', __FILE__, __LINE__);
if($input && is_object($input)) return $input;
return $this->decodeInput($input);
}
/**
* Encrypt an output object.
*
* @param mixed $output array | object
* @access public
* @return string
*/
public function encrypt($output = null)
{
if(is_array($output) or is_object($output)) $output = helper::jsonEncode($output);
if($this->debug)
{
$this->log("encrypt: " . $output);
}
if($this->enableAES) $output = $this->aes->encrypt($output);
return helper::removeUTF8Bom($output);
}
/**
* Decode input params.
*
* @param array $input
* @access public
* @return array
*/
public function decodeInput($inputArray)
{
list($api, $input) = $inputArray;
$maps = zget($this->config->maps, $api, array());
/* Using requestPack as fallback maps */
if(empty($maps)) $maps = zget($this->config->maps, 'requestPack', array());
if($this->debug && empty($maps))
{
$this->log("warning: decode maps is empty for api \"$api\"");
}
$decodedParams = self::decodeArray($maps, $input);
if($this->debug)
{
$this->log("decode input($api): " . json_encode($decodedParams));
}
return $decodedParams;
}
/**
* Decode array to assorted array.
*
* @param array $maps
* @param array $data
* @static
* @access public
* @return array
*/
public static function decodeArray($maps, $data)
{
$params = array();
if(empty($maps)) return array();
/* $maps should be a type with dataType set. */
foreach($maps['dataType'] as $key => $prop)
{
/* Skip extra dataTypes that do not exist in the $data array. */
if(!isset($data[$key])) continue;
/* Basic type may contain options that allow using an index to represent a value defined in the scheme. */
if($prop['type'] == 'basic')
{
if(isset($prop['options']))
{
$params[$prop['name']] = zget($prop['options'], $data[$key]);
}
else
{
$params[$prop['name']] = zget($data, $key, '');
}
continue;
}
/* Object type may have a dataType of nested or mixed types. */
if($prop['type'] == 'object')
{
$params[$prop['name']] = self::decodeArray($prop, $data[$key]);
continue;
}
/* List type describes an array of its dataType instances. */
if($prop['type'] == 'list')
{
$params[$prop['name']] = self::decodeArray(array('dataType' => array($prop['dataType'])), $data[$key]);
}
}
return $params;
}
/**
* Output message with echo.
*
* @param string $message
* @access public
* @return void
*/
public function output($message)
{
echo $message;
}
/**
* Save a log.
*
* @param string $log
* @param string $file
* @param string $line
* @access public
* @return void
*/
public function log($message, $file = '', $line = '')
{
$log = "\n" . date('H:i:s') . " $message";
if($file) $log .= " in <strong>$file</strong>";
if($line) $log .= " on line <strong>$line</strong> ";
$file = $this->getLogRoot() . 'xuanxuan.' . date('Ymd') . '.log.php';
if(!is_file($file)) file_put_contents($file, "<?php\n die();\n?>\n");
$fh = @fopen($file, 'a');
if($fh) fwrite($fh, $log) && fclose($fh);
}
}

0
index.html Normal file
View File

2120
lib/base/dao/dao.class.php Normal file

File diff suppressed because it is too large Load Diff

0
lib/base/dao/index.html Normal file
View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

0
lib/base/index.html Normal file
View File

View File

View File

@ -0,0 +1,607 @@
<?php
/**
* ZenTaoPHP的分页类。
* The pager class file of ZenTaoPHP framework.
*
* The author disclaims copyright to this source code. In place of
* a legal notice, here is a blessing:
*
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
*/
/**
* pager类.
* Pager class.
*
* @package framework
*/
class basePager
{
/**
* 每页的默认显示记录数。
* The default counts of per page.
*
* @public int
*/
const DEFAULT_REC_PER_PAGE = 20;
/**
* 总个数。
* The total counts.
*
* @var int
* @access public
*/
public $recTotal;
/**
* 每页的记录数。
* Record count per page.
*
* @var int
* @access public
*/
public $recPerPage;
/**
* The cookie name of recPerPage.
*
* @var string
* @access public
*/
public $pageCookie;
/**
* 总页面数。
* Page count.
*
* @var string
* @access public
*/
public $pageTotal;
/**
* 当前页码。
* Current page id.
*
* @var string
* @access public
*/
public $pageID;
/**
* 全局变量$app。
* The global $app.
*
* @var object
* @access public
*/
public $app;
/**
* 全局变量$lang。
* The global $lang.
*
* @var object
* @access public
*/
public $lang;
/**
* 当前的模块名。
* Current module name.
*
* @var string
* @access public
*/
public $moduleName;
/**
* 当前的方法名。
* Current method.
*
* @var string
* @access public
*/
public $methodName;
/**
* 参数信息。
* The params.
*
* @public array
*/
public $params;
/**
* 构造方法。
* The construct function.
*
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function __construct($recTotal = 0, $recPerPage = 20, $pageID = 1)
{
$this->setApp();
$this->setLang();
$this->setModuleName();
$this->setMethodName();
$this->setRecTotal($recTotal);
$this->setRecPerPage($recPerPage);
$this->setPageTotal();
$this->setPageID($pageID);
}
/**
* 构造方法。
* The factory function.
*
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return object
*/
public static function init($recTotal = 0, $recPerPage = 20, $pageID = 1)
{
return new pager($recTotal, $recPerPage, $pageID);
}
/**
* 设置总记录数。
* Set the recTotal property.
*
* @param int $recTotal
* @access public
* @return void
*/
public function setRecTotal($recTotal = 0)
{
$this->recTotal = (int)$recTotal;
}
/**
* 设置每页记录数。
* Set the recPerPage property.
*
* @param int $recPerPage
* @access public
* @return void
*/
public function setRecPerPage($recPerPage)
{
/* Set the cookie name. */
$this->pageCookie = 'pager' . ucfirst($this->app->getModuleName()) . ucfirst($this->app->getMethodName());
if(isset($_COOKIE[$this->pageCookie])) $recPerPage = $_COOKIE[$this->pageCookie];
$this->recPerPage = ($recPerPage > 0) ? $recPerPage : PAGER::DEFAULT_REC_PER_PAGE;
}
/**
* 设置总页数。
* Set the pageTotal property.
*
* @access public
* @return void
*/
public function setPageTotal()
{
$this->pageTotal = ceil($this->recTotal / $this->recPerPage);
}
/**
* 设置页码。
* Set the page id.
*
* @param int $pageID
* @access public
* @return void
*/
public function setPageID($pageID)
{
if($pageID > 0 and ($this->pageTotal == 0 or $pageID <= $this->pageTotal))
{
$this->pageID = $pageID;
}
else
{
$this->pageID = 1;
}
}
/**
* 设置全局变量$app。
* Set the $app property;
*
* @access public
* @return void
*/
public function setApp()
{
global $app;
$this->app = $app;
}
/**
* 设置全局变量$lang。
* Set the $lang property.
*
* @access public
* @return void
*/
public function setLang()
{
global $lang;
$this->lang = $lang;
}
/**
* 设置模块名。
* Set the $moduleName property.
*
* @access public
* @return void
*/
public function setModuleName()
{
$this->moduleName = $this->app->getModuleName();
}
/**
* 设置方法名。
* Set the $methodName property.
*
* @access public
* @return void
*/
public function setMethodName()
{
$this->methodName = $this->app->getMethodName();
}
/**
* 从请求网址中获取记录总数、每页记录数、页码。
* Get recTotal, recPerpage, pageID from the request params, and add them to params.
*
* @access public
* @return void
*/
public function setParams()
{
$this->params = $this->app->getParams();
foreach($this->params as $key => $value)
{
if(strtolower($key) == 'rectotal') $this->params[$key] = $this->recTotal;
if(strtolower($key) == 'recperpage') $this->params[$key] = $this->recPerPage;
if(strtolower($key) == 'pageid') $this->params[$key] = $this->pageID;
}
parse_str(strip_tags(urldecode($_SERVER['QUERY_STRING'])), $query);
if(!empty($query['m']) && !empty($query['f']) && $query['m'] == $this->moduleName && $query['f'] == $this->methodName)
{
unset($query['m']);
unset($query['f']);
unset($query['t']);
$this->params = array_merge($this->params, $query);
}
}
/**
* 创建limit语句。
* Create the limit string.
*
* @access public
* @return string
*/
public function limit()
{
$limit = '';
if($this->pageTotal > 1) $limit = ' lImiT ' . ($this->pageID - 1) * $this->recPerPage . ", $this->recPerPage";
return $limit;
}
/**
* 向页面显示分页信息。
* Print the pager's html.
*
* @param string $align
* @param string $type
* @access public
* @return void
*/
public function show($align = 'right', $type = 'full')
{
if($align === 'justify')
{
echo $this->getJustify($type);
}
else
{
echo $this->get($align, $type);
}
}
/**
* 获取优化后的分页。
* Get the justify pager html string
*
* @access public
* @return [type] [description]
*/
public function getJustify()
{
if($this->recTotal <= 0) return '';
$this->setParams();
$pager = '';
$pager .= "<li class='previous" . ($this->pageID == 1 ? ' disabled' : '') . "'>";
$this->params['pageID'] = 1;
$pager .= $this->createLink('« ' . $this->lang->pager->previousPage) . '</li>';
$pager .= "<li class='caption'>";
$firstId = $this->recPerPage * ($this->pageID - 1) + 1;
$pager .= sprintf($this->lang->pager->summery, $firstId, max(min($this->recPerPage * $this->pageID, $this->recTotal), $firstId), $this->recTotal);
$pager .= '</li>';
$pager .= "<li class='next" . (($this->pageID == $this->pageTotal || $this->pageTotal <= 1) ? ' disabled' : '') . "'>";
$this->params['pageID'] = min($this->pageTotal, $this->pageID + 1);
$pager .= $this->createLink($this->lang->pager->nextPage . ' »') . '</li>';
return "<ul class='pager pager-justify'>{$pager}</ul>";
}
/**
* 设置分页信息的样式。
* Get the pager html string.
*
* @param string $align
* @param string $type the pager type, full|short|shortest
* @access public
* @return string
*/
public function get($align = 'right', $type = 'full')
{
/* 如果记录个数为0返回没有记录。 */
/* If the RecTotal is zero, return with no record. */
if($this->recTotal == 0) return $type == 'mobile' ? '' : "<div style='float:$align; clear:none;' class='page'>{$this->lang->pager->noRecord}</div>";
/* Set the params. */
$this->setParams();
/* 创建前一页和后一页链接。 */
/* Create the prePage and nextpage, all types have them. */
$pager = $this->createPrePage($type);
$pager .= $this->createNextPage($type);
/* 简单和完全模式。 The short and full type. */
if($type !== 'shortest' and $type !== 'mobile')
{
$pager = $this->createFirstPage() . $pager;
$pager .= $this->createLastPage();
}
if($type == 'mobile')
{
$position = $this->pageTotal == 1 ? '' : $this->pageID . '/' . $this->pageTotal;
$pager = $pager . ' ' . $position;
}
else if($type != 'full')
{
$pager = $this->pageID . '/' . $this->pageTotal . ' ' . $pager;
}
/* 只是完全模式。 Only the full type . */
if($type == 'full')
{
$pager = $this->createDigest() . $pager;
$pager .= $this->createGoTo();
$pager .= $this->createRecPerPageJS();
}
return "<div style='float:$align; clear:none;' class='pager form-inline'>$pager</div>";
}
/**
* 生成分页摘要信息。
* Create the digest code.
*
* @access public
* @return string
*/
public function createDigest()
{
return sprintf($this->lang->pager->digest, $this->recTotal, $this->createRecPerPageList(), $this->pageID, $this->pageTotal);
}
/**
* 创建首页链接。
* Create the first page.
*
* @access public
* @return string
*/
public function createFirstPage()
{
if($this->pageID == 1) return $this->lang->pager->first . ' ';
$this->params['pageID'] = 1;
return $this->createLink($this->lang->pager->first);
}
/**
* 创建前一页链接。
* Create the pre page html.
*
* @param string $type
* @access public
* @return string
*/
public function createPrePage($type = 'full')
{
if($type == 'mobile')
{
if($this->pageID == 1) return '';
$this->params['pageID'] = $this->pageID - 1;
return $this->createLink($this->lang->pager->pre);
}
else
{
if($this->pageID == 1) return $this->lang->pager->pre . ' ';
$this->params['pageID'] = $this->pageID - 1;
return $this->createLink($this->lang->pager->pre);
}
}
/**
* 创建下一页链接。
* Create the next page html.
*
* @param string $type
* @access public
* @return string
*/
public function createNextPage($type = 'full')
{
if($type == 'mobile')
{
if($this->pageID == $this->pageTotal) return '';
$this->params['pageID'] = $this->pageID + 1;
return $this->createLink($this->lang->pager->next);
}
else
{
if($this->pageID == $this->pageTotal) return $this->lang->pager->next . ' ';
$this->params['pageID'] = $this->pageID + 1;
return $this->createLink($this->lang->pager->next);
}
}
/**
* 创建最后一页链接。
* Create the last page
*
* @access public
* @return string
*/
public function createLastPage()
{
if($this->pageID == $this->pageTotal) return $this->lang->pager->last . ' ';
$this->params['pageID'] = $this->pageTotal;
return $this->createLink($this->lang->pager->last);
}
/**
* 创建每页显示记录数的select标签。
* Create the select object of record perpage.
*
* @access public
* @return string
*/
public function createRecPerPageJS()
{
/*
* 替换recTotal, recPerPage, pageID为特殊的字符串然后用js代码替换掉。
* Replace the recTotal, recPerPage, pageID to special string, and then replace them with values by JS.
**/
$params = $this->params;
foreach($params as $key => $value)
{
if(strtolower($key) == 'rectotal') $params[$key] = '_recTotal_';
if(strtolower($key) == 'recperpage') $params[$key] = '_recPerPage_';
if(strtolower($key) == 'pageid') $params[$key] = '_pageID_';
}
$vars = '';
foreach($params as $key => $value) $vars .= "$key=$value&";
$vars = rtrim($vars, '&');
$js = <<<EOT
<script language='Javascript'>
vars = '$vars';
pageCookie = '$this->pageCookie';
function submitPage(mode, perPage)
{
pageTotal = parseInt(document.getElementById('_pageTotal').value);
pageID = document.getElementById('_pageID').value;
recPerPage = document.getElementById('_recPerPage').getAttribute('data-value');
recTotal = document.getElementById('_recTotal').value;
if(mode == 'changePageID')
{
if(pageID > pageTotal) pageID = pageTotal;
if(pageID < 1) pageID = 1;
}
else if(mode == 'changeRecPerPage')
{
recPerPage = perPage;
pageID = 1;
}
$.cookie(pageCookie, recPerPage, {expires:config.cookieLife, path:config.webRoot});
vars = vars.replace('_recTotal_', recTotal)
vars = vars.replace('_recPerPage_', recPerPage)
vars = vars.replace('_pageID_', pageID);
location.href=createLink('$this->moduleName', '$this->methodName', vars);
}
</script>
EOT;
return $js;
}
/**
* 生成每页显示记录数的select列表。
* Create the select list of RecPerPage.
*
* @access public
* @return string
*/
public function createRecPerPageList()
{
for($i = 5; $i <= 50; $i += 5) $range[$i] = $i;
$range[100] = 100;
$range[200] = 200;
$range[500] = 500;
$range[1000] = 1000;
$range[2000] = 2000;
$html = "<div class='dropdown dropup'><a href='javascript:;' data-toggle='dropdown' id='_recPerPage' data-value='{$this->recPerPage}'>" . (sprintf($this->lang->pager->recPerPage, $this->recPerPage)) . "<span class='caret'></span></a><ul class='dropdown-menu'>";
foreach ($range as $key => $value)
{
$html .= '<li' . ($this->recPerPage == $value ? " class='active'" : '') .'>' . "<a href='javascript:submitPage(\"changeRecPerPage\", $value)'>{$value}</a>" . '</li>';
}
$html .= '</ul></div>';
return $html;
}
/**
* 生成跳转到指定页码的部分。
* Create the goto part html.
*
* @access public
* @return string
*/
public function createGoTo()
{
$goToHtml = "<input type='hidden' id='_recTotal' value='$this->recTotal' />\n";
$goToHtml .= "<input type='hidden' id='_pageTotal' value='$this->pageTotal' />\n";
$goToHtml .= "<input type='text' id='_pageID' value='$this->pageID' style='text-align:center;width:30px;' class='form-control' /> \n";
$goToHtml .= "<input type='button' id='goto' value='{$this->lang->pager->locate}' onclick='submitPage(\"changePageID\");' class='btn'/>";
return $goToHtml;
}
/**
* 创建链接。
* Create link.
*
* @param string $title
* @access public
* @return string
*/
public function createLink($title)
{
return html::a(helper::createLink($this->moduleName, $this->methodName, $this->params), $title);
}
}

View File

@ -0,0 +1,957 @@
<?php
/**
* CRON expression parser that can determine whether or not a CRON expression is
* due to run, the next run date and previous run date of a CRON expression.
* The determinations made by this class are accurate if checked run once per
* minute (seconds are dropped from date time comparisons).
*
* Schedule parts must map to:
* minute [0-59], hour [0-23], day of month, month [1-12|JAN-DEC], day of week
* [1-7|MON-SUN], and an optional year.
*
* @author Michael Dowling <mtdowling@gmail.com>
* @link http://en.wikipedia.org/wiki/Cron
*/
class CronExpression
{
const MINUTE = 0;
const HOUR = 1;
const DAY = 2;
const MONTH = 3;
const WEEKDAY = 4;
const YEAR = 5;
/**
* @var array CRON expression parts
*/
private $cronParts;
/**
* @var FieldFactory CRON field factory
*/
private $fieldFactory;
/**
* @var array Order in which to test of cron parts
*/
private static $order = array(self::YEAR, self::MONTH, self::DAY, self::WEEKDAY, self::HOUR, self::MINUTE);
/**
* Factory method to create a new CronExpression.
*
* @param string $expression The CRON expression to create. There are
* several special predefined values which can be used to substitute the
* CRON expression:
*
* @yearly, @annually) - Run once a year, midnight, Jan. 1 - 0 0 1 1 *
* @monthly - Run once a month, midnight, first of month - 0 0 1 * *
* @weekly - Run once a week, midnight on Sun - 0 0 * * 0
* @daily - Run once a day, midnight - 0 0 * * *
* @hourly - Run once an hour, first minute - 0 * * * *
* @param FieldFactory $fieldFactory (optional) Field factory to use
*
* @return CronExpression
*/
public static function factory($expression, FieldFactory $fieldFactory = null)
{
$mappings = array(
'@yearly' => '0 0 1 1 *',
'@annually' => '0 0 1 1 *',
'@monthly' => '0 0 1 * *',
'@weekly' => '0 0 * * 0',
'@daily' => '0 0 * * *',
'@hourly' => '0 * * * *'
);
if (isset($mappings[$expression])) {
$expression = $mappings[$expression];
}
return new self($expression, $fieldFactory ? $fieldFactory : new FieldFactory());
}
/**
* Parse a CRON expression
*
* @param string $expression CRON expression (e.g. '8 * * * *')
* @param FieldFactory $fieldFactory Factory to create cron fields
*/
public function __construct($expression, FieldFactory $fieldFactory)
{
$this->fieldFactory = $fieldFactory;
$this->setExpression($expression);
}
/**
* Set or change the CRON expression
*
* @param string $schedule CRON expression (e.g. 8 * * * *)
*
* @return CronExpression
* @throws InvalidArgumentException if not a valid CRON expression
*/
public function setExpression($value)
{
$this->cronParts = explode(' ', $value);
if (count($this->cronParts) < 5) {
throw new InvalidArgumentException(
$value . ' is not a valid CRON expression'
);
}
foreach ($this->cronParts as $position => $part) {
$this->setPart($position, $part);
}
return $this;
}
/**
* Set part of the CRON expression
*
* @param int $position The position of the CRON expression to set
* @param string $value The value to set
*
* @return CronExpression
* @throws InvalidArgumentException if the value is not valid for the part
*/
public function setPart($position, $value)
{
if (!$this->fieldFactory->getField($position)->validate($value)) {
throw new InvalidArgumentException(
'Invalid CRON field value ' . $value . ' as position ' . $position
);
}
$this->cronParts[$position] = $value;
return $this;
}
/**
* Get a next run date relative to the current date or a specific date
*
* @param string|DateTime $currentTime (optional) Relative calculation date
* @param int $nth (optional) Number of matches to skip before returning a
* matching next run date. 0, the default, will return the current
* date and time if the next run date falls on the current date and
* time. Setting this value to 1 will skip the first match and go to
* the second match. Setting this value to 2 will skip the first 2
* matches and so on.
* @param bool $allowCurrentDate (optional) Set to TRUE to return the
* current date if it matches the cron expression
*
* @return DateTime
* @throws RuntimeExpression on too many iterations
*/
public function getNextRunDate($currentTime = 'now', $nth = 0, $allowCurrentDate = false)
{
return $this->getRunDate($currentTime, $nth, false, $allowCurrentDate);
}
/**
* Get a previous run date relative to the current date or a specific date
*
* @param string|DateTime $currentTime (optional) Relative calculation date
* @param int $nth (optional) Number of matches to skip before returning
* @param bool $allowCurrentDate (optional) Set to TRUE to return the
* current date if it matches the cron expression
*
* @return DateTime
* @throws RuntimeExpression on too many iterations
* @see Cron\CronExpression::getNextRunDate
*/
public function getPreviousRunDate($currentTime = 'now', $nth = 0, $allowCurrentDate = false)
{
return $this->getRunDate($currentTime, $nth, true, $allowCurrentDate);
}
/**
* Get multiple run dates starting at the current date or a specific date
*
* @param int $total Set the total number of dates to calculate
* @param string|DateTime $currentTime (optional) Relative calculation date
* @param bool $invert (optional) Set to TRUE to retrieve previous dates
* @param bool $allowCurrentDate (optional) Set to TRUE to return the
* current date if it matches the cron expression
*
* @return array Returns an array of run dates
*/
public function getMultipleRunDates($total, $currentTime = 'now', $invert = false, $allowCurrentDate = false)
{
$matches = array();
for ($i = 0; $i < max(0, $total); $i++) {
$matches[] = $this->getRunDate($currentTime, $i, $invert, $allowCurrentDate);
}
return $matches;
}
/**
* Get all or part of the CRON expression
*
* @param string $part (optional) Specify the part to retrieve or NULL to
* get the full cron schedule string.
*
* @return string|null Returns the CRON expression, a part of the
* CRON expression, or NULL if the part was specified but not found
*/
public function getExpression($part = null)
{
if (null === $part) {
return implode(' ', $this->cronParts);
} else if (array_key_exists($part, $this->cronParts)) {
return $this->cronParts[$part];
}
return null;
}
/**
* Helper method to output the full expression.
*
* @return string Full CRON expression
*/
public function __toString()
{
return $this->getExpression();
}
/**
* Deterime if the cron is due to run based on the current date or a
* specific date. This method assumes that the current number of
* seconds are irrelevant, and should be called once per minute.
*
* @param string|DateTime $currentTime (optional) Relative calculation date
*
* @return bool Returns TRUE if the cron is due to run or FALSE if not
*/
public function isDue($currentTime = null)
{
if (null === $currentTime || 'now' === $currentTime) {
$currentDate = date('Y-m-d H:i');
$currentTime = strtotime($currentDate);
} else if ($currentTime instanceof DateTime) {
$currentDate = $currentTime->format('Y-m-d H:i');
$currentTime = strtotime($currentDate);
} else {
$currentTime = new DateTime($currentTime);
$currentTime->setTime($currentTime->format('H'), $currentTime->format('i'), 0);
$currentDate = $currentTime->format('Y-m-d H:i');
$currentTime = $currentTime->getTimeStamp();
}
return $this->getNextRunDate($currentDate, 0, true)->getTimestamp() == $currentTime;
}
/**
* Get the next or previous run date of the expression relative to a date
*
* @param string|DateTime $currentTime (optional) Relative calculation date
* @param int $nth (optional) Number of matches to skip before returning
* @param bool $invert (optional) Set to TRUE to go backwards in time
* @param bool $allowCurrentDate (optional) Set to TRUE to return the
* current date if it matches the cron expression
*
* @return DateTime
* @throws RuntimeExpression on too many iterations
*/
protected function getRunDate($currentTime = null, $nth = 0, $invert = false, $allowCurrentDate = false)
{
$currentDate = $currentTime instanceof DateTime
? $currentTime
: new DateTime($currentTime ? $currentTime : 'now');
// set the timezone
$currentDate->setTimezone(new DateTimeZone(date_default_timezone_get()));
$currentDate->setTime($currentDate->format('H'), $currentDate->format('i'), 0);
$nextRun = clone $currentDate;
$nth = (int) $nth;
// Set a hard limit to bail on an impossible date
for ($i = 0; $i < 1000; $i++) {
foreach (self::$order as $position) {
$part = $this->getExpression($position);
if (null === $part) {
continue;
}
$satisfied = false;
// Get the field object used to validate this part
$field = $this->fieldFactory->getField($position);
// Check if this is singular or a list
if (strpos($part, ',') === false) {
$satisfied = $field->isSatisfiedBy($nextRun, $part);
} else {
foreach (array_map('trim', explode(',', $part)) as $listPart) {
if ($field->isSatisfiedBy($nextRun, $listPart)) {
$satisfied = true;
break;
}
}
}
// If the field is not satisfied, then start over
if (!$satisfied) {
$field->increment($nextRun, $invert);
continue 2;
}
}
// Skip this match if needed
if ((!$allowCurrentDate && $nextRun == $currentDate) || --$nth > -1) {
$this->fieldFactory->getField(0)->increment($nextRun, $invert);
continue;
}
return $nextRun;
}
// @codeCoverageIgnoreStart
throw new RuntimeException('Impossible CRON expression');
// @codeCoverageIgnoreEnd
}
}
/**
* Abstract CRON expression field
*
* @author Michael Dowling <mtdowling@gmail.com>
*/
abstract class AbstractField implements FieldInterface
{
/**
* Check to see if a field is satisfied by a value
*
* @param string $dateValue Date value to check
* @param string $value Value to test
*
* @return bool
*/
public function isSatisfied($dateValue, $value)
{
if ($this->isIncrementsOfRanges($value)) {
return $this->isInIncrementsOfRanges($dateValue, $value);
} else if ($this->isRange($value)) {
return $this->isInRange($dateValue, $value);
}
return $value == '*' || $dateValue == $value;
}
/**
* Check if a value is a range
*
* @param string $value Value to test
*
* @return bool
*/
public function isRange($value)
{
return strpos($value, '-') !== false;
}
/**
* Check if a value is an increments of ranges
*
* @param string $value Value to test
*
* @return bool
*/
public function isIncrementsOfRanges($value)
{
return strpos($value, '/') !== false;
}
/**
* Test if a value is within a range
*
* @param string $dateValue Set date value
* @param string $value Value to test
*
* @return bool
*/
public function isInRange($dateValue, $value)
{
$parts = array_map('trim', explode('-', $value, 2));
return $dateValue >= $parts[0] && $dateValue <= $parts[1];
}
/**
* Test if a value is within an increments of ranges (offset[-to]/step size)
*
* @param string $dateValue Set date value
* @param string $value Value to test
*
* @return bool
*/
public function isInIncrementsOfRanges($dateValue, $value)
{
$parts = array_map('trim', explode('/', $value, 2));
$stepSize = isset($parts[1]) ? $parts[1] : 0;
if ($parts[0] == '*' || $parts[0] == 0) {
return (int) $dateValue % $stepSize == 0;
}
$range = explode('-', $parts[0], 2);
$offset = $range[0];
$to = isset($range[1]) ? $range[1] : $dateValue;
// Ensure that the date value is within the range
if ($dateValue < $offset || $dateValue > $to) {
return false;
}
for ($i = $offset; $i <= $to; $i+= $stepSize) {
if ($i == $dateValue) {
return true;
}
}
return false;
}
}
/**
* CRON field interface
*
* @author Michael Dowling <mtdowling@gmail.com>
*/
interface FieldInterface
{
/**
* Check if the respective value of a DateTime field satisfies a CRON exp
*
* @param DateTime $date DateTime object to check
* @param string $value CRON expression to test against
*
* @return bool Returns TRUE if satisfied, FALSE otherwise
*/
function isSatisfiedBy(DateTime $date, $value);
/**
* When a CRON expression is not satisfied, this method is used to increment
* or decrement a DateTime object by the unit of the cron field
*
* @param DateTime $date DateTime object to change
* @param bool $invert (optional) Set to TRUE to decrement
*
* @return FieldInterface
*/
function increment(DateTime $date, $invert = false);
/**
* Validates a CRON expression for a given field
*
* @param string $value CRON expression value to validate
*
* @return bool Returns TRUE if valid, FALSE otherwise
*/
function validate($value);
}
/**
* CRON field factory implementating a flyweight factory
*
* @author Michael Dowling <mtdowling@gmail.com>
* @link http://en.wikipedia.org/wiki/Cron
*/
class FieldFactory
{
/**
* @var array Cache of instantiated fields
*/
private $fields = array();
/**
* Get an instance of a field object for a cron expression position
*
* @param int $position CRON expression position value to retrieve
*
* @return FieldInterface
* @throws InvalidArgumentException if a position is not valide
*/
public function getField($position)
{
if (!isset($this->fields[$position])) {
switch ($position) {
case 0:
$this->fields[$position] = new MinutesField();
break;
case 1:
$this->fields[$position] = new HoursField();
break;
case 2:
$this->fields[$position] = new DayOfMonthField();
break;
case 3:
$this->fields[$position] = new MonthField();
break;
case 4:
$this->fields[$position] = new DayOfWeekField();
break;
case 5:
$this->fields[$position] = new YearField();
break;
default:
throw new InvalidArgumentException(
$position . ' is not a valid position'
);
}
}
return $this->fields[$position];
}
}
/**
* Day of month field. Allows: * , / - ? L W
*
* 'L' stands for "last" and specifies the last day of the month.
*
* The 'W' character is used to specify the weekday (Monday-Friday) nearest the
* given day. As an example, if you were to specify "15W" as the value for the
* day-of-month field, the meaning is: "the nearest weekday to the 15th of the
* month". So if the 15th is a Saturday, the trigger will fire on Friday the
* 14th. If the 15th is a Sunday, the trigger will fire on Monday the 16th. If
* the 15th is a Tuesday, then it will fire on Tuesday the 15th. However if you
* specify "1W" as the value for day-of-month, and the 1st is a Saturday, the
* trigger will fire on Monday the 3rd, as it will not 'jump' over the boundary
* of a month's days. The 'W' character can only be specified when the
* day-of-month is a single day, not a range or list of days.
*
* @author Michael Dowling <mtdowling@gmail.com>
*/
class DayOfMonthField extends AbstractField
{
/**
* Get the last day of the month
*
* @param DateTime $date Date object to check
*
* @param return int returns the last day of the month
*/
public static function getLastDayOfMonth(DateTime $date)
{
$month = $date->format('n');
if ($month == 2) {
return (bool) $date->format('L') ? 29 : 28;
} else {
$dates = array(
1 => 31,
3 => 31,
4 => 30,
5 => 31,
6 => 30,
7 => 31,
8 => 31,
9 => 30,
10 => 31,
11 => 30,
12 => 31
);
return $dates[$month];
}
}
/**
* Get the nearest day of the week for a given day in a month
*
* @param int $currentYear Current year
* @param int $currentYear Current month
* @param int $targetDay Target day of the month
*
* @return DateTime Returns the nearest date
*/
private static function getNearestWeekday($currentYear, $currentMonth, $targetDay)
{
$tday = str_pad($targetDay, 2, '0', STR_PAD_LEFT);
$target = DateTime::createFromFormat('Y-m-d', "$currentYear-$currentMonth-$tday");
$currentWeekday = (int) $target->format('N');
if ($currentWeekday < 6) {
return $target;
}
$lastDayOfMonth = self::getLastDayOfMonth($target);
foreach (array(-1, 1, -2, 2) as $i) {
$adjusted = $targetDay + $i;
if ($adjusted > 0 && $adjusted <= $lastDayOfMonth) {
$target->setDate($currentYear, $currentMonth, $adjusted);
if ($target->format('N') < 6 && $target->format('m') == $currentMonth) {
return $target;
}
}
}
}
/**
* {@inheritdoc}
*/
public function isSatisfiedBy(DateTime $date, $value)
{
// ? states that the field value is to be skipped
if ($value == '?') {
return true;
}
$fieldValue = $date->format('d');
// Check to see if this is the last day of the month
if ($value == 'L') {
return $fieldValue == self::getLastDayOfMonth($date);
}
// Check to see if this is the nearest weekday to a particular value
if (strpos($value, 'W')) {
// Parse the target day
$targetDay = substr($value, 0, strpos($value, 'W'));
// Find out if the current day is the nearest day of the week
return $date->format('j') == self::getNearestWeekday($date->format('Y'), $date->format('m'), $targetDay)->format('j');
}
return $this->isSatisfied($date->format('d'), $value);
}
/**
* {@inheritdoc}
*/
public function increment(DateTime $date, $invert = false)
{
if ($invert) {
$date->modify('-1 day');
$date->setTime(23, 59, 0);
} else {
$date->modify('+1 day');
$date->setTime(0, 0, 0);
}
return $this;
}
/**
* {@inheritdoc}
*/
public function validate($value)
{
return (bool) preg_match('/[\*,\/\-\?LW0-9A-Za-z]+/', $value);
}
}
/**
* Day of week field. Allows: * / , - ? L #
*
* Days of the week can be represented as a number 0-7 (0|7 = Sunday)
* or as a three letter string: SUN, MON, TUE, WED, THU, FRI, SAT.
*
* 'L' stands for "last". It allows you to specify constructs such as
* "the last Friday" of a given month.
*
* '#' is allowed for the day-of-week field, and must be followed by a
* number between one and five. It allows you to specify constructs such as
* "the second Friday" of a given month.
*
* @author Michael Dowling <mtdowling@gmail.com>
*/
class DayOfWeekField extends AbstractField
{
/**
* {@inheritdoc}
*/
public function isSatisfiedBy(DateTime $date, $value)
{
if ($value == '?') {
return true;
}
// Convert text day of the week values to integers
$value = strtr($value, array(
'SUN' => 0,
'MON' => 1,
'TUE' => 2,
'WED' => 3,
'THU' => 4,
'FRI' => 5,
'SAT' => 6
));
$currentYear = $date->format('Y');
$currentMonth = $date->format('m');
$lastDayOfMonth = DayOfMonthField::getLastDayOfMonth($date);
// Find out if this is the last specific weekday of the month
if (strpos($value, 'L')) {
$weekday = str_replace('7', '0', substr($value, 0, strpos($value, 'L')));
$tdate = clone $date;
$tdate->setDate($currentYear, $currentMonth, $lastDayOfMonth);
while ($tdate->format('w') != $weekday) {
$tdate->setDate($currentYear, $currentMonth, --$lastDayOfMonth);
}
return $date->format('j') == $lastDayOfMonth;
}
// Handle # hash tokens
if (strpos($value, '#')) {
list($weekday, $nth) = explode('#', $value);
// Validate the hash fields
if ($weekday < 1 || $weekday > 5) {
throw new InvalidArgumentException("Weekday must be a value between 1 and 5. {$weekday} given");
}
if ($nth > 5) {
throw new InvalidArgumentException('There are never more than 5 of a given weekday in a month');
}
// The current weekday must match the targeted weekday to proceed
if ($date->format('N') != $weekday) {
return false;
}
$tdate = clone $date;
$tdate->setDate($currentYear, $currentMonth, 1);
$dayCount = 0;
$currentDay = 1;
while ($currentDay < $lastDayOfMonth + 1) {
if ($tdate->format('N') == $weekday) {
if (++$dayCount >= $nth) {
break;
}
}
$tdate->setDate($currentYear, $currentMonth, ++$currentDay);
}
return $date->format('j') == $currentDay;
}
// Handle day of the week values
if (strpos($value, '-')) {
$parts = explode('-', $value);
if ($parts[0] == '7') {
$parts[0] = '0';
} else if ($parts[1] == '0') {
$parts[1] = '7';
}
$value = implode('-', $parts);
}
// Test to see which Sunday to use -- 0 == 7 == Sunday
$format = in_array(7, str_split($value)) ? 'N' : 'w';
$fieldValue = $date->format($format);
return $this->isSatisfied($fieldValue, $value);
}
/**
* {@inheritdoc}
*/
public function increment(DateTime $date, $invert = false)
{
if ($invert) {
$date->modify('-1 day');
$date->setTime(23, 59, 0);
} else {
$date->modify('+1 day');
$date->setTime(0, 0, 0);
}
return $this;
}
/**
* {@inheritdoc}
*/
public function validate($value)
{
return (bool) preg_match('/[\*,\/\-0-9A-Z]+/', $value);
}
}
/**
* Hours field. Allows: * , / -
*
* @author Michael Dowling <mtdowling@gmail.com>
*/
class HoursField extends AbstractField
{
/**
* {@inheritdoc}
*/
public function isSatisfiedBy(DateTime $date, $value)
{
return $this->isSatisfied($date->format('H'), $value);
}
/**
* {@inheritdoc}
*/
public function increment(DateTime $date, $invert = false)
{
if ($invert) {
$date->modify('-1 hour');
$date->setTime($date->format('H'), 59, 0);
} else {
$date->modify('+1 hour');
$date->setTime($date->format('H'), 0, 0);
}
return $this;
}
/**
* {@inheritdoc}
*/
public function validate($value)
{
return (bool) preg_match('/[\*,\/\-0-9]+/', $value);
}
}
/**
* Minutes field. Allows: * , / -
*
* @author Michael Dowling <mtdowling@gmail.com>
*/
class MinutesField extends AbstractField
{
/**
* {@inheritdoc}
*/
public function isSatisfiedBy(DateTime $date, $value)
{
return $this->isSatisfied($date->format('i'), $value);
}
/**
* {@inheritdoc}
*/
public function increment(DateTime $date, $invert = false)
{
if ($invert) {
$date->modify('-1 minute');
} else {
$date->modify('+1 minute');
}
return $this;
}
/**
* {@inheritdoc}
*/
public function validate($value)
{
return (bool) preg_match('/[\*,\/\-0-9]+/', $value);
}
}
/**
* Month field. Allows: * , / -
*
* @author Michael Dowling <mtdowling@gmail.com>
*/
class MonthField extends AbstractField
{
/**
* {@inheritdoc}
*/
public function isSatisfiedBy(DateTime $date, $value)
{
// Convert text month values to integers
$value = strtr($value, array(
'JAN' => 1,
'FEB' => 2,
'MAR' => 3,
'APR' => 4,
'MAY' => 5,
'JUN' => 6,
'JUL' => 7,
'AUG' => 8,
'SEP' => 9,
'OCT' => 10,
'NOV' => 11,
'DEC' => 12
));
return $this->isSatisfied($date->format('m'), $value);
}
/**
* {@inheritdoc}
*/
public function increment(DateTime $date, $invert = false)
{
$year = $date->format('Y');
if ($invert) {
$month = $date->format('m') - 1;
if ($month < 1) {
$month = 12;
$year--;
}
$date->setDate($year, $month, 1);
$date->setDate($year, $month, DayOfMonthField::getLastDayOfMonth($date));
$date->setTime(23, 59, 0);
} else {
$month = $date->format('m') + 1;
if ($month > 12) {
$month = 1;
$year++;
}
$date->setDate($year, $month, 1);
$date->setTime(0, 0, 0);
}
return $this;
}
/**
* {@inheritdoc}
*/
public function validate($value)
{
return (bool) preg_match('/[\*,\/\-0-9A-Z]+/', $value);
}
}
/**
* Year field. Allows: * , / -
*
* @author Michael Dowling <mtdowling@gmail.com>
*/
class YearField extends AbstractField
{
/**
* {@inheritdoc}
*/
public function isSatisfiedBy(DateTime $date, $value)
{
return $this->isSatisfied($date->format('Y'), $value);
}
/**
* {@inheritdoc}
*/
public function increment(DateTime $date, $invert = false)
{
if ($invert) {
$date->modify('-1 year');
$date->setDate($date->format('Y'), 12, 31);
$date->setTime(23, 59, 0);
} else {
$date->modify('+1 year');
$date->setDate($date->format('Y'), 1, 1);
$date->setTime(0, 0, 0);
}
return $this;
}
/**
* {@inheritdoc}
*/
public function validate($value)
{
return (bool) preg_match('/[\*,\/\-0-9]+/', $value);
}
}

0
lib/crontab/index.html Normal file
View File

209
lib/dao/dao.class.php Normal file
View File

@ -0,0 +1,209 @@
<?php
/**
* ZenTaoPHP的dao和sql类。
* The dao and sql class file of ZenTaoPHP framework.
*
* The author disclaims copyright to this source code. In place of
* a legal notice, here is a blessing:
*
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
*/
helper::import(dirname(dirname(__FILE__)) . '/base/dao/dao.class.php');
/**
* DAO类。
* DAO, data access object.
*
* @package framework
*/
class dao extends baseDAO
{
/**
* 检查字段是否满足条件。
* Check a filed is satisfied with the check rule.
*
* @param string $fieldName the field to check
* @param string $funcName the check rule
* @param string $condition the condition
* @access public
* @return object the dao object self.
*/
public function check($fieldName, $funcName, $condition = '')
{
/*
* 如果没数据中没有该字段,直接返回。
* If no this field in the data, return.
**/
if(!isset($this->sqlobj->data->$fieldName)) return $this;
/* 设置字段值。 */
/* Set the field label and value. */
global $lang, $config, $app;
$table = strtolower(substr($this->table, strrpos($this->table, '_') + 1));
$table = str_replace('`', '', $table);
$fieldLabel = isset($lang->$table->$fieldName) ? $lang->$table->$fieldName : $fieldName;
$value = isset($this->sqlobj->data->$fieldName) ? $this->sqlobj->data->$fieldName : null;
/*
* 检查唯一性。
* Check unique.
**/
if($funcName == 'unique')
{
$args = func_get_args();
$sql = "SELECT COUNT(*) AS count FROM $this->table WHERE `$fieldName` = " . $this->sqlobj->quote($value);
if($condition) $sql .= ' AND ' . $condition;
try
{
$row = $this->dbh->query($sql)->fetch();
if($row->count != 0) $this->logError($funcName, $fieldName, $fieldLabel, array($value));
}
catch (PDOException $e)
{
$this->sqlError($e);
}
}
else
{
/*
* 创建参数。
* Create the params.
**/
$funcArgs = func_get_args();
unset($funcArgs[0]);
unset($funcArgs[1]);
for($i = 0; $i < VALIDATER::MAX_ARGS; $i ++)
{
${"arg$i"} = isset($funcArgs[$i + 2]) ? $funcArgs[$i + 2] : null;
}
$checkFunc = 'check' . $funcName;
if(validater::$checkFunc($value, $arg0, $arg1, $arg2) === false)
{
$this->logError($funcName, $fieldName, $fieldLabel, $funcArgs);
}
}
return $this;
}
/**
* 获取查询记录条数。
* The count method, call sql::select() and from().
* use as $this->dao->select()->from(TABLE_BUG)->where()->count();
*
* @param string $distinctField
* @access public
* @return void
*/
public function count($distinctField = '')
{
/* 获得SELECTFROM的位置使用count(*)替换其字段。 */
/* Get the SELECT, FROM position, thus get the fields, replace it by count(*). */
$sql = $this->get();
$selectPOS = strpos($sql, 'SELECT') + strlen('SELECT');
$fromPOS = strpos($sql, 'FROM');
$fields = substr($sql, $selectPOS, $fromPOS - $selectPOS);
$countField = $distinctField ? 'distinct ' . $distinctField : '*';
$sql = str_replace($fields, " COUNT($countField) AS recTotal ", substr($sql, 0, $fromPOS)) . substr($sql, $fromPOS);
/*
* 去掉SQL语句中group, order和limit之后的部分。
* Remove the part after group, order and limit.
**/
$subLength = strlen($sql);
$groupPOS = strripos($sql, 'group by');
$orderPOS = strripos($sql, 'order by');
$limitPOS = strripos($sql, 'limit');
if($limitPOS) $subLength = $limitPOS;
if($orderPOS) $subLength = $orderPOS;
if($groupPOS) $subLength = $groupPOS;
$sql = substr($sql, 0, $subLength);
self::$querys[] = $sql;
/*
* 获取记录数。
* Get the records count.
**/
try
{
$row = $this->dbh->query($sql)->fetch(PDO::FETCH_OBJ);
}
catch (PDOException $e)
{
$this->sqlError($e);
}
return is_object($row) ? $row->recTotal : 0;
}
}
/**
* SQL类。
* The SQL class.
*
* @package framework
*/
class sql extends baseSQL
{
public $checkGroupBy = true;
/**
* Set Check groupby.
*
* @param bool $open
* @access public
* @return void
*/
public function setCheckGroupBy($open = true)
{
$this->checkGroupBy = $open;
}
/**
* 创建ORDER BY部分。
* Create the order by part.
*
* @param string $order
* @access public
* @return object the sql object.
*/
public function orderBy($order)
{
if(strpos($order, 'convert(') !== false)
{
if($this->inCondition and !$this->conditionIsTrue) return $this;
$order = str_replace(array('|', '', '_'), ' ', $order);
$this->sql .= ' ' . DAO::ORDERBY . " $order";
return $this;
}
else
{
return parent::orderBy($order);
}
}
/**
* 创建GROUP BY部分。
* Create the groupby part.
*
* @param string $groupBy
* @access public
* @return object the sql object.
*/
public function groupBy($groupBy)
{
if($this->inCondition and !$this->conditionIsTrue) return $this;
if($this->checkGroupBy and !preg_match('/^\w+[a-zA-Z0-9_`.,\s]+$/', $groupBy))
{
$groupBy = htmlspecialchars($groupBy);
die("Group is bad query, The group is $groupBy");
}
$this->sql .= ' ' . DAO::GROUPBY . " $groupBy";
return $this;
}
}

0
lib/dao/index.html Normal file
View File

560
lib/excel/excel.class.php Normal file
View File

@ -0,0 +1,560 @@
<?php
/**
* The excel library of xxb, can be used to export excel file.
*
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd., www.zentao.net)
* @license ZOSL (https://zpl.pub/page/zoslv1.html)
* @author Gang Liu <liugang@cnezsoft.com>
* @author yaozeyuan <yaozeyuan@cnezsoft.com>
* @package Excel
* @version $Id$
* @link https://xuanim.com
*
* excel - a library to export excel file, depends on phpexcel.
*
* Here are some tips of excelData(named $data) structure maybe uesful. you can use these to create xls/xlsx file . The API is interchangeable.
*
* Base property:
* data->fileName set the fileName
* data->kind set the kind of excel module
* data->fields is array like ($field => $fieldTitle). The order of data->fields is also the column's order
* data->row is array like ($rowNumber => array($field => $value)).This is the data of Excel file. System will fill $value as data into every cell according to $rowNumber and $field
*
* Merge cell
* if there is set data->dataRowspan[$row][$field] or data->dataColspan[$row][$field], the cells will be merge
* data->dataRowspan[$row][$field] => merge excelKey[$field]:$rowNumber to excelKey[$field]:($rowNumber + data->dataRowspan[$row][$field]) into one cell
* data->dataColspan[$row][$field] => merge excelKey[$field]:$rowNumber to transIntoExcelKey(int(excelKey[$field]) + dataColspan[$row][$field]):$rowNumber into one cell
*
* html content
* if you set config->excel->editor[$this->rawExcelData->kind] like 'excelKey1,excelKey2...', and excelKey in that, then $value of all column's cell will be process to remove html tag
*
* write sysData and use droplist style on cell
* sysData is an array like (excelKey => valueList), system use this sheet to store extraData.
* if you want to have droplist style on some column in sheet1, you can set data->($exceKey . 'List'), data->listStyle and data->sysData sothat the data will be writen into the sysData sheet and you can see the droplist style is enable.
* the data->listStyle and data->sysData is an array of series value like ['dropListStyleColumnName' . 'List'] , like ('nameList', 'categoryList', ...) the dropListStyleColumnName used to indicate witch column need that style and data->[dropListStyleColumnName . 'List'] use to transfer data for system get real data to build datalist in sysdata sheet.
*
* FreezePane
* if you set config->excel->freeze->{$this->data->kind}->targetColumnName, this column will be freezed
*
* Set width
* You can set $data->customWidth like array($field => width, $field2 => width, $field3 => width,...) to set width by you like
* or modify
* config->excel->titleFields
* config->excel->centerFields
* config->excel->dateFields
* to have default style
*
* color
* if you set data->nocolor, the excel file won't have color
*
* File title
* The lang->excel->title->{data->kind} is the title of data->kind excel file
*
* SysData title
* The lang->excel->title->sysValue is the name of sysData sheet , this is only can use for xls file.
*/
class excel extends model
{
/**
* __construct
*
* @access public
* @return void
*/
public function __construct()
{
parent::__construct();
$this->phpExcel = $this->app->loadClass('phpexcel');
$this->file = $this->loadModel('file');
$this->sysDataColIndex = 0;
$this->hasSysData = false;
}
/**
* Init for excel data.
*
* @param int $data
* @access public
* @return void
*/
public function init($data)
{
$this->rawExcelData = $data;
$this->fields = $data->fields;
$this->rows = $data->rows;
$this->headerRowCount = isset($data->headerRowCount) ? $data->headerRowCount : 1;
$this->fieldsKey = $this->headerRowCount == 1 ? array_keys($this->fields) : array_keys(reset($this->fields));
}
/**
* Export data to Excel. This is main function.
*
* @param object $data
* @param string $fileType xls | xlsx
* @param string $savePath, if $savePath != '', then the file will save in $savePath
* @access public
* @return void
*/
public function export($excelData, $fileType = 'xls', $savePath = '', $schemaSheets = '', $schemaSheetIndex = null)
{
$sheetIndex = 0;
foreach($excelData->dataList as $data) $this->phpExcel->createSheet(); // Create sheets.
foreach($excelData->dataList as $data)
{
$this->init($data);
$this->excelKey = array();
foreach($this->fieldsKey as $colIndex => $field) $this->excelKey[$field] = $this->setExcelField($colIndex);
/* Set file base property */
$excelProps = $this->phpExcel->getProperties();
$excelProps->setCreator('ZDOO');
$excelProps->setLastModifiedBy('ZDOO');
$excelProps->setTitle('Office XLS Document');
$excelProps->setSubject('Office XLS Document');
$excelProps->setDescription('Document generated by PHPExcel.');
$excelProps->setKeywords('office excel PHPExcel');
$excelProps->setCategory('Result file');
$excelSheet = $this->phpExcel->getSheet($sheetIndex);
$sheetTitle = isset($this->rawExcelData->title) ? $this->rawExcelData->title : $this->rawExcelData->kind;
if($sheetTitle) $excelSheet->setTitle($sheetTitle);
$sheetRow = 1;
if($this->headerRowCount == 1)
{
foreach($this->fields as $field => $fieldName)
{
$cell = $this->excelKey[$field] . $sheetRow;
$excelSheet->setCellValueExplicit($cell, $fieldName, PHPExcel_Cell_DataType::TYPE_STRING);
}
$sheetRow++;
}
else
{
foreach($this->fields as $fieldIndex => $fields)
{
foreach($fields as $field => $fieldName)
{
if(isset($this->excelKey[$field]))
{
$cell = $this->excelKey[$field] . $sheetRow;
/* Merge Cells.*/
if(isset($this->rawExcelData->headerRowspan[$fieldIndex][$field]) && is_int($this->rawExcelData->headerRowspan[$fieldIndex][$field]))
{
$endCell = $this->excelKey[$field] . ($sheetRow + $this->rawExcelData->headerRowspan[$fieldIndex][$field] - 1);
$excelSheet->mergeCells($cell . ":" . $endCell);
}
if(isset($this->rawExcelData->headerColspan[$fieldIndex][$field]) && is_int($this->rawExcelData->headerColspan[$fieldIndex][$field]))
{
$column = $this->setExcelField($this->rawExcelData->headerColspan[$fieldIndex][$field] - 1, $this->excelKey[$field]);
$endCell = $column . $sheetRow;
$excelSheet->mergeCells($cell . ":" . $endCell);
}
$excelSheet->setCellValueExplicit($cell, $fieldName, PHPExcel_Cell_DataType::TYPE_STRING);
}
}
$sheetRow++;
}
}
/* Write system data in excel.*/
$this->writeSysData();
foreach($this->rows as $rowIndex => $row)
{
foreach($row as $field => $value)
{
if(isset($this->excelKey[$field]))
{
$cell = $this->excelKey[$field] . $sheetRow;
/* Merge Cells.*/
if(isset($this->rawExcelData->dataRowspan[$rowIndex][$field]) && is_int($this->rawExcelData->dataRowspan[$rowIndex][$field]))
{
$endCell = $this->excelKey[$field] . ($sheetRow + $this->rawExcelData->dataRowspan[$rowIndex][$field] - 1);
$excelSheet->mergeCells($cell . ":" . $endCell);
}
if(isset($this->rawExcelData->dataColspan[$rowIndex][$field]) && is_int($this->rawExcelData->dataColspan[$rowIndex][$field]))
{
$column = $this->setExcelField($this->rawExcelData->dataColspan[$rowIndex][$field] - 1, $this->excelKey[$field]);
$endCell = $column . $sheetRow;
$excelSheet->mergeCells($cell . ":" . $endCell);
}
/* Wipe off html tags.*/
if(isset($this->config->excel->editor[$this->rawExcelData->kind]) and in_array($field, $this->config->excel->editor[$this->rawExcelData->kind])) $value = $this->file->excludeHtml($value);
if(isset($this->rawExcelData->percentageFields[$rowIndex][$field]))
{
$excelSheet->setCellValueExplicit($cell, $value, PHPExcel_Cell_DataType::TYPE_STRING);
}
elseif(isset($this->rawExcelData->numberFields) && in_array($field, $this->rawExcelData->numberFields))
{
$excelSheet->setCellValueExplicit($cell, $value, PHPExcel_Cell_DataType::TYPE_NUMERIC);
}
else
{
$excelSheet->setCellValueExplicit($cell, $value, PHPExcel_Cell_DataType::TYPE_STRING);
}
/* Add comments to cell, Excel5 don't work, must be Excel2007. */
if(isset($this->rawExcelData->comments[$rowIndex][$field]))
{
$excelSheet->getComment($cell)->getText()->createTextRun($this->rawExcelData->comments[$rowIndex][$field]);
}
/* Calculate date. */
if($value && (strpos($field, 'Date') !== false or in_array($field, $this->config->excel->dateFields)))
{
$excelSheet->setCellValue($cell, PHPExcel_Calculation_DateTime::DATEVALUE($value));
}
}
/* Build excel list.*/
if(isset($this->rawExcelData->listStyle) and in_array($field, $this->rawExcelData->listStyle)) $this->buildList($excelSheet, $field, $sheetRow);
}
$sheetRow++;
}
$this->setStyle($excelSheet, $sheetRow);
$this->setAlignment($excelSheet);
$sheetRow++;
if(isset($this->rawExcelData->help))
{
$excelSheet->mergeCells("A" . $sheetRow . ":" . end($this->excelKey) . $sheetRow);
$excelSheet->setCellValue("A" . $sheetRow, $this->rawExcelData->help);
}
$sheetIndex++;
}
/* If hasn't sys data remove the last sheet. */
if(!$this->hasSysData) $this->phpExcel->removeSheetByIndex($this->phpExcel->getSheetCount() - 1);
$this->phpExcel->setActiveSheetIndex(0);
if(!empty($schemaSheets))
{
foreach($schemaSheets as $schemaSheet)
{
$schemaSheetRows = $schemaSheet->getHighestRow();
if($schemaSheetRows > 1) $this->phpExcel->addSheet($schemaSheet, $schemaSheetIndex);
}
}
/* urlencode the filename for ie. */
$fileName = $excelData->fileName;
if(strpos($this->server->http_user_agent, 'MSIE') !== false || strpos($this->server->http_user_agent, 'Trident') !== false) $fileName = urlencode($fileName);
$writer = $fileType == 'xls' ? 'Excel5' : 'Excel2007';
$excelWriter = PHPExcel_IOFactory::createWriter($this->phpExcel, $writer);
$excelWriter->setPreCalculateFormulas(false);
if($savePath == '')
{
/* Clean the ob content to make sure no space or utf-8 bom output. */
$obLevel = ob_get_level();
for($i = 0; $i < $obLevel; $i++) ob_end_clean();
setcookie('downloading', 1);
header('Content-Type: application/vnd.ms-excel');
header("Content-Disposition: attachment;filename=\"{$fileName}.{$fileType}\"");
header('Cache-Control: max-age=0');
$excelWriter->save('php://output');
}
else
{
$excelWriter->save($savePath);
}
exit;
}
/**
* Set excel filed name.
*
* @param int $colIndex
* @param string $letter
* @access public
* @return string
*/
public function setExcelField($colIndex, $letter = 'A')
{
for($i = 1; $i <= $colIndex; $i++) $letter++;
return $letter;
}
/**
* Write SysData sheet in xls.
*
* @access public
* @return void
*/
public function writeSysData()
{
if(!isset($this->rawExcelData->sysDataList)) return true;
$this->hasSysData = true;
$sheetIndex = $this->phpExcel->getSheetCount() - 1;
$this->phpExcel->getSheet($sheetIndex)->setTitle($this->lang->excel->title->sysValue);
foreach($this->rawExcelData->sysDataList as $field)
{
$column = $this->setExcelField($this->sysDataColIndex);
$dataKey = $field . 'List';
if(!isset($this->rawExcelData->$dataKey)) continue;
$row = 1;
foreach($this->rawExcelData->$dataKey as $value)
{
$this->phpExcel->getSheet($sheetIndex)->setCellValueExplicit("$column$row", $value, PHPExcel_Cell_DataType::TYPE_STRING);
$row++;
}
$this->sysDataColIndex++;
}
}
/**
* Build dropmenu list.
* For a tip , if you want to modify that function , search "phpExcel DataValidation namedRange" in stackoverflow.com maybe helpful.
*
* @param int $excelSheet
* @param int $field
* @param int $row
* @access public
* @return void
*/
public function buildList($excelSheet, $field, $row)
{
$listName = $field . 'List';
$colIndex = array_search($field, $this->rawExcelData->sysDataList);
$column = $this->setExcelField($colIndex);
if(isset($this->rawExcelData->$listName))
{
$itemCount = count($this->rawExcelData->$listName);
if($itemCount == 0) $itemCount = 1;
$range = "{$this->lang->excel->title->sysValue}!\${$column}\$1:\${$column}\$" . $itemCount;
}
else
{
$range = is_array($this->rawExcelData->$listName) ? '' : '"' . $this->rawExcelData->$listName . '"';
}
$objValidation = $excelSheet->getCell($this->excelKey[$field] . $row)->getDataValidation();
$objValidation->setType(PHPExcel_Cell_DataValidation::TYPE_LIST)
->setErrorStyle(PHPExcel_Cell_DataValidation::STYLE_INFORMATION)
->setAllowBlank(false)
->setShowErrorMessage(false)
->setShowDropDown(true)
->setErrorTitle($this->lang->excel->error->title)
->setError($this->lang->excel->error->info)
->setFormula1($range);
}
/**
* Set excel style.
*
* @param object $excelSheet
* @param int $endRow
* @access public
* @return void
*/
public function setStyle($excelSheet, $endRow)
{
$startRow = $this->headerRowCount + 1;
$endColumn = $this->setExcelField(count($this->excelKey) - 1);
if(isset($this->rawExcelData->help) and isset($this->rawExcelData->extraNum)) $endRow--;
/* Freeze column.*/
if(isset($this->config->excel->freeze->{$this->rawExcelData->kind}))
{
$column = $this->excelKey[$this->config->excel->freeze->{$this->rawExcelData->kind}];
$column++;
$excelSheet->FreezePane($column . $startRow);
}
/* Set row height. */
$excelSheet->getRowDimension(1)->setRowHeight(20);
/* Set header style for this table.*/
$headerStyle = array(
'borders' => array(
'allborders' => array(
'style' => PHPExcel_Style_Border::BORDER_THIN,
'color' => array('rgb' => '808080')
)
),
'font' => array(
'bold' => true,
'color' => array('rgb' => 'ffffff')
),
'alignment' => array(
'horizontal' => PHPExcel_Style_Alignment::HORIZONTAL_CENTER,
'vertical' => PHPExcel_Style_Alignment::VERTICAL_CENTER
),
'fill' => array(
'type' => PHPExcel_Style_Fill::FILL_SOLID,
'startcolor' => array('rgb' => '343399')
)
);
if(isset($this->rawExcelData->nocolor))
{
$headerStyle['font']['color']['rgb'] = '000000';
$headerStyle['fill']['startcolor']['rgb'] = 'ffffff';
}
$this->setAreaStyle($excelSheet, $headerStyle, 'A1:' . $endColumn . $this->headerRowCount);
/* Set content style for this table.*/
$contentStyle = array(
'font' => array(
'size' => 9
),
'alignment' => array(
'vertical' => PHPExcel_Style_Alignment::VERTICAL_CENTER,
'wrap' => true
),
'borders' => array(
'allborders' => array(
'style' => PHPExcel_Style_Border::BORDER_THIN,
'color' => array('rgb' => '808080')
)
)
);
$this->setAreaStyle($excelSheet, $contentStyle, 'A' . $startRow . ':' . $endColumn . $endRow);
/* Set column width and style. */
$customWidth = isset($this->rawExcelData->customWidth) ? array_keys($this->rawExcelData->customWidth) : array();
foreach($this->excelKey as $key => $letter)
{
$titleWidth = $this->config->excel->width->title;
$contWidth = $this->config->excel->width->content;
/* Set width of date fields. */
if(strpos($key, 'Date') !== false) $excelSheet->getColumnDimension($letter)->setWidth(12);
/* Set width of title fields. */
if(in_array($key, $this->config->excel->titleFields)) $excelSheet->getColumnDimension($letter)->setWidth($titleWidth);
/* Set width of editor fields. */
if(isset($this->config->excel->editor[$this->rawExcelData->kind]) and in_array($key, $this->config->excel->editor[$this->rawExcelData->kind]))
{
$excelSheet->getColumnDimension($letter)->setWidth($contWidth);
}
/* Set cell format of center fields. */
if(in_array($key, $this->config->excel->centerFields))
{
$centerStyle = array(
'font' => array(
'size' => 9
),
'alignment' => array(
'horizontal' => PHPExcel_Style_Alignment::HORIZONTAL_CENTER
),
'borders' => array(
'allborders' => array(
'style' => PHPExcel_Style_Border::BORDER_THIN,
'color' => array('rgb' => '808080')
)
)
);
$this->setAreaStyle($excelSheet, $centerStyle, $letter . $startRow . ':' . $letter . $endRow);
}
/* Set cell format of date fields. */
if(strpos($key, 'Date') !== false or in_array($key, $this->config->excel->dateFields))
{
$dateFormat = array(
'font' => array(
'size' => 9
),
'alignment' => array(
'vertical' => PHPExcel_Style_Alignment::VERTICAL_CENTER,
'wrap' => true
),
'numberformat' => array(
'code' => PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD2
),
'borders' => array(
'allborders' => array(
'style' => PHPExcel_Style_Border::BORDER_THIN,
'color' => array('rgb' => '808080')
)
)
);
$this->setAreaStyle($excelSheet, $dateFormat, $letter . $startRow . ':' . $letter . $endRow);
}
/* Set column width by userdefined settings. */
if(in_array($key, $customWidth)) $excelSheet->getColumnDimension($letter)->setWidth($this->rawExcelData->customWidth[$key]);
}
/* Set row color. */
if(isset($this->rawExcelData->colors))
{
foreach($this->rawExcelData->colors as $row => $color)
{
$beginColumn = $this->excelKey[$color->begin];
$endColumn = $this->excelKey[$color->end];
$excelSheet->getStyle("$beginColumn$row:$endColumn$row")->getFill()->setFillType(PHPExcel_Style_Fill::FILL_SOLID);
$excelSheet->getStyle("$beginColumn$row:$endColumn$row")->getFill()->getStartColor()->setRGB($color->color);
}
}
elseif(!isset($this->rawExcelData->nocolor))
{
/* Set interlaced color for this table. */
for($row = $startRow; $row <= $endRow; $row++)
{
$excelSheet->getRowDimension($row)->setRowHeight(20);
$area = "A$row:$endColumn$row";
$color = $row % 2 == 0 ? 'FFB2D7EA' : 'FFdee6fb';
$excelStyle = $excelSheet->getStyle($area);
$excelFill = $excelStyle->getFill();
$excelFill->setFillType(PHPExcel_Style_Fill::FILL_SOLID);
$excelFill->getStartColor()->setARGB($color);
}
}
}
/**
* Set area style.
*
* @param object $excelSheet
* @param array $style
* @param string $area
* @access public
* @return void
*/
public function setAreaStyle($excelSheet, $style, $area)
{
$styleObj = new PHPExcel_Style();
$styleObj->applyFromArray($style);
$excelSheet->setSharedStyle($styleObj, $area);
}
/**
* Set alignment.
*
* @param object $excelSheet
* @access public
* @return bool
*/
public function setAlignment($excelSheet)
{
if(!isset($this->rawExcelData->percentageFields)) return true;
foreach($this->rawExcelData->percentageFields as $row => $fields)
{
foreach($fields as $key => $field)
{
if(isset($this->excelKey[$key]))
{
$cell = $this->excelKey[$key] . ($this->headerRowCount + $row + 1);
$excelSheet->getStyle($cell)->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_RIGHT);
}
}
}
}
}

0
lib/excel/index.html Normal file
View File

Some files were not shown because too many files have changed in this diff Show More