├── 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 | } --------------------------------------------------------------------------------