mirror of
https://github.com/newnius/YAO-portal.git
synced 2025-12-13 09:06:43 +00:00
init & add agent & add job
This commit is contained in:
34
util4p/AccessController.class.php
Executable file
34
util4p/AccessController.class.php
Executable file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
class AccessController
|
||||
{
|
||||
private static $rules_array = array();
|
||||
|
||||
/*
|
||||
* set privilege bitmap
|
||||
* sample $map = array(
|
||||
* 'post.add' => array('Admin', 'Moderator', 'User'),
|
||||
* 'post.comment' => array'Admin', 'Moderator', 'User'),
|
||||
* 'post.pin' => array('Admin', 'Moderator'),
|
||||
* 'user.block' => array('Admin')
|
||||
* );
|
||||
*/
|
||||
public static function setMap(array $map)
|
||||
{
|
||||
if (is_array($map)) {
|
||||
self::$rules_array = $map;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* AccessController::hasAccess('Moderator', 'user.block');
|
||||
*/
|
||||
public static function hasAccess($role, $operation)
|
||||
{
|
||||
if (array_key_exists($operation, self::$rules_array)) {
|
||||
return in_array($role, self::$rules_array[$operation]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
165
util4p/CRLogger.class.php
Executable file
165
util4p/CRLogger.class.php
Executable file
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
require_once('util.php');
|
||||
require_once('CRObject.class.php');
|
||||
require_once('SQLBuilder.class.php');
|
||||
require_once('MysqlPDO.class.php');
|
||||
|
||||
class CRLogger
|
||||
{
|
||||
const LEVEL_DEBUG = 1;
|
||||
const LEVEL_INFO = 2;
|
||||
const LEVEL_WARN = 3;
|
||||
const LEVEL_ERROR = 4;
|
||||
|
||||
private static $db_table = 'cr_log';
|
||||
|
||||
public static function configure(CRObject $config)
|
||||
{
|
||||
self::$db_table = $config->get('db_table', self::$db_table);
|
||||
}
|
||||
|
||||
public static function log(CRObject $log)
|
||||
{
|
||||
$scope = $log->get('scope', '');
|
||||
$tag = $log->get('tag');
|
||||
$level = $log->getInt('level', self::LEVEL_INFO);
|
||||
$ip = $log->get('ip', cr_get_client_ip(false));
|
||||
$time = $log->getInt('time', time());
|
||||
$content = $log->get('content');
|
||||
|
||||
$key_values = array(
|
||||
'scope' => '?', 'tag' => '?', 'level' => '?', 'ip' => '?', 'time' => '?', 'content' => '?'
|
||||
);
|
||||
$builder = new SQLBuilder();
|
||||
$builder->insert(self::$db_table, $key_values);
|
||||
$sql = $builder->build();
|
||||
$params = array($scope, $tag, $level, ip2long($ip), $time, $content);
|
||||
return (new MysqlPDO())->execute($sql, $params);
|
||||
}
|
||||
|
||||
public static function search(CRObject $filter)
|
||||
{
|
||||
$scope = $filter->get('scope');
|
||||
$tag = $filter->get('tag');
|
||||
$level_min = $filter->getInt('level_min');
|
||||
$ip = $filter->get('ip');
|
||||
$time_begin = $filter->getInt('time_begin');
|
||||
$time_end = $filter->getInt('time_end');
|
||||
$offset = $filter->getInt('offset', 0);
|
||||
$limit = $filter->getInt('limit', -1);
|
||||
$order = $filter->get('order');
|
||||
|
||||
$selected_rows = array('id', 'scope', 'tag', 'level', 'ip', 'time', 'content');
|
||||
$where_arr = array();
|
||||
$opt_arr = array();
|
||||
$order_arr = array();
|
||||
$params = array();
|
||||
|
||||
if (!empty($scope)) {
|
||||
$where_arr['scope'] = '?';
|
||||
$params[] = $scope;
|
||||
}
|
||||
if (!empty($tag)) {
|
||||
$where_arr['tag'] = '?';
|
||||
$params[] = $tag;
|
||||
}
|
||||
if (!is_null($level_min)) {
|
||||
$where_arr['level'] = '?';
|
||||
$opt_arr['level'] = '>=';
|
||||
$params[] = $level_min;
|
||||
}
|
||||
if (!empty($ip)) {
|
||||
$where_arr['ip'] = '?';
|
||||
$params[] = ip2long($ip);
|
||||
}
|
||||
if (!is_null($time_begin) && !is_null($time_end)) {
|
||||
$where_arr['time'] = '? AND ?';
|
||||
$opt_arr['time'] = 'BETWEEN';
|
||||
$params[] = $time_begin;
|
||||
$params[] = $time_end;
|
||||
} else if (!is_null($time_begin)) {
|
||||
$where_arr['time'] = '?';
|
||||
$opt_arr['time'] = '>=';
|
||||
$params[] = $time_begin;
|
||||
} else if (!is_null($time_end)) {
|
||||
$where_arr['time'] = '?';
|
||||
$opt_arr['time'] = '<=';
|
||||
$params[] = $time_end;
|
||||
}
|
||||
|
||||
switch ($order) {
|
||||
case 'latest':
|
||||
$order_arr['time'] = 'desc';
|
||||
break;
|
||||
default:
|
||||
$order_arr['id'] = 'desc';
|
||||
break;
|
||||
}
|
||||
$builder = new SQLBuilder();
|
||||
$builder->select(self::$db_table, $selected_rows);
|
||||
$builder->where($where_arr, $opt_arr);
|
||||
$builder->order($order_arr);
|
||||
$builder->limit($offset, $limit);
|
||||
$sql = $builder->build();
|
||||
$logs = (new MysqlPDO())->executeQuery($sql, $params);
|
||||
return $logs;
|
||||
}
|
||||
|
||||
public static function getCount(CRObject $filter)
|
||||
{
|
||||
$scope = $filter->get('scope');
|
||||
$tag = $filter->get('tag');
|
||||
$level_min = $filter->getInt('level_min');
|
||||
$ip = $filter->get('ip');
|
||||
$time_begin = $filter->getInt('time_begin');
|
||||
$time_end = $filter->getInt('time_end');
|
||||
|
||||
$selected_rows = array('id');
|
||||
$where_arr = array();
|
||||
$opt_arr = array();
|
||||
$params = array();
|
||||
|
||||
if (!empty($scope)) {
|
||||
$where_arr['scope'] = '?';
|
||||
$params[] = $scope;
|
||||
}
|
||||
if (!empty($tag)) {
|
||||
$where_arr['tag'] = '?';
|
||||
$params[] = $tag;
|
||||
}
|
||||
if (!is_null($level_min)) {
|
||||
$where_arr['level'] = '?';
|
||||
$opt_arr['level'] = '>=';
|
||||
$params[] = $level_min;
|
||||
}
|
||||
if (!empty($ip)) {
|
||||
$where_arr['ip'] = '?';
|
||||
$params[] = ip2long($ip);
|
||||
}
|
||||
if (!is_null($time_begin) && !is_null($time_end)) {
|
||||
$where_arr['time'] = '? AND ?';
|
||||
$opt_arr['time'] = 'BETWEEN';
|
||||
$params[] = $time_begin;
|
||||
$params[] = $time_end;
|
||||
} else if (!is_null($time_begin)) {
|
||||
$where_arr['time'] = '?';
|
||||
$opt_arr['time'] = '>=';
|
||||
$params[] = $time_begin;
|
||||
} else if (!is_null($time_end)) {
|
||||
$where_arr['time'] = '?';
|
||||
$opt_arr['time'] = '<=';
|
||||
$params[] = $time_end;
|
||||
}
|
||||
|
||||
$builder = new SQLBuilder();
|
||||
$builder->select(self::$db_table, $selected_rows);
|
||||
$builder->where($where_arr, $opt_arr);
|
||||
$builder->limit(0, 1000);
|
||||
$sql = $builder->build();
|
||||
$sql = "SELECT COUNT(1) AS `count` FROM ( $sql ) as tmp";
|
||||
$res = (new MysqlPDO())->executeQuery($sql, $params);
|
||||
return intval($res[0]['count']);
|
||||
}
|
||||
|
||||
}
|
||||
69
util4p/CRObject.class.php
Executable file
69
util4p/CRObject.class.php
Executable file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
class CRObject implements JsonSerializable
|
||||
{
|
||||
private $map;
|
||||
|
||||
/*
|
||||
* @param $map: key-value array
|
||||
*/
|
||||
public function __construct(array $map = array())
|
||||
{
|
||||
$this->map = $map;
|
||||
}
|
||||
|
||||
public function set($key, $value)
|
||||
{
|
||||
$this->map[$key] = $value;
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
if (isset($this->map[$key]) && !is_null($this->map[$key])) {
|
||||
return $this->map[$key];
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
public function getInt($key, $default = null)
|
||||
{
|
||||
if (isset($this->map[$key]) && !is_null($this->map[$key]) && is_numeric($this->map[$key])) {
|
||||
return intval($this->map[$key]);
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
public function getBool($key, $default = false)
|
||||
{
|
||||
if (isset($this->map[$key]) && !is_null($this->map[$key])) {
|
||||
return $this->map[$key] === true;
|
||||
}
|
||||
return $default === true;
|
||||
}
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
return $this->map;
|
||||
}
|
||||
|
||||
/*
|
||||
* set $this[$key] if isset($obj[$key])&&!isset($this[$key])
|
||||
* (new CRObject(['k1' => 'v1'])).union(new CRObject(['k1' => 'v1.1', 'k2' => 'v2']))
|
||||
* = new CRObject(['k1' => 'v1', 'k2' => 'v2'])
|
||||
*/
|
||||
public function union(CRObject $obj)
|
||||
{
|
||||
$keys = array_keys($obj->toArray());
|
||||
foreach ($keys as $key) {
|
||||
$this->set($key, $this->get($key, $obj->get($key)));
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
|
||||
}
|
||||
201
util4p/LICENSE
Executable file
201
util4p/LICENSE
Executable file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
99
util4p/MysqlPDO.class.php
Executable file
99
util4p/MysqlPDO.class.php
Executable file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
require_once('CRObject.class.php');
|
||||
|
||||
class MysqlPDO
|
||||
{
|
||||
private static $host = 'localhost';
|
||||
private static $port = '3307';
|
||||
private static $db = '';
|
||||
private static $user = 'root';
|
||||
private static $password = '';
|
||||
private static $charset = 'utf8';
|
||||
private static $show_error = false;
|
||||
private $dbh;
|
||||
|
||||
/**/
|
||||
public static function configure(CRObject $config)
|
||||
{
|
||||
self::$host = $config->get('host', self::$host);
|
||||
self::$port = $config->getInt('port', self::$port);
|
||||
self::$db = $config->get('db', self::$db);
|
||||
self::$user = $config->get('user', self::$user);
|
||||
self::$password = $config->get('password', self::$password);
|
||||
self::$charset = $config->get('charset', self::$charset);
|
||||
self::$show_error = $config->getBool('show_error', self::$show_error);
|
||||
}
|
||||
|
||||
/**/
|
||||
public function __construct()
|
||||
{
|
||||
$this->connect();
|
||||
}
|
||||
|
||||
/**/
|
||||
private function connect()
|
||||
{
|
||||
try {
|
||||
$this->dbh = new PDO('mysql:host=' . (self::$host) . ';port=' . (self::$port) . ';dbname=' . (self::$db), self::$user, self::$password);
|
||||
$this->dbh->exec('SET names ' . self::$charset);
|
||||
return true;
|
||||
} catch (PDOException $e) {
|
||||
$this->dbh = null;
|
||||
if (self::$show_error)
|
||||
var_dump($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @return bool
|
||||
* */
|
||||
public function execute($sql, $a_params, $need_inserted_id = false)
|
||||
{
|
||||
if ($this->dbh === null) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$stmt = $this->dbh->prepare($sql);
|
||||
$result = $stmt->execute($a_params);
|
||||
if (self::$show_error && !$result) {
|
||||
var_dump($stmt->errorInfo()[2]);
|
||||
}
|
||||
if ($need_inserted_id) {
|
||||
$result = $result ? $this->dbh->lastInsertId() : false;
|
||||
}
|
||||
$this->dbh = null;
|
||||
return $result;
|
||||
} catch (Exception $e) {
|
||||
if (self::$show_error)
|
||||
var_dump($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @param $a_params: key-value array
|
||||
*/
|
||||
function executeQuery($sql, $a_params)
|
||||
{
|
||||
if ($this->dbh === null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
$stmt = $this->dbh->prepare($sql);
|
||||
$stmt->setFetchMode(PDO::FETCH_ASSOC);
|
||||
$result = null;
|
||||
if ($stmt->execute($a_params)) {
|
||||
$result = $stmt->fetchAll();
|
||||
}
|
||||
$this->dbh = null;
|
||||
return $result;
|
||||
} catch (Exception $e) {
|
||||
if (self::$show_error)
|
||||
var_dump($e->getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
23
util4p/README.md
Executable file
23
util4p/README.md
Executable file
@@ -0,0 +1,23 @@
|
||||
# utilities for php
|
||||
|
||||
Require PHP version >= 5.1.0
|
||||
|
||||
## AccessController.class.php
|
||||
|
||||
## CRLogger.class.php
|
||||
|
||||
## CRObject.class.php
|
||||
|
||||
## MysqlPDO.class.php
|
||||
|
||||
## Random.class.php
|
||||
|
||||
## RedisDAO.class.php
|
||||
|
||||
## Session.class.php
|
||||
|
||||
## SQLBuilder.class.php
|
||||
|
||||
## util.php
|
||||
|
||||
## Validator.class.php
|
||||
51
util4p/Random.class.php
Executable file
51
util4p/Random.class.php
Executable file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
class Random
|
||||
{
|
||||
const LEVEL_LOW = 1;
|
||||
const LEVEL_MIDDLE = 2;
|
||||
const LEVEL_HIGH = 3;
|
||||
|
||||
/*
|
||||
* generate a digit in range of [$min, $max]
|
||||
* origin: stackoverflow
|
||||
* notice: this method tends to generate unique numbers compared with rand()
|
||||
*/
|
||||
public static function randomInt($min, $max)
|
||||
{
|
||||
$range = intval($max) - intval($min);
|
||||
if ($range < 1) return $min; // not so random...
|
||||
$log = ceil(log($range, 2));
|
||||
$bytes = (int)($log / 8) + 1; // length in bytes
|
||||
$bits = (int)$log + 1; // length in bits
|
||||
$filter = (int)(1 << $bits) - 1; // set all lower bits to 1
|
||||
do {
|
||||
$rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
|
||||
$rnd = $rnd & $filter; // discard irrelevant bits
|
||||
} while ($rnd >= $range);
|
||||
return $min + $rnd;
|
||||
}
|
||||
|
||||
/*
|
||||
* generate random string of length $length
|
||||
* level: LOW - only numbers, MIDDLE - plus letters(upper and lower), HIGH - plus special chars
|
||||
*/
|
||||
public static function randomString($strlen, $level = self::LEVEL_MIDDLE)
|
||||
{
|
||||
$alphabet = '0123456789';
|
||||
if ($level > self::LEVEL_LOW) {
|
||||
$alphabet .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
$alphabet .= 'abcdefghijklmnopqrstuvwxyz';
|
||||
}
|
||||
if ($level > self::LEVEL_MIDDLE)
|
||||
$alphabet .= '+-*/?!%`~@#^&(){}';
|
||||
|
||||
$length = strlen($alphabet);
|
||||
$token = '';
|
||||
for ($i = 0; $i < $strlen; $i++) {
|
||||
$token .= $alphabet[self::randomInt(0, $length - 1)];
|
||||
}
|
||||
return $token;
|
||||
}
|
||||
|
||||
}
|
||||
169
util4p/RateLimiter.class.php
Executable file
169
util4p/RateLimiter.class.php
Executable file
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
require_once('util.php');
|
||||
require_once('RedisDAO.class.php');
|
||||
|
||||
/*
|
||||
* limit request rate, prevent spam
|
||||
* normally used in fields such as login, register
|
||||
* based on fatigue degree
|
||||
*
|
||||
* fatigue degree grow algorithm rule, call increase($degree)
|
||||
* rule format
|
||||
* array(
|
||||
* 'degree'=>100, //min point to reach this punishment
|
||||
* 'interval'=>300 //count interval, degree will expire after interval
|
||||
* )
|
||||
*
|
||||
* rules are stored in redis db
|
||||
* will auto grow by fatigue degree, call setAutoIncrease($bool)
|
||||
* punish directly, call punish($arr)
|
||||
*/
|
||||
|
||||
class RateLimiter
|
||||
{
|
||||
private static $keyPrefix = 'rl';
|
||||
private static $id = '';
|
||||
private static $rules = array();
|
||||
|
||||
|
||||
/*
|
||||
* @param $key customize your own key, default is ip2long(ip)
|
||||
*/
|
||||
public static function configure(CRObject $config)
|
||||
{
|
||||
self::$keyPrefix = $config->get('key_prefix', self::$keyPrefix);
|
||||
self::$id = $config->get('id', cr_get_client_ip(false));
|
||||
self::$rules = $config->get('rules', self::$rules);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @param
|
||||
*
|
||||
*/
|
||||
public static function increase($degree)
|
||||
{
|
||||
if (!is_numeric($degree)) {
|
||||
return false;
|
||||
}
|
||||
$lua_script = <<<LUA
|
||||
local degree = redis.call('incrby', KEYS[1], ARGV[1])
|
||||
if degree == tonumber(ARGV[1]) then
|
||||
redis.call('expire', KEYS[1], ARGV[2])
|
||||
end
|
||||
return degree
|
||||
LUA;
|
||||
$redis = RedisDAO::instance();
|
||||
if ($redis === null) {
|
||||
return false;
|
||||
}
|
||||
foreach (self::$rules as $rule) {
|
||||
$interval = $rule['interval'];
|
||||
$key = self::$keyPrefix . ':degree:' . self::$id . '-' . $interval;
|
||||
$redis->eval($lua_script, 1, $key, $degree, $interval);
|
||||
}
|
||||
$redis->disconnect();
|
||||
$rule = self::whichRuleToPunish();
|
||||
if ($rule !== null) {
|
||||
self::punish($rule);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**/
|
||||
public static function punish($rule, $id = null)
|
||||
{
|
||||
if ($id === null) {
|
||||
$id = self::$id;
|
||||
}
|
||||
$redis = RedisDAO::instance();
|
||||
if ($redis === null) {
|
||||
return false;
|
||||
}
|
||||
$redis->set(self::$keyPrefix . ':punishing:' . $id, $rule['degree'], 'EX', $rule['interval']);
|
||||
$redis->disconnect();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* get punish time left, negative means not being punished
|
||||
*/
|
||||
public static function getFreezeTime($id = null)
|
||||
{
|
||||
if ($id === null) {
|
||||
$id = self::$id;
|
||||
}
|
||||
$redis = RedisDAO::instance();
|
||||
if ($redis === null) {
|
||||
return 0;
|
||||
}
|
||||
$freezeTime = (int)$redis->ttl(self::$keyPrefix . ':punishing:' . $id);
|
||||
$redis->disconnect();
|
||||
return $freezeTime;
|
||||
}
|
||||
|
||||
/*
|
||||
* get which rule to punish current user
|
||||
* mostly of the time, you dont have to call this, as it is called automatically
|
||||
*/
|
||||
private static function whichRuleToPunish()
|
||||
{
|
||||
$redis = RedisDAO::instance();
|
||||
if ($redis === null) {
|
||||
return null;
|
||||
}
|
||||
foreach (self::$rules as $rule) {
|
||||
$interval = $rule['interval'];
|
||||
$key = self::$keyPrefix . ':degree:' . self::$id . '-' . $interval;
|
||||
$degree = (int)$redis->get($key);
|
||||
if ($degree > $rule['degree']) {
|
||||
$redis->disconnect();
|
||||
return $rule;
|
||||
}
|
||||
}
|
||||
$redis->disconnect();
|
||||
return null;
|
||||
}
|
||||
|
||||
/* clear degree count and punishing state */
|
||||
public static function clear($id = null)
|
||||
{
|
||||
if ($id === null) {
|
||||
$id = self::$id;
|
||||
}
|
||||
$redis = RedisDAO::instance();
|
||||
if ($redis === null) {
|
||||
return null;
|
||||
}
|
||||
foreach (self::$rules as $rule) {
|
||||
$interval = $rule['interval'];
|
||||
$key = self::$keyPrefix . ':degree:' . $id . '-' . $interval;
|
||||
$redis->del(array($key));
|
||||
}
|
||||
$redis->del(array(self::$keyPrefix . ':punishing:' . $id));
|
||||
$redis->disconnect();
|
||||
return true;
|
||||
}
|
||||
|
||||
/* list IDs being punished */
|
||||
public static function listPunished()
|
||||
{
|
||||
$redis = RedisDAO::instance();
|
||||
if ($redis === null) {
|
||||
return false;
|
||||
}
|
||||
$redis_key = self::$keyPrefix . ':punishing:*';
|
||||
$list = $redis->keys($redis_key);
|
||||
$redis->disconnect();
|
||||
$len = strlen(self::$keyPrefix . ':punishing:');
|
||||
$ids = array();
|
||||
foreach ($list as $item) {
|
||||
$ids[]['id'] = mb_substr($item, $len);
|
||||
}
|
||||
return $ids;
|
||||
}
|
||||
|
||||
}
|
||||
208
util4p/ReSession.class.php
Executable file
208
util4p/ReSession.class.php
Executable file
@@ -0,0 +1,208 @@
|
||||
<?php
|
||||
|
||||
require_once('util.php');
|
||||
require_once('CRObject.class.php');
|
||||
require_once('RedisDAO.class.php');
|
||||
require_once('Random.class.php');
|
||||
|
||||
class Session
|
||||
{
|
||||
private static $time_out = 0; // 0-never expire
|
||||
private static $bind_ip = false; // bind session with ip, when client ip changes, previous session will be unavailable
|
||||
private static $sid = '';
|
||||
private static $guid_key = '_session_id';
|
||||
private static $cache = array();
|
||||
|
||||
/* configuration && initialization */
|
||||
public static function configure(CRObject $config)
|
||||
{
|
||||
self::$time_out = $config->get('time_out', self::$time_out);
|
||||
self::$bind_ip = $config->getBool('bind_ip', self::$bind_ip);
|
||||
self::$guid_key = $config->get('guid_key', self::$guid_key);
|
||||
/* assign id from new sessions */
|
||||
if (!isset($_COOKIE[self::$guid_key])) {
|
||||
$redis = RedisDAO::instance();
|
||||
if ($redis === null) {
|
||||
return false;
|
||||
}
|
||||
do { // generate an unique session id
|
||||
self::$sid = Random::randomString(64);
|
||||
} while ($redis->exists('session:' . self::$sid) === 1);
|
||||
$redis->disconnect();
|
||||
setcookie(self::$guid_key, self::$sid);
|
||||
} else {
|
||||
self::$sid = $_COOKIE[self::$guid_key];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Ask browser to remember session id even if browser restarts */
|
||||
public static function persist($duration)
|
||||
{
|
||||
$redis = RedisDAO::instance();
|
||||
if ($redis === null) {
|
||||
return false;
|
||||
}
|
||||
$redis_key = 'session:' . self::$sid;
|
||||
$redis->expire($redis_key, $duration);
|
||||
$redis->disconnect();
|
||||
setcookie(self::$guid_key, self::$sid, time() + $duration);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* attach session to $group to avoid wild sessions */
|
||||
public static function attach($group)
|
||||
{
|
||||
$redis = RedisDAO::instance();
|
||||
if ($redis === null) {
|
||||
return false;
|
||||
}
|
||||
$redis_key = 'session:' . self::$sid;
|
||||
$key = 'session-group:' . $group;
|
||||
$redis->sadd($key, array($redis_key));
|
||||
$redis->disconnect();
|
||||
return true;
|
||||
}
|
||||
|
||||
/* detach session from $group */
|
||||
public static function detach($group)
|
||||
{
|
||||
$redis = RedisDAO::instance();
|
||||
if ($redis === null) {
|
||||
return false;
|
||||
}
|
||||
$key = 'session-group:' . $group;
|
||||
$redis_key = 'session:' . self::$sid;
|
||||
$redis->srem($key, $redis_key);
|
||||
$redis->disconnect();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**/
|
||||
public static function put($key, $value)
|
||||
{
|
||||
$redis = RedisDAO::instance();
|
||||
if ($redis === null) {
|
||||
return false;
|
||||
}
|
||||
$redis_key = 'session:' . self::$sid;
|
||||
$redis->hset($redis_key, $key, $value);
|
||||
$redis->hset($redis_key, '_ip', cr_get_client_ip(false));
|
||||
self::$cache[$key] = $value;//update cache
|
||||
self::get('_ip');//renew expiration
|
||||
$redis->disconnect();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**/
|
||||
public static function get($key, $default = null)
|
||||
{
|
||||
if (isset(self::$cache[$key])) {
|
||||
return self::$cache[$key];
|
||||
}
|
||||
$redis = RedisDAO::instance();
|
||||
if ($redis === null) {
|
||||
return $default;
|
||||
}
|
||||
$redis_key = 'session:' . self::$sid;
|
||||
$list = $redis->hgetall($redis_key);
|
||||
if (self::$bind_ip) {
|
||||
if (!(isset($list['_ip']) && $list['_ip'] === cr_get_client_ip(false))) {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
self::$cache = $list;
|
||||
if ($redis->ttl($redis_key) < self::$time_out) {
|
||||
$redis->expire($redis_key, self::$time_out);
|
||||
}
|
||||
$redis->disconnect();
|
||||
if (isset($list[$key])) {
|
||||
return $list[$key];
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/* expire current session */
|
||||
public static function expire()
|
||||
{
|
||||
$redis = RedisDAO::instance();
|
||||
if ($redis === null) {
|
||||
return false;
|
||||
}
|
||||
$redis_key = 'session:' . self::$sid;
|
||||
$redis->del(array($redis_key));
|
||||
$redis->disconnect();
|
||||
setcookie(self::$guid_key, self::$sid, time() - 3600);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**/
|
||||
public static function expireByGroup($group, $index = null)
|
||||
{
|
||||
$redis = RedisDAO::instance();
|
||||
if ($redis === null) {
|
||||
return false;
|
||||
}
|
||||
$group_key = "session-group:$group";
|
||||
$keys = $redis->smembers($group_key);
|
||||
foreach ($keys as $i => $key) {
|
||||
if ($index === null || $i === $index) {
|
||||
$redis->srem($group_key, $key);
|
||||
$redis->del($key);
|
||||
}
|
||||
}
|
||||
$redis->disconnect();
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Low Performance, Not recommended */
|
||||
public static function listGroup(CRObject $rule)
|
||||
{
|
||||
$redis = RedisDAO::instance();
|
||||
if ($redis === null) {
|
||||
return false;
|
||||
}
|
||||
$prefix = 'session-group:';
|
||||
$keys = $redis->keys($prefix . '*');
|
||||
$offset = $rule->getInt('offset', 0);
|
||||
$limit = $rule->getInt('limit', -1);
|
||||
$groups = array();
|
||||
$len = strlen($prefix);
|
||||
foreach ($keys as $index => $key) {
|
||||
if ($index < $offset) {
|
||||
continue;
|
||||
}
|
||||
if ($limit !== -1 && $offset + $limit <= $index) {
|
||||
break;
|
||||
}
|
||||
$groups[] = array('index' => $index, 'group' => substr($key, $len));
|
||||
}
|
||||
$redis->disconnect();
|
||||
return $groups;
|
||||
}
|
||||
|
||||
/* Low Performance, Not recommended */
|
||||
public static function listSession(CRObject $rule)
|
||||
{
|
||||
$redis = RedisDAO::instance();
|
||||
if ($redis === null) {
|
||||
return false;
|
||||
}
|
||||
$group = $rule->get('group', '');
|
||||
$redis_key = "session-group:$group";
|
||||
$keys = $redis->smembers($redis_key);
|
||||
$sessions = array();
|
||||
foreach ($keys as $index => $key) {
|
||||
$session = $redis->hgetall($key);
|
||||
if (count($session) === 0) {
|
||||
$redis->srem($redis_key, $key);
|
||||
continue;
|
||||
}
|
||||
$session['_index'] = $index;
|
||||
$session['_current'] = $key === 'session:' . self::$sid;
|
||||
$sessions[] = $session;
|
||||
}
|
||||
return $sessions;
|
||||
}
|
||||
|
||||
}
|
||||
44
util4p/RedisDAO.class.php
Executable file
44
util4p/RedisDAO.class.php
Executable file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
require_once('CRObject.class.php');
|
||||
if (!class_exists('Predis\Client')) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
var_dump('predis (github.com/nrk/predis.git) required');
|
||||
exit;
|
||||
}
|
||||
|
||||
class RedisDAO
|
||||
{
|
||||
private static $scheme = 'tcp';
|
||||
private static $host = 'localhost';
|
||||
private static $port = 6379;
|
||||
private static $show_error = false;
|
||||
|
||||
public static function configure(CRObject $config)
|
||||
{
|
||||
self::$scheme = $config->get('scheme', self::$scheme);
|
||||
self::$host = $config->get('host', self::$host);
|
||||
self::$port = $config->getInt('port', self::$port);
|
||||
self::$show_error = $config->getBool('show_error', self::$show_error);
|
||||
}
|
||||
|
||||
public static function instance()
|
||||
{
|
||||
try {
|
||||
$redis = new Predis\Client(
|
||||
array(
|
||||
'scheme' => RedisDAO::$scheme,
|
||||
'host' => RedisDAO::$host,
|
||||
'port' => RedisDAO::$port
|
||||
)
|
||||
);
|
||||
$redis->connect();
|
||||
return $redis;
|
||||
} catch (Exception $e) {
|
||||
if (self::$show_error)
|
||||
var_dump($e->getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
162
util4p/SQLBuilder.class.php
Executable file
162
util4p/SQLBuilder.class.php
Executable file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Replace long SQL string with several functions
|
||||
* Fixed SQL string is hard to migrate to another DB whose syntax may differ.
|
||||
* Using a high level abstract interface makes code clean and easy to migrate.
|
||||
* Is is strongly recommended to use prepared statement in order to avoid SQL-injection
|
||||
*/
|
||||
|
||||
class SQLBuilder
|
||||
{
|
||||
private $sql = '';
|
||||
|
||||
/**/
|
||||
public function insert($table, array $key_values)
|
||||
{
|
||||
$this->sql = "INSERT INTO `$table`";
|
||||
$keys = array_keys($key_values);
|
||||
if (count($keys) && $keys[0] !== 0) { //support `INSERT INTO table VALUES (...)
|
||||
$this->sql .= '(';
|
||||
foreach ($keys as $key) {
|
||||
$this->sql .= "`$key`, ";
|
||||
}
|
||||
$this->sql = substr($this->sql, 0, strlen($this->sql) - 2);
|
||||
$this->sql .= ')';
|
||||
}
|
||||
$this->sql .= " VALUES(";
|
||||
foreach ($key_values as $key => $value) {
|
||||
if ($value === null) {
|
||||
$this->sql .= "null, ";
|
||||
} else if ($value === '?') {// support prepared statment
|
||||
$this->sql .= "?, ";
|
||||
} else {// FIXME: $value may contains '
|
||||
$this->sql .= "'$value', ";
|
||||
}
|
||||
}
|
||||
$this->sql = substr($this->sql, 0, strlen($this->sql) - 2);
|
||||
$this->sql .= ")";
|
||||
}
|
||||
|
||||
/**/
|
||||
public function select($table, array $selected_rows = array())
|
||||
{
|
||||
$this->sql = 'SELECT ';
|
||||
foreach ($selected_rows as $row) {
|
||||
if (strpos($row, ' ') || strpos($row, '(')) {//contain functions, not pure row name
|
||||
$this->sql .= "$row, ";
|
||||
} else {
|
||||
$this->sql .= "`$row`, ";
|
||||
}
|
||||
}
|
||||
if (count($selected_rows) === 0) {
|
||||
$this->sql .= ' * ';
|
||||
} else {
|
||||
$this->sql = substr($this->sql, 0, strlen($this->sql) - 2);
|
||||
}
|
||||
$this->sql .= " FROM `$table` ";
|
||||
}
|
||||
|
||||
/**/
|
||||
public function update($table, array $key_values)
|
||||
{
|
||||
if ($key_values === null || count($key_values) === 0) {
|
||||
return;
|
||||
}
|
||||
$this->sql = "UPDATE `$table` SET ";
|
||||
foreach ($key_values as $key => $value) {
|
||||
if ($value === null) {
|
||||
$this->sql .= " `$key` = null, ";
|
||||
} else if ($value === '?') {
|
||||
$this->sql .= " `$key` = ?, ";
|
||||
} else {//FIXME: $value may contain '
|
||||
$this->sql .= " `$key` = '$value', ";
|
||||
}
|
||||
}
|
||||
$this->sql = substr($this->sql, 0, strlen($this->sql) - 2);
|
||||
}
|
||||
|
||||
/**/
|
||||
public function delete($table)
|
||||
{
|
||||
$this->sql = "DELETE FROM `$table` ";
|
||||
}
|
||||
|
||||
/* currently, can only represent AND */
|
||||
public function where($key_values, $opts = array())
|
||||
{
|
||||
$where_clause_cnt = 0;
|
||||
$keys = array_keys($key_values);
|
||||
|
||||
foreach ($keys as $key) {
|
||||
if (!isset($opts[$key])) {
|
||||
$opts[$key] = '=';
|
||||
}
|
||||
if ($where_clause_cnt == 0) {
|
||||
$this->sql .= ' WHERE ';
|
||||
} else {
|
||||
$this->sql .= ' AND ';
|
||||
}
|
||||
if ($key_values[$key] === null) {
|
||||
if ($opts[$key] === '=') {
|
||||
$this->sql .= " `$key` is null ";
|
||||
} else {
|
||||
$this->sql .= " `$key` is not null ";
|
||||
}
|
||||
$where_clause_cnt++;
|
||||
} else if ($key_values[$key] === '?' || in_array(strtoupper($opts[$key]), array('IN', 'BETWEEN', 'LIKE'))) {
|
||||
$this->sql .= " `$key` {$opts[$key]} {$key_values[$key]} ";
|
||||
$where_clause_cnt++;
|
||||
} else {//FIXME: $key_values[$key] may contain '
|
||||
$this->sql .= " `$key` {$opts[$key]} '{$key_values[$key]}' ";
|
||||
$where_clause_cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**/
|
||||
public function group(array $by_arr)
|
||||
{
|
||||
if ($by_arr === null || count($by_arr) === 0) {
|
||||
return;
|
||||
}
|
||||
$this->sql .= ' GROUP BY ';
|
||||
foreach ($by_arr as $by) {
|
||||
$this->sql .= "`$by`, ";
|
||||
}
|
||||
$this->sql = substr($this->sql, 0, strlen($this->sql) - 2);
|
||||
}
|
||||
|
||||
/**/
|
||||
public function order(array $by_arr)
|
||||
{
|
||||
if ($by_arr === null || count($by_arr) === 0) {
|
||||
return;
|
||||
}
|
||||
$this->sql .= ' ORDER BY ';
|
||||
foreach ($by_arr as $by => $order) {
|
||||
if (strtoupper($order) !== 'DESC') {
|
||||
$order = 'ASC';
|
||||
}
|
||||
$this->sql .= "`$by` $order, ";
|
||||
}
|
||||
$this->sql = substr($this->sql, 0, strlen($this->sql) - 2);
|
||||
}
|
||||
|
||||
/**/
|
||||
public function limit($offset, $cnt)
|
||||
{
|
||||
if ($cnt < 0) {// support LIMIT 0 ,-1 to get all records
|
||||
$this->sql .= " LIMIT $offset, 18446744073709551615";
|
||||
} else {
|
||||
$this->sql .= " LIMIT $offset, $cnt";
|
||||
}
|
||||
}
|
||||
|
||||
/**/
|
||||
public function build()
|
||||
{
|
||||
return $this->sql;
|
||||
}
|
||||
|
||||
}
|
||||
50
util4p/Session.class.php
Executable file
50
util4p/Session.class.php
Executable file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
session_start();
|
||||
|
||||
class Session
|
||||
{
|
||||
private static $time_out = 0; // 0-never expire
|
||||
private static $bind_ip = false; // bind session with ip, when client ip changes, previous session will be unavailable
|
||||
|
||||
/**/
|
||||
public static function configure(CRObject $config)
|
||||
{
|
||||
self::$time_out = $config->get('time_out', self::$time_out);
|
||||
self::$bind_ip = $config->getBool('bind_ip', self::$bind_ip);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**/
|
||||
public static function put($key, $value)
|
||||
{
|
||||
$_SESSION[$key] = $value;
|
||||
$_SESSION['_SELF']['LAST_ACTIVE'] = time();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**/
|
||||
public static function get($key, $default = null)
|
||||
{
|
||||
if (!isset($_SESSION['_SELF']['LAST_ACTIVE'])) {
|
||||
$_SESSION['_SELF']['LAST_ACTIVE'] = 0;
|
||||
}
|
||||
if (self::$time_out > 0 && time() - $_SESSION['_SELF']['LAST_ACTIVE'] > self::$time_out) {
|
||||
return $default;
|
||||
}
|
||||
$_SESSION['_SELF']['LAST_ACTIVE'] = time();
|
||||
if (isset($_SESSION[$key]) && !is_null($_SESSION[$key])) {
|
||||
return $_SESSION[$key];
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/* expire current session */
|
||||
public static function expire()
|
||||
{
|
||||
$_SESSION = array();
|
||||
session_destroy();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
36
util4p/Validator.class.php
Executable file
36
util4p/Validator.class.php
Executable file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
class Validator
|
||||
{
|
||||
/**/
|
||||
public static function isIP($str)
|
||||
{
|
||||
$ip = explode('.', $str);
|
||||
for ($i = 0; $i < count($ip); $i++) {
|
||||
if ($ip[$i] < 0 || $ip[$i] > 255) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $str);
|
||||
}
|
||||
|
||||
/**/
|
||||
public static function isEmail($str)
|
||||
{
|
||||
if ($str === null) {
|
||||
return false;
|
||||
}
|
||||
return preg_match("/^([0-9A-Za-z\\-_\\.]+)@([0-9a-z]+\\.[a-z]{2,3}(\\.[a-z]{2})?)$/i", $str) === 1;
|
||||
}
|
||||
|
||||
|
||||
/*TODO*/
|
||||
public static function isURL($url)
|
||||
{
|
||||
if (is_null($url) || empty($url)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
67
util4p/util.php
Executable file
67
util4p/util.php
Executable file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* get client side ip
|
||||
* Notice: This method works best in the situation where the server is behind proxy
|
||||
* and proxy will replace HTTP_CLIENT_IP. If your app is exposed straightly to
|
||||
* the Internet, this may return a wrong ip when a visits from Intranet but
|
||||
* claims from Internet. It is a trade-off.
|
||||
*/
|
||||
function cr_get_client_ip($allow_ipv6 = true)
|
||||
{
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
// REMOTE_ADDR may not be real ip in case server is behind proxy (nginx, docker etc.)
|
||||
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
|
||||
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
|
||||
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
||||
} else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||
$ips = explode(', ', $_SERVER['HTTP_X_FORWARDED_FOR']);
|
||||
for ($i = 0; $i < count($ips); $i++) {
|
||||
if (!preg_match('/^(10│172.16│192.168)./i', $ips[$i])) {
|
||||
$ip = $ips[$i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$allow_ipv6 && filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
|
||||
$ip = '0.0.0.0';
|
||||
}
|
||||
return $ip;
|
||||
}
|
||||
|
||||
/* get from $_GET */
|
||||
function cr_get_GET($key, $default = null)
|
||||
{
|
||||
if (isset($_GET[$key]) && strlen($_GET[$key]) > 0) {
|
||||
return $_GET[$key];
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/* get from $_POST */
|
||||
function cr_get_POST($key, $default = null)
|
||||
{
|
||||
if (isset($_POST[$key]) && strlen($_POST[$key]) > 0) {
|
||||
return $_POST[$key];
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/* get from $_COOKIE */
|
||||
function cr_get_COOKIE($key, $default = null)
|
||||
{
|
||||
if (isset($_COOKIE[$key]) && strlen($_COOKIE[$key]) > 0) {
|
||||
return $_COOKIE[$key];
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/* get from $_SERVER */
|
||||
function cr_get_SERVER($key, $default = null)
|
||||
{
|
||||
if (isset($_SERVER[$key]) && strlen($_SERVER[$key]) > 0) {
|
||||
return $_SERVER[$key];
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
Reference in New Issue
Block a user