游戏桌面mac显示桌面快捷键array什么意思

IOS开发中有时用到这个@[]来代替数组,是什么意思?_百度知道
IOS开发中有时用到这个@[]来代替数组,是什么意思?
我有更好的答案
只不过是苹果给objective-C一种新写法而已比如NSNumber * number = [NSNumber numberWithInt:1];NSArray * array = [NSArray arrayWithObjects:@&one&, @&two&, nil];NSDictionary * dict = [NSDictionary dictionaryWithObjectsAndKeys:@&value1&, @&key1&, @&value2&, @&key2&, nil];可以用NSNumber * number = @1; NSArray * array = @[@&one&, @&two&];NSDictionary * dict = @{@&key1&:@&value1&, @&key2&:@&value2&};这没有什么好深入研究的
采纳率:50%
为您推荐:
其他类似问题
ios的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。后使用快捷导航没有帐号?
查看: 579|回复: 10
新人欢迎积分1 阅读权限30积分101精华0UID帖子金钱803 威望0
Lv.3, 积分 101, 距离下一级还需 149 积分
UID帖子威望0 多玩草0 草
如题,求各路大神解惑。
附几张图片作为答谢。
新人欢迎积分0 阅读权限90积分20201精华0UID帖子金钱11506 威望0
Lv.9, 积分 20201, 距离下一级还需 7799 积分
UID帖子威望0 多玩草796 草
我是来看图的.....
爱玩游戏的吃货
新人欢迎积分1 阅读权限60积分3969精华0UID帖子金钱10929 威望-1
Lv.6, 积分 3969, 距离下一级还需 1031 积分
UID帖子威望-1 多玩草0 草
数据排队更新!
:我每天每辆车第一把都是这样!!!&
&但是我发现出这个字母的人好像都很厉害的样子&
“有江湖的地方就有侠客”。看惯了钢铁侠、蜘蛛侠、蝙蝠侠、闪电侠、绿灯侠、神奇女侠,早已觉得不新鲜。如今,一股“新势力”正在崛起——键盘侠。以键盘为武器,以网络为战场,致命绝招为一个字“喷”,遇神喷神,遇鬼喷鬼。我是一个玩游戏的吃货。
尔等都是水笔
新人欢迎积分1 阅读权限50积分2081精华0UID帖子金钱2924 威望0
Lv.5, 积分 2081, 距离下一级还需 419 积分
UID帖子威望0 多玩草0 草
好图(?▽?)
&施主你可以拿走笑纳了。&
新人欢迎积分0 阅读权限60积分4193精华0UID帖子金钱7501 威望0
Lv.6, 积分 4193, 距离下一级还需 807 积分
UID帖子威望0 多玩草0 草
我擦&&今天前途胸险那。。。
新人欢迎积分0 阅读权限60积分3148精华0UID帖子金钱6692 威望0
Lv.6, 积分 3148, 距离下一级还需 1852 积分
UID帖子威望0 多玩草0 草
我是来看图的.....
新人欢迎积分1 阅读权限30积分215精华0UID帖子金钱703 威望0
Lv.3, 积分 215, 距离下一级还需 35 积分
UID帖子威望0 多玩草0 草
累不O_o,,,,,,
新人欢迎积分0 阅读权限30积分138精华0UID帖子金钱848 威望0
Lv.3, 积分 138, 距离下一级还需 112 积分
UID帖子威望0 多玩草0 草
好图,我是来撸图的,。。。。。。
新人欢迎积分1 阅读权限80积分10229精华0UID帖子金钱12889 威望-1
Lv.8, 积分 10229, 距离下一级还需 7771 积分
UID帖子威望-1 多玩草0 草
盒子来大姨妈的意思
新人欢迎积分0 阅读权限50积分1138精华0UID帖子金钱2063 威望0
Lv.5, 积分 1138, 距离下一级还需 1362 积分
UID帖子威望0 多玩草0 草
曹,进来了,jb没了
新人欢迎积分0 阅读权限40积分841精华0UID帖子金钱2568 威望0
Lv.4, 积分 841, 距离下一级还需 159 积分
UID帖子威望0 多玩草0 草
靠,进来没图了,舔毛个屏!
手机论坛勋章
APP发帖双倍积分,登陆即送勋章!
需要金钱:1100
手机盒子客户端点击或扫描下载
Powered by您好,欢迎来到新东方
& 文章正文
11:40&&作者:&&来源:人民网&&字号:|
  研究报告20日发表在著名科学杂志《自然》周刊网站上。
  万人实验
  英国医学研究委员会和老年痴呆症学会研究人员共同主持一项大型实验。他们从英国广播公司(BBC)科学类节目《理论大爆炸》的观众中挑选约1。14万名志愿者,随机将他们分为实验组和对照组。
  实验组有8600多人,年龄在18岁至60岁之间。研究人员将他们分为2个小组,分别提供不同的网络益智游戏,要求每人每天至少玩10分钟,每周玩3次。这些游戏均由研究人员自己设计开发。第一组所玩游戏旨在训练人的推理、计划和解决问题的能力,第二组所玩游戏旨在训练人的短时记忆、注意力、数学能力和视觉空间能力。
  对照组有2700多人。他们不玩益智游戏,但要花与实验组相同的时间上网和回答各种常识性问题。
  实验过程持续6周,所有受试者在实验前后各参加一次智商测验。
  游戏无益
  6周后,尽管实验组在益智游戏及相关认知能力方面表现更佳,但智商测验显示,实验组的表现并不优于对照组;在测验的某些部分,对照组得分甚至更高。
  英国广播公司21日援引报告第一作者、英国医学研究委员会神经学家阿德里安&欧文的话报道,受试者接受电脑益智游戏&训练&后,表现与花相同时间上网的人比,并无任何统计学意义上的显著差别。
  &益智游戏有意思所以你想玩一会儿,这当然没问题,&欧文说,&如果指望益智游戏提高智商,我们的研究数据可以告诉你,根本没有这回事。&
  老年痴呆症学会研究人员克莱夫&巴拉德说:&研究事实将改变人们对益智游戏的看法,散步等使身体保持活跃状态的活动更有意义。&
  研究人员希望进一步研究能揭示,随着年龄增长,益智游戏是否对认知能力有正面影响。
  态度各异
  电脑益智游戏是否能益智一直是热门话题,游戏厂家和反对者各执一词。
  美国益智游戏厂家&定位科学&公司认为,这项研究对它的产品并不适用。公司首席执行官史蒂夫&奥尔德里奇说,他们的产品获美国国家卫生研究院资助,研究证明产品具有&健脑&功效。他对欧文等人研究结论的评价是:你做不到,不代表别人无法做到。
  著名游戏机制造商日本任天堂公司开发的一些游戏在全世界拥有众多玩家。据称,这些游戏能改善记忆、推理和其他认知能力,但尚无研究证明是否名副其实。
  有些研究人员对益智游戏的功能持保留态度。英国伦敦大学国王学院心理学和神经科学教授菲利普&阿迪认为,真正能够益智的游戏必定欠缺趣味性,他建议人们学习外语或参加体育活动来健脑益智。
  (责任编辑:张梦璇)
更多&&文章推荐
相关文章导读
精彩是人生持续一辈子的过程,绝对不是高考和中考一锤子就可以定下来的,这一锤子只是你的精彩之一!
教育万花筒
||||||||||
经营许可证编号:京ICP备 | 京ICP证060601号| 京网文(0号 | 京公网安备 90号
Neworiental Corporation, All Rights Reserved包的面材质是array什么意思_百度知道
包的面材质是array什么意思
我有更好的答案
所谓的材质包即为游戏贴图,就像贴在东西外面的一层贴纸一样,不同的材质就像是不同的贴纸,使物品的外貌发生了改变。
为您推荐:
其他类似问题
array的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。/ game_dkp
项目语言:PHP
权限:read-only(如需更高权限请先加入项目)
Index: operatorlogmanage.xml
===================================================================
--- operatorlogmanage.xml (revision 0)
+++ operatorlogmanage.xml (revision 3)
@@ -0,0 +1,19 @@
+ &register ctl=&backup& act=&backup_sdf&&
&operate&数据备份&/operate&
+ &/register&
+ &register ctl=&comeback& act=&comeback&&
&operate&数据恢复&/operate&
+ &/register&
+ &register ctl=&comeback& act=&removeTgz&&
&operate&删除备份&/operate&
+ &/register&
+ &register ctl=&debug& act=&cleardata&&
&operate&清除体验数据&/operate&
+ &/register&
\ No newline at end of file
Index: dbschema/hasrole.php
===================================================================
--- dbschema/hasrole.php (revision 0)
+++ dbschema/hasrole.php (revision 3)
@@ -0,0 +1,27 @@
+ * ShopEx licence
+ * @copyright
Copyright (c)
ShopEx Technologies Inc. (http://www.shopex.cn)
+ * @license
http://ecos.shopex.cn/ ShopEx License
+$db['hasrole']=array (
'columns' =&
'user_id' =&
'type' =& 'table:users',
'required' =& true,
'pkey' =& true,
'role_id' =&
'type' =& 'table:roles',
'required' =& true,
'pkey' =& true,
'version' =& '$Rev: 40654 $',
Index: dbschema/tag_rel.php
===================================================================
--- dbschema/tag_rel.php (revision 0)
+++ dbschema/tag_rel.php (revision 3)
@@ -0,0 +1,48 @@
+ * ShopEx licence
+ * @copyright
Copyright (c)
ShopEx Technologies Inc. (http://www.shopex.cn)
+ * @license
http://ecos.shopex.cn/ ShopEx License
+$db['tag_rel']=array (
'columns' =&
'tag_id' =&
'type' =& 'table:tag',
'sdfpath' =& 'tag/tag_id',
'required' =& true,
'default' =& 0,
'pkey' =& true,
'editable' =& false,
'rel_id' =&
'type' =& 'varchar(32)',
'required' =& true,
'default' =& 0,
'pkey' =& true,
'editable' =& false,
'app_id' =&
'type' =& 'varchar(32)',
'label' =& app::get('desktop')-&_('应用'),
'required' =& true,
'width' =& 100,
'in_list' =& true,
'tag_type' =&
'type' =& 'varchar(20)',
'required' =& true,
'default' =& '',
'label' =& app::get('desktop')-&_('标签对象'),
'editable' =& false,
'in_list' =& true,
'version' =& '$Rev$',
Index: dbschema/users.php
===================================================================
--- dbschema/users.php (revision 0)
+++ dbschema/users.php (revision 3)
@@ -0,0 +1,131 @@
+ * ShopEx licence
+ * @copyright
Copyright (c)
ShopEx Technologies Inc. (http://www.shopex.cn)
+ * @license
http://ecos.shopex.cn/ ShopEx License
+$db['users']=array (
'columns' =&
'user_id' =&
'type' =& 'table:account@pam',
'required' =& true,
'sdfpath' =& 'pam_account/account_id',
'pkey' =& true,
'label' =& app::get('desktop')-&_('用户名'),
'width' =& 110,
'editable' =& false,
'hidden' =& true,
'in_list' =& true,
'default_in_list' =& true,
'status' =&
'type' =& 'intbool',
'default' =& '0',
'label' =& app::get('desktop')-&_('启用'),
'width' =& 100,
'required' =& true,
'editable' =& true,
'in_list' =& true,
'default_in_list' =& true,
'name' =&
'type' =& 'varchar(30)',
'label' =& app::get('desktop')-&_('姓名'),
'width' =& 110,
'editable' =& true,
'in_list' =& true,
'default_in_list' =& true,
'lastlogin' =&
'type' =& 'time',
'default' =& 0,
'required' =& true,
'label' =& app::get('desktop')-&_('最后登陆时间'),
'width' =& 110,
'editable' =& false,
'in_list' =& true,
'default_in_list' =& true,
'config' =&
'type' =& 'serialize',
'editable' =& false,
'favorite' =&
'type' =& 'longtext',
'editable' =& false,
'super' =&
'type' =& 'intbool',
'default' =& '0',
'required' =& true,
'label' =& app::get('desktop')-&_('超级管理员'),
'width' =& 75,
'editable' =& false,
'in_list' =& true,
'default_in_list' =& true,
'lastip' =&
'type' =& 'varchar(20)',
'editable' =& false,
'logincount' =&
'type' =& 'number',
'default' =& 0,
'required' =& true,
'label' =& app::get('desktop')-&_('登陆次数'),
'width' =& 110,
'editable' =& false,
'in_list' =& true,
'disabled' =&
'type' =& 'bool',
'default' =& 'false',
'required' =& true,
'editable' =& false,
'op_no' =&
'type' =& 'varchar(50)',
'label' =& app::get('desktop')-&_('编号'),
'width' =& 30,
'editable' =& true,
'in_list' =& true,
'memo' =&
'type' =& 'text',
'label' =& app::get('desktop')-&_('备注'),
'width' =& 270,
'editable' =& false,
'in_list' =& true,
'comment' =& app::get('desktop')-&_('商店后台管理员表'),
'index' =&
'ind_disabled' =&
'columns' =&
0 =& 'disabled',
'engine' =& 'innodb',
'version' =& '$Rev: 40912 $',
Index: dbschema/roles.php
===================================================================
--- dbschema/roles.php (revision 0)
+++ dbschema/roles.php (revision 3)
@@ -0,0 +1,44 @@
+ * ShopEx licence
+ * @copyright
Copyright (c)
ShopEx Technologies Inc. (http://www.shopex.cn)
+ * @license
http://ecos.shopex.cn/ ShopEx License
+$db['roles']=array (
'columns' =&
'role_id' =&
'type' =& 'number',
'required' =& true,
'pkey' =& true,
'width' =& 50,
'label' =& app::get('desktop')-&_('工作组id'),
'hidden' =& 1,
'editable' =& false,
'extra' =& 'auto_increment',
'in_list' =& true,
'role_name' =&
'type' =& 'varchar(100)',
'required' =& true,
'label' =& app::get('desktop')-&_('角色名'),
'width' =& 310,
'in_list' =& true,
'is_title' =& true,
'default_in_list' =& true,
'workground' =&
'label' =& app::get('desktop')-&_('工作场景'),
'type' =& 'text',
'editable' =& false,
'in_list' =& false,
'hidden' =& true,
'version' =& '$Rev: 40654 $',
Index: dbschema/filter.php
===================================================================
--- dbschema/filter.php (revision 0)
+++ dbschema/filter.php (revision 3)
@@ -0,0 +1,105 @@
+ * ShopEx licence
+ * @copyright
Copyright (c)
ShopEx Technologies Inc. (http://www.shopex.cn)
+ * @license
http://ecos.shopex.cn/ ShopEx License
+* @package Schemas
+* @version $
+* @copyright
+* @license Commercial
+$db['filter']=array (
'columns' =&
'filter_id' =&
'type' =& 'number',
'required' =& true,
'pkey' =& true,
'extra' =& 'auto_increment',
'editable' =& false,
'filter_name' =&
'type' =& 'varchar(20)',
'required' =& false,
'label' =& app::get('desktop')-&_('筛选器名'),
'class' =& 'span-3',
'in_list' =& true,
'default_in_list' =& true,
'editable' =& false,
'user_id' =&
'type' =& 'number',
'required' =& true,
'label' =& app::get('desktop')-&_('用户id'),
'width' =& 110,
'editable' =& false,
'hidden' =& true,
'in_list' =& true,
'default_in_list' =& true,
'model' =&
'type' =& 'varchar(100)',
'required' =& true,
'label' =& app::get('desktop')-&_('表'),
'class' =& 'span-3',
'in_list' =& true,
'default_in_list' =& true,
'editable' =& false,
'filter_query' =&
'type' =& 'text',
'hidden' =& true,
'label' =& app::get('desktop')-&_('筛选条件'),
'class' =& 'span-4',
'in_list' =& true,
'editable' =& false,
'ctl'=&array(
'type' =& 'varchar(100)',
'required' =& true,
'default'=&'',
'label' =& app::get('desktop')-&_('控制器'),
'class' =& 'span-3',
'editable' =& false,
'app'=&array(
'type' =& 'varchar(50)',
'required' =& true,
'default'=&'',
'label' =& app::get('desktop')-&_('控制器'),
'class' =& 'span-3',
'editable' =& false,
'act'=&array(
'type' =& 'varchar(50)',
'required' =& true,
'default'=&'',
'label' =& app::get('desktop')-&_('方法'),
'class' =& 'span-3',
'editable' =& false,
'create_time' =&
'type' =& 'time',
'default' =& 0,
'required' =& true,
'label' =& app::get('desktop')-&_('建立时间'),
'width' =& 110,
'editable' =& false,
'in_list' =& true,
'default_in_list' =& true,
\ No newline at end of file
Index: dbschema/user_flow.php
===================================================================
--- dbschema/user_flow.php (revision 0)
+++ dbschema/user_flow.php (revision 3)
@@ -0,0 +1,45 @@
+ * ShopEx licence
+ * @copyright
Copyright (c)
ShopEx Technologies Inc. (http://www.shopex.cn)
+ * @license
http://ecos.shopex.cn/ ShopEx License
+$db['user_flow']=array (
'columns' =&
'user_id' =& array (
'type' =& 'table:users',
'required' =& true,
'pkey' =& true,
'flow_id' =& array (
'type' =& 'table:flow',
'required' =& true,
'pkey' =& true,
'unread' =& array (
'type' =& 'bool',
'required' =& true,
'default'=&'true',
'note' =& array (
'type' =& 'varchar(50)',
'default'=&'',
'has_star' =& array (
'type' =& 'bool',
'required' =& true,
'default'=&'false',
'keep_unread' =& array (
'type' =& 'bool',
'required' =& true,
'default'=&'false',
'comment' =& app::get('desktop')-&_('信息表'),
'version' =& '$Rev$',
'ignore_cache' =& true,
Index: dbschema/recycle.php
===================================================================
--- dbschema/recycle.php (revision 0)
+++ dbschema/recycle.php (revision 3)
@@ -0,0 +1,76 @@
+ * ShopEx licence
+ * @copyright
Copyright (c)
ShopEx Technologies Inc. (http://www.shopex.cn)
+ * @license
http://ecos.shopex.cn/ ShopEx License
+$db['recycle']=array (
'columns' =&
'item_id' =&
'type' =& 'number',
'required' =& true,
'pkey' =& true,
'extra' =& 'auto_increment',
'editable' =& false,
'item_title' =&
'type' =& 'varchar(200)',
'label'=&app::get('desktop')-&_('名称'),
'required' =& false,
'is_title'=&true,
'in_list'=&true,
'width'=&200,
'filtertype' =& 'yes',
'filterdefault' =& true,
'default_in_list'=&true,
'item_type'=&array(
'label'=&app::get('desktop')-&_('类型'),
'type' =& 'varchar(80)',
'required' =& true,
'in_list'=&true,
'width'=&100,
'filtertype' =& 'yes',
'filterdefault' =& true,
'default_in_list'=&true,
'app_key'=&array(
'label'=&app::get('desktop')-&_('应用'),
'type' =& 'varchar(80)',
'required' =& true,
'in_list'=&true,
'width'=&100,
'default_in_list'=&true,
'drop_time'=&array(
'type' =& 'time',
'label'=&app::get('desktop')-&_('删除时间'),
'required' =& true,
'in_list'=&true,
'width'=&150,
'filtertype' =& 'yes',
'filterdefault' =& true,
'default_in_list'=&true,
'item_sdf'=&array(
'type' =& 'serialize',
'required' =& true,
+ 'permission'=&array(
+ 'type'=&'varchar(80)',
+ 'label'=&app::get('desktop')-&_('相关权限'),
+ 'in_list'=&false,
+ 'default_in_list'=&false,
'engine' =& 'innodb',
'version' =& '$Rev: 40912 $',
+//需要id从大到小的执行
Index: dbschema/flow.php
===================================================================
--- dbschema/flow.php (revision 0)
+++ dbschema/flow.php (revision 3)
@@ -0,0 +1,101 @@
+ * ShopEx licence
+ * @copyright
Copyright (c)
ShopEx Technologies Inc. (http://www.shopex.cn)
+ * @license
http://ecos.shopex.cn/ ShopEx License
+$db['flow']=array (
'columns' =&
'flow_id' =&
'label' =& app::get('desktop')-&_('序号'),
'type' =& 'number',
'required' =& true,
'pkey' =& true,
'extra' =& 'auto_increment',
'editable' =& false,
'in_list' =& true,
'default_in_list' =& true,
'flow_from' =&
'label' =& app::get('desktop')-&_('发送者'),
'type' =&
'user' =& app::get('desktop')-&_('管理员'),
'system' =& app::get('desktop')-&_('系统'),
'internet' =& app::get('desktop')-&_('站外'),
'user' =& app::get('desktop')-&_('用户'),
'default' =& 'system',
'required' =& true,
'in_list' =& true,
'from_id' =&
'type' =& 'number',
'default' =& 0,
'editable' =& false,
'subject' =&
'label' =& app::get('desktop')-&_('消息标题'),
'type' =& 'varchar(50)',
'required' =& true,
'default' =& '',
'editable' =& false,
'in_list' =& true,
'is_title' =& true,
'flow_desc' =&
'label' =& app::get('desktop')-&_('消息描述'),
'type' =& 'varchar(100)',
'required' =& true,
'default' =& '',
'editable' =& false,
'in_list' =& true,
'body' =&
'label' =& app::get('desktop')-&_('内容本体'),
'type' =& 'text',
'required' =& true,
'default' =& '',
'editable' =& false,
'in_list' =& true,
'flow_ip' =&
'type' =& 'varchar(20)',
'default' =& '',
'required' =& true,
'editable' =& false,
'send_mode'=&array(
'type'=&array(
'direct'=&app::get('desktop')-&_('直送'),
'broadcast'=&app::get('desktop')-&_('广播'),
'fetch'=&app::get('desktop')-&_('收取'),
'default' =& 'direct',
'required' =& true,
'flow_type' =&
'type' =& 'varchar(32)',
'default' =& 'default',
'required' =& true,
'editable' =& false,
'send_time'=&array(
'type'=&'time',
'required' =& true,
'comment' =& app::get('desktop')-&_('信息表'),
'version' =& '$Rev$',
Index: dbschema/menus.php
===================================================================
--- dbschema/menus.php (revision 0)
+++ dbschema/menus.php (revision 3)
@@ -0,0 +1,95 @@
+ * ShopEx licence
+ * @copyright
Copyright (c)
ShopEx Technologies Inc. (http://www.shopex.cn)
+ * @license
http://ecos.shopex.cn/ ShopEx License
+$db['menus']=array (
'columns' =&
'menu_id'=&array(
'type' =& 'number',
'pkey' =& true,
'extra' =& 'auto_increment',
'menu_type' =&
'type' =& 'varchar(80)',
'required' =& true,
'width' =& 100,
'in_list' =& true,
'default_in_list' =& true,
'app_id' =&
'type' =& 'table:apps@base',
'required' =& true,
'width' =& 100,
'in_list' =& true,
'default_in_list' =& true,
'workground'=&array(
'type'=&'varchar(200)',
'menu_group'=&array(
'type'=&'varchar(200)',
'menu_title'=&array(
'type'=&'varchar(100)',
'is_title'=&true,
'menu_path'=&array(
'type'=&'varchar(255)',
'disabled'=&array(
'type'=&'bool',
'default'=&'false'
'display'=&array(
'type'=&&enum('true', 'false')&,
'default'=&'false'
'permission'=&array(
'type'=&'varchar(80)',
'addon'=&array(
'type'=&'text',
'target'=&array(
'type'=&'varchar(10)',
'default'=&''
'menu_order'=&array(
'type' =& 'number',
'default'=&'0'
'index' =&
'ind_menu_type' =&
'columns' =&
0 =& 'menu_type',
'ind_menu_path' =&
'columns' =&
0 =& 'menu_path',
'ind_menu_order' =&
'columns' =&
0 =& 'menu_order',
'version' =& '$Rev: 44008 $',
'unbackup' =& true,
Index: dbschema/role_flow.php
===================================================================
--- dbschema/role_flow.php (revision 0)
+++ dbschema/role_flow.php (revision 3)
@@ -0,0 +1,25 @@
+ * ShopEx licence
+ * @copyright
Copyright (c)
ShopEx Technologies Inc. (http://www.shopex.cn)
+ * @license
http://ecos.shopex.cn/ ShopEx License
+$db['role_flow']=array (
'columns' =&
'role_id' =& array (
'type' =& 'table:roles',
'required' =& true,
'pkey' =& true,
'flow_id' =& array (
'type' =& 'table:flow',
'required' =& true,
'pkey' =& true,
'comment' =& app::get('desktop')-&_('信息表'),
'version' =& '$Rev$',
Index: dbschema/tag.php
===================================================================
--- dbschema/tag.php (revision 0)
+++ dbschema/tag.php (revision 3)
@@ -0,0 +1,126 @@
+ * ShopEx licence
+ * @copyright
Copyright (c)
ShopEx Technologies Inc. (http://www.shopex.cn)
+ * @license
http://ecos.shopex.cn/ ShopEx License
+$db['tag']=array (
'columns' =&
'tag_id' =&
'type' =& 'number',
'required' =& true,
'pkey' =& true,
'extra' =& 'auto_increment',
'editable' =& false,
'tag_name' =&
'type' =& 'varchar(20)',
'required' =& true,
'default' =& '',
'label' =& app::get('desktop')-&_('标签名'),
'width' =& 200,
'editable' =& true,
'in_list' =& true,
'default_in_list' =& true,
'is_title' =& true,
'tag_mode' =&
'type' =&
'normal' =& app::get('desktop')-&_('普通标签'),
'filter' =& app::get('desktop')-&_('自动标签'),
'default' =& 'normal',
'label' =& app::get('desktop')-&_('标签类型'),
'required' =& true,
'editable' =& false,
'in_list' =& true,
'default_in_list' =& true,
'app_id' =&
'type' =& 'varchar(32)',
'label' =& app::get('desktop')-&_('应用'),
'required' =& true,
'width' =& 100,
'in_list' =& true,
'tag_type' =&
'type' =& 'varchar(20)',
'required' =& true,
'default' =& '',
'label' =& app::get('desktop')-&_('标签对象'),
'editable' =& false,
'in_list' =& true,
'tag_abbr' =&
'type' =& 'varchar(150)',
'required' =& true,
'default' =& '',
'label' =& app::get('desktop')-&_('标签备注'),
'editable' =& false,
'in_list' =& true,
'tag_bgcolor' =&
'type' =& 'varchar(7)',
'required' =& true,
'default' =& '',
'label' =& app::get('desktop')-&_('标签背景颜色'),
'editable' =& false,
'in_list' =& true,
'tag_fgcolor' =&
'type' =& 'varchar(7)',
'required' =& true,
'default' =& '',
'label' =& app::get('desktop')-&_('标签字体颜色'),
'editable' =& false,
'in_list' =& true,
'tag_filter' =&
'type' =& 'varchar(255)',
'required' =& true,
'default' =& '',
'label' =& app::get('desktop')-&_('标签条件'),
'editable' =& false,
'in_list' =& false,
'default_in_list' =& false,
'rel_count' =&
'type' =& 'number',
'default' =& 0,
'required' =& true,
'editable' =& false,
'index' =&
'ind_type' =&
'columns' =&
0 =& 'tag_type',
'ind_name' =&
'columns' =&
0 =& 'tag_name',
'version' =& '$Rev: 42201 $',
Index: lib/system/mysqldumper.php
===================================================================
--- lib/system/mysqldumper.php (revision 0)
+++ lib/system/mysqldumper.php (revision 3)
@@ -0,0 +1,204 @@
+ * ShopEx licence
+ * @copyright
Copyright (c)
ShopEx Technologies Inc. (http://www.shopex.cn)
+ * @license
http://ecos.shopex.cn/ ShopEx License
+class desktop_system_mysqldumper {
public $_isD
//数据表ID
public function __construct() {
$this-&_db = kernel::database();
* @params $app 所属app
* @params $bakdir 备份临时文件夹
public function multi_dump_sdf( $app,$bakdir ) {
$dirname = $bakdir .'/sdf';
$dbschema_dirname = $bakdir .'/dbschema';
is_dir($dirname) or mkdir( $dirname,0755,true );
is_dir($dbschema_dirname) or mkdir( $dbschema_dirname,0755,true );
$sql = 'SELECT app_id FROM sdb_base_apps WHERE status=\'active\'';
$tables = $this-&_db-&select($sql);
if($app) {
foreach($tables as $key =& $name) {
if($app==$name['app_id']) {
$tables = array_slice($tables, $key);
foreach($tables as $key =& $tbl) {
$app = $tbl['app_id'];
$service =
foreach ( kernel::servicelist('desktop_backup.'. $app) as $object ) {
$service =
$m = substr( get_class($object), ( strpos(get_class($object), $app) + strlen($app) + strlen('_mdl_') ) );
$this-&dump_data( $dirname, $app, $m );
if( !$service) {
if(!is_dir(APP_DIR . '/' . $app .'/dbschema')){
if( count($tables)==1 ) {
$arr = $tables[$key+1];
return $arr['app_id'];
if ($handle = opendir(APP_DIR . '/' . $app .'/dbschema')) {
chdir(APP_DIR . '/' . $app .'/dbschema');
while (false !== ($file = readdir($handle))) {
if($file{0}!='.') {
if( strtolower(substr( $file, -strpos(strrev($file),'.') ))!='php' ) {
if( count($tables)==1 ) {
$arr = $tables[$key+1];
return $arr['app_id'];
require($file);
closedir($handle);
if(!is_array($db)) {
if( count($tables)==1 ) {
$arr = $tables[$key+1];
return $arr['app_id'];
foreach($db as $m =& $row) {
if($row['unbackup'])
$this-&dump_data( $dirname, $app, $m );
utils::cp( APP_DIR .'/'. $app .'/dbschema',$dbschema_dirname.'/'.$app );
if( count($tables)==1 ) {
$arr = $tables[$key+1];
return $arr['app_id'];
private function dump_data( $dirname, $app, $model ) {
$len = 10;
$cols = $startid = $filesize = 0;
while(true) {
$bakfile = $this-&get_bak_file( $app,$model,$cols );
$tname = &sdb_{$app}_{$model}&;
$limit = sprintf( 'LIMIT %s,%s', $startid, $len );
if( strtolower($app)=='base' && strtolower($model)=='kvstore' )
$where = ' WHERE prefix NOT LIKE &cache/%&';
$sql = &SELECT * FROM $tname $where $limit&;
$aData = $this-&_db-&select( $sql );
require APP_DIR . &/{$app}/dbschema/{$model}.php&;
if(empty($aData)) { $startid=0; }
foreach($aData as $row) {
foreach( $row as $key =& &$val ) {
if( $db[$model]['columns'][$key]['type']=='serialize' ) $val = unserialize($val);
$i_str = serialize($row);
$filesize += strlen($i_str);
$this-&write( $dirname,$bakfile,$i_str.&\r\n& );
if( $filesize& ) {
$bakfile = $this-&get_bak_file( $app,$model,$cols );
$filesize = 0;
$startid++;
if( count($aData)&$len ) { $startid=0; }
private function write( $dirname, $bakfile, $str ) {
$fp = fopen($dirname.'/'.$bakfile, 'a+');
fwrite( $fp, $str );
fclose($fp);
private function get_bak_file( $app,$model,$cols ) {
$ext = 'sdf';
if( empty($cols) ) {
return &{$app}.{$model}.{$ext}&;
return &{$app}.{$model}.{$cols}.{$ext}&;
//截最后一个是否是半个UTF-8中文
public function utftrim($str)
for($i=0;$i&4&&$i&strlen($str);$i++)
$ord = ord(substr($str,strlen($str)-$i-1,1));
//UTF-8中文分{四/三/二字节码},第一位分别为11110xxx(&192),1110xxxx(&192),110xxxxx(&192);接下去的位数都是10xxxxxx(&192)
//其他ASCII码都是0xxxxxxx
if($ord& 192)
if ($i==0 && $ord & 128){
if($found)
if($ord&240)
if($i==3) return $
else return substr($str,0,strlen($str)-$i-1);
elseif($ord&224)
if($i&=2) return $
else return substr($str,0,strlen($str)-$i-1);
if($i&=1) return $
else return substr($str,0,strlen($str)-$i-1);
else return $
Index: lib/system/backup.php
===================================================================
--- lib/system/backup.php (revision 0)
+++ lib/system/backup.php (revision 3)
@@ -0,0 +1,523 @@
+ * ShopEx licence
+ * @copyright
Copyright (c)
ShopEx Technologies Inc. (http://www.shopex.cn)
+ * @license
http://ecos.shopex.cn/ ShopEx License
+class desktop_system_backup {
private $header = &&? ?&&;
//追加头文件内容
private $tar_ext = '.zip';
//下载扩展名
private $ //备份目录
private $prefilename = 'multibak_';
public function __construct() {
$this-&backdir = DATA_DIR.'/backup';
public function get($var='') {
return $this-&$
public function getList(){
$dir = $this-&
if(!is_dir($dir))
$handle=opendir($dir);
if ($handle = opendir($dir)) {
$return = array();
while (false !== ($file = readdir($handle))) {
if($file{0}=='.')
if( is_file($dir.'/'.$file) ){
//备份时间取文件名字
$array = explode( '.',$file );
$temp = array();
if( count($array)==3 ) {
$temp['app']
= $array[0];
$nfilename = $array[1];
$nfilename = $array[0];
$temp['app'] = '全局备份';
$datetime = ltrim($nfilename,$this-&prefilename);
if( strlen($datetime)!=14 )
$datetime = mktime( substr($datetime,8,2) ,
substr($datetime,10,2) ,
substr($datetime,12,2) ,
substr($datetime,4,2) ,
substr($datetime,6,2) ,
substr($datetime,0,4)
$temp['name'] = str_replace('.php', $this-&tar_ext, $file);
$temp['size'] = filesize($dir .'/'. $file);
$temp['time'] = $
if( end($array)==trim($this-&tar_ext,'.') ) {
$this-&convertFile( $dir,$file );
@unlink($dir.'/'.$file);
$return[] = $
krsort($return);
closedir($handle);
public function uninstall_backup( $app ) {
$oMysqlDump = kernel::single(&desktop_system_mysqldumper&);
$backdir = $this-&
$dirname = date(&Ymdhis&);
is_dir($backdir) or mkdir($backdir, 0755, true);
$oMysqlDump-&multi_dump_sdf( $app,$backdir .'/' . $dirname );
$this-&create_tar( $backdir,$dirname,$app );
public function start_backup_sdf(&$params,&$nexturl){
set_time_limit(0);
header(&Content-type:text/charset=utf-8&);
$app = $params['appname'];
$dirname = $params['dirname'];
#$cols = $params['cols'];
#$model = $params['model'];
#$startid = $params['startid'];
$oMysqlDump = kernel::single(&desktop_system_mysqldumper&);
$backdir = $this-&
$oMysqlDump-&tableid = $
$oMysqlDump-&startid = $
is_dir($backdir) or mkdir($backdir, 0755, true);
is_dir($backdir .'/' . $dirname) or mkdir($backdir .'/' . $dirname, 0755, true);
$app = $oMysqlDump-&multi_dump_sdf( $app,$backdir .'/' . $dirname );
$nexturl = &index.php?app=desktop&ctl=backup&act=backup_sdf&appname=$app&dirname=$dirname&;
$params['app'] = $
return $this-&create_tar( $backdir,$dirname );
* 生成tar包
private function create_tar( $backdir,$dirname,$app='' ) {
$tar = kernel::single(&base_tar&);
$dir = $backdir. '/' . $
chdir($dir);
$size = $this-&add_tar( $dir,$tar );
$size = ceil($size/) + 128;
ini_set(&memory_limit&, &{$size}M&);
$tar-&filename = ($app?$app.'.':''). $this-&prefilename.$dirname.$this-&tar_
$tar-&saveTar();
@copy($dir . '/' . $tar-&filename, $backdir.'/'.$tar-&filename);
$this-&convertFile($backdir, $tar-&filename, '.php');
if(is_resource($tar-&tar_file)) {
fclose($tar-&tar_file);
@unlink($tar-&filename);
@unlink($backdir.'/'.$tar-&filename);
$dir = $backdir. '/' . $
chdir($dir);
if ($handle = opendir($dir)) {
while (false !== ($file = readdir($handle))) {
if(is_file($file)) {
@unlink($file);
closedir($handle);
utils::remove_p($dir);
private function add_tar( $dir,&$tar,$parentdir='' ) {
$size = 0;
if ($handle = opendir($dir)) {
while (false !== ($file = readdir($handle))) {
if($file{0}!='.') {
if( is_file($dir.'/'.$file) ) {
$size += filesize($parentdir.$file);
$tar-&addFile($parentdir.$file);
$tar-&addDirectory($parentdir.$file);
$size += $this-&add_tar( $dir.'/'.$file, $tar, $parentdir.$file.'/' );
closedir($handle);
public function download($file) {
$dir = DATA_DIR.'/backup/';
$file = str_replace($this-&tar_ext, '.php', $file);
if(!file_exists($dir . $file)){
$etag = md5_file($dir . $file);
header('Etag: '.$etag);
if(isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $etag){
header('HTTP/1.1 304 Not Modified',true,304);
set_time_limit(0);
ob_end_clean();
$content_size = filesize($dir . $file) - strlen($this-&header);
$filename = substr($file, 0, strrpos($file, '.')) . $this-&tar_
header(&Content-Disposition: filename=\&$filename\&&);
header(&Content-Length: & . $content_size);
$handle = fopen($dir . $file, &r&);
while($buffer = fread($handle,102400)){
if(!$flag) $buffer = str_replace($this-&header, '', $buffer);
fclose($handle);
function recover($sTgz,&$vols,$fileid,&$pre_app){
$prefix = substr($sTgz,0,23);
$sTmpDir = DATA_DIR.'/tmp/'.md5($sTgz).'/';
$sTgz = str_replace($this-&tar_ext, '.php', $sTgz);
if($fileid==1){
$vols = 0;
$rTar = kernel::single(&base_tar&);
is_dir($sTmpDir) or mkdir($sTmpDir, 0755, true);
$file = DATA_DIR.'/backup/'.$sT
$size = filesize($file);
$size = ceil($size/) + 128;
ini_set(&memory_limit&, &{$size}M&);
$newFile = $this-&convertFile(DATA_DIR.'/backup/', $sTgz, $this-&tar_ext);
if($rTar-&openTAR($newFile, null)){
if(!$rTar-&files)
foreach($rTar-&files as $id =& $aFile) {
if( substr($aFile['name'],0,4)=='sdf/') $vols++;
$sPath=$sTmpDir.$aFile['name'];
is_dir( dirname($sPath) ) or mkdir( dirname($sPath),0755,true );
file_put_contents($sPath,$rTar-&getContents($aFile));
chmod($sPath,0755);
$rTar-&closeTAR();
@unlink($newFile);
return $this-&comeback($sTmpDir, 1, $vols, $pre_app);
return $this-&comeback($sTmpDir, $fileid, $vols, $pre_app);
function comeback($sDir, $fileid=1, $vols, &$pre_app){
$dir = $sD
$sDir = $sDir .'/sdf';
if(!is_dir($sDir))
chdir($sDir);
if($rHandle=opendir($sDir)){
while(false!==($sFile=readdir($rHandle))){
if($sFile{0}=='.')
$handle = fopen($sFile,'r');
$app = substr($sFile, 0, strpos($sFile, '.'));
$model = substr($sFile, strpos($sFile, '.')+1, -(strpos(strrev($sFile), '.') + 1));
$model = strpos($model, '.') ? substr($model, 0, strpos($model, '.')) : $
if(!$app || !$model)
if( app::get($app)-&is_actived() ) { //APP安装了继续跑
$o = app::get($app)-&model($model);
$this-&app_update( $dir,$app,$pre_app,$model,$o );
while($sdf=$this-&fgetline($handle)){
if(!is_array(@unserialize($sdf))){
$buffer .= $
$sdf = @unserialize($buffer);
if(!is_array($sdf))
$sdf = @unserialize($sdf);
if( $app=='base' && $model=='app_content' ) {
if( !$sdf['app_id'] )
if( !isset($arr_app_status[$sdf['app_id']]) )
$arr_app_status[$sdf['app_id']] = app::get($sdf['app_id'])-&is_actived();
if( !$arr_app_status[$sdf['app_id']] )
//删除kvstore主键 避免冲突 session
if( $app=='base' && $model=='kvstore' ) unset( $sdf['id'] );
$return = @$o-&insert($sdf);
$this-&show_message .= 'app: '.$app .' 没有安装!数据无法还原!&BR /&';
fclose($handle);
@unlink($sFile);
$pre_app = $
closedir($rHandle);
if( !$sFile ) {
$this-&app_update( $dir,$app,$pre_app );
utils::remove_p($sDir);
if( $fileid==$vols ) {
$this-&post_comeback($dir);
utils::remove_p($dir);
//////////////////////////////////////////////////////////////////////////
//数据还原之后
///////////////////////////////////////////////////////////////////////////
private function post_comeback($dir) {
if($rHandle=opendir($dir.'/dbschema/')){
while(false!==($app=readdir($rHandle))){
if( $app{0}=='.' )
if( !is_dir($dir.'/dbschema/'.$app) )
#if( $handle=opendir($dir.'/dbschema/'.$app) ) {
while(false!==($sFile=readdir($handle))){
if( $sFile{0}=='.' )
$tmp_model = substr($sFile,0,strpos($sFile,'.'));
//最后会修复表结构到最新
以下没有意义
#$dbschema_file = $dir.'/dbschema/'.$app.'/'.$sF
#if( $db[$tmp_model]['unbackup'] )
#$this-&create_table( $pre_app,$tmp_model,$o,$dbschema_file );
if( !$this-&dbtable )
$this-&dbtable = kernel::single('base_application_dbtable');
$this-&dbtable-&update($app);
private function app_update( $dir,$app,$pre_app,$model='',$o='' ) {
if( !$app )
$dbschema_file = $dir.'/dbschema/'.$app.'/'.$model.'.php';
$dbschema_file_bak = $dir.'/dbschema/'.$app.'/'.$model.'.bak.php';;
if( is_file($dbschema_file) ) {
$this-&create_table( $app,$model,$o,$dbschema_file );
#unlink( $dbschema_file );
rename($dbschema_file,$dbschema_file_bak);
} else if(is_file($dbschema_file_bak)) {
$this-&create_table( $app,$model,$o,$dbschema_file_bak,false );
* 创建数据表
private function create_table( $app,$model,$o,$dbschema_file,$createtable=true ) {
if( !$app )
if( !$model )
require( $dbschema_file );
if( !$this-&dbtable )
$this-&dbtable = kernel::single('base_application_dbtable');
$this-&dbtable-&target_app = app::get($app);
//是否默认使用innodb
$this-&dbtable-&_enable_innodb = 'YES';
$this-&dbtable-&key = $
$real_table_name = $this-&dbtable-&real_table_name();
$define = $db[$model];
$this-&get_defined_dbsdf( $define );
$this-&dbtable-&_define[$real_table_name] = $
if( $createtable ) {
$sql = $this-&dbtable-&get_sql(&sdb_{$app}_{$model}&);
$o-&db-&exec(&DROP TABLE IF EXISTS sdb_{$app}_{$model}&);
$o-&db-&exec($sql);
private function get_defined_dbsdf( &$define ) {
foreach($define['columns'] as $k=&$v){
if($v['pkey'])
$define['idColumn'][$k] = $k;
if($v['is_title'])
$define['textColumn'][$k] = $k;
if($v['in_list']){
$define['in_list'][] = $k;
if($v['default_in_list']){
$define['default_in_list'][] = $k;
$define['columns'][$k] = $this-&dbtable-&_prepare_column($k, $v);
if(isset($v['pkey']) && $v['pkey']){
$define['pkeys'][$k] = $k;
if(!$define['idColumn']){
$define['idColumn'] = key($define['columns']);
}elseif(count($define['idColumn'])==1){
$define['idColumn'] = current($define['idColumn']);
if(!$define['textColumn']){
$keys = array_keys($define['columns']);
$define['textColumn'] = $keys[1];
}elseif(count($define['idColumn'])==1){
$define['textColumn'] = current($define['textColumn']);
* 文件类型转换
private function convertFile($dir, $file, $type='.php') {
$dir = rtrim($dir, '/') . '/';
$new_file_name = substr($file, 0, -(strpos(strrev($file), '.')+1)) . $
$newFile = $dir . $new_file_
if($type==$this-&tar_ext) {
//还原时从php转换成tar包
//is_dir($dir .'/tmptar/') or mkdir($dir .'/tmptar/');
//$newFile = $dir .'/tmptar/'. md5($newFile);
if(file_exists($newFile)) { //如果是tar文件转换成php形式
$this-&convertFile( $dir,$new_file_name );
if(file_exists($newFile)) {
return $newF
$handle = fopen($newFile, 'x');
if($flag) {
fwrite($handle, $this-&header);
$src = fopen($dir . $file, 'r');
while (!feof($src)) {
$contents = fgets($src);
if(!$flag && strpos($contents, $this-&header)!==false) $contents = substr($contents, strlen($this-&header));
if($contents) {
fwrite($handle, $contents);
fclose($src);
fclose($handle);
return $newF
function fgetline($handle){
$buffer = fgets($handle, 4096);
if (!$buffer){
if(( 4095 & strlen($buffer)) || ( 4095 == strlen($buffer) && &\n& == $buffer{4094} )){
while( 4095 == strlen($buffer) && &\n& != $buffer{4094} ){
$buffer = fgets($handle,4096);
function removeTgz($sFile){
#foreach($aTgz as $sFile){
$pathinfo = pathinfo($sFile);
@unlink(DATA_DIR.'/backup/'.$pathinfo['filename'].'.php');
function __finish($sDir){
$this-&__removeDir($sDir);
return $sD
function __removeDir($sDir){
if($rHandle=opendir($sDir)){
while(false!==($sItem=readdir($rHandle))){
if ($sItem!='.' && $sItem!='..'){
if(is_dir($sDir.'/'.$sItem)){
$this-&__removeDir($sDir.'/'.$sItem);
@unlink($sDir.'/'.$sItem);
closedir($rHandle);
utils::remove_p($sDir);
Index: lib/system/recycle.php
===================================================================
--- lib/system/recycle.php (revision 0)
+++ lib/system/recycle.php (revision 3)
@@ -0,0 +1,65 @@
+class desktop_system_recycle {
function dorecycle($mdl_name,$filter=null){
$oRecycle = app::get('desktop')-&model('recycle');
list($app_id,$table) = explode('_mdl_',$mdl_name);
$o = app::get($app_id)-&model($table);
$recycle_item = array();
$recycle_item['drop_time'] = time();
$recycle_item['item_type'] = $o-&table_name();
$dbschema = $o-&get_schema();
$textColumn = $dbschema['textColumn'];
$pkey = $dbschema['idColumn'];
foreach($dbschema['columns'] as $k=&$col){
if($col['is_title']&&$col['sdfpath']){
$textColumn = $col['sdfpath'];
$rows = $o-&getList('*',$filter,0,-1);
if(method_exists($o, 'pre_recycle')){
if(!$o-&pre_recycle($rows)){
$menus = app::get('desktop')-&model('menus');
$permission_id = $menus-&permissionId($_GET);
foreach($rows as $k=&$v){
$pkey_value = $v[$pkey];
$v = $o-&dump($v[$pkey],'*','delete');
$recycle_item['item_sdf'] = $v;
$recycle_item['app_key'] = $app_
$recycle_item['item_title'] = $v[$textColumn];
if(method_exists($o,'title_recycle'))
$recycle_item['item_title'] = $o-&title_recycle($v);
$tmp = $recycle_
$tmp['permission'] = $permission_
$return = $oRecycle-&save($tmp);
unset($tmp[$pkey]);
$o-&delete(array($pkey=&$pkey_value));
if(method_exists($o, 'suf_recycle')){
if(!$o-&suf_recycle($_POST)){
$services = kernel::serviceList('desktop_finder_callback.' . get_class($o));
foreach($services AS $service){
if(method_exists($service, 'recycle')){
$service-&recycle($_POST);
Index: lib/email/emailconf.php
===================================================================
--- lib/email/emailconf.php (revision 0)
+++ lib/email/emailconf.php (revision 3)
@@ -0,0 +1,21 @@
+ * ShopEx licence
+ * @copyright
Copyright (c)
ShopEx Technologies Inc. (http://www.shopex.cn)
+ * @license
http://ecos.shopex.cn/ ShopEx License
+class desktop_email_emailconf{
function get_emailConfig(){
$app = app::get('desktop');
$aTmp['usermail'] = $app-&getConf('email.config.usermail');
$aTmp['smtpport'] = $app-&getConf('email.config.smtpport');
$aTmp['smtpserver'] = $app-&getConf('email.config.smtpserver');
$aTmp['smtpuname'] = $app-&getConf('email.config.smtpuname');
$aTmp['smtppasswd'] = $app-&getConf('email.config.smtppasswd');
$aTmp['sendway'] = $app-&getConf('email.config.sendway') ? $app-&getConf('email.config.sendway') : 'mail';
return $aT
\ No newline at end of file
Index: lib/email/smtp.php
===================================================================
--- lib/email/smtp.php (revision 0)
+++ lib/email/smtp.php (revision 3)
@@ -0,0 +1,1051 @@
+ * ShopEx licence
+ * @copyright
Copyright (c)
ShopEx Technologies Inc. (http://www.shopex.cn)
+ * @license
http://ecos.shopex.cn/ ShopEx License
+////////////////////////////////////////////////////
+// SMTP - PHP SMTP class
+// Version 1.02
+// Define an SMTP class that can be used to connect
+// and communicate with any SMTP server. It implements
+// all the SMTP functions defined in RFC821 except TURN.
+// Author: Chris Ryan
+// License: LGPL, see LICENSE
+////////////////////////////////////////////////////
+ * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP
+ * commands except TURN which will always return a not implemented
+ * error. SMTP also provides some utility methods for sending mail
+ * to an SMTP server.
+ * @package PHPMailer
+ * @author Chris Ryan
+class desktop_email_smtp {
SMTP server port
var $SMTP_PORT = 25;
SMTP reply line ending
@var string
var $CRLF = &\r\n&;
Sets whether debugging is turned on
# the level of debug to perform
* @access private
var $smtp_
# the socket to the server
# error if any on the last call
var $helo_
# the reply the server sent to us for HELO
* Initialize the class so that the data is in a known state.
* @access public
* @return void
function shopex_member_smtp() {
$this-&smtp_conn = 0;
$this-&error =
$this-&helo_rply =
$this-&do_debug = 0;
/*************************************************************
CONNECTION FUNCTIONS
***********************************************************/
* Connect to the server specified on the port specified.
* If the port is not specified use the default SMTP_PORT.
* If tval is specified then a connection will try and be
* established with the server for that number of seconds.
* If tval is not specified the default is 30 seconds to
* try on the connection.
* SMTP CODE SUCCESS: 220
* SMTP CODE FAILURE: 421
* @access public
* @return bool
function Connect($host,$port=0,$tval=30) {
# set the error val to null so there is no confusion
$this-&error =
# make sure we are __not__ connected
if($this-&connected()) {
# ok we are connected! what should we do?
# for now we will just give an error saying we
# are already connected
$this-&error =
array(&error& =& &Already connected to a server&);
if(empty($port)) {
$port = $this-&SMTP_PORT;
#connect to the smtp server
$this-&smtp_conn = @fsockopen($host,
# the host of the servers
# the port to use
# error number if any
# error message if any
# give up after ? secs
# verify we connected properly
if(empty($this-&smtp_conn)) {
$this-&error = array(&error& =& &Failed to connect to server&,
&errno& =& $errno,
&errstr& =& $errstr);
if($this-&do_debug &= 1) {
echo &SMTP -& ERROR: & . $this-&error[&error&] .
&: $errstr ($errno)& . $this-&CRLF;
# sometimes the SMTP server takes a little longer to respond
# so we will give it a longer timeout for the first read
// Windows still does not have support for this timeout function
if(substr(PHP_OS, 0, 3) != &WIN&)
socket_set_timeout($this-&smtp_conn, $tval, 0);
# get any announcement stuff
$announce = $this-&get_lines();
# set the timeout
of any socket functions at 1/10 of a second
//if(function_exists(&socket_set_timeout&))
socket_set_timeout($this-&smtp_conn, 0, 100000);
if($this-&do_debug &= 2) {
echo &SMTP -& FROM SERVER:& . $this-&CRLF . $
* Performs SMTP authentication.
Must be run after running the
* Hello() method.
Returns true if successfully authenticated.
* @access public
* @return bool
function Authenticate($username, $password) {
// Start authentication
@fputs($this-&smtp_conn,&AUTH LOGIN& . $this-&CRLF);
$rply = $this-&get_lines();
$code = substr($rply,0,3);
if($code != 334) {
$this-&error =
array(&error& =& &AUTH not accepted from server&,
&smtp_code& =& $code,
&smtp_msg& =& substr($rply,4));
if($this-&do_debug &= 1) {
echo &SMTP -& ERROR: & . $this-&error[&error&] .
&: & . $rply . $this-&CRLF;
// Send encoded username
fputs($this-&smtp_conn, base64_encode($username) . $this-&CRLF);
$rply = $this-&get_lines();
$code = substr($rply,0,3);
if($code != 334) {
$this-&error =
array(&error& =& &Username not accepted from server&,
&smtp_code& =& $code,
&smtp_msg& =& substr($rply,4));
if($this-&do_debug &= 1) {
echo &SMTP -& ERROR: & . $this-&error[&error&] .
&: & . $rply . $this-&CRLF;
// Send encoded password
fputs($this-&smtp_conn, base64_encode($password) . $this-&CRLF);
$rply = $this-&get_lines();
$code = substr($rply,0,3);
if($code != 235) {
$this-&error =
array(&error& =& &Password not accepted from server&,
&smtp_code& =& $code,
&smtp_msg& =& substr($rply,4));
if($this-&do_debug &= 1) {
echo &SMTP -& ERROR: & . $this-&error[&error&] .
&: & . $rply . $this-&CRLF;
* Returns true if connected to a server otherwise false
* @access private
* @return bool
function Connected() {
if(!empty($this-&smtp_conn)) {
$sock_status = socket_get_status($this-&smtp_conn);
if($sock_status[&eof&]) {
# hmm this is an odd situation... the socket is
# valid but we aren't connected anymore
if($this-&do_debug &= 1) {
echo &SMTP -& NOTICE:& . $this-&CRLF .
&EOF caught while checking if connected&;
$this-&Close();
# everything looks good
* Closes the socket and cleans up the state of the class.
* It is not considered good to use this function without
* first trying to use QUIT.
* @access public
* @return void
function Close() {
$this-&error = # so there is no confusion
$this-&helo_rply =
if(!empty($this-&smtp_conn)) {
# close the connection and cleanup
fclose($this-&smtp_conn);
$this-&smtp_conn = 0;
/***************************************************************
SMTP COMMANDS
*************************************************************/
* Issues a data command and sends the msg_data to the server
* finializing the mail transaction. $msg_data is the message
* that is to be send with the headers. Each header needs to be
* on a single line followed by a &CRLF& with the message headers
* and the message body being seperated by and additional &CRLF&.
* Implements rfc 821: DATA &CRLF&
* SMTP CODE INTERMEDIATE: 354
&CRLF&.&CRLF&
SMTP CODE SUCCESS: 250
SMTP CODE FAILURE: 552,554,451,452
* SMTP CODE FAILURE: 451,554
* SMTP CODE ERROR
: 500,501,503,421
* @access public
* @return bool
function Data($msg_data) {
$this-&error = # so no confusion is caused
if(!$this-&connected()) {
$this-&error = array(
&error& =& &Called Data() without being connected&);
fputs($this-&smtp_conn,&DATA& . $this-&CRLF);
$rply = $this-&get_lines();
$code = substr($rply,0,3);
if($this-&do_debug &= 2) {
echo &SMTP -& FROM SERVER:& . $this-&CRLF . $
if($code != 354) {
$this-&error =
array(&error& =& &DATA command not accepted from server&,
&smtp_code& =& $code,
&smtp_msg& =& substr($rply,4));
if($this-&do_debug &= 1) {
echo &SMTP -& ERROR: & . $this-&error[&error&] .
&: & . $rply . $this-&CRLF;
# the server is ready to accept data!
# according to rfc 821 we should not send more than 1000
# including the CRLF
# characters on a single line so we will break the data up
# into lines by \r and/or \n then if needed we will break
# each of those into smaller lines to fit within the limit.
# in addition we will be looking for lines that start with
# a period '.' and append and additional period '.' to that
# line. NOTE: this does not count towards are limit.
# normalize the line breaks so we know the explode works
$msg_data = str_replace(&\r\n&,&\n&,$msg_data);
$msg_data = str_replace(&\r&,&\n&,$msg_data);
$lines = explode(&\n&,$msg_data);
# we need to find a good way to determine is headers are
# in the msg_data or if it is a straight msg body
# currently I'm assuming rfc 822 definitions of msg headers
# and if the first field of the first line (':' sperated)
# does not contain a space then it _should_ be a header
# and we can process all lines before a blank && line as
# headers.
$field = substr($lines[0],0,strpos($lines[0],&:&));
$in_headers =
if(!empty($field) && !strstr($field,& &)) {
$in_headers =
$max_line_length = 998; # set here for ease in change
while(list(,$line) = @each($lines)) {
$lines_out =
if($line == && && $in_headers) {
$in_headers =
# ok we need to break this line up into several
# smaller lines
while(strlen($line) & $max_line_length) {
$pos = strrpos(substr($line,0,$max_line_length),& &);
# Patch to fix DOS attack
if(!$pos) {
$pos = $max_line_length - 1;
$lines_out[] = substr($line,0,$pos);
$line = substr($line,$pos + 1);
# if we are processing headers we need to
# add a LWSP-char to the front of the new line
# rfc 822 on long msg headers
if($in_headers) {
$line = &\t& . $
$lines_out[] = $
# now send the lines to the server
while(list(,$line_out) = @each($lines_out)) {
if(strlen($line_out) & 0)
if(substr($line_out, 0, 1) == &.&) {
$line_out = &.& . $line_
fputs($this-&smtp_conn,$line_out . $this-&CRLF);
# ok all the message data has been sent so lets get this
# over with aleady
fputs($this-&smtp_conn, $this-&CRLF . &.& . $this-&CRLF);
$rply = $this-&get_lines();
$code = substr($rply,0,3);
if($this-&do_debug &= 2) {
echo &SMTP -& FROM SERVER:& . $this-&CRLF . $
if($code != 250) {
$this-&error =
array(&error& =& &DATA not accepted from server&,
&smtp_code& =& $code,
&smtp_msg& =& substr($rply,4));
if($this-&do_debug &= 1) {
echo &SMTP -& ERROR: & . $this-&error[&error&] .
&: & . $rply . $this-&CRLF;
* Expand takes the name and asks the server to list all the
* people who are members of the _list_. Expand will return
* back and array of the result or false if an error occurs.
* Each value in the array returned has the format of:
[ &full-name& &sp& ] &path&
* The definition of &path& is defined in rfc 821
* Implements rfc 821: EXPN &SP& &string& &CRLF&
* SMTP CODE SUCCESS: 250
* SMTP CODE FAILURE: 550
* SMTP CODE ERROR
: 500,501,502,504,421
* @access public
* @return string array
function Expand($name) {
$this-&error = # so no confusion is caused
if(!$this-&connected()) {
$this-&error = array(
&error& =& &Called Expand() without being connected&);
fputs($this-&smtp_conn,&EXPN & . $name . $this-&CRLF);
$rply = $this-&get_lines();
$code = substr($rply,0,3);
if($this-&do_debug &= 2) {
echo &SMTP -& FROM SERVER:& . $this-&CRLF . $
if($code != 250) {
$this-&error =
array(&error& =& &EXPN not accepted from server&,
&smtp_code& =& $code,
&smtp_msg& =& substr($rply,4));
if($this-&do_debug &= 1) {
echo &SMTP -& ERROR: & . $this-&error[&error&] .
&: & . $rply . $this-&CRLF;
# parse the reply and place in our array to return to user
$entries = explode($this-&CRLF,$rply);
while(list(,$l) = @each($entries)) {
$list[] = substr($l,4);
* Sends the HELO command to the smtp server.
* This makes sure that we and the server are in
* the same known state.
* Implements from rfc 821: HELO &SP& &domain& &CRLF&
* SMTP CODE SUCCESS: 250
* SMTP CODE ERROR
: 500, 501, 504, 421
* @access public
* @return bool
function Hello($host=&&) {
$this-&error = # so no confusion is caused
if(!$this-&connected()) {
$this-&error = array(
&error& =& &Called Hello() without being connected&);
# if a hostname for the HELO wasn't specified determine
# a suitable one to send
if(empty($host)) {
# we need to determine some sort of appopiate default
# to send to the server
$host = &localhost&;
// Send extended hello first (RFC 2821)
if(!$this-&SendHello(&EHLO&, $host))
if(!$this-&SendHello(&HELO&, $host))
* Sends a HELO/EHLO command.
* @access private
* @return bool
function SendHello($hello, $host) {
fputs($this-&smtp_conn, $hello . & & . $host . $this-&CRLF);
$rply = $this-&get_lines();
$code = substr($rply,0,3);
if($this-&do_debug &= 2) {
echo &SMTP -& FROM SERVER: & . $this-&CRLF . $
if($code != 250) {
$this-&error =
array(&error& =& $hello . & not accepted from server&,
&smtp_code& =& $code,
&smtp_msg& =& substr($rply,4));
if($this-&do_debug &= 1) {
echo &SMTP -& ERROR: & . $this-&error[&error&] .
&: & . $rply . $this-&CRLF;
$this-&helo_rply = $
* Gets help information on the keyword specified. If the keyword
* is not specified then returns generic help, ussually contianing
* A list of keywords that help is available on. This function
* returns the results back to the user. It is up to the user to
* handle the returned data. If an error occurs then false is
* returned with $this-&error set appropiately.
* Implements rfc 821: HELP [ &SP& &string& ] &CRLF&
* SMTP CODE SUCCESS: 211,214
* SMTP CODE ERROR
: 500,501,502,504,421
* @access public
* @return string
function Help($keyword=&&) {
$this-&error = # to avoid confusion
if(!$this-&connected()) {
$this-&error = array(
&error& =& &Called Help() without being connected&);
$extra = &&;
if(!empty($keyword)) {
$extra = & & . $
fputs($this-&smtp_conn,&HELP& . $extra . $this-&CRLF);
$rply = $this-&get_lines();
$code = substr($rply,0,3);
if($this-&do_debug &= 2) {
echo &SMTP -& FROM SERVER:& . $this-&CRLF . $
if($code != 211 && $code != 214) {
$this-&error =
array(&error& =& &HELP not accepted from server&,
&smtp_code& =& $code,
&smtp_msg& =& substr($rply,4));
if($this-&do_debug &= 1) {
echo &SMTP -& ERROR: & . $this-&error[&error&] .
&: & . $rply . $this-&CRLF;
* Starts a mail transaction from the email address specified in
* $from. Returns true if successful or false otherwise. If True
* the mail transaction is started and then one or more Recipient
* commands may be called followed by a Data command.
* Implements rfc 821: MAIL &SP& FROM:&reverse-path& &CRLF&
* SMTP CODE SUCCESS: 250
* SMTP CODE SUCCESS: 552,451,452
* SMTP CODE SUCCESS: 500,501,421
* @access public
* @return bool
function Mail($from) {
$this-&error = # so no confusion is caused
if(!$this-&connected()) {
$this-&error = array(
&error& =& &Called Mail() without being connected&);
fputs($this-&smtp_conn,&MAIL FROM:&& . $from . &&& . $this-&CRLF);
$rply = $this-&get_lines();
$code = substr($rply,0,3);
if($this-&do_debug &= 2) {
echo &SMTP -& FROM SERVER:& . $this-&CRLF . $
if($code != 250) {
$this-&error =
array(&error& =& &MAIL not accepted from server&,
&smtp_code& =& $code,
&smtp_msg& =& substr($rply,4));
if($this-&do_debug &= 1) {
echo &SMTP -& ERROR: & . $this-&error[&error&] .
&: & . $rply . $this-&CRLF;
* Sends the command NOOP to the SMTP server.
* Implements from rfc 821: NOOP &CRLF&
* SMTP CODE SUCCESS: 250
* SMTP CODE ERROR
: 500, 421
* @access public
* @return bool
function Noop() {
$this-&error = # so no confusion is caused
if(!$this-&connected()) {
$this-&error = array(
&error& =& &Called Noop() without being connected&);
fputs($this-&smtp_conn,&NOOP& . $this-&CRLF);
$rply = $this-&get_lines();
$code = substr($rply,0,3);
if($this-&do_debug &= 2) {
echo &SMTP -& FROM SERVER:& . $this-&CRLF . $
if($code != 250) {
$this-&error =
array(&error& =& &NOOP not accepted from server&,
&smtp_code& =& $code,
&smtp_msg& =& substr($rply,4));
if($this-&do_debug &= 1) {
echo &SMTP -& ERROR: & . $this-&error[&error&] .
&: & . $rply . $this-&CRLF;
* Sends the quit command to the server and then closes the socket
* if there is no error or the $close_on_error argument is true.
* Implements from rfc 821: QUIT &CRLF&
* SMTP CODE SUCCESS: 221
* SMTP CODE ERROR
* @access public
* @return bool
function Quit($close_on_error=true) {
$this-&error = # so there is no confusion
if(!$this-&connected()) {
$this-&error = array(
&error& =& &Called Quit() without being connected&);
# send the quit command to the server
fputs($this-&smtp_conn,&quit& . $this-&CRLF);
# get any good-bye messages
$byemsg = $this-&get_lines();
if($this-&do_debug &= 2) {
echo &SMTP -& FROM SERVER:& . $this-&CRLF . $
$code = substr($byemsg,0,3);
if($code != 221) {
# use e as a tmp var cause Close will overwrite $this-&error
$e = array(&error& =& &SMTP server rejected quit command&,
&smtp_code& =& $code,
&smtp_rply& =& substr($byemsg,4));
if($this-&do_debug &= 1) {
echo &SMTP -& ERROR: & . $e[&error&] . &: & .
$byemsg . $this-&CRLF;
if(empty($e) || $close_on_error) {
$this-&Close();
* Sends the command RCPT to the SMTP server with the TO: argument of $to.
* Returns true if the recipient was accepted false if it was rejected.
* Implements from rfc 821: RCPT &SP& TO:&forward-path& &CRLF&
* SMTP CODE SUCCESS: 250,251
* SMTP CODE FAILURE: 550,551,552,553,450,451,452
* SMTP CODE ERROR
: 500,501,503,421
* @access public
* @return bool
function Recipient($to) {
$this-&error = # so no confusion is caused
if(!$this-&connected()) {
$this-&error = array(
&error& =& &Called Recipient() without being connected&);
fputs($this-&smtp_conn,&RCPT TO:&& . $to . &&& . $this-&CRLF);
$rply = $this-&get_lines();
$code = substr($rply,0,3);
if($this-&do_debug &= 2) {
echo &SMTP -& FROM SERVER:& . $this-&CRLF . $
if($code != 250 && $code != 251) {
$this-&error =
array(&error& =& &RCPT not accepted from server&,
&smtp_code& =& $code,
&smtp_msg& =& substr($rply,4));
if($this-&do_debug &= 1) {
echo &SMTP -& ERROR: & . $this-&error[&error&] .
&: & . $rply . $this-&CRLF;
* Sends the RSET command to abort and transaction that is
* currently in progress. Returns true if successful false
* otherwise.
* Implements rfc 821: RSET &CRLF&
* SMTP CODE SUCCESS: 250
* SMTP CODE ERROR
: 500,501,504,421
* @access public
* @return bool
function Reset() {
$this-&error = # so no confusion is caused
if(!$this-&connected()) {
$this-&error = array(
&error& =& &Called Reset() without being connected&);
fputs($this-&smtp_conn,&RSET& . $this-&CRLF);
$rply = $this-&get_lines();
$code = substr($rply,0,3);
if($this-&do_debug &= 2) {
echo &SMTP -& FROM SERVER:& . $this-&CRLF . $
if($code != 250) {
$this-&error =
array(&error& =& &RSET failed&,
&smtp_code& =& $code,
&smtp_msg& =& substr($rply,4));
if($this-&do_debug &= 1) {
echo &SMTP -& ERROR: & . $this-&error[&error&] .
&: & . $rply . $this-&CRLF;
* Starts a mail transaction from the email address specified in
* $from. Returns true if successful or false otherwise. If True
* the mail transaction is started and then one or more Recipient
* commands may be called followed by a Data command. This command
* will send the message to the users terminal if they are logged
* Implements rfc 821: SEND &SP& FROM:&reverse-path& &CRLF&
* SMTP CODE SUCCESS: 250
* SMTP CODE SUCCESS: 552,451,452
* SMTP CODE SUCCESS: 500,501,502,421
* @access public
* @return bool
function Send($from) {
$this-&error = # so no confusion is caused
if(!$this-&connected()) {
$this-&error = array(
&error& =& &Called Send() without being connected&);
fputs($this-&smtp_conn,&SEND FROM:& . $from . $this}

我要回帖

更多关于 逆战桌面不显示游戏 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信