Initial import from local backup (Documents-Playground/pakerpale)

This commit is contained in:
jeonghwa
2026-07-03 05:27:38 +09:00
commit 1bf24f7d86
79 changed files with 9869 additions and 0 deletions

View File

@@ -0,0 +1,231 @@
<?php
/**
* Name: Bcrypt
*
* Requirements: PHP5 or above
*
* @package CodeIgniter-Ion-Auth
* @author Ben Edmunds
* @link http://github.com/benedmunds/CodeIgniter-Ion-Auth
* @filesource
*/
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Class Bcrypt
*/
class Bcrypt
{
/**
* @var int
*/
private $rounds;
/**
* @var string
*/
private $salt_prefix;
/**
* @var int|string|null
*/
private $randomState;
/**
* Bcrypt constructor.
*
* @param array $params
*
* @throws Exception
*/
public function __construct($params = array('rounds' => 7, 'salt_prefix' => '$2y$'))
{
if (CRYPT_BLOWFISH != 1)
{
throw new Exception("bcrypt not supported in this installation. See http://php.net/crypt");
}
$this->rounds = $params['rounds'];
$this->salt_prefix = $params['salt_prefix'];
}
/**
* @param string $input
*
* @return bool|string
*/
public function hash($input)
{
$hash = crypt($input, $this->getSalt());
if (strlen($hash) > 13)
{
return $hash;
}
return FALSE;
}
/**
* @param string $input
* @param string $existingHash
*
* @return bool
*/
public function verify($input, $existingHash)
{
$hash = crypt($input, $existingHash);
return $this->hashEquals($existingHash, $hash);
}
/**
* Polyfill for hash_equals()
* Code mainly taken from hash_equals() compat function of CodeIgniter 3
*
* @param string $known_string
* @param string $user_string
*
* @return bool
*/
private function hashEquals($known_string, $user_string)
{
// For CI3 or PHP >= 5.6
if (function_exists('hash_equals'))
{
return hash_equals($known_string, $user_string);
}
// For CI2 with PHP < 5.6
// Code from CI3 https://github.com/bcit-ci/CodeIgniter/blob/develop/system/core/compat/hash.php
if (!is_string($known_string))
{
trigger_error('hash_equals(): Expected known_string to be a string, ' . strtolower(gettype($known_string)) . ' given', E_USER_WARNING);
return FALSE;
}
else if (!is_string($user_string))
{
trigger_error('hash_equals(): Expected user_string to be a string, ' . strtolower(gettype($user_string)) . ' given', E_USER_WARNING);
return FALSE;
}
else if (($length = strlen($known_string)) !== strlen($user_string))
{
return FALSE;
}
$diff = 0;
for ($i = 0; $i < $length; $i++)
{
$diff |= ord($known_string[$i]) ^ ord($user_string[$i]);
}
return ($diff === 0);
}
/**
* @return string
*/
private function getSalt()
{
$salt = sprintf($this->salt_prefix . '%02d$', $this->rounds);
$bytes = $this->getRandomBytes(16);
$salt .= $this->encodeBytes($bytes);
return $salt;
}
/**
* @param $count
*
* @return string
*/
private function getRandomBytes($count)
{
$bytes = '';
if (function_exists('openssl_random_pseudo_bytes') &&
(strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN'))
{
// OpenSSL slow on Win
$bytes = openssl_random_pseudo_bytes($count);
}
if ($bytes === '' && @is_readable('/dev/urandom') &&
($hRand = @fopen('/dev/urandom', 'rb')) !== FALSE)
{
$bytes = fread($hRand, $count);
fclose($hRand);
}
if (strlen($bytes) < $count)
{
$bytes = '';
if ($this->randomState === NULL)
{
$this->randomState = microtime();
if (function_exists('getmypid'))
{
$this->randomState .= getmypid();
}
}
for ($i = 0; $i < $count; $i += 16)
{
$this->randomState = md5(microtime() . $this->randomState);
if (PHP_VERSION >= '5')
{
$bytes .= md5($this->randomState, TRUE);
}
else
{
$bytes .= pack('H*', md5($this->randomState));
}
}
$bytes = substr($bytes, 0, $count);
}
return $bytes;
}
/**
* @param string $input
*
* @return string
*/
private function encodeBytes($input)
{
// The following is code from the PHP Password Hashing Framework
$itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$output = '';
$i = 0;
do
{
$c1 = ord($input[$i++]);
$output .= $itoa64[$c1 >> 2];
$c1 = ($c1 & 0x03) << 4;
if ($i >= 16)
{
$output .= $itoa64[$c1];
break;
}
$c2 = ord($input[$i++]);
$c1 |= $c2 >> 4;
$output .= $itoa64[$c1];
$c1 = ($c2 & 0x0f) << 2;
$c2 = ord($input[$i++]);
$c1 |= $c2 >> 6;
$output .= $itoa64[$c1];
$output .= $itoa64[$c2 & 0x3f];
} while (1);
return $output;
}
}

View File

@@ -0,0 +1,267 @@
<?php
/**
* Format class
*
* Help convert between various formats such as XML, JSON, CSV, etc.
*
* @author Phil Sturgeon
* @license http://philsturgeon.co.uk/code/dbad-license
*/
class Format {
// Array to convert
protected $_data = array();
// View filename
protected $_from_type = null;
/**
* Returns an instance of the Format object.
*
* echo $this->format->factory(array('foo' => 'bar'))->to_xml();
*
* @param mixed general date to be converted
* @param string data format the file was provided in
* @return Factory
*/
public function factory($data, $from_type = null)
{
// Stupid stuff to emulate the "new static()" stuff in this libraries PHP 5.3 equivilent
$class = __CLASS__;
return new $class($data, $from_type);
}
/**
* Do not use this directly, call factory()
*/
public function __construct($data = null, $from_type = null)
{
get_instance()->load->helper('inflector');
// If the provided data is already formatted we should probably convert it to an array
if ($from_type !== null)
{
if (method_exists($this, '_from_' . $from_type))
{
$data = call_user_func(array($this, '_from_' . $from_type), $data);
}
else
{
throw new Exception('Format class does not support conversion from "' . $from_type . '".');
}
}
$this->_data = $data;
}
public function to_data() {
return $this->_data;
}
// FORMATING OUTPUT ---------------------------------------------------------
public function to_array($data = null)
{
// If not just null, but nopthing is provided
if ($data === null and ! func_num_args())
{
$data = $this->_data;
}
$array = array();
foreach ((array) $data as $key => $value)
{
if (is_object($value) or is_array($value))
{
$array[$key] = $this->to_array($value);
}
else
{
$array[$key] = $value;
}
}
return $array;
}
// Format XML for output
public function to_xml($data = null, $structure = null, $basenode = 'xml')
{
if ($data === null and ! func_num_args())
{
$data = $this->_data;
}
// turn off compatibility mode as simple xml throws a wobbly if you don't.
if (ini_get('zend.ze1_compatibility_mode') == 1)
{
ini_set('zend.ze1_compatibility_mode', 0);
}
if ($structure === null)
{
$structure = simplexml_load_string("<?xml version='1.0' encoding='utf-8'?><$basenode />");
}
// Force it to be something useful
if ( ! is_array($data) AND ! is_object($data))
{
$data = (array) $data;
}
foreach ($data as $key => $value)
{
// no numeric keys in our xml please!
if (is_numeric($key))
{
// make string key...
$key = (singular($basenode) != $basenode) ? singular($basenode) : 'item';
}
// replace anything not alpha numeric
$key = preg_replace('/[^a-z_\-0-9]/i', '', $key);
// if there is another array found recrusively call this function
if (is_array($value) || is_object($value))
{
$node = $structure->addChild($key);
// recrusive call.
$this->to_xml($value, $node, $key);
}
else
{
// add single node.
$value = htmlspecialchars(html_entity_decode($value, ENT_QUOTES, 'UTF-8'), ENT_QUOTES, "UTF-8");
$structure->addChild($key, $value);
}
}
return $structure->asXML();
}
// Format HTML for output
public function to_html()
{
$data = $this->_data;
// Multi-dimentional array
if (isset($data[0]))
{
$headings = array_keys($data[0]);
}
// Single array
else
{
$headings = array_keys($data);
$data = array($data);
}
$ci = get_instance();
$ci->load->library('table');
$ci->table->set_heading($headings);
foreach ($data as &$row)
{
$ci->table->add_row($row);
}
return $ci->table->generate();
}
// Format HTML for output
public function to_csv()
{
$data = $this->_data;
// Multi-dimentional array
if (isset($data[0]))
{
$headings = array_keys($data[0]);
}
// Single array
else
{
$headings = array_keys($data);
$data = array($data);
}
$output = implode(',', $headings).PHP_EOL;
foreach ($data as &$row)
{
$output .= '"'.implode('","', $row).'"'.PHP_EOL;
}
return $output;
}
// Encode as JSON
public function to_json()
{
return json_encode($this->_data, JSON_NUMERIC_CHECK);
}
// Encode as Serialized array
public function to_serialized()
{
return serialize($this->_data);
}
// Output as a string representing the PHP structure
public function to_php()
{
return var_export($this->_data, TRUE);
}
// Format XML for output
protected function _from_xml($string)
{
return $string ? (array) simplexml_load_string($string, 'SimpleXMLElement', LIBXML_NOCDATA) : array();
}
// Format HTML for output
// This function is DODGY! Not perfect CSV support but works with my REST_Controller
protected function _from_csv($string)
{
$data = array();
// Splits
$rows = explode("\n", trim($string));
$headings = explode(',', array_shift($rows));
foreach ($rows as $row)
{
// The substr removes " from start and end
$data_fields = explode('","', trim(substr($row, 1, -1)));
if (count($data_fields) == count($headings))
{
$data[] = array_combine($headings, $data_fields);
}
}
return $data;
}
// Encode as JSON
private function _from_json($string)
{
return json_decode(trim($string));
}
// Encode as Serialized array
private function _from_serialize($string)
{
return unserialize(trim($string));
}
}
/* End of file format.php */

View File

@@ -0,0 +1,549 @@
<?php
/**
* Name: Ion Auth
* Author: Ben Edmunds
* ben.edmunds@gmail.com
* @benedmunds
*
* Added Awesomeness: Phil Sturgeon
*
* Created: 10.01.2009
*
* Description: Modified auth system based on redux_auth with extensive customization. This is basically what Redux Auth 2 should be.
* Original Author name has been kept but that does not mean that the method has not been modified.
*
* Requirements: PHP5 or above
*
* @package CodeIgniter-Ion-Auth
* @author Ben Edmunds
* @link http://github.com/benedmunds/CodeIgniter-Ion-Auth
* @filesource
*/
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Class Ion_auth
*/
class Ion_auth
{
/**
* account status ('not_activated', etc ...)
*
* @var string
**/
protected $status;
/**
* extra where
*
* @var array
**/
public $_extra_where = array();
/**
* extra set
*
* @var array
**/
public $_extra_set = array();
/**
* caching of users and their groups
*
* @var array
**/
public $_cache_user_in_group;
/**
* __construct
*
* @author Ben
*/
public function __construct()
{
$this->config->load('ion_auth', TRUE);
$this->load->library(array('email'));
$this->lang->load('ion_auth');
$this->load->helper(array('cookie', 'language','url'));
$this->load->library('session');
$this->load->model('ion_auth_model');
$this->_cache_user_in_group =& $this->ion_auth_model->_cache_user_in_group;
$email_config = $this->config->item('email_config', 'ion_auth');
if ($this->config->item('use_ci_email', 'ion_auth') && isset($email_config) && is_array($email_config))
{
$this->email->initialize($email_config);
}
$this->ion_auth_model->trigger_events('library_constructor');
}
/**
* __call
*
* Acts as a simple way to call model methods without loads of stupid alias'
*
* @param string $method
* @param array $arguments
*
* @return mixed
* @throws Exception
*/
public function __call($method, $arguments)
{
if (!method_exists( $this->ion_auth_model, $method) )
{
throw new Exception('Undefined method Ion_auth::' . $method . '() called');
}
if($method == 'create_user')
{
return call_user_func_array(array($this, 'register'), $arguments);
}
if($method=='update_user')
{
return call_user_func_array(array($this, 'update'), $arguments);
}
return call_user_func_array( array($this->ion_auth_model, $method), $arguments);
}
/**
* __get
*
* Enables the use of CI super-global without having to define an extra variable.
*
* I can't remember where I first saw this, so thank you if you are the original author. -Militis
*
* @param string $var
*
* @return mixed
*/
public function __get($var)
{
$CI = & get_instance();
return isset($CI->$var) ? $CI->$var : null;
}
/**
* Forgotten password feature
*
* @param string $identity
*
* @return array|bool
* @author Mathew
*/
public function forgotten_password($identity)
{
if ($this->ion_auth_model->forgotten_password($identity))
{
// Get user information
$identifier = $this->ion_auth_model->identity_column; // use model identity column, so it can be overridden in a controller
$user = $this->where($identifier, $identity)->where('active', 1)->users()->row();
if ($user)
{
$data = array(
'identity' => $user->{$this->config->item('identity', 'ion_auth')},
'forgotten_password_code' => $user->forgotten_password_code
);
if (!$this->config->item('use_ci_email', 'ion_auth'))
{
$this->set_message('forgot_password_successful');
return $data;
}
else
{
$message = $this->load->view($this->config->item('email_templates', 'ion_auth') . $this->config->item('email_forgot_password', 'ion_auth'), $data, TRUE);
$this->email->clear();
$this->email->from($this->config->item('admin_email', 'ion_auth'), $this->config->item('site_title', 'ion_auth'));
$this->email->to($user->email);
$this->email->subject($this->config->item('site_title', 'ion_auth') . ' - ' . $this->lang->line('email_forgotten_password_subject'));
$this->email->message($message);
if ($this->email->send())
{
$this->set_message('forgot_password_successful');
return TRUE;
}
else
{
$this->set_error('forgot_password_unsuccessful');
return FALSE;
}
}
}
else
{
$this->set_error('forgot_password_unsuccessful');
return FALSE;
}
}
else
{
$this->set_error('forgot_password_unsuccessful');
return FALSE;
}
}
/**
* forgotten_password_complete
*
* @param string $code
*
* @return array|bool
* @author Mathew
*/
public function forgotten_password_complete($code)
{
$this->ion_auth_model->trigger_events('pre_password_change');
$identity = $this->config->item('identity', 'ion_auth');
$profile = $this->where('forgotten_password_code', $code)->users()->row(); // pass the code to profile
if (!$profile)
{
$this->ion_auth_model->trigger_events(array('post_password_change', 'password_change_unsuccessful'));
$this->set_error('password_change_unsuccessful');
return FALSE;
}
$new_password = $this->ion_auth_model->forgotten_password_complete($code, $profile->salt);
if ($new_password)
{
$data = array(
'identity' => $profile->{$identity},
'new_password' => $new_password
);
if(!$this->config->item('use_ci_email', 'ion_auth'))
{
$this->set_message('password_change_successful');
$this->ion_auth_model->trigger_events(array('post_password_change', 'password_change_successful'));
return $data;
}
else
{
$message = $this->load->view($this->config->item('email_templates', 'ion_auth').$this->config->item('email_forgot_password_complete', 'ion_auth'), $data, true);
$this->email->clear();
$this->email->from($this->config->item('admin_email', 'ion_auth'), $this->config->item('site_title', 'ion_auth'));
$this->email->to($profile->email);
$this->email->subject($this->config->item('site_title', 'ion_auth') . ' - ' . $this->lang->line('email_new_password_subject'));
$this->email->message($message);
if ($this->email->send())
{
$this->set_message('password_change_successful');
$this->ion_auth_model->trigger_events(array('post_password_change', 'password_change_successful'));
return TRUE;
}
else
{
$this->set_error('password_change_unsuccessful');
$this->ion_auth_model->trigger_events(array('post_password_change', 'password_change_unsuccessful'));
return FALSE;
}
}
}
$this->ion_auth_model->trigger_events(array('post_password_change', 'password_change_unsuccessful'));
return FALSE;
}
/**
* forgotten_password_check
*
* @param string $code
*
* @return object|bool
* @author Michael
*/
public function forgotten_password_check($code)
{
$profile = $this->where('forgotten_password_code', $code)->users()->row(); // pass the code to profile
if (!is_object($profile))
{
$this->set_error('password_change_unsuccessful');
return FALSE;
}
else
{
if ($this->config->item('forgot_password_expiration', 'ion_auth') > 0)
{
//Make sure it isn't expired
$expiration = $this->config->item('forgot_password_expiration', 'ion_auth');
if (time() - $profile->forgotten_password_time > $expiration)
{
//it has expired
$this->ion_auth_model->clear_forgotten_password_code($code);
$this->set_error('password_change_unsuccessful');
return FALSE;
}
}
return $profile;
}
}
/**
* register
*
* @param string $identity
* @param string $password
* @param string $email
* @param array $additional_data
* @param array $group_ids
*
* @return int|array|bool The new user's ID if e-mail activation is disabled or Ion-Auth e-mail activation was
* completed; or an array of activation details if CI e-mail validation is enabled; or FALSE
* if the operation failed.
* @author Mathew
*/
public function register($identity, $password, $email, $additional_data = array(), $group_ids = array())
{
$this->ion_auth_model->trigger_events('pre_account_creation');
$email_activation = $this->config->item('email_activation', 'ion_auth');
$id = $this->ion_auth_model->register($identity, $password, $email, $additional_data, $group_ids);
if (!$email_activation)
{
if ($id !== FALSE)
{
$this->set_message('account_creation_successful');
$this->ion_auth_model->trigger_events(array('post_account_creation', 'post_account_creation_successful'));
return $id;
}
else
{
$this->set_error('account_creation_unsuccessful');
$this->ion_auth_model->trigger_events(array('post_account_creation', 'post_account_creation_unsuccessful'));
return FALSE;
}
}
else
{
if (!$id)
{
$this->set_error('account_creation_unsuccessful');
return FALSE;
}
// deactivate so the user much follow the activation flow
$deactivate = $this->ion_auth_model->deactivate($id);
// the deactivate method call adds a message, here we need to clear that
$this->ion_auth_model->clear_messages();
if (!$deactivate)
{
$this->set_error('deactivate_unsuccessful');
$this->ion_auth_model->trigger_events(array('post_account_creation', 'post_account_creation_unsuccessful'));
return FALSE;
}
$activation_code = $this->ion_auth_model->activation_code;
$identity = $this->config->item('identity', 'ion_auth');
$user = $this->ion_auth_model->user($id)->row();
$data = array(
'identity' => $user->{$identity},
'id' => $user->id,
'email' => $email,
'activation' => $activation_code,
);
if(!$this->config->item('use_ci_email', 'ion_auth'))
{
$this->ion_auth_model->trigger_events(array('post_account_creation', 'post_account_creation_successful', 'activation_email_successful'));
$this->set_message('activation_email_successful');
return $data;
}
else
{
$message = $this->load->view($this->config->item('email_templates', 'ion_auth').$this->config->item('email_activate', 'ion_auth'), $data, true);
$this->email->clear();
$this->email->from($this->config->item('admin_email', 'ion_auth'), $this->config->item('site_title', 'ion_auth'));
$this->email->to($email);
$this->email->subject($this->config->item('site_title', 'ion_auth') . ' - ' . $this->lang->line('email_activation_subject'));
$this->email->message($message);
if ($this->email->send() === TRUE)
{
$this->ion_auth_model->trigger_events(array('post_account_creation', 'post_account_creation_successful', 'activation_email_successful'));
$this->set_message('activation_email_successful');
return $id;
}
}
$this->ion_auth_model->trigger_events(array('post_account_creation', 'post_account_creation_unsuccessful', 'activation_email_unsuccessful'));
$this->set_error('activation_email_unsuccessful');
return FALSE;
}
}
/**
* Logout
*
* @return true
* @author Mathew
**/
public function logout()
{
$this->ion_auth_model->trigger_events('logout');
$identity = $this->config->item('identity', 'ion_auth');
if (substr(CI_VERSION, 0, 1) == '2')
{
$this->session->unset_userdata(array($identity => '', 'id' => '', 'user_id' => ''));
}
else
{
$this->session->unset_userdata(array($identity, 'id', 'user_id'));
}
// delete the remember me cookies if they exist
if (get_cookie($this->config->item('identity_cookie_name', 'ion_auth')))
{
delete_cookie($this->config->item('identity_cookie_name', 'ion_auth'));
}
if (get_cookie($this->config->item('remember_cookie_name', 'ion_auth')))
{
delete_cookie($this->config->item('remember_cookie_name', 'ion_auth'));
}
// Destroy the session
$this->session->sess_destroy();
//Recreate the session
if (substr(CI_VERSION, 0, 1) == '2')
{
$this->session->sess_create();
}
else
{
session_start();
$this->session->sess_regenerate(TRUE);
}
$this->set_message('logout_successful');
return TRUE;
}
/**
* Auto logs-in the user if they are remembered
* @return bool Whether the user is logged in
* @author Mathew
**/
public function logged_in()
{
$this->ion_auth_model->trigger_events('logged_in');
$recheck = $this->ion_auth_model->recheck_session();
// auto-login the user if they are remembered
if (!$recheck && get_cookie($this->config->item('identity_cookie_name', 'ion_auth')) && get_cookie($this->config->item('remember_cookie_name', 'ion_auth')))
{
$recheck = $this->ion_auth_model->login_remembered_user();
}
return $recheck;
}
/**
* @return int|null The user's ID from the session user data or NULL if not found
* @author jrmadsen67
**/
public function get_user_id()
{
$user_id = $this->session->userdata('user_id');
if (!empty($user_id))
{
return $user_id;
}
return NULL;
}
/**
* @param int|string|bool $id
*
* @return bool Whether the user is an administrator
* @author Ben Edmunds
*/
public function is_admin($id = FALSE)
{
$this->ion_auth_model->trigger_events('is_admin');
$admin_group = $this->config->item('admin_group', 'ion_auth');
return $this->in_group($admin_group, $id);
}
/**
* @param int|string|array $check_group group(s) to check
* @param int|string|bool $id user id
* @param bool $check_all check if all groups is present, or any of the groups
*
* @return bool Whether the/all user(s) with the given ID(s) is/are in the given group
* @author Phil Sturgeon
**/
public function in_group($check_group, $id = FALSE, $check_all = FALSE)
{
$this->ion_auth_model->trigger_events('in_group');
$id || $id = $this->session->userdata('user_id');
if (!is_array($check_group))
{
$check_group = array($check_group);
}
if (isset($this->_cache_user_in_group[$id]))
{
$groups_array = $this->_cache_user_in_group[$id];
}
else
{
$users_groups = $this->ion_auth_model->get_users_groups($id)->result();
$groups_array = array();
foreach ($users_groups as $group)
{
$groups_array[$group->id] = $group->name;
}
$this->_cache_user_in_group[$id] = $groups_array;
}
foreach ($check_group as $key => $value)
{
$groups = (is_numeric($value)) ? array_keys($groups_array) : $groups_array;
/**
* if !all (default), in_array
* if all, !in_array
*/
if (in_array($value, $groups) xor $check_all)
{
/**
* if !all (default), true
* if all, false
*/
return !$check_all;
}
}
/**
* if !all (default), false
* if all, true
*/
return $check_all;
}
}

View File

@@ -0,0 +1,733 @@
<?php defined('BASEPATH') or exit('No direct script access allowed');
/**
* REST_controller V 2.5.x
*
* @see https://github.com/philsturgeon/codeigniter-restserver
*
*/
class REST_Controller extends CI_Controller
{
protected $rest_format = null; // Set this in a controller to use a default format
protected $methods = array(); // contains a list of method properties such as limit, log and level
protected $request = null; // Stores accept, language, body, headers, etc
protected $response = null; // What is gonna happen in output?
public $rest = null; // Stores DB, keys, key level, etc
protected $_get_args = array();
protected $_post_args = array();
protected $_put_args = array();
protected $_delete_args = array();
protected $_args = array();
protected $_allow = true;
// List all supported methods, the first will be the default format
protected $_supported_formats = array(
'xml' => 'application/xml',
'rawxml' => 'application/xml',
'json' => 'application/json',
'jsonp' => 'application/javascript',
'serialized' => 'application/vnd.php.serialized',
'php' => 'text/plain',
'html' => 'text/html',
'csv' => 'application/csv',
);
// Constructor function
public function __construct()
{
parent::__construct();
// Lets grab the config and get ready to party
$this->load->config('rest');
if (empty($this->request)) {
$this->request = new stdClass;
}
if (empty($this->rest)) {
$this->rest = new stdClass;
}
// How is this request being made? POST, DELETE, GET, PUT?
$this->request->method = $this->_detect_method();
// Set up our GET variables
$this->_get_args = array_merge($this->_get_args, $this->uri->ruri_to_assoc());
//$this->load->library('security');
// This library is bundled with REST_Controller 2.5+, but will eventually be part of CodeIgniter itself
$this->load->library('format');
// Try to find a format for the request (means we have a request body)
$this->request->format = $this->_detect_input_format();
// Some Methods cant have a body
$this->request->body = null;
switch ($this->request->method) {
case 'get':
// Grab proper GET variables
parse_str(parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY), $get);
// If there are any, populate $this->_get_args
empty($get) or $this->_get_args = $get;
break;
case 'post':
$this->_post_args = $_POST;
$this->request->format and $this->request->body = file_get_contents('php://input');
break;
case 'put':
// It might be a HTTP body
if ($this->request->format) {
$this->request->body = file_get_contents('php://input');
}
// If no file type is provided, this is probably just arguments
else {
parse_str(file_get_contents('php://input'), $this->_put_args);
}
break;
case 'delete':
// Set up out DELETE variables (which shouldn't really exist, but sssh!)
parse_str(file_get_contents('php://input'), $this->_delete_args);
break;
}
// Now we know all about our request, let's try and parse the body if it exists
if ($this->request->format and $this->request->body) {
$this->request->body = $this->format->factory($this->request->body, $this->request->format)->to_data();
}
// Merge both for one mega-args variable
$this->_args = array_merge($this->_get_args, $this->_put_args, $this->_post_args, $this->_delete_args);
// Which format should the data be returned in?
if (empty($this->response)) {
$this->response = new stdClass;
}
$this->response->format = $this->_detect_output_format();
// Which format should the data be returned in?
$this->response->lang = $this->_detect_lang();
// Check if there is a specific auth type for the current class/method
$this->auth_override = $this->_auth_override_check();
// When there is no specific override for the current class/method, use the default auth value set in the config
if ($this->auth_override !== true) {
if ($this->config->item('rest_auth') == 'basic') {
$this->_prepare_basic_auth();
} elseif ($this->config->item('rest_auth') == 'digest') {
$this->_prepare_digest_auth();
}
}
// Load DB if its enabled
// if (config_item('rest_database_group') AND (config_item('rest_enable_keys') OR config_item('rest_enable_logging')))
// {
$this->rest->db = $this->load->database(config_item('rest_database_group'), true);
// }
// Checking for keys? GET TO WORK!
if (config_item('rest_enable_keys')) {
$this->_allow = $this->_detect_api_key();
}
// only allow ajax requests
if (!$this->input->is_ajax_request() and config_item('rest_ajax_only')) {
$this->response(array('status' => false, 'error' => 'Only AJAX requests are accepted.'), 505);
}
}
/*
* Remap
*
* Requests are not made to methods directly The request will be for an "object".
* this simply maps the object and method to the correct Controller method.
*/
public function _remap($object_called, $arguments)
{
$pattern = '/^(.*)\.(' . implode('|', array_keys($this->_supported_formats)) . ')$/';
if (preg_match($pattern, $object_called, $matches)) {
$object_called = $matches[1];
}
$controller_method = $object_called . '_' . $this->request->method;
// Do we want to log this method (if allowed by config)?
$log_method = !(isset($this->methods[$controller_method]['log']) and $this->methods[$controller_method]['log'] == false);
// Use keys for this method?
$use_key = !(isset($this->methods[$controller_method]['key']) and $this->methods[$controller_method]['key'] == false);
// Get that useless shitty key out of here
if (config_item('rest_enable_keys') and $use_key and $this->_allow === false) {
if (config_item('rest_enable_logging') and $log_method) {
$this->_log_request();
}
$this->response(array('status' => false, 'error' => 'Invalid API Key.'), 403);
}
// Sure it exists, but can they do anything with it?
if (!method_exists($this, $controller_method)) {
$this->response(array('status' => false, 'error' => 'Unknown method.'), 404);
}
// Doing key related stuff? Can only do it if they have a key right?
if (config_item('rest_enable_keys') and !empty($this->rest->key)) {
// Check the limit
if (config_item('rest_enable_limits') and !$this->_check_limit($controller_method)) {
$this->response(array('status' => false, 'error' => 'This API key has reached the hourly limit for this method.'), 401);
}
// If no level is set use 0, they probably aren't using permissions
$level = isset($this->methods[$controller_method]['level']) ? $this->methods[$controller_method]['level'] : 0;
// If no level is set, or it is lower than/equal to the key's level
$authorized = $level <= $this->rest->level;
// IM TELLIN!
if (config_item('rest_enable_logging') and $log_method) {
$this->_log_request($authorized);
}
// They don't have good enough perms
$authorized or $this->response(array('status' => false, 'error' => 'This API key does not have enough permissions.'), 401);
}
// No key stuff, but record that stuff is happening
else if (config_item('rest_enable_logging') and $log_method) {
$this->_log_request($authorized = true);
}
// And...... GO!
call_user_func_array(array($this, $controller_method), $arguments);
}
/*
* response
*
* Takes pure data and optionally a status code, then creates the response
*/
public function response($data = array(), $http_code = null)
{
// If data is empty and not code provide, error and bail
if (empty($data) && $http_code === null) {
$http_code = 404;
}
// Otherwise (if no data but 200 provided) or some data, carry on camping!
else {
is_numeric($http_code) or $http_code = 200;
// If the format method exists, call and return the output in that format
if (method_exists($this, '_format_' . $this->response->format)) {
// Set the correct format header
header('Content-Type: ' . $this->_supported_formats[$this->response->format]);
$output = $this->{'_format_' . $this->response->format}($data);
}
// If the format method exists, call and return the output in that format
elseif (method_exists($this->format, 'to_' . $this->response->format)) {
// Set the correct format header
header('Content-Type: ' . $this->_supported_formats[$this->response->format]);
$output = $this->format->factory($data)->{'to_' . $this->response->format}();
}
// Format not supported, output directly
else {
$output = $data;
}
}
header('HTTP/1.1: ' . $http_code);
header('Status: ' . $http_code);
header('Content-Length: ' . strlen($output));
exit($output);
}
protected function res($code = 200, $message = 'Success', $data = null)
{
$this->response(array('code' => $code, 'message' => $message, 'data' => $data), 200);
}
/*
* Detect input format
*
* Detect which format the HTTP Body is provided in
*/
protected function _detect_input_format()
{
if ($this->input->server('CONTENT_TYPE')) {
// Check all formats against the HTTP_ACCEPT header
foreach ($this->_supported_formats as $format => $mime) {
if (strpos($match = $this->input->server('CONTENT_TYPE'), ';')) {
$match = current(explode(';', $match));
}
if ($match == $mime) {
return $format;
}
}
}
return null;
}
/*
* Detect format
*
* Detect which format should be used to output the data
*/
protected function _detect_output_format()
{
$pattern = '/\.(' . implode('|', array_keys($this->_supported_formats)) . ')$/';
// Check if a file extension is used
if (preg_match($pattern, $this->uri->uri_string(), $matches)) {
return $matches[1];
}
// Check if a file extension is used
elseif ($this->_get_args and !is_array(end($this->_get_args)) and preg_match($pattern, end($this->_get_args), $matches)) {
// The key of the last argument
$last_key = end(array_keys($this->_get_args));
// Remove the extension from arguments too
$this->_get_args[$last_key] = preg_replace($pattern, '', $this->_get_args[$last_key]);
$this->_args[$last_key] = preg_replace($pattern, '', $this->_args[$last_key]);
return $matches[1];
}
// A format has been passed as an argument in the URL and it is supported
if (isset($this->_get_args['format']) and array_key_exists($this->_get_args['format'], $this->_supported_formats)) {
return $this->_get_args['format'];
}
// Otherwise, check the HTTP_ACCEPT (if it exists and we are allowed)
if ($this->config->item('rest_ignore_http_accept') === false and $this->input->server('HTTP_ACCEPT')) {
// Check all formats against the HTTP_ACCEPT header
foreach (array_keys($this->_supported_formats) as $format) {
// Has this format been requested?
if (strpos($this->input->server('HTTP_ACCEPT'), $format) !== false) {
// If not HTML or XML assume its right and send it on its way
if ($format != 'html' and $format != 'xml') {
return $format;
}
// HTML or XML have shown up as a match
else {
// If it is truely HTML, it wont want any XML
if ($format == 'html' and strpos($this->input->server('HTTP_ACCEPT'), 'xml') === false) {
return $format;
}
// If it is truely XML, it wont want any HTML
elseif ($format == 'xml' and strpos($this->input->server('HTTP_ACCEPT'), 'html') === false) {
return $format;
}
}
}
}
} // End HTTP_ACCEPT checking
// Well, none of that has worked! Let's see if the controller has a default
if (!empty($this->rest_format)) {
return $this->rest_format;
}
// Just use the default format
return config_item('rest_default_format');
}
/*
* Detect method
*
* Detect which method (POST, PUT, GET, DELETE) is being used
*/
protected function _detect_method()
{
$method = strtolower($this->input->server('REQUEST_METHOD'));
if ($this->config->item('enable_emulate_request') && $this->input->post('_method')) {
$method = $this->input->post('_method');
}
if (in_array($method, array('get', 'delete', 'post', 'put'))) {
return $method;
}
return 'get';
}
/*
* Detect API Key
*
* See if the user has provided an API key
*/
protected function _detect_api_key()
{
// Get the api key name variable set in the rest config file
$api_key_variable = config_item('rest_key_name');
// Work out the name of the SERVER entry based on config
$key_name = 'HTTP_' . strtoupper(str_replace('-', '_', $api_key_variable));
$this->rest->key = null;
$this->rest->level = null;
$this->rest->ignore_limits = false;
// Find the key from server or arguments
if ($key = isset($this->_args[$api_key_variable]) ? $this->_args[$api_key_variable] : $this->input->server($key_name)) {
if (!$row = $this->rest->db->where('key', $key)->get(config_item('rest_keys_table'))->row()) {
return false;
}
$this->rest->key = $row->key;
isset($row->level) and $this->rest->level = $row->level;
isset($row->ignore_limits) and $this->rest->ignore_limits = $row->ignore_limits;
return true;
}
// No key has been sent
return false;
}
/*
* Detect language(s)
*
* What language do they want it in?
*/
protected function _detect_lang()
{
if (!$lang = $this->input->server('HTTP_ACCEPT_LANGUAGE')) {
return null;
}
// They might have sent a few, make it an array
if (strpos($lang, ',') !== false) {
$langs = explode(',', $lang);
$return_langs = array();
$i = 1;
foreach ($langs as $lang) {
// Remove weight and strip space
list($lang) = explode(';', $lang);
$return_langs[] = trim($lang);
}
return $return_langs;
}
// Nope, just return the string
return $lang;
}
/*
* Log request
*
* Record the entry for awesomeness purposes
*/
protected function _log_request($authorized = false)
{
return $this->rest->db->insert(config_item('rest_logs_table'), array(
'uri' => $this->uri->uri_string(),
'method' => $this->request->method,
'params' => serialize($this->_args),
'api_key' => isset($this->rest->key) ? $this->rest->key : '',
'ip_address' => $this->input->ip_address(),
'time' => function_exists('now') ? now() : time(),
'authorized' => $authorized,
));
}
/*
* Log request
*
* Record the entry for awesomeness purposes
*/
protected function _check_limit($controller_method)
{
// They are special, or it might not even have a limit
if (!empty($this->rest->ignore_limits) or !isset($this->methods[$controller_method]['limit'])) {
// On your way sonny-jim.
return true;
}
// How many times can you get to this method an hour?
$limit = $this->methods[$controller_method]['limit'];
// Get data on a keys usage
$result = $this->rest->db
->where('uri', $this->uri->uri_string())
->where('api_key', $this->rest->key)
->get(config_item('rest_limits_table'))
->row();
// No calls yet, or been an hour since they called
if (!$result or $result->hour_started < time() - (60 * 60)) {
// Right, set one up from scratch
$this->rest->db->insert(config_item('rest_limits_table'), array(
'uri' => $this->uri->uri_string(),
'api_key' => isset($this->rest->key) ? $this->rest->key : '',
'count' => 1,
'hour_started' => time(),
));
}
// They have called within the hour, so lets update
else {
// Your luck is out, you've called too many times!
if ($result->count >= $limit) {
return false;
}
$this->rest->db
->where('uri', $this->uri->uri_string())
->where('api_key', $this->rest->key)
->set('count', 'count + 1', false)
->update(config_item('rest_limits_table'));
}
return true;
}
/*
* Auth override check
*
* Check if there is a specific auth type set for the current class/method being called
*/
protected function _auth_override_check()
{
// Assign the class/method auth type override array from the config
$this->overrides_array = $this->config->item('auth_override_class_method');
// Check to see if the override array is even populated, otherwise return false
if (empty($this->overrides_array)) {
return false;
}
// Check to see if there's an override value set for the current class/method being called
if (empty($this->overrides_array[$this->router->class][$this->router->method])) {
return false;
}
// None auth override found, prepare nothing but send back a true override flag
if ($this->overrides_array[$this->router->class][$this->router->method] == 'none') {
return true;
}
// Basic auth override found, prepare basic
if ($this->overrides_array[$this->router->class][$this->router->method] == 'basic') {
$this->_prepare_basic_auth();
return true;
}
// Digest auth override found, prepare digest
if ($this->overrides_array[$this->router->class][$this->router->method] == 'digest') {
$this->_prepare_digest_auth();
return true;
}
// Return false when there is an override value set but it doesn't match 'basic', 'digest', or 'none'. (the value was misspelled)
return false;
}
// INPUT FUNCTION --------------------------------------------------------------
public function get($key = null, $xss_clean = true)
{
if ($key === null) {
return $this->_get_args;
}
return array_key_exists($key, $this->_get_args) ? $this->_xss_clean($this->_get_args[$key], $xss_clean) : false;
}
public function post($key = null, $xss_clean = true)
{
if ($key === null) {
return $this->_post_args;
}
return $this->input->post($key, $xss_clean);
}
public function put($key = null, $xss_clean = true)
{
if ($key === null) {
return $this->_put_args;
}
return array_key_exists($key, $this->_put_args) ? $this->_xss_clean($this->_put_args[$key], $xss_clean) : false;
}
public function delete($key = null, $xss_clean = true)
{
if ($key === null) {
return $this->_delete_args;
}
return array_key_exists($key, $this->_delete_args) ? $this->_xss_clean($this->_delete_args[$key], $xss_clean) : false;
}
protected function _xss_clean($val, $bool)
{
if (CI_VERSION < 2) {
return $bool ? $this->input->xss_clean($val) : $val;
} else {
return $bool ? $this->security->xss_clean($val) : $val;
}
}
public function validation_errors()
{
$string = strip_tags($this->form_validation->error_string());
return explode("\n", trim($string, "\n"));
}
// SECURITY FUNCTIONS ---------------------------------------------------------
protected function _check_login($username = '', $password = null)
{
if (empty($username)) {
return false;
}
$valid_logins = &$this->config->item('rest_valid_logins');
if (!array_key_exists($username, $valid_logins)) {
return false;
}
// If actually NULL (not empty string) then do not check it
if ($password !== null and $valid_logins[$username] != $password) {
return false;
}
return true;
}
protected function _prepare_basic_auth()
{
$username = null;
$password = null;
// mod_php
if ($this->input->server('PHP_AUTH_USER')) {
$username = $this->input->server('PHP_AUTH_USER');
$password = $this->input->server('PHP_AUTH_PW');
}
// most other servers
elseif ($this->input->server('HTTP_AUTHENTICATION')) {
if (strpos(strtolower($this->input->server('HTTP_AUTHENTICATION')), 'basic') === 0) {
list($username, $password) = explode(':', base64_decode(substr($this->input->server('HTTP_AUTHORIZATION'), 6)));
}
}
if (!$this->_check_login($username, $password)) {
$this->_force_login();
}
}
protected function _prepare_digest_auth()
{
$uniqid = uniqid(""); // Empty argument for backward compatibility
// We need to test which server authentication variable to use
// because the PHP ISAPI module in IIS acts different from CGI
if ($this->input->server('PHP_AUTH_DIGEST')) {
$digest_string = $this->input->server('PHP_AUTH_DIGEST');
} elseif ($this->input->server('HTTP_AUTHORIZATION')) {
$digest_string = $this->input->server('HTTP_AUTHORIZATION');
} else {
$digest_string = "";
}
/* The $_SESSION['error_prompted'] variabile is used to ask
the password again if none given or if the user enters
a wrong auth. informations. */
if (empty($digest_string)) {
$this->_force_login($uniqid);
}
// We need to retrieve authentication informations from the $auth_data variable
preg_match_all('@(username|nonce|uri|nc|cnonce|qop|response)=[\'"]?([^\'",]+)@', $digest_string, $matches);
$digest = array_combine($matches[1], $matches[2]);
if (!array_key_exists('username', $digest) or !$this->_check_login($digest['username'])) {
$this->_force_login($uniqid);
}
$valid_logins = &$this->config->item('rest_valid_logins');
$valid_pass = $valid_logins[$digest['username']];
// This is the valid response expected
$A1 = md5($digest['username'] . ':' . $this->config->item('rest_realm') . ':' . $valid_pass);
$A2 = md5(strtoupper($this->request->method) . ':' . $digest['uri']);
$valid_response = md5($A1 . ':' . $digest['nonce'] . ':' . $digest['nc'] . ':' . $digest['cnonce'] . ':' . $digest['qop'] . ':' . $A2);
if ($digest['response'] != $valid_response) {
header('HTTP/1.0 401 Unauthorized');
header('HTTP/1.1 401 Unauthorized');
exit;
}
}
protected function _force_login($nonce = '')
{
if ($this->config->item('rest_auth') == 'basic') {
header('WWW-Authenticate: Basic realm="' . $this->config->item('rest_realm') . '"');
} elseif ($this->config->item('rest_auth') == 'digest') {
header('WWW-Authenticate: Digest realm="' . $this->config->item('rest_realm') . '" qop="auth" nonce="' . $nonce . '" opaque="' . md5($this->config->item('rest_realm')) . '"');
}
$this->response(array('status' => false, 'error' => 'Not authorized'), 401);
}
// Force it into an array
protected function _force_loopable($data)
{
// Force it to be something useful
if (!is_array($data) and !is_object($data)) {
$data = (array) $data;
}
return $data;
}
// FORMATING FUNCTIONS ---------------------------------------------------------
// Many of these have been moved to the Format class for better separation, but these methods will be checked too
// Encode as JSONP
protected function _format_jsonp($data = array())
{
return $this->get('callback') . '(' . json_encode($data) . ')';
}
}

View File

@@ -0,0 +1,62 @@
<?php
class RadioService
{
private $CI;
const TOKEN_MAXAGE = 3600;
const APP_ID = 75;
public function __construct()
{
$this->CI = &get_instance();
}
public function getAppId($appId = null) {
return $appId ? $appId : self::APP_ID;
}
public function checkToken()
{
$key = $this->CI->input->server('HTTP_ACCESS_TOKEN');
$key = $this->CI->rest->db->where('key', $key)->get(config_item('rest_keys_table'));
if ($key->num_rows() == 0) {
return 401;
} else if ($key->row()->date_created < time() - self::TOKEN_MAXAGE) {
return 402;
}
}
public function getSchedule($categoryId, $day)
{
$this->CI->load->model('station_schedule_model');
return $this->CI->station_schedule_model->findSchedulesByCategoryIdAndDayName($categoryId, $day)->result();
}
public function getApp($appId)
{
$this->CI->load->model('app_model');
$app = $this->CI->app_model->findByAppId($appId)->row();
$customInfos = unserialize($app->customInfo);
$app->customInfo = array();
for ($i = 0; $i < count($customInfos['link']); $i++) {
foreach ($customInfos as $field => $values) {
$app->customInfo[$i][$field] = $values[$i];
}
}
$app->customInfo = array_filter($app->customInfo, function ($info) {
return count(array_filter(array_values($info)));
});
return $app;
}
public function getCategory($appId)
{
$this->CI->load->model('category_model');
$categories = $this->CI->category_model->findCategoriesByAppId($appId)->result();
return $categories;
}
}

View File

@@ -0,0 +1,10 @@
<html>
<head>
<title>403 Forbidden</title>
</head>
<body>
<p>Directory access is forbidden.</p>
</body>
</html>