huwhois 1 年之前
父节点
当前提交
a90da9a326

+ 40 - 56
application/App.php

@ -1,75 +1,59 @@
1 1
<?php
2 2
namespace app;
3
use \app\Route;
4 3
5
class App{
6
    public static $classMap = array();#用于判断类是否存在,节约性能
7
 
4
use RuntimeException;
5
6
use app\utils\Str;
7
use app\utils\RRException;
8
9
class App {
10
    /**
11
     * 用于判断类是否存在
12
     */
13
    protected $classMap = array();
14
8 15
    /**
9 16
     * 运行控制器和方法
10 17
     * @throws \Exception
11 18
     */
12
    public static function run()
19
    public function run()
13 20
    {
14
        $ctrlClass = '\\app\\Index';
15
        $action = self::getAction();
16
        $ctrl = new $ctrlClass();
17
        $ctrl->$action();
18
    }
21
        $request = Request::getInstance();
19 22
20
    public static function getAction()
21
    {
22
        $pathinfo = "";
23
        if (isset($_SERVER['PATH_INFO']) && !empty($_SERVER['PATH_INFO']) ) {
24
            $pathinfo = $_SERVER['PATH_INFO'];
25
        } else {
26
            $pathinfo = strpos($_SERVER['REQUEST_URI'], '?') ? strstr($_SERVER['REQUEST_URI'], '?', true) : $_SERVER['REQUEST_URI'];
23
        try {
24
            // 实例化控制器
25
            $instance = $this->makeController($request->controller);
26
        } catch (RuntimeException $e) {
27
            throw new RRException($e->getMessage(), 404);
27 28
        }
28 29
30
        $action = $request->actionName;
29 31
30
        $action = '';
31
        $doc = '';
32
        if (is_callable([$instance, $action])) {
33
            $instance->$action();
34
        } else {
35
            // 操作不存在
36
            throw new RRException('method not exists:'.get_class($instance) . '->' . $action . '()', 404);
37
        }
38
    }
32 39
33
        if ($pathinfo) {
34
            // $pathArr = explode('/',trim($pathinfo,'/'));//数组
35
            // if (isset($pathArr[0])){
36
            //     $action = camelize($pathArr[0]);
37
            //     unset($pathArr[0]);
38
            // }
39
            //url 多余部分转换成GET eg:index/id/1 实现get传值
40
            // $count = count($pathArr) + 1;
40
    public function makeController(string $controller, bool $newInstance = false)
41
    {
42
        $class =  'app' . '\\' . 'controller' . '\\' . $controller;
43
        if (class_exists($class)) {
44
            if (isset($this->classMap[$class]) && !$newInstance) {
45
                return $this->classMap[$class];
46
            }
41 47
42
            // $i = 1;
43
            // while ($i < $count){
44
            //     if (isset($pathArr[$i+1])){
45
            //         $_GET[$pathArr[$i]] = $pathArr[$i+1];
46
            //     }
47
            //     $i = $i + 2;
48
            // };
49
            // foreach ($pathArr as $value) {
50
            //     $doc .= '/' . $value;
51
            // }
52
            // if (isset($pathArr[1])) {
53
            //     $_GET['doc'] = $pathArr[1];
54
            // }
48
            $instance = new $class;
55 49
56
            // 提取 action, 多余部分转为 markdown 文件路径
57
            $pathinfo = ltrim($pathinfo, '/');
58
            
59
            if ($index = strpos($pathinfo, '/')) {
60
                $action = substr($pathinfo,0,$index);
61
            } else {
62
                $action = $pathinfo;
50
            if (!$newInstance) {
51
                $this->classMap[$class] = $instance;
63 52
            }
64
            // var_dump($pathinfo);
65
66
            $doc = substr($pathinfo, strlen($action));
53
            
54
            return $instance;            
55
        } else {
56
            throw new RuntimeException('class not exists:' . $class);
67 57
        }
68
        $action = $action ? : "index";
69
        
70
        $GLOBALS['action'] = $action;
71
        $GLOBALS['doc'] = $doc;
72
        
73
        return $action;
74 58
    }
75 59
}

+ 119 - 0
application/Request.php

@ -0,0 +1,119 @@
1
<?php
2
namespace app;
3
4
use app\utils\Str;
5
6
class Request
7
{
8
    /**
9
     * 请求方法是否为Post
10
     * @var bool
11
     */
12
    protected $isPost = false;
13
14
    /**
15
     * 控制器名
16
     * @var string
17
     */
18
    public $controller;
19
20
    /**
21
     * 操作名
22
     * @var string
23
     */
24
    public $actionName;
25
26
    /**
27
     * 参数
28
     * @var array
29
     */
30
    public $params;
31
32
    /**
33
     * 初始化
34
     * @var bool
35
     */
36
    protected static $initialized = false;
37
38
    //创建静态私有的变量保存该类对象
39
    private static $instance;
40
41
    //防止直接创建对象
42
    private function __construct(){
43
        
44
    }
45
46
    public static function getInstance($initforce = false){
47
        //判断$instance是否是APP的对象 没有则创建
48
        if (!self::$instance instanceof self) {
49
            self::$instance = new self();
50
        }
51
52
        // 判断是否强制初始化及是否未初始化
53
        if ($initforce || !self::$initialized) {
54
            self::$instance->init();
55
        }
56
57
        return self::$instance;
58
    }
59
60
    public function init()
61
    {
62
        self::$initialized = true;
63
64
        if ($_SERVER['REQUEST_METHOD'] == 'POST') { 
65
            $this->isPost = true;
66
        }
67
68
        $pathinfo = "";
69
        if (isset($_SERVER['PATH_INFO']) && !empty($_SERVER['PATH_INFO']) ) {
70
            $pathinfo = $_SERVER['PATH_INFO'];
71
        } else {
72
            $pathinfo = strpos($_SERVER['REQUEST_URI'], '?') ? strstr($_SERVER['REQUEST_URI'], '?', true) : $_SERVER['REQUEST_URI'];
73
        }
74
75
        if (is_string($pathinfo)) {
76
            $result = explode('/', trim($pathinfo,'/'));
77
        }
78
79
        // 获取控制器名
80
        // $controller = strip_tags($result[0] ?: 'Index');
81
82
        // $this->controller = camelize($controller);
83
        
84
        // 获取操作名
85
        // $this->actionName = strip_tags(isset($result[1]) ? $result[1] : 'index');
86
        
87
        // 控制器名只用 Index
88
        $this->controller = "Index";
89
90
        $this->actionName = strip_tags(isset($result[0]) && !empty($result[0]) ? $result[0] : 'index');
91
92
        // 文档路径
93
        $doc = '';
94
        if (count($result) > 1) 
95
        {
96
            for ($i = 1; $i < count($result); $i++) {
97
                $doc .= '/' . $result[$i];
98
            }
99
        }
100
101
        $this->params = array_merge($_GET, $_POST, ['doc'=>$doc]);
102
103
        return $this;
104
    }
105
106
    /**
107
     * 是否初始化过
108
     * @return bool
109
     */
110
    public function initialized()
111
    {
112
        return $this->initialized;
113
    }
114
115
    public function isPost()
116
    {
117
        return $this->isPost;
118
    }
119
}

+ 29 - 0
application/Session.php

@ -0,0 +1,29 @@
1
<?php
2
namespace app;
3
4
class Session
5
{
6
    public static function set($name, $value)
7
    {
8
        $_SESSION[$name] = $value;
9
    }
10
 
11
    public static function get($name)
12
    {
13
        if(isset($_SESSION[$name]))
14
            return $_SESSION[$name];
15
        else
16
            return false;
17
    }
18
 
19
    public static function del($name)
20
    {
21
        unset($_SESSION[$name]);
22
    }
23
 
24
    public static function destroy()
25
    {
26
        $_SESSION = array();
27
        session_destroy();
28
    }
29
}

+ 14 - 9
application/View.php

@ -1,20 +1,21 @@
1 1
<?php
2
2 3
namespace app;
3 4
4 5
class View
5 6
{
6
    public $assign;#用于判断类是否存在,节约性能
7
    public $assign; #用于判断类是否存在,节约性能
7 8
8 9
    /**
9 10
     * 变量名替换
10 11
     * @param $name
11 12
     * @param $value
12 13
     */
13
    public function assign($name,$value)
14
    public function assign($name, $value)
14 15
    {
15 16
        $this->assign[$name] = $value;
16 17
    }
17
 
18
18 19
    /**
19 20
     * 显示视图
20 21
     * @param $file
@ -28,17 +29,21 @@ class View
28 29
    //     }
29 30
    // }
30 31
31
    public function fetch($file = ""){
32
        // var_dump($this->assign);
33
        // exit;
32
    public function fetch($file = "")
33
    {
34
        $request = Request::getInstance();
35
34 36
        if (!empty($this->assign)) {
35 37
            extract($this->assign);
36 38
        }
39
37 40
        if ($file) {
38
            $filename = ROOT_PATH ."html" . DS . $file;
41
            $filename = ROOT_PATH . DIRECTORY_SEPARATOR . "view" . DIRECTORY_SEPARATOR . $file;
39 42
        } else {
40
            $filename = ROOT_PATH ."html" . DS . $GLOBALS['action'] . '.html';
43
            $filename = ROOT_PATH . DIRECTORY_SEPARATOR . "view" . DIRECTORY_SEPARATOR . $request->actionName . '.php';
41 44
        }
45
42 46
        return require($filename);
47
        die();
43 48
    }
44
}
49
}

+ 6 - 6
application/common.php

@ -1,14 +1,14 @@
1 1
<?php
2 2
/**
3
 * 下划线转驼峰
3
 * 下划线转驼峰(首字母大写)
4 4
 * 思路:
5 5
 * step1.原字符串转小写,原字符串中的分隔符用空格替换,在字符串开头加上分隔符
6 6
 * step2.将字符串中每个单词的首字母转换为大写,再去空格,去字符串首部附加的分隔符.
7 7
 */
8
function camelize($uncamelized_words, $separator='_')
8
function camelize($uncamelized_words, $separator = '_')
9 9
{
10
    $uncamelized_words = $separator. str_replace($separator, " ", strtolower($uncamelized_words));
11
    return ltrim(str_replace(" ", "", ucwords($uncamelized_words)), $separator );
10
    $uncamelized_words = $separator . str_replace($separator, " ", strtolower($uncamelized_words));
11
    return ucwords(ltrim(str_replace(" ", "", ucwords($uncamelized_words)), $separator));
12 12
}
13 13
14 14
/**
@ -16,7 +16,7 @@ function camelize($uncamelized_words, $separator='_')
16 16
 * 思路:
17 17
 * 小写和大写紧挨一起的地方,加上分隔符,然后全部转小写
18 18
 */
19
function uncamelize($camelCaps, $separator='_')
19
function uncamelize($camelCaps, $separator = '_')
20 20
{
21 21
    return strtolower(preg_replace('/([a-z])([A-Z])/', "$1" . $separator . "$2", $camelCaps));
22 22
}
@ -44,4 +44,4 @@ function escapeString($content)
44 44
        }
45 45
    }
46 46
    return $content;
47
}
47
}

+ 4 - 0
application/config.php

@ -0,0 +1,4 @@
1
<?php
2
return [
3
    'app_namespace' => 'app',
4
];

+ 208 - 0
application/controller/Index.php

@ -0,0 +1,208 @@
1
<?php
2
namespace app\controller;
3
4
// use \Firebase\JWT\JWT;
5
6
use app\Request;
7
use app\View;
8
use app\model\User;
9
use app\Session;
10
use app\utils\RRException;
11
use app\utils\ParsedownExtension;
12
13
class Index extends View
14
{
15
    public function auth()
16
    {
17
        if (!Session::get('userid')) {
18
            echo "您未登录请登录";
19
            header("Location: /login", TRUE, 301);
20
21
            exit();
22
        }
23
    }
24
25
    public function index()
26
    {
27
        $this->auth();
28
29
        $request = Request::getInstance();
30
31
        $doc = $request->params['doc'];
32
33
        $doc = ltrim($doc, '/');
34
        
35
        if (substr($doc, -1) === '/') {
36
            $doc = $doc . "index.md";
37
        }
38
39
        $doc = empty($doc) ? 'index.md' : $doc;
40
        
41
        if (pathinfo($doc,PATHINFO_EXTENSION) != 'md') {
42
            $doc = $doc . ".md";
43
        }
44
        
45
        $filename = DATA_PATH . $doc;
46
        $text = "";
47
        $toc = "";
48
        $content = "";
49
50
        if ($is_file_exists = file_exists($filename)) {
51
            $parsedownExtension = new ParsedownExtension();
52
            $parsedownExtension->setTocEnabled(true);
53
            $text = file_get_contents($filename);
54
            $res = $parsedownExtension->text($text);
55
            $toc = $res['toc'];
56
            $content = $res['content'];
57
        }
58
        
59
        $this->assign('doc',$doc);
60
        $this->assign('is_file_exists', $is_file_exists);
61
        $this->assign('text',$text);
62
        $this->assign('toc',$toc);
63
        $this->assign('content',$content);
64
65
        $this->fetch();
66
    }
67
68
    public function editor()
69
    {
70
        $doc = $GLOBALS['doc'];
71
        var_dump($doc);
72
        exit;
73
        $this->fetch();
74
    }
75
76
    public function save()
77
    {
78
        $this->auth();
79
80
        // 获取payload json数据,转换成数组形式
81
        $postData = file_get_contents('php://input');
82
        $requests = !empty($postData) ? json_decode($postData, true) : [];
83
84
        $doc = $requests['doc'];
85
        $content = $requests['content'];
86
87
        $pathinfo = pathinfo($doc);
88
        
89
        $dir_name = DATA_PATH . $pathinfo['dirname'];
90
91
        if (!is_dir($dir_name) && !mkdir($dir_name, 0744, true)) {
92
            die(json_encode(['code'=>2, 'msg'=>'目录创建失败']));
93
        }
94
95
        $filename = DATA_PATH . $doc;
96
97
        $res = file_put_contents($filename, $content);
98
99
        if ($res === false) {
100
            echo json_encode(['code'=>2, 'msg'=>'保存失败']);
101
        } else {
102
            echo json_encode(['code'=>0, 'msg'=>'保存成功, 字数:' . $res]);
103
        }
104
        die();
105
    }
106
107
    public function login()
108
    {
109
        $this->fetch();
110
    }
111
112
    public function dologin()
113
    {
114
        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
115
            $username = strip_tags(htmlentities($_POST['username']));
116
            $password = strip_tags(htmlentities($_POST['password']));
117
118
            if (!$username || !$password) {
119
                throw new RRException("用户名或密码不能为空!", 1);
120
            }
121
            
122
            $user = new User();
123
            
124
            $info = $user->getInfoByUsername($username);
125
126
            if (!$info) {
127
                throw new RRException("用户名或密码错误!", 1);
128
            }
129
130
            if (md5($password) !== $info['password']) {
131
                throw new RRException("用户名或密码错误!", 1);
132
            }
133
134
            // // 用户名和密码正确,则签发tokon
135
            // $nowtime = time();
136
            // $jwtInfo = [
137
            //     'iss' => 'huwhois@163.com', //签发者
138
            //     'iat' => $nowtime, //签发时间
139
            //     'nbf' => $nowtime + 10, //在什么时间之后该jwt才可用
140
            //     'exp' => $nowtime + 64800, //过期时间-18h
141
            //     'data' => [
142
            //         'userid' => $user['id'],
143
            //         'username' => $username
144
            //     ]
145
            // ];
146
            // $token = JWT::encode($jwtInfo, KEY);
147
            // echo json_encode(['code'=>0, 'msg'=>'success', 'token'=>$token]);
148
            // 存 session
149
            Session::set('userid', $info['id']);
150
            Session::set('username', $info['username']);
151
152
            echo json_encode(['code'=>0, 'msg'=>'success']);
153
        }
154
        die();
155
    }
156
157
    // private function validate ()
158
    // {
159
    //     $jwt = isset($_SERVER['HTTP_TOKEN']) ? $_SERVER['HTTP_TOKEN'] : '';
160
    //     if (empty($jwt)) {
161
    //         throw new RRException("You do not have permission to access.", 401);
162
    //     }
163
    
164
    //     try {
165
    //         JWT::$leeway = 60;
166
    //         $decoded = JWT::decode($jwt, KEY, ['HS256']);
167
    //         $arr = (array)$decoded;
168
    //         if ($arr['exp'] < time()) {
169
    //             throw new RRException("认证信息已过期, 请重新登录.", 401);
170
    //         }
171
    //     } catch(\Exception $e) {
172
    //         throw new RRException($e->getMessage(), 401);
173
    //     }
174
175
    //     return true;
176
    // }
177
178
    public function userlist()
179
    {
180
        $list = (new User())->dataList();
181
182
        $this->assign('list', $list);
183
184
        $this->fetch();
185
    }
186
187
    public function userdelete()
188
    {
189
        $request = Request::getInstance();
190
191
        if ($request->isPost()) {
192
            $id = isset($request->params['userid']) ? (int) $request->params['userid'] : 0;
193
    
194
            if (!$id)
195
            {
196
                throw new RRException('userid 不能为空', 1);
197
            }
198
199
            $res = (new User())->deleteById($id);
200
201
            if ($res) {
202
                throw new RRException('操作成功', 0); 
203
            } else {
204
                throw new RRException('操作失败', 1); 
205
            }
206
        }
207
    }
208
}

+ 3 - 10
application/model/MySqlite.php

@ -1,5 +1,5 @@
1 1
<?php
2
namespace app;
2
namespace app\model;
3 3
4 4
class MySqlite
5 5
{
@ -8,7 +8,7 @@ class MySqlite
8 8
9 9
    public function __construct()
10 10
    {
11
        $mydb = new \SQLite3(DB . DS . 'mysqlitedb.db');
11
        $mydb = new \SQLite3(DB . DIRECTORY_SEPARATOR . 'mysqlitedb.sqlite');
12 12
        if (!$mydb) {
13 13
            throw new \Exception("$mydb->lastErrorMsg()", 1);
14 14
        } else {
@ -139,13 +139,6 @@ class MySqlite
139 139
        return $data;
140 140
    }
141 141
    
142
143
    //public function list($where='')
144
    //{
145
    //    $sql = "select * from $this->tablename $where;";
146
    //    return $this->select($sql);
147
    //}
148
149 142
    public function listByName($name='', $order = '', $desc = false)
150 143
    {
151 144
        $where = "";
@ -205,8 +198,8 @@ class MySqlite
205 198
     */
206 199
    public function deleteById($id)
207 200
    {
208
        $sql = "DELETE FROM `$this->tablename` WHERE `id` IN(";
209 201
        if (is_array($id)) {
202
            $sql = "DELETE FROM `$this->tablename` WHERE `id` IN(";
210 203
            for ($i=0; $i < count($id); $i++) { 
211 204
                $sql .= $id[$i] . ',';
212 205
            }

+ 31 - 0
application/model/User.php

@ -0,0 +1,31 @@
1
<?php
2
namespace app\model;
3
4
class User extends MySqlite
5
{
6
    protected $tablename = 'sys_user';
7
8
    protected $pk = 'id';
9
10
    protected $schema = [
11
        "id"          => "INTEGER",
12
        "username"    => "TEXT",
13
        "password"    => "TEXT",
14
        "create_time" => "INTEGER",
15
    ];
16
17
    public function __construct()
18
    {
19
        parent::__construct();
20
    }
21
22
    public function getInfoByUsername($username)
23
    {
24
        $sql = "select * from " . $this->tablename . " where username='" . $username . "' limit 1";
25
26
        $data = $this->getOne($sql);
27
28
        return $data;
29
    }
30
}
31

+ 14 - 11
application/start.php

@ -3,23 +3,26 @@ namespace app;
3 3
4 4
//定义系统常量
5 5
define("DB", __DIR__ . '/../db');
6
define("DS", DIRECTORY_SEPARATOR);
7 6
define("VENDOR", __DIR__ . '/../vendor');
8 7
9 8
// 环境常量
10 9
define('IS_CLI', PHP_SAPI == 'cli' ? true : false);
11 10
define('IS_WIN', strpos(PHP_OS, 'WIN') !== false);
12 11
13
require "function.php";
12
require "common.php";
13
14
//注册加载类函数
15
spl_autoload_register(function($class) {
16
    $filename = APP_PATH . strtr(str_replace('app\\', '', $class), '\\', DIRECTORY_SEPARATOR) . '.php';
17
    if (file_exists($filename)) {
18
        include $filename;
19
    }
20
});
14 21
15
// 加载使用到的类文件
16
require (APP_PATH . "App.php");
17
require (APP_PATH . "View.php");
18
require (APP_PATH . "Index.php");
19
require (APP_PATH . "MySqlite.php");
20
require (APP_PATH . "RRException.php");
21
require (APP_PATH . "parsedown/Parsedown.php");
22
require (APP_PATH . "parsedown/ParsedownExtension.php");
23 22
require (VENDOR . "/autoload.php");
23
24
// 开启 session
25
session_start();
26
24 27
// 执行应用
25
App::run();
28
(new App())->run();

+ 60 - 0
application/utils/JWTUtils.php

@ -0,0 +1,60 @@
1
<?php
2
3
declare(strict_types=1);
4
5
namespace app\utils;
6
7
use \Firebase\JWT\JWT;
8
9
/**
10
 * PHP实现jwt
11
 */
12
class JWTUtils extends JWT
13
{
14
    //使用HMAC生成信息摘要时所使用的密钥
15
    private static $key = 'bf731bcb3f5e52ec1b8b12c95f503d7a';
16
17
    /**
18
     * 获取jwt token
19
     * @param array $payload jwt载荷   格式如下非必须
20
     * [
21
     *  'iss'=>'jwt_admin',  //该JWT的签发者
22
     *  'iat'=>time(),  //签发时间
23
     *  'exp'=>time()+7200,  //过期时间
24
     *  'nbf'=>time()+60,  //该时间之前不接收处理该Token
25
     *  'sub'=>'www.admin.com',  //面向的用户
26
     *  'jti'=>md5(uniqid('JWT').time())  //该Token唯一标识
27
     * ]
28
     * @return bool|string
29
     */
30
    public static function getToken(array $payload)
31
    {
32
        if (is_array($payload)) {
33
            $token = self::encode($payload, self::$key);
34
35
            return $token;
36
        } else {
37
            return false;
38
        }
39
    }
40
41
    /**
42
     * 验证token是否有效,默认验证exp,nbf,iat时间
43
     * @param string $Token 需要验证的token
44
     * @return bool|string
45
     */
46
    public static function verifyToken(string $Token)
47
    {
48
        try {
49
            self::$leeway = 60;
50
            $decoded = self::decode($Token, self::$key, ['HS256']);
51
            $arr = (array)$decoded;
52
            if ($arr['exp'] < time()) {
53
                throw new RRException("认证信息已过期, 请重新登录.", 401);
54
            }
55
            return true;
56
        } catch(\Exception $e) {
57
            throw new RRException($e->getMessage(), 401);
58
        }
59
    }
60
}

+ 18 - 0
application/utils/RRException.php

@ -0,0 +1,18 @@
1
<?php
2
namespace app\utils;
3
use RuntimeException;
4
5
class RRException extends RuntimeException
6
{
7
    protected  $msg;
8
    protected  $code = 500;
9
10
    public function __construct($message = "", $code = 0)
11
    {
12
        $res['msg'] = $message;
13
        $res['code'] = $code;
14
15
        echo json_encode($res);
16
        exit;
17
    }
18
}