├── app
├── cache
│ └── tpl
│ │ └── index.html
├── index
│ ├── tpl
│ │ └── index
│ │ │ ├── test.html
│ │ │ └── template.html
│ ├── common.php
│ ├── config.php
│ ├── model
│ │ └── user.php
│ └── ctrl
│ │ └── index.php
└── common.php
├── .gitignore
├── .htaccess
├── index.php
├── icf
├── lib
│ ├── db
│ │ ├── mysql.php
│ │ └── query.php
│ ├── db.php
│ ├── model.php
│ ├── other
│ │ ├── http.php
│ │ ├── HttpHelp.php
│ │ ├── check.php
│ │ └── ImageVerifyCode.php
│ ├── log.php
│ ├── info
│ │ ├── AliSms.php
│ │ └── smtp.php
│ ├── view.php
│ └── route.php
├── config.php
├── common
│ ├── string.php
│ └── common.php
├── loader.php
├── index.php
└── functions.php
└── README.md
/app/cache/tpl/index.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | /app/cache/tpl/*.php
3 | *.log
4 | /icf/res
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/index/tpl/index/test.html:
--------------------------------------------------------------------------------
1 | 哈哈哈
2 |
3 | 我是二号
4 | ---
5 | 模板测试
6 |
{$test['ce']}{$test['c3']}
--------------------------------------------------------------------------------
/app/common.php:
--------------------------------------------------------------------------------
1 |
2 | Options +FollowSymlinks
3 | RewriteEngine On
4 |
5 | RewriteCond %{REQUEST_FILENAME} !-d
6 | RewriteCond %{REQUEST_FILENAME} !-f
7 | RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
8 |
--------------------------------------------------------------------------------
/app/index/common.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Title
6 |
7 |
8 |
9 | 模板测试
10 |
{$test['ce']}{$test['c3']}
--
11 | {include 'test'}--
12 |
函数输出:{:test()}
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/index/config.php:
--------------------------------------------------------------------------------
1 | [
13 | '*' => [
14 | 'users#p' => 'index->index->users'
15 | ]
16 | ]
17 | ];
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 | user = db::table('user')->where('uid', $uid)->find();
23 | }
24 |
25 | public function getUserMsg() {
26 | return "uid:{$this->user['uid']} username:{$this->user['username']}";
27 | }
28 | }
--------------------------------------------------------------------------------
/icf/config.php:
--------------------------------------------------------------------------------
1 | true,
13 | 'db' => [
14 | 'type' => 'mysql',
15 | 'server' => 'localhost',
16 | 'port' => 3306,
17 | 'db' => 'tmp',
18 | 'user' => 'root',
19 | 'pwd' => '',
20 | 'prefix' => 'test_'
21 | ],
22 | //开启restful
23 | 'rest' => true,
24 | //模块,控制器,操作 默认关键字
25 | 'module_key' => 'm',
26 | 'ctrl_key' => 'c',
27 | 'action_key' => 'a',
28 | 'route' => ['*' => ['debug/{test}' => 'index->debug']],
29 | 'tpl_suffix' => 'html',
30 | 'log' => true,
31 | 'url_style' => 1
32 | ];
--------------------------------------------------------------------------------
/icf/common/string.php:
--------------------------------------------------------------------------------
1 | lastinsertid();
32 | }
33 |
34 | /**
35 | * 开始事务
36 | * @author Farmer
37 | */
38 | public static function begin() {
39 | (new query(''))->begin();
40 | }
41 |
42 | /**
43 | * 提交事务
44 | * @author Farmer
45 | */
46 | public static function commit() {
47 | (new query(''))->commit();
48 | }
49 |
50 | /**
51 | * 回滚事务
52 | * @author Farmer
53 | */
54 | public static function rollback() {
55 | (new query(''))->rollback();
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/icf/loader.php:
--------------------------------------------------------------------------------
1 | 'icf/lib'];
17 | //已加载
18 | static $loaded = [];
19 |
20 | /**
21 | * 加载类
22 | * @param $className
23 | * @return bool
24 | */
25 | static function loadClass($className) {
26 | if (in_array($className, self::$loaded)) {
27 | return true;
28 | }
29 | self::$loaded[] = $className;
30 | //处理斜杠,linux系统中得用/
31 | $className = str_replace('\\', '/', $className);
32 | //取出左边的路径
33 | $rootPath = substr($className, 0, strpos($className, '/'));
34 | $loadFile = __ROOT_ . '/' . (isset(loader::$path[$rootPath]) ? loader::$path[$rootPath] : $rootPath);
35 | $loadFile .= substr($className, strpos($className, '/')) . '.php';
36 | if (!is_file($loadFile)) {
37 | $loadFile = __ROOT_ . '/icf/lib/' . (isset(loader::$path[$rootPath]) ? loader::$path[$rootPath] : $rootPath);
38 | $loadFile .= substr($className, strpos($className, '/')) . '.php';
39 | }
40 | if (is_file($loadFile)) {
41 | require_once $loadFile;
42 | }
43 | return true;
44 | }
45 | }
--------------------------------------------------------------------------------
/app/index/ctrl/index.php:
--------------------------------------------------------------------------------
1 | getUserMsg();
29 | }
30 |
31 | public function vcode() {
32 | $v = new ImageVerifyCode();
33 | $v->display();
34 | }
35 |
36 | public function sms($phone = '') {
37 | $sms = new AliSms('LTAINi8D1CVqk6Wv', 'MniMfZHFMI4axWOvU3VzrKsii9c3F7');
38 | return $sms->sendSms('爱编码的Farmer', 'SMS_119087721', ['code' => 'test' . rand(10, 99)], $phone);
39 | }
40 |
41 | public function debug($test = 'hello') {
42 | echo $test . "
";
43 | $rec = db::table('tmp')->where('data', 'haha')->order('data', 'desc')->select();
44 | print_r($rec->fetchAll());
45 | echo "\r\n";
46 | $count = db::table('tmp')->where('data', 'haha')->update(['data' => 'haha', 'value' => rand(1000, 10000)]);
47 | echo "count:$count";
48 | $count = db::table('tmp')->where('data=:data')->bind(':data', '5723')->delete();
49 | echo "count:$count";
50 | }
51 |
52 | public function template() {
53 | $v = new view();
54 | $v->assign('test', ['ce' => 'emm', 'c3' => 'ha']);
55 | $v->display();
56 | }
57 |
58 | //rest test
59 | public function getUsers() {
60 | echo 'get method';
61 | }
62 |
63 | public function deleteUsers($uid = 0) {
64 | echo 'delete method uid:' . $uid;
65 | }
66 |
67 | public function users() {
68 | echo 'does not exist';
69 | }
70 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ICF-PHP
2 |
3 | ## 框架目录结构
4 | ```
5 | |-app //项目目录
6 | |common //全局的模块(可选)
7 | |-ctrl
8 | |-model
9 | |cache //缓存目录
10 | |-module_1 //项目各个模块目录
11 | |-ctrl //控制器
12 | |-model //模型(可选)
13 | |-tpl //视图(可选)
14 | common.php //模块的公共函数库(可选)
15 | config.php //模块的配置目录(可选)
16 | |-module_2 //模块2
17 | .....
18 | common.php //全局的函数库
19 | |-icf //框架目录
20 | |-common //框架内置函数库
21 | |-common.php //框架默认的函数库
22 | |-lib //框架类库
23 | |-db.php //数据库驱动
24 | |-route.php //路由实现
25 | |-view.php //模板引擎
26 | |-config.php //框架配置
27 | |-function.php //框架核心函数
28 | |-index.php //框架入口
29 | |-loader.php //自动加载
30 | |-index.php //启动框架
31 | ```
32 |
33 | ## 框架配置
34 | ```
35 | true,
39 | //数据库配置
40 | 'db' => [
41 | 'type' => 'mysql',
42 | 'server' => 'localhost',
43 | 'port' => 3306,
44 | 'db' => 'tmp',
45 | 'user' => 'root',
46 | 'pwd' => '',
47 | 'prefix' => 'test_'
48 | ],
49 | //开启restful
50 | 'rest' => true,
51 | //模块,控制器,操作 默认关键字
52 | 'module_key' => 'm',
53 | 'ctrl_key' => 'c',
54 | 'action_key' => 'a',
55 | //路由表
56 | 'route' => ['*' => [
57 | 'debug/{test}' => 'index->debug' // URL样式=>对应的控制器
58 | ]
59 | ],
60 | //模板后缀
61 | 'tpl_suffix' => 'html',
62 | //是否记录日志
63 | 'log' => true,
64 | //url 样式
65 | //0=module/ctrl/action/key1/value1/key2/value2
66 | //1=module.php?{$ctrl_key}=ctrl&{$action_key}=action&key1=value1
67 | //2=?{$module_key}=module&{$ctrl_key}=ctrl&{$action_key}=action&key1=value1
68 | 'url_style' => 1
69 | ];
70 | ```
71 |
--------------------------------------------------------------------------------
/icf/lib/model.php:
--------------------------------------------------------------------------------
1 | table = $table;
20 | $this->where = $where;
21 | if ($where !== '') {
22 | $this->data = db::table($table)->where($where)->find();
23 | }
24 | }
25 |
26 | public function __get($name) {
27 | // TODO: Implement __get() method.
28 | if (substr($name, 0, 1) == '_') {
29 | $tmpKey = $this->table . $name;
30 | } else {
31 | $tmpKey = $name;
32 | }
33 | if (isset($this->data[$tmpKey])) {
34 | return $this->data[$tmpKey];
35 | } else {
36 | throw new \Exception('not find ' . $name);
37 | }
38 | }
39 |
40 | public function __set($name, $value) {
41 | // TODO: Implement __set() method.
42 | if (substr($name, 0, 1) == '_') {
43 | $tmpKey = $this->table . $name;
44 | } else {
45 | $tmpKey = $name;
46 | }
47 | $this->data[$tmpKey] = $value;
48 | }
49 |
50 | /**
51 | * 添加数据到数据库
52 | * @author Farmer
53 | * @return int
54 | */
55 | public function add() {
56 | db::table($this->table)->insert($this->data);
57 | return db::table()->lastinsertid();
58 | }
59 |
60 | /**
61 | * 修改数据
62 | * @author Farmer
63 | * @param $where
64 | */
65 | public function put($where) {
66 | db::table($this->table)->where($where)->update($this->data);
67 | }
68 |
69 | /**
70 | * 获取数据
71 | * @author Farmer
72 | * @return mixed
73 | */
74 | public function getData() {
75 | return $this->data;
76 | }
77 |
78 | /**
79 | * 设置数据
80 | * @author Farmer
81 | * @param $data
82 | */
83 | public function setData($data) {
84 | $this->data = $data;
85 | }
86 | }
--------------------------------------------------------------------------------
/icf/index.php:
--------------------------------------------------------------------------------
1 | notice('ip:' . getip() . ' url:' . getReqUrl() . ' post:' . json_encode($_POST, JSON_UNESCAPED_UNICODE)
59 | . ' cookie:' . json_encode($_COOKIE, JSON_UNESCAPED_UNICODE));
60 | }
61 | //路由加载
62 | if (isset($config['route'])) {
63 | foreach ($config['route'] as $key => $item) {
64 | route::add($key, $item);
65 | }
66 | }
67 | route::analyze();
68 | }
69 | }
--------------------------------------------------------------------------------
/icf/lib/other/http.php:
--------------------------------------------------------------------------------
1 | curl = curl_init($url);
23 | curl_setopt($this->curl, CURLOPT_HEADER, 0); //不返回header部分
24 | curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); //返回字符串,而非直接输出
25 | curl_setopt($this->curl, CURLOPT_TIMEOUT, 10);
26 | }
27 |
28 | public function setopt($key, $value) {
29 | curl_setopt($this->curl, $key, $value);
30 | }
31 |
32 | public function setRedirection($value = 1) {
33 | curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, $value);
34 | }
35 |
36 | public function __destruct() {
37 | // TODO: Implement __destruct() method.
38 | curl_close($this->curl);
39 | }
40 |
41 | public function setCookie($cookie) {
42 | curl_setopt($this->curl, CURLOPT_COOKIE, $cookie);
43 | }
44 |
45 | public function setHeader($header) {
46 | curl_setopt($this->curl, CURLOPT_HTTPHEADER, $header);
47 | }
48 |
49 | public function setUrl($url) {
50 | curl_setopt($this->curl, CURLOPT_URL, $url);
51 | }
52 |
53 | public function https() {
54 | curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false);
55 | }
56 |
57 | public function get($url = '') {
58 | if (!empty($url)) {
59 | $this->setUrl($url);
60 | }
61 | curl_setopt($this->curl, CURLOPT_POST, 0);
62 | return $this->access();
63 | }
64 |
65 | public function post($url = '', $data = '') {
66 | curl_setopt($this->curl, CURLOPT_POST, 1);
67 | if (!empty($data)) {
68 | $this->setUrl($url);
69 | curl_setopt($this->curl, CURLOPT_POSTFIELDS, $data);
70 | } else {
71 | curl_setopt($this->curl, CURLOPT_POSTFIELDS, $url);
72 | }
73 | return $this->access();
74 | }
75 |
76 | public function access() {
77 | $response = curl_exec($this->curl);
78 | if ($response == false) return curl_error($this->curl);
79 | return $response;
80 | }
81 | }
--------------------------------------------------------------------------------
/icf/lib/log.php:
--------------------------------------------------------------------------------
1 | >> [notice] $msg");
73 | }
74 |
75 | /**
76 | * 错误日志
77 | * @author Farmer
78 | * @param $msg
79 | * @return bool|int
80 | */
81 | public function error($msg) {
82 | return self::wline(date('Y-m-d H:i:s') . ">>> [error] $msg");
83 | }
84 |
85 | }
--------------------------------------------------------------------------------
/icf/lib/info/AliSms.php:
--------------------------------------------------------------------------------
1 | akID = $AccessKeyID;
23 | $this->akSecrt = $AccessKeySecret;
24 |
25 | }
26 |
27 | public function sendSms($SignName, $TemplateCode, $TemplateParam, $PhoneNumbers) {
28 | return $this->request([
29 | 'Action' => 'SendSms',
30 | 'Version' => '2017-05-25',
31 | 'RegionId' => 'cn',
32 | 'SignName' => $SignName,
33 | 'TemplateCode' => $TemplateCode,
34 | 'TemplateParam' => json_encode($TemplateParam, JSON_UNESCAPED_UNICODE),
35 | 'PhoneNumbers' => $PhoneNumbers
36 | ]);
37 | }
38 |
39 | public function request($param) {
40 | $req = array_merge([
41 | 'AccessKeyId' => $this->akID,
42 | 'Timestamp' => gmdate("Y-m-d\TH:i:s\Z"),
43 | 'SignatureMethod' => 'HMAC-SHA1',
44 | 'SignatureVersion' => '1.0',
45 | 'SignatureNonce' => uniqid(mt_rand(0, 0xffff), true),
46 | 'Format' => 'JSON'
47 | ], $param);
48 | $getParam = $this->getReqString($req);
49 | $Signature = $this->sign($getParam);
50 | $http = new http("https://dysmsapi.aliyuncs.com/?Signature={$Signature}{$getParam}");
51 | $http->https();
52 | $data = $http->get();
53 | return $data;
54 | }
55 |
56 | private function getReqString($req) {
57 | ksort($req);
58 | $ret = '';
59 | foreach ($req as $key => $value) {
60 | $ret .= '&' . $this->encode($key) . '=' . $this->encode($value);
61 | }
62 | return $ret;
63 | }
64 |
65 | private function sign($param) {
66 | $stringToSign = "GET&%2F&" . $this->encode(substr($param, 1));
67 | $sign = base64_encode(hash_hmac("sha1", $stringToSign, $this->akSecrt . "&", true));
68 | return $this->encode($sign);
69 | }
70 |
71 | private function encode($str) {
72 | $res = urlencode($str);
73 | $res = preg_replace("/\+/", "%20", $res);
74 | $res = preg_replace("/\*/", "%2A", $res);
75 | $res = preg_replace("/%7E/", "~", $res);
76 | return $res;
77 | }
78 |
79 | }
--------------------------------------------------------------------------------
/icf/functions.php:
--------------------------------------------------------------------------------
1 | 'text/html', 'json' => 'application/json', 'jpg' => 'image/jpeg',
25 | 'png' => 'image/png', 'gif' => 'image/gif', 'xml' => 'text/xml'
26 | ];
27 |
28 | public static function setContentType($type = 'html') {
29 | header('Content-Type:' . self::$contentType[$type] . '; charset=utf-8');
30 | }
31 |
32 | public static function getHeaderVal($key) {
33 | if (isset($_SERVER['HTTP_' . strtoupper($key)])) {
34 | return $_SERVER['HTTP_' . strtoupper($key)];
35 | }
36 | return false;
37 | }
38 |
39 | public static function getHttpStatusMessage($statusCode) {
40 | $httpStatus = array(
41 | 100 => 'Continue',
42 | 101 => 'Switching Protocols',
43 | 200 => 'OK',
44 | 201 => 'Created',
45 | 202 => 'Accepted',
46 | 203 => 'Non-Authoritative Information',
47 | 204 => 'No Content',
48 | 205 => 'Reset Content',
49 | 206 => 'Partial Content',
50 | 300 => 'Multiple Choices',
51 | 301 => 'Moved Permanently',
52 | 302 => 'Found',
53 | 303 => 'See Other',
54 | 304 => 'Not Modified',
55 | 305 => 'Use Proxy',
56 | 306 => '(Unused)',
57 | 307 => 'Temporary Redirect',
58 | 400 => 'Bad Request',
59 | 401 => 'Unauthorized',
60 | 402 => 'Payment Required',
61 | 403 => 'Forbidden',
62 | 404 => 'Not Found',
63 | 405 => 'Method Not Allowed',
64 | 406 => 'Not Acceptable',
65 | 407 => 'Proxy Authentication Required',
66 | 408 => 'Request Timeout',
67 | 409 => 'Conflict',
68 | 410 => 'Gone',
69 | 411 => 'Length Required',
70 | 412 => 'Precondition Failed',
71 | 413 => 'Request Entity Too Large',
72 | 414 => 'Request-URI Too Long',
73 | 415 => 'Unsupported Media Type',
74 | 416 => 'Requested Range Not Satisfiable',
75 | 417 => 'Expectation Failed',
76 | 500 => 'Internal Server Error',
77 | 501 => 'Not Implemented',
78 | 502 => 'Bad Gateway',
79 | 503 => 'Service Unavailable',
80 | 504 => 'Gateway Timeout',
81 | 505 => 'HTTP Version Not Supported');
82 | return ($httpStatus[$statusCode]) ? $httpStatus[$statusCode] : $httpStatus[500];
83 | }
84 | }
--------------------------------------------------------------------------------
/icf/lib/other/check.php:
--------------------------------------------------------------------------------
1 | checkRule = array_merge($this->checkRule, $key);
24 | } else {
25 | $this->checkRule[$key] = $rule;
26 | }
27 | return $this;
28 | }
29 |
30 | public function addData($key, $value = null) {
31 | if (is_null($value)) {
32 | $this->checkData = array_merge($this->checkData, $key);
33 | } else {
34 | $this->checkData[$key] = $value;
35 | }
36 | return $this;
37 | }
38 |
39 | public function check() {
40 | foreach ($this->checkRule as $key => $value) {
41 | if (($ret = $this->dealRule($key, $value)) !== true) {
42 | return $ret;
43 | }
44 | }
45 | return true;
46 | }
47 |
48 | public function isNull($key) {
49 | return (!isset($this->checkData[$key]) || empty($this->checkData[$key]));
50 | }
51 |
52 | private function dealRule($key, $rule) {
53 | $pos = strpos($key, ':');
54 | if ($pos !== false) {
55 | $name = substr($key, $pos ? $pos + 1 : 0);
56 | $key = substr($key, 0, $pos);
57 | } else {
58 | $name = $key;
59 | }
60 | if ($this->isNull($key)) {
61 | if (isset($rule['null']) && $rule['null']) {
62 | return true;
63 | } else {
64 | return $name . '不能为空';
65 | }
66 | }
67 | if (isset($rule['func'])) {
68 | $parameter = array();
69 | $parameter[] = $this->checkData[$key];
70 | if (is_array($rule['func'])) {
71 | $paramName = $rule['func'];
72 | $funName = $rule['func'][0];
73 | unset($paramName[0]);
74 | foreach ($paramName as $v) {
75 | $parameter[] = $this->checkData[$v];
76 | }
77 | } else {
78 | $funName = $rule['func'];
79 | }
80 | $tmpValue = call_user_func_array($funName, $parameter);
81 | if ($tmpValue !== true) {
82 | return $tmpValue;
83 | }
84 | }
85 | if (isset($rule['regex'])) {
86 | if (is_array($rule['regex'])) {
87 | $reg = $rule['regex'][0];
88 | $msg = $rule['regex'][1];
89 | } else {
90 | $reg = $rule['regex'];
91 | $msg = ($name . '不符合规则');
92 | }
93 | if (!preg_match($reg, $this->checkData[$key])) {
94 | return $msg;
95 | }
96 | }
97 | if (isset($rule['range'])) {
98 | $min = 0;
99 | if (is_array($rule['range'])) {
100 | $min = $rule['range'][0];
101 | $max = $rule['range'][1];
102 | } else {
103 | $max = $rule['range'];
104 | }
105 | if (is_numeric($this->checkData[$key])) {
106 | $len = $this->checkData[$key];
107 | } else if (is_string($this->checkData[$key])) {
108 | $len = mb_strlen($this->checkData[$key]);
109 | }
110 | if ($len < $min) {
111 | return "{$name}长度过小,要求在($min-$max)之内";
112 | } else if ($len > $max) {
113 | return "{$name}长度过长,要求在($min-$max)之内";
114 | }
115 | }
116 | if (isset($rule['bind'])) {
117 | $this->bindVar[empty($rule['bind']) ? $key : $rule['bind']] = htmlspecialchars($this->checkData[$key], ENT_QUOTES, 'UTF-8');
118 | }
119 | return true;
120 | }
121 |
122 | public function getBindVar() {
123 |
124 | return $this->bindVar;
125 | }
126 | }
--------------------------------------------------------------------------------
/icf/lib/view.php:
--------------------------------------------------------------------------------
1 | module = $module;
36 | }
37 |
38 | /**
39 | * 设置值
40 | *
41 | * @author Farmer
42 | * @param string $param
43 | * @param string $value
44 | * @return
45 | *
46 | */
47 | public function assign($param, $value) {
48 | self::$tplVar [$param] = $value;
49 | }
50 |
51 | /**
52 | * 输出模板内容
53 | * @author Farmer
54 | * @param string $filename
55 | * @return null
56 | */
57 | public function display($filename = '') {
58 | $cache = self::compile($filename);
59 | if ($cache) {
60 | header('Content-type: text/html; charset=utf-8');
61 | echo $cache;
62 | return true;
63 | }
64 | return false;
65 | }
66 |
67 | /**
68 | * 返回编译内容
69 | * @param $filename
70 | * @return string
71 | */
72 | public function compile($filename = '') {
73 | if ($filename === '') {
74 | $filename = input('action');
75 | }
76 | if (strpos($filename, '/') === false) {
77 | $path = __ROOT_ . '/app/' . input('module') . '/tpl/' . input('ctrl') . '/' . $filename;
78 | } else {
79 | $path = __ROOT_ . '/app/' . input('module') . '/tpl/' . $filename;
80 | }
81 | $suffix = '.' . input('config.tpl_suffix');
82 | if (substr($path, strlen($path) - strlen($suffix), strlen($suffix)) != $suffix) {
83 | $path .= $suffix;
84 | }
85 | if (!is_file($path)) {
86 | echo 'template load error';
87 | return false;
88 | }
89 | $cache = __ROOT_ . '/app/cache/tpl/' . md5($path) . '.php';
90 | return self::fetch($path, $cache);
91 | }
92 |
93 | /**
94 | * 生成编译文件并返回
95 | *
96 | * @author Farmer
97 | * @param string $path
98 | * @param string $cache
99 | * @return
100 | *
101 | */
102 | private function fetch($path, $cache) {
103 | $fileData = file_get_contents($path);
104 | if (!file_exists($cache) || filemtime($path) > filemtime($cache)) {
105 | $pattern = array(
106 | '/\{(\$[\w\[\]\']+)\}/',
107 | '/{break}/',
108 | '/{continue}/',
109 | '/{if (.*?)}/',
110 | '/{\/if}/',
111 | '/{elseif (.*?)}/',
112 | '/{else}/',
113 | '/{foreach (.*?)}/',
114 | '/{\/foreach}/',
115 | "/{include '(.*?)'}/",
116 | '/{\:(.*?)}/'
117 | );
118 | $replace = array(
119 | '',
120 | '',
121 | '',
122 | '',
123 | '',
124 | '',
125 | '',
126 | '',
127 | '',
128 | 'display("${1}");?>',
129 | ''
130 | );
131 | $cacheData = preg_replace($pattern, $replace, $fileData);
132 | @file_put_contents($cache, $cacheData);
133 | } else {
134 | $cacheData = file_get_contents($cache);
135 | }
136 | $pattern = array(
137 | '/__HOME__/'
138 | );
139 | $replace = array(
140 | __HOME_
141 | );
142 | $cacheData = preg_replace($pattern, $replace, $cacheData);
143 | preg_match_all('/\{\$([a-zA-Z0-9]+)\}/', $fileData, $tmp);
144 | for ($i = 0; $i < sizeof($tmp [1]); $i++) {
145 | if (!isset (self::$tplVar [$tmp [1] [$i]])) {
146 | self::$tplVar [$tmp [1] [$i]] = '';
147 | }
148 | }
149 | ob_start();
150 | extract(self::$tplVar);
151 | eval ('?>' . $cacheData);
152 | $content = ob_get_contents();
153 | ob_end_clean();
154 | return $content;
155 | }
156 | }
--------------------------------------------------------------------------------
/icf/lib/other/ImageVerifyCode.php:
--------------------------------------------------------------------------------
1 | left = mt_rand(10, 15);
27 | $this->backcolor();//生成背景颜色
28 | $this->code = '';
29 | for ($i = 0; $i < 4; $i++) {//绘制字符
30 | $tmp = self::getRandString(1);
31 | $this->createWord($tmp);
32 | $this->code .= $tmp;
33 | }
34 | $this->_writeCurve();//绘制干扰线
35 | return $this->code;
36 | }
37 |
38 | /**
39 | * 取随机字符串
40 | * @author Farmer
41 | * @param $length
42 | * @param $type
43 | * @return string
44 | */
45 | public static function getRandString($length, $type = 2) {
46 | $randString = '123456789qwwertyuopasdfghjkzxcvbnmQWERTYUIPASDFGHHJKLZXCVBNM';
47 | $retStr = '';
48 | for ($n = 0; $n < $length; $n++) {
49 | $retStr .= substr($randString, mt_rand(0, 9 + $type * 24), 1);
50 | }
51 | return $retStr;
52 | }
53 |
54 | public function getImage() {
55 | return $this->im;
56 | }
57 |
58 | public function display() {
59 | $this->create();
60 | header('Pragma: no-cache');
61 | header('Content-type: image/png');
62 | imagepng($this->im);
63 | imagedestroy($this->im);
64 | return $this->code;
65 | }
66 |
67 | private function backcolor() {
68 | $this->im = imagecreatetruecolor($this->imageL, $this->imageH);
69 | $this->bgc = imagecolorallocate($this->im, 255, 255, 255);
70 | imagefill($this->im, 0, 0, imagecolorallocate($this->im, 255, 255, 255));
71 | }
72 |
73 | private function createWord($word) {
74 | $font = __ROOT_ . '/icf/res/arial.ttf';
75 | $size = mt_rand(24, 28);
76 | imagefttext($this->im, $size, mt_rand(-60, 60), $this->left, $size * 1.5, $this->createRandColor(), $font, $word);
77 | $this->left += mt_rand($size * 1.2, $size * 1.6);
78 | }
79 |
80 | private function createRandColor() {
81 | return imagecolorallocate($this->im, mt_rand(10, 200), mt_rand(10, 200), mt_rand(10, 200));
82 | }
83 |
84 | /**
85 | * 算法来自:http://www.piaoyi.org/php/php-yanzhengma-rand-shape.html
86 | * 画一条由两条连在一起构成的随机正弦函数曲线作干扰线(你可以改成更帅的曲线函数)
87 | * 正弦型函数解析式:y=Asin(ωx+φ)+b
88 | * 各常数值对函数图像的影响:
89 | * A:决定峰值(即纵向拉伸压缩的倍数)
90 | * b:表示波形在Y轴的位置关系或纵向移动距离(上加下减)
91 | * φ:决定波形与X轴位置关系或横向移动距离(左加右减)
92 | * ω:决定周期(最小正周期T=2π/∣ω∣)
93 | */
94 | protected function _writeCurve() {
95 | $A = mt_rand(1, $this->imageH / 2); // 振幅
96 | $b = mt_rand(-$this->imageH / 4, $this->imageH / 4); // Y轴方向偏移量
97 | $f = mt_rand(-$this->imageH / 4, $this->imageH / 4); // X轴方向偏移量
98 | $T = mt_rand($this->imageH * 1.5, $this->imageL * 2); // 周期
99 | $w = (2 * M_PI) / $T;
100 |
101 | $px1 = 0; // 曲线横坐标起始位置
102 | $px2 = mt_rand($this->imageL / 2, $this->imageL * 0.667); // 曲线横坐标结束位置
103 | $t_bg = $this->createRandColor();
104 | for ($px = $px1; $px <= $px2; $px = $px + 0.9) {
105 | if ($w != 0) {
106 | $py = $A * sin($w * $px + $f) + $b + $this->imageH / 2; // y = Asin(ωx+φ) + b
107 | $i = (int)(($this->fontSize - 6) / 4);
108 | while ($i > 0) {
109 | imagesetpixel($this->im, $px + $i, $py + $i, $t_bg);
110 | //这里画像素点比imagettftext和imagestring性能要好很多
111 | $i--;
112 | }
113 | }
114 | }
115 |
116 | $A = mt_rand(1, $this->imageH / 2); // 振幅
117 | $f = mt_rand(-$this->imageH / 4, $this->imageH / 4); // X轴方向偏移量
118 | $T = mt_rand($this->imageH * 1.5, $this->imageL * 2); // 周期
119 | $w = (2 * M_PI) / $T;
120 | $b = $py - $A * sin($w * $px + $f) - $this->imageH / 2;
121 | $px1 = $px2;
122 | $px2 = $this->imageL;
123 | for ($px = $px1; $px <= $px2; $px = $px + 0.9) {
124 | if ($w != 0) {
125 | $py = $A * sin($w * $px + $f) + $b + $this->imageH / 2; // y = Asin(ωx+φ) + b
126 | $i = (int)(($this->fontSize - 8) / 4);
127 | while ($i > 0) {
128 | imagesetpixel($this->im, $px + $i, $py + $i, $t_bg);
129 | //这里(while)循环画像素点比imagettftext和imagestring用字体大小一次画出
130 | //的(不用while循环)性能要好很多
131 | $i--;
132 | }
133 | }
134 | }
135 | }
136 |
137 | }
--------------------------------------------------------------------------------
/icf/common/common.php:
--------------------------------------------------------------------------------
1 | $value) {
141 | $url .= "{$p_left}{$key}{$p_mid}{$value}";
142 | }
143 | return $url;
144 | }
145 |
146 |
147 | function _404() {
148 | \icf\lib\other\HttpHelp::setStatusCode(404);
149 | echo '404';
150 | }
151 |
152 |
153 | /**
154 | * 更深层次的合并两个数组
155 | * @param array $array1
156 | * @param array $array2
157 | * @return array
158 | */
159 | function array_merge_in($array1, $array2 = null) {
160 | $towArr = [];
161 | foreach ($array1 as $key => $value) {
162 | if (is_array($value) && isset($array2[$key])) {
163 | $towArr[$key] = array_merge_in($array1[$key], $array2[$key]);
164 | }
165 | }
166 | $tmpArr = array_merge($array1, $array2);
167 | if ($towArr != []) {
168 | $towArr = array_merge($tmpArr, $towArr);
169 | } else {
170 | $towArr = $tmpArr;
171 | }
172 | return $towArr;
173 | }
174 |
--------------------------------------------------------------------------------
/icf/lib/route.php:
--------------------------------------------------------------------------------
1 | [
24 | '{s}.php' => '${1}->index->index',
25 | '{s}/{s}/{s}#p' => '${1}->${2}->${3}',
26 | '{s}/{s}#p' => '${1}->${2}',
27 | '{s}#p' => '${1}->index'
28 | ], 'get' => [
29 |
30 | ]];
31 |
32 | static $get_param = [];
33 |
34 | static $replace_param = '';
35 |
36 | static $classNamePace = '';
37 |
38 | static $get = [];
39 |
40 | static $matchUrl = '';
41 |
42 | static $req_method = 'get';
43 |
44 | static function matchRule($match, $pathInfo) {
45 | //初始化
46 | self::$module = '';
47 | self::$ctrl = '';
48 | self::$action = '';
49 | //处理各个参数
50 | $param = '';
51 | if ($cut = strpos($match[0], '#')) {
52 | $param = substr($match[0], $cut + 1);
53 | $match[0] = substr($match[0], 0, $cut);
54 | if (strpos($param, 'p') !== false) {
55 | $match[0] .= '/';
56 | $pathInfo .= '/';
57 | }
58 | }
59 | $var = preg_replace_callback('#{(.*?)}#', function ($v) {
60 | static $count = 0;
61 | $count++;
62 | self::$get_param[$count] = $v[1];
63 | return '([\S][^\{^\}^/]*)';
64 | }, $match[0]);
65 | self::$replace_param = $match[1];
66 | self::$get = [];
67 | $count = 0;
68 | preg_replace_callback('#^\/' . $var . '#', function ($v) {
69 | foreach ($v as $key => $value) {
70 | self::$replace_param = str_replace('${' . $key . '}', $value, self::$replace_param);
71 | if (isset(self::$get_param[$key])) {
72 | self::$get[self::$get_param[$key]] = $value;
73 | }
74 | }
75 | self::$matchUrl = $v[0];
76 | return '';
77 | }, $pathInfo, 1, $count);
78 | if ($count <= 0) {
79 | return false;
80 | }
81 | $mca = explode('->', self::$replace_param, 3);
82 | if (sizeof($mca) <= 2) {
83 | $mca[2] = $mca[isset($mca[1])];
84 | $mca[1] = isset($mca[1]) ? $mca[0] : 'index';
85 | $mca[0] = __DEFAULT_MODULE_;
86 | }
87 | self::$module = _get(_config('module_key'), $mca[0]);
88 | self::$ctrl = _get(_config('ctrl_key'), $mca[1]);
89 | self::$action = _get(_config('action_key'), $mca[2]);
90 | self::$classNamePace = 'app\\' . self::$module . '\\ctrl\\' . self::$ctrl;
91 | $className = str_replace('\\', '/', self::$classNamePace);
92 | if (!is_file($className . '.php')) {
93 | return false;
94 | }
95 | $tmpParam = '';
96 | if (self::$matchUrl) {
97 | $tmpParam = substr($pathInfo, strpos($pathInfo, self::$matchUrl) + strlen(self::$matchUrl));
98 | }
99 | if (strpos($param, 'p') !== false) {
100 | //处理后方参数
101 | preg_match_all('#/([\S][^\{^\}^/]*)/([\S][^\{^\}^/]*)#', '/' . $tmpParam, $matchArr, PREG_SET_ORDER);
102 | foreach ($matchArr as $item) {
103 | self::$get[$item[1]] = $item[2];
104 | }
105 | } else {
106 | if ($tmpParam != '') {
107 | return false;
108 | }
109 | }
110 | return true;
111 | }
112 |
113 | /**
114 | * 解析URL,加载控制类
115 | * @access public
116 | * @author Farmer
117 | */
118 | static function analyze() {
119 | self::$req_method = strtolower($_SERVER['REQUEST_METHOD']);
120 | if (isset($_SERVER['PATH_INFO']) && !empty($_SERVER['PATH_INFO'])) {
121 | $pathInfo = $_SERVER['PATH_INFO'];
122 | if (isset(self::$rule[self::$req_method])) {
123 | $tmpRule = self::$rule[self::$req_method];
124 | foreach ($tmpRule as $key => $value) {
125 | //匹配规则
126 | if (self::matchRule([$key, $value], $pathInfo)) {
127 | if (self::runAction()) {
128 | return;
129 | }
130 | }
131 | }
132 | }
133 | $tmpRule = self::$rule['*'];
134 | foreach ($tmpRule as $key => $value) {
135 | //匹配规则
136 | if (self::matchRule([$key, $value], $pathInfo)) {
137 | if (self::runAction()) {
138 | return;
139 | }
140 | }
141 | }
142 | _404();
143 | return;
144 | } else {
145 | self::$module = _get(_config('module_key'), __DEFAULT_MODULE_);
146 | self::$ctrl = _get(_config('ctrl_key'), 'index');
147 | self::$action = _get(_config('action_key'), 'index');
148 | self::$classNamePace = 'app\\' . self::$module . '\\ctrl\\' . self::$ctrl;
149 | $className = str_replace('\\', '/', self::$classNamePace);
150 | if (!is_file($className . '.php')) {
151 | _404();
152 | return false;
153 | }
154 | self::runAction();
155 | return;
156 | }
157 | }
158 |
159 |
160 | static function runAction() {
161 | input('module', route::$module);
162 | input('ctrl', route::$ctrl);
163 | input('action', route::$action);
164 | //加载全局函数
165 | $comPath = __ROOT_ . '/app/common.php';
166 | if (file_exists($comPath)) {
167 | require_once $comPath;
168 | }
169 | //加载模块函数
170 | $comPath = __ROOT_ . '/app/' . self::$module . '/';
171 | if (file_exists($comPath . 'common.php')) {
172 | require_once $comPath . 'common.php';
173 | }
174 | try {
175 | input('get', $_GET);
176 | if ($_SERVER['REQUEST_METHOD'] != 'GET') {
177 | $input = file_get_contents('php://input');
178 | if (sizeof($_POST) <= 0 && $input != '') {
179 | if (strpos(isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : '', 'application/json') !== false) {
180 | $_POST = json_decode($input, true);
181 | if (!$_POST || sizeof($_POST) <= 0) {
182 | parse_str($input, $_POST);
183 | }
184 | } else {
185 | parse_str($input, $_POST);
186 | }
187 | }
188 | }
189 | input('post', $_POST);
190 | $tmp = self::$classNamePace;
191 | $object = new $tmp();
192 | if (input('config.rest')) {
193 | $tmpMethod = self::$req_method . self::$action;
194 | if (method_exists($object, $tmpMethod)) {
195 | self::$action = $tmpMethod;
196 | }
197 | }
198 | // 获取方法参数
199 | $method = new \ReflectionMethod ($object, self::$action);
200 | // 参数绑定
201 | $param = [];
202 | $_GET = array_merge($_GET, self::$get);
203 | foreach ($method->getParameters() as $value) {
204 | if ($val = _get($value->getName())) {
205 | $param [] = $val;
206 | } else {
207 | $param [] = $value->isDefaultValueAvailable() ? $value->getDefaultValue() : '';
208 | }
209 | }
210 | $data = call_user_func_array([
211 | $object,
212 | self::$action
213 | ], $param);
214 | if (is_array($data)) {
215 | header('Content-Type: application/json; charset=utf-8');
216 | echo json($data);
217 | } else {
218 | echo $data;
219 | }
220 | } catch (\Throwable $e) {
221 | if (input('config.debug')) {
222 | if (input('config.log')) {
223 | index::$log->error('[file] ' . $e->getFile() . ' [line] ' . $e->getLine() . ' [error] ' . $e->getMessage());
224 | }
225 | echo "file:" . $e->getFile() . "
\n";
226 | echo "line:" . $e->getLine() . "
\n";
227 | echo "error:" . $e->getMessage() . "
\n";
228 | var_dump($e->getTrace());
229 | } else {
230 | _404();
231 | }
232 | }
233 | return true;
234 | }
235 |
236 | /**
237 | * 添加规则
238 | * @access public
239 | * @author Farmer
240 | * @param $req_type
241 | * @param $rule
242 | * @param string $to
243 | */
244 | static function add($req_type, $rule, $to = '') {
245 | if (is_array($rule)) {
246 | foreach ($rule as $pattern => $value) {
247 | self::$rule [$req_type][$pattern] = $value;
248 | }
249 | } else {
250 | self::$rule [$req_type][$rule] = $to;
251 | }
252 | }
253 | }
--------------------------------------------------------------------------------
/icf/lib/db/query.php:
--------------------------------------------------------------------------------
1 | setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
26 | self::$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
27 | }
28 | if (!empty($table)) {
29 | $this->table = input('config.db.prefix') . str_replace('|', ',' . input('config.db.prefix'), $table);
30 | }
31 | }
32 |
33 | private $table = '';
34 | private $where = '';
35 | private $field = '';
36 | private $order = '';
37 | private $limit = '';
38 | private $join = '';
39 |
40 | private $lastOper = 'and';
41 | private $bindParam = [];
42 |
43 | /**
44 | * 条件
45 | * @author Farmer
46 | * @param $field
47 | * @param null $value
48 | * @param string $operator
49 | * @return $this
50 | */
51 | public function where($field, $value = null, $operator = '=') {
52 | $this->where .= ' ' . (empty($this->where) ? '' : $this->lastOper . ' ');
53 | //恢复默认运算符
54 | $this->lastOper = 'and';
55 | if (is_array($field)) {
56 | //获取最后一个
57 | $keys = array_keys($field);
58 | foreach ($field as $key => $item) {
59 | if (is_string($key)) {
60 | $this->where .= "`$key`$operator? ";
61 | $this->bindParam[] = $item;
62 | if ($key !== end($keys)) {
63 | $this->where .= 'and ';
64 | }
65 | } else if (is_numeric($key)) {
66 | $this->where .= "$item";
67 | if ($key !== end($keys)) {
68 | $this->where .= 'and ';
69 | }
70 | }
71 | }
72 | } else if (is_string($field)) {
73 | if (is_null($value)) {
74 | $this->where .= $field;
75 | } else {
76 | $this->where .= " `$field`$operator?";
77 | $this->bindParam[] = $value;
78 | }
79 | }
80 | return $this;
81 | }
82 |
83 | public function join($table, $on = '', $link = 'left') {
84 | if (is_array($table)) {
85 | foreach ($table as $key => $value) {
86 | if (is_string($key)) {
87 | $this->join .= " $link join `" . input('config.db.prefix') . $key . "` as $value " . (empty($on) ? '' : "on $on");
88 | } else if (is_numeric($key)) {
89 | $this->join .= ' ' . $value;
90 | }
91 | }
92 | } else if (is_string($table)) {
93 | $table = str_replace(':', input('config.db.prefix'), $table);
94 | $this->join .= " $link join $table " . (empty($on) ? '' : "on $on");
95 | }
96 | return $this;
97 | }
98 |
99 | /**
100 | * 插入数据
101 | * @author Farmer
102 | * @param array $items
103 | * @return bool|int
104 | */
105 | public function insert(array $items) {
106 | if (!empty ($items)) {
107 | $param = [];
108 | $sql = 'insert into ' . $this->table . '(`' . implode('`,`', array_keys($items)) . '`) values(';
109 | foreach ($items as $value) {
110 | $sql .= '?,';
111 | $param[] = $value;
112 | }
113 | $sql = substr($sql, 0, strlen($sql) - 1);
114 | $sql .= ')';
115 | $result = self::$db->prepare($sql);
116 | if ($result->execute($param)) {
117 | return $result->rowCount();
118 | }
119 | return false;
120 | }
121 | return false;
122 | }
123 |
124 | /**
125 | * and
126 | * @author Farmer
127 | * @return $this
128 | */
129 | public function _and() {
130 | $this->lastOper = 'and';
131 | return $this;
132 | }
133 |
134 | /**
135 | * or
136 | * @author Farmer
137 | * @return $this
138 | */
139 | public function _or() {
140 | $this->lastOper = 'or';
141 | return $this;
142 | }
143 |
144 | /**
145 | * 查询记录
146 | * @author Farmer
147 | * @return bool|record
148 | */
149 | public function select() {
150 | $sql = 'select ' . ($this->field ?: '*') . " from {$this->table} {$this->join} " . ($this->where ? 'where' : '');
151 | $sql .= $this->dealParam();
152 | $result = self::$db->prepare($sql);
153 | if ($result->execute($this->bindParam)) {
154 | return new record($result);
155 | }
156 | return false;
157 | }
158 |
159 | public function count() {
160 | $tmpField = $this->field;
161 | $tmpLimit = $this->limit;
162 | $this->field = '';
163 | $count = $this->field('count(*)')->find()['count(*)'];
164 | $this->field = $tmpField;
165 | $this->limit = $tmpLimit;
166 | return $count;
167 | }
168 |
169 | /**
170 | * 数据更新
171 | * @author Farmer
172 | * @param $set
173 | * @return bool|int
174 | */
175 | public function update($set) {
176 | $data = null;
177 | if (is_string($set)) {
178 | $data = $set;
179 | } else if (is_array($set)) {
180 | foreach ($set as $key => $value) {
181 | if (is_numeric($key)) {
182 | $data .= ',' . $set[$key];
183 | } else {
184 | $data .= ",`{$key}`=?";
185 | $tmpParam[] = $value;
186 | }
187 | }
188 | $this->bindParam = array_merge($tmpParam, $this->bindParam);
189 | $data = substr($data, 1);
190 | }
191 | $sql = "update {$this->table} set $data where" . $this->dealParam();
192 | $result = self::$db->prepare($sql);
193 | if ($result->execute($this->bindParam)) {
194 | return $result->rowCount();
195 | }
196 | return false;
197 | }
198 |
199 | /**
200 | * 删除数据
201 | * @author Farmer
202 | * @return bool|int
203 | */
204 | public function delete() {
205 | $sql = "delete from {$this->table} where" . $this->dealParam();
206 | $result = self::$db->prepare($sql);
207 | if ($result->execute($this->bindParam)) {
208 | return $result->rowCount();
209 | }
210 | return false;
211 | }
212 |
213 | /**
214 | * 对where等进行处理
215 | * @author Farmer
216 | * @return string
217 | */
218 | private function dealParam() {
219 | $sql = $this->where ?: '';
220 | $sql .= $this->order ?: '';
221 | $sql .= $this->limit ?: '';
222 | return $sql;
223 | }
224 |
225 | /**
226 | * 绑定参数
227 | * @author Farmer
228 | * @param $key
229 | * @param string $value
230 | * @return $this
231 | */
232 | public function bind($key, $value = '') {
233 | if (is_array($key)) {
234 | $this->bindParam = array_merge($this->bindParam, $key);
235 | } else {
236 | $this->bindParam[$key] = $value;
237 | }
238 | return $this;
239 | }
240 |
241 | /**
242 | * 排序
243 | * @author Farmer
244 | * @param $field
245 | * @param string $rule
246 | * @return $this
247 | */
248 | public function order($field, $rule = 'desc') {
249 | if ($this->order) {
250 | $this->order .= ",`$field` $rule";
251 | } else {
252 | $this->order = " order by `$field` $rule";
253 | }
254 | return $this;
255 | }
256 |
257 | /**
258 | * 分页
259 | * @author Farmer
260 | * @param $start
261 | * @param int $count
262 | * @return $this
263 | */
264 | public function limit($start, $count = 0) {
265 | if ($count) {
266 | $this->limit = " limit $start,$count";
267 | } else {
268 | $this->limit = " limit $start";
269 | }
270 | return $this;
271 | }
272 |
273 | /**
274 | * 查询出单条数据
275 | * @author Farmer
276 | * @return mixed
277 | */
278 | public function find() {
279 | return $this->limit('1')->select()->fetch();
280 | }
281 |
282 | /**
283 | * 开始事务
284 | * @author Farmer
285 | */
286 | public function begin() {
287 | self::$db->exec('begin');
288 | }
289 |
290 | /**
291 | * 提交事务
292 | * @author Farmer
293 | */
294 | public function commit() {
295 | self::$db->exec('commit');
296 | }
297 |
298 | /**
299 | * 回滚事务
300 | * @author Farmer
301 | */
302 | public function rollback() {
303 | self::$db->exec('rollback');
304 | }
305 |
306 | public function field($field, $alias = '') {
307 | if (is_string($field)) {
308 | if (empty($alias)) {
309 | $this->field .= (empty($this->field) ? '' : ',') . $field . ' ';
310 | } else {
311 | $this->field .= (empty($this->field) ? '' : ',') . $field . ' as ' . $alias . ' ';
312 | }
313 | } else if (is_array($field)) {
314 | foreach ($field as $key => $value) {
315 | if (is_string($key)) {
316 | $this->field .= (empty($this->field) ? '' : ',') . $key . ' as ' . $value . ' ';
317 | } else {
318 | $this->field .= (empty($this->field) ? '' : ',') . $value . ' ';
319 | }
320 | }
321 | }
322 | return $this;
323 | }
324 |
325 | /**
326 | * 上一个插入id
327 | * @author Farmer
328 | * @return int
329 | */
330 | public function lastinsertid() {
331 | return self::$db->lastInsertId();
332 | }
333 |
334 | public function __call($func, $arguments) {
335 | if (is_null(self::$db)) {
336 | return 0;
337 | }
338 | return call_user_func_array(array(
339 | self::$db,
340 | $func
341 | ), $arguments);
342 | }
343 | }
344 |
345 | /**
346 | * 记录集类
347 | * @author Farmer
348 | * @package icf\lib
349 | */
350 | class record {
351 | private $result;
352 |
353 | public function __call($func, $arguments) {
354 | if (is_null($this->result)) {
355 | return 0;
356 | }
357 | return call_user_func_array(array(
358 | $this->result,
359 | $func
360 | ), $arguments);
361 | }
362 |
363 | function __construct(\PDOStatement $result) {
364 | $this->result = $result;
365 | $this->result->setFetchMode(PDO::FETCH_ASSOC);
366 | }
367 |
368 | function fetchAll() {
369 | return $this->result->fetchAll();
370 | }
371 |
372 | function fetch() {
373 | return $this->result->fetch();
374 | }
375 |
376 | }
--------------------------------------------------------------------------------
/icf/lib/info/smtp.php:
--------------------------------------------------------------------------------
1 | _name=$name;
89 | }
90 | /**
91 | * 设置邮件传输代理,如果是可以匿名发送有邮件的服务器,只需传递代理服务器地址就行
92 | * @access public
93 | * @param string $server 代理服务器的ip或者域名
94 | * @param string $username 认证账号
95 | * @param string $password 认证密码
96 | * @param int $port 代理服务器的端口,smtp默认25号端口
97 | * @param boolean $isSecurity 到服务器的连接是否为安全连接,默认false
98 | * @return boolean
99 | */
100 | public function setServer($server, $username = "", $password = "", $port = 25, $isSecurity = false) {
101 | $this->_sendServer = $server;
102 | $this->_port = $port;
103 | $this->_isSecurity = $isSecurity;
104 | $this->_userName = empty($username) ? "" : base64_encode($username);
105 | $this->_password = empty($password) ? "" : base64_encode($password);
106 | return true;
107 | }
108 |
109 | /**
110 | * 设置发件人
111 | * @access public
112 | * @param string $from 发件人地址
113 | * @return boolean
114 | */
115 | public function setFrom($from) {
116 | $this->_from = $from;
117 | return true;
118 | }
119 |
120 | /**
121 | * 设置收件人,多个收件人,调用多次.
122 | * @access public
123 | * @param string $to 收件人地址
124 | * @return boolean
125 | */
126 | public function setReceiver($to) {
127 | $this->_to[] = $to;
128 | return true;
129 | }
130 |
131 | /**
132 | * 设置抄送,多个抄送,调用多次.
133 | * @access public
134 | * @param string $cc 抄送地址
135 | * @return boolean
136 | */
137 | public function setCc($cc) {
138 | $this->_cc[] = $cc;
139 | return true;
140 | }
141 |
142 | /**
143 | * 设置秘密抄送,多个秘密抄送,调用多次
144 | * @access public
145 | * @param string $bcc 秘密抄送地址
146 | * @return boolean
147 | */
148 | public function setBcc($bcc) {
149 | $this->_bcc[] = $bcc;
150 | return true;
151 | }
152 |
153 | /**
154 | * 设置邮件附件,多个附件,调用多次
155 | * @access public
156 | * @param string $file 文件地址
157 | * @return boolean
158 | */
159 | public function addAttachment($file) {
160 | if (!file_exists($file)) {
161 | $this->_errorMessage = "file " . $file . " does not exist.";
162 | return false;
163 | }
164 | $this->_attachment[] = $file;
165 | return true;
166 | }
167 |
168 | /**
169 | * 设置邮件信息
170 | * @access public
171 | * @param string $body 邮件主题
172 | * @param string $subject 邮件主体内容,可以是纯文本,也可是是HTML文本
173 | * @return boolean
174 | */
175 | public function setMail($subject, $body) {
176 | $this->_subject = base64_encode($subject);
177 | $this->_body = base64_encode($body);
178 | return true;
179 | }
180 |
181 | /**
182 | * 发送邮件
183 | * @access public
184 | * @return boolean
185 | */
186 | public function sendMail() {
187 | $command = $this->getCommand();
188 | $this->_isSecurity ? $this->socketSecurity() : $this->socket();
189 | foreach ($command as $value) {
190 | $result = $this->_isSecurity ? $this->sendCommandSecurity($value[0], $value[1]) : $this->sendCommand($value[0], $value[1]);
191 | if ($result) {
192 | continue;
193 | } else {
194 | return false;
195 | }
196 | }
197 | //其实这里也没必要关闭,smtp命令:QUIT发出之后,服务器就关闭了连接,本地的socket资源会自动释放
198 | $this->_isSecurity ? $this->closeSecutity() : $this->close();
199 | return true;
200 | }
201 |
202 | /**
203 | * 返回错误信息
204 | * @return string
205 | */
206 | public function error() {
207 | if (!isset($this->_errorMessage)) {
208 | $this->_errorMessage = "";
209 | }
210 | return $this->_errorMessage;
211 | }
212 |
213 | /**
214 | * 返回mail命令
215 | * @access protected
216 | * @return array
217 | */
218 | protected function getCommand() {
219 | $separator = "----=_Part_" . md5($this->_from . time()) . uniqid(); //分隔符
220 | $command = array(
221 | array("HELO sendmail\r\n", 250)
222 | );
223 | if (!empty($this->_userName)) {
224 | $command[] = array("AUTH LOGIN\r\n", 334);
225 | $command[] = array($this->_userName . "\r\n", 334);
226 | $command[] = array($this->_password . "\r\n", 235);
227 | }
228 | //设置发件人
229 | $command[] = array("MAIL FROM: <" . $this->_from . ">\r\n", 250);
230 | $header = "FROM: =?utf-8?b?".base64_encode($this->_name)."?= <" . $this->_from . ">\r\n";
231 | //设置收件人
232 | if (!empty($this->_to)) {
233 | $count = count($this->_to);
234 | if ($count == 1) {
235 | $command[] = array("RCPT TO: <" . $this->_to[0] . ">\r\n", 250);
236 | $header .= "TO: <" . $this->_to[0] . ">\r\n";
237 | } else {
238 | for ($i = 0; $i < $count; $i++) {
239 | $command[] = array("RCPT TO: <" . $this->_to[$i] . ">\r\n", 250);
240 | if ($i == 0) {
241 | $header .= "TO: <" . $this->_to[$i] . ">";
242 | } elseif ($i + 1 == $count) {
243 | $header .= ",<" . $this->_to[$i] . ">\r\n";
244 | } else {
245 | $header .= ",<" . $this->_to[$i] . ">";
246 | }
247 | }
248 | }
249 | }
250 | //设置抄送
251 | if (!empty($this->_cc)) {
252 | $count = count($this->_cc);
253 | if ($count == 1) {
254 | $command[] = array("RCPT TO: <" . $this->_cc[0] . ">\r\n", 250);
255 | $header .= "CC: <" . $this->_cc[0] . ">\r\n";
256 | } else {
257 | for ($i = 0; $i < $count; $i++) {
258 | $command[] = array("RCPT TO: <" . $this->_cc[$i] . ">\r\n", 250);
259 | if ($i == 0) {
260 | $header .= "CC: <" . $this->_cc[$i] . ">";
261 | } elseif ($i + 1 == $count) {
262 | $header .= ",<" . $this->_cc[$i] . ">\r\n";
263 | } else {
264 | $header .= ",<" . $this->_cc[$i] . ">";
265 | }
266 | }
267 | }
268 | }
269 | //设置秘密抄送
270 | if (!empty($this->_bcc)) {
271 | $count = count($this->_bcc);
272 | if ($count == 1) {
273 | $command[] = array("RCPT TO: <" . $this->_bcc[0] . ">\r\n", 250);
274 | $header .= "BCC: <" . $this->_bcc[0] . ">\r\n";
275 | } else {
276 | for ($i = 0; $i < $count; $i++) {
277 | $command[] = array("RCPT TO: <" . $this->_bcc[$i] . ">\r\n", 250);
278 | if ($i == 0) {
279 | $header .= "BCC: <" . $this->_bcc[$i] . ">";
280 | } elseif ($i + 1 == $count) {
281 | $header .= ",<" . $this->_bcc[$i] . ">\r\n";
282 | } else {
283 | $header .= ",<" . $this->_bcc[$i] . ">";
284 | }
285 | }
286 | }
287 | }
288 | //主题
289 | $header .= "Subject: =?UTF-8?B?" . $this->_subject . "?=\r\n";
290 | if (isset($this->_attachment)) {
291 | //含有附件的邮件头需要声明成这个
292 | $header .= "Content-Type: multipart/mixed;\r\n";
293 | } elseif (false) {
294 | //邮件体含有图片资源的,且包含的图片在邮件内部时声明成这个,如果是引用的远程图片,就不需要了
295 | $header .= "Content-Type: multipart/related;\r\n";
296 | } else {
297 | //html或者纯文本的邮件声明成这个
298 | $header .= "Content-Type: multipart/alternative;\r\n";
299 | }
300 | //邮件头分隔符
301 | $header .= "\t" . 'boundary="' . $separator . '"';
302 | $header .= "\r\nMIME-Version: 1.0\r\n";
303 | //这里开始是邮件的body部分,body部分分成几段发送
304 | $header .= "\r\n--" . $separator . "\r\n";
305 | $header .= "Content-Type:text/html; charset=utf-8\r\n";
306 | $header .= "Content-Transfer-Encoding: base64\r\n\r\n";
307 | $header .= $this->_body . "\r\n";
308 | $header .= "--" . $separator . "\r\n";
309 | //加入附件
310 | if (!empty($this->_attachment)) {
311 | $count = count($this->_attachment);
312 | for ($i = 0; $i < $count; $i++) {
313 | $header .= "\r\n--" . $separator . "\r\n";
314 | $header .= "Content-Type: " . $this->getMIMEType($this->_attachment[$i]) . '; name="=?UTF-8?B?' . base64_encode(basename($this->_attachment[$i])) . '?="' . "\r\n";
315 | $header .= "Content-Transfer-Encoding: base64\r\n";
316 | $header .= 'Content-Disposition: attachment; filename="=?UTF-8?B?' . base64_encode(basename($this->_attachment[$i])) . '?="' . "\r\n";
317 | $header .= "\r\n";
318 | $header .= $this->readFile($this->_attachment[$i]);
319 | $header .= "\r\n--" . $separator . "\r\n";
320 | }
321 | }
322 | //结束邮件数据发送
323 | $header .= "\r\n.\r\n";
324 |
325 | $command[] = array("DATA\r\n", 354);
326 | $command[] = array($header, 250);
327 | $command[] = array("QUIT\r\n", 221);
328 | return $command;
329 | }
330 |
331 | /**
332 | * 发送命令
333 | * @access protected
334 | * @param string $command 发送到服务器的smtp命令
335 | * @param int $code 期望服务器返回的响应吗
336 | * @return boolean
337 | */
338 | protected function sendCommand($command, $code) {
339 | // echo 'Send command:' . $command . ',expected code:' . $code . '
';
340 | //发送命令给服务器
341 | try {
342 | if (socket_write($this->_socket, $command, strlen($command))) {
343 | //当邮件内容分多次发送时,没有$code,服务器没有返回
344 | if (empty($code)) {
345 | return true;
346 | }
347 | //读取服务器返回
348 | $data = trim(socket_read($this->_socket, 1024));
349 | // echo 'response:' . $data . '
';
350 | if ($data) {
351 | $pattern = "/^" . $code . "+?/";
352 | if (preg_match($pattern, $data)) {
353 | return true;
354 | } else {
355 | $this->_errorMessage = "Error:" . $data . "|**| command:";
356 | return false;
357 | }
358 | } else {
359 | $this->_errorMessage = "Error:" . socket_strerror(socket_last_error());
360 | return false;
361 | }
362 | } else {
363 | $this->_errorMessage = "Error:" . socket_strerror(socket_last_error());
364 | return false;
365 | }
366 | } catch (Exception $e) {
367 | $this->_errorMessage = "Error:" . $e->getMessage();
368 | }
369 | }
370 |
371 | /**
372 | * 安全连接发送命令
373 | * @access protected
374 | * @param string $command 发送到服务器的smtp命令
375 | * @param int $code 期望服务器返回的响应吗
376 | * @return boolean
377 | */
378 | protected function sendCommandSecurity($command, $code) {
379 | // echo 'Send command:' . $command . ',expected code:' . $code . '
';
380 | try {
381 | if (fwrite($this->_socket, $command)) {
382 | //当邮件内容分多次发送时,没有$code,服务器没有返回
383 | if (empty($code)) {
384 | return true;
385 | }
386 | //读取服务器返回
387 | $data = trim(fread($this->_socket, 1024));
388 | // echo 'response:' . $data . '
';
389 | if ($data) {
390 | $pattern = "/^" . $code . "+?/";
391 | if (preg_match($pattern, $data)) {
392 | return true;
393 | } else {
394 | $this->_errorMessage = "Error:" . $data . "|**| command:";
395 | return false;
396 | }
397 | } else {
398 | return false;
399 | }
400 | } else {
401 | $this->_errorMessage = "Error: " . $command . " send failed";
402 | return false;
403 | }
404 | } catch (Exception $e) {
405 | $this->_errorMessage = "Error:" . $e->getMessage();
406 | }
407 | }
408 |
409 | /**
410 | * 读取附件文件内容,返回base64编码后的文件内容
411 | * @access protected
412 | * @param string $file 文件
413 | * @return mixed
414 | */
415 | protected function readFile($file) {
416 | if (file_exists($file)) {
417 | $file_obj = file_get_contents($file);
418 | return base64_encode($file_obj);
419 | } else {
420 | $this->_errorMessage = "file " . $file . " dose not exist";
421 | return false;
422 | }
423 | }
424 |
425 | /**
426 | * 获取附件MIME类型
427 | * @access protected
428 | * @param string $file 文件
429 | * @return mixed
430 | */
431 | protected function getMIMEType($file) {
432 | if (file_exists($file)) {
433 | $mime = mime_content_type($file);
434 | /*if(! preg_match("/gif|jpg|png|jpeg/", $mime)){
435 | $mime = "application/octet-stream";
436 | }*/
437 | return $mime;
438 | } else {
439 | return false;
440 | }
441 | }
442 |
443 | /**
444 | * 建立到服务器的网络连接
445 | * @access protected
446 | * @return boolean
447 | */
448 | protected function socket() {
449 | //创建socket资源
450 | $this->_socket = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));
451 | if (!$this->_socket) {
452 | $this->_errorMessage = socket_strerror(socket_last_error());
453 | return false;
454 | }
455 | socket_set_block($this->_socket);//设置阻塞模式
456 | //连接服务器
457 | if (!socket_connect($this->_socket, $this->_sendServer, $this->_port)) {
458 | $this->_errorMessage = socket_strerror(socket_last_error());
459 | return false;
460 | }
461 | $str = socket_read($this->_socket, 1024);
462 | if (!preg_match("/220+?/", $str)) {
463 | $this->_errorMessage = $str;
464 | return false;
465 | }
466 | return true;
467 | }
468 |
469 | /**
470 | * 建立到服务器的SSL网络连接
471 | * @access protected
472 | * @return boolean
473 | */
474 | protected function socketSecurity() {
475 | $remoteAddr = "tcp://" . $this->_sendServer . ":" . $this->_port;
476 | $this->_socket = stream_socket_client($remoteAddr, $errno, $errstr, 30);
477 | if (!$this->_socket) {
478 | $this->_errorMessage = $errstr;
479 | return false;
480 | }
481 | //设置加密连接,默认是ssl,如果需要tls连接,可以查看php手册stream_socket_enable_crypto函数的解释
482 | stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_SSLv23_CLIENT);
483 | stream_set_blocking($this->_socket, 1); //设置阻塞模式
484 | $str = fread($this->_socket, 1024);
485 | if (!preg_match("/220+?/", $str)) {
486 | $this->_errorMessage = $str;
487 | return false;
488 | }
489 | return true;
490 | }
491 |
492 | /**
493 | * 关闭socket
494 | * @access protected
495 | * @return boolean
496 | */
497 | protected function close() {
498 | if (isset($this->_socket) && is_object($this->_socket)) {
499 | $this->_socket->close();
500 | return true;
501 | }
502 | $this->_errorMessage = "No resource can to be close";
503 | return false;
504 | }
505 |
506 | /**
507 | * 关闭安全socket
508 | * @access protected
509 | * @return boolean
510 | */
511 | protected function closeSecutity() {
512 | if (isset($this->_socket) && is_object($this->_socket)) {
513 | stream_socket_shutdown($this->_socket, STREAM_SHUT_WR);
514 | return true;
515 | }
516 | $this->_errorMessage = "No resource can to be close";
517 | return false;
518 | }
519 | }
--------------------------------------------------------------------------------