Explorar o código

信呼OA版本v2.3.8

雨中磐石 %!s(int64=3) %!d(string=hai) anos
pai
achega
e3fcd913e3
Modificáronse 100 ficheiros con 6482 adicións e 73 borrados
  1. 0 36
      README.en.md
  2. 60 37
      README.md
  3. 39 0
      api.php
  4. 102 0
      config/config.php
  5. 12 0
      config/iplist.php
  6. 88 0
      config/iplogs.php
  7. 3 0
      config/version.php
  8. BIN=BIN
      favicon.ico
  9. BIN=BIN
      images/adddk.png
  10. BIN=BIN
      images/apply.png
  11. BIN=BIN
      images/back.png
  12. BIN=BIN
      images/bq.png
  13. BIN=BIN
      images/bwl.png
  14. BIN=BIN
      images/bwl2.png
  15. BIN=BIN
      images/calendar.png
  16. BIN=BIN
      images/checkbox0.png
  17. BIN=BIN
      images/checkbox1.png
  18. BIN=BIN
      images/close.gif
  19. BIN=BIN
      images/crm.png
  20. BIN=BIN
      images/daiban.png
  21. BIN=BIN
      images/daily.png
  22. BIN=BIN
      images/del.png
  23. BIN=BIN
      images/email.png
  24. BIN=BIN
      images/error.png
  25. BIN=BIN
      images/ewml.png
  26. BIN=BIN
      images/fawen.png
  27. BIN=BIN
      images/file.png
  28. BIN=BIN
      images/files.png
  29. BIN=BIN
      images/fkuan.png
  30. BIN=BIN
      images/flow.png
  31. BIN=BIN
      images/folder.png
  32. BIN=BIN
      images/gong.png
  33. BIN=BIN
      images/group.png
  34. BIN=BIN
      images/gw.png
  35. BIN=BIN
      images/gzt.png
  36. BIN=BIN
      images/helpbg.png
  37. BIN=BIN
      images/hetong.png
  38. BIN=BIN
      images/i.gif
  39. BIN=BIN
      images/jia.png
  40. BIN=BIN
      images/jian1.gif
  41. BIN=BIN
      images/jian2.gif
  42. BIN=BIN
      images/jiank.png
  43. BIN=BIN
      images/jwcl.png
  44. BIN=BIN
      images/kaoqin.png
  45. BIN=BIN
      images/kaoshi.png
  46. BIN=BIN
      images/loading.gif
  47. BIN=BIN
      images/loadings.gif
  48. BIN=BIN
      images/logo.png
  49. BIN=BIN
      images/meet.png
  50. BIN=BIN
      images/mloading.gif
  51. BIN=BIN
      images/nav_chat0.png
  52. BIN=BIN
      images/nav_chat1.png
  53. BIN=BIN
      images/nav_my0.png
  54. BIN=BIN
      images/nav_my1.png
  55. BIN=BIN
      images/nav_user0.png
  56. BIN=BIN
      images/nav_user1.png
  57. BIN=BIN
      images/nav_ying0.png
  58. BIN=BIN
      images/nav_ying1.png
  59. BIN=BIN
      images/new.gif
  60. BIN=BIN
      images/news.png
  61. BIN=BIN
      images/noface.png
  62. BIN=BIN
      images/noimg.jpg
  63. BIN=BIN
      images/nologo.png
  64. BIN=BIN
      images/project.png
  65. BIN=BIN
      images/sale.png
  66. BIN=BIN
      images/shouwen.png
  67. BIN=BIN
      images/skuan.png
  68. BIN=BIN
      images/sousuo.png
  69. BIN=BIN
      images/taolun.png
  70. BIN=BIN
      images/tiku.png
  71. BIN=BIN
      images/todo.png
  72. BIN=BIN
      images/tongxunlu.png
  73. BIN=BIN
      images/waichu.png
  74. BIN=BIN
      images/wclose.png
  75. BIN=BIN
      images/white.gif
  76. BIN=BIN
      images/wjj.png
  77. BIN=BIN
      images/work.png
  78. BIN=BIN
      images/xh829.png
  79. BIN=BIN
      images/xiangyou1.png
  80. BIN=BIN
      images/zhishi.png
  81. 209 0
      include/Action.php
  82. 47 0
      include/Chajian.php
  83. 191 0
      include/Model.php
  84. 2320 0
      include/PHPMailer/class.phpmailer.php
  85. 407 0
      include/PHPMailer/class.pop3.php
  86. 814 0
      include/PHPMailer/class.smtp.php
  87. 90 0
      include/View.php
  88. 98 0
      include/chajian/JPushChajian.php
  89. 383 0
      include/chajian/PHPExcelChajian.php
  90. 65 0
      include/chajian/PHPExcelReaderChajian.php
  91. 69 0
      include/chajian/PHPWordChajian.php
  92. 180 0
      include/chajian/alismsChajian.php
  93. 95 0
      include/chajian/arrayChajian.php
  94. 123 0
      include/chajian/cacheChajian.php
  95. 247 0
      include/chajian/calendarChajian.php
  96. 122 0
      include/chajian/checkChajian.php
  97. 40 0
      include/chajian/colorChajian.php
  98. 146 0
      include/chajian/curlChajian.php
  99. 313 0
      include/chajian/dateChajian.php
  100. 219 0
      include/chajian/downChajian.php

+ 0 - 36
README.en.md

@@ -1,36 +0,0 @@
-# xinhu
-
-#### Description
-信呼,免费开源的办公OA系统,包括APP,pc上客户端,REIM即时通信,服务端等,让每个企业单位都有自己的办公系统。
-
-#### Software Architecture
-Software architecture description
-
-#### Installation
-
-1.  xxxx
-2.  xxxx
-3.  xxxx
-
-#### Instructions
-
-1.  xxxx
-2.  xxxx
-3.  xxxx
-
-#### Contribution
-
-1.  Fork the repository
-2.  Create Feat_xxx branch
-3.  Commit your code
-4.  Create Pull Request
-
-
-#### Gitee Feature
-
-1.  You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
-2.  Gitee blog [blog.gitee.com](https://blog.gitee.com)
-3.  Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
-4.  The most valuable open source project [GVP](https://gitee.com/gvp)
-5.  The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
-6.  The most popular members  [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

+ 60 - 37
README.md

@@ -1,37 +1,60 @@
-# xinhu
-
-#### 浠嬬粛
-淇″懠锛屽厤璐瑰紑婧愮殑鍔炲叕OA绯荤粺锛屽寘鎷珹PP锛宲c涓婂�鎴风�锛孯EIM鍗虫椂閫氫俊锛屾湇鍔$�绛夛紝璁╂瘡涓�紒涓氬崟浣嶉兘鏈夎嚜宸辩殑鍔炲叕绯荤粺銆�
-
-#### 杞�欢鏋舵瀯
-杞�欢鏋舵瀯璇存槑
-
-
-#### 瀹夎�鏁欑▼
-
-1.  xxxx
-2.  xxxx
-3.  xxxx
-
-#### 浣跨敤璇存槑
-
-1.  xxxx
-2.  xxxx
-3.  xxxx
-
-#### 鍙備笌璐$尞
-
-1.  Fork 鏈�粨搴�
-2.  鏂板缓 Feat_xxx 鍒嗘敮
-3.  鎻愪氦浠g爜
-4.  鏂板缓 Pull Request
-
-
-#### 鐗规妧
-
-1.  浣跨敤 Readme\_XXX.md 鏉ユ敮鎸佷笉鍚岀殑璇�█锛屼緥濡� Readme\_en.md, Readme\_zh.md
-2.  Gitee 瀹樻柟鍗氬� [blog.gitee.com](https://blog.gitee.com)
-3.  浣犲彲浠� [https://gitee.com/explore](https://gitee.com/explore) 杩欎釜鍦板潃鏉ヤ簡瑙� Gitee 涓婄殑浼樼�寮€婧愰」鐩�
-4.  [GVP](https://gitee.com/gvp) 鍏ㄧО鏄� Gitee 鏈€鏈変环鍊煎紑婧愰」鐩�紝鏄�患鍚堣瘎瀹氬嚭鐨勪紭绉€寮€婧愰」鐩�
-5.  Gitee 瀹樻柟鎻愪緵鐨勪娇鐢ㄦ墜鍐� [https://gitee.com/help](https://gitee.com/help)
-6.  Gitee 灏侀潰浜虹墿鏄�竴妗g敤鏉ュ睍绀� Gitee 浼氬憳椋庨噰鐨勬爮鐩� [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
+# 信呼,免费开源的办公OA系统
+
+开发者:雨中磐石(rainrock)  
+邮箱:admin@rockoa.com  
+公司团队:信呼开发团队  
+官网网站:http://www.rockoa.com/  
+源码仅供学习二次开发使用,禁止二次发布,禁止用于商业用途出售等(违者必究)  
+版权:Copyright @2016-2022 信呼开发团队  
+版本整理时间:2022-07-10 23:59:59  
+版本号:V2.3.8   
+
+
+### V2.3.8更新说明
+1、完善系统安全性。  
+2、更多升级日志详见:http://www.rockoa.com/view_core.html  
+
+
+### 安装说明
+1、环境要求:可以运行在Win/Linux系统下,php5.2~7.3,mysql5.3~5.7  
+2、测试环境搭建详见:http://www.rockoa.com/view_install.html  
+3、自己手动安装详见:http://www.rockoa.com/view_anzz.html  
+4、配置文件:webmain/webmainConfig.php,也可到【系统→系统工具→系统设置】下修改  
+5、打开浏览器访问:http://您的地址/  
+6、您使用此系统时,请务必遵守我们的开源思想,请尊重我们的劳动成果,谢谢!
+
+### 开发帮助文档
+地址:http://www.rockoa.com/help.html  
+
+### 信呼相关产品
+1、信呼OA系统(后台/手机网页版/REIM)  
+2、安卓APP  
+3、信呼服务端(即时通信,计划任务使用)  
+4、REIM即时通信PC客户端  
+5、以上下载地址:http://www.rockoa.com/view_down.html  
+
+
+
+### 信呼声明 
+1、没有一款系统是100%安全,信呼也是如此,任何暴露在公网中的系统,都有数据泄露的风险,一旦您决定将信呼OA部署在公网环境中,请仔细评估可能由此带来的风险,并尽可能的加强安全措施。  
+2、或许您觉得此系统不好有缺陷或漏洞等,欢迎提意见和您的想法给我们,或者发邮件给我们:admin@rockoa.com。  
+
+### 声明感谢  
+系统有用到一些开源的项目,特别感谢他们提供奉献,不分先后顺序。    
+1、PHP后端语言:http://www.php.net/   
+2、MySql数据库:https://www.mysql.com/    
+3、Bootstrap后台样式组件:http://v3.bootcss.com/components/  
+4、字体图标:http://www.bootcss.com/p/font-awesome/  
+5、Jquery框架:http://jquery.com/  
+6、PHPMailer邮件发送组件:https://github.com/PHPMailer/PHPMailer  
+7、kindeditor富文本编辑器:http://kindeditor.net/  
+8、pdfjs预览pdf:http://mozilla.github.io/pdf.js/  
+9、weui手机端框架:https://weui.io/0.4.x/#/  
+10、phpqrcode生成二维码:http://phpqrcode.sourceforge.net/    
+11、JPush极光推送:https://www.jiguang.cn/  
+12、小米推送:https://dev.mi.com/console/appservice/push.html  
+13、workerman服务端phpsocket框架:http://www.workerman.net/  
+14、nwjs的PC客户端框架:https://nwjs.io/  
+15、iconfont图标库:http://www.iconfont.cn/   
+16、腾讯地图:http://map.qq.com/  
+16、nodejs:https://nodejs.org/ 

+ 39 - 0
api.php

@@ -0,0 +1,39 @@
+<?php
+/**
+*	api的入口地址请求访问,访问方法:http://我的域名/api.php?m=index&a=方法
+*	主页:http://www.rockoa.com/
+*	软件:信呼
+*	作者:雨中磐石(rainrock)
+*/
+define('ENTRANCE', 'api');
+include_once('config/config.php');
+$_paths = '';
+$d		= 'task';$m	= 'index';$a = 'index';
+if(isset($_GET['m'])){
+	$m  = $rock->get('m');
+	$a  = $rock->get('a', $a);
+}else{
+	if(isset($_SERVER['PHP_SELF']))$_paths=$_SERVER['PHP_SELF'];
+	if($_paths==''&&isset($_SERVER['ORIG_PATH_INFO']))$_paths=$_SERVER['ORIG_PATH_INFO'];
+	$_patha = explode('api.php', $_paths);
+	$_paths = '/index/index';
+	if(isset($_patha[1])){
+		$_paths = $_patha[1];
+	}else{
+		if(isset($_SERVER['PATH_INFO']))$_paths=$_SERVER['PATH_INFO'];
+	}
+}
+unset($_GET['d']);
+unset($_GET['m']);
+unset($_GET['a']);
+if($_paths){
+	$_pa = explode('/', $_paths);
+	if(isset($_pa[1])&&$_pa[1])$m=$_pa[1];
+	if(isset($_pa[2])&&$_pa[2])$a=$_pa[2];
+}
+if(substr($m,0,4)=='open'){
+	$m 	= ''.$m.'|openapi';
+}else{
+	$m 	= ''.$m.'|api';
+}
+include_once('include/View.php');

+ 102 - 0
config/config.php

@@ -0,0 +1,102 @@
+<?php
+/**
+*	来自:信呼开发团队
+*	作者:磐石(rainrock)
+*	网址:http://www.rockoa.com/
+*	系统默认配置文件,请不要去修改
+*	要修改配置文件在:webmain/webmainConfig.php
+*/
+@session_start();
+if(function_exists('date_default_timezone_set'))date_default_timezone_set('Asia/Shanghai'); //设置默认时区
+header('Content-Type:text/html;charset=utf-8');
+define('ROOT_PATH',str_replace('\\','/',dirname(dirname(__FILE__))));	//系统跟目录路径
+
+include_once(''.ROOT_PATH.'/include/rockFun.php');
+include_once(''.ROOT_PATH.'/include/Chajian.php');
+include_once(''.ROOT_PATH.'/include/class/rockClass.php');
+$rock 		= new rockClass();
+
+$db			= null;		
+$smarty		= false;
+define('HOST', $rock->host);
+define('REWRITE', 'true');
+if(!defined('PROJECT'))define('PROJECT', 'webmain');
+if(!defined('ENTRANCE'))define('ENTRANCE', 'index');
+
+$config		= array(
+	'title'		=> '信呼',
+	'url'		=> '',
+	'urly'		=> 'http://www.rockoa.com/',	//官网域名地址,修改后就无法提供在线升级了。
+	'db_host'	=> '127.0.0.1',
+	'db_user'	=> 'root',
+	'db_pass'	=> '',
+	'db_base'	=> '',
+	'perfix'	=> '',
+	'qom'		=> '',
+	'highpass'	=> '',
+	'install'	=> false,
+	'version'	=> require('version.php'),
+	'path'		=> 'index',
+	'updir'		=> 'upload',
+	'dbencrypt'	=> false,
+	'sqllog'	=> false,
+	'checksign'	=> false,			//列表请求是否验证
+	'memory_limit'	=> '',			//运行内存大小
+	'timeout'		=> -1,			//抄送时间(秒),-1默认的
+	'db_drive'		=> 'mysqli',	//数据库操作驱动
+	'db_engine'		=> 'MyISAM',	//数据库默认引擎
+	'debug'			=> true,	//默认debug模式
+	'reim_show' 	=> true,	//首页是否显示REIM
+	'mobile_show' 	=> true,	//首页是否显示手机版
+	'accesslogs' 	=> false,	//是否记录访问日志和限制IP
+	'upurl'			=> '', 		//上传文件附件地址(还不能使用)
+	'authorkey'		=> '', 		//系统授权的key,请联系官网获取
+	'companymode'	=> false 	//是否开启多单位模式切换
+);
+
+//引入配置文件
+$_confpath		= $rock->strformat('?0/?1/?1Config.php', ROOT_PATH, PROJECT);
+if(file_exists($_confpath)){
+	$_tempconf	= require($_confpath);
+	foreach($_tempconf as $_tkey=>$_tvs)$config[$_tkey] = $_tvs;
+	if(isempt($config['url']))$config['url'] = $rock->url();
+	if(!isempt($config['memory_limit']) && function_exists('ini_set'))
+		ini_set('memory_limit', $config['memory_limit']);
+	if($config['timeout']>-1 && function_exists('set_time_limit'))set_time_limit($config['timeout']);	
+}
+
+$_confpath	= ''.ROOT_PATH.'/config/author.php';
+if(file_exists($_confpath)){
+	$config['authorkey'] = require($_confpath);
+}
+
+$_confpath	= ''.ROOT_PATH.'/config/xinhuplat.php';
+if(file_exists($_confpath))include_once($_confpath);
+if(!defined('COMPANYNUM'))define('COMPANYNUM', '');
+
+define('DEBUG', $config['debug']);
+error_reporting(DEBUG ? E_ALL : 0);
+
+define('TITLE', $config['title']);
+define('URL', $config['url']);
+define('URLY', $config['urly']);
+define('PATH', $config['path']);
+
+define('DB_DRIVE', $config['db_drive']);
+define('DB_HOST', $config['db_host']);
+define('DB_USER', $config['db_user']);
+define('DB_PASS', $config['db_pass']);
+define('DB_BASE', $config['db_base']);
+
+define('UPDIR', $config['updir']);
+define('PREFIX', $config['perfix']);
+define('QOM', $config['qom']);
+define('VERSION', $config['version']);
+define('HIGHPASS', $config['highpass']);
+define('SYSURL', ''.URL.PATH.'.php');
+define('UPURL', $config['upurl']);
+define('ISMORECOM', $config['companymode']);
+
+$_confpath	= ''.ROOT_PATH.'/config/iplogs.php'; //这个用来限制IP访问的
+if(file_exists($_confpath) && PHP_SAPI != 'cli')include_once($_confpath);
+$rock->initRock();

+ 12 - 0
config/iplist.php

@@ -0,0 +1,12 @@
+<?php
+/**
+*	这个页面是设置黑白名单访问的
+*/
+return array(
+
+	//黑名单IP,多个,分开如:127.0.0.1,192.168.1.100,也可以写192.168.1这样就是现在192.168.1.*所有的
+	'blackip' 	=> '',
+	
+	 //白名单
+	'whiteip'	=> ''
+);

+ 88 - 0
config/iplogs.php

@@ -0,0 +1,88 @@
+<?php
+/**
+*	添加方法日志,和IP限制判断
+*/
+function ipwhiteshow($ip, $rock){
+	$iplist = ''.ROOT_PATH.'/config/iplist.php';
+	$bool 	= 0;
+	if(file_exists($iplist)){
+		$iparr 	= require($iplist);
+	}else{
+		$iparr 	= array(
+			'blackip' 	=> '',
+			'whiteip'	=> '' 
+		);
+	}
+
+	//白名单判断
+	$whiteip = $iparr['whiteip'];
+	if($whiteip!=''){
+		$whiteipa = explode(',', $whiteip);
+		foreach($whiteipa as $ips){
+			$bo = strpos($ip, $ips);
+			if($bo===0 || $ips=='*'){
+				$bool = 1; //可以访问
+				break;
+			}
+		}
+	}
+	
+	//黑名单判断
+	if($bool==0){
+		$blackip = $iparr['blackip'];
+		if($blackip!=''){
+			$blackipa = explode(',', $blackip);
+			foreach($blackipa as $ips){
+				$bo = strpos($ip, $ips);
+				if($bo===0 || $ips=='*'){
+					$bool = 2;//不能访问
+					break;
+				}
+			}
+		}
+	}
+
+	//创建访问日志
+	if(getconfig('accesslogs')){
+		$str = '';
+		foreach($_SERVER as $k=>$v)$str.='['.$k.']:'.$v.chr(10).'';
+		
+		$str1 = '';
+		foreach($_GET as $k=>$v)$str1.='['.$k.']:'.$v.chr(10).'';
+		
+		$str2 = '';
+		foreach($_POST as $k=>$v)$str2.='['.$k.']:'.$v.chr(10).'';
+		$act  = arrvalue($_SERVER,'REQUEST_METHOD');
+		if($act=='POST' && $str2==''){
+			$str2 = arrvalue($GLOBALS, 'HTTP_RAW_POST_DATA');
+		}
+
+		$logs = ''.UPDIR.'/logs/'.date('Y-m-d').'/'.date('H').'/'.date('H.i.s').'_'.$act.'_'.$ip.'_'.rand(100,999).'.log';
+$logstr = '[datetime]:'.$rock->now.'
+[URL]:'.$rock->nowurl().'	
+[ACTION]:'.$act.'
+[IP]:'.$ip.'
+[GET]
+'.$str1.'
+[POST]
+'.$str2.'
+[SERVER]
+'.$str.'	
+';
+		$rock->createtxt($logs, $logstr);
+	}
+	
+	
+	if($bool==2){
+		$logs = ''.UPDIR.'/logs_access/'.date('YmdHis').'_'.rand(100,999).'.log';
+		$logstr = '[datetime]:'.$rock->now.''.chr(10).'[URL]:'.$rock->nowurl().''.chr(10).'[IP]:'.$ip.'';		
+		$rock->createtxt($logs, $logstr);
+		exit('您IP['.$ip.']禁止访问我们站点,有问题请联系我们');
+	}
+}
+
+function ipwhiteshows($ips, $rock){
+	$ipa = explode(',', $ips); 
+	foreach($ipa as $ip)ipwhiteshow($ip, $rock);
+}
+ipwhiteshows($rock->ip, $rock);

+ 3 - 0
config/version.php

@@ -0,0 +1,3 @@
+<?php
+//版本
+return '2.3.8';

BIN=BIN
favicon.ico


BIN=BIN
images/adddk.png


BIN=BIN
images/apply.png


BIN=BIN
images/back.png


BIN=BIN
images/bq.png


BIN=BIN
images/bwl.png


BIN=BIN
images/bwl2.png


BIN=BIN
images/calendar.png


BIN=BIN
images/checkbox0.png


BIN=BIN
images/checkbox1.png


BIN=BIN
images/close.gif


BIN=BIN
images/crm.png


BIN=BIN
images/daiban.png


BIN=BIN
images/daily.png


BIN=BIN
images/del.png


BIN=BIN
images/email.png


BIN=BIN
images/error.png


BIN=BIN
images/ewml.png


BIN=BIN
images/fawen.png


BIN=BIN
images/file.png


BIN=BIN
images/files.png


BIN=BIN
images/fkuan.png


BIN=BIN
images/flow.png


BIN=BIN
images/folder.png


BIN=BIN
images/gong.png


BIN=BIN
images/group.png


BIN=BIN
images/gw.png


BIN=BIN
images/gzt.png


BIN=BIN
images/helpbg.png


BIN=BIN
images/hetong.png


BIN=BIN
images/i.gif


BIN=BIN
images/jia.png


BIN=BIN
images/jian1.gif


BIN=BIN
images/jian2.gif


BIN=BIN
images/jiank.png


BIN=BIN
images/jwcl.png


BIN=BIN
images/kaoqin.png


BIN=BIN
images/kaoshi.png


BIN=BIN
images/loading.gif


BIN=BIN
images/loadings.gif


BIN=BIN
images/logo.png


BIN=BIN
images/meet.png


BIN=BIN
images/mloading.gif


BIN=BIN
images/nav_chat0.png


BIN=BIN
images/nav_chat1.png


BIN=BIN
images/nav_my0.png


BIN=BIN
images/nav_my1.png


BIN=BIN
images/nav_user0.png


BIN=BIN
images/nav_user1.png


BIN=BIN
images/nav_ying0.png


BIN=BIN
images/nav_ying1.png


BIN=BIN
images/new.gif


BIN=BIN
images/news.png


BIN=BIN
images/noface.png


BIN=BIN
images/noimg.jpg


BIN=BIN
images/nologo.png


BIN=BIN
images/project.png


BIN=BIN
images/sale.png


BIN=BIN
images/shouwen.png


BIN=BIN
images/skuan.png


BIN=BIN
images/sousuo.png


BIN=BIN
images/taolun.png


BIN=BIN
images/tiku.png


BIN=BIN
images/todo.png


BIN=BIN
images/tongxunlu.png


BIN=BIN
images/waichu.png


BIN=BIN
images/wclose.png


BIN=BIN
images/white.gif


BIN=BIN
images/wjj.png


BIN=BIN
images/work.png


BIN=BIN
images/xh829.png


BIN=BIN
images/xiangyou1.png


BIN=BIN
images/zhishi.png


+ 209 - 0
include/Action.php

@@ -0,0 +1,209 @@
+<?php 
+/**
+	*****************************************************************
+	* 联系QQ: 290802026/1073744729									*
+	* 版  本: V2.0													*
+	* 开发者:雨中磐石工作室										*
+	* 邮  箱: admin@rockoa.com										*
+	* 网  址: http://www.rockoa.com/								*
+	* 说  明: 主控制器处理											*
+	* 备  注: 未经允许不得商业出售,代码欢迎参考纠正				*
+	*****************************************************************
+*/
+
+abstract class mainAction{
+	
+	public $rock;
+	public $db;
+	public $smarty;
+	public $smartydata	= array();	//模版数据
+	public $assigndata	= array();
+	public $display		= true;		//是否显示模板	
+	public $bodytitle	= '';		//副标题
+	public $keywords	= '';		//关键词
+	public $description	= '';		//说明
+	public $linkdb		= true;		//是否连接数据库
+	public $params		= array();	//参数
+	public $now;
+	public $date;
+	public $ip;
+	public $web;
+	public $title		= TITLE;
+	public $titles		= '';
+	public $option;
+	public $jm;
+	
+	public $table;
+	public $extentid	= 0;
+	public $importjs	= '';
+	public $perfix		= '';
+	public $tplname		= '';		//模板文件
+	public $tplpath		= '';		//模板文件路径
+	public $tpltype		= 'tpl';
+	public $tpldom		= 'html';
+	public $displayfile	= '';
+	
+	public $bodyMessage	= '';		//返回的内容
+	
+	public function __construct()
+	{
+		$this->rock		= $GLOBALS['rock'];
+		$this->smarty	= $GLOBALS['smarty'];
+		$this->jm		= c('jm', true);
+		$_obj = c('lang');if($_obj!=NULL && method_exists($_obj,'initLang'))$_obj->initLang();
+		$this->now		= $this->rock->now();
+		$this->date		= $this->rock->date;
+		$this->ip		= $this->rock->ip;
+		$this->web		= $this->rock->web;
+		$this->perfix	= PREFIX;
+		$this->display	= true;
+		$this->initMysql();	
+		$this->initConstruct();
+		$this->initProject();
+		$this->initAction();
+	}
+	
+	public function defaultAction(){}
+	public function initAction(){}
+	public function initProject(){}
+	public function afterAction(){}
+	public function initMysql(){}
+	public function beforeAction(){}
+	
+	public function T($n)
+	{
+		return $this->perfix.''.$n;
+	}
+	
+	public function assign($k, $v)
+	{
+		$this->assigndata[$k]=$v;
+	}
+
+	private function initConstruct()
+	{
+		$linkdb			= $this->rock->get('linkdb','true');
+		$this->params	= explode('-', $this->rock->get('s'));	//参数
+		if($linkdb == 'true' && $this->linkdb){
+			$this->initMysqllink();
+		}
+	}
+
+	private function initMysqllink()
+	{
+		$this->db		= import(DB_DRIVE);
+		$GLOBALS['db']	= $this->db;
+		include_once(''.ROOT_PATH.'/include/Model.php');
+		$this->option	= m('option');
+	}
+	
+	private function setBasedata()
+	{
+		$this->smartydata['bodytitle']	= $this->bodytitle;
+		$this->smartydata['keywords']	= $this->keywords;
+		$this->smartydata['description']= $this->description;
+		$this->smartydata['title']		= $this->title;
+		$this->smartydata['titles']		= $this->titles;
+		$this->smartydata['rewrite']	= REWRITE;
+		$this->smartydata['now']		= $this->now;
+		$this->smartydata['web']		= $this->rock->web;
+		$this->smartydata['ip']			= $this->ip;
+		$this->smartydata['url']		= URL;
+		$this->smartydata['urly']		= URLY;
+		$web 	= $this->rock->web;
+		$this->assign('web', $web);
+		$showheader	= 1;
+		$hide 	= $this->get('hideheader', $this->getsession('hideheader'));
+		if($hide=='true')$this->rock->savesession(array('hideheader' => $hide));
+		if($this->rock->iswebbro(0)
+			|| $this->rock->iswebbro(1)
+			|| $this->rock->iswebbro(4)
+			|| $this->rock->iswebbro(7)
+			|| $hide=='true'
+			|| $this->get('headerhide')=='true'
+			|| $this->rock->iswebbro(2))$showheader = 0; //隐藏头部
+		if($this->get('showheader')=='true')$showheader = 1;
+		$this->assign('showheader', $showheader);
+	}
+
+	public function setSmartyData()
+	{
+		$this->setBasedata();
+	}
+	
+	public function setHtmlData()
+	{
+		$this->setBasedata();
+		
+	}
+
+	public function getsession($name,$dev='')
+	{
+		return $this->rock->session($name, $dev);
+	}
+	
+	public function post($na, $dev='', $lx=0)
+	{
+		return $this->rock->post($na, $dev, $lx);
+	}
+	
+	public function get($na, $dev='', $lx=0)
+	{
+		return $this->rock->get($na, $dev, $lx);
+	}
+	
+	public function request($na, $dev='', $lx=0)
+	{
+		return $this->rock->request($na, $dev, $lx);
+	}
+	
+	public function isempt($str)
+	{
+		return $this->rock->isempt($str);
+	}
+	
+	public function contain($str, $a)
+	{
+		return $this->rock->contain($str, $a);
+	}
+	
+	public function getcookie($name, $dev='')
+	{
+		return $this->rock->cookie($name, $dev);
+	}
+	
+	public function stringformat($str, $arr=array())
+	{
+		return $this->rock->stringformat($str, $arr);
+	}
+	
+	public function getcan($i,$dev='')
+	{
+		$val	= '';
+		if(isset($this->params[$i]))$val=$this->params[$i];
+		if($this->rock->isempt($val)){
+			$val=$dev;
+		}else{
+			$val=str_replace('[a]','-',$val);
+		}
+		return $val;
+	}
+	
+	public function getmnumAjax()
+	{
+		$mnum	= $this->rock->request('mnum');
+		$rows	= $this->option->getmnum($mnum);
+		echo json_encode($rows);
+	}
+	
+	public function returnjson($arr)
+	{
+		echo json_encode($arr);
+		exit();
+	}
+		
+	public function showreturn($arr='', $msg='', $code=200)
+	{
+		showreturn($arr, $msg, $code);
+	}
+}

+ 47 - 0
include/Chajian.php

@@ -0,0 +1,47 @@
+<?php 
+/**
+	*****************************************************************
+	* 联系QQ: 290802026/1073744729									*
+	* 版  本: V2.0													*
+	* 开发者:雨中磐石工作室										*
+	* 邮  箱: qqqq2900@126.com										*
+	* 网  址: http://www.rockoa.com/								*
+	* 说  明: 插件主类												*
+	* 备  注: 未经允许不得商业出售,代码欢迎参考纠正			*
+	* 创建时间: 2014-08-30											*
+	*****************************************************************
+*/
+abstract class Chajian{
+	
+	public	$rock;
+	public 	$db;
+	public 	$adminname;
+	public 	$adminid;
+	
+	public function __construct()
+	{
+		$this->rock			= $GLOBALS['rock'];
+		$this->db			= $GLOBALS['db'];
+		$this->adminid		= $this->rock->adminid;
+		$this->adminname	= $this->rock->adminname;
+		$this->initChajian();
+	}
+	
+	public function __destruct()
+	{
+		$this->destChajian();
+	}
+	
+	public function isempt($str)
+	{
+		return $this->rock->isempt($str);
+	}
+	
+	public function contain($str, $s1)
+	{
+		return $this->rock->contain($str, $s1);
+	}
+		
+	protected function initChajian(){}
+	protected function destChajian(){}
+}

+ 191 - 0
include/Model.php

@@ -0,0 +1,191 @@
+<?php 
+/**
+	*****************************************************************
+	* 联系QQ: 290802026											*
+	* 版  本: V2.0													*
+	* 开发者:雨中磐石工作室										*
+	* 邮  箱: admin@rockoa.com										*
+	* 网  址: http://www.rockoa.com/								*
+	* 说  明: 数据模型												*
+	* 备  注: 未经允许不得商业出售,代码欢迎参考纠正				*
+	*****************************************************************
+*/
+
+abstract class Model{
+	
+	public 	$perfix		= PREFIX;
+	public	$rock;
+	public 	$db;
+	public  $table;
+	public 	$adminname;
+	public 	$adminid;
+	public 	$tempxinxi	= array();
+	
+	public function __construct($table='')
+	{
+		$this->rock			= $GLOBALS['rock'];
+		$this->db			= $GLOBALS['db'];
+		$this->adminid		= $this->rock->adminid;
+		$this->adminname	= $this->rock->adminname;
+		$this->settable($table);
+		$this->initModel();
+	}
+	
+	public function settable($table, $qzbo=true)
+	{
+		$this->table	= ''.$this->perfix.''.$table.'';
+		if(!$qzbo)$this->table = $table;
+	}
+	
+	public function initModel(){}
+	
+
+	public function getmou($fields, $where, $order='')
+	{
+		return $this->db->getmou($this->table, $fields, $where, $order);
+	}
+
+	public function getone($where, $fields='*', $order='')
+	{
+		return $this->db->getone($this->table, $where, $fields, $order);
+	}
+	
+	public function getrows($where, $fields='*', $order='', $limit='')
+	{
+		return $this->db->getrows($this->table, $where, $fields, $order, $limit);
+	}
+	
+	public function getall($where, $fields='*', $order='', $limit='')
+	{
+		$sql	= $this->db->getsql(array(
+			'fields'	=> $fields,
+			'table'		=> $this->table,
+			'where'		=> $where,
+			'order'		=> $order,
+			'limit'		=> $limit
+		));
+		return $this->db->getall($sql);
+	}
+	
+	public function getarr($where, $fields='*', $kfied='id')
+	{
+		return $this->db->getarr($this->table, $where, $fields, $kfied);
+	}
+	public function rows($where)
+	{
+		return $this->db->rows($this->table, $where);
+	}
+
+	public function query($where, $fields='*', $order='', $limit='')
+	{
+		$sql	= $this->db->getsql(array(
+			'fields'	=> $fields,
+			'table'		=> $this->table,
+			'where'		=> $where,
+			'order'		=> $order,
+			'limit'		=> $limit
+		));
+		return $this->db->query($sql);
+	}
+	
+	public function record($arr, $where='')
+	{
+		return $this->db->record($this->table, $arr, $where);
+	}
+	
+	public function update($arr,$where)
+	{
+		return $this->record($arr, $where);
+	}
+	
+	public function insert($arr)
+	{
+		$nid = 0;
+		if($this->record($arr, ''))$nid = $this->db->insert_id();
+		return $nid;
+	}
+	
+	public function insertAll($arr)
+	{
+		$name 	= $values = '';
+		foreach($arr as $k=>$rs){
+			$cont = '';
+			foreach($rs as $i=>$v){
+				if($k==0)$name.=',`'.$i.'`';
+				$cont.=",".$this->db->toaddval($v)."";
+			}
+			$cont = substr($cont, 1);
+			if($k>0)$values.=',';
+			$values.='('.$cont.')';
+		}
+		return $this->db->insert($this->table, substr($name, 1),'values '.$values.'', true);
+	}
+	
+	public function getwhere($where='')
+	{
+		return $this->db->getwhere($where);
+	}
+	
+	public function getfields()
+	{
+		return $this->db->getallfields($this->table);
+	}
+	
+	public function delete($where)
+	{
+		return  $this->db->delete($this->table, $where);
+	}
+	
+	public function getlimit($where, $page=1, $fields='*', $order='', $limit=20, $table='')
+	{
+		if($order != '')$order = 'order by '.$order.'';
+		$where  	= $this->getwhere($where);
+		if($table == '')$table = $this->table;
+		$sql 		= "select $fields from $table where $where $order ";
+		$count 		= $this->db->rows($table, $where);
+		if($page <= 0)$page=1;
+		$sql	.= "limit ".($page-1)*$limit.",$limit";
+		$rows	 = $this->db->getall($sql);
+		$maxpage = ceil($count/$limit);
+		return array(
+			'rows'		=> $rows,
+			'count'		=> $count,
+			'maxpage'  	=> $maxpage,
+			'page'		=> $page,
+			'limit'		=> $limit,
+			'prevpage'	=> $page-1,
+			'nextpage'	=> $page+1,
+			'url'		=> ''
+		);
+	}
+	
+	public function isempt($str)
+	{
+		return $this->rock->isempt($str);
+	}
+	
+	public function contain($str, $s1)
+	{
+		return $this->rock->contain($str, $s1);
+	}
+	
+	public function getLastSql()
+	{
+		return $this->db->getLastSql();
+	}
+	
+	public function count($where='1=1')
+	{
+		return $this->rows($where);
+	}
+	
+	public function getXinxi($id,$fields='*')
+	{
+		if(isset($this->tempxinxi[$id]))return $this->tempxinxi[$id];
+		$rs = $this->getone($id,$fields);
+		$this->tempxinxi[$id] = $rs;
+		return $rs;
+	}
+}
+
+class sModel extends Model{}

+ 2320 - 0
include/PHPMailer/class.phpmailer.php

@@ -0,0 +1,2320 @@
+<?php
+/*~ class.phpmailer.php
+.---------------------------------------------------------------------------.
+|  Software: PHPMailer - PHP email class                                    |
+|   Version: 5.1                                                            |
+|   Contact: via sourceforge.net support pages (also www.worxware.com)      |
+|      Info: http://phpmailer.sourceforge.net                               |
+|   Support: http://sourceforge.net/projects/phpmailer/                     |
+| ------------------------------------------------------------------------- |
+|     Admin: Andy Prevost (project admininistrator)                         |
+|   Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net |
+|          : Marcus Bointon (coolbru) coolbru@users.sourceforge.net         |
+|   Founder: Brent R. Matzelle (original founder)                           |
+| Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved.               |
+| Copyright (c) 2001-2003, Brent R. Matzelle                                |
+| ------------------------------------------------------------------------- |
+|   License: Distributed under the Lesser General Public License (LGPL)     |
+|            http://www.gnu.org/copyleft/lesser.html                        |
+| This program is distributed in the hope that it will be useful - WITHOUT  |
+| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |
+| FITNESS FOR A PARTICULAR PURPOSE.                                         |
+| ------------------------------------------------------------------------- |
+| We offer a number of paid services (www.worxware.com):                    |
+| - Web Hosting on highly optimized fast and secure servers                 |
+| - Technology Consulting                                                   |
+| - Oursourcing (highly qualified programmers and graphic designers)        |
+'---------------------------------------------------------------------------'
+*/
+
+/**
+ * PHPMailer - PHP email transport class
+ * NOTE: Requires PHP version 5 or later
+ * @package PHPMailer
+ * @author Andy Prevost
+ * @author Marcus Bointon
+ * @copyright 2004 - 2009 Andy Prevost
+ * @version $Id: class.phpmailer.php 447 2009-05-25 01:36:38Z codeworxtech $
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+if (version_compare(PHP_VERSION, '5.0.0', '<') ) exit("Sorry, this version of PHPMailer will only run on PHP version 5 or greater!\n");
+
+class PHPMailer {
+
+  /////////////////////////////////////////////////
+  // PROPERTIES, PUBLIC
+  /////////////////////////////////////////////////
+
+  /**
+   * Email priority (1 = High, 3 = Normal, 5 = low).
+   * @var int
+   */
+  public $Priority          = 3;
+
+  /**
+   * Sets the CharSet of the message.
+   * @var string
+   */
+  public $CharSet           = 'iso-8859-1';
+
+  /**
+   * Sets the Content-type of the message.
+   * @var string
+   */
+  public $ContentType       = 'text/plain';
+
+  /**
+   * Sets the Encoding of the message. Options for this are
+   *  "8bit", "7bit", "binary", "base64", and "quoted-printable".
+   * @var string
+   */
+  public $Encoding          = '8bit';
+
+  /**
+   * Holds the most recent mailer error message.
+   * @var string
+   */
+  public $ErrorInfo         = '';
+
+  /**
+   * Sets the From email address for the message.
+   * @var string
+   */
+  public $From              = 'root@localhost';
+
+  /**
+   * Sets the From name of the message.
+   * @var string
+   */
+  public $FromName          = 'Root User';
+
+  /**
+   * Sets the Sender email (Return-Path) of the message.  If not empty,
+   * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.
+   * @var string
+   */
+  public $Sender            = '';
+
+  /**
+   * Sets the Subject of the message.
+   * @var string
+   */
+  public $Subject           = '';
+
+  /**
+   * Sets the Body of the message.  This can be either an HTML or text body.
+   * If HTML then run IsHTML(true).
+   * @var string
+   */
+  public $Body              = '';
+
+  /**
+   * Sets the text-only body of the message.  This automatically sets the
+   * email to multipart/alternative.  This body can be read by mail
+   * clients that do not have HTML email capability such as mutt. Clients
+   * that can read HTML will view the normal Body.
+   * @var string
+   */
+  public $AltBody           = '';
+
+  /**
+   * Sets word wrapping on the body of the message to a given number of
+   * characters.
+   * @var int
+   */
+  public $WordWrap          = 0;
+
+  /**
+   * Method to send mail: ("mail", "sendmail", or "smtp").
+   * @var string
+   */
+  public $Mailer            = 'mail';
+
+  /**
+   * Sets the path of the sendmail program.
+   * @var string
+   */
+  public $Sendmail          = '/usr/sbin/sendmail';
+
+  /**
+   * Path to PHPMailer plugins.  Useful if the SMTP class
+   * is in a different directory than the PHP include path.
+   * @var string
+   */
+  public $PluginDir         = '';
+
+  /**
+   * Sets the email address that a reading confirmation will be sent.
+   * @var string
+   */
+  public $ConfirmReadingTo  = '';
+
+  /**
+   * Sets the hostname to use in Message-Id and Received headers
+   * and as default HELO string. If empty, the value returned
+   * by SERVER_NAME is used or 'localhost.localdomain'.
+   * @var string
+   */
+  public $Hostname          = '';
+
+  /**
+   * Sets the message ID to be used in the Message-Id header.
+   * If empty, a unique id will be generated.
+   * @var string
+   */
+  public $MessageID         = '';
+
+  /////////////////////////////////////////////////
+  // PROPERTIES FOR SMTP
+  /////////////////////////////////////////////////
+
+  /**
+   * Sets the SMTP hosts.  All hosts must be separated by a
+   * semicolon.  You can also specify a different port
+   * for each host by using this format: [hostname:port]
+   * (e.g. "smtp1.example.com:25;smtp2.example.com").
+   * Hosts will be tried in order.
+   * @var string
+   */
+  public $Host          = 'localhost';
+
+  /**
+   * Sets the default SMTP server port.
+   * @var int
+   */
+  public $Port          = 25;
+
+  /**
+   * Sets the SMTP HELO of the message (Default is $Hostname).
+   * @var string
+   */
+  public $Helo          = '';
+
+  /**
+   * Sets connection prefix.
+   * Options are "", "ssl" or "tls"
+   * @var string
+   */
+  public $SMTPSecure    = '';
+
+  /**
+   * Sets SMTP authentication. Utilizes the Username and Password variables.
+   * @var bool
+   */
+  public $SMTPAuth      = false;
+
+  /**
+   * Sets SMTP username.
+   * @var string
+   */
+  public $Username      = '';
+
+  /**
+   * Sets SMTP password.
+   * @var string
+   */
+  public $Password      = '';
+
+  /**
+   * Sets the SMTP server timeout in seconds.
+   * This function will not work with the win32 version.
+   * @var int
+   */
+  public $Timeout       = 10;
+
+  /**
+   * Sets SMTP class debugging on or off.
+   * @var bool
+   */
+  public $SMTPDebug     = false;
+
+  /**
+   * Prevents the SMTP connection from being closed after each mail
+   * sending.  If this is set to true then to close the connection
+   * requires an explicit call to SmtpClose().
+   * @var bool
+   */
+  public $SMTPKeepAlive = false;
+
+  /**
+   * Provides the ability to have the TO field process individual
+   * emails, instead of sending to entire TO addresses
+   * @var bool
+   */
+  public $SingleTo      = false;
+
+   /**
+   * If SingleTo is true, this provides the array to hold the email addresses
+   * @var bool
+   */
+  public $SingleToArray = array();
+
+ /**
+   * Provides the ability to change the line ending
+   * @var string
+   */
+  public $LE              = "\n";
+
+  /**
+   * Used with DKIM DNS Resource Record
+   * @var string
+   */
+  public $DKIM_selector   = 'phpmailer';
+
+  /**
+   * Used with DKIM DNS Resource Record
+   * optional, in format of email address 'you@yourdomain.com'
+   * @var string
+   */
+  public $DKIM_identity   = '';
+
+  /**
+   * Used with DKIM DNS Resource Record
+   * optional, in format of email address 'you@yourdomain.com'
+   * @var string
+   */
+  public $DKIM_domain     = '';
+
+  /**
+   * Used with DKIM DNS Resource Record
+   * optional, in format of email address 'you@yourdomain.com'
+   * @var string
+   */
+  public $DKIM_private    = '';
+
+  /**
+   * Callback Action function name
+   * the function that handles the result of the send email action. Parameters:
+   *   bool    $result        result of the send action
+   *   string  $to            email address of the recipient
+   *   string  $cc            cc email addresses
+   *   string  $bcc           bcc email addresses
+   *   string  $subject       the subject
+   *   string  $body          the email body
+   * @var string
+   */
+  public $action_function = ''; //'callbackAction';
+
+  /**
+   * Sets the PHPMailer Version number
+   * @var string
+   */
+  public $Version         = '5.1';
+
+  /////////////////////////////////////////////////
+  // PROPERTIES, PRIVATE AND PROTECTED
+  /////////////////////////////////////////////////
+
+  private   $smtp           = NULL;
+  private   $to             = array();
+  private   $cc             = array();
+  private   $bcc            = array();
+  private   $ReplyTo        = array();
+  private   $all_recipients = array();
+  private   $attachment     = array();
+  private   $CustomHeader   = array();
+  private   $message_type   = '';
+  private   $boundary       = array();
+  protected $language       = array();
+  private   $error_count    = 0;
+  private   $sign_cert_file = "";
+  private   $sign_key_file  = "";
+  private   $sign_key_pass  = "";
+  private   $exceptions     = false;
+
+  /////////////////////////////////////////////////
+  // CONSTANTS
+  /////////////////////////////////////////////////
+
+  const STOP_MESSAGE  = 0; // message only, continue processing
+  const STOP_CONTINUE = 1; // message?, likely ok to continue processing
+  const STOP_CRITICAL = 2; // message, plus full stop, critical error reached
+
+  /////////////////////////////////////////////////
+  // METHODS, VARIABLES
+  /////////////////////////////////////////////////
+
+  /**
+   * Constructor
+   * @param boolean $exceptions Should we throw external exceptions?
+   */
+  public function __construct($exceptions = false) {
+    $this->exceptions = ($exceptions == true);
+  }
+
+  /**
+   * Sets message type to HTML.
+   * @param bool $ishtml
+   * @return void
+   */
+  public function IsHTML($ishtml = true) {
+    if ($ishtml) {
+      $this->ContentType = 'text/html';
+    } else {
+      $this->ContentType = 'text/plain';
+    }
+  }
+
+  /**
+   * Sets Mailer to send message using SMTP.
+   * @return void
+   */
+  public function IsSMTP() {
+    $this->Mailer = 'smtp';
+  }
+
+  /**
+   * Sets Mailer to send message using PHP mail() function.
+   * @return void
+   */
+  public function IsMail() {
+    $this->Mailer = 'mail';
+  }
+
+  /**
+   * Sets Mailer to send message using the $Sendmail program.
+   * @return void
+   */
+  public function IsSendmail() {
+    if (!stristr(ini_get('sendmail_path'), 'sendmail')) {
+      $this->Sendmail = '/var/qmail/bin/sendmail';
+    }
+    $this->Mailer = 'sendmail';
+  }
+
+  /**
+   * Sets Mailer to send message using the qmail MTA.
+   * @return void
+   */
+  public function IsQmail() {
+    if (stristr(ini_get('sendmail_path'), 'qmail')) {
+      $this->Sendmail = '/var/qmail/bin/sendmail';
+    }
+    $this->Mailer = 'sendmail';
+  }
+
+  /////////////////////////////////////////////////
+  // METHODS, RECIPIENTS
+  /////////////////////////////////////////////////
+
+  /**
+   * Adds a "To" address.
+   * @param string $address
+   * @param string $name
+   * @return boolean true on success, false if address already used
+   */
+  public function AddAddress($address, $name = '') {
+    return $this->AddAnAddress('to', $address, $name);
+  }
+
+  /**
+   * Adds a "Cc" address.
+   * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer.
+   * @param string $address
+   * @param string $name
+   * @return boolean true on success, false if address already used
+   */
+  public function AddCC($address, $name = '') {
+    return $this->AddAnAddress('cc', $address, $name);
+  }
+
+  /**
+   * Adds a "Bcc" address.
+   * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer.
+   * @param string $address
+   * @param string $name
+   * @return boolean true on success, false if address already used
+   */
+  public function AddBCC($address, $name = '') {
+    return $this->AddAnAddress('bcc', $address, $name);
+  }
+
+  /**
+   * Adds a "Reply-to" address.
+   * @param string $address
+   * @param string $name
+   * @return boolean
+   */
+  public function AddReplyTo($address, $name = '') {
+    return $this->AddAnAddress('ReplyTo', $address, $name);
+  }
+
+  /**
+   * Adds an address to one of the recipient arrays
+   * Addresses that have been added already return false, but do not throw exceptions
+   * @param string $kind One of 'to', 'cc', 'bcc', 'ReplyTo'
+   * @param string $address The email address to send to
+   * @param string $name
+   * @return boolean true on success, false if address already used or invalid in some way
+   * @access private
+   */
+  private function AddAnAddress($kind, $address, $name = '') {
+    if (!preg_match('/^(to|cc|bcc|ReplyTo)$/', $kind)) {
+      echo 'Invalid recipient array: ' . kind;
+      return false;
+    }
+    $address = trim($address);
+    $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
+    if (!self::ValidateAddress($address)) {
+      $this->SetError($this->Lang('invalid_address').': '. $address);
+      if ($this->exceptions) {
+        throw new phpmailerException($this->Lang('invalid_address').': '.$address);
+      }
+      echo $this->Lang('invalid_address').': '.$address;
+      return false;
+    }
+    if ($kind != 'ReplyTo') {
+      if (!isset($this->all_recipients[strtolower($address)])) {
+        array_push($this->$kind, array($address, $name));
+        $this->all_recipients[strtolower($address)] = true;
+        return true;
+      }
+    } else {
+      if (!array_key_exists(strtolower($address), $this->ReplyTo)) {
+        $this->ReplyTo[strtolower($address)] = array($address, $name);
+      return true;
+    }
+  }
+  return false;
+}
+
+/**
+ * Set the From and FromName properties
+ * @param string $address
+ * @param string $name
+ * @return boolean
+ */
+  public function SetFrom($address, $name = '',$auto=1) {
+    $address = trim($address);
+    $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
+    if (!self::ValidateAddress($address)) {
+      $this->SetError($this->Lang('invalid_address').': '. $address);
+      if ($this->exceptions) {
+        throw new phpmailerException($this->Lang('invalid_address').': '.$address);
+      }
+      echo $this->Lang('invalid_address').': '.$address;
+      return false;
+    }
+    $this->From = $address;
+    $this->FromName = $name;
+    if ($auto) {
+      if (empty($this->ReplyTo)) {
+        $this->AddAnAddress('ReplyTo', $address, $name);
+      }
+      if (empty($this->Sender)) {
+        $this->Sender = $address;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Check that a string looks roughly like an email address should
+   * Static so it can be used without instantiation
+   * Tries to use PHP built-in validator in the filter extension (from PHP 5.2), falls back to a reasonably competent regex validator
+   * Conforms approximately to RFC2822
+   * @link http://www.hexillion.com/samples/#Regex Original pattern found here
+   * @param string $address The email address to check
+   * @return boolean
+   * @static
+   * @access public
+   */
+  public static function ValidateAddress($address) {
+    if (function_exists('filter_var')) { //Introduced in PHP 5.2
+      if(filter_var($address, FILTER_VALIDATE_EMAIL) === FALSE) {
+        return false;
+      } else {
+        return true;
+      }
+    } else {
+      return preg_match('/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!\.)){0,61}[a-zA-Z0-9_-]?\.)+[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!$)){0,61}[a-zA-Z0-9_]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/', $address);
+    }
+  }
+
+  /////////////////////////////////////////////////
+  // METHODS, MAIL SENDING
+  /////////////////////////////////////////////////
+
+  /**
+   * Creates message and assigns Mailer. If the message is
+   * not sent successfully then it returns false.  Use the ErrorInfo
+   * variable to view description of the error.
+   * @return bool
+   */
+  public function Send() {
+    try {
+      if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
+        throw new phpmailerException($this->Lang('provide_address'), self::STOP_CRITICAL);
+      }
+
+      // Set whether the message is multipart/alternative
+      if(!empty($this->AltBody)) {
+        $this->ContentType = 'multipart/alternative';
+      }
+
+      $this->error_count = 0; // reset errors
+      $this->SetMessageType();
+      $header = $this->CreateHeader();
+      $body = $this->CreateBody();
+
+      if (empty($this->Body)) {
+        throw new phpmailerException($this->Lang('empty_message'), self::STOP_CRITICAL);
+      }
+
+      // digitally sign with DKIM if enabled
+      if ($this->DKIM_domain && $this->DKIM_private) {
+        $header_dkim = $this->DKIM_Add($header,$this->Subject,$body);
+        $header = str_replace("\r\n","\n",$header_dkim) . $header;
+      }
+
+      // Choose the mailer and send through it
+      switch($this->Mailer) {
+        case 'sendmail':
+          return $this->SendmailSend($header, $body);
+        case 'smtp':
+          return $this->SmtpSend($header, $body);
+        default:
+          return $this->MailSend($header, $body);
+      }
+
+    } catch (phpmailerException $e) {
+      $this->SetError($e->getMessage());
+      if ($this->exceptions) {
+        throw $e;
+      }
+      echo $e->getMessage()."\n";
+      return false;
+    }
+  }
+
+  /**
+   * Sends mail using the $Sendmail program.
+   * @param string $header The message headers
+   * @param string $body The message body
+   * @access protected
+   * @return bool
+   */
+  protected function SendmailSend($header, $body) {
+    if ($this->Sender != '') {
+      $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
+    } else {
+      $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail));
+    }
+    if ($this->SingleTo === true) {
+      foreach ($this->SingleToArray as $key => $val) {
+        if(!@$mail = popen($sendmail, 'w')) {
+          throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
+        }
+        fputs($mail, "To: " . $val . "\n");
+        fputs($mail, $header);
+        fputs($mail, $body);
+        $result = pclose($mail);
+        // implement call back function if it exists
+        $isSent = ($result == 0) ? 1 : 0;
+        $this->doCallback($isSent,$val,$this->cc,$this->bcc,$this->Subject,$body);
+        if($result != 0) {
+          throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
+        }
+      }
+    } else {
+      if(!@$mail = popen($sendmail, 'w')) {
+        throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
+      }
+      fputs($mail, $header);
+      fputs($mail, $body);
+      $result = pclose($mail);
+      // implement call back function if it exists
+      $isSent = ($result == 0) ? 1 : 0;
+      $this->doCallback($isSent,$this->to,$this->cc,$this->bcc,$this->Subject,$body);
+      if($result != 0) {
+        throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Sends mail using the PHP mail() function.
+   * @param string $header The message headers
+   * @param string $body The message body
+   * @access protected
+   * @return bool
+   */
+  protected function MailSend($header, $body) {
+    $toArr = array();
+    foreach($this->to as $t) {
+      $toArr[] = $this->AddrFormat($t);
+    }
+    $to = implode(', ', $toArr);
+
+    $params = sprintf("-oi -f %s", $this->Sender);
+    if ($this->Sender != '' && strlen(ini_get('safe_mode'))< 1) {
+      $old_from = ini_get('sendmail_from');
+      ini_set('sendmail_from', $this->Sender);
+      if ($this->SingleTo === true && count($toArr) > 1) {
+        foreach ($toArr as $key => $val) {
+          $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
+          // implement call back function if it exists
+          $isSent = ($rt == 1) ? 1 : 0;
+          $this->doCallback($isSent,$val,$this->cc,$this->bcc,$this->Subject,$body);
+        }
+      } else {
+        $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
+        // implement call back function if it exists
+        $isSent = ($rt == 1) ? 1 : 0;
+        $this->doCallback($isSent,$to,$this->cc,$this->bcc,$this->Subject,$body);
+      }
+    } else {
+      if ($this->SingleTo === true && count($toArr) > 1) {
+        foreach ($toArr as $key => $val) {
+          $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
+          // implement call back function if it exists
+          $isSent = ($rt == 1) ? 1 : 0;
+          $this->doCallback($isSent,$val,$this->cc,$this->bcc,$this->Subject,$body);
+        }
+      } else {
+        $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header);
+        // implement call back function if it exists
+        $isSent = ($rt == 1) ? 1 : 0;
+        $this->doCallback($isSent,$to,$this->cc,$this->bcc,$this->Subject,$body);
+      }
+    }
+    if (isset($old_from)) {
+      ini_set('sendmail_from', $old_from);
+    }
+    if(!$rt) {
+      throw new phpmailerException($this->Lang('instantiate'), self::STOP_CRITICAL);
+    }
+    return true;
+  }
+
+  /**
+   * Sends mail via SMTP using PhpSMTP
+   * Returns false if there is a bad MAIL FROM, RCPT, or DATA input.
+   * @param string $header The message headers
+   * @param string $body The message body
+   * @uses SMTP
+   * @access protected
+   * @return bool
+   */
+  protected function SmtpSend($header, $body) {
+    require_once $this->PluginDir . 'class.smtp.php';
+    $bad_rcpt = array();
+
+    if(!$this->SmtpConnect()) {
+      throw new phpmailerException($this->Lang('smtp_connect_failed'), self::STOP_CRITICAL);
+    }
+    $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender;
+    if(!$this->smtp->Mail($smtp_from)) {
+      throw new phpmailerException($this->Lang('from_failed') . $smtp_from, self::STOP_CRITICAL);
+    }
+
+    // Attempt to send attach all recipients
+    foreach($this->to as $to) {
+      if (!$this->smtp->Recipient($to[0])) {
+        $bad_rcpt[] = $to[0];
+        // implement call back function if it exists
+        $isSent = 0;
+        $this->doCallback($isSent,$to[0],'','',$this->Subject,$body);
+      } else {
+        // implement call back function if it exists
+        $isSent = 1;
+        $this->doCallback($isSent,$to[0],'','',$this->Subject,$body);
+      }
+    }
+    foreach($this->cc as $cc) {
+      if (!$this->smtp->Recipient($cc[0])) {
+        $bad_rcpt[] = $cc[0];
+        // implement call back function if it exists
+        $isSent = 0;
+        $this->doCallback($isSent,'',$cc[0],'',$this->Subject,$body);
+      } else {
+        // implement call back function if it exists
+        $isSent = 1;
+        $this->doCallback($isSent,'',$cc[0],'',$this->Subject,$body);
+      }
+    }
+    foreach($this->bcc as $bcc) {
+      if (!$this->smtp->Recipient($bcc[0])) {
+        $bad_rcpt[] = $bcc[0];
+        // implement call back function if it exists
+        $isSent = 0;
+        $this->doCallback($isSent,'','',$bcc[0],$this->Subject,$body);
+      } else {
+        // implement call back function if it exists
+        $isSent = 1;
+        $this->doCallback($isSent,'','',$bcc[0],$this->Subject,$body);
+      }
+    }
+
+
+    if (count($bad_rcpt) > 0 ) { //Create error message for any bad addresses
+      $badaddresses = implode(', ', $bad_rcpt);
+      throw new phpmailerException($this->Lang('recipients_failed') . $badaddresses);
+    }
+    if(!$this->smtp->Data($header . $body)) {
+      throw new phpmailerException($this->Lang('data_not_accepted'), self::STOP_CRITICAL);
+    }
+    if($this->SMTPKeepAlive == true) {
+      $this->smtp->Reset();
+    }
+    return true;
+  }
+
+  /**
+   * Initiates a connection to an SMTP server.
+   * Returns false if the operation failed.
+   * @uses SMTP
+   * @access public
+   * @return bool
+   */
+  public function SmtpConnect() {
+    if(is_null($this->smtp)) {
+      $this->smtp = new SMTP();
+    }
+
+    $this->smtp->do_debug = $this->SMTPDebug;
+    $hosts = explode(';', $this->Host);
+    $index = 0;
+    $connection = $this->smtp->Connected();
+
+    // Retry while there is no connection
+    try {
+      while($index < count($hosts) && !$connection) {
+        $hostinfo = array();
+        if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) {
+          $host = $hostinfo[1];
+          $port = $hostinfo[2];
+        } else {
+          $host = $hosts[$index];
+          $port = $this->Port;
+        }
+
+        $tls = ($this->SMTPSecure == 'tls');
+        $ssl = ($this->SMTPSecure == 'ssl');
+
+        if ($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout)) {
+
+          $hello = ($this->Helo != '' ? $this->Helo : $this->ServerHostname());
+          $this->smtp->Hello($hello);
+
+          if ($tls) {
+            if (!$this->smtp->StartTLS()) {
+              throw new phpmailerException($this->Lang('tls'));
+            }
+
+            //We must resend HELO after tls negotiation
+            $this->smtp->Hello($hello);
+          }
+
+          $connection = true;
+          if ($this->SMTPAuth) {
+            if (!$this->smtp->Authenticate($this->Username, $this->Password)) {
+              throw new phpmailerException($this->Lang('authenticate'));
+            }
+          }
+        }
+        $index++;
+        if (!$connection) {
+          throw new phpmailerException($this->Lang('connect_host'));
+        }
+      }
+    } catch (phpmailerException $e) {
+      $this->smtp->Reset();
+      throw $e;
+    }
+    return true;
+  }
+
+  /**
+   * Closes the active SMTP session if one exists.
+   * @return void
+   */
+  public function SmtpClose() {
+    if(!is_null($this->smtp)) {
+      if($this->smtp->Connected()) {
+        $this->smtp->Quit();
+        $this->smtp->Close();
+      }
+    }
+  }
+
+  /**
+  * Sets the language for all class error messages.
+  * Returns false if it cannot load the language file.  The default language is English.
+  * @param string $langcode ISO 639-1 2-character language code (e.g. Portuguese: "br")
+  * @param string $lang_path Path to the language file directory
+  * @access public
+  */
+  function SetLanguage($langcode = 'en', $lang_path = 'language/') {
+    //Define full set of translatable strings
+    $PHPMAILER_LANG = array(
+      'provide_address' => 'You must provide at least one recipient email address.',
+      'mailer_not_supported' => ' mailer is not supported.',
+      'execute' => 'Could not execute: ',
+      'instantiate' => 'Could not instantiate mail function.',
+      'authenticate' => 'SMTP Error: Could not authenticate.',
+      'from_failed' => 'The following From address failed: ',
+      'recipients_failed' => 'SMTP Error: The following recipients failed: ',
+      'data_not_accepted' => 'SMTP Error: Data not accepted.',
+      'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
+      'file_access' => 'Could not access file: ',
+      'file_open' => 'File Error: Could not open file: ',
+      'encoding' => 'Unknown encoding: ',
+      'signing' => 'Signing Error: ',
+      'smtp_error' => 'SMTP server error: ',
+      'empty_message' => 'Message body empty',
+      'invalid_address' => 'Invalid address',
+      'variable_set' => 'Cannot set or reset variable: '
+    );
+    //Overwrite language-specific strings. This way we'll never have missing translations - no more "language string failed to load"!
+    $l = true;
+    if ($langcode != 'en') { //There is no English translation file
+      $l = @include $lang_path.'phpmailer.lang-'.$langcode.'.php';
+    }
+    $this->language = $PHPMAILER_LANG;
+    return ($l == true); //Returns false if language not found
+  }
+
+  /**
+  * Return the current array of language strings
+  * @return array
+  */
+  public function GetTranslations() {
+    return $this->language;
+  }
+
+  /////////////////////////////////////////////////
+  // METHODS, MESSAGE CREATION
+  /////////////////////////////////////////////////
+
+  /**
+   * Creates recipient headers.
+   * @access public
+   * @return string
+   */
+  public function AddrAppend($type, $addr) {
+    $addr_str = $type . ': ';
+    $addresses = array();
+    foreach ($addr as $a) {
+      $addresses[] = $this->AddrFormat($a);
+    }
+    $addr_str .= implode(', ', $addresses);
+    $addr_str .= $this->LE;
+
+    return $addr_str;
+  }
+
+  /**
+   * Formats an address correctly.
+   * @access public
+   * @return string
+   */
+  public function AddrFormat($addr) {
+    if (empty($addr[1])) {
+      return $this->SecureHeader($addr[0]);
+    } else {
+      return $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">";
+    }
+  }
+
+  /**
+   * Wraps message for use with mailers that do not
+   * automatically perform wrapping and for quoted-printable.
+   * Original written by philippe.
+   * @param string $message The message to wrap
+   * @param integer $length The line length to wrap to
+   * @param boolean $qp_mode Whether to run in Quoted-Printable mode
+   * @access public
+   * @return string
+   */
+  public function WrapText($message, $length, $qp_mode = false) {
+    $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE;
+    // If utf-8 encoding is used, we will need to make sure we don't
+    // split multibyte characters when we wrap
+    $is_utf8 = (strtolower($this->CharSet) == "utf-8");
+
+    $message = $this->FixEOL($message);
+    if (substr($message, -1) == $this->LE) {
+      $message = substr($message, 0, -1);
+    }
+
+    $line = explode($this->LE, $message);
+    $message = '';
+    for ($i=0 ;$i < count($line); $i++) {
+      $line_part = explode(' ', $line[$i]);
+      $buf = '';
+      for ($e = 0; $e<count($line_part); $e++) {
+        $word = $line_part[$e];
+        if ($qp_mode and (strlen($word) > $length)) {
+          $space_left = $length - strlen($buf) - 1;
+          if ($e != 0) {
+            if ($space_left > 20) {
+              $len = $space_left;
+              if ($is_utf8) {
+                $len = $this->UTF8CharBoundary($word, $len);
+              } elseif (substr($word, $len - 1, 1) == "=") {
+                $len--;
+              } elseif (substr($word, $len - 2, 1) == "=") {
+                $len -= 2;
+              }
+              $part = substr($word, 0, $len);
+              $word = substr($word, $len);
+              $buf .= ' ' . $part;
+              $message .= $buf . sprintf("=%s", $this->LE);
+            } else {
+              $message .= $buf . $soft_break;
+            }
+            $buf = '';
+          }
+          while (strlen($word) > 0) {
+            $len = $length;
+            if ($is_utf8) {
+              $len = $this->UTF8CharBoundary($word, $len);
+            } elseif (substr($word, $len - 1, 1) == "=") {
+              $len--;
+            } elseif (substr($word, $len - 2, 1) == "=") {
+              $len -= 2;
+            }
+            $part = substr($word, 0, $len);
+            $word = substr($word, $len);
+
+            if (strlen($word) > 0) {
+              $message .= $part . sprintf("=%s", $this->LE);
+            } else {
+              $buf = $part;
+            }
+          }
+        } else {
+          $buf_o = $buf;
+          $buf .= ($e == 0) ? $word : (' ' . $word);
+
+          if (strlen($buf) > $length and $buf_o != '') {
+            $message .= $buf_o . $soft_break;
+            $buf = $word;
+          }
+        }
+      }
+      $message .= $buf . $this->LE;
+    }
+
+    return $message;
+  }
+
+  /**
+   * Finds last character boundary prior to maxLength in a utf-8
+   * quoted (printable) encoded string.
+   * Original written by Colin Brown.
+   * @access public
+   * @param string $encodedText utf-8 QP text
+   * @param int    $maxLength   find last character boundary prior to this length
+   * @return int
+   */
+  public function UTF8CharBoundary($encodedText, $maxLength) {
+    $foundSplitPos = false;
+    $lookBack = 3;
+    while (!$foundSplitPos) {
+      $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
+      $encodedCharPos = strpos($lastChunk, "=");
+      if ($encodedCharPos !== false) {
+        // Found start of encoded character byte within $lookBack block.
+        // Check the encoded byte value (the 2 chars after the '=')
+        $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);
+        $dec = hexdec($hex);
+        if ($dec < 128) { // Single byte character.
+          // If the encoded char was found at pos 0, it will fit
+          // otherwise reduce maxLength to start of the encoded char
+          $maxLength = ($encodedCharPos == 0) ? $maxLength :
+          $maxLength - ($lookBack - $encodedCharPos);
+          $foundSplitPos = true;
+        } elseif ($dec >= 192) { // First byte of a multi byte character
+          // Reduce maxLength to split at start of character
+          $maxLength = $maxLength - ($lookBack - $encodedCharPos);
+          $foundSplitPos = true;
+        } elseif ($dec < 192) { // Middle byte of a multi byte character, look further back
+          $lookBack += 3;
+        }
+      } else {
+        // No encoded character found
+        $foundSplitPos = true;
+      }
+    }
+    return $maxLength;
+  }
+
+
+  /**
+   * Set the body wrapping.
+   * @access public
+   * @return void
+   */
+  public function SetWordWrap() {
+    if($this->WordWrap < 1) {
+      return;
+    }
+
+    switch($this->message_type) {
+      case 'alt':
+      case 'alt_attachments':
+        $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap);
+        break;
+      default:
+        $this->Body = $this->WrapText($this->Body, $this->WordWrap);
+        break;
+    }
+  }
+
+  /**
+   * Assembles message header.
+   * @access public
+   * @return string The assembled header
+   */
+  public function CreateHeader() {
+    $result = '';
+
+    // Set the boundaries
+    $uniq_id = md5(uniqid(time()));
+    $this->boundary[1] = 'b1_' . $uniq_id;
+    $this->boundary[2] = 'b2_' . $uniq_id;
+
+    $result .= $this->HeaderLine('Date', self::RFCDate());
+    if($this->Sender == '') {
+      $result .= $this->HeaderLine('Return-Path', trim($this->From));
+    } else {
+      $result .= $this->HeaderLine('Return-Path', trim($this->Sender));
+    }
+
+    // To be created automatically by mail()
+    if($this->Mailer != 'mail') {
+      if ($this->SingleTo === true) {
+        foreach($this->to as $t) {
+          $this->SingleToArray[] = $this->AddrFormat($t);
+        }
+      } else {
+        if(count($this->to) > 0) {
+          $result .= $this->AddrAppend('To', $this->to);
+        } elseif (count($this->cc) == 0) {
+          $result .= $this->HeaderLine('To', 'undisclosed-recipients:;');
+        }
+      }
+    }
+
+    $from = array();
+    $from[0][0] = trim($this->From);
+    $from[0][1] = $this->FromName;
+    $result .= $this->AddrAppend('From', $from);
+
+    // sendmail and mail() extract Cc from the header before sending
+    if(count($this->cc) > 0) {
+      $result .= $this->AddrAppend('Cc', $this->cc);
+    }
+
+    // sendmail and mail() extract Bcc from the header before sending
+    if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) {
+      $result .= $this->AddrAppend('Bcc', $this->bcc);
+    }
+
+    if(count($this->ReplyTo) > 0) {
+      $result .= $this->AddrAppend('Reply-to', $this->ReplyTo);
+    }
+
+    // mail() sets the subject itself
+    if($this->Mailer != 'mail') {
+      $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject)));
+    }
+
+    if($this->MessageID != '') {
+      $result .= $this->HeaderLine('Message-ID',$this->MessageID);
+    } else {
+      $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE);
+    }
+    $result .= $this->HeaderLine('X-Priority', $this->Priority);
+    $result .= $this->HeaderLine('X-Mailer', 'PHPMailer '.$this->Version.' (phpmailer.sourceforge.net)');
+
+    if($this->ConfirmReadingTo != '') {
+      $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>');
+    }
+
+    // Add custom headers
+    for($index = 0; $index < count($this->CustomHeader); $index++) {
+      $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), $this->EncodeHeader(trim($this->CustomHeader[$index][1])));
+    }
+    if (!$this->sign_key_file) {
+      $result .= $this->HeaderLine('MIME-Version', '1.0');
+      $result .= $this->GetMailMIME();
+    }
+
+    return $result;
+  }
+
+  /**
+   * Returns the message MIME.
+   * @access public
+   * @return string
+   */
+  public function GetMailMIME() {
+    $result = '';
+    switch($this->message_type) {
+      case 'plain':
+        $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding);
+        $result .= sprintf("Content-Type: %s; charset=\"%s\"", $this->ContentType, $this->CharSet);
+        break;
+      case 'attachments':
+      case 'alt_attachments':
+        if($this->InlineImageExists()){
+          $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", 'multipart/related', $this->LE, $this->LE, $this->boundary[1], $this->LE);
+        } else {
+          $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;');
+          $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
+        }
+        break;
+      case 'alt':
+        $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
+        $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
+        break;
+    }
+
+    if($this->Mailer != 'mail') {
+      $result .= $this->LE.$this->LE;
+    }
+
+    return $result;
+  }
+
+  /**
+   * Assembles the message body.  Returns an empty string on failure.
+   * @access public
+   * @return string The assembled message body
+   */
+  public function CreateBody() {
+    $body = '';
+
+    if ($this->sign_key_file) {
+      $body .= $this->GetMailMIME();
+    }
+
+    $this->SetWordWrap();
+
+    switch($this->message_type) {
+      case 'alt':
+        $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
+        $body .= $this->EncodeString($this->AltBody, $this->Encoding);
+        $body .= $this->LE.$this->LE;
+        $body .= $this->GetBoundary($this->boundary[1], '', 'text/html', '');
+        $body .= $this->EncodeString($this->Body, $this->Encoding);
+        $body .= $this->LE.$this->LE;
+        $body .= $this->EndBoundary($this->boundary[1]);
+        break;
+      case 'plain':
+        $body .= $this->EncodeString($this->Body, $this->Encoding);
+        break;
+      case 'attachments':
+        $body .= $this->GetBoundary($this->boundary[1], '', '', '');
+        $body .= $this->EncodeString($this->Body, $this->Encoding);
+        $body .= $this->LE;
+        $body .= $this->AttachAll();
+        break;
+      case 'alt_attachments':
+        $body .= sprintf("--%s%s", $this->boundary[1], $this->LE);
+        $body .= sprintf("Content-Type: %s;%s" . "\tboundary=\"%s\"%s", 'multipart/alternative', $this->LE, $this->boundary[2], $this->LE.$this->LE);
+        $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '') . $this->LE; // Create text body
+        $body .= $this->EncodeString($this->AltBody, $this->Encoding);
+        $body .= $this->LE.$this->LE;
+        $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '') . $this->LE; // Create the HTML body
+        $body .= $this->EncodeString($this->Body, $this->Encoding);
+        $body .= $this->LE.$this->LE;
+        $body .= $this->EndBoundary($this->boundary[2]);
+        $body .= $this->AttachAll();
+        break;
+    }
+
+    if ($this->IsError()) {
+      $body = '';
+    } elseif ($this->sign_key_file) {
+      try {
+        $file = tempnam('', 'mail');
+        file_put_contents($file, $body); //TODO check this worked
+        $signed = tempnam("", "signed");
+        if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), NULL)) {
+          @unlink($file);
+          @unlink($signed);
+          $body = file_get_contents($signed);
+        } else {
+          @unlink($file);
+          @unlink($signed);
+          throw new phpmailerException($this->Lang("signing").openssl_error_string());
+        }
+      } catch (phpmailerException $e) {
+        $body = '';
+        if ($this->exceptions) {
+          throw $e;
+        }
+      }
+    }
+
+    return $body;
+  }
+
+  /**
+   * Returns the start of a message boundary.
+   * @access private
+   */
+  private function GetBoundary($boundary, $charSet, $contentType, $encoding) {
+    $result = '';
+    if($charSet == '') {
+      $charSet = $this->CharSet;
+    }
+    if($contentType == '') {
+      $contentType = $this->ContentType;
+    }
+    if($encoding == '') {
+      $encoding = $this->Encoding;
+    }
+    $result .= $this->TextLine('--' . $boundary);
+    $result .= sprintf("Content-Type: %s; charset = \"%s\"", $contentType, $charSet);
+    $result .= $this->LE;
+    $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding);
+    $result .= $this->LE;
+
+    return $result;
+  }
+
+  /**
+   * Returns the end of a message boundary.
+   * @access private
+   */
+  private function EndBoundary($boundary) {
+    return $this->LE . '--' . $boundary . '--' . $this->LE;
+  }
+
+  /**
+   * Sets the message type.
+   * @access private
+   * @return void
+   */
+  private function SetMessageType() {
+    if(count($this->attachment) < 1 && strlen($this->AltBody) < 1) {
+      $this->message_type = 'plain';
+    } else {
+      if(count($this->attachment) > 0) {
+        $this->message_type = 'attachments';
+      }
+      if(strlen($this->AltBody) > 0 && count($this->attachment) < 1) {
+        $this->message_type = 'alt';
+      }
+      if(strlen($this->AltBody) > 0 && count($this->attachment) > 0) {
+        $this->message_type = 'alt_attachments';
+      }
+    }
+  }
+
+  /**
+   *  Returns a formatted header line.
+   * @access public
+   * @return string
+   */
+  public function HeaderLine($name, $value) {
+    return $name . ': ' . $value . $this->LE;
+  }
+
+  /**
+   * Returns a formatted mail line.
+   * @access public
+   * @return string
+   */
+  public function TextLine($value) {
+    return $value . $this->LE;
+  }
+
+  /////////////////////////////////////////////////
+  // CLASS METHODS, ATTACHMENTS
+  /////////////////////////////////////////////////
+
+  /**
+   * Adds an attachment from a path on the filesystem.
+   * Returns false if the file could not be found
+   * or accessed.
+   * @param string $path Path to the attachment.
+   * @param string $name Overrides the attachment name.
+   * @param string $encoding File encoding (see $Encoding).
+   * @param string $type File extension (MIME) type.
+   * @return bool
+   */
+  public function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
+    try {
+      if ( !@is_file($path) ) {
+        throw new phpmailerException($this->Lang('file_access') . $path, self::STOP_CONTINUE);
+      }
+      $filename = basename($path);
+      if ( $name == '' ) {
+        $name = $filename;
+      }
+
+      $this->attachment[] = array(
+        0 => $path,
+        1 => $filename,
+        2 => $name,
+        3 => $encoding,
+        4 => $type,
+        5 => false,  // isStringAttachment
+        6 => 'attachment',
+        7 => 0
+      );
+
+    } catch (phpmailerException $e) {
+      $this->SetError($e->getMessage());
+      if ($this->exceptions) {
+        throw $e;
+      }
+      echo $e->getMessage()."\n";
+      if ( $e->getCode() == self::STOP_CRITICAL ) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+  * Return the current array of attachments
+  * @return array
+  */
+  public function GetAttachments() {
+    return $this->attachment;
+  }
+
+  /**
+   * Attaches all fs, string, and binary attachments to the message.
+   * Returns an empty string on failure.
+   * @access private
+   * @return string
+   */
+  private function AttachAll() {
+    // Return text of body
+    $mime = array();
+    $cidUniq = array();
+    $incl = array();
+
+    // Add all attachments
+    foreach ($this->attachment as $attachment) {
+      // Check for string attachment
+      $bString = $attachment[5];
+      if ($bString) {
+        $string = $attachment[0];
+      } else {
+        $path = $attachment[0];
+      }
+
+      if (in_array($attachment[0], $incl)) { continue; }
+      $filename    = $attachment[1];
+      $name        = $attachment[2];
+      $encoding    = $attachment[3];
+      $type        = $attachment[4];
+      $disposition = $attachment[6];
+      $cid         = $attachment[7];
+      $incl[]      = $attachment[0];
+      if ( $disposition == 'inline' && isset($cidUniq[$cid]) ) { continue; }
+      $cidUniq[$cid] = true;
+
+      $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE);
+      $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $this->EncodeHeader($this->SecureHeader($name)), $this->LE);
+      $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE);
+
+      if($disposition == 'inline') {
+        $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE);
+      }
+
+      $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE);
+
+      // Encode as string attachment
+      if($bString) {
+        $mime[] = $this->EncodeString($string, $encoding);
+        if($this->IsError()) {
+          return '';
+        }
+        $mime[] = $this->LE.$this->LE;
+      } else {
+        $mime[] = $this->EncodeFile($path, $encoding);
+        if($this->IsError()) {
+          return '';
+        }
+        $mime[] = $this->LE.$this->LE;
+      }
+    }
+
+    $mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE);
+
+    return join('', $mime);
+  }
+
+  /**
+   * Encodes attachment in requested format.
+   * Returns an empty string on failure.
+   * @param string $path The full path to the file
+   * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
+   * @see EncodeFile()
+   * @access private
+   * @return string
+   */
+  private function EncodeFile($path, $encoding = 'base64') {
+    try {
+      if (!is_readable($path)) {
+        throw new phpmailerException($this->Lang('file_open') . $path, self::STOP_CONTINUE);
+      }
+      if (function_exists('get_magic_quotes')) {
+        function get_magic_quotes() {
+          return false;
+        }
+      }
+      if (PHP_VERSION < 6) {
+        $magic_quotes = get_magic_quotes_runtime();
+        @set_magic_quotes_runtime(0);
+      }
+      $file_buffer  = file_get_contents($path);
+      $file_buffer  = $this->EncodeString($file_buffer, $encoding);
+      if (PHP_VERSION < 6) { @set_magic_quotes_runtime($magic_quotes); }
+      return $file_buffer;
+    } catch (Exception $e) {
+      $this->SetError($e->getMessage());
+      return '';
+    }
+  }
+
+  /**
+   * Encodes string to requested format.
+   * Returns an empty string on failure.
+   * @param string $str The text to encode
+   * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
+   * @access public
+   * @return string
+   */
+  public function EncodeString ($str, $encoding = 'base64') {
+    $encoded = '';
+    switch(strtolower($encoding)) {
+      case 'base64':
+        $encoded = chunk_split(base64_encode($str), 76, $this->LE);
+        break;
+      case '7bit':
+      case '8bit':
+        $encoded = $this->FixEOL($str);
+        //Make sure it ends with a line break
+        if (substr($encoded, -(strlen($this->LE))) != $this->LE)
+          $encoded .= $this->LE;
+        break;
+      case 'binary':
+        $encoded = $str;
+        break;
+      case 'quoted-printable':
+        $encoded = $this->EncodeQP($str);
+        break;
+      default:
+        $this->SetError($this->Lang('encoding') . $encoding);
+        break;
+    }
+    return $encoded;
+  }
+
+  /**
+   * Encode a header string to best (shortest) of Q, B, quoted or none.
+   * @access public
+   * @return string
+   */
+  public function EncodeHeader($str, $position = 'text') {
+    $x = 0;
+
+    switch (strtolower($position)) {
+      case 'phrase':
+        if (!preg_match('/[\200-\377]/', $str)) {
+          // Can't use addslashes as we don't know what value has magic_quotes_sybase
+          $encoded = addcslashes($str, "\0..\37\177\\\"");
+          if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
+            return ($encoded);
+          } else {
+            return ("\"$encoded\"");
+          }
+        }
+        $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
+        break;
+      case 'comment':
+        $x = preg_match_all('/[()"]/', $str, $matches);
+        // Fall-through
+      case 'text':
+      default:
+        $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
+        break;
+    }
+
+    if ($x == 0) {
+      return ($str);
+    }
+
+    $maxlen = 75 - 7 - strlen($this->CharSet);
+    // Try to select the encoding which should produce the shortest output
+    if (strlen($str)/3 < $x) {
+      $encoding = 'B';
+      if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) {
+        // Use a custom function which correctly encodes and wraps long
+        // multibyte strings without breaking lines within a character
+        $encoded = $this->Base64EncodeWrapMB($str);
+      } else {
+        $encoded = base64_encode($str);
+        $maxlen -= $maxlen % 4;
+        $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
+      }
+    } else {
+      $encoding = 'Q';
+      $encoded = $this->EncodeQ($str, $position);
+      $encoded = $this->WrapText($encoded, $maxlen, true);
+      $encoded = str_replace('='.$this->LE, "\n", trim($encoded));
+    }
+
+    $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded);
+    $encoded = trim(str_replace("\n", $this->LE, $encoded));
+
+    return $encoded;
+  }
+
+  /**
+   * Checks if a string contains multibyte characters.
+   * @access public
+   * @param string $str multi-byte text to wrap encode
+   * @return bool
+   */
+  public function HasMultiBytes($str) {
+    if (function_exists('mb_strlen')) {
+      return (strlen($str) > mb_strlen($str, $this->CharSet));
+    } else { // Assume no multibytes (we can't handle without mbstring functions anyway)
+      return false;
+    }
+  }
+
+  /**
+   * Correctly encodes and wraps long multibyte strings for mail headers
+   * without breaking lines within a character.
+   * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php
+   * @access public
+   * @param string $str multi-byte text to wrap encode
+   * @return string
+   */
+  public function Base64EncodeWrapMB($str) {
+    $start = "=?".$this->CharSet."?B?";
+    $end = "?=";
+    $encoded = "";
+
+    $mb_length = mb_strlen($str, $this->CharSet);
+    // Each line must have length <= 75, including $start and $end
+    $length = 75 - strlen($start) - strlen($end);
+    // Average multi-byte ratio
+    $ratio = $mb_length / strlen($str);
+    // Base64 has a 4:3 ratio
+    $offset = $avgLength = floor($length * $ratio * .75);
+
+    for ($i = 0; $i < $mb_length; $i += $offset) {
+      $lookBack = 0;
+
+      do {
+        $offset = $avgLength - $lookBack;
+        $chunk = mb_substr($str, $i, $offset, $this->CharSet);
+        $chunk = base64_encode($chunk);
+        $lookBack++;
+      }
+      while (strlen($chunk) > $length);
+
+      $encoded .= $chunk . $this->LE;
+    }
+
+    // Chomp the last linefeed
+    $encoded = substr($encoded, 0, -strlen($this->LE));
+    return $encoded;
+  }
+
+  /**
+  * Encode string to quoted-printable.
+  * Only uses standard PHP, slow, but will always work
+  * @access public
+  * @param string $string the text to encode
+  * @param integer $line_max Number of chars allowed on a line before wrapping
+  * @return string
+  */
+  public function EncodeQPphp( $input = '', $line_max = 76, $space_conv = false) {
+    $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
+    $lines = preg_split('/(?:\r\n|\r|\n)/', $input);
+    $eol = "\r\n";
+    $escape = '=';
+    $output = '';
+    while( list(, $line) = each($lines) ) {
+      $linlen = strlen($line);
+      $newline = '';
+      for($i = 0; $i < $linlen; $i++) {
+        $c = substr( $line, $i, 1 );
+        $dec = ord( $c );
+        if ( ( $i == 0 ) && ( $dec == 46 ) ) { // convert first point in the line into =2E
+          $c = '=2E';
+        }
+        if ( $dec == 32 ) {
+          if ( $i == ( $linlen - 1 ) ) { // convert space at eol only
+            $c = '=20';
+          } else if ( $space_conv ) {
+            $c = '=20';
+          }
+        } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required
+          $h2 = floor($dec/16);
+          $h1 = floor($dec%16);
+          $c = $escape.$hex[$h2].$hex[$h1];
+        }
+        if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted
+          $output .= $newline.$escape.$eol; //  soft line break; " =\r\n" is okay
+          $newline = '';
+          // check if newline first character will be point or not
+          if ( $dec == 46 ) {
+            $c = '=2E';
+          }
+        }
+        $newline .= $c;
+      } // end of for
+      $output .= $newline.$eol;
+    } // end of while
+    return $output;
+  }
+
+  /**
+  * Encode string to RFC2045 (6.7) quoted-printable format
+  * Uses a PHP5 stream filter to do the encoding about 64x faster than the old version
+  * Also results in same content as you started with after decoding
+  * @see EncodeQPphp()
+  * @access public
+  * @param string $string the text to encode
+  * @param integer $line_max Number of chars allowed on a line before wrapping
+  * @param boolean $space_conv Dummy param for compatibility with existing EncodeQP function
+  * @return string
+  * @author Marcus Bointon
+  */
+  public function EncodeQP($string, $line_max = 76, $space_conv = false) {
+    if (function_exists('quoted_printable_encode')) { //Use native function if it's available (>= PHP5.3)
+      return quoted_printable_encode($string);
+    }
+    $filters = stream_get_filters();
+    if (!in_array('convert.*', $filters)) { //Got convert stream filter?
+      return $this->EncodeQPphp($string, $line_max, $space_conv); //Fall back to old implementation
+    }
+    $fp = fopen('php://temp/', 'r+');
+    $string = preg_replace('/\r\n?/', $this->LE, $string); //Normalise line breaks
+    $params = array('line-length' => $line_max, 'line-break-chars' => $this->LE);
+    $s = stream_filter_append($fp, 'convert.quoted-printable-encode', STREAM_FILTER_READ, $params);
+    fputs($fp, $string);
+    rewind($fp);
+    $out = stream_get_contents($fp);
+    stream_filter_remove($s);
+    $out = preg_replace('/^\./m', '=2E', $out); //Encode . if it is first char on a line, workaround for bug in Exchange
+    fclose($fp);
+    return $out;
+  }
+
+  /**
+   * Encode string to q encoding.
+   * @link http://tools.ietf.org/html/rfc2047
+   * @param string $str the text to encode
+   * @param string $position Where the text is going to be used, see the RFC for what that means
+   * @access public
+   * @return string
+   */
+  public function EncodeQ ($str, $position = 'text') {
+    // There should not be any EOL in the string
+    $encoded = preg_replace('/[\r\n]*/', '', $str);
+
+    switch (strtolower($position)) {
+      case 'phrase':
+        $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
+        break;
+      case 'comment':
+        $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
+      case 'text':
+      default:
+        // Replace every high ascii, control =, ? and _ characters
+        //TODO using /e (equivalent to eval()) is probably not a good idea
+        $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e',
+              "'='.sprintf('%02X', ord('\\1'))", $encoded);
+        break;
+    }
+
+    // Replace every spaces to _ (more readable than =20)
+    $encoded = str_replace(' ', '_', $encoded);
+
+    return $encoded;
+  }
+
+  /**
+   * Adds a string or binary attachment (non-filesystem) to the list.
+   * This method can be used to attach ascii or binary data,
+   * such as a BLOB record from a database.
+   * @param string $string String attachment data.
+   * @param string $filename Name of the attachment.
+   * @param string $encoding File encoding (see $Encoding).
+   * @param string $type File extension (MIME) type.
+   * @return void
+   */
+  public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') {
+    // Append to $attachment array
+    $this->attachment[] = array(
+      0 => $string,
+      1 => $filename,
+      2 => basename($filename),
+      3 => $encoding,
+      4 => $type,
+      5 => true,  // isStringAttachment
+      6 => 'attachment',
+      7 => 0
+    );
+  }
+
+  /**
+   * Adds an embedded attachment.  This can include images, sounds, and
+   * just about any other document.  Make sure to set the $type to an
+   * image type.  For JPEG images use "image/jpeg" and for GIF images
+   * use "image/gif".
+   * @param string $path Path to the attachment.
+   * @param string $cid Content ID of the attachment.  Use this to identify
+   *        the Id for accessing the image in an HTML form.
+   * @param string $name Overrides the attachment name.
+   * @param string $encoding File encoding (see $Encoding).
+   * @param string $type File extension (MIME) type.
+   * @return bool
+   */
+  public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
+
+    if ( !@is_file($path) ) {
+      $this->SetError($this->Lang('file_access') . $path);
+      return false;
+    }
+
+    $filename = basename($path);
+    if ( $name == '' ) {
+      $name = $filename;
+    }
+
+    // Append to $attachment array
+    $this->attachment[] = array(
+      0 => $path,
+      1 => $filename,
+      2 => $name,
+      3 => $encoding,
+      4 => $type,
+      5 => false,  // isStringAttachment
+      6 => 'inline',
+      7 => $cid
+    );
+
+    return true;
+  }
+
+  /**
+   * Returns true if an inline attachment is present.
+   * @access public
+   * @return bool
+   */
+  public function InlineImageExists() {
+    foreach($this->attachment as $attachment) {
+      if ($attachment[6] == 'inline') {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /////////////////////////////////////////////////
+  // CLASS METHODS, MESSAGE RESET
+  /////////////////////////////////////////////////
+
+  /**
+   * Clears all recipients assigned in the TO array.  Returns void.
+   * @return void
+   */
+  public function ClearAddresses() {
+    foreach($this->to as $to) {
+      unset($this->all_recipients[strtolower($to[0])]);
+    }
+    $this->to = array();
+  }
+
+  /**
+   * Clears all recipients assigned in the CC array.  Returns void.
+   * @return void
+   */
+  public function ClearCCs() {
+    foreach($this->cc as $cc) {
+      unset($this->all_recipients[strtolower($cc[0])]);
+    }
+    $this->cc = array();
+  }
+
+  /**
+   * Clears all recipients assigned in the BCC array.  Returns void.
+   * @return void
+   */
+  public function ClearBCCs() {
+    foreach($this->bcc as $bcc) {
+      unset($this->all_recipients[strtolower($bcc[0])]);
+    }
+    $this->bcc = array();
+  }
+
+  /**
+   * Clears all recipients assigned in the ReplyTo array.  Returns void.
+   * @return void
+   */
+  public function ClearReplyTos() {
+    $this->ReplyTo = array();
+  }
+
+  /**
+   * Clears all recipients assigned in the TO, CC and BCC
+   * array.  Returns void.
+   * @return void
+   */
+  public function ClearAllRecipients() {
+    $this->to = array();
+    $this->cc = array();
+    $this->bcc = array();
+    $this->all_recipients = array();
+  }
+
+  /**
+   * Clears all previously set filesystem, string, and binary
+   * attachments.  Returns void.
+   * @return void
+   */
+  public function ClearAttachments() {
+    $this->attachment = array();
+  }
+
+  /**
+   * Clears all custom headers.  Returns void.
+   * @return void
+   */
+  public function ClearCustomHeaders() {
+    $this->CustomHeader = array();
+  }
+
+  /////////////////////////////////////////////////
+  // CLASS METHODS, MISCELLANEOUS
+  /////////////////////////////////////////////////
+
+  /**
+   * Adds the error message to the error container.
+   * @access protected
+   * @return void
+   */
+  protected function SetError($msg) {
+    $this->error_count++;
+    if ($this->Mailer == 'smtp' and !is_null($this->smtp)) {
+      $lasterror = $this->smtp->getError();
+      if (!empty($lasterror) and array_key_exists('smtp_msg', $lasterror)) {
+        $msg .= '<p>' . $this->Lang('smtp_error') . $lasterror['smtp_msg'] . "</p>\n";
+      }
+    }
+    $this->ErrorInfo = $msg;
+  }
+
+  /**
+   * Returns the proper RFC 822 formatted date.
+   * @access public
+   * @return string
+   * @static
+   */
+  public static function RFCDate() {
+    $tz = date('Z');
+    $tzs = ($tz < 0) ? '-' : '+';
+    $tz = abs($tz);
+    $tz = (int)($tz/3600)*100 + ($tz%3600)/60;
+    $result = sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz);
+
+    return $result;
+  }
+
+  /**
+   * Returns the server hostname or 'localhost.localdomain' if unknown.
+   * @access private
+   * @return string
+   */
+  private function ServerHostname() {
+    if (!empty($this->Hostname)) {
+      $result = $this->Hostname;
+    } elseif (isset($_SERVER['SERVER_NAME'])) {
+      $result = $_SERVER['SERVER_NAME'];
+    } else {
+      $result = 'localhost.localdomain';
+    }
+
+    return $result;
+  }
+
+  /**
+   * Returns a message in the appropriate language.
+   * @access private
+   * @return string
+   */
+  private function Lang($key) {
+    if(count($this->language) < 1) {
+      $this->SetLanguage('en'); // set the default language
+    }
+
+    if(isset($this->language[$key])) {
+      return $this->language[$key];
+    } else {
+      return 'Language string failed to load: ' . $key;
+    }
+  }
+
+  /**
+   * Returns true if an error occurred.
+   * @access public
+   * @return bool
+   */
+  public function IsError() {
+    return ($this->error_count > 0);
+  }
+
+  /**
+   * Changes every end of line from CR or LF to CRLF.
+   * @access private
+   * @return string
+   */
+  private function FixEOL($str) {
+    $str = str_replace("\r\n", "\n", $str);
+    $str = str_replace("\r", "\n", $str);
+    $str = str_replace("\n", $this->LE, $str);
+    return $str;
+  }
+
+  /**
+   * Adds a custom header.
+   * @access public
+   * @return void
+   */
+  public function AddCustomHeader($custom_header) {
+    $this->CustomHeader[] = explode(':', $custom_header, 2);
+  }
+
+  /**
+   * Evaluates the message and returns modifications for inline images and backgrounds
+   * @access public
+   * @return $message
+   */
+  public function MsgHTML($message, $basedir = '') {
+    preg_match_all("/(src|background)=\"(.*)\"/Ui", $message, $images);
+    if(isset($images[2])) {
+      foreach($images[2] as $i => $url) {
+        // do not change urls for absolute images (thanks to corvuscorax)
+        if (!preg_match('#^[A-z]+://#',$url)) {
+          $filename = basename($url);
+          $directory = dirname($url);
+          ($directory == '.')?$directory='':'';
+          $cid = 'cid:' . md5($filename);
+          $ext = pathinfo($filename, PATHINFO_EXTENSION);
+          $mimeType  = self::_mime_types($ext);
+          if ( strlen($basedir) > 1 && substr($basedir,-1) != '/') { $basedir .= '/'; }
+          if ( strlen($directory) > 1 && substr($directory,-1) != '/') { $directory .= '/'; }
+          if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64',$mimeType) ) {
+            $message = preg_replace("/".$images[1][$i]."=\"".preg_quote($url, '/')."\"/Ui", $images[1][$i]."=\"".$cid."\"", $message);
+          }
+        }
+      }
+    }
+    $this->IsHTML(true);
+    $this->Body = $message;
+    $textMsg = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s','',$message)));
+    if (!empty($textMsg) && empty($this->AltBody)) {
+      $this->AltBody = html_entity_decode($textMsg);
+    }
+    if (empty($this->AltBody)) {
+      $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . "\n\n";
+    }
+  }
+
+  /**
+   * Gets the MIME type of the embedded or inline image
+   * @param string File extension
+   * @access public
+   * @return string MIME type of ext
+   * @static
+   */
+  public static function _mime_types($ext = '') {
+    $mimes = array(
+      'hqx'   =>  'application/mac-binhex40',
+      'cpt'   =>  'application/mac-compactpro',
+      'doc'   =>  'application/msword',
+      'bin'   =>  'application/macbinary',
+      'dms'   =>  'application/octet-stream',
+      'lha'   =>  'application/octet-stream',
+      'lzh'   =>  'application/octet-stream',
+      'exe'   =>  'application/octet-stream',
+      'class' =>  'application/octet-stream',
+      'psd'   =>  'application/octet-stream',
+      'so'    =>  'application/octet-stream',
+      'sea'   =>  'application/octet-stream',
+      'dll'   =>  'application/octet-stream',
+      'oda'   =>  'application/oda',
+      'pdf'   =>  'application/pdf',
+      'ai'    =>  'application/postscript',
+      'eps'   =>  'application/postscript',
+      'ps'    =>  'application/postscript',
+      'smi'   =>  'application/smil',
+      'smil'  =>  'application/smil',
+      'mif'   =>  'application/vnd.mif',
+      'xls'   =>  'application/vnd.ms-excel',
+      'ppt'   =>  'application/vnd.ms-powerpoint',
+      'wbxml' =>  'application/vnd.wap.wbxml',
+      'wmlc'  =>  'application/vnd.wap.wmlc',
+      'dcr'   =>  'application/x-director',
+      'dir'   =>  'application/x-director',
+      'dxr'   =>  'application/x-director',
+      'dvi'   =>  'application/x-dvi',
+      'gtar'  =>  'application/x-gtar',
+      'php'   =>  'application/x-httpd-php',
+      'php4'  =>  'application/x-httpd-php',
+      'php3'  =>  'application/x-httpd-php',
+      'phtml' =>  'application/x-httpd-php',
+      'phps'  =>  'application/x-httpd-php-source',
+      'js'    =>  'application/x-javascript',
+      'swf'   =>  'application/x-shockwave-flash',
+      'sit'   =>  'application/x-stuffit',
+      'tar'   =>  'application/x-tar',
+      'tgz'   =>  'application/x-tar',
+      'xhtml' =>  'application/xhtml+xml',
+      'xht'   =>  'application/xhtml+xml',
+      'zip'   =>  'application/zip',
+      'mid'   =>  'audio/midi',
+      'midi'  =>  'audio/midi',
+      'mpga'  =>  'audio/mpeg',
+      'mp2'   =>  'audio/mpeg',
+      'mp3'   =>  'audio/mpeg',
+      'aif'   =>  'audio/x-aiff',
+      'aiff'  =>  'audio/x-aiff',
+      'aifc'  =>  'audio/x-aiff',
+      'ram'   =>  'audio/x-pn-realaudio',
+      'rm'    =>  'audio/x-pn-realaudio',
+      'rpm'   =>  'audio/x-pn-realaudio-plugin',
+      'ra'    =>  'audio/x-realaudio',
+      'rv'    =>  'video/vnd.rn-realvideo',
+      'wav'   =>  'audio/x-wav',
+      'bmp'   =>  'image/bmp',
+      'gif'   =>  'image/gif',
+      'jpeg'  =>  'image/jpeg',
+      'jpg'   =>  'image/jpeg',
+      'jpe'   =>  'image/jpeg',
+      'png'   =>  'image/png',
+      'tiff'  =>  'image/tiff',
+      'tif'   =>  'image/tiff',
+      'css'   =>  'text/css',
+      'html'  =>  'text/html',
+      'htm'   =>  'text/html',
+      'shtml' =>  'text/html',
+      'txt'   =>  'text/plain',
+      'text'  =>  'text/plain',
+      'log'   =>  'text/plain',
+      'rtx'   =>  'text/richtext',
+      'rtf'   =>  'text/rtf',
+      'xml'   =>  'text/xml',
+      'xsl'   =>  'text/xml',
+      'mpeg'  =>  'video/mpeg',
+      'mpg'   =>  'video/mpeg',
+      'mpe'   =>  'video/mpeg',
+      'qt'    =>  'video/quicktime',
+      'mov'   =>  'video/quicktime',
+      'avi'   =>  'video/x-msvideo',
+      'movie' =>  'video/x-sgi-movie',
+      'doc'   =>  'application/msword',
+      'word'  =>  'application/msword',
+      'xl'    =>  'application/excel',
+      'eml'   =>  'message/rfc822'
+    );
+    return (!isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)];
+  }
+
+  /**
+  * Set (or reset) Class Objects (variables)
+  *
+  * Usage Example:
+  * $page->set('X-Priority', '3');
+  *
+  * @access public
+  * @param string $name Parameter Name
+  * @param mixed $value Parameter Value
+  * NOTE: will not work with arrays, there are no arrays to set/reset
+  * @todo Should this not be using __set() magic function?
+  */
+  public function set($name, $value = '') {
+    try {
+      if (isset($this->$name) ) {
+        $this->$name = $value;
+      } else {
+        throw new phpmailerException($this->Lang('variable_set') . $name, self::STOP_CRITICAL);
+      }
+    } catch (Exception $e) {
+      $this->SetError($e->getMessage());
+      if ($e->getCode() == self::STOP_CRITICAL) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Strips newlines to prevent header injection.
+   * @access public
+   * @param string $str String
+   * @return string
+   */
+  public function SecureHeader($str) {
+    $str = str_replace("\r", '', $str);
+    $str = str_replace("\n", '', $str);
+    return trim($str);
+  }
+
+  /**
+   * Set the private key file and password to sign the message.
+   *
+   * @access public
+   * @param string $key_filename Parameter File Name
+   * @param string $key_pass Password for private key
+   */
+  public function Sign($cert_filename, $key_filename, $key_pass) {
+    $this->sign_cert_file = $cert_filename;
+    $this->sign_key_file = $key_filename;
+    $this->sign_key_pass = $key_pass;
+  }
+
+  /**
+   * Set the private key file and password to sign the message.
+   *
+   * @access public
+   * @param string $key_filename Parameter File Name
+   * @param string $key_pass Password for private key
+   */
+  public function DKIM_QP($txt) {
+    $tmp="";
+    $line="";
+    for ($i=0;$i<strlen($txt);$i++) {
+      $ord=ord($txt[$i]);
+      if ( ((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E)) ) {
+        $line.=$txt[$i];
+      } else {
+        $line.="=".sprintf("%02X",$ord);
+      }
+    }
+    return $line;
+  }
+
+  /**
+   * Generate DKIM signature
+   *
+   * @access public
+   * @param string $s Header
+   */
+  public function DKIM_Sign($s) {
+    $privKeyStr = file_get_contents($this->DKIM_private);
+    if ($this->DKIM_passphrase!='') {
+      $privKey = openssl_pkey_get_private($privKeyStr,$this->DKIM_passphrase);
+    } else {
+      $privKey = $privKeyStr;
+    }
+    if (openssl_sign($s, $signature, $privKey)) {
+      return base64_encode($signature);
+    }
+  }
+
+  /**
+   * Generate DKIM Canonicalization Header
+   *
+   * @access public
+   * @param string $s Header
+   */
+  public function DKIM_HeaderC($s) {
+    $s=preg_replace("/\r\n\s+/"," ",$s);
+    $lines=explode("\r\n",$s);
+    foreach ($lines as $key=>$line) {
+      list($heading,$value)=explode(":",$line,2);
+      $heading=strtolower($heading);
+      $value=preg_replace("/\s+/"," ",$value) ; // Compress useless spaces
+      $lines[$key]=$heading.":".trim($value) ; // Don't forget to remove WSP around the value
+    }
+    $s=implode("\r\n",$lines);
+    return $s;
+  }
+
+  /**
+   * Generate DKIM Canonicalization Body
+   *
+   * @access public
+   * @param string $body Message Body
+   */
+  public function DKIM_BodyC($body) {
+    if ($body == '') return "\r\n";
+    // stabilize line endings
+    $body=str_replace("\r\n","\n",$body);
+    $body=str_replace("\n","\r\n",$body);
+    // END stabilize line endings
+    while (substr($body,strlen($body)-4,4) == "\r\n\r\n") {
+      $body=substr($body,0,strlen($body)-2);
+    }
+    return $body;
+  }
+
+  /**
+   * Create the DKIM header, body, as new header
+   *
+   * @access public
+   * @param string $headers_line Header lines
+   * @param string $subject Subject
+   * @param string $body Body
+   */
+  public function DKIM_Add($headers_line,$subject,$body) {
+    $DKIMsignatureType    = 'rsa-sha1'; // Signature & hash algorithms
+    $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body
+    $DKIMquery            = 'dns/txt'; // Query method
+    $DKIMtime             = time() ; // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)
+    $subject_header       = "Subject: $subject";
+    $headers              = explode("\r\n",$headers_line);
+    foreach($headers as $header) {
+      if (strpos($header,'From:') === 0) {
+        $from_header=$header;
+      } elseif (strpos($header,'To:') === 0) {
+        $to_header=$header;
+      }
+    }
+    $from     = str_replace('|','=7C',$this->DKIM_QP($from_header));
+    $to       = str_replace('|','=7C',$this->DKIM_QP($to_header));
+    $subject  = str_replace('|','=7C',$this->DKIM_QP($subject_header)) ; // Copied header fields (dkim-quoted-printable
+    $body     = $this->DKIM_BodyC($body);
+    $DKIMlen  = strlen($body) ; // Length of body
+    $DKIMb64  = base64_encode(pack("H*", sha1($body))) ; // Base64 of packed binary SHA-1 hash of body
+    $ident    = ($this->DKIM_identity == '')? '' : " i=" . $this->DKIM_identity . ";";
+    $dkimhdrs = "DKIM-Signature: v=1; a=" . $DKIMsignatureType . "; q=" . $DKIMquery . "; l=" . $DKIMlen . "; s=" . $this->DKIM_selector . ";\r\n".
+                "\tt=" . $DKIMtime . "; c=" . $DKIMcanonicalization . ";\r\n".
+                "\th=From:To:Subject;\r\n".
+                "\td=" . $this->DKIM_domain . ";" . $ident . "\r\n".
+                "\tz=$from\r\n".
+                "\t|$to\r\n".
+                "\t|$subject;\r\n".
+                "\tbh=" . $DKIMb64 . ";\r\n".
+                "\tb=";
+    $toSign   = $this->DKIM_HeaderC($from_header . "\r\n" . $to_header . "\r\n" . $subject_header . "\r\n" . $dkimhdrs);
+    $signed   = $this->DKIM_Sign($toSign);
+    return "X-PHPMAILER-DKIM: phpmailer.worxware.com\r\n".$dkimhdrs.$signed."\r\n";
+  }
+
+  protected function doCallback($isSent,$to,$cc,$bcc,$subject,$body) {
+    if (!empty($this->action_function) && function_exists($this->action_function)) {
+      $params = array($isSent,$to,$cc,$bcc,$subject,$body);
+      call_user_func_array($this->action_function,$params);
+    }
+  }
+}
+
+class phpmailerException extends Exception {
+  public function errorMessage() {
+    $errorMsg = '<strong>' . $this->getMessage() . "</strong><br />\n";
+    return $errorMsg;
+  }
+}
+?>

+ 407 - 0
include/PHPMailer/class.pop3.php

@@ -0,0 +1,407 @@
+<?php
+/*~ class.pop3.php
+.---------------------------------------------------------------------------.
+|  Software: PHPMailer - PHP email class                                    |
+|   Version: 5.1                                                            |
+|   Contact: via sourceforge.net support pages (also www.codeworxtech.com)  |
+|      Info: http://phpmailer.sourceforge.net                               |
+|   Support: http://sourceforge.net/projects/phpmailer/                     |
+| ------------------------------------------------------------------------- |
+|     Admin: Andy Prevost (project admininistrator)                         |
+|   Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net |
+|          : Marcus Bointon (coolbru) coolbru@users.sourceforge.net         |
+|   Founder: Brent R. Matzelle (original founder)                           |
+| Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved.               |
+| Copyright (c) 2001-2003, Brent R. Matzelle                                |
+| ------------------------------------------------------------------------- |
+|   License: Distributed under the Lesser General Public License (LGPL)     |
+|            http://www.gnu.org/copyleft/lesser.html                        |
+| This program is distributed in the hope that it will be useful - WITHOUT  |
+| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |
+| FITNESS FOR A PARTICULAR PURPOSE.                                         |
+| ------------------------------------------------------------------------- |
+| We offer a number of paid services (www.codeworxtech.com):                |
+| - Web Hosting on highly optimized fast and secure servers                 |
+| - Technology Consulting                                                   |
+| - Oursourcing (highly qualified programmers and graphic designers)        |
+'---------------------------------------------------------------------------'
+*/
+
+/**
+ * PHPMailer - PHP POP Before SMTP Authentication Class
+ * NOTE: Designed for use with PHP version 5 and up
+ * @package PHPMailer
+ * @author Andy Prevost
+ * @author Marcus Bointon
+ * @copyright 2004 - 2009 Andy Prevost
+ * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL)
+ * @version $Id: class.pop3.php 444 2009-05-05 11:22:26Z coolbru $
+ */
+
+/**
+ * POP Before SMTP Authentication Class
+ * Version 5.0.0
+ *
+ * Author: Richard Davey (rich@corephp.co.uk)
+ * Modifications: Andy Prevost
+ * License: LGPL, see PHPMailer License
+ *
+ * Specifically for PHPMailer to allow POP before SMTP authentication.
+ * Does not yet work with APOP - if you have an APOP account, contact Richard Davey
+ * and we can test changes to this script.
+ *
+ * This class is based on the structure of the SMTP class originally authored by Chris Ryan
+ *
+ * This class is rfc 1939 compliant and implements all the commands
+ * required for POP3 connection, authentication and disconnection.
+ *
+ * @package PHPMailer
+ * @author Richard Davey
+ */
+
+class POP3 {
+  /**
+   * Default POP3 port
+   * @var int
+   */
+  public $POP3_PORT = 110;
+
+  /**
+   * Default Timeout
+   * @var int
+   */
+  public $POP3_TIMEOUT = 30;
+
+  /**
+   * POP3 Carriage Return + Line Feed
+   * @var string
+   */
+  public $CRLF = "\r\n";
+
+  /**
+   * Displaying Debug warnings? (0 = now, 1+ = yes)
+   * @var int
+   */
+  public $do_debug = 2;
+
+  /**
+   * POP3 Mail Server
+   * @var string
+   */
+  public $host;
+
+  /**
+   * POP3 Port
+   * @var int
+   */
+  public $port;
+
+  /**
+   * POP3 Timeout Value
+   * @var int
+   */
+  public $tval;
+
+  /**
+   * POP3 Username
+   * @var string
+   */
+  public $username;
+
+  /**
+   * POP3 Password
+   * @var string
+   */
+  public $password;
+
+  /////////////////////////////////////////////////
+  // PROPERTIES, PRIVATE AND PROTECTED
+  /////////////////////////////////////////////////
+
+  private $pop_conn;
+  private $connected;
+  private $error;     //  Error log array
+
+  /**
+   * Constructor, sets the initial values
+   * @access public
+   * @return POP3
+   */
+  public function __construct() {
+    $this->pop_conn  = 0;
+    $this->connected = false;
+    $this->error     = null;
+  }
+
+  /**
+   * Combination of public events - connect, login, disconnect
+   * @access public
+   * @param string $host
+   * @param integer $port
+   * @param integer $tval
+   * @param string $username
+   * @param string $password
+   */
+  public function Authorise ($host, $port = false, $tval = false, $username, $password, $debug_level = 0) {
+    $this->host = $host;
+
+    //  If no port value is passed, retrieve it
+    if ($port == false) {
+      $this->port = $this->POP3_PORT;
+    } else {
+      $this->port = $port;
+    }
+
+    //  If no port value is passed, retrieve it
+    if ($tval == false) {
+      $this->tval = $this->POP3_TIMEOUT;
+    } else {
+      $this->tval = $tval;
+    }
+
+    $this->do_debug = $debug_level;
+    $this->username = $username;
+    $this->password = $password;
+
+    //  Refresh the error log
+    $this->error = null;
+
+    //  Connect
+    $result = $this->Connect($this->host, $this->port, $this->tval);
+
+    if ($result) {
+      $login_result = $this->Login($this->username, $this->password);
+
+      if ($login_result) {
+        $this->Disconnect();
+
+        return true;
+      }
+
+    }
+
+    //  We need to disconnect regardless if the login succeeded
+    $this->Disconnect();
+
+    return false;
+  }
+
+  /**
+   * Connect to the POP3 server
+   * @access public
+   * @param string $host
+   * @param integer $port
+   * @param integer $tval
+   * @return boolean
+   */
+  public function Connect ($host, $port = false, $tval = 30) {
+    //  Are we already connected?
+    if ($this->connected) {
+      return true;
+    }
+
+    /*
+    On Windows this will raise a PHP Warning error if the hostname doesn't exist.
+    Rather than supress it with @fsockopen, let's capture it cleanly instead
+    */
+
+    set_error_handler(array(&$this, 'catchWarning'));
+
+    //  Connect to the POP3 server
+    $this->pop_conn = fsockopen($host,    //  POP3 Host
+                  $port,    //  Port #
+                  $errno,   //  Error Number
+                  $errstr,  //  Error Message
+                  $tval);   //  Timeout (seconds)
+
+    //  Restore the error handler
+    restore_error_handler();
+
+    //  Does the Error Log now contain anything?
+    if ($this->error && $this->do_debug >= 1) {
+      $this->displayErrors();
+    }
+
+    //  Did we connect?
+    if ($this->pop_conn == false) {
+      //  It would appear not...
+      $this->error = array(
+        'error' => "Failed to connect to server $host on port $port",
+        'errno' => $errno,
+        'errstr' => $errstr
+      );
+
+      if ($this->do_debug >= 1) {
+        $this->displayErrors();
+      }
+
+      return false;
+    }
+
+    //  Increase the stream time-out
+
+    //  Check for PHP 4.3.0 or later
+    if (version_compare(phpversion(), '5.0.0', 'ge')) {
+      stream_set_timeout($this->pop_conn, $tval, 0);
+    } else {
+      //  Does not work on Windows
+      if (substr(PHP_OS, 0, 3) !== 'WIN') {
+        socket_set_timeout($this->pop_conn, $tval, 0);
+      }
+    }
+
+    //  Get the POP3 server response
+    $pop3_response = $this->getResponse();
+
+    //  Check for the +OK
+    if ($this->checkResponse($pop3_response)) {
+    //  The connection is established and the POP3 server is talking
+    $this->connected = true;
+      return true;
+    }
+
+  }
+
+  /**
+   * Login to the POP3 server (does not support APOP yet)
+   * @access public
+   * @param string $username
+   * @param string $password
+   * @return boolean
+   */
+  public function Login ($username = '', $password = '') {
+    if ($this->connected == false) {
+      $this->error = 'Not connected to POP3 server';
+
+      if ($this->do_debug >= 1) {
+        $this->displayErrors();
+      }
+    }
+
+    if (empty($username)) {
+      $username = $this->username;
+    }
+
+    if (empty($password)) {
+      $password = $this->password;
+    }
+
+    $pop_username = "USER $username" . $this->CRLF;
+    $pop_password = "PASS $password" . $this->CRLF;
+
+    //  Send the Username
+    $this->sendString($pop_username);
+    $pop3_response = $this->getResponse();
+
+    if ($this->checkResponse($pop3_response)) {
+      //  Send the Password
+      $this->sendString($pop_password);
+      $pop3_response = $this->getResponse();
+
+      if ($this->checkResponse($pop3_response)) {
+        return true;
+      } else {
+        return false;
+      }
+    } else {
+      return false;
+    }
+  }
+
+  /**
+   * Disconnect from the POP3 server
+   * @access public
+   */
+  public function Disconnect () {
+    $this->sendString('QUIT');
+
+    fclose($this->pop_conn);
+  }
+
+  /////////////////////////////////////////////////
+  //  Private Methods
+  /////////////////////////////////////////////////
+
+  /**
+   * Get the socket response back.
+   * $size is the maximum number of bytes to retrieve
+   * @access private
+   * @param integer $size
+   * @return string
+   */
+  private function getResponse ($size = 128) {
+    $pop3_response = fgets($this->pop_conn, $size);
+
+    return $pop3_response;
+  }
+
+  /**
+   * Send a string down the open socket connection to the POP3 server
+   * @access private
+   * @param string $string
+   * @return integer
+   */
+  private function sendString ($string) {
+    $bytes_sent = fwrite($this->pop_conn, $string, strlen($string));
+
+    return $bytes_sent;
+  }
+
+  /**
+   * Checks the POP3 server response for +OK or -ERR
+   * @access private
+   * @param string $string
+   * @return boolean
+   */
+  private function checkResponse ($string) {
+    if (substr($string, 0, 3) !== '+OK') {
+      $this->error = array(
+        'error' => "Server reported an error: $string",
+        'errno' => 0,
+        'errstr' => ''
+      );
+
+      if ($this->do_debug >= 1) {
+        $this->displayErrors();
+      }
+
+      return false;
+    } else {
+      return true;
+    }
+
+  }
+
+  /**
+   * If debug is enabled, display the error message array
+   * @access private
+   */
+  private function displayErrors () {
+    echo '<pre>';
+
+    foreach ($this->error as $single_error) {
+      print_r($single_error);
+    }
+
+    echo '</pre>';
+  }
+
+  /**
+   * Takes over from PHP for the socket warning handler
+   * @access private
+   * @param integer $errno
+   * @param string $errstr
+   * @param string $errfile
+   * @param integer $errline
+   */
+  private function catchWarning ($errno, $errstr, $errfile, $errline) {
+    $this->error[] = array(
+      'error' => "Connecting to the POP3 server raised a PHP warning: ",
+      'errno' => $errno,
+      'errstr' => $errstr
+    );
+  }
+
+  //  End of class
+}
+?>

+ 814 - 0
include/PHPMailer/class.smtp.php

@@ -0,0 +1,814 @@
+<?php
+/*~ class.smtp.php
+.---------------------------------------------------------------------------.
+|  Software: PHPMailer - PHP email class                                    |
+|   Version: 5.1                                                            |
+|   Contact: via sourceforge.net support pages (also www.codeworxtech.com)  |
+|      Info: http://phpmailer.sourceforge.net                               |
+|   Support: http://sourceforge.net/projects/phpmailer/                     |
+| ------------------------------------------------------------------------- |
+|     Admin: Andy Prevost (project admininistrator)                         |
+|   Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net |
+|          : Marcus Bointon (coolbru) coolbru@users.sourceforge.net         |
+|   Founder: Brent R. Matzelle (original founder)                           |
+| Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved.               |
+| Copyright (c) 2001-2003, Brent R. Matzelle                                |
+| ------------------------------------------------------------------------- |
+|   License: Distributed under the Lesser General Public License (LGPL)     |
+|            http://www.gnu.org/copyleft/lesser.html                        |
+| This program is distributed in the hope that it will be useful - WITHOUT  |
+| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |
+| FITNESS FOR A PARTICULAR PURPOSE.                                         |
+| ------------------------------------------------------------------------- |
+| We offer a number of paid services (www.codeworxtech.com):                |
+| - Web Hosting on highly optimized fast and secure servers                 |
+| - Technology Consulting                                                   |
+| - Oursourcing (highly qualified programmers and graphic designers)        |
+'---------------------------------------------------------------------------'
+*/
+
+/**
+ * PHPMailer - PHP SMTP email transport class
+ * NOTE: Designed for use with PHP version 5 and up
+ * @package PHPMailer
+ * @author Andy Prevost
+ * @author Marcus Bointon
+ * @copyright 2004 - 2008 Andy Prevost
+ * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL)
+ * @version $Id: class.smtp.php 444 2009-05-05 11:22:26Z coolbru $
+ */
+
+/**
+ * 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.
+ * original author: Chris Ryan
+ */
+
+class SMTP {
+  /**
+   *  SMTP server port
+   *  @var int
+   */
+  public $SMTP_PORT = 25;
+
+  /**
+   *  SMTP reply line ending
+   *  @var string
+   */
+  public $CRLF = "\r\n";
+
+  /**
+   *  Sets whether debugging is turned on
+   *  @var bool
+   */
+  public $do_debug;       // the level of debug to perform
+
+  /**
+   *  Sets VERP use on/off (default is off)
+   *  @var bool
+   */
+  public $do_verp = false;
+
+  /////////////////////////////////////////////////
+  // PROPERTIES, PRIVATE AND PROTECTED
+  /////////////////////////////////////////////////
+
+  private $smtp_conn; // the socket to the server
+  private $error;     // error if any on the last call
+  private $helo_rply; // 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
+   */
+  public function __construct() {
+    $this->smtp_conn = 0;
+    $this->error = null;
+    $this->helo_rply = null;
+
+    $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
+   */
+  public function Connect($host, $port = 0, $tval = 30) {
+    // set the error val to null so there is no confusion
+    $this->error = null;
+
+    // make sure we are __not__ connected
+    if($this->connected()) {
+      // already connected, generate error
+      $this->error = array("error" => "Already connected to a server");
+      return false;
+    }
+
+    if(empty($port)) {
+      $port = $this->SMTP_PORT;
+    }
+
+    // connect to the smtp server
+    $this->smtp_conn = @fsockopen($host,    // the host of the server
+                                 $port,    // the port to use
+                                 $errno,   // error number if any
+                                 $errstr,  // error message if any
+                                 $tval);   // 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 . '<br />';
+      }
+      return false;
+    }
+
+    // SMTP server can take longer to respond, give longer timeout for first read
+    // Windows 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
+    $announce = $this->get_lines();
+
+    if($this->do_debug >= 2) {
+      echo "SMTP -> FROM SERVER:" . $announce . $this->CRLF . '<br />';
+    }
+
+    return true;
+  }
+
+  /**
+   * Initiate a TLS communication with the server.
+   *
+   * SMTP CODE 220 Ready to start TLS
+   * SMTP CODE 501 Syntax error (no parameters allowed)
+   * SMTP CODE 454 TLS not available due to temporary reason
+   * @access public
+   * @return bool success
+   */
+  public function StartTLS() {
+    $this->error = null; # to avoid confusion
+
+    if(!$this->connected()) {
+      $this->error = array("error" => "Called StartTLS() without being connected");
+      return false;
+    }
+
+    fputs($this->smtp_conn,"STARTTLS" . $this->CRLF);
+
+    $rply = $this->get_lines();
+    $code = substr($rply,0,3);
+
+    if($this->do_debug >= 2) {
+      echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
+    }
+
+    if($code != 220) {
+      $this->error =
+         array("error"     => "STARTTLS 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 . '<br />';
+      }
+      return false;
+    }
+
+    // Begin encrypted connection
+    if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
+      return false;
+    }
+
+    return true;
+  }
+
+  /**
+   * Performs SMTP authentication.  Must be run after running the
+   * Hello() method.  Returns true if successfully authenticated.
+   * @access public
+   * @return bool
+   */
+  public 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 . '<br />';
+      }
+      return false;
+    }
+
+    // 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 . '<br />';
+      }
+      return false;
+    }
+
+    // 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 . '<br />';
+      }
+      return false;
+    }
+
+    return true;
+  }
+
+  /**
+   * Returns true if connected to a server otherwise false
+   * @access public
+   * @return bool
+   */
+  public function Connected() {
+    if(!empty($this->smtp_conn)) {
+      $sock_status = socket_get_status($this->smtp_conn);
+      if($sock_status["eof"]) {
+        // the socket is valid but we are not connected
+        if($this->do_debug >= 1) {
+            echo "SMTP -> NOTICE:" . $this->CRLF . "EOF caught while checking if connected";
+        }
+        $this->Close();
+        return false;
+      }
+      return true; // everything looks good
+    }
+    return false;
+  }
+
+  /**
+   * 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
+   */
+  public function Close() {
+    $this->error = null; // so there is no confusion
+    $this->helo_rply = null;
+    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
+   *     [data]
+   *     <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
+   */
+  public function Data($msg_data) {
+    $this->error = null; // so no confusion is caused
+
+    if(!$this->connected()) {
+      $this->error = array(
+              "error" => "Called Data() without being connected");
+      return false;
+    }
+
+    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:" . $rply . $this->CRLF . '<br />';
+    }
+
+    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 . '<br />';
+      }
+      return false;
+    }
+
+    /* 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 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 am 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 = false;
+    if(!empty($field) && !strstr($field," ")) {
+      $in_headers = true;
+    }
+
+    $max_line_length = 998; // used below; set here for ease in change
+
+    while(list(,$line) = @each($lines)) {
+      $lines_out = null;
+      if($line == "" && $in_headers) {
+        $in_headers = false;
+      }
+      // 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);
+        } else {
+          $lines_out[] = substr($line,0,$pos);
+          $line = substr($line,$pos + 1);
+        }
+
+        /* if processing headers add a LWSP-char to the front of new line
+         * rfc 822 on long msg headers
+         */
+        if($in_headers) {
+          $line = "\t" . $line;
+        }
+      }
+      $lines_out[] = $line;
+
+      // 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_out;
+          }
+        }
+        fputs($this->smtp_conn,$line_out . $this->CRLF);
+      }
+    }
+
+    // message data has been sent
+    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:" . $rply . $this->CRLF . '<br />';
+    }
+
+    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 . '<br />';
+      }
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * 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
+   */
+  public function Hello($host = '') {
+    $this->error = null; // so no confusion is caused
+
+    if(!$this->connected()) {
+      $this->error = array(
+            "error" => "Called Hello() without being connected");
+      return false;
+    }
+
+    // if hostname for HELO was not specified send default
+    if(empty($host)) {
+      // determine appropriate default to send to server
+      $host = "localhost";
+    }
+
+    // Send extended hello first (RFC 2821)
+    if(!$this->SendHello("EHLO", $host)) {
+      if(!$this->SendHello("HELO", $host)) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  /**
+   * Sends a HELO/EHLO command.
+   * @access private
+   * @return bool
+   */
+  private 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: " . $rply . $this->CRLF . '<br />';
+    }
+
+    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 . '<br />';
+      }
+      return false;
+    }
+
+    $this->helo_rply = $rply;
+
+    return true;
+  }
+
+  /**
+   * 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
+   */
+  public function Mail($from) {
+    $this->error = null; // so no confusion is caused
+
+    if(!$this->connected()) {
+      $this->error = array(
+              "error" => "Called Mail() without being connected");
+      return false;
+    }
+
+    $useVerp = ($this->do_verp ? "XVERP" : "");
+    fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF);
+
+    $rply = $this->get_lines();
+    $code = substr($rply,0,3);
+
+    if($this->do_debug >= 2) {
+      echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
+    }
+
+    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 . '<br />';
+      }
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * 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  : 500
+   * @access public
+   * @return bool
+   */
+  public function Quit($close_on_error = true) {
+    $this->error = null; // so there is no confusion
+
+    if(!$this->connected()) {
+      $this->error = array(
+              "error" => "Called Quit() without being connected");
+      return false;
+    }
+
+    // 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:" . $byemsg . $this->CRLF . '<br />';
+    }
+
+    $rval = true;
+    $e = null;
+
+    $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));
+      $rval = false;
+      if($this->do_debug >= 1) {
+        echo "SMTP -> ERROR: " . $e["error"] . ": " . $byemsg . $this->CRLF . '<br />';
+      }
+    }
+
+    if(empty($e) || $close_on_error) {
+      $this->Close();
+    }
+
+    return $rval;
+  }
+
+  /**
+   * 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
+   */
+  public function Recipient($to) {
+    $this->error = null; // so no confusion is caused
+
+    if(!$this->connected()) {
+      $this->error = array(
+              "error" => "Called Recipient() without being connected");
+      return false;
+    }
+
+    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:" . $rply . $this->CRLF . '<br />';
+    }
+
+    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 . '<br />';
+      }
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * 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
+   */
+  public function Reset() {
+    $this->error = null; // so no confusion is caused
+
+    if(!$this->connected()) {
+      $this->error = array(
+              "error" => "Called Reset() without being connected");
+      return false;
+    }
+
+    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:" . $rply . $this->CRLF . '<br />';
+    }
+
+    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 . '<br />';
+      }
+      return false;
+    }
+
+    return true;
+  }
+
+  /**
+   * 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
+   * in and send them an email.
+   *
+   * Implements rfc 821: SAML <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
+   */
+  public function SendAndMail($from) {
+    $this->error = null; // so no confusion is caused
+
+    if(!$this->connected()) {
+      $this->error = array(
+          "error" => "Called SendAndMail() without being connected");
+      return false;
+    }
+
+    fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);
+
+    $rply = $this->get_lines();
+    $code = substr($rply,0,3);
+
+    if($this->do_debug >= 2) {
+      echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
+    }
+
+    if($code != 250) {
+      $this->error =
+        array("error" => "SAML 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 . '<br />';
+      }
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * This is an optional command for SMTP that this class does not
+   * support. This method is here to make the RFC821 Definition
+   * complete for this class and __may__ be implimented in the future
+   *
+   * Implements from rfc 821: TURN <CRLF>
+   *
+   * SMTP CODE SUCCESS: 250
+   * SMTP CODE FAILURE: 502
+   * SMTP CODE ERROR  : 500, 503
+   * @access public
+   * @return bool
+   */
+  public function Turn() {
+    $this->error = array("error" => "This method, TURN, of the SMTP ".
+                                    "is not implemented");
+    if($this->do_debug >= 1) {
+      echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF . '<br />';
+    }
+    return false;
+  }
+
+  /**
+  * Get the current error
+  * @access public
+  * @return array
+  */
+  public function getError() {
+    return $this->error;
+  }
+
+  /////////////////////////////////////////////////
+  // INTERNAL FUNCTIONS
+  /////////////////////////////////////////////////
+
+  /**
+   * Read in as many lines as possible
+   * either before eof or socket timeout occurs on the operation.
+   * With SMTP we can tell if we have more lines to read if the
+   * 4th character is '-' symbol. If it is a space then we don't
+   * need to read anything else.
+   * @access private
+   * @return string
+   */
+  private function get_lines() {
+    $data = "";
+    while($str = @fgets($this->smtp_conn,515)) {
+      if($this->do_debug >= 4) {
+        echo "SMTP -> get_lines(): \$data was \"$data\"" . $this->CRLF . '<br />';
+        echo "SMTP -> get_lines(): \$str is \"$str\"" . $this->CRLF . '<br />';
+      }
+      $data .= $str;
+      if($this->do_debug >= 4) {
+        echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF . '<br />';
+      }
+      // if 4th character is a space, we are done reading, break the loop
+      if(substr($str,3,1) == " ") { break; }
+    }
+    return $data;
+  }
+
+}
+
+?>

+ 90 - 0
include/View.php

@@ -0,0 +1,90 @@
+<?php
+if(!isset($ajaxbool))$ajaxbool = $rock->jm->gettoken('ajaxbool', 'false');
+$ajaxbool	= $rock->get('ajaxbool', $ajaxbool);
+$p			= PROJECT;
+if(!isset($m))$m='index';
+if(!isset($a))$a='default';
+if(!isset($d))$d='';
+$m			= $rock->get('m', $m);
+$a			= $rock->get('a', $a);
+$d			= $rock->get('d', $d);
+
+define('M', $m);
+define('A', $a);
+define('D', $d);
+define('P', $p);
+
+$_m			= $m;
+if($rock->contain($m, '|')){
+	$_mas 	= explode('|', $m);
+	$m 		= $_mas[0];
+	$_m		= $_mas[1];
+}
+include_once($rock->strformat('?0/?1/?1Action.php',ROOT_PATH, $p));
+$rand		= date('YmdHis').rand(1000,9999);
+if(substr($d,-1)!='/' && $d!='')$d.='/';
+$errormsg	= '';
+$methodbool	= true;
+$actpath	= $rock->strformat('?0/?1/?2?3',ROOT_PATH, $p, $d, $_m);
+define('ACTPATH', $actpath);
+$actfile	= $rock->strformat('?0/?1Action.php',$actpath, $m);
+$actfile1	= $rock->strformat('?0/?1Action.php',$actpath, $_m);
+$actbstr 	= null;
+if(file_exists($actfile1))include_once($actfile1);
+if(file_exists($actfile)){
+	include_once($actfile);
+	$clsname	= ''.$m.'ClassAction';
+	$xhrock		= new $clsname();
+	$actname	= ''.$a.'Action';
+	if($ajaxbool == 'true')$actname	= ''.$a.'Ajax';
+	if(method_exists($xhrock, $actname)){
+		$xhrock->beforeAction();
+		$actbstr = $xhrock->$actname();
+		$xhrock->bodyMessage = $actbstr;
+		if(is_string($actbstr)){echo $actbstr;$xhrock->display=false;}
+		if(is_array($actbstr)){echo json_encode($actbstr);$xhrock->display=false;}
+	}else{
+		$methodbool = false;
+		if($ajaxbool == 'false')echo ''.$actname.' not found;';
+	}
+	$xhrock->afterAction();
+}else{
+	echo 'actionfile not exists;';
+	$xhrock		= new Action();
+}
+
+$_showbool = false;
+if($xhrock->display && ($ajaxbool == 'html' || $ajaxbool == 'false')){
+	$xhrock->smartydata['p']	= $p;
+	$xhrock->smartydata['a']	= $a;
+	$xhrock->smartydata['m']	= $m;
+	$xhrock->smartydata['d']	= $d;
+	$xhrock->smartydata['rand']	= $rand;
+	$xhrock->smartydata['qom']	= QOM;
+	$xhrock->smartydata['path']	= PATH;
+	$xhrock->smartydata['sysurl']= SYSURL;
+	$temppath					= ''.ROOT_PATH.'/'.$p.'/';
+	$tplpaths					= ''.$temppath.''.$d.''.$m.'/';
+	$tplname					= 'tpl_'.$m.'';
+	if($a!='default')$tplname  .= '_'.$a.'';
+	$tplname				   .= '.'.$xhrock->tpldom.'';
+	$mpathname					= $tplpaths.$tplname;
+	if($xhrock->displayfile!='' && file_exists($xhrock->displayfile))$mpathname = $xhrock->displayfile;
+	if(!file_exists($mpathname) || !$methodbool){
+		if(!$methodbool){
+			$errormsg	= 'in ('.$m.') not found Method('.$a.');';
+		}else{
+			$errormsg	= ''.$tplname.' not exists;';
+		}
+		echo $errormsg;
+	}else{
+		$_showbool = true;
+	}
+}
+if($xhrock->display && ($ajaxbool == 'html' || $xhrock->tpltype=='html' || $ajaxbool == 'false') && $_showbool){
+	$xhrock->setHtmlData();
+	$da = $xhrock->smartydata;
+	foreach($xhrock->assigndata as $_k=>$_v)$$_k=$_v;
+	include_once($mpathname);
+	$_showbool = false;
+}

+ 98 - 0
include/chajian/JPushChajian.php

@@ -0,0 +1,98 @@
+<?php 
+/**
+* 	最新系统推送1.9.7后
+*	软件:信呼OA
+*	最后更新:2021-10-09
+*/
+class JPushChajian extends Chajian{
+
+
+	//-------------最新原生app推送app是1.2.3版本 和 最新app+---------------
+	public function push($title, $desc, $cont, $palias)
+	{
+		
+		$alias		= $palias['alias'];
+		$xmalias	= $palias['xmalias']; //小米的
+		$newalias	= $palias['newalias']; //最新使用的
+		$oldalias	= $palias['oldalias']; //一般自己编译
+		$uids		= $palias['uids'];
+		$alias2019	= $palias['alias2019'];
+		$pushuids	= $palias['pushuids']; //可以推送的用户ID
+		$xmpush		= c('xmpush');
+		$hwpush		= c('hwpush');
+		
+		//可推送判断
+		$ketualia	= array();
+		foreach($alias2019 as $ali1){
+			$ali1aa = explode('|', $ali1);
+			$_uid	= $ali1aa[2];
+			if(in_array($_uid, $pushuids))$ketualia[] = $ali1;
+		}
+		$alias2019 = $ketualia;
+		
+		
+		//$this->rock->debugs($palias,'pushalias');//判断能不能推送,打印这个
+		
+		$xharr = array(
+			'uids'  => $uids,
+			'title' => $this->rock->jm->base64encode($title),
+			'cont'  => $this->rock->jm->base64encode($cont),
+			'desc'  => $desc,
+			'systype'=> getconfig('systype')
+		);
+		$isuguanw 	= false;
+		
+
+		//没有设置推送(走的信呼官网渠道)
+		if(!$xmpush->sendbool() && !$hwpush->sendbool()){
+			if($xmalias || $newalias || $oldalias || $alias2019){
+				if($xmalias)$xharr['xmalias'] 		= join(',', $xmalias);
+				if($newalias)$xharr['newalias'] 	= join(',', $newalias);
+				if($oldalias)$xharr['oldalias'] 	= join(',', $oldalias);
+				if($alias2019)$xharr['alias2019']	= join(',', $alias2019);
+				$isuguanw = true;
+			}
+		}else{
+			$desc = $this->rock->jm->base64decode($desc);
+			$xmarr = array();//小米的人员
+			$othar = array();//其他人用
+			$iosar = array(); //IOS
+			$hwarr = array(); //华为
+			$iospas= array();
+			if($alias2019)foreach($alias2019 as $ali1){
+				$ali1aa = explode('|', $ali1);
+				$regid  = $ali1aa[0];
+				$sjlxx  = $ali1aa[1];
+				if(contain($sjlxx,'xiaomi')){
+					$xmarr[] = $regid;
+				}else if(contain($sjlxx,'huawei')){
+					if(isset($ali1aa[3]) && $ali1aa[3])$hwarr[] = $ali1aa[3];
+				}else if(contain($sjlxx,'iphone')){	
+					$iosar[] = $regid;
+					$iospas[]= $ali1;
+				}else{
+					$othar[] = $regid;
+				}
+			}
+			$msg = $msg1 = $msg2 = '';
+			if($oldalias)$msg = $xmpush->androidsend($oldalias, $title, $desc, $cont);
+			if($xmarr)$msg = $xmpush->androidsend($xmarr, $title, $desc);
+			if($iosar){
+				if(!$xmpush->jpushiosbool()){
+					$xharr['alias2019']	= join(',', $iospas);
+					$isuguanw = true;	
+				}else{
+					$msg1= $xmpush->jpushiossend($iosar, $title, $desc);
+				}
+			}
+			if($hwarr)$msg2= $hwpush->androidsend($hwarr, $title, $desc);
+			$msg5 = $msg.$msg1.$msg2;
+			if($msg5)$this->rock->debugs($msg5,'mypush');
+		}
+		
+		if($isuguanw){
+			$runurl = c('xinhu')->geturlstr('jpushplat', $xharr);
+			c('curl')->getcurl($runurl);
+		}
+	}
+}

+ 383 - 0
include/chajian/PHPExcelChajian.php

@@ -0,0 +1,383 @@
+<?php 
+/**
+*	PHPExcel类
+*/
+class PHPExcelChajian extends Chajian{
+	
+	public  $excel				= null;
+	public  $sheetObj;
+	public	$headlen			= 0;
+
+	public  $headbgcolor		= 'CDF79E';
+	public  $bordercolor		= '000000';
+	public  $headfontcolor		= '';
+	public	$headfontbold		= false;
+	public 	$borderbool			= true;
+	
+	public 	$title				= '';
+	public 	$titlebool			= true;
+	public 	$titlebgbool		= false;
+	
+	public 	$sheettitle			= '';
+	public 	$headArr			= array();
+	public 	$rows				= array();
+	
+	
+	public 	$titleboolArray		= array();
+	public  $titleArray			= array();
+	public  $headArrArray		= array();
+	public  $rowsArray			= array();
+	
+	public  $pageCode			= 'utf-8';
+	public  $code				= 'utf-8';
+	public 	$createbool			= false;
+	
+	public function initChajian()
+	{
+		$this->A	= explode(',','A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR,AS,AT,AU,AV,AW,AX,AY,AZ,BA,BB,BC,BD,BE,BF,BG,BH,BI,BJ,BK,BL,BM,BN,BO,BP,BQ,BR,BS,BT,BU,BV,BW,BX,BY,BZ,CA,CB,CC,CD,CE,CF,CG,CH,CI,CJ,CK,CL,CM,CN,CO,CP,CQ,CR,CS,CT,CU,CV,CW,CX,CY,CZ');
+		$this->headWidth= array();
+		$pastr = ROOT_PATH.'/include/PHPExcel.php';
+		if(file_exists($pastr)){
+			include_once($pastr);
+			$this->excel 	= new PHPExcel();
+		}
+	}
+	
+	public function isBool()
+	{
+		if($this->excel==null){
+			return false;
+		}else{
+			return true;
+		}
+	}
+	
+	/**
+		设置表头
+	*/
+	private function setHead($sheet=0)
+	{
+		$arrh	= $this->headArr;
+		$title	= $this->sheettitle;
+		if($title=='')$title = $this->title;
+		$this->headWidth	 = array();
+		if($sheet>0)$this->excel->createSheet();
+
+		$this->excel->setActiveSheetIndex($sheet);//设置当前的sheet工作簿
+		$this->sheetObj	= $this->excel->getActiveSheet();
+		$this->sheetObj->setTitle($title);//设置sheet的工作簿标题
+
+		$k	= 0;
+		if($sheet == 0){
+			$this->excel->getProperties()->setCreator('rock'); 		//创建者
+			$this->excel->getProperties()->setLastModifiedBy('rock');  //最后修改
+			$this->excel->getProperties()->setTitle('rock');  			//设置标题
+			$this->excel->getProperties()->setSubject('rock');  		//设置备注
+			$this->excel->getProperties()->setDescription('rock');  	//设置描述
+			$this->excel->getProperties()->setKeywords('rock');  		//设置关键字 | 标记
+			$this->excel->getProperties()->setCategory('rock');  		//设置类别
+		}
+		
+		$this->headlen	= -1;
+		foreach($arrh as $_arrh)$this->headlen++;
+		$this->rowslen	= 0;
+		if(is_array($this->rows))$this->rowslen=count($this->rows);//长度
+		if($this->headlen==-1)return false;
+
+		//整体添加边框颜色,居中
+		$zta		= ($this->titlebool)?2:1;
+		$getStyle	= $this->sheetObj->getStyle('A1:'.$this->A[$this->headlen].''.($this->rowslen+$zta).'');
+		$getStyle->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_CENTER);//垂直居中
+		$getStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::VERTICAL_CENTER);//水平居中
+		
+		if($this->borderbool){
+			$getStyle->getBorders()->getAllborders()->setBorderStyle(PHPExcel_Style_Border::BORDER_THIN);//边框
+			if($this->bordercolor!='000000')$getStyle->getBorders()->getAllborders()->getColor()->setARGB('FF'.$this->bordercolor.'');//边框颜色
+		}
+
+		//设置头部标题
+		if($this->titlebool){
+			$this->sheetObj->mergeCells('A1:'.$this->A[$this->headlen].'1');  //合并单元格
+			$this->sheetObj->setCellValue('A1', $title);
+			$this->sheetObj->getRowDimension(1)->setRowHeight(30); //设置行高
+			$getStyle	= $this->sheetObj->getStyle('A1');
+			$getStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
+			$getStyle->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_CENTER);//垂直剧中
+			$getStyle->getFont()->setBold(true);
+			$getStyle->getFont()->setSize(16);
+			//标题背景颜色
+			if($this->titlebgbool){
+				$getStyle->getFill()->setFillType(PHPExcel_Style_Fill::FILL_SOLID);
+				$getStyle->getFill()->getStartColor()->setARGB('FF'.$this->headbgcolor.'');
+			}
+		}
+		
+		//设置表头列标题
+		if($this->headfontbold)$this->sheetObj->getStyle('A'.$zta.':'.$this->A[$this->headlen].''.$zta.'')->getFont()->setBold(true);//标题是否加粗
+		foreach($arrh as $key=>$_arrh){
+			$name			= $_arrh;
+			$xlsfontcolor	= $this->headfontcolor;
+			$xlsbgcolor		= $this->headbgcolor;
+			$xlsbordercolor	= $this->bordercolor;
+			$xlsfontsize	= '';//字体大小
+			$xlswidth		= 0;		//宽度
+			$xlsalign		= 'center';	//对齐方式
+			$xlsbold		= false;	//是否加粗
+			if(is_array($_arrh)){
+				if(isset($_arrh['xlsfontcolor']))$xlsfontcolor=$_arrh['xlsfontcolor'];
+				if(isset($_arrh['xlsbgcolor']))$xlsbgcolor=$_arrh['xlsbgcolor'];
+				if(isset($_arrh['xlsbordercolor']))$xlsbordercolor=$_arrh['xlsbordercolor'];
+				if(isset($_arrh['xlswidth']))$xlswidth=$_arrh['xlswidth'];
+				if(isset($_arrh['xlsalign']))$xlswidth=$_arrh['xlsalign'];
+				if(isset($_arrh['xlsbold']))$xlsbold=$_arrh['xlsbold'];
+				if(isset($_arrh['xlsfontsize']))$xlsfontsize=$_arrh['xlsfontsize'];
+				$name= $_arrh['name'];
+			}
+			$this->headWidth[$key] = array(strlen($name), $xlswidth);	//设置宽度
+			//设置样式
+			$vk	= ''.$this->A[$k].'2';
+			
+			if(!$this->titlebool)$vk = ''.$this->A[$k].'1';
+			$getStyle	= $this->sheetObj->getStyle($vk);
+			
+			//边框
+			if($xlsbordercolor!='000000')$getStyle->getBorders()->getAllborders()->getColor()->setARGB('FF'.$xlsbordercolor.''); 
+				
+			
+			//设置背景色
+			$getStyle->getFill()->setFillType(PHPExcel_Style_Fill::FILL_SOLID);
+			$getStyle->getFill()->getStartColor()->setARGB('FF'.$xlsbgcolor.'');
+			
+			//设置字体颜色加粗,大小
+			if($xlsfontcolor!='')$getStyle->getFont()->getColor()->setARGB('FF'.$xlsfontcolor.'');
+			if($xlsbold)$getStyle->getFont()->setBold(true);
+			if($xlsfontsize!='')$getStyle->getFont()->setSize($xlsfontsize);
+			
+			//设置对齐方式
+			if($xlsalign!='center')$getStyle->getAlignment()->setHorizontal($xlsalign);
+			
+			$this->sheetObj->setCellValue($vk, $name);
+			$k++;
+		}
+	}
+	
+	
+	/**
+		添加数据
+	*/
+	private function setData()
+	{
+		$rows	= $this->rows;
+		if(!is_array($rows))return false;
+		$arrh	= $this->headArr;
+		$zta	= ($this->titlebool)?3:2;
+		//添加数据
+		foreach($rows as $r=>$rs){
+			if(!is_array($rs))continue;
+			$k			= 0;
+			$xlsmerge	= '';
+			$xlsbgcolor	= '';
+			$xua		= $r+$zta;
+			if(isset($rs['xlsmerge']))$xlsmerge=$rs['xlsmerge'];
+			if(isset($rs['xlsbgcolor']))$xlsbgcolor=$rs['xlsbgcolor'];
+			
+			//整行背景色
+			if($xlsbgcolor!=''){
+				$this->sheetObj->getStyle('A'.$xua.':'.$this->A[$this->headlen].''.$xua.'')
+				->getFill()->setFillType(PHPExcel_Style_Fill::FILL_SOLID)
+				->getStartColor()->setARGB('FF'.$xlsbgcolor.'');
+			}
+			
+			//判断是否有合并单元格的(A:D)
+			if($xlsmerge!=''){
+				$ncta	= explode(':',$xlsmerge);
+				$this->sheetObj->mergeCells(''.$ncta[0].''.$xua.':'.$ncta[1].''.$xua.'');
+			}
+			
+			foreach($arrh as $key=>$_arrh){
+				if(!isset($rs[$key])){
+					$k++;
+					continue;
+				}
+				$vk	= ''.$this->A[$k].''.$xua.'';
+				$xlsfontcolor	= $xlsbgcolor = '';
+				$xlsbordercolor	= $this->bordercolor;
+				$xlsunderline	= '';
+				$xlsfontsize	= '';
+				$xlsalign		= 'center';	//对齐方式
+				$xlsbold		= false;	//是否加粗
+				$xlsitalic		= false;	//是否斜体
+				$val			= $rs[$key];
+				$vallen			= strlen(''.$val.'');
+				if($this->headWidth[$key][0]<$vallen)$this->headWidth[$key][0]=$vallen;
+				if(is_array($_arrh)){
+					if(isset($_arrh['xlsfontcolor']))$xlsfontcolor=$_arrh['xlsfontcolor'];
+					if(isset($_arrh['xlsbgcolor']))$xlsbgcolor=$_arrh['xlsbgcolor'];
+					if(isset($_arrh['xlsbordercolor']))$xlsbordercolor=$_arrh['xlsbordercolor'];
+					if(isset($_arrh['xlsalign']))$xlsalign=$_arrh['xlsalign'];
+				}
+				
+				if(isset($rs['xlsfontcolor']))$xlsfontcolor=$rs['xlsfontcolor'];
+				if(isset($rs['xlsbordercolor']))$xlsbordercolor=$rs['xlsbordercolor'];
+				if(isset($rs['xlsalign']))$xlsalign=$rs['xlsalign'];
+				if(isset($rs['xlsbold']))$xlsbold=$rs['xlsbold'];
+				if(isset($rs['xlsfontsize']))$xlsfontsize=$rs['xlsfontsize'];
+				if(isset($rs['xlsunderline']))$xlsunderline=$rs['xlsunderline'];
+				
+				if(isset($rs[''.$key.'xlsfontcolor']))$xlsfontcolor=$rs[''.$key.'xlsfontcolor'];
+				if(isset($rs[''.$key.'xlsbgcolor']))$xlsbgcolor=$rs[''.$key.'xlsbgcolor'];
+				if(isset($rs[''.$key.'xlsbordercolor']))$xlsbordercolor=$rs[''.$key.'xlsbordercolor'];
+				if(isset($rs[''.$key.'xlsalign']))$xlsalign=$rs[''.$key.'xlsalign'];
+				if(isset($rs[''.$key.'xlsbold']))$xlsbold=$rs[''.$key.'xlsbold'];
+				if(isset($rs[''.$key.'xlsfontsize']))$xlsfontsize=$rs[''.$key.'xlsfontsize'];
+				if(isset($rs[''.$key.'xlsitalic']))$xlsitalic=$rs[''.$key.'xlsitalic'];
+				if(isset($rs[''.$key.'xlsunderline']))$xlsunderline=$rs[''.$key.'xlsunderline'];
+				
+				$getStyle	= $this->sheetObj->getStyle($vk);
+				//设置背景色
+				if($xlsbgcolor!=''){
+					$getStyle->getFill()->setFillType(PHPExcel_Style_Fill::FILL_SOLID);
+					$getStyle->getFill()->getStartColor()->setARGB('FF'.$xlsbgcolor.'');
+				}
+				
+				//字体颜色
+				if($xlsfontcolor!='')$getStyle->getFont()->getColor()->setARGB('FF'.$xlsfontcolor.'');
+				if($xlsbold)$getStyle->getFont()->setBold(true);
+				if($xlsitalic)$getStyle->getFont()->setItalic(true);//斜体
+				if($xlsfontsize!='')$getStyle->getFont()->setSize($xlsfontsize);
+				if($xlsunderline!='')$getStyle->getFont()->setUnderline($xlsunderline);//下划线情况double,双下划线、doubleAccounting,整个单元格双下划线、single,单下划线、singleAccounting,整个单元格单下划线
+				
+				//设置边框颜色
+				if($xlsbordercolor!='000000')$getStyle->getBorders()->getAllborders()->getColor()->setARGB('FF'.$xlsbordercolor.''); 
+				
+				//对齐方式
+				if($xlsalign!='center')$getStyle->getAlignment()->setHorizontal($xlsalign);
+				
+				$this->sheetObj->setCellValue($vk, $val);
+				$k++;
+			}
+			
+			//设置行高
+			$xlsrowheight	= 0;
+			if(isset($rs['xlsrowheight']))$xlsrowheight=$rs['xlsrowheight'];
+			if($xlsrowheight != 0)$this->sheetObj->getRowDimension($r+$zta)->setRowHeight($xlsrowheight); 
+		}
+	}
+	
+	/**
+		设置列宽
+	*/
+	private function setColwidth()
+	{
+		$k=0;
+		foreach($this->headWidth as $key=>$v){
+			$w	= $v[1];
+			if($w<=0){
+				$w= $v[0] * 1.2;
+			}else{
+				$w= $w/70*12;
+			}
+			if($w>0)$this->sheetObj->getColumnDimension($this->A[$k])->setWidth($w);
+			$k++;
+		}		
+	}
+
+	/**
+		创建数据
+	*/
+	public function createData()
+	{
+		$len1	= count($this->titleArray);
+		$len2	= count($this->headArrArray);
+		$len3	= count($this->rowsArray);
+		
+		if($len1==$len2 && $len2==$len3 && $len1>0){
+			for($i=0; $i<$len1; $i++){
+				$this->sheettitle	= $this->titleArray[$i];
+				$this->headArr		= $this->headArrArray[$i];
+				$this->rows			= $this->rowsArray[$i];
+				$this->titlebool	= true;
+				if(isset($this->titleboolArray[$i]))$this->titlebool=$this->titleboolArray[$i];
+				
+				$this->setHead($i);
+				$this->setData();
+				$this->setColwidth();
+			}
+			$this->excel->setActiveSheetIndex(0);
+		}else{
+			$this->setHead(0);
+			$this->setData();
+			$this->setColwidth();
+		}
+		$this->createbool	= true;
+	}
+	
+	/**
+		输出显示
+		@param	string  $ext   	输出类型 xls,xlsx
+		@param	string  $type   是否直接下载
+		@return string 文件名
+	*/
+	public function display($ext='xls', $type='down')
+	{
+		if(!$this->createbool){
+			$this->createData();
+		}
+		
+		$title	= $this->title;
+
+		//有随机数
+		$rand		= '';
+		if(contain($type,'rand'))$rand	= date('YmdHis');
+		$filename	= ''.$title.''.$rand.'.'.$ext.'';
+
+		//输出
+		if($ext!='xlsx'){
+			$objWriter = PHPExcel_IOFactory::createWriter($this->excel, 'Excel5');
+		}else{
+			$objWriter = PHPExcel_IOFactory::createWriter($this->excel, 'Excel2007'); //保存excel—2007格式或者
+		}
+		$backfile = 'down';
+		
+		//保存文件
+		if(contain($type,'savelogs')){
+			$dir	= 'logs';
+			$path	= ''.ROOT_PATH.'/'.UPDIR.'/'.$dir.'/';
+			if(!is_dir($path))mkdir($path);
+			$savefile	= $path.''.$this->iconvstr($filename).'';
+			$objWriter->save($savefile); //是否保存本地
+			$backfile	= ''.UPDIR.'/'.$dir.'/'.$filename.'';
+		}
+		
+		//下载
+		if(contain($type, 'down')){
+			header('Content-type: application/vnd.ms-excel');
+			header('Content-Disposition: attachment; filename="'.iconv('utf-8', 'gbk', $filename).'"');
+			header('Cache-Control: max-age=0');
+			$objWriter->save('php://output');
+		}
+		
+		return $backfile;
+	}
+	
+	
+	/**
+		编码转化
+	*/	
+	private function iconvstr($str)
+	{
+		if($this->pageCode=='utf-8')$str	= iconv('utf-8', 'gbk', $str);
+		return $str;
+	}
+	
+	
+	/**
+		合并单元格
+	*/
+	public function mergeCells($cel1, $cel2, $val=null, $sheet=-1)
+	{
+		if($sheet != -1)$this->excel->setActiveSheetIndex($sheet);
+		$this->excel->getActiveSheet()->mergeCells(''.$cel1.':'.$cel2.'');
+		if($val != null)$this->sheetObj->setCellValue($cel1, $val);
+	}
+}                         

+ 65 - 0
include/chajian/PHPExcelReaderChajian.php

@@ -0,0 +1,65 @@
+<?php 
+/**
+*	PHPExcel 读取插件类
+*/
+class PHPExcelReaderChajian extends Chajian{
+	
+	public $A;
+	public $AT;
+	
+	protected function initChajian()
+	{
+		$this->Astr	= 'A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR,AS,AT,AU,AV,AW,AX,AY,AZ,BA,BB,BC,BD,BE,BF,BG,BH,BI,BJ,BK,BL,BM,BN,BO,BP,BQ,BR,BS,BT,BU,BV,BW,BX,BY,BZ,CA,CB,CC,CD,CE,CF,CG,CH,CI,CJ,CK,CL,CM,CN,CO,CP,CQ,CR,CS,CT,CU,CV,CW,CX,CY,CZ';
+		$this->A	= explode(',', $this->Astr);
+		$this->AT	= array('A'=>0,'B'=>1,'C'=>2,'D'=>3,'E'=>4,'F'=>5,'G'=>6,'H'=>7,'I'=>8,'J'=>9,'K'=>10,'L'=>11,'M'=>12,'N'=>13,'O'=>14,'P'=>15,'Q'=>16,'R'=>17,'S'=>18,'T'=>19,'U'=>20,'V'=>21,'W'=>22,'X'=>23,'Y'=>24,'Z'=>25,'AA'=>26,'AB'=>27,'AC'=>28,'AD'=>29,'AE'=>30,'AF'=>31,'AG'=>32,'AH'=>33,'AI'=>34,'AJ'=>35,'AK'=>36,'AL'=>37,'AM'=>38,'AN'=>39,'AO'=>40,'AP'=>41,'AQ'=>42,'AR'=>43,'AS'=>44,'AT'=>45,'AU'=>46,'AV'=>47,'AW'=>48,'AX'=>49,'AY'=>50,'AZ'=>51,'BA'=>52,'BB'=>53,'BC'=>54,'BD'=>55,'BE'=>56,'BF'=>57,'BG'=>58,'BH'=>59,'BI'=>60,'BJ'=>61,'BK'=>62,'BL'=>63,'BM'=>64,'BN'=>65,'BO'=>66,'BP'=>67,'BQ'=>68,'BR'=>69,'BS'=>70,'BT'=>71,'BU'=>72,'BV'=>73,'BW'=>74,'BX'=>75,'BY'=>76,'BZ'=>77,'CA'=>78,'CB'=>79,'CC'=>80,'CD'=>81,'CE'=>82,'CF'=>83,'CG'=>84,'CH'=>85,'CI'=>86,'CJ'=>87,'CK'=>88,'CL'=>89,'CM'=>90,'CN'=>91,'CO'=>92,'CP'=>93,'CQ'=>94,'CR'=>95,'CS'=>96,'CT'=>97,'CU'=>98,'CV'=>99,'CW'=>100,'CX'=>101,'CY'=>102,'CZ'=>103);
+	}
+	
+	public function reader($filePath=null, $index=2)
+	{
+		if(file_exists(ROOT_PATH.'/include/PHPExcel/Reader/Excel2007.php'))include_once(ROOT_PATH.'/include/PHPExcel/Reader/Excel2007.php');
+if(file_exists(ROOT_PATH.'/include/PHPExcel/Reader/Excel5.php'))include_once(ROOT_PATH.'/include/PHPExcel/Reader/Excel5.php');
+		$help = c('xinhu')->helpstr('phpexcel');
+		if(!class_exists('PHPExcel_Reader_Excel2007'))return '没有安装PHPExcel插件'.$help.'';
+		if($filePath==null)$filePath = $_FILES['file']['tmp_name'];
+		$PHPReader = new PHPExcel_Reader_Excel2007();
+		if(!$PHPReader->canRead($filePath)){
+			$PHPReader = new PHPExcel_Reader_Excel5();
+			if(!$PHPReader->canRead($filePath)){
+				return '不是正规的Excel文件'.$help.'';
+			}
+		}
+		
+		$PHPExcel 	= $PHPReader->load($filePath);
+		$rows		= array();
+		$sheet 		= $PHPExcel->getSheet(0); //第一个表
+		$allColumn 	= $sheet->getHighestColumn();
+		$allRow 	= $sheet->getHighestRow();
+		$allCell	= $this->AT[$allColumn];
+
+		for($row = $index; $row <= $allRow; $row++){
+			$arr = array();	
+			for($cell= 0; $cell<= $allCell; $cell++){
+				$val = $sheet->getCellByColumnAndRow($cell, $row)->getValue();
+				$arr[$this->A[$cell]] = $val;
+			}
+			$rows[] = $arr;
+		}
+		
+		return $rows;
+	}
+	
+	/**
+		导入到表
+	*/
+	public function importTable($table, $rows, $fields)
+	{
+		
+	}
+	
+	public function ExcelToDate($lx, $val)
+	{
+		if($lx=='date')$lx = 'Y-m-d';
+		if($lx=='datetime')$lx = 'Y-m-d H:i:s';
+		return date($lx, PHPExcel_Shared_Date::ExcelToPHP($val)-8*3600);
+	}
+}                         

+ 69 - 0
include/chajian/PHPWordChajian.php

@@ -0,0 +1,69 @@
+<?php 
+/**
+*	PHPWord类
+*/
+
+class PHPWordChajian extends Chajian{
+	
+	private $vendorbool=false;
+	
+	protected function initChajian()
+	{
+		$path = ''.ROOT_PATH.'/include/vendor/autoload.php';
+		if(file_exists($path)){
+			require_once($path);
+			$this->vendorbool = true;
+		}
+	}
+	
+	public function isbool()
+	{
+		return $this->vendorbool;
+	}
+	
+	public function test()
+	{
+		if(!$this->vendorbool)return;
+		
+		\PhpOffice\PhpWord\Settings::loadConfig();
+		
+		\PhpOffice\PhpWord\Settings::setPdfRenderer(\PhpOffice\PhpWord\Settings::PDF_RENDERER_DOMPDF, ''.ROOT_PATH.'/include/vendor/dompdf/dompdf');
+		\PhpOffice\PhpWord\Settings::setOutputEscapingEnabled(true);
+		
+		$languageEnGb = new \PhpOffice\PhpWord\Style\Language(\PhpOffice\PhpWord\Style\Language::EN_GB);
+
+		$phpWord = new \PhpOffice\PhpWord\PhpWord();
+		$phpWord->getSettings()->setThemeFontLang($languageEnGb);
+		
+		
+		$section = $phpWord->addSection();
+		// Adding Text element to the Section having font styled by default...
+		$section->addText(
+			'"Learn from yesterday, live for today, hope for tomorrow. '
+				. 'The important thing is信呼 not to stop questioning." '
+				. '(Albert Einstein)'
+		);
+		//$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007');
+		//$objWriter->save('wfewew.docx');
+		$phpWord->save('helloWorld'.time().'.pdf','PDF');
+		
+		
+		
+	}
+	
+	/**
+	*	只能替换.docx
+	*/
+	public function replaceWord($path, $data=array(), $npath='')
+	{
+		if(!$this->vendorbool)return returnerror('未安装插件');
+		
+		$PhpWord = new \PhpOffice\PhpWord\TemplateProcessor($path);
+		foreach($data as $k=>$v)$PhpWord->setValue($k, $v);
+
+		if($npath=='')$npath = str_replace('.docx',''.rand(1000,9999).'.docx', $path);
+		$PhpWord->saveAs($npath);
+		
+		return returnsuccess($npath);
+	}
+}                         

+ 180 - 0
include/chajian/alismsChajian.php

@@ -0,0 +1,180 @@
+<?php
+/**
+*	阿里云短信服务api
+*/
+class alismsChajian extends Chajian{
+	
+	private $accesskeyid;
+	private $accesskeysecret;
+	
+	protected function initChajian()
+	{
+		$this->accesskeyid 		= getconfig('alisms_keyid');
+		$this->accesskeysecret 	= getconfig('alisms_keysecret');
+	}
+	
+	/**
+	*	批量发送短信
+	*/
+	public function send($mobiles, $qianm, $tplid, $cans=array())
+	{
+		if(isempt($this->accesskeyid) || isempt($this->accesskeysecret))return returnerror('没有设置短信keyid或keysecret');
+		
+		if(isempt($qianm))return returnerror('请设置短信签名');
+		if(isempt($tplid) || substr($tplid,0,4) != 'SMS_')return returnerror('短信模版CODE格式有误');
+		
+		$mbarr = $this->getTplcont($tplid);
+		if(!$mbarr['success'])return $mbarr;
+		$tplcont = $mbarr['data']['TemplateContent'];
+		
+		if(isset($cans['url']))$cans['url'] = c('xinhuapi')->urlsmall($cans['url']); //如果有短域名用这个生成,不要就删掉这行
+		
+		//把没用参数删掉
+		$csarr	= $this->rock->matcharr($tplcont);
+		foreach($csarr as $cs1)if(!isset($cans[$cs1]))return returnerror('模版里有{'.$cs1.'}参数,发送必须传');
+		foreach($cans as $k1=>$v1)if(!in_array($k1, $csarr))unset($cans[$k1]);
+		
+		
+		$params = array();
+		$shoujha= explode(',', $mobiles);
+		$params["PhoneNumberJson"] 	= $shoujha;
+		$params["TemplateCode"] 	=  $tplid;
+		
+		foreach($shoujha as $smid){
+			$params["SignNameJson"][] 		= $qianm;
+			if($cans)$params["TemplateParamJson"][] 	= $cans;
+		}
+	
+		if($cans)$params["TemplateParamJson"]  = json_encode($params["TemplateParamJson"], JSON_UNESCAPED_UNICODE);
+		$params["SignNameJson"] 		= json_encode($params["SignNameJson"], JSON_UNESCAPED_UNICODE);
+		$params["PhoneNumberJson"] 	= json_encode($params["PhoneNumberJson"], JSON_UNESCAPED_UNICODE);
+		
+		$helper 	= new SignatureHelper();
+		$result 	= $helper->request(
+			$this->accesskeyid,
+			$this->accesskeysecret,
+			'dysmsapi.aliyuncs.com',
+			array_merge($params, array(
+				"RegionId" => "cn-hangzhou",
+				"Action" => "SendBatchSms",
+				"Version" => "2017-05-25",
+			))
+		);
+		if(!$result)return returnerror('发送失败');
+		$barr	= json_decode($result, true);
+		if($barr['Code']=='OK')return returnsuccess($barr);
+		return returnerror('发送失败:'.$result.'');
+	}
+	
+	public function getTplcont($tplid)
+	{
+		$num = 'alisms_'.$tplid.'';
+		$val = m('option')->getval($num);
+		if(!isempt($val)){
+			return returnsuccess(array('TemplateContent'=>$val));
+		}
+		if(isempt($this->accesskeyid) || isempt($this->accesskeysecret))return returnerror('没有设置短信keyid或keysecret');
+		$helper 	= new SignatureHelper();
+		$params['TemplateCode'] = $tplid;
+		$result 	= $helper->request(
+			$this->accesskeyid,
+			$this->accesskeysecret,
+			'dysmsapi.aliyuncs.com',
+			array_merge($params, array(
+				"RegionId" => "cn-hangzhou",
+				"Action" => "QuerySmsTemplate",
+				"Version" => "2017-05-25",
+			))
+		);
+		if(!$result)return returnerror('获取模版失败'.$tplid.'');
+		$barr	= json_decode($result, true);
+		if($barr['Code']=='OK'){
+			m('option')->setval($num, $barr['TemplateContent']);
+			return returnsuccess($barr);
+		}
+		return returnerror('获取失败:'.$result.'');
+	}
+}
+
+/**
+ * 签名助手 2017/11/19
+ *
+ * Class SignatureHelper
+ */
+class SignatureHelper {
+
+    /**
+     * 生成签名并发起请求
+     *
+     * @param $accessKeyId string AccessKeyId (https://ak-console.aliyun.com/)
+     * @param $accessKeySecret string AccessKeySecret
+     * @param $domain string API接口所在域名
+     * @param $params array API具体参数
+     * @param $security boolean 使用https
+     * @return bool|\stdClass 返回API接口调用结果,当发生错误时返回false
+     */
+    public function request($accessKeyId, $accessKeySecret, $domain, $params, $security=false) {
+        $apiParams = array_merge(array (
+            "SignatureMethod" => "HMAC-SHA1",
+            "SignatureNonce" => uniqid(mt_rand(0,0xffff), true),
+            "SignatureVersion" => "1.0",
+            "AccessKeyId" => $accessKeyId,
+            "Timestamp" => gmdate("Y-m-d\TH:i:s\Z"),
+            "Format" => "JSON",
+        ), $params);
+        ksort($apiParams);
+
+        $sortedQueryStringTmp = "";
+        foreach ($apiParams as $key => $value) {
+            $sortedQueryStringTmp .= "&" . $this->encode($key) . "=" . $this->encode($value);
+        }
+
+        $stringToSign = "GET&%2F&" . $this->encode(substr($sortedQueryStringTmp, 1));
+
+        $sign = base64_encode(hash_hmac("sha1", $stringToSign, $accessKeySecret . "&",true));
+
+        $signature = $this->encode($sign);
+
+        $url = ($security ? 'https' : 'http')."://{$domain}/?Signature={$signature}{$sortedQueryStringTmp}";
+
+        try {
+            $content = $this->fetchContent($url);
+            return $content;
+        } catch( \Exception $e) {
+            return false;
+        }
+    }
+
+    private function encode($str)
+    {
+        $res = urlencode($str);
+        $res = preg_replace("/\+/", "%20", $res);
+        $res = preg_replace("/\*/", "%2A", $res);
+        $res = preg_replace("/%7E/", "~", $res);
+        return $res;
+    }
+
+    private function fetchContent($url) {
+        $ch = curl_init();
+        curl_setopt($ch, CURLOPT_URL, $url);
+        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
+            "x-sdk-client" => "php/2.0.0"
+        ));
+
+        if(substr($url, 0,5) == 'https') {
+            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
+        }
+
+        $rtn = curl_exec($ch);
+
+        if($rtn === false) {
+            trigger_error("[CURL_" . curl_errno($ch) . "]: " . curl_error($ch), E_USER_ERROR);
+        }
+        curl_close($ch);
+
+        return $rtn;
+    }
+}

+ 95 - 0
include/chajian/arrayChajian.php

@@ -0,0 +1,95 @@
+<?php 
+/**
+	数组操作
+*/
+class arrayChajian extends Chajian{
+	/**
+		二维数组排序
+	*/
+	public function order($arr, $field, $tyee='desc')
+	{
+		$temp_a = array();
+		foreach ($arr as $arrs) {
+			$temp_a[] = $arrs[$field];
+		}
+		$tyee	= strtolower($tyee);
+		if($tyee == 'desc'){
+			array_multisort($temp_a, SORT_DESC, $arr);
+		}else{
+			array_multisort($temp_a, SORT_ASC, $arr);
+		}
+		return $arr;
+	}
+	
+	/**
+		转换为用数字做的键值
+	*/
+	public function tonumarray($arr, $otarr='')
+	{
+		$varr=array();
+		if(is_array($otarr))$varr[]=$otarr;
+		if(is_array($arr)){
+			foreach($arr as $da){
+				$key = array_keys($da);
+				$zarr=array();
+				for($i=0;$i<count($key);$i++)$zarr[$i]=$da[$key[$i]];
+				$varr[]=$zarr;
+			}			
+		}
+		return $varr;
+	}
+	
+	/**
+		$str  转化为 数组 0|昨天,2|d
+	*/
+	public function strtoarray($str)
+	{
+		$a	= explode(',', $str);
+		$arr= array();
+		foreach($a as $a1){
+			$a2	= explode('|', $a1);
+			$k 	= $a2[0];
+			$v 	= $a2[0];
+			$c	= '';
+			if(isset($a2[1]))$v = $a2[1];
+			if(isset($a2[2]))$c = $a2[2];
+			$arr[] = array($k, $v, $c);
+		}
+		return $arr;
+	}
+	
+	/**
+		$str  转化为 数组对象 0|昨天,2|d
+	*/
+	public function strtoobject($str)
+	{
+		$rowa = $this->strtoarray($str);
+		$arr  = array();
+		foreach($rowa as $k=>$rs){
+			$arr[$rs[0]] = $rs[1];
+		}
+		return $arr;
+	}
+	
+	/**
+		[{}]数组转化为{ke1:ke2}
+	*/
+	public function arrrytoobject($arr, $lx=0)
+	{
+		$rows = array();
+		foreach($arr as $k=>$da){
+			$karr 	= array_keys($da);
+			$key	= $da[$karr[0]];
+			$nav	= $key;
+			if(count($karr)>1){
+				$nav = $da[$karr[1]];
+			}
+			if($lx == 1){
+				$rows[$key] = $da;
+			}else{
+				$rows[$key] = $nav;
+			}
+		}
+		return $rows;
+	}
+}                                                                                                                                                            

+ 123 - 0
include/chajian/cacheChajian.php

@@ -0,0 +1,123 @@
+<?php 
+/**
+*	缓存,目前是使用磁盘文件存储
+*/
+class cacheChajian extends Chajian{
+	
+	private $dirvie = 'file'; //redis,file
+	
+	/**
+	*	设置缓存
+	* 	$time 缓存时间(秒)
+	*/
+	public function set($key, $data, $time=0)
+	{
+		$this->del($key); //删除原来的
+		$sarr['key']  = $this->getkey($key);
+		$sarr['data'] = $data;
+		if($time>0){
+			$time = time()+$time;
+		}else{
+			$time = 0;
+		}
+		$sarr['time'] = $time;
+		if($time>0)$sarr['timedt'] = date('Y-m-d H:i:s', $time);
+		$sarr['url']  = $this->rock->nowurl();
+		$this->delexpire();
+		return $this->rock->createtxt($this->getpath($key, $time, 1), json_encode($sarr));
+	}
+	
+	private function getkey($key)
+	{
+		return ''.QOM.''.$key.'';
+	}
+	
+	private function getpath($key, $time=0, $lx=0)
+	{
+		$key = $this->getkey($key);
+		$ske = '';
+		if($time>0)$ske='_'.$time.'';
+		
+		if($lx==0)return ''.ROOT_PATH.'/'.UPDIR.'/cache/'.md5($key).''.$ske.'';
+		return ''.UPDIR.'/cache/'.md5($key).''.$ske.'';
+	}
+	
+	//获取文件名
+	private function getpaths($key)
+	{
+		$key = $this->getkey($key);
+		$file= ''.ROOT_PATH.'/'.UPDIR.'/cache/'.md5($key).'';
+		$bar = glob(''.$file.'*');
+		if(is_array($bar))foreach($bar as $k=>$fil1){
+			if($k==0){
+				$file = $fil1;
+			}else{
+				unlink($fil1);
+			}
+		}
+		return $file;
+	}
+	
+	/**
+	*	获取缓存
+	*/
+	public function get($key, $dev='')
+	{
+		$file= $this->getpaths($key);
+		$data= $dev;
+		if(file_exists($file)){
+			$filea= explode('_', $file);
+			$time = (int)arrvalue($filea, count($filea)-1,'0');
+			if($time==0 || $time>=time()){
+				$cont = file_get_contents($file);
+				if(!isempt($cont)){
+					$sarr = json_decode($cont, true);
+					$data = arrvalue($sarr, 'data');
+				}
+			}else{
+				unlink($file); //已经过期了
+			}
+		}
+		return $data;
+	}
+	
+	/**
+	*	删除缓存
+	*/
+	public function del($key)
+	{
+		$file= $this->getpaths($key);
+		if(file_exists($file))@unlink($file);
+		return true;
+	}
+	
+	/**
+	*	删除所有缓存
+	*/
+	public function delall()
+	{
+		$bar = glob(''.ROOT_PATH.'/'.UPDIR.'/cache/*');
+		foreach($bar as $k=>$fil1){
+			unlink($fil1);
+		}
+	}
+	
+	/**
+	*	删除过期的缓存
+	*/
+	public function delexpire()
+	{
+		$bar = glob(''.ROOT_PATH.'/'.UPDIR.'/cache/*');
+		$time= time();
+		foreach($bar as $k=>$fil1){
+			if(contain($fil1,'_')){
+				$fil11 = substr($fil1, strripos($fil1, '_')+1);
+				if(is_numeric($fil11)){
+					if($fil11<$time){
+						unlink($fil1);
+					}
+				}
+			}
+		}
+	}
+}                               

+ 247 - 0
include/chajian/calendarChajian.php

@@ -0,0 +1,247 @@
+<?php 
+class calendarChajian extends Chajian{
+
+	//农历每月的天数
+    private $everyCMonth=array(
+    0=>array(8,0,0,0,0,0,0,0,0,0,0,0,29,30,7,1),
+    1=>array(0,29,30,29,29,30,29,30,29,30,30,30,29,0,8,2),
+    2=>array(0,30,29,30,29,29,30,29,30,29,30,30,30,0,9,3),
+    3=>array(5,29,30,29,30,29,29,30,29,29,30,30,29,30,10,4),
+    4=>array(0,30,30,29,30,29,29,30,29,29,30,30,29,0,1,5),
+    5=>array(0,30,30,29,30,30,29,29,30,29,30,29,30,0,2,6),
+    6=>array(4,29,30,30,29,30,29,30,29,30,29,30,29,30,3,7),
+    7=>array(0,29,30,29,30,29,30,30,29,30,29,30,29,0,4,8),
+    8=>array(0,30,29,29,30,30,29,30,29,30,30,29,30,0,5,9),
+    9=>array(2,29,30,29,29,30,29,30,29,30,30,30,29,30,6,10),
+    10=>array(0,29,30,29,29,30,29,30,29,30,30,30,29,0,7,11),
+    11=>array(6,30,29,30,29,29,30,29,29,30,30,29,30,30,8,12),
+    12=>array(0,30,29,30,29,29,30,29,29,30,30,29,30,0,9,1),
+    13=>array(0,30,30,29,30,29,29,30,29,29,30,29,30,0,10,2),
+    14=>array(5,30,30,29,30,29,30,29,30,29,30,29,29,30,1,3),
+    15=>array(0,30,29,30,30,29,30,29,30,29,30,29,30,0,2,4),
+    16=>array(0,29,30,29,30,29,30,30,29,30,29,30,29,0,3,5),
+    17=>array(2,30,29,29,30,29,30,30,29,30,30,29,30,29,4,6),
+    18=>array(0,30,29,29,30,29,30,29,30,30,29,30,30,0,5,7),
+    19=>array(7,29,30,29,29,30,29,29,30,30,29,30,30,30,6,8),
+    20=>array(0,29,30,29,29,30,29,29,30,30,29,30,30,0,7,9),
+    21=>array(0,30,29,30,29,29,30,29,29,30,29,30,30,0,8,10),
+    22=>array(5,30,29,30,30,29,29,30,29,29,30,29,30,30,9,11),
+    23=>array(0,29,30,30,29,30,29,30,29,29,30,29,30,0,10,12),
+    24=>array(0,29,30,30,29,30,30,29,30,29,30,29,29,0,1,1),
+    25=>array(4,30,29,30,29,30,30,29,30,30,29,30,29,30,2,2),
+    26=>array(0,29,29,30,29,30,29,30,30,29,30,30,29,0,3,3),
+    27=>array(0,30,29,29,30,29,30,29,30,29,30,30,30,0,4,4),
+    28=>array(2,29,30,29,29,30,29,29,30,29,30,30,30,30,5,5),
+    29=>array(0,29,30,29,29,30,29,29,30,29,30,30,30,0,6,6),
+    30=>array(6,29,30,30,29,29,30,29,29,30,29,30,30,29,7,7),
+    31=>array(0,30,30,29,30,29,30,29,29,30,29,30,29,0,8,8),
+    32=>array(0,30,30,30,29,30,29,30,29,29,30,29,30,0,9,9),
+    33=>array(5,29,30,30,29,30,30,29,30,29,30,29,29,30,10,10),
+    34=>array(0,29,30,29,30,30,29,30,29,30,30,29,30,0,1,11),
+    35=>array(0,29,29,30,29,30,29,30,30,29,30,30,29,0,2,12),
+    36=>array(3,30,29,29,30,29,29,30,30,29,30,30,30,29,3,1),
+    37=>array(0,30,29,29,30,29,29,30,29,30,30,30,29,0,4,2),
+    38=>array(7,30,30,29,29,30,29,29,30,29,30,30,29,30,5,3),
+    39=>array(0,30,30,29,29,30,29,29,30,29,30,29,30,0,6,4),
+    40=>array(0,30,30,29,30,29,30,29,29,30,29,30,29,0,7,5),
+    41=>array(6,30,30,29,30,30,29,30,29,29,30,29,30,29,8,6),
+    42=>array(0,30,29,30,30,29,30,29,30,29,30,29,30,0,9,7),
+    43=>array(0,29,30,29,30,29,30,30,29,30,29,30,29,0,10,8),
+    44=>array(4,30,29,30,29,30,29,30,29,30,30,29,30,30,1,9),
+    45=>array(0,29,29,30,29,29,30,29,30,30,30,29,30,0,2,10),
+    46=>array(0,30,29,29,30,29,29,30,29,30,30,29,30,0,3,11),
+    47=>array(2,30,30,29,29,30,29,29,30,29,30,29,30,30,4,12),
+    48=>array(0,30,29,30,29,30,29,29,30,29,30,29,30,0,5,1),
+    49=>array(7,30,29,30,30,29,30,29,29,30,29,30,29,30,6,2),
+    50=>array(0,29,30,30,29,30,30,29,29,30,29,30,29,0,7,3),
+    51=>array(0,30,29,30,30,29,30,29,30,29,30,29,30,0,8,4),
+    52=>array(5,29,30,29,30,29,30,29,30,30,29,30,29,30,9,5),
+    53=>array(0,29,30,29,29,30,30,29,30,30,29,30,29,0,10,6),
+    54=>array(0,30,29,30,29,29,30,29,30,30,29,30,30,0,1,7),
+    55=>array(3,29,30,29,30,29,29,30,29,30,29,30,30,30,2,8),
+    56=>array(0,29,30,29,30,29,29,30,29,30,29,30,30,0,3,9),
+    57=>array(8,30,29,30,29,30,29,29,30,29,30,29,30,29,4,10),
+    58=>array(0,30,30,30,29,30,29,29,30,29,30,29,30,0,5,11),
+    59=>array(0,29,30,30,29,30,29,30,29,30,29,30,29,0,6,12),
+    60=>array(6,30,29,30,29,30,30,29,30,29,30,29,30,29,7,1),
+    61=>array(0,30,29,30,29,30,29,30,30,29,30,29,30,0,8,2),
+    62=>array(0,29,30,29,29,30,29,30,30,29,30,30,29,0,9,3),
+    63=>array(4,30,29,30,29,29,30,29,30,29,30,30,30,29,10,4),
+    64=>array(0,30,29,30,29,29,30,29,30,29,30,30,30,0,1,5),
+    65=>array(0,29,30,29,30,29,29,30,29,29,30,30,29,0,2,6),
+    66=>array(3,30,30,30,29,30,29,29,30,29,29,30,30,29,3,7),
+    67=>array(0,30,30,29,30,30,29,29,30,29,30,29,30,0,4,8),
+    68=>array(7,29,30,29,30,30,29,30,29,30,29,30,29,30,5,9),
+    69=>array(0,29,30,29,30,29,30,30,29,30,29,30,29,0,6,10),
+    70=>array(0,30,29,29,30,29,30,30,29,30,30,29,30,0,7,11),
+    71=>array(5,29,30,29,29,30,29,30,29,30,30,30,29,30,8,12),
+    72=>array(0,29,30,29,29,30,29,30,29,30,30,29,30,0,9,1),
+    73=>array(0,30,29,30,29,29,30,29,29,30,30,29,30,0,10,2),
+    74=>array(4,30,30,29,30,29,29,30,29,29,30,30,29,30,1,3),
+    75=>array(0,30,30,29,30,29,29,30,29,29,30,29,30,0,2,4),
+    76=>array(8,30,30,29,30,29,30,29,30,29,29,30,29,30,3,5),
+    77=>array(0,30,29,30,30,29,30,29,30,29,30,29,29,0,4,6),
+    78=>array(0,30,29,30,30,29,30,30,29,30,29,30,29,0,5,7),
+    79=>array(6,30,29,29,30,29,30,30,29,30,30,29,30,29,6,8),
+    80=>array(0,30,29,29,30,29,30,29,30,30,29,30,30,0,7,9),
+    81=>array(0,29,30,29,29,30,29,29,30,30,29,30,30,0,8,10),
+    82=>array(4,30,29,30,29,29,30,29,29,30,29,30,30,30,9,11),
+    83=>array(0,30,29,30,29,29,30,29,29,30,29,30,30,0,10,12),
+    84=>array(10,30,29,30,30,29,29,30,29,29,30,29,30,30,1,1),
+    85=>array(0,29,30,30,29,30,29,30,29,29,30,29,30,0,2,2),
+    86=>array(0,29,30,30,29,30,30,29,30,29,30,29,29,0,3,3),
+    87=>array(6,30,29,30,29,30,30,29,30,30,29,30,29,29,4,4),
+    88=>array(0,30,29,30,29,30,29,30,30,29,30,30,29,0,5,5),
+    89=>array(0,30,29,29,30,29,29,30,30,29,30,30,30,0,6,6),
+    90=>array(5,29,30,29,29,30,29,29,30,29,30,30,30,30,7,7),
+    91=>array(0,29,30,29,29,30,29,29,30,29,30,30,30,0,8,8),
+    92=>array(0,29,30,30,29,29,30,29,29,30,29,30,30,0,9,9),
+    93=>array(3,29,30,30,29,30,29,30,29,29,30,29,30,29,10,10),
+    94=>array(0,30,30,30,29,30,29,30,29,29,30,29,30,0,1,11),
+    95=>array(8,29,30,30,29,30,29,30,30,29,29,30,29,30,2,12),
+    96=>array(0,29,30,29,30,30,29,30,29,30,30,29,29,0,3,1),
+    97=>array(0,30,29,30,29,30,29,30,30,29,30,30,29,0,4,2),
+    98=>array(5,30,29,29,30,29,29,30,30,29,30,30,29,30,5,3),
+    99=>array(0,30,29,29,30,29,29,30,29,30,30,30,29,0,6,4),
+    100=>array(0,30,30,29,29,30,29,29,30,29,30,30,29,0,7,5),
+    101=>array(4,30,30,29,30,29,30,29,29,30,29,30,29,30,8,6),
+    102=>array(0,30,30,29,30,29,30,29,29,30,29,30,29,0,9,7),
+    103=>array(0,30,30,29,30,30,29,30,29,29,30,29,30,0,10,8),
+    104=>array(2,29,30,29,30,30,29,30,29,30,29,30,29,30,1,9),
+    105=>array(0,29,30,29,30,29,30,30,29,30,29,30,29,0,2,10),
+    106=>array(7,30,29,30,29,30,29,30,29,30,30,29,30,30,3,11),
+    107=>array(0,29,29,30,29,29,30,29,30,30,30,29,30,0,4,12),
+    108=>array(0,30,29,29,30,29,29,30,29,30,30,29,30,0,5,1),
+    109=>array(5,30,30,29,29,30,29,29,30,29,30,29,30,30,6,2),
+    110=>array(0,30,29,30,29,30,29,29,30,29,30,29,30,0,7,3),
+    111=>array(0,30,29,30,30,29,30,29,29,30,29,30,29,0,8,4),
+    112=>array(4,30,29,30,30,29,30,29,30,29,30,29,30,29,9,5),
+    113=>array(0,30,29,30,29,30,30,29,30,29,30,29,30,0,10,6),
+    114=>array(9,29,30,29,30,29,30,29,30,30,29,30,29,30,1,7),
+    115=>array(0,29,30,29,29,30,29,30,30,30,29,30,29,0,2,8),
+    116=>array(0,30,29,30,29,29,30,29,30,30,29,30,30,0,3,9),
+    117=>array(6,29,30,29,30,29,29,30,29,30,29,30,30,30,4,10),
+    118=>array(0,29,30,29,30,29,29,30,29,30,29,30,30,0,5,11),
+    119=>array(0,30,29,30,29,30,29,29,30,29,29,30,30,0,6,12),
+    120=>array(4,29,30,30,30,29,30,29,29,30,29,30,29,30,7,1)
+    );
+//农历天干
+    private $mten=array("null","甲","乙","丙","丁","戊","己","庚","辛","壬","癸");    //农历地支
+    private $mtwelve=array("null","子(鼠)","丑(牛)","寅(虎)","卯(兔)","辰(龙)",
+                   "巳(蛇)","午(马)","未(羊)","申(猴)","酉(鸡)","戌(狗)","亥(猪)");    //农历月份
+    private $mmonth=array("闰","正","二","三","四","五","六",
+                  "七","八","九","十","十一","十二","月");
+    private $mday=array("null","初一","初二","初三","初四","初五","初六","初七","初八","初九","初十",
+                "十一","十二","十三","十四","十五","十六","十七","十八","十九","二十",
+                "廿一","廿二","廿三","廿四","廿五","廿六","廿七","廿八","廿九","三十");//农历日
+//赋给初值
+//天干地支
+    private $ten=0;
+    private $twelve=0;
+    private function MyPub($cYear,$cMonth,$cDay)
+    {
+        $total=11;//阳历总天数 至1900年12月21日  
+        $mtotal=0;//阴历总天数
+        for ($y=1901;$y<$cYear;$y++)
+        {
+            $total+=365;
+            if ($y%4==0) $total ++;
+        }
+        //再加当年的几个月
+        switch ($cMonth){
+                 case 12:
+                      $total+=30;
+                 case 11:
+                      $total+=31;
+                 case 10:
+                      $total+=30;
+                 case 9:
+                      $total+=31;
+                 case 8:
+                      $total+=31;
+                 case 7:
+                      $total+=30;
+                 case 6:
+                      $total+=31;
+                 case 5:
+                      $total+=30;
+                 case 4:
+                      $total+=31;
+                 case 3:
+                      $total+=28;
+                 case 2:
+                      $total+=31;
+               }
+ 
+            //如果当年是闰年还要加一天
+            if ($cYear%4==0 and $cMonth>2)
+            {
+                $total++;
+            }
+            $total+=$cDay-1;
+			$flag = 0;
+            //用农历的天数累加来判断是否超过阳历的天数
+            for($j=0;$j<=120;$j++)
+            {
+                $i=1;
+                for($i=1;$i<=13;$i++)
+                {
+                    $mtotal+=$this->everyCMonth[$j][$i];
+                    if ($mtotal>=$total)
+                    {
+                        $flag=1;
+                        break;
+                    }
+                }
+                if ($flag==1)break;
+            }
+                    return array("m"=>$j,"d"=>$i,"t"=>$total,"n"=>$mtotal);
+    }
+    public function Cal($Year,$Month,$Day)
+    {
+        $Par=$this->MyPub($Year,$Month,$Day);
+ 
+        $md=$this->everyCMonth[$Par["m"]][$Par["d"]]-($Par["n"]-$Par["t"]);
+        $week=($Par["t"]+5)%7;
+        if ($this->everyCMonth[$Par["m"]][0]<>0 and $this->everyCMonth[$Par["m"]][0]<$Par["d"])
+        {
+                $mm=$Par["d"]-1;
+        }else{
+                $mm=$Par["d"];
+        }
+        if ($Par["d"]==$this->everyCMonth[$Par["d"]][0]+1 and $this->everyCMonth[$Par["d"]][0]<>0)
+        {
+            $cMonth=$this->mmonth[0].$this->mmonth[$mm];//闰月
+        }else{
+            $cMonth=$this->mmonth[$mm].$this->mmonth[13];
+        }
+		$mmd 	= ($mm<10)?  '0'.$mm.'' : $mm;
+		$mdd 	= ($md<10)?  '0'.$md.'' : $md;
+        return array("year"=>$this->mten[$this->everyCMonth[$Par["m"]][14]].$this->mtwelve[$this->everyCMonth[$Par["m"]][15]],
+                    "month"	=>$cMonth,
+                    "day"	=>$this->mday[$md],
+                    "week"	=>$week,
+                    "m"		=>$mm,
+                    'd'		=>$md,
+					'cal' 	=> ''.$mmd.'-'.$mdd.''
+		);
+    }
+	public function toCalday($dt)
+	{
+		$dts = explode('-', $dt);
+		return $this->Cal((int)$dts[0],(int)$dts[1],(int)$dts[2]);
+	}
+	
+	public function daytocal($dt)
+	{
+		$dts = explode('-', $dt);
+		$mm  = (int)$dts[1];
+		$md  = (int)$dts[2];
+		$my  = (int)$dts[0];
+		return array(
+			'year'	=> $my,
+			'month' => $this->mmonth[$mm],
+			'day' 	=> $this->mday[$md],
+		);
+	}
+}

+ 122 - 0
include/chajian/checkChajian.php

@@ -0,0 +1,122 @@
+<?php 
+/**
+*	字符检查插件
+*/
+
+class checkChajian extends Chajian{
+	
+	/**
+	*	是否为邮箱
+	*/
+	public function isemail($str)
+	{
+		if(isempt($str))return false;
+		return filter_var($str, FILTER_VALIDATE_EMAIL);
+	}
+	
+	/**
+	*	是否为手机号
+	*/
+	public function ismobile($str)
+	{
+		if(isempt($str))return false;
+		if(!is_numeric($str) || strlen($str)<5)return false;
+		return true;
+	}
+	
+	/**
+	*	判断是否为国内手机号
+	*/
+	public function iscnmobile($str)
+	{
+		if(isempt($str))return false;
+		if(!is_numeric($str) || strlen($str)!=11)return false;
+		if(!preg_match("/1[3458769]{1}\d{9}$/", $str))return false;
+		return true;
+	}
+	
+	/**
+	*	是否有中文
+	*/
+	public function isincn($str)
+	{
+		return preg_match("/[\x7f-\xff]/", $str);
+	}
+	
+	//是否整个的英文a-z,0-9
+	public function iszgen($str)
+	{
+		if(isempt($str))return false;
+		if($this->isincn($str)){
+			return false;
+		}
+		return true;
+	}
+	
+	//返回字符串编码
+	public function getencode($str)
+	{
+		$encode = mb_detect_encoding($str, array('ASCII','UTF-8','GB2312','GBK','BIG5'));
+		$encode = strtolower($encode);
+		return $encode;
+	}
+	
+	/**
+	*	是否为数字
+	*/
+	public function isnumber($str)
+	{
+		if(isempt($str))return false;
+		return is_numeric($str);
+	}
+	
+	/**
+	*	字符是否包含数字
+	*/
+	public function isinnumber($str)
+	{
+		return preg_match("/[0-9]/", $str);
+	}
+	
+	/**
+	*	是否为日期
+	*/
+	public function isdate($str)
+	{
+		return preg_match("/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/", $str);
+	}
+	
+	/**
+	*	是否为日期时间
+	*/
+	public function isdatetime($str)
+	{
+		return preg_match("/^([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})$/", $str);
+	}
+	
+	/**
+	*	是否为月份
+	*/
+	public function ismonth($str)
+	{
+		return preg_match("/^([0-9]{4})-([0-9]{2})$/", $str);
+	}
+	
+	/**
+	*	过滤字母,只留数字
+	*/
+	public function onlynumber($str)
+	{
+		return preg_replace('/[a-zA-Z]/','', $str);
+	}
+	
+	/**
+	*	替换空格
+	*/
+	public function replacekg($str)
+	{
+		$str 	= preg_replace('/\s*/', '', $str);
+		$qian	= array(" "," ","\t","\n","\r");
+		return str_replace($qian, '', $str); 
+	}
+}

+ 40 - 0
include/chajian/colorChajian.php

@@ -0,0 +1,40 @@
+<?php 
+/**
+	颜色操作
+*/
+class colorChajian extends Chajian{
+
+	/**
+		颜色
+	*/
+	public function color($color,$l=127.5)
+	{
+		$r=hexdec(substr($color,1,2));
+		$g=hexdec(substr($color,3,2));
+		$b=hexdec(substr($color,5));
+		$yb=127.5;
+		if($l > $yb){
+			$l = $l - $yb;
+			$r = ($r * ($yb - $l) + 255 * $l) / $yb;
+			$g = ($g * ($yb - $l) + 255 * $l) / $yb;
+			$b = ($b * ($yb - $l) + 255 * $l) / $yb;
+		}else{
+			$r = ($r * $l) / $yb;
+			$g = ($g * $l) / $yb;
+			$b = ($b * $l) / $yb;
+		}
+		$nr=$this->tohex($r);
+		$ng=$this->tohex($g);
+		$nb=$this->tohex($b);
+		return '#'.$nr.$ng.$nb;
+	}
+	
+	private function tohex($n)
+	{
+		$hexch = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
+		$n 	= round($n);
+		$l 	= $n % 16;
+		$h 	= floor(($n / 16)) % 16;
+		return ''.$hexch[$h].''.$hexch[$l].'';
+	}
+}

+ 146 - 0
include/chajian/curlChajian.php

@@ -0,0 +1,146 @@
+<?php
+/**
+	curl
+*/
+class curlChajian extends Chajian{
+	
+	private $TIMEOUT	= 30;
+	
+	private function strurl($url)
+	{
+		$url = str_replace('&#47;', '/', $url);
+		$url = str_replace(' ', '', $url);
+		$url = str_replace("\n", '', $url);
+		return $url;
+	}
+	
+	/**
+	*	设置超时是手机
+	*	$ms 秒数
+	*/
+	public function setTimeout($ms)
+	{
+		$this->TIMEOUT = $ms;
+		return $this;
+	}
+	
+	private function getdatastr($data)
+	{
+		$cont = '';
+		if(is_array($data)){
+			foreach($data as $k=>$v)$cont.='&'.$k.'='.$v.'';
+			if($cont!='')$cont=substr($cont,1);
+		}else{
+			$cont 	= $data;
+		}
+		return $cont;
+	}
+	
+	public function getfilecont($url)
+	{
+		$url 	 = $this->strurl($url);
+		@$result = file_get_contents($url);
+		return $result;
+	}
+	
+	public function postfilecont($url, $data=array())
+	{
+		$url  	= $this->strurl($url);
+		$cont 	= $this->getdatastr($data);
+		$len 	= strlen($cont);
+		$opts 	= array(  
+			'http'	=>	array(  
+				'method'	=>	'POST',  
+				'header' 	=>
+                "Content-type: application/x-www-form-urlencoded\r\n" .
+                "Content-length: $len\r\n", 
+				'content' => $cont,  
+			)  
+		 );  
+		$cxContext 	= stream_context_create($opts);  
+		@$sFile 	= file_get_contents($url, false, $cxContext);  
+		return $sFile;
+	}
+	
+	public function getcurl($url, $headarr=array())
+	{
+		if(!function_exists('curl_init')){
+			return $this->getfilecont($url);
+		}
+		$url= $this->strurl($url);
+		$ishttps = 0;
+		if(substr($url,0, 5)=='https')$ishttps=1;
+		$ch = curl_init();
+		curl_setopt($ch, CURLOPT_URL, $url);
+		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+		curl_setopt($ch, CURLOPT_HEADER, 0);
+		if($ishttps==1){
+			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+		}
+		//设置head
+		if($headarr){
+			$heads = array();
+			foreach($headarr as $k=>$v)$heads[] = ''.$k.':'.$v.'';
+			curl_setopt($ch, CURLOPT_HTTPHEADER, $heads);
+		}
+		curl_setopt($ch, CURLOPT_TIMEOUT, $this->TIMEOUT); 
+		$output = curl_exec($ch);
+		$this->setResponseHeaders($ch);
+		curl_close($ch);
+		return $output;
+	}
+	
+	public function postcurl($url, $data=array(), $lx=0, $headarr=array())
+	{
+		if(!function_exists('curl_init')){
+			return $this->postfilecont($url, $data);
+		}
+		$url	= $this->strurl($url);
+		$cont 	= $data;
+		if($lx==0)$cont = $this->getdatastr($data);
+		$ishttps = 0;
+		if(substr($url,0, 5)=='https')$ishttps=1;
+		$ch = curl_init();
+		curl_setopt($ch, CURLOPT_URL, $url);
+		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //要求结果为字符串且输出到屏幕上
+		curl_setopt($ch, CURLOPT_HEADER, 0); //不返回header
+		curl_setopt($ch, CURLOPT_POST, 1);
+		@curl_setopt($ch, CURLOPT_POSTFIELDS, $cont);
+		if($ishttps==1){
+			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+			//curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,  false);
+		}
+		//设置head
+		if($headarr){
+			$heads = array();
+			foreach($headarr as $k=>$v)$heads[] = ''.$k.':'.$v.'';
+			curl_setopt($ch, CURLOPT_HTTPHEADER, $heads);
+		}
+		curl_setopt($ch, CURLOPT_TIMEOUT, $this->TIMEOUT); 
+		$output = curl_exec($ch);
+		$curl_errno = curl_errno($ch);
+		$this->setResponseHeaders($ch);
+		curl_close($ch);
+		return $output;
+	}
+	
+	/**
+	*	postjson的类型
+	*/
+	public function postjson($url, $data=array())
+	{
+		return $this->postcurl($url, $data, 0, array(
+			'Content-Type' => 'application/json'
+		));
+	}
+	
+	public function getResponseHeaders()
+	{
+		return $this->ResponseHeaders;
+	}
+	
+	private function setResponseHeaders($ch)
+	{
+		$this->ResponseHeaders = curl_getinfo($ch);
+	}
+}                                                                                                                                                            

+ 313 - 0
include/chajian/dateChajian.php

@@ -0,0 +1,313 @@
+<?php 
+class dateChajian extends Chajian
+{
+	public $now;
+	public $date;
+	
+	protected function initChajian()
+	{
+		$this->now 		= $this->rock->now;
+		$this->date 	= $this->rock->date;
+	}
+
+	public function formatdt($dt='',$format='Y-m-d H:i:s')
+	{
+		return date($format,strtotime($dt));
+	}
+	
+	/**
+		获取上月
+	*/
+	public function lastmonth($dt, $type='Y-m')
+	{
+		return $this->adddate($dt,'m',-1,$type);
+	}
+
+	/**
+		计算时间间隔
+	*/	
+	public function datediff($type,$start,$end)
+	{
+		$time1 = strtotime($start);
+		$time2 = strtotime($end);
+		$val=0;
+		switch($type){
+			case 'Y'://年
+				$Y1 = date('Y',$time1);
+				$Y2 = date('Y',$time2);
+				$val = $Y2 - $Y1;
+			break;
+			case 'm'://月份
+				$y1 = date('Y',$time1);
+				$y2 = date('Y',$time2);
+				$m1 = date('m',$time1);
+				$m2 = date('m',$time2);
+				$y = $y1 - $y2;
+				$mz = 0;
+				if($y1 == $y2){
+					$mz=$m2-$m1;
+				}elseif($y1<$y2){
+					$mz = 12-$m1+$m2+12*($y2-$y1-1);
+				}else{
+					$mz = -(12-$m2+$m1+12*($y1-$y2-1));
+				}
+				$val = $mz;
+			break;
+			case 'd'://日
+				$dt1 = strtotime(date('Y-m-d',$time1));
+				$dt2 = strtotime(date('Y-m-d',$time2));
+				$time=$dt2-$dt1;
+				$val = $time/3600/24;
+			break;
+			case 'H'://小时
+				$time = $time2 - $time1;
+				$val = floor($time/3600);
+			break;
+			case 'i'://分钟
+				$time = $time2 - $time1;
+				$val = floor($time/60);
+			break;
+			case 's'://秒
+				$val = $time2 - $time1;
+			break;
+		}
+		return $val;
+	}
+	
+	/**
+		时间计算添加
+	*/
+	public function adddate($dt,$lx,$v=0,$type='')
+	{
+		$time	= strtotime($dt);
+		$arrn1	= explode(' ',$dt);
+		$arrn	= explode('-',$arrn1[0]);
+		$Y		= (int)$arrn[0];
+		$m		= (int)$arrn[1];
+		$d		= (int)$arrn[2];
+		$H=$i=$s=0;
+		if($this->contain($dt,':')){
+			$arrn2	= explode(':',$arrn1[1]);
+			$H		= (int)$arrn2[0];
+			$i		= (int)$arrn2[1];
+			$s		= (int)$arrn2[2];
+		}
+		$rval	= $dt;
+		if($type=='')$type=($H==0)?'Y-m-d':'Y-m-d H:i:s';
+		if($type=='datetime')$type='Y-m-d H:i:s';
+		if($v ==0)return date($type, $time);
+		switch($lx){
+			case 'm'://月份
+				$time	= mktime($H, $i, $s, $m+$v, $d, $Y);
+			break;
+			case 'Y'://年
+				$time	= mktime($H, $i, $s, $m, $d, $Y+$v);
+			break;
+			case 'd'://日期
+				$time	= mktime($H, $i, $s, $m, $d+$v, $Y);
+			break;
+			case 'H'://时
+				$time	= mktime($H+$v, $i, $s, $m, $d, $Y);
+			break;
+			case 'i'://分
+				$time	= mktime($H, $i+$v, $s, $m, $d, $Y);
+			break;
+			case 's'://秒
+				$time	= mktime($H, $i, $s+$v, $m, $d, $Y);
+			break;
+		}
+		$rval	= date($type,$time);
+		return $rval;
+	}
+	
+	//是否包含返回bool
+	public function contain($str,$a)
+	{
+		return $this->rock->contain($str,$a);
+	}
+	
+	//判断是否为空
+	public function isempt($str)
+	{
+		return $this->rock->isempt($str);
+	}	
+	
+	public function diffstr($start, $end, $str, $lx=0, $restr='')
+	{
+		$time1 	= strtotime($start);
+		$time2 	= strtotime($end);
+		$sj		= $time1-$time2;
+		if($lx==1 && $sj<=0)return '';
+		return $this->sjdate($sj, $str, $restr);
+	}
+	
+	public function sjdate($sj, $str='', $restr='')
+	{
+		$h 	= $i = $s = $d = 0;
+		$d 	= floor($sj/3600/24);
+		$sj = $sj - $d * 3600 * 24;
+		$h 	= floor($sj/3600);
+		$sj = $sj - $h*3600;
+		$i 	= floor($sj/60);
+		$s  = $sj - $i * 60;
+		$str = str_replace(array('d','H','i','s'),array($d,$h,$i,$s), $str);
+		if($restr!=''){
+			$resta = explode(',', $restr);
+			foreach($resta as $restas)$str = str_replace($restas,'', $str);
+		}
+		return $str;
+	}
+	
+	public function isdate($dt)
+	{
+		$bo	= false;
+		if($this->isempt($dt))return $bo;
+		$arr	= explode('-', $dt);
+		if(count($arr)>2)$bo = true;
+		$len 	= strlen($dt);
+		if($len>10){
+			$sfm = explode(' ', $dt);
+			if(!isset($sfm[1]))return false;
+			$arr = explode(':', $sfm[1]);
+			if(count($arr)<2)return false;
+		}
+		return $bo;
+	}
+	
+	/**
+		返回月份最大日期
+	*/
+	public function getenddt($month)
+	{
+		$month	= substr($month,0,7);
+		$max 	= $this->getmaxdt($month);
+		return  ''.$month.'-'.$max.'';
+	}
+	
+	public function getmaxdt($dt)
+	{
+		$d 	= explode('-', $dt);
+		$m	= (int)$d[1];
+		$y	= (int)$d[0];
+		$a	= array(31,28,31,30,31,30,31,31,30,31,30,31);
+		$d	= $a[$m-1];
+		if($y%4 == 0 && $m==2 && $y%100 != 0)$d++;
+		return $d;
+	}
+	
+	public function cnweek($date)
+	{
+		$arr = array('日','一','二','三','四','五','六');
+		return $arr[date('w', strtotime($date))];
+	}
+	
+	//读取本周日期
+	public function getweekarr($dt)
+	{
+		$w = date('w', strtotime($dt));
+		$a = array(-6,0,-1,-2,-3,-4,-5);
+		$oi   = $a[$w];
+		$le	  = $oi+7;
+		for($j=$oi; $j<$le; $j++){
+			$arr[] = $this->adddate($dt, 'd', $j);
+		}
+		return $arr;
+	}
+	
+	public function getweekfirst($dt)
+	{
+		$arr = $this->getweekarr($dt);
+		return $arr[0];
+	}
+	
+	public function getweeklast($dt)
+	{
+		$arr = $this->getweekarr($dt);
+		return $arr[6];
+	}
+	
+	/**
+		计算返回当前间隔分析:今天 10:20
+	*/
+	public function stringdt($dttime, $type='G H:i')
+	{
+		$s 	= '';$H=$s=$i='00';
+		$dts= explode(' ', $dttime);
+		$yms= explode('-', $dts[0]);
+		$Y 	= $yms[0];$m = $yms[1];$d = $yms[2];
+		$jg = $this->datediff('d', $dts[0], $this->date);
+		$G	= '';
+		if($jg==0)$G='今天';
+		if($jg==1)$G='昨天';
+		if($jg==2)$G='前天';
+		if($jg==-1)$G='明天';
+		if($jg==-2)$G='后天';
+		$A = $G;
+		if($G=='')$G=substr($dts[0], 5);
+		if($A=='')$A=$dts[0];
+		$w	 = $this->cnweek($dts[0]);
+		if(isset($dts[1])){
+			$sjs = explode(':', $dts[1]);
+			$H 	 = $sjs[0];
+			if(isset($sjs[1]))$i = $sjs[1];
+			if(isset($sjs[2]))$s = $sjs[2];
+		}
+		$str = str_replace(
+			array('A','G','H','i','s','w','Y','m','d'),
+			array($A,$G,$H,$i,$s,$w, $Y, $m, $d),
+		$type);
+		return $str;
+	}
+	
+	
+	/**
+	*	计算周期$rate:d1,d2,$dt开始时间
+	*	返回日期,根据日期判断是不是今天
+	*/
+	public function daterate($rate, $dt, $nowdt='')
+	{
+		if(isempt($rate) || isempt($dt))return false;//没有周期
+		$dt 	= substr($dt,0, 10);//日期的类型
+		if($nowdt=='')$nowdt 	= $this->rock->date;
+		$nowdt	= substr($nowdt, 0, 10);
+		$jg 	= str_replace(array('m','d','w','y'),array('','','',''),$rate);
+		if($jg=='')$jg='1';
+		$jg = (int)$jg;
+		$lx = substr($rate, 0, 1);
+		
+		if($lx=='d'){
+			$jge = $this->datediff('d', $dt, $nowdt);
+			if($jge % $jg==0 || $jge==0){
+				return $nowdt;
+			}
+		}
+		
+		//每月
+		if($lx=='m'){
+			$jge = $this->datediff('m', $dt, $nowdt);
+			if($jge % $jg==0 || $jge==0){
+				$ndt = date('Y-m-'.substr($dt, 8).'');
+				if($ndt==$nowdt)return $nowdt;
+			}
+		}
+		
+		//每年
+		if($lx=='y'){
+			$jge = $this->datediff('y', $dt, $nowdt);
+			if($jge % $jg==0 || $jge==0){
+				$ndt = date('Y-'.substr($dt, 5).'');
+				if($ndt==$nowdt)return $nowdt;
+			}
+		}
+		
+		//每周
+		if($lx=='w'){
+			$w 		= (int)date('w', strtotime($nowdt));if($w==0)$w=7;//星期7
+			if($w==$jg){
+				return $nowdt;
+			}
+		}
+		
+		return false;
+	}
+}                                    

+ 219 - 0
include/chajian/downChajian.php

@@ -0,0 +1,219 @@
+<?php
+/**
+	下载文件类插件
+*/
+
+class downChajian extends Chajian{
+	
+	private $upobj;
+	private $messign;
+	
+	protected function initChajian()
+	{
+		$this->messign = '';
+		$this->upobj = c('upfile');
+	}
+	
+	/**
+	*	获取随机文件名
+	*/
+	public function getallfilename($ext)
+	{
+		if(!is_dir(UPDIR))mkdir(UPDIR);
+		$mkdir 	= ''.UPDIR.'/'.date('Y-m').'';
+		if(!is_dir($mkdir))mkdir($mkdir);
+		$allfilename			= ''.$mkdir.'/'.date('d_His').''.rand(10,99).'.'.$ext.'';
+		return $allfilename;
+	}
+	
+	/**
+	*	根据扩展名保存文件(一般邮件附件下载)
+	*/
+	public function savefilecont($ext, $cont)
+	{
+		$bo  = $this->upobj->issavefile($ext);
+		if(isempt($cont))return;
+		$file= '';
+		if(!$bo){
+			$file	= $this->getallfilename('uptemp');
+			$bo 	= @file_put_contents($file, base64_encode($cont));
+		}else{
+			$file 	= $this->getallfilename($ext);
+			$bo 	= @file_put_contents($file, $cont);
+		}
+		if(!$bo){
+			$file = '';
+		}else{
+			if($this->upobj->isimg($ext)){
+				$bo = $this->upobj->isimgsave($ext, $file);
+				if(!$bo)$file = '';
+			}
+		}
+		return $file;
+	}
+	
+	private function reutnmsg($msg)
+	{
+		$this->messign = $msg;
+		return false;
+	}
+	
+	//获取提示内容
+	public function gettishi($msg1='')
+	{
+		$msg = $this->messign;
+		if(isempt($msg))$msg = $msg1;
+		return $msg;
+	}
+	
+	/**
+	*	根据内容创建文件
+	*/
+	public function createimage($cont, $ext, $filename, $thumbnail='')
+	{
+		if(isempt($cont))return $this->reutnmsg('创建内容为空');
+		$allfilename			= $this->getallfilename($ext);
+		$upses['oldfilename'] 	= $filename.'.'.$ext;
+		$upses['fileext'] 	  	= $ext;
+		@file_put_contents($allfilename, $cont);
+		if(!file_exists($allfilename))return $this->reutnmsg('无法写入:'.$allfilename.'');
+		
+		$fileobj				= getimagesize($allfilename);
+		$mime					= strtolower($fileobj['mime']);
+		$next 					= 'jpg';
+		if(contain($mime,'bmp'))$next = 'bmp';
+		if($mime=='image/gif')$next = 'gif';
+		if($mime=='image/png')$next = 'png';
+		if($ext != $next){
+			@unlink($allfilename);
+			$ext = $next;
+			$allfilename			= $this->getallfilename($ext);
+			$upses['oldfilename'] 	= $filename.'.'.$ext;
+			$upses['fileext'] 	  	= $ext;
+			@file_put_contents($allfilename, $cont);
+			if(!file_exists($allfilename))return $this->reutnmsg('无法写入:'.$allfilename.'');
+		}
+		
+		$filesize 			  	= filesize($allfilename);
+		$filesizecn 		  	= $this->upobj->formatsize($filesize);
+		$picw					= $fileobj[0];				
+		$pich					= $fileobj[1];
+		if($picw==0||$pich==0){
+			@unlink($allfilename);
+			return $this->reutnmsg('无效的图片');;
+		}
+		$upses['filesize']	 	= $filesize;
+		$upses['filesizecn']	= $filesizecn;
+		$upses['allfilename']	= $allfilename;
+		$upses['picw']	 		= $picw;
+		$upses['pich']	 		= $pich;
+		$arr 					= $this->uploadback($upses, $thumbnail);
+		return $arr;
+	}
+	
+	public function uploadback($upses, $thumbnail='', $subo=true)
+	{
+		if($thumbnail=='')$thumbnail='150x150';
+		$msg 		= '';
+		$data 		= array();
+		if(is_array($upses)){
+			$noasyn = $this->rock->get('noasyn'); //=yes就不同步到文件平台
+			$noyaso = $this->rock->get('noyaso'); //=yes就不压缩
+			$fileext= substr($upses['fileext'],0,10);
+			$arrs	= array(
+				'adddt'	=> $this->rock->now,
+				'valid'	=> 1,
+				'filename'	=> $this->replacefile($upses['oldfilename']),
+				'web'		=> $this->rock->web,
+				'ip'		=> $this->rock->ip,
+				'mknum'		=> $this->rock->get('sysmodenum'),
+				//'mid'		=> $this->rock->get('sysmid','0'),
+				'fileext'	=> $fileext,
+				'filesize'	=> (int)$this->rock->get('filesize', $upses['filesize']),
+				'filesizecn'=> $upses['filesizecn'],
+				'filepath'	=> str_replace('../','',$upses['allfilename']),
+				'optid'		=> $this->adminid,
+				'optname'	=> $this->adminname,
+				'comid'		=> m('admin')->getcompanyid(),
+			);
+			$arrs['filetype'] = m('file')->getmime($fileext);
+			$thumbpath	= $arrs['filepath'];
+			$sttua		= explode('x', $thumbnail);
+			$lw 		= (int)$sttua[0];
+			$lh 		= (int)$sttua[1];
+			
+			//判断是不是需要压缩jpg和jpeg
+			$compress	= getconfig('imgcompress');
+			if($compress && $noyaso!='yes' && ($fileext=='jpg' || $fileext=='jpeg') && $upses['picw']>0 && $upses['pich']>0){
+				$sttuc	= explode('x', $compress);
+				$yw 	= (int)$sttuc[0];
+				$yh 	= (int)arrvalue($sttuc, 1, 0);
+				if($upses['picw'] > $yw || $upses['pich'] > $yh){
+					$imgac	= c('image', true);
+					$imgac->createimg($thumbpath);
+					$yspaht = $imgac->compress($yw, $yh);
+					if($yspaht){
+						if($thumbpath != $yspaht)unlink($thumbpath);
+						$thumbpath = $yspaht;
+						$arrs['filepath'] = $yspaht;
+						$arrs['filesize'] = filesize($yspaht);
+						$arrs['filesizecn'] = $this->upobj->formatsize($arrs['filesize']);
+					}
+				}
+			}
+			
+			if($upses['picw']>$lw || $upses['pich']>$lh){
+				$imgaa	= c('image', true);
+				$imgaa->createimg($thumbpath);
+				$thumbpath 	= $imgaa->thumbnail($lw, $lh, 1);
+			}
+			if($upses['picw'] == 0 && $upses['pich']==0)$thumbpath = '';
+			$arrs['thumbpath'] = $thumbpath;
+			
+			
+			$bo = $this->db->record('[Q]file',$arrs);
+			if(!$bo)$this->reutnmsg($this->db->error());
+			
+			$id	= $this->db->insert_id();
+			$arrs['id']   = $id;
+			$arrs['picw'] = $upses['picw'];
+			$arrs['pich'] = $upses['pich'];
+			$data= $arrs;
+			
+			//上传到上传的文件管理2021-08-09
+			if(getconfig('rockfile_autoup') && $noasyn != 'yes'){
+				$stime = time()+rand(3,6);
+				if($subo)$stime=0;
+				c('rockqueue')->push('flow,uptofile', array('fileid'=>$id), $stime);
+			}
+			
+			//自动上传到腾讯云存储/阿里云oss存储
+			if((getconfig('qcloudCos_autoup') || getconfig('alioss_autoup'))  && $noasyn != 'yes'){
+				$stime = time()+rand(3,6);
+				if($subo)$stime=0;
+				c('rockqueue')->sendfile($id, $stime);
+			}
+			
+		}else{
+			$data['msg'] = $upses;
+		}
+		return $data;
+	}
+	
+	//过滤特殊文件名
+	private function replacefile($str)
+	{
+		$s 			= strtolower($str);
+		$s2			= $s.'';
+		$lvlaraa  	= explode(',','user(),found_rows,(),select*from,select*,%20,<,>');
+		$s = str_replace($lvlaraa, '', $s);
+		if($s!=$s2)$str = $s;
+		return $str;
+	}
+	
+	//获取扩展名
+	public function getext($file)
+	{
+		return strtolower(substr($file,strrpos($file,'.')+1));
+	}
+}

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio

粤ICP备19079148号