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

This commit is contained in:
jeonghwa
2026-07-03 05:27:47 +09:00
commit d8dab43237
1460 changed files with 134466 additions and 0 deletions

View File

@@ -0,0 +1,78 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Accesslevel class
*/
/**
* 권한이 있는지 없는지 판단하는 class 입니다.
*/
class Accesslevel extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
/**
* 접근권한이 있는지를 판단합니다
*/
public function is_accessable($access_type = '', $group = '', $check = array())
{
$access_type = (string) $access_type;
if (empty($access_type)) { // 모든 사용자
return true;
} elseif ($access_type === '1') { // 로그인 사용자
if ($this->CI->userlib->is_user() === false) {
return false;
}
return true;
} elseif ($access_type === '100') { // 관리자
if ($this->CI->userlib->is_admin($check) === false) {
return false;
}
return true;
}
}
/**
* 접근권한이 없으면 alert 를 띄웁니다
*/
public function check($access_type = '', $group = '', $alertmessage = '', $check = array())
{
if (empty($alertmessage)) {
$alertmessage = '접근 권한이 없습니다';
}
$accessable = $this->is_accessable($access_type, $group, $check);
if ($accessable) {
return true;
} else {
alert($alertmessage);
return false;
}
}
public function check_admin($type = '', $msg = '')
{
if (empty($msg)) {
$msg = '접근 권한이 없습니다';
}
if ($this->CI->userlib->is_admin() == 'super') {
return;
}
if ( ! $this->CI->userlib->is_admin()) {
alert($msg);
exit;
}
alert($msg);
exit;
}
}

View File

@@ -0,0 +1,183 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Apilib
*/
class Apilib extends CI_Controller
{
private $CI;
public $returntype;
function __construct()
{
$this->CI = & get_instance();
}
function callapi($data ='', $returntype='xml')
{
$libraryname = element('api_name', $data);
$this->returntype = $returntype;
if (strtolower(element('api_method', $data)) == 'get' && strtolower($this->CI->input->method()) != 'get')
{
$this->CI->apilib->make_error("GET 방식으로 넘어오지 않았습니다");
}
if (strtolower(element('api_method', $data)) == 'post' && strtolower($this->CI->input->method()) != 'post')
{
$this->CI->apilib->make_error("POST 방식으로 넘어오지 않았습니다");
}
if ($returntype == 'xml') {
$result = $this->xml($libraryname);
}
else if ($returntype == 'json') {
$result = $this->json($libraryname);
}
else if ($returntype == 'json2') {
$result = $this->json2($libraryname);
}
return $result;
}
function array2XML($arr, $root)
{
$xml = new SimpleXMLElement("<?xml version=\"1.0\" encoding=\"utf-8\" ?><{$root}></{$root}>");
if(is_array($arr)){
$this->array2XML2($arr, $xml);
}
return $xml->asXML();
}
function array2XML2($arr, $obj)
{
if(is_array($arr)){
foreach($arr as $k => $v){
if(is_array($v)){
if(is_numeric($k)){
${$k} = $obj->addChild("data");
$this->array2XML2($v, ${$k});
}else{
${$k} = $obj->addChild($k);
$this->array2XML2($v, ${$k});
}
}else{
$node = $obj->addChild($k);
$node = dom_import_simplexml($node);
$no = $node->ownerDocument;
$node->appendChild($no->createCDATASection($v));
}
}
}
}
function urlencode_data($arg)
{
if(is_array($arg)){
foreach($arg as $k => $v){
$arg[$k] = $this->urlencode_data($v);
}
}else{
if(gettype($arg) == "string")
$arg = urlencode($arg);
if(is_numeric($arg))
$arg = (float)$arg;
if(is_int($arg))
$arg = (int)$arg;
}
return $arg;
}
function make_error($result_text)
{
$arr = array();
$arr['result'] = "error";
$arr['result_text'] = $result_text;
$this->make_error_log($result_text);
$returntype = 'show_' . $this->returntype;
echo $this->$returntype($arr);
exit;
}
function make_error_log($el_result)
{
$strlen = strlen(admin_url());
if(substr($this->CI->input->SERVER('PHP_SELF'), 0, $strlen) == admin_url()) {
return;
}
$vars = ($this->CI->input->method() == "post") ? $_POST : $_GET;
$el_vars_arr = array();
foreach($vars as $k => $v){
$el_vars_arr[] = $k . '=' . $v;
}
$el_vars = implode("&", $el_vars_arr);
$this->CI->load->model('Api_error_log_model');
$insertdata = array(
'el_ip' => $this->CI->input->ip_address(),
'el_result' => $el_result,
'el_self' => $this->CI->input->SERVER('PHP_SELF'),
'el_vars' => $el_vars,
'el_regdate' => cdate('Y-m-d H:i:s'),
);
$this->CI->Api_error_log_model->insert($insertdata);
}
function xml($libraryname)
{
header("Content-Type: text/xml;charset=utf-8");
$this->CI->load->library('apis/' . $libraryname);
$result = $this->CI->{$libraryname}->main();
return $this->array2XML($result, 'info');
}
function json($libraryname)
{
header("Content-Type: text/html;charset=utf-8");
$this->CI->load->library('apis/' . $libraryname);
$result = $this->CI->{$libraryname}->main();
$result = $this->urlencode_data($result);
return json_encode($result);
}
function json2($libraryname)
{
header("Content-Type: text/html;charset=utf-8");
$this->CI->load->library('apis/' . $libraryname);
$result = $this->CI->{$libraryname}->main();
$result = $this->urlencode_data($result);
return urldecode(json_encode($result));
}
function show_xml($arr)
{
header("Content-Type: text/xml;charset=utf-8");
return $this->array2XML($arr, 'info');
}
function show_json($arr)
{
header("Content-Type: text/html;charset=utf-8");
$result = $this->urlencode_data($arr);
return json_encode($result);
}
function show_json2($arr)
{
header("Content-Type: text/html;charset=utf-8");
$result = $this->urlencode_data($arr);
return urldecode(json_encode($result));
}
}

View File

@@ -0,0 +1,89 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Configlib class
*/
/**
* config table 을 관리하는 class 입니다.
*/
class Configlib extends CI_Controller
{
private $CI;
private $cfg;
private $device_view_type;
private $device_type;
function __construct()
{
$this->CI = & get_instance();
}
/**
* config table 에서 정보를 얻습니다
*/
public function get_config()
{
$this->CI->load->model('Config_model');
$this->cfg = $this->CI->Config_model->get_all_meta();
}
/**
* config table 의 item 을 얻습니다
*/
public function item($column = '')
{
if (empty($column)) {
return false;
}
if (empty($this->cfg)) {
$this->get_config();
}
if (empty($this->cfg)) {
return false;
}
$config = $this->cfg;
return isset($config[$column]) ? $config[$column] : false;
}
/**
* 모바일버전보기/PC버전보기 설정 저장합니다
*/
public function set_device_view_type($device_view_type)
{
$this->device_view_type = $device_view_type;
}
/**
* 모바일버전보기/PC버전보기 설정 불러옵니다
*/
public function get_device_view_type()
{
return $this->device_view_type;
}
/**
* 현재 접속한 디바이스가 PC인지 mobile 인지를 저장합니다
*/
public function set_device_type($device_type)
{
$this->device_type = $device_type;
}
/**
* 현재 접속한 디바이스가 PC인지 mobile 인지를 불러옵니다
*/
public function get_device_type()
{
return $this->device_type;
}
}

View File

@@ -0,0 +1,9 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
require_once FCPATH . "plugin/phpexcel/PHPExcel.php";
class Excel extends PHPExcel {
public function __construct() {
parent::__construct();
}
}

View File

@@ -0,0 +1,115 @@
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
class Fcm_library {
function __construct() {
$this->ci = & get_instance();
$this->ci->load->config('fcm');
}
function send($sendto='topic', $topic='all', $user_id, $token, $title, $body) {
if($sendto=='token' && !$token) return false;
if(!$title || !$body) return false;
//토큰값 가져오기
$google_api_key = $this->ci->config->item('fcm_api_key');
//전송하기
$url = 'https://fcm.googleapis.com/fcm/send';
$fields = array(
'priority' => 'high',
'data' => json_decode($body,true),//array로 넘겨야 함
'content_available' => true
);
//iOS용 notification을 추가. 백그라운드 상태에서 보이기위함
$fields['notification'] = array(
'title' => $title,
'body' => $body,
'content_available' => true
);
//전송대상
if($sendto=='topic') {
$fields['to'] = "/topics/".$topic;
} else {
$fields['to'] = $token;
}
$headers = array(
'Authorization:key=' . $google_api_key,
'Content-Type: application/json'
);
//print_r($fields);
//CURL 로 전송
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
$response = curl_exec($ch);
if ($response === false) {
$response = curl_error($ch);
}
curl_close($ch);
//echo $response;
$this->log(
$sendto
, $topic
, $user_id
, $token
, $title
, $body
, $response
);
return $response;
}
function log($sendto, $topic, $user_id, $user_token, $title, $message, $response) {
//응답값 처리
$response_arr = json_decode($response, true);
//응답값 받아서 DB에 넣기
$updatedate = array(
'sendto' => $sendto,
'topic' => $topic,
'user_id' => $user_id,
'user_token' => $user_token,
'title' => $title,
'message' => $message,
'message_id' => (element('multicast_id',$response_arr)) ? element('multicast_id',$response_arr) : element('message_id',$response_arr),
'success' => element('success', $response_arr),
'failure' => element('failure', $response_arr),
'response' => $response,
'regdate' => date('Y-m-d H:i:s')
);
$this->ci->db->insert('fcm_result', $updatedate);
}
//회원에 토큰등록
function update_token($user_id, $user_fcm_token) {
if(!$user_id) return false;
if(!$user_fcm_token) return false;
//기존 토큰 등록된 아이디는 없애기
$updatedata = array('user_fcm_token'=>'');
$this->ci->db->update('user', $updatedata, array('user_fcm_token'=>$user_fcm_token));
//토큰 등록
$updatedata = array('user_fcm_token'=>$user_fcm_token);
$this->ci->db->update('user', $updatedata, array('user_id'=>$user_id));
return true;
}
}

View File

@@ -0,0 +1,114 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Imagelib class
*/
/**
* image 를 관리하는 class 입니다.
*/
class Imagelib extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
/**
* 본문 내용중 외부 이미지주소를 서버로 가져온 후에 내부 주소로 변경합니다
*/
public function replace_external_image($content = '')
{
if (empty($content)) {
return;
}
$patten = "/<img[^>]*src=[\"']?([^>\"']+)[\"']?[^>]*>/i";
preg_match_all($patten, $content, $match);
if (isset($match[1]) && $match[1]) {
foreach ($match[1] as $link) {
$url = @parse_url($link);
if ( ! empty($url['host']) && $url['host'] !== $this->CI->input->server('HTTP_HOST')) {
$image = $this->save_external_image($link, $url['path']);
if ($image) {
$content = str_replace($link, $image, $content);
}
}
}
}
return $content;
}
public function save_external_image($url = '', $path = '')
{
if (empty($url)) {
return;
}
$ch = curl_init ($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_BINARYTRANSFER,1);
$err = curl_error($ch);
if (empty($err)) {
$rawdata = curl_exec($ch);
}
curl_close ($ch);
if ($rawdata) {
$ext = get_extension($path);
$upload_path = config_item('uploads_dir') . '/editor/';
if (is_dir($upload_path) === false) {
mkdir($upload_path, 0707);
$file = $upload_path . 'index.php';
$f = @fopen($file, 'w');
@fwrite($f, '');
@fclose($f);
@chmod($file, 0644);
}
$upload_path .= cdate('Y') . '/';
if (is_dir($upload_path) === false) {
mkdir($upload_path, 0707);
$file = $upload_path . 'index.php';
$f = @fopen($file, 'w');
@fwrite($f, '');
@fclose($f);
@chmod($file, 0644);
}
$upload_path .= cdate('m') . '/';
if (is_dir($upload_path) === false) {
mkdir($upload_path, 0707);
$file = $upload_path . 'index.php';
$f = @fopen($file, 'w');
@fwrite($f, '');
@fclose($f);
@chmod($file, 0644);
}
list($usec, $sec) = explode(' ', microtime());
$file_name = md5(uniqid(mt_rand())) . '_' . str_replace('.', '', $sec . $usec) . '.' . $ext;
$save_dir = $upload_path. $file_name;
$save_url = site_url(config_item('uploads_dir') . '/editor/' . cdate('Y') . '/' . cdate('m') . '/' . $file_name);
$fp = fopen($save_dir, 'w');
fwrite($fp, $rawdata);
fclose($fp);
if (file_exists($save_dir)) {
return $save_url;
}
}
return;
}
}

View File

@@ -0,0 +1,72 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/* Copyright (C) NAVER <http://www.navercorp.com> */
/**
*xpressengine 소스 참고
*/
class Ipfilter
{
public function filter($ip_list = '', $ip = null)
{
if (empty($ip)) {
$ip = $_SERVER['REMOTE_ADDR'];
}
$long_ip = ip2long($ip);
if ($ip_list) {
foreach ($ip_list as $filter_ip) {
$range = explode('-', $filter_ip);
if ( ! isset($range[1]) OR empty($range[1])) { // single address type
$star_pos = strpos($filter_ip, '*');
if ($star_pos !== false) { // wild card exist
if (strncmp($filter_ip, $ip, $star_pos) === 0) {
return true;
}
} elseif (strcmp($filter_ip, $ip) === 0) {
return true;
}
} elseif (ip2long($range[0]) <= $long_ip && ip2long($range[1]) >= $long_ip) {
return true;
}
}
}
return false;
}
public function validate($ip_list = array())
{
/* 사용가능한 표현
* 192.168.2.10 - 4자리의 정확한 ip주소
* 192.168.*.* - 와일드카드(*)가 사용된 4자리의 ip주소, a클래스에는 와일드카드 사용불가,
* 와일드카드 이후의 아이피주소 허용(단, filter()를 쓸 경우 와일드카드 이후 주소는 무시됨
* 192.168.1.1-192.168.1.10 - '-'로 구분된 정확한 4자리의 ip주소 2개
*/
$regex = "/^
(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
(?:
(?:
(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}
(?:-(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){1}
(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}
)
|
(?:
(?:\.(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|\*)){3}
)
)
$/";
$regex = str_replace(array("\r\n", "\n", "\r", "\t", " "), '', $regex);
foreach ($ip_list as $i => $ip) {
preg_match($regex, $ip, $matches);
if ( ! count($matches)) {
return false;
}
}
return true;
}
}

View File

@@ -0,0 +1,174 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Layoutlib class
*/
/**
* 레이아웃을 관리하는 class 입니다.
*/
class Layoutlib extends CI_Controller
{
private $css = array();
private $js = array();
function __construct()
{
}
/**
* 관리자페이지 레이아웃관리합니다
*/
function admin($config = array(), $device_view_type = '')
{
$data = array();
$CI = & get_instance();
$CI->load->config('ci_admin_menu');
$admin_page_menu = config_item('admin_page_menu');
$data['admin_page_menu'] = $admin_page_menu;
if (uri_string() !== config_item('uri_segment_admin')) {
list($data['menu_dir1'], $data['menu_dir2']) = explode('/', str_replace(config_item('uri_segment_admin') . '/', '', uri_string()));
$data['menu_title'] = element('name', element(element('menu_dir2', $data), element('menu', element(element('menu_dir1', $data), element('admin_page_menu', $data)))));
} else {
$data['menu_dir1'] = '';
$data['menu_dir2'] = '';
}
$layout_skin_file = element('layout', $config);
$skin_file = element('skin', $config);
$data['layout_skin_path'] = 'admin';
$data['layout_skin_url'] = base_url( VIEW_DIR . element('layout_skin_path', $data));
$data['index_url'] = admin_url($data['menu_dir1'] . '/' . $data['menu_dir2']);
$data['layout_skin_file'] = $data['layout_skin_path'] . '/' . $layout_skin_file;
$data['view_skin_file'] = $data['layout_skin_path'] . '/';
if ($data['menu_dir1']) {
$data['view_skin_file'] .= $data['menu_dir1'] . '/';
}
if ($data['menu_dir2']) {
$data['view_skin_file'] .= $data['menu_dir2'] . '/';
}
$data['view_skin_path'] = $data['view_skin_file'];
$data['view_skin_url'] = base_url( VIEW_DIR . $data['view_skin_path']);
$data['view_skin_file'] .= $skin_file;
$data['favicon'] = $CI->configlib->item('site_favicon') ? site_url(config_item('uploads_dir') . '/favicon/' . $CI->configlib->item('site_favicon')) : '';
$data['admin-skin'] = $CI->userlib->item('admin-skin') ? $CI->userlib->item('admin-skin') : 'skin-blue';
$data['admin-layout-fixed'] = $CI->userlib->item('admin-layout-fixed') == 'fixed' ? $CI->userlib->item('admin-layout-fixed') : '';
$data['admin-layout-layout-boxed'] = $CI->userlib->item('admin-layout-layout-boxed') == 'layout-boxed' ? $CI->userlib->item('admin-layout-layout-boxed') : '';
$data['admin-layout-sidebar-collapse'] = $CI->userlib->item('admin-layout-sidebar-collapse') == 'sidebar-collapse' ? $CI->userlib->item('admin-layout-sidebar-collapse') : '';
$data['admin-layout-control-sidebar-open'] = $CI->userlib->item('admin-layout-control-sidebar-open') == 'control-sidebar-open' ? $CI->userlib->item('admin-layout-control-sidebar-open') : '';
$data['admin-layout-sidebarskin'] = $CI->userlib->item('admin-layout-sidebarskin') == 'control-sidebar-light' ? 'control-sidebar-light' : 'control-sidebar-dark';
$page_name = '';
if (isset($data['menu_dir1']) && $data['menu_dir1'] ) {
$page_name = $data['admin_page_menu'][$data['menu_dir1']]['__config']['name'];
}
$user_id = (int) $CI->userlib->item('user_id');
return $data;
}
/**
* 프론트페이지 레이아웃관리합니다
*/
function front($config = array(), $device_view_type = '')
{
$data = array();
$CI = & get_instance();
$layout = '_layout';
$data['layout_skin_path'] = $layout;
$data['layout_skin_url'] = base_url( VIEW_DIR . $data['layout_skin_path']);
$layout .= '/';
if (element('layout', $config)) {
$layout .= element('layout', $config);
}
$data['layout_skin_file'] = $layout;
$skin = '';
if (element('path', $config)) {
$skin .= element('path', $config);
}
$data['view_skin_path'] = $skin;
$data['view_skin_url'] = base_url( VIEW_DIR . $data['view_skin_path']);
$skin .= '/';
if (element('skin', $config)) {
$skin .= element('skin', $config);
}
$data['view_skin_file'] = $skin;
$data['page_title'] = $CI->configlib->item('site_title');
$data['favicon'] = $CI->configlib->item('site_favicon') ? site_url(config_item('uploads_dir') . '/favicon/' . $CI->configlib->item('site_favicon')) : '';
$user_id = (int) $CI->userlib->item('user_id');
return $data;
}
/**
* css를 추가합니다
*/
function add_css($file = '')
{
if (empty($file)) {
return;
}
array_push($this->css, $file);
}
/**
* js를 추가합니다
*/
function add_js($file = '')
{
if (empty($file)) {
return;
}
array_push($this->js, $file);
}
/**
* 추가된 css를 리턴합니다
*/
function display_css()
{
$return = '';
$_css = $this->css;
if ($_css) {
foreach ($_css as $val) {
$return .= '<link rel="stylesheet" type="text/css" href="' . $val . '" />';
}
}
return $return;
}
/**
* 추가된 js를 리턴합니다
*/
function display_js()
{
$return = '';
$_js = $this->js;
if ($_js) {
foreach ($_js as $val) {
$return .= '<script type="text/javascript" src="' . $val . '"></script>';
}
}
return $return;
}
}

View File

@@ -0,0 +1,75 @@
<?php
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014 - 2015, British Columbia Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author EllisLab Dev Team
* @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
* @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
* @license http://opensource.org/licenses/MIT MIT License
* @link http://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Email Class
*
* Permits email to be sent using Mail, Sendmail, or SMTP.
*
* @package CodeIgniter
* @subpackage Libraries
* @category Libraries
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/libraries/email.html
*/
class MY_Email extends CI_Email
{
var $CI;
/**
* Constructor - Sets Email Preferences
*
* The constructor can be passed an array of config values
*/
function __construct()
{
parent::__construct();
$this->CI =& get_instance();
$this->protocol = $this->CI->config->item('email_protocal') ? $this->CI->config->item('email_protocal') : 'mail'; // mail/sendmail/smtp
$this->smtp_host = $this->CI->config->item('email_smtp_host'); // SMTP Server. Example: mail.earthlink.net
$this->smtp_user = $this->CI->config->item('email_smtp_user'); // SMTP Username
$this->smtp_pass = $this->CI->config->item('email_smtp_pass'); // SMTP Password
$this->smtp_port = $this->CI->config->item('email_smtp_port'); // SMTP Port
$this->smtp_crypto = $this->CI->config->item('email_smtp_crypto'); // SMTP Encryption. Can be null, tls or ssl.
$this->mailtype = 'html';
}
}

View File

@@ -0,0 +1,135 @@
<?php
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014 - 2015, British Columbia Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author EllisLab Dev Team
* @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
* @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
* @license http://opensource.org/licenses/MIT MIT License
* @link http://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Form Validation Class
*
* @package CodeIgniter
* @subpackage Libraries
* @category Validation
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/libraries/form_validation.html
*/
/*
CI_Form_validation 에서 is_unique 변형
db 업데이트시 자기 자신의 값과는 비교하지 않음
예를 들어 email 이 is_unique 임을 체크할 때
본인의 이메일을 수정 가능하다고 할 때, 기존 자기 이메일의 값과는 비교하지 않음
*/
class MY_Form_validation extends CI_Form_validation
{
protected $CI;
protected $_field_data = array();
protected $_config_rules = array();
protected $_error_array = array();
protected $_error_messages = array();
protected $_error_prefix = '<p>';
protected $_error_suffix = '</p>';
protected $error_string = '';
protected $_safe_form_data = false;
/**
* Constructor
*/
function __construct()
{
parent::__construct();
}
// --------------------------------------------------------------------
/**
* Match one field to another
*
* @access public
* @param string
* @param field
* @return bool
*/
public function is_unique($str, $field)
{
if (substr_count($field, '.') === 3) {
list($table, $field, $id_field, $id_val) = explode('.', $field);
$query = $this->CI->db->limit(1)->where($field, $str)->where($id_field . ' != ', $id_val)->get($table);
} else {
list($table, $field) = explode('.', $field);
$query = $this->CI->db->limit(1)->get_where($table, array($field => $str));
}
return $query->num_rows() === 0;
}
// --------------------------------------------------------------------
/**
* Alpha-numeric with underscores and dashes
*
* @access public
* @param string
* @return bool
*/
public function alphanumunder($str)
{
return ( ! preg_match("/^([-a-z0-9_])+$/i", $str)) ? false : true;
}
public function valid_url($str)
{
$pattern = "|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i";
if ( ! preg_match($pattern, $str)) {
return false;
}
return true;
}
public function valid_phone($value)
{
$value = trim($value);
if ($value === '') {
return true;
} else {
if (preg_match('/^\(?[0-9]{2,3}\)?[-. ]?[0-9]{3,4}[-. ]?[0-9]{4}$/', $value)) {
return preg_replace('/^\(?([0-9]{2,3})\)?[-. ]?([0-9]{3,4})[-. ]?([0-9]{4})$/', '$1-$2-$3', $value);
} else {
return false;
}
}
}
}

View File

@@ -0,0 +1,83 @@
<?php
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014 - 2015, British Columbia Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author EllisLab Dev Team
* @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
* @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
* @license http://opensource.org/licenses/MIT MIT License
* @link http://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Pagination Class
*
* @package CodeIgniter
* @subpackage Libraries
* @category Pagination
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/libraries/pagination.html
*/
class MY_Pagination extends CI_Pagination
{
public $num_links = 5;
public $cur_page = 1;
public $use_page_numbers = true;
public $first_link = '<span aria-hidden="true">&laquo;</span>';
public $next_link = '<span aria-hidden="true">&gt;</span>';
public $prev_link = '<span aria-hidden="true">&lt;</span>';
public $last_link = '<span aria-hidden="true">&raquo;</span>';
public $first_tag_open = '<li>';
public $first_tag_close = '</li>';
public $last_tag_open = '<li>';
public $last_tag_close = '</li>';
public $cur_tag_open = '<li class="active"><a>';
public $cur_tag_close = '</a></li>';
public $next_tag_open = '<li>';
public $next_tag_close = '</li>';
public $prev_tag_open = '<li>';
public $prev_tag_close = '</li>';
public $full_tag_open = '<ul class="pagination">';
public $full_tag_close = '</ul>';
public $num_tag_open = '<li>';
public $num_tag_close = '</li>';
public $page_query_string = true;
public $query_string_segment = 'page';
/**
* Constructor
*/
function __construct()
{
parent::__construct();
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,252 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
#
# Portable PHP password hashing framework.
#
# Version 0.3 / genuine.
#
# Written by Solar Designer <solar at openwall.com> in 2004-2006 and placed in
# the public domain. Revised in subsequent years, still public domain.
#
# There's absolutely no warranty.
#
# The homepage URL for this framework is:
#
# http://www.openwall.com/phpass/
#
# Please be sure to update the Version line if you edit this file in any way.
# It is suggested that you leave the main version number intact, but indicate
# your project name (after the slash) and add your own revision information.
#
# Please do not change the "private" password hashing method implemented in
# here, thereby making your hashes incompatible. However, if you must, please
# change the hash type identifier (the "$P$") to something different.
#
# Obviously, since this code is in the public domain, the above are not
# requirements (there can be none), but merely suggestions.
#
class PasswordHash {
var $itoa64;
var $iteration_count_log2=8;
var $portable_hashes= FALSE;
var $random_state;
function PasswordHash()
{
$this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$this->iteration_count_log2 = 8;
$this->portable_hashes = FALSE;
$this->random_state = microtime();
if (function_exists('getmypid'))
$this->random_state .= getmypid();
}
function get_random_bytes($count)
{
$output = '';
if (is_readable('/dev/urandom') &&
($fh = @fopen('/dev/urandom', 'rb'))) {
$output = fread($fh, $count);
fclose($fh);
}
if (strlen($output) < $count) {
$output = '';
for ($i = 0; $i < $count; $i += 16) {
$this->random_state =
md5(microtime() . $this->random_state);
$output .=
pack('H*', md5($this->random_state));
}
$output = substr($output, 0, $count);
}
return $output;
}
function encode64($input, $count)
{
$output = '';
$i = 0;
do {
$value = ord($input[$i++]);
$output .= $this->itoa64[$value & 0x3f];
if ($i < $count)
$value |= ord($input[$i]) << 8;
$output .= $this->itoa64[($value >> 6) & 0x3f];
if ($i++ >= $count)
break;
if ($i < $count)
$value |= ord($input[$i]) << 16;
$output .= $this->itoa64[($value >> 12) & 0x3f];
if ($i++ >= $count)
break;
$output .= $this->itoa64[($value >> 18) & 0x3f];
} while ($i < $count);
return $output;
}
function gensalt_private($input)
{
$output = '$P$';
$output .= $this->itoa64[min($this->iteration_count_log2 +
((PHP_VERSION >= '5') ? 5 : 3), 30)];
$output .= $this->encode64($input, 6);
return $output;
}
function crypt_private($password, $setting)
{
$output = '*0';
if (substr($setting, 0, 2) == $output)
$output = '*1';
$id = substr($setting, 0, 3);
# We use "$P$", phpBB3 uses "$H$" for the same thing
if ($id != '$P$' && $id != '$H$')
return $output;
$count_log2 = strpos($this->itoa64, $setting[3]);
if ($count_log2 < 7 || $count_log2 > 30)
return $output;
$count = 1 << $count_log2;
$salt = substr($setting, 4, 8);
if (strlen($salt) != 8)
return $output;
# We're kind of forced to use MD5 here since it's the only
# cryptographic primitive available in all versions of PHP
# currently in use. To implement our own low-level crypto
# in PHP would result in much worse performance and
# consequently in lower iteration counts and hashes that are
# quicker to crack (by non-PHP code).
if (PHP_VERSION >= '5') {
$hash = md5($salt . $password, TRUE);
do {
$hash = md5($hash . $password, TRUE);
} while (--$count);
} else {
$hash = pack('H*', md5($salt . $password));
do {
$hash = pack('H*', md5($hash . $password));
} while (--$count);
}
$output = substr($setting, 0, 12);
$output .= $this->encode64($hash, 16);
return $output;
}
function gensalt_extended($input)
{
$count_log2 = min($this->iteration_count_log2 + 8, 24);
# This should be odd to not reveal weak DES keys, and the
# maximum valid value is (2**24 - 1) which is odd anyway.
$count = (1 << $count_log2) - 1;
$output = '_';
$output .= $this->itoa64[$count & 0x3f];
$output .= $this->itoa64[($count >> 6) & 0x3f];
$output .= $this->itoa64[($count >> 12) & 0x3f];
$output .= $this->itoa64[($count >> 18) & 0x3f];
$output .= $this->encode64($input, 3);
return $output;
}
function gensalt_blowfish($input)
{
# This one needs to use a different order of characters and a
# different encoding scheme from the one in encode64() above.
# We care because the last character in our encoded string will
# only represent 2 bits. While two known implementations of
# bcrypt will happily accept and correct a salt string which
# has the 4 unused bits set to non-zero, we do not want to take
# chances and we also do not want to waste an additional byte
# of entropy.
$itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$output = '$2a$';
$output .= chr(ord('0') + $this->iteration_count_log2 / 10);
$output .= chr(ord('0') + $this->iteration_count_log2 % 10);
$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;
}
function HashPassword($password)
{
$random = '';
if (CRYPT_BLOWFISH == 1 && !$this->portable_hashes) {
$random = $this->get_random_bytes(16);
$hash =
crypt($password, $this->gensalt_blowfish($random));
if (strlen($hash) == 60)
return $hash;
}
if (CRYPT_EXT_DES == 1 && !$this->portable_hashes) {
if (strlen($random) < 3)
$random = $this->get_random_bytes(3);
$hash =
crypt($password, $this->gensalt_extended($random));
if (strlen($hash) == 20)
return $hash;
}
if (strlen($random) < 6)
$random = $this->get_random_bytes(6);
$hash =
$this->crypt_private($password,
$this->gensalt_private($random));
if (strlen($hash) == 34)
return $hash;
# Returning '*' on error is safe here, but would _not_ be safe
# in a crypt(3)-like function used _both_ for generating new
# hashes and for validating passwords against existing hashes.
return '*';
}
function CheckPassword($password, $stored_hash)
{
$hash = $this->crypt_private($password, $stored_hash);
if ($hash[0] == '*')
$hash = crypt($password, $stored_hash);
return $hash == $stored_hash;
}
}

View File

@@ -0,0 +1,196 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Simple PHP User agent
*
* @link http://github.com/ornicar/php-user-agent
* @version 1.0
* @author Thibault Duplessis <thibault.duplessis at gmail dot com>
* @license MIT License
*
* Documentation: http://github.com/ornicar/php-user-agent/blob/master/README.markdown
* Tickets: http://github.com/ornicar/php-user-agent/issues
*/
class Phpuseragent
{
protected $userAgentString;
protected $browserName;
protected $browserVersion;
protected $operatingSystem;
protected $engine;
public function __construct($userAgentString = null, Phpuseragentstringparser $userAgentStringParser = null)
{
$this->configureFromUserAgentString($userAgentString, $userAgentStringParser);
}
/**
* Get the browser name
*
* @return string the browser name
*/
public function getBrowserName()
{
return $this->browserName;
}
/**
* Set the browser name
*
* @param string $name the browser name
*/
public function setBrowserName($name)
{
$this->browserName = $name;
}
/**
* Get the browser version
*
* @return string the browser version
*/
public function getBrowserVersion()
{
return $this->browserVersion;
}
/**
* Set the browser version
*
* @param string $version the browser version
*/
public function setBrowserVersion($version)
{
$this->browserVersion = $version;
}
/**
* Get the operating system name
*
* @return string the operating system name
*/
public function getOperatingSystem()
{
return $this->operatingSystem;
}
/**
* Set the operating system name
*
* @param string $operatingSystem the operating system name
*/
public function setOperatingSystem($operatingSystem)
{
$this->operatingSystem = $operatingSystem;
}
/**
* Get the engine name
*
* @return string the engine name
*/
public function getEngine()
{
return $this->engine;
}
/**
* Set the engine name
*
* @param string $operatingSystem the engine name
*/
public function setEngine($engine)
{
$this->engine = $engine;
}
/**
* Get the user agent string
*
* @return string the user agent string
*/
public function getUserAgentString()
{
return $this->userAgentString;
}
/**
* Set the user agent string
*
* @param string $userAgentString the user agent string
*/
public function setUserAgentString($userAgentString)
{
$this->userAgentString = $userAgentString;
}
/**
* Tell whether this user agent is unknown or not
*
* @return boolean true if this user agent is unknown, false otherwise
*/
public function isUnknown()
{
return empty($this->browserName);
}
/**
* @return string combined browser name and version
*/
public function getFullName()
{
return $this->getBrowserName().' '.$this->getBrowserVersion();
}
public function __toString()
{
return $this->getFullName();
}
/**
* Configure the user agent from a user agent string
* @param string $userAgentString the user agent string
* @param Phpuseragentstringparser $userAgentStringParser the parser used to parse the string
*/
public function configureFromUserAgentString($userAgentString, Phpuseragentstringparser $userAgentStringParser = null)
{
if (null === $userAgentStringParser)
{
$userAgentStringParser = new Phpuseragentstringparser();
}
$this->setUserAgentString($userAgentString);
$this->fromArray($userAgentStringParser->parse($userAgentString));
}
/**
* Convert the user agent to a data array
*
* @return array data
*/
public function toArray()
{
return array(
'browser_name' => $this->getBrowserName(),
'browser_version' => $this->getBrowserVersion(),
'operating_system' => $this->getOperatingSystem()
);
}
/**
* Configure the user agent from a data array
*
* @param array $data
*/
public function fromArray(array $data)
{
$this->setBrowserName($data['browser_name']);
$this->setBrowserVersion($data['browser_version']);
$this->setOperatingSystem($data['operating_system']);
$this->setEngine($data['engine']);
}
}

View File

@@ -0,0 +1,323 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Simple PHP User Agent string parser
*/
class Phpuseragentstringparser
{
/**
* Parse a user agent string.
*
* @param string $userAgentString defaults to $_SERVER['HTTP_USER_AGENT'] if empty
* @return array ( the user agent informations
* 'browser_name' => 'firefox',
* 'browser_version' => '3.6',
* 'operating_system' => 'linux'
* )
*/
public function parse($userAgentString = null)
{
// use current user agent string as default
if (!$userAgentString)
{
$userAgentString = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null;
}
// parse quickly (with medium accuracy)
$informations = $this->doParse($userAgentString);
// run some filters to increase accuracy
foreach ($this->getFilters() as $filter)
{
$this->$filter($informations);
}
return $informations;
}
/**
* Detect quickly informations from the user agent string
*
* @param string $userAgentString user agent string
* @return array user agent informations array
*/
protected function doParse($userAgentString)
{
$userAgent = array(
'string' => $this->cleanUserAgentString($userAgentString),
'browser_name' => null,
'browser_version' => null,
'operating_system' => null,
'engine' => null
);
if (empty($userAgent['string']))
{
return $userAgent;
}
// build regex that matches phrases for known browsers
// (e.g. "Firefox/2.0" or "MSIE 6.0" (This only matches the major and minor
// version numbers. E.g. "2.0.0.6" is parsed as simply "2.0"
$pattern = '#('.join('|', $this->getKnownBrowsers()).')[/ ]+([0-9]+(?:\.[0-9]+)?)#';
// Find all phrases (or return empty array if none found)
if (preg_match_all($pattern, $userAgent['string'], $matches))
{
// Since some UAs have more than one phrase (e.g Firefox has a Gecko phrase,
// Opera 7,8 have a MSIE phrase), use the last one found (the right-most one
// in the UA). That's usually the most correct.
$i = count($matches[1])-1;
if (isset($matches[1][$i]))
{
$userAgent['browser_name'] = $matches[1][$i];
}
if (isset($matches[2][$i]))
{
$userAgent['browser_version'] = $matches[2][$i];
}
}
// Find operating system
$pattern = '#'.join('|', $this->getKnownOperatingSystems()).'#';
if (preg_match($pattern, $userAgent['string'], $match))
{
if (isset($match[0]))
{
$userAgent['operating_system'] = $match[0];
}
}
// Find engine
$pattern = '#'.join('|', $this->getKnownEngines()).'#';
if (preg_match($pattern, $userAgent['string'], $match))
{
if (isset($match[0]))
{
$userAgent['engine'] = $match[0];
}
}
return $userAgent;
}
/**
* Make user agent string lowercase, and replace browser aliases
*
* @param string $userAgentString the dirty user agent string
* @return string the clean user agent string
*/
public function cleanUserAgentString($userAgentString)
{
// clean up the string
$userAgentString = trim(strtolower($userAgentString));
// replace browser names with their aliases
$userAgentString = strtr($userAgentString, $this->getKnownBrowserAliases());
// replace operating system names with their aliases
$userAgentString = strtr($userAgentString, $this->getKnownOperatingSystemAliases());
// replace engine names with their aliases
$userAgentString = strtr($userAgentString, $this->getKnownEngineAliases());
return $userAgentString;
}
/**
* Get the list of filters that get called when parsing a user agent
*
* @return array list of valid callables
*/
public function getFilters()
{
return array(
'filterAndroid',
'filterGoogleChrome',
'filterSafariVersion',
'filterOperaVersion',
'filterYahoo',
'filterMsie',
);
}
/**
* Add a filter to be called when parsing a user agent
*
* @param string $filter name of the filter method
*/
public function addFilter($filter)
{
$this->filters += $filter;
}
/**
* Get known browsers
*
* @return array the browsers
*/
protected function getKnownBrowsers()
{
return array(
'msie',
'firefox',
'safari',
'webkit',
'opera',
'netscape',
'konqueror',
'gecko',
'chrome',
'googlebot',
'iphone',
'msnbot',
'applewebkit'
);
}
/**
* Get known browser aliases
*
* @return array the browser aliases
*/
protected function getKnownBrowserAliases()
{
return array(
'shiretoko' => 'firefox',
'namoroka' => 'firefox',
'shredder' => 'firefox',
'minefield' => 'firefox',
'granparadiso' => 'firefox'
);
}
/**
* Get known operating system
*
* @return array the operating systems
*/
protected function getKnownOperatingSystems()
{
return array(
'windows',
'macintosh',
'linux',
'freebsd',
'unix',
'iphone'
);
}
/**
* Get known operating system aliases
*
* @return array the operating system aliases
*/
protected function getKnownOperatingSystemAliases()
{
return array();
}
/**
* Get known engines
*
* @return array the engines
*/
protected function getKnownEngines()
{
return array(
'gecko',
'webkit',
'trident',
'presto'
);
}
/**
* Get known engines aliases
*
* @return array the engines aliases
*/
protected function getKnownEngineAliases()
{
return array();
}
/**
* Filters
*/
/**
* Google chrome has a safari like signature
*/
protected function filterGoogleChrome(array &$userAgent)
{
if ('safari' === $userAgent['browser_name'] && strpos($userAgent['string'], 'chrome/'))
{
$userAgent['browser_name'] = 'chrome';
$userAgent['browser_version'] = preg_replace('|.+chrome/([0-9]+(?:\.[0-9]+)?).+|', '$1', $userAgent['string']);
}
}
/**
* Safari version is not encoded "normally"
*/
protected function filterSafariVersion(array &$userAgent)
{
if ('safari' === $userAgent['browser_name'] && strpos($userAgent['string'], ' version/'))
{
$userAgent['browser_version'] = preg_replace('|.+\sversion/([0-9]+(?:\.[0-9]+)?).+|', '$1', $userAgent['string']);
}
}
/**
* Opera 10.00 (and higher) version number is located at the end
*/
protected function filterOperaVersion(array &$userAgent)
{
if ('opera' === $userAgent['browser_name'] && strpos($userAgent['string'], ' version/'))
{
$userAgent['browser_version'] = preg_replace('|.+\sversion/([0-9]+\.[0-9]+)\s*.*|', '$1', $userAgent['string']);
}
}
/**
* Yahoo bot has a special user agent string
*/
protected function filterYahoo(array &$userAgent)
{
if (null === $userAgent['browser_name'] && strpos($userAgent['string'], 'yahoo! slurp'))
{
$userAgent['browser_name'] = 'yahoobot';
}
}
/**
* MSIE does not always declare its engine
*/
protected function filterMsie(array &$userAgent)
{
if ('msie' === $userAgent['browser_name'] && empty($userAgent['engine']))
{
$userAgent['engine'] = 'trident';
}
}
/**
* Android has a safari like signature
*/
protected function filterAndroid(array &$userAgent) {
if ('safari' === $userAgent['browser_name'] && strpos($userAgent['string'], 'android ')) {
$userAgent['browser_name'] = 'android';
$userAgent['operating_system'] = 'android';
$userAgent['browser_version'] = preg_replace('|.+android ([0-9]+(?:\.[0-9]+)+).+|', '$1', $userAgent['string']);
}
}
}

View File

@@ -0,0 +1,62 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
// 검색 파라미터
class Querystring
{
private $CI;
public function __construct()
{
$this->CI =& get_instance();
}
// 전체 주소
public function output()
{
return $this->CI->input->server('QUERY_STRING', null, '');
}
// 쿼리스트링 수정
public function replace($key = '', $val = '', $query_string = '')
{
if ( ! $key) {
return false;
}
$query_string = $query_string ? $query_string : $this->CI->input->server('QUERY_STRING', null, '');
parse_str($query_string, $qr);
// remove from query string
if ($key) {
if ($val) {
$qr[$key] = $val;
} else {
unset($qr[$key]);
}
}
// return result
$return = '';
if (count($qr) > 0) {
$return = http_build_query($qr);
}
return $return;
}
// 필드 정렬
public function sort($findex, $forder = 'desc')
{
if ($this->CI->input->get('findex') === $findex) {
$param_qstr = $this->replace('forder', (strtolower($this->CI->input->get('forder')) === 'asc') ? 'desc' : 'asc');
} else {
$param_qstr = $this->replace('forder', '', $this->replace('findex', '')) . '&amp;findex=' . $findex . '&amp;forder=' . $forder;
}
return '?' . $param_qstr;
}
}

View File

@@ -0,0 +1,872 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
Copyright (c) 2010-2012 Ryan McCue and contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* Requests for PHP
*
* Inspired by Requests for Python.
*
* Based on concepts from SimplePie_File, RequestCore and WP_Http.
*
* @package Requests
*/
class Requests {
/**
* POST method
*
* @var string
*/
const POST = 'POST';
/**
* PUT method
*
* @var string
*/
const PUT = 'PUT';
/**
* GET method
*
* @var string
*/
const GET = 'GET';
/**
* HEAD method
*
* @var string
*/
const HEAD = 'HEAD';
/**
* DELETE method
*
* @var string
*/
const DELETE = 'DELETE';
/**
* PATCH method
*
* @link http://tools.ietf.org/html/rfc5789
* @var string
*/
const PATCH = 'PATCH';
/**
* Current version of Requests
*
* @var string
*/
const VERSION = '1.6';
/**
* Registered transport classes
*
* @var array
*/
protected static $transports = array();
/**
* Selected transport name
*
* Use {@see get_transport()} instead
*
* @var string|null
*/
public static $transport = null;
/**
* This is a static class, do not instantiate it
*
* @codeCoverageIgnore
*/
public function __construct() {}
/**
* Autoloader for Requests
*
* Register this with {@see register_autoloader()} if you'd like to avoid
* having to create your own.
*
* (You can also use `spl_autoload_register` directly if you'd prefer.)
*
* @codeCoverageIgnore
*
* @param string $class Class name to load
*/
public static function autoloader($class) {
// Check that the class starts with "Requests"
if (strpos($class, 'Requests') !== 0) {
return;
}
$file = str_replace('_', '/', $class);
if (file_exists(dirname(__FILE__) . '/' . $file . '.php')) {
require_once(dirname(__FILE__) . '/' . $file . '.php');
}
}
/**
* Register the built-in autoloader
*
* @codeCoverageIgnore
*/
public static function register_autoloader() {
spl_autoload_register(array('Requests', 'autoloader'));
}
/**
* Register a transport
*
* @param string $transport Transport class to add, must support the Requests_Transport interface
*/
public static function add_transport($transport) {
if (empty(self::$transports)) {
self::$transports = array(
'Requests_Transport_cURL',
'Requests_Transport_fsockopen',
);
}
self::$transports = array_merge(self::$transports, array($transport));
}
/**
* Get a working transport
*
* @throws Requests_Exception If no valid transport is found (`notransport`)
* @return Requests_Transport
*/
protected static function get_transport() {
// Caching code, don't bother testing coverage
// @codeCoverageIgnoreStart
if (self::$transport !== null) {
return new self::$transport();
}
// @codeCoverageIgnoreEnd
if (empty(self::$transports)) {
self::$transports = array(
'Requests_Transport_cURL',
'Requests_Transport_fsockopen',
);
}
// Find us a working transport
foreach (self::$transports as $class) {
if (!class_exists($class))
continue;
$result = call_user_func(array($class, 'test'));
if ($result) {
self::$transport = $class;
break;
}
}
if (self::$transport === null) {
throw new Requests_Exception('No working transports found', 'notransport', self::$transports);
}
return new self::$transport();
}
/**#@+
* @see request()
* @param string $url
* @param array $headers
* @param array $options
* @return Requests_Response
*/
/**
* Send a GET request
*/
public static function get($url, $headers = array(), $options = array()) {
return self::request($url, $headers, null, self::GET, $options);
}
/**
* Send a HEAD request
*/
public static function head($url, $headers = array(), $options = array()) {
return self::request($url, $headers, null, self::HEAD, $options);
}
/**
* Send a DELETE request
*/
public static function delete($url, $headers = array(), $options = array()) {
return self::request($url, $headers, null, self::DELETE, $options);
}
/**#@-*/
/**#@+
* @see request()
* @param string $url
* @param array $headers
* @param array $data
* @param array $options
* @return Requests_Response
*/
/**
* Send a POST request
*/
public static function post($url, $headers = array(), $data = array(), $options = array()) {
return self::request($url, $headers, $data, self::POST, $options);
}
/**
* Send a PUT request
*/
public static function put($url, $headers = array(), $data = array(), $options = array()) {
return self::request($url, $headers, $data, self::PUT, $options);
}
/**
* Send a PATCH request
*
* Note: Unlike {@see post} and {@see put}, `$headers` is required, as the
* specification recommends that should send an ETag
*
* @link http://tools.ietf.org/html/rfc5789
*/
public static function patch($url, $headers, $data = array(), $options = array()) {
return self::request($url, $headers, $data, self::PATCH, $options);
}
/**#@-*/
/**
* Main interface for HTTP requests
*
* This method initiates a request and sends it via a transport before
* parsing.
*
* The `$options` parameter takes an associative array with the following
* options:
*
* - `timeout`: How long should we wait for a response?
* (integer, seconds, default: 10)
* - `useragent`: Useragent to send to the server
* (string, default: php-requests/$version)
* - `follow_redirects`: Should we follow 3xx redirects?
* (boolean, default: true)
* - `redirects`: How many times should we redirect before erroring?
* (integer, default: 10)
* - `blocking`: Should we block processing on this request?
* (boolean, default: true)
* - `filename`: File to stream the body to instead.
* (string|boolean, default: false)
* - `auth`: Authentication handler or array of user/password details to use
* for Basic authentication
* (Requests_Auth|array|boolean, default: false)
* - `proxy`: Proxy details to use for proxy by-passing and authentication
* (Requests_Proxy|array|boolean, default: false)
* - `idn`: Enable IDN parsing
* (boolean, default: true)
* - `transport`: Custom transport. Either a class name, or a
* transport object. Defaults to the first working transport from
* {@see getTransport()}
* (string|Requests_Transport, default: {@see getTransport()})
* - `hooks`: Hooks handler.
* (Requests_Hooker, default: new Requests_Hooks())
* - `verify`: Should we verify SSL certificates? Allows passing in a custom
* certificate file as a string. (Using true uses the system-wide root
* certificate store instead, but this may have different behaviour
* across transports.)
* (string|boolean, default: library/Requests/Transport/cacert.pem)
* - `verifyname`: Should we verify the common name in the SSL certificate?
* (boolean: default, true)
*
* @throws Requests_Exception On invalid URLs (`nonhttp`)
*
* @param string $url URL to request
* @param array $headers Extra headers to send with the request
* @param array $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests
* @param string $type HTTP request type (use Requests constants)
* @param array $options Options for the request (see description for more information)
* @return Requests_Response
*/
public static function request($url, $headers = array(), $data = array(), $type = self::GET, $options = array()) {
if (empty($options['type'])) {
$options['type'] = $type;
}
$options = array_merge(self::get_default_options(), $options);
self::set_defaults($url, $headers, $data, $type, $options);
$options['hooks']->dispatch('requests.before_request', array(&$url, &$headers, &$data, &$type, &$options));
if (!empty($options['transport'])) {
$transport = $options['transport'];
if (is_string($options['transport'])) {
$transport = new $transport();
}
}
else {
$transport = self::get_transport();
}
$response = $transport->request($url, $headers, $data, $options);
$options['hooks']->dispatch('requests.before_parse', array(&$response, $url, $headers, $data, $type, $options));
return self::parse_response($response, $url, $headers, $data, $options);
}
/**
* Send multiple HTTP requests simultaneously
*
* The `$requests` parameter takes an associative or indexed array of
* request fields. The key of each request can be used to match up the
* request with the returned data, or with the request passed into your
* `multiple.request.complete` callback.
*
* The request fields value is an associative array with the following keys:
*
* - `url`: Request URL Same as the `$url` parameter to
* {@see Requests::request}
* (string, required)
* - `headers`: Associative array of header fields. Same as the `$headers`
* parameter to {@see Requests::request}
* (array, default: `array()`)
* - `data`: Associative array of data fields or a string. Same as the
* `$data` parameter to {@see Requests::request}
* (array|string, default: `array()`)
* - `type`: HTTP request type (use Requests constants). Same as the `$type`
* parameter to {@see Requests::request}
* (string, default: `Requests::GET`)
* - `data`: Associative array of options. Same as the `$options` parameter
* to {@see Requests::request}
* (array, default: see {@see Requests::request})
* - `cookies`: Associative array of cookie name to value, or cookie jar.
* (array|Requests_Cookie_Jar)
*
* If the `$options` parameter is specified, individual requests will
* inherit options from it. This can be used to use a single hooking system,
* or set all the types to `Requests::POST`, for example.
*
* In addition, the `$options` parameter takes the following global options:
*
* - `complete`: A callback for when a request is complete. Takes two
* parameters, a Requests_Response/Requests_Exception reference, and the
* ID from the request array (Note: this can also be overridden on a
* per-request basis, although that's a little silly)
* (callback)
*
* @param array $requests Requests data (see description for more information)
* @param array $options Global and default options (see {@see Requests::request})
* @return array Responses (either Requests_Response or a Requests_Exception object)
*/
public static function request_multiple($requests, $options = array()) {
$options = array_merge(self::get_default_options(true), $options);
if (!empty($options['hooks'])) {
$options['hooks']->register('transport.internal.parse_response', array('Requests', 'parse_multiple'));
if (!empty($options['complete'])) {
$options['hooks']->register('multiple.request.complete', $options['complete']);
}
}
foreach ($requests as $id => &$request) {
if (!isset($request['headers'])) {
$request['headers'] = array();
}
if (!isset($request['data'])) {
$request['data'] = array();
}
if (!isset($request['type'])) {
$request['type'] = self::GET;
}
if (!isset($request['options'])) {
$request['options'] = $options;
$request['options']['type'] = $request['type'];
}
else {
if (empty($request['options']['type'])) {
$request['options']['type'] = $request['type'];
}
$request['options'] = array_merge($options, $request['options']);
}
self::set_defaults($request['url'], $request['headers'], $request['data'], $request['type'], $request['options']);
// Ensure we only hook in once
if ($request['options']['hooks'] !== $options['hooks']) {
$request['options']['hooks']->register('transport.internal.parse_response', array('Requests', 'parse_multiple'));
if (!empty($request['options']['complete'])) {
$request['options']['hooks']->register('multiple.request.complete', $request['options']['complete']);
}
}
}
unset($request);
if (!empty($options['transport'])) {
$transport = $options['transport'];
if (is_string($options['transport'])) {
$transport = new $transport();
}
}
else {
$transport = self::get_transport();
}
$responses = $transport->request_multiple($requests, $options);
foreach ($responses as $id => &$response) {
// If our hook got messed with somehow, ensure we end up with the
// correct response
if (is_string($response)) {
$request = $requests[$id];
self::parse_multiple($response, $request);
$request['options']['hooks']->dispatch('multiple.request.complete', array(&$response, $id));
}
}
return $responses;
}
/**
* Get the default options
*
* @see Requests::request() for values returned by this method
* @param boolean $multirequest Is this a multirequest?
* @return array Default option values
*/
protected static function get_default_options($multirequest = false) {
$defaults = array(
'timeout' => 10,
'useragent' => 'php-requests/' . self::VERSION,
'redirected' => 0,
'redirects' => 10,
'follow_redirects' => true,
'blocking' => true,
'type' => self::GET,
'filename' => false,
'auth' => false,
'proxy' => false,
'cookies' => false,
'idn' => true,
'hooks' => null,
'transport' => null,
'verify' => dirname( __FILE__ ) . '/Requests/Transport/cacert.pem',
'verifyname' => true,
);
if ($multirequest !== false) {
$defaults['complete'] = null;
}
return $defaults;
}
/**
* Set the default values
*
* @param string $url URL to request
* @param array $headers Extra headers to send with the request
* @param array $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests
* @param string $type HTTP request type
* @param array $options Options for the request
* @return array $options
*/
protected static function set_defaults(&$url, &$headers, &$data, &$type, &$options) {
if (!preg_match('/^http(s)?:\/\//i', $url)) {
throw new Requests_Exception('Only HTTP requests are handled.', 'nonhttp', $url);
}
if (empty($options['hooks'])) {
$options['hooks'] = new Requests_Hooks();
}
if (is_array($options['auth'])) {
$options['auth'] = new Requests_Auth_Basic($options['auth']);
}
if ($options['auth'] !== false) {
$options['auth']->register($options['hooks']);
}
if (!empty($options['proxy'])) {
$options['proxy'] = new Requests_Proxy_HTTP($options['proxy']);
}
if ($options['proxy'] !== false) {
$options['proxy']->register($options['hooks']);
}
if (is_array($options['cookies'])) {
$options['cookies'] = new Requests_Cookie_Jar($options['cookies']);
}
elseif (empty($options['cookies'])) {
$options['cookies'] = new Requests_Cookie_Jar();
}
if ($options['cookies'] !== false) {
$options['cookies']->register($options['hooks']);
}
if ($options['idn'] !== false) {
$iri = new Requests_IRI($url);
$iri->host = Requests_IDNAEncoder::encode($iri->ihost);
$url = $iri->uri;
}
}
/**
* HTTP response parser
*
* @throws Requests_Exception On missing head/body separator (`requests.no_crlf_separator`)
* @throws Requests_Exception On missing head/body separator (`noversion`)
* @throws Requests_Exception On missing head/body separator (`toomanyredirects`)
*
* @param string $headers Full response text including headers and body
* @param string $url Original request URL
* @param array $req_headers Original $headers array passed to {@link request()}, in case we need to follow redirects
* @param array $req_data Original $data array passed to {@link request()}, in case we need to follow redirects
* @param array $options Original $options array passed to {@link request()}, in case we need to follow redirects
* @return Requests_Response
*/
protected static function parse_response($headers, $url, $req_headers, $req_data, $options) {
$return = new Requests_Response();
if (!$options['blocking']) {
return $return;
}
$return->raw = $headers;
$return->url = $url;
if (!$options['filename']) {
if (($pos = strpos($headers, "\r\n\r\n")) === false) {
// Crap!
throw new Requests_Exception('Missing header/body separator', 'requests.no_crlf_separator');
}
$headers = substr($return->raw, 0, $pos);
$return->body = substr($return->raw, $pos + strlen("\n\r\n\r"));
}
else {
$return->body = '';
}
// Pretend CRLF = LF for compatibility (RFC 2616, section 19.3)
$headers = str_replace("\r\n", "\n", $headers);
// Unfold headers (replace [CRLF] 1*( SP | HT ) with SP) as per RFC 2616 (section 2.2)
$headers = preg_replace('/\n[ \t]/', ' ', $headers);
$headers = explode("\n", $headers);
preg_match('#^HTTP/1\.\d[ \t]+(\d+)#i', array_shift($headers), $matches);
if (empty($matches)) {
throw new Requests_Exception('Response could not be parsed', 'noversion', $headers);
}
$return->status_code = (int) $matches[1];
if ($return->status_code >= 200 && $return->status_code < 300) {
$return->success = true;
}
foreach ($headers as $header) {
list($key, $value) = explode(':', $header, 2);
$value = trim($value);
preg_replace('#(\s+)#i', ' ', $value);
$return->headers[$key] = $value;
}
if (isset($return->headers['transfer-encoding'])) {
$return->body = self::decode_chunked($return->body);
unset($return->headers['transfer-encoding']);
}
if (isset($return->headers['content-encoding'])) {
$return->body = self::decompress($return->body);
}
//fsockopen and cURL compatibility
if (isset($return->headers['connection'])) {
unset($return->headers['connection']);
}
$options['hooks']->dispatch('requests.before_redirect_check', array(&$return, $req_headers, $req_data, $options));
if ((in_array($return->status_code, array(300, 301, 302, 303, 307)) || $return->status_code > 307 && $return->status_code < 400) && $options['follow_redirects'] === true) {
if (isset($return->headers['location']) && $options['redirected'] < $options['redirects']) {
if ($return->status_code === 303) {
$options['type'] = Requests::GET;
}
$options['redirected']++;
$location = $return->headers['location'];
if (strpos ($location, '/') === 0) {
// relative redirect, for compatibility make it absolute
$location = Requests_IRI::absolutize($url, $location);
$location = $location->uri;
}
$redirected = self::request($location, $req_headers, $req_data, false, $options);
$redirected->history[] = $return;
return $redirected;
}
elseif ($options['redirected'] >= $options['redirects']) {
throw new Requests_Exception('Too many redirects', 'toomanyredirects', $return);
}
}
$return->redirects = $options['redirected'];
$options['hooks']->dispatch('requests.after_request', array(&$return, $req_headers, $req_data, $options));
return $return;
}
/**
* Callback for `transport.internal.parse_response`
*
* Internal use only. Converts a raw HTTP response to a Requests_Response
* while still executing a multiple request.
*
* @param string $headers Full response text including headers and body
* @param array $request Request data as passed into {@see Requests::request_multiple()}
* @return null `$response` is either set to a Requests_Response instance, or a Requests_Exception object
*/
public static function parse_multiple(&$response, $request) {
try {
$response = self::parse_response($response, $request['url'], $request['headers'], $request['data'], $request['options']);
}
catch (Requests_Exception $e) {
$response = $e;
}
}
/**
* Decoded a chunked body as per RFC 2616
*
* @see http://tools.ietf.org/html/rfc2616#section-3.6.1
* @param string $data Chunked body
* @return string Decoded body
*/
protected static function decode_chunked($data) {
if (!preg_match('/^([0-9a-f]+)[^\r\n]*\r\n/i', trim($data))) {
return $data;
}
$decoded = '';
$encoded = $data;
while (true) {
$is_chunked = (bool) preg_match('/^([0-9a-f]+)[^\r\n]*\r\n/i', $encoded, $matches );
if (!$is_chunked) {
// Looks like it's not chunked after all
return $data;
}
$length = hexdec(trim($matches[1]));
if ($length === 0) {
// Ignore trailer headers
return $decoded;
}
$chunk_length = strlen($matches[0]);
$decoded .= $part = substr($encoded, $chunk_length, $length);
$encoded = substr($encoded, $chunk_length + $length + 2);
if (trim($encoded) === '0' || empty($encoded)) {
return $decoded;
}
}
// We'll never actually get down here
// @codeCoverageIgnoreStart
}
// @codeCoverageIgnoreEnd
/**
* Convert a key => value array to a 'key: value' array for headers
*
* @param array $array Dictionary of header values
* @return array List of headers
*/
public static function flatten($array) {
$return = array();
foreach ($array as $key => $value) {
$return[] = "$key: $value";
}
return $return;
}
/**
* Convert a key => value array to a 'key: value' array for headers
*
* @deprecated Misspelling of {@see Requests::flatten}
* @param array $array Dictionary of header values
* @return array List of headers
*/
public static function flattern($array) {
return self::flatten($array);
}
/**
* Decompress an encoded body
*
* Implements gzip, compress and deflate. Guesses which it is by attempting
* to decode.
*
* @todo Make this smarter by defaulting to whatever the headers say first
* @param string $data Compressed data in one of the above formats
* @return string Decompressed string
*/
public static function decompress($data) {
if (substr($data, 0, 2) !== "\x1f\x8b" && substr($data, 0, 2) !== "\x78\x9c") {
// Not actually compressed. Probably cURL ruining this for us.
return $data;
}
if (function_exists('gzdecode') && ($decoded = @gzdecode($data)) !== false) {
return $decoded;
}
elseif (function_exists('gzinflate') && ($decoded = @gzinflate($data)) !== false) {
return $decoded;
}
elseif (($decoded = self::compatible_gzinflate($data)) !== false) {
return $decoded;
}
elseif (function_exists('gzuncompress') && ($decoded = @gzuncompress($data)) !== false) {
return $decoded;
}
return $data;
}
/**
* Decompression of deflated string while staying compatible with the majority of servers.
*
* Certain Servers will return deflated data with headers which PHP's gzinflate()
* function cannot handle out of the box. The following function has been created from
* various snippets on the gzinflate() PHP documentation.
*
* Warning: Magic numbers within. Due to the potential different formats that the compressed
* data may be returned in, some "magic offsets" are needed to ensure proper decompression
* takes place. For a simple progmatic way to determine the magic offset in use, see:
* http://core.trac.wordpress.org/ticket/18273
*
* @since 2.8.1
* @link http://core.trac.wordpress.org/ticket/18273
* @link http://au2.php.net/manual/en/function.gzinflate.php#70875
* @link http://au2.php.net/manual/en/function.gzinflate.php#77336
*
* @param string $gzData String to decompress.
* @return string|bool False on failure.
*/
public static function compatible_gzinflate($gzData) {
// Compressed data might contain a full zlib header, if so strip it for
// gzinflate()
if ( substr($gzData, 0, 3) == "\x1f\x8b\x08" ) {
$i = 10;
$flg = ord( substr($gzData, 3, 1) );
if ($flg > 0 ) {
if ($flg & 4 ) {
list($xlen) = unpack('v', substr($gzData, $i, 2) );
$i = $i + 2 + $xlen;
}
if ($flg & 8 )
$i = strpos($gzData, "\0", $i) + 1;
if ($flg & 16 )
$i = strpos($gzData, "\0", $i) + 1;
if ($flg & 2 )
$i = $i + 2;
}
$decompressed = self::compatible_gzinflate( substr($gzData, $i ) );
if ( false !== $decompressed ) {
return $decompressed;
}
}
// If the data is Huffman Encoded, we must first strip the leading 2
// byte Huffman marker for gzinflate()
// The response is Huffman coded by many compressors such as
// java.util.zip.Deflater, Rubys Zlib::Deflate, and .NET's
// System.IO.Compression.DeflateStream.
//
// See http://decompres.blogspot.com/ for a quick explanation of this
// data type
$huffman_encoded = false;
// low nibble of first byte should be 0x08
list( , $first_nibble ) = unpack('h', $gzData );
// First 2 bytes should be divisible by 0x1F
list( , $first_two_bytes ) = unpack('n', $gzData );
if ( 0x08 == $first_nibble && 0 == ($first_two_bytes % 0x1F ) )
$huffman_encoded = true;
if ($huffman_encoded ) {
if ( false !== ($decompressed = @gzinflate( substr($gzData, 2 ) ) ) )
return $decompressed;
}
if ( "\x50\x4b\x03\x04" == substr($gzData, 0, 4 ) ) {
// ZIP file format header
// Offset 6: 2 bytes, General-purpose field
// Offset 26: 2 bytes, filename length
// Offset 28: 2 bytes, optional field length
// Offset 30: Filename field, followed by optional field, followed
// immediately by data
list( , $general_purpose_flag ) = unpack('v', substr($gzData, 6, 2 ) );
// If the file has been compressed on the fly, 0x08 bit is set of
// the general purpose field. We can use this to differentiate
// between a compressed document, and a ZIP file
$zip_compressed_on_the_fly = ( 0x08 == (0x08 & $general_purpose_flag ) );
if ( ! $zip_compressed_on_the_fly ) {
// Don't attempt to decode a compressed zip file
return $gzData;
}
// Determine the first byte of data, based on the above ZIP header
// offsets:
$first_file_start = array_sum( unpack('v2', substr($gzData, 26, 4 ) ) );
if ( false !== ($decompressed = @gzinflate( substr($gzData, 30 + $first_file_start ) ) ) ) {
return $decompressed;
}
return false;
}
// Finally fall back to straight gzinflate
if ( false !== ($decompressed = @gzinflate($gzData ) ) ) {
return $decompressed;
}
// Fallback for all above failing, not expected, but included for
// debugging and preventing regressions and to track stats
if ( false !== ($decompressed = @gzinflate( substr($gzData, 2 ) ) ) ) {
return $decompressed;
}
return false;
}
public static function match_domain($host, $reference) {
// Check for a direct match
if ($host === $reference) {
return true;
}
// Calculate the valid wildcard match if the host is not an IP address
// Also validates that the host has 3 parts or more, as per Firefox's
// ruleset.
$parts = explode('.', $host);
if (ip2long($host) === false && count($parts) >= 3) {
$parts[0] = '*';
$wildcard = implode('.', $parts);
if ($wildcard === $reference) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,33 @@
<?php
/**
* Authentication provider interface
*
* @package Requests
* @subpackage Authentication
*/
/**
* Authentication provider interface
*
* Implement this interface to act as an authentication provider.
*
* Parameters should be passed via the constructor where possible, as this
* makes it much easier for users to use your provider.
*
* @see Requests_Hooks
* @package Requests
* @subpackage Authentication
*/
interface Requests_Auth {
/**
* Register hooks as needed
*
* This method is called in {@see Requests::request} when the user has set
* an instance as the 'auth' option. Use this callback to register all the
* hooks you'll need.
*
* @see Requests_Hooks::register
* @param Requests_Hooks $hooks Hook system
*/
public function register(Requests_Hooks &$hooks);
}

View File

@@ -0,0 +1,88 @@
<?php
/**
* Basic Authentication provider
*
* @package Requests
* @subpackage Authentication
*/
/**
* Basic Authentication provider
*
* Provides a handler for Basic HTTP authentication via the Authorization
* header.
*
* @package Requests
* @subpackage Authentication
*/
class Requests_Auth_Basic implements Requests_Auth {
/**
* Username
*
* @var string
*/
public $user;
/**
* Password
*
* @var string
*/
public $pass;
/**
* Constructor
*
* @throws Requests_Exception On incorrect number of arguments (`authbasicbadargs`)
* @param array|null $args Array of user and password. Must have exactly two elements
*/
public function __construct($args = null) {
if (is_array($args)) {
if (count($args) !== 2) {
throw new Requests_Exception('Invalid number of arguments', 'authbasicbadargs');
}
list($this->user, $this->pass) = $args;
}
}
/**
* Register the necessary callbacks
*
* @see curl_before_send
* @see fsockopen_header
* @param Requests_Hooks $hooks Hook system
*/
public function register(Requests_Hooks &$hooks) {
$hooks->register('curl.before_send', array(&$this, 'curl_before_send'));
$hooks->register('fsockopen.after_headers', array(&$this, 'fsockopen_header'));
}
/**
* Set cURL parameters before the data is sent
*
* @param resource $handle cURL resource
*/
public function curl_before_send(&$handle) {
curl_setopt($handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($handle, CURLOPT_USERPWD, $this->getAuthString());
}
/**
* Add extra headers to the request before sending
*
* @param string $out HTTP header string
*/
public function fsockopen_header(&$out) {
$out .= "Authorization: Basic " . base64_encode($this->getAuthString()) . "\r\n";
}
/**
* Get the authentication string (user:pass)
*
* @return string
*/
public function getAuthString() {
return $this->user . ':' . $this->pass;
}
}

View File

@@ -0,0 +1,171 @@
<?php
/**
* Cookie storage object
*
* @package Requests
* @subpackage Cookies
*/
/**
* Cookie storage object
*
* @package Requests
* @subpackage Cookies
*/
class Requests_Cookie {
/**
*
* @var string
*/
public $name;
/**
* @var string
*/
public $value;
/**
* Cookie attributes
*
* Valid keys are (currently) path, domain, expires, max-age, secure and
* httponly.
*
* @var array
*/
public $attributes = array();
/**
* Create a new cookie object
*
* @param string $name
* @param string $value
* @param array $attributes Associative array of attribute data
*/
public function __construct($name, $value, $attributes = array()) {
$this->name = $name;
$this->value = $value;
$this->attributes = $attributes;
}
/**
* Format a cookie for a Cookie header
*
* This is used when sending cookies to a server.
*
* @return string Cookie formatted for Cookie header
*/
public function formatForHeader() {
return sprintf('%s=%s', $this->name, $this->value);
}
/**
* Format a cookie for a Set-Cookie header
*
* This is used when sending cookies to clients. This isn't really
* applicable to client-side usage, but might be handy for debugging.
*
* @return string Cookie formatted for Set-Cookie header
*/
public function formatForSetCookie() {
$header_value = $this->formatForHeader();
if (!empty($this->attributes)) {
$parts = array();
foreach ($this->attributes as $key => $value) {
// Ignore non-associative attributes
if (is_numeric($key)) {
$parts[] = $value;
}
else {
$parts[] = sprintf('%s=%s', $key, $value);
}
}
$header_value .= '; ' . implode('; ', $parts);
}
return $header_value;
}
/**
* Get the cookie value
*
* Attributes and other data can be accessed via methods.
*/
public function __toString() {
return $this->value;
}
/**
* Parse a cookie string into a cookie object
*
* Based on Mozilla's parsing code in Firefox and related projects, which
* is an intentional deviation from RFC 2109 and RFC 2616. RFC 6265
* specifies some of this handling, but not in a thorough manner.
*
* @param string Cookie header value (from a Set-Cookie header)
* @return Requests_Cookie Parsed cookie object
*/
public static function parse($string, $name = '') {
$parts = explode(';', $string);
$kvparts = array_shift($parts);
if (!empty($name)) {
$value = $string;
}
elseif (strpos($kvparts, '=') === false) {
// Some sites might only have a value without the equals separator.
// Deviate from RFC 6265 and pretend it was actually a blank name
// (`=foo`)
//
// https://bugzilla.mozilla.org/show_bug.cgi?id=169091
$name = '';
$value = $kvparts;
}
else {
list($name, $value) = explode('=', $kvparts, 2);
}
$name = trim($name);
$value = trim($value);
// Attribute key are handled case-insensitively
$attributes = new Requests_Utility_CaseInsensitiveDictionary();
if (!empty($parts)) {
foreach ($parts as $part) {
if (strpos($part, '=') === false) {
$part_key = $part;
$part_value = true;
}
else {
list($part_key, $part_value) = explode('=', $part, 2);
$part_value = trim($part_value);
}
$part_key = trim($part_key);
$attributes[$part_key] = $part_value;
}
}
return new Requests_Cookie($name, $value, $attributes);
}
/**
* Parse all Set-Cookie headers from request headers
*
* @param Requests_Response_Headers $headers
* @return array
*/
public static function parseFromHeaders(Requests_Response_Headers $headers) {
$cookie_headers = $headers->getValues('Set-Cookie');
if (empty($cookie_headers)) {
return array();
}
$cookies = array();
foreach ($cookie_headers as $header) {
$parsed = self::parse($header);
$cookies[$parsed->name] = $parsed;
}
return $cookies;
}
}

View File

@@ -0,0 +1,146 @@
<?php
/**
* Cookie holder object
*
* @package Requests
* @subpackage Cookies
*/
/**
* Cookie holder object
*
* @package Requests
* @subpackage Cookies
*/
class Requests_Cookie_Jar implements ArrayAccess, IteratorAggregate {
/**
* Actual item data
*
* @var array
*/
protected $cookies = array();
/**
* Create a new jar
*
* @param array $cookies Existing cookie values
*/
public function __construct($cookies = array()) {
$this->cookies = $cookies;
}
/**
* Normalise cookie data into a Requests_Cookie
*
* @param string|Requests_Cookie $cookie
* @return Requests_Cookie
*/
public function normalizeCookie($cookie, $key = null) {
if ($cookie instanceof Requests_Cookie) {
return $cookie;
}
return Requests_Cookie::parse($cookie, $key);
}
/**
* Check if the given item exists
*
* @param string $key Item key
* @return boolean Does the item exist?
*/
public function offsetExists($key) {
return isset($this->cookies[$key]);
}
/**
* Get the value for the item
*
* @param string $key Item key
* @return string Item value
*/
public function offsetGet($key) {
if (!isset($this->cookies[$key]))
return null;
return $this->cookies[$key];
}
/**
* Set the given item
*
* @throws Requests_Exception On attempting to use dictionary as list (`invalidset`)
*
* @param string $key Item name
* @param string $value Item value
*/
public function offsetSet($key, $value) {
if ($key === null) {
throw new Requests_Exception('Object is a dictionary, not a list', 'invalidset');
}
$this->cookies[$key] = $value;
}
/**
* Unset the given header
*
* @param string $key
*/
public function offsetUnset($key) {
unset($this->cookies[$key]);
}
/**
* Get an iterator for the data
*
* @return ArrayIterator
*/
public function getIterator() {
return new ArrayIterator($this->cookies);
}
/**
* Register the cookie handler with the request's hooking system
*
* @param Requests_Hooker $hooks Hooking system
*/
public function register(Requests_Hooker $hooks) {
$hooks->register('requests.before_request', array($this, 'before_request'));
$hooks->register('requests.before_redirect_check', array($this, 'before_redirect_check'));
}
/**
* Add Cookie header to a request if we have any
*
* As per RFC 6265, cookies are separated by '; '
*
* @param string $url
* @param array $headers
* @param array $data
* @param string $type
* @param array $options
*/
public function before_request(&$url, &$headers, &$data, &$type, &$options) {
if (!empty($this->cookies)) {
$cookies = array();
foreach ($this->cookies as $key => $cookie) {
$cookie = $this->normalizeCookie($cookie, $key);
$cookies[] = $cookie->formatForHeader();
}
$headers['Cookie'] = implode('; ', $cookies);
}
}
/**
* Parse all cookies from a response and attach them to the response
*
* @var Requests_Response $response
*/
public function before_redirect_check(Requests_Response &$return) {
$cookies = Requests_Cookie::parseFromHeaders($return->headers);
$this->cookies = array_merge($this->cookies, $cookies);
$return->cookies = $this;
}
}

View File

@@ -0,0 +1,62 @@
<?php
/**
* Exception for HTTP requests
*
* @package Requests
*/
/**
* Exception for HTTP requests
*
* @package Requests
*/
class Requests_Exception extends Exception {
/**
* Type of exception
*
* @var string
*/
protected $type;
/**
* Data associated with the exception
*
* @var mixed
*/
protected $data;
/**
* Create a new exception
*
* @param string $message Exception message
* @param string $type Exception type
* @param mixed $data Associated data
* @param integer $code Exception numerical code, if applicable
*/
public function __construct($message, $type, $data = null, $code = 0) {
parent::__construct($message, $code);
$this->type = $type;
$this->data = $data;
}
/**
* Like {@see getCode()}, but a string code.
*
* @codeCoverageIgnore
* @return string
*/
public function getType() {
return $this->type;
}
/**
* Gives any relevant data
*
* @codeCoverageIgnore
* @return mixed
*/
public function getData() {
return $this->data;
}
}

View File

@@ -0,0 +1,67 @@
<?php
/**
* Exception based on HTTP response
*
* @package Requests
*/
/**
* Exception based on HTTP response
*
* @package Requests
*/
class Requests_Exception_HTTP extends Requests_Exception {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 0;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Unknown';
/**
* Create a new exception
*
* There is no mechanism to pass in the status code, as this is set by the
* subclass used. Reason phrases can vary, however.
*
* @param string $reason Reason phrase
* @param mixed $data Associated data
*/
public function __construct($reason = null, $data = null) {
if ($reason !== null) {
$this->reason = $reason;
}
$message = sprintf('%d %s', $this->code, $this->reason);
parent::__construct($message, 'httpresponse', $data, $this->code);
}
/**
* Get the status message
*/
public function getReason() {
return $this->reason;
}
/**
* Get the correct exception class for a given error code
*
* @param int $code HTTP status code
* @return string Exception class name to use
*/
public static function get_class($code) {
$class = sprintf('Requests_Exception_HTTP_%d', $code);
if (class_exists($class)) {
return $class;
}
return 'Requests_Exception_HTTP_Unknown';
}
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 400 Bad Request responses
*
* @package Requests
*/
/**
* Exception for 400 Bad Request responses
*
* @package Requests
*/
class Requests_Exception_HTTP_400 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 400;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Bad Request';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 401 Unauthorized responses
*
* @package Requests
*/
/**
* Exception for 401 Unauthorized responses
*
* @package Requests
*/
class Requests_Exception_HTTP_401 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 401;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Unauthorized';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 402 Payment Required responses
*
* @package Requests
*/
/**
* Exception for 402 Payment Required responses
*
* @package Requests
*/
class Requests_Exception_HTTP_402 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 402;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Payment Required';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 403 Forbidden responses
*
* @package Requests
*/
/**
* Exception for 403 Forbidden responses
*
* @package Requests
*/
class Requests_Exception_HTTP_403 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 403;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Forbidden';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 404 Not Found responses
*
* @package Requests
*/
/**
* Exception for 404 Not Found responses
*
* @package Requests
*/
class Requests_Exception_HTTP_404 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 404;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Not Found';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 405 Method Not Allowed responses
*
* @package Requests
*/
/**
* Exception for 405 Method Not Allowed responses
*
* @package Requests
*/
class Requests_Exception_HTTP_405 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 405;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Method Not Allowed';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 406 Not Acceptable responses
*
* @package Requests
*/
/**
* Exception for 406 Not Acceptable responses
*
* @package Requests
*/
class Requests_Exception_HTTP_406 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 406;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Not Acceptable';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 407 Proxy Authentication Required responses
*
* @package Requests
*/
/**
* Exception for 407 Proxy Authentication Required responses
*
* @package Requests
*/
class Requests_Exception_HTTP_407 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 407;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Proxy Authentication Required';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 408 Request Timeout responses
*
* @package Requests
*/
/**
* Exception for 408 Request Timeout responses
*
* @package Requests
*/
class Requests_Exception_HTTP_408 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 408;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Request Timeout';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 409 Conflict responses
*
* @package Requests
*/
/**
* Exception for 409 Conflict responses
*
* @package Requests
*/
class Requests_Exception_HTTP_409 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 409;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Conflict';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 410 Gone responses
*
* @package Requests
*/
/**
* Exception for 410 Gone responses
*
* @package Requests
*/
class Requests_Exception_HTTP_410 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 410;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Gone';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 411 Length Required responses
*
* @package Requests
*/
/**
* Exception for 411 Length Required responses
*
* @package Requests
*/
class Requests_Exception_HTTP_411 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 411;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Length Required';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 412 Precondition Failed responses
*
* @package Requests
*/
/**
* Exception for 412 Precondition Failed responses
*
* @package Requests
*/
class Requests_Exception_HTTP_412 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 412;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Precondition Failed';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 413 Request Entity Too Large responses
*
* @package Requests
*/
/**
* Exception for 413 Request Entity Too Large responses
*
* @package Requests
*/
class Requests_Exception_HTTP_413 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 413;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Request Entity Too Large';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 414 Request-URI Too Large responses
*
* @package Requests
*/
/**
* Exception for 414 Request-URI Too Large responses
*
* @package Requests
*/
class Requests_Exception_HTTP_414 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 414;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Request-URI Too Large';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 415 Unsupported Media Type responses
*
* @package Requests
*/
/**
* Exception for 415 Unsupported Media Type responses
*
* @package Requests
*/
class Requests_Exception_HTTP_415 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 415;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Unsupported Media Type';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 416 Requested Range Not Satisfiable responses
*
* @package Requests
*/
/**
* Exception for 416 Requested Range Not Satisfiable responses
*
* @package Requests
*/
class Requests_Exception_HTTP_416 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 416;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Requested Range Not Satisfiable';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 417 Expectation Failed responses
*
* @package Requests
*/
/**
* Exception for 417 Expectation Failed responses
*
* @package Requests
*/
class Requests_Exception_HTTP_417 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 417;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Expectation Failed';
}

View File

@@ -0,0 +1,29 @@
<?php
/**
* Exception for 418 I'm A Teapot responses
*
* @see http://tools.ietf.org/html/rfc2324
* @package Requests
*/
/**
* Exception for 418 I'm A Teapot responses
*
* @see http://tools.ietf.org/html/rfc2324
* @package Requests
*/
class Requests_Exception_HTTP_418 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 418;
/**
* Reason phrase
*
* @var string
*/
protected $reason = "I'm A Teapot";
}

View File

@@ -0,0 +1,29 @@
<?php
/**
* Exception for 428 Precondition Required responses
*
* @see http://tools.ietf.org/html/rfc6585
* @package Requests
*/
/**
* Exception for 428 Precondition Required responses
*
* @see http://tools.ietf.org/html/rfc6585
* @package Requests
*/
class Requests_Exception_HTTP_428 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 428;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Precondition Required';
}

View File

@@ -0,0 +1,29 @@
<?php
/**
* Exception for 429 Too Many Requests responses
*
* @see http://tools.ietf.org/html/draft-nottingham-http-new-status-04
* @package Requests
*/
/**
* Exception for 429 Too Many Requests responses
*
* @see http://tools.ietf.org/html/draft-nottingham-http-new-status-04
* @package Requests
*/
class Requests_Exception_HTTP_429 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 429;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Too Many Requests';
}

View File

@@ -0,0 +1,29 @@
<?php
/**
* Exception for 431 Request Header Fields Too Large responses
*
* @see http://tools.ietf.org/html/rfc6585
* @package Requests
*/
/**
* Exception for 431 Request Header Fields Too Large responses
*
* @see http://tools.ietf.org/html/rfc6585
* @package Requests
*/
class Requests_Exception_HTTP_431 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 431;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Request Header Fields Too Large';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 500 Internal Server Error responses
*
* @package Requests
*/
/**
* Exception for 500 Internal Server Error responses
*
* @package Requests
*/
class Requests_Exception_HTTP_500 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 500;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Internal Server Error';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 501 Not Implemented responses
*
* @package Requests
*/
/**
* Exception for 501 Not Implemented responses
*
* @package Requests
*/
class Requests_Exception_HTTP_501 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 501;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Not Implemented';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 502 Bad Gateway responses
*
* @package Requests
*/
/**
* Exception for 502 Bad Gateway responses
*
* @package Requests
*/
class Requests_Exception_HTTP_502 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 502;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Bad Gateway';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 503 Service Unavailable responses
*
* @package Requests
*/
/**
* Exception for 503 Service Unavailable responses
*
* @package Requests
*/
class Requests_Exception_HTTP_503 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 503;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Service Unavailable';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 504 Gateway Timeout responses
*
* @package Requests
*/
/**
* Exception for 504 Gateway Timeout responses
*
* @package Requests
*/
class Requests_Exception_HTTP_504 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 504;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Gateway Timeout';
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Exception for 505 HTTP Version Not Supported responses
*
* @package Requests
*/
/**
* Exception for 505 HTTP Version Not Supported responses
*
* @package Requests
*/
class Requests_Exception_HTTP_505 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 505;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'HTTP Version Not Supported';
}

View File

@@ -0,0 +1,29 @@
<?php
/**
* Exception for 511 Network Authentication Required responses
*
* @see http://tools.ietf.org/html/rfc6585
* @package Requests
*/
/**
* Exception for 511 Network Authentication Required responses
*
* @see http://tools.ietf.org/html/rfc6585
* @package Requests
*/
class Requests_Exception_HTTP_511 extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 511;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Network Authentication Required';
}

View File

@@ -0,0 +1,44 @@
<?php
/**
* Exception for unknown status responses
*
* @package Requests
*/
/**
* Exception for unknown status responses
*
* @package Requests
*/
class Requests_Exception_HTTP_Unknown extends Requests_Exception_HTTP {
/**
* HTTP status code
*
* @var integer
*/
protected $code = 0;
/**
* Reason phrase
*
* @var string
*/
protected $reason = 'Unknown';
/**
* Create a new exception
*
* If `$data` is an instance of {@see Requests_Response}, uses the status
* code from it. Otherwise, sets as 0
*
* @param string $reason Reason phrase
* @param mixed $data Associated data
*/
public function __construct($reason = null, $data = null) {
if ($data instanceof Requests_Response) {
$this->code = $data->status_code;
}
parent::__construct($reason, $data);
}
}

View File

@@ -0,0 +1,33 @@
<?php
/**
* Event dispatcher
*
* @package Requests
* @subpackage Utilities
*/
/**
* Event dispatcher
*
* @package Requests
* @subpackage Utilities
*/
interface Requests_Hooker {
/**
* Register a callback for a hook
*
* @param string $hook Hook name
* @param callback $callback Function/method to call on event
* @param int $priority Priority number. <0 is executed earlier, >0 is executed later
*/
public function register($hook, $callback, $priority = 0);
/**
* Dispatch a message
*
* @param string $hook Hook name
* @param array $parameters Parameters to pass to callbacks
* @return boolean Successfulness
*/
public function dispatch($hook, $parameters = array());
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* Handles adding and dispatching events
*
* @package Requests
* @subpackage Utilities
*/
/**
* Handles adding and dispatching events
*
* @package Requests
* @subpackage Utilities
*/
class Requests_Hooks implements Requests_Hooker {
/**
* Constructor
*/
public function __construct() {
// pass
}
/**
* Register a callback for a hook
*
* @param string $hook Hook name
* @param callback $callback Function/method to call on event
* @param int $priority Priority number. <0 is executed earlier, >0 is executed later
*/
public function register($hook, $callback, $priority = 0) {
if (!isset($this->hooks[$hook])) {
$this->hooks[$hook] = array();
}
if (!isset($this->hooks[$hook][$priority])) {
$this->hooks[$hook][$priority] = array();
}
$this->hooks[$hook][$priority][] = $callback;
}
/**
* Dispatch a message
*
* @param string $hook Hook name
* @param array $parameters Parameters to pass to callbacks
* @return boolean Successfulness
*/
public function dispatch($hook, $parameters = array()) {
if (empty($this->hooks[$hook])) {
return false;
}
foreach ($this->hooks[$hook] as $priority => $hooked) {
foreach ($hooked as $callback) {
call_user_func_array($callback, $parameters);
}
}
return true;
}
}

View File

@@ -0,0 +1,390 @@
<?php
/**
* IDNA URL encoder
*
* Note: Not fully compliant, as nameprep does nothing yet.
*
* @package Requests
* @subpackage Utilities
* @see http://tools.ietf.org/html/rfc3490 IDNA specification
* @see http://tools.ietf.org/html/rfc3492 Punycode/Bootstrap specification
*/
class Requests_IDNAEncoder {
/**
* ACE prefix used for IDNA
*
* @see http://tools.ietf.org/html/rfc3490#section-5
* @var string
*/
const ACE_PREFIX = 'xn--';
/**#@+
* Bootstrap constant for Punycode
*
* @see http://tools.ietf.org/html/rfc3492#section-5
* @var int
*/
const BOOTSTRAP_BASE = 36;
const BOOTSTRAP_TMIN = 1;
const BOOTSTRAP_TMAX = 26;
const BOOTSTRAP_SKEW = 38;
const BOOTSTRAP_DAMP = 700;
const BOOTSTRAP_INITIAL_BIAS = 72;
const BOOTSTRAP_INITIAL_N = 128;
/**#@-*/
/**
* Encode a hostname using Punycode
*
* @param string $string Hostname
* @return string Punycode-encoded hostname
*/
public static function encode($string) {
$parts = explode('.', $string);
foreach ($parts as &$part) {
$part = self::to_ascii($part);
}
return implode('.', $parts);
}
/**
* Convert a UTF-8 string to an ASCII string using Punycode
*
* @throws Requests_Exception Provided string longer than 64 ASCII characters (`idna.provided_too_long`)
* @throws Requests_Exception Prepared string longer than 64 ASCII characters (`idna.prepared_too_long`)
* @throws Requests_Exception Provided string already begins with xn-- (`idna.provided_is_prefixed`)
* @throws Requests_Exception Encoded string longer than 64 ASCII characters (`idna.encoded_too_long`)
*
* @param string $string ASCII or UTF-8 string (max length 64 characters)
* @return string ASCII string
*/
public static function to_ascii($string) {
// Step 1: Check if the string is already ASCII
if (self::is_ascii($string)) {
// Skip to step 7
if (strlen($string) < 64) {
return $string;
}
throw new Requests_Exception('Provided string is too long', 'idna.provided_too_long', $string);
}
// Step 2: nameprep
$string = self::nameprep($string);
// Step 3: UseSTD3ASCIIRules is false, continue
// Step 4: Check if it's ASCII now
if (self::is_ascii($string)) {
// Skip to step 7
if (strlen($string) < 64) {
return $string;
}
throw new Requests_Exception('Prepared string is too long', 'idna.prepared_too_long', $string);
}
// Step 5: Check ACE prefix
if (strpos($string, self::ACE_PREFIX) === 0) {
throw new Requests_Exception('Provided string begins with ACE prefix', 'idna.provided_is_prefixed', $string);
}
// Step 6: Encode with Punycode
$string = self::punycode_encode($string);
// Step 7: Prepend ACE prefix
$string = self::ACE_PREFIX . $string;
// Step 8: Check size
if (strlen($string) < 64) {
return $string;
}
throw new Requests_Exception('Encoded string is too long', 'idna.encoded_too_long', $string);
}
/**
* Check whether a given string contains only ASCII characters
*
* @internal (Testing found regex was the fastest implementation)
*
* @param string $string
* @return bool Is the string ASCII-only?
*/
protected static function is_ascii($string) {
return (preg_match('/(?:[^\x00-\x7F])/', $string) !== 1);
}
/**
* Prepare a string for use as an IDNA name
*
* @todo Implement this based on RFC 3491 and the newer 5891
* @param string $string
* @return string Prepared string
*/
protected static function nameprep($string) {
return $string;
}
/**
* Convert a UTF-8 string to a UCS-4 codepoint array
*
* Based on Requests_IRI::replace_invalid_with_pct_encoding()
*
* @throws Requests_Exception Invalid UTF-8 codepoint (`idna.invalidcodepoint`)
* @param string $input
* @return array Unicode code points
*/
protected static function utf8_to_codepoints($input) {
$codepoints = array();
// Get number of bytes
$strlen = strlen($input);
for ($position = 0; $position < $strlen; $position++) {
$value = ord($input[$position]);
// One byte sequence:
if ((~$value & 0x80) === 0x80) {
$character = $value;
$length = 1;
$remaining = 0;
}
// Two byte sequence:
elseif (($value & 0xE0) === 0xC0) {
$character = ($value & 0x1F) << 6;
$length = 2;
$remaining = 1;
}
// Three byte sequence:
elseif (($value & 0xF0) === 0xE0) {
$character = ($value & 0x0F) << 12;
$length = 3;
$remaining = 2;
}
// Four byte sequence:
elseif (($value & 0xF8) === 0xF0) {
$character = ($value & 0x07) << 18;
$length = 4;
$remaining = 3;
}
// Invalid byte:
else {
throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $value);
}
if ($remaining > 0) {
if ($position + $length > $strlen) {
throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character);
}
for ($position++; $remaining > 0; $position++) {
$value = ord($input[$position]);
// If it is invalid, count the sequence as invalid and reprocess the current byte:
if (($value & 0xC0) !== 0x80) {
throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character);
}
$character |= ($value & 0x3F) << (--$remaining * 6);
}
$position--;
}
if (
// Non-shortest form sequences are invalid
$length > 1 && $character <= 0x7F
|| $length > 2 && $character <= 0x7FF
|| $length > 3 && $character <= 0xFFFF
// Outside of range of ucschar codepoints
// Noncharacters
|| ($character & 0xFFFE) === 0xFFFE
|| $character >= 0xFDD0 && $character <= 0xFDEF
|| (
// Everything else not in ucschar
$character > 0xD7FF && $character < 0xF900
|| $character < 0x20
|| $character > 0x7E && $character < 0xA0
|| $character > 0xEFFFD
)
) {
throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character);
}
$codepoints[] = $character;
}
return $codepoints;
}
/**
* RFC3492-compliant encoder
*
* @internal Pseudo-code from Section 6.3 is commented with "#" next to relevant code
* @throws Requests_Exception On character outside of the domain (never happens with Punycode) (`idna.character_outside_domain`)
*
* @param string $input UTF-8 encoded string to encode
* @return string Punycode-encoded string
*/
public static function punycode_encode($input) {
$output = '';
# let n = initial_n
$n = self::BOOTSTRAP_INITIAL_N;
# let delta = 0
$delta = 0;
# let bias = initial_bias
$bias = self::BOOTSTRAP_INITIAL_BIAS;
# let h = b = the number of basic code points in the input
$h = $b = 0; // see loop
# copy them to the output in order
$codepoints = self::utf8_to_codepoints($input);
foreach ($codepoints as $char) {
if ($char < 128) {
// Character is valid ASCII
// TODO: this should also check if it's valid for a URL
$output .= chr($char);
$h++;
}
// Check if the character is non-ASCII, but below initial n
// This never occurs for Punycode, so ignore in coverage
// @codeCoverageIgnoreStart
elseif ($char < $n) {
throw new Requests_Exception('Invalid character', 'idna.character_outside_domain', $char);
}
// @codeCoverageIgnoreEnd
else {
$extended[$char] = true;
}
}
$extended = array_keys($extended);
sort($extended);
$b = $h;
# [copy them] followed by a delimiter if b > 0
if (strlen($output) > 0) {
$output .= '-';
}
# {if the input contains a non-basic code point < n then fail}
# while h < length(input) do begin
while ($h < count($codepoints)) {
# let m = the minimum code point >= n in the input
$m = array_shift($extended);
//printf('next code point to insert is %s' . PHP_EOL, dechex($m));
# let delta = delta + (m - n) * (h + 1), fail on overflow
$delta += ($m - $n) * ($h + 1);
# let n = m
$n = $m;
# for each code point c in the input (in order) do begin
for ($num = 0; $num < count($codepoints); $num++) {
$c = $codepoints[$num];
# if c < n then increment delta, fail on overflow
if ($c < $n) {
$delta++;
}
# if c == n then begin
elseif ($c === $n) {
# let q = delta
$q = $delta;
# for k = base to infinity in steps of base do begin
for ($k = self::BOOTSTRAP_BASE; ; $k += self::BOOTSTRAP_BASE) {
# let t = tmin if k <= bias {+ tmin}, or
# tmax if k >= bias + tmax, or k - bias otherwise
if ($k <= ($bias + self::BOOTSTRAP_TMIN)) {
$t = self::BOOTSTRAP_TMIN;
}
elseif ($k >= ($bias + self::BOOTSTRAP_TMAX)) {
$t = self::BOOTSTRAP_TMAX;
}
else {
$t = $k - $bias;
}
# if q < t then break
if ($q < $t) {
break;
}
# output the code point for digit t + ((q - t) mod (base - t))
$digit = $t + (($q - $t) % (self::BOOTSTRAP_BASE - $t));
//printf('needed delta is %d, encodes as "%s"' . PHP_EOL, $delta, self::digit_to_char($digit));
$output .= self::digit_to_char($digit);
# let q = (q - t) div (base - t)
$q = floor(($q - $t) / (self::BOOTSTRAP_BASE - $t));
# end
}
# output the code point for digit q
$output .= self::digit_to_char($q);
//printf('needed delta is %d, encodes as "%s"' . PHP_EOL, $delta, self::digit_to_char($q));
# let bias = adapt(delta, h + 1, test h equals b?)
$bias = self::adapt($delta, $h + 1, $h === $b);
//printf('bias becomes %d' . PHP_EOL, $bias);
# let delta = 0
$delta = 0;
# increment h
$h++;
# end
}
# end
}
# increment delta and n
$delta++;
$n++;
# end
}
return $output;
}
/**
* Convert a digit to its respective character
*
* @see http://tools.ietf.org/html/rfc3492#section-5
* @throws Requests_Exception On invalid digit (`idna.invalid_digit`)
*
* @param int $digit Digit in the range 0-35
* @return string Single character corresponding to digit
*/
protected static function digit_to_char($digit) {
// @codeCoverageIgnoreStart
// As far as I know, this never happens, but still good to be sure.
if ($digit < 0 || $digit > 35) {
throw new Requests_Exception(sprintf('Invalid digit %d', $digit), 'idna.invalid_digit', $digit);
}
// @codeCoverageIgnoreEnd
$digits = 'abcdefghijklmnopqrstuvwxyz0123456789';
return substr($digits, $digit, 1);
}
/**
* Adapt the bias
*
* @see http://tools.ietf.org/html/rfc3492#section-6.1
* @param int $delta
* @param int $numpoints
* @param bool $firsttime
* @return int New bias
*/
protected static function adapt($delta, $numpoints, $firsttime) {
# function adapt(delta,numpoints,firsttime):
# if firsttime then let delta = delta div damp
if ($firsttime) {
$delta = floor($delta / self::BOOTSTRAP_DAMP);
}
# else let delta = delta div 2
else {
$delta = floor($delta / 2);
}
# let delta = delta + (delta div numpoints)
$delta += floor($delta / $numpoints);
# let k = 0
$k = 0;
# while delta > ((base - tmin) * tmax) div 2 do begin
$max = floor(((self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN) * self::BOOTSTRAP_TMAX) / 2);
while ($delta > $max) {
# let delta = delta div (base - tmin)
$delta = floor($delta / (self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN));
# let k = k + base
$k += self::BOOTSTRAP_BASE;
# end
}
# return k + (((base - tmin + 1) * delta) div (delta + skew))
return $k + floor(((self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN + 1) * $delta) / ($delta + self::BOOTSTRAP_SKEW));
}
}

View File

@@ -0,0 +1,221 @@
<?php
/**
* Class to validate and to work with IPv6 addresses
*
* @package Requests
* @subpackage Utilities
*/
/**
* Class to validate and to work with IPv6 addresses
*
* This was originally based on the PEAR class of the same name, but has been
* entirely rewritten.
*
* @package Requests
* @subpackage Utilities
*/
class Requests_IPv6
{
/**
* Uncompresses an IPv6 address
*
* RFC 4291 allows you to compress consecutive zero pieces in an address to
* '::'. This method expects a valid IPv6 address and expands the '::' to
* the required number of zero pieces.
*
* Example: FF01::101 -> FF01:0:0:0:0:0:0:101
* ::1 -> 0:0:0:0:0:0:0:1
*
* @author Alexander Merz <alexander.merz@web.de>
* @author elfrink at introweb dot nl
* @author Josh Peck <jmp at joshpeck dot org>
* @copyright 2003-2005 The PHP Group
* @license http://www.opensource.org/licenses/bsd-license.php
* @param string $ip An IPv6 address
* @return string The uncompressed IPv6 address
*/
public static function uncompress($ip)
{
$c1 = -1;
$c2 = -1;
if (substr_count($ip, '::') === 1)
{
list($ip1, $ip2) = explode('::', $ip);
if ($ip1 === '')
{
$c1 = -1;
}
else
{
$c1 = substr_count($ip1, ':');
}
if ($ip2 === '')
{
$c2 = -1;
}
else
{
$c2 = substr_count($ip2, ':');
}
if (strpos($ip2, '.') !== false)
{
$c2++;
}
// ::
if ($c1 === -1 && $c2 === -1)
{
$ip = '0:0:0:0:0:0:0:0';
}
// ::xxx
else if ($c1 === -1)
{
$fill = str_repeat('0:', 7 - $c2);
$ip = str_replace('::', $fill, $ip);
}
// xxx::
else if ($c2 === -1)
{
$fill = str_repeat(':0', 7 - $c1);
$ip = str_replace('::', $fill, $ip);
}
// xxx::xxx
else
{
$fill = ':' . str_repeat('0:', 6 - $c2 - $c1);
$ip = str_replace('::', $fill, $ip);
}
}
return $ip;
}
/**
* Compresses an IPv6 address
*
* RFC 4291 allows you to compress consecutive zero pieces in an address to
* '::'. This method expects a valid IPv6 address and compresses consecutive
* zero pieces to '::'.
*
* Example: FF01:0:0:0:0:0:0:101 -> FF01::101
* 0:0:0:0:0:0:0:1 -> ::1
*
* @see uncompress()
* @param string $ip An IPv6 address
* @return string The compressed IPv6 address
*/
public static function compress($ip)
{
// Prepare the IP to be compressed
$ip = self::uncompress($ip);
$ip_parts = self::split_v6_v4($ip);
// Replace all leading zeros
$ip_parts[0] = preg_replace('/(^|:)0+([0-9])/', '\1\2', $ip_parts[0]);
// Find bunches of zeros
if (preg_match_all('/(?:^|:)(?:0(?::|$))+/', $ip_parts[0], $matches, PREG_OFFSET_CAPTURE))
{
$max = 0;
$pos = null;
foreach ($matches[0] as $match)
{
if (strlen($match[0]) > $max)
{
$max = strlen($match[0]);
$pos = $match[1];
}
}
$ip_parts[0] = substr_replace($ip_parts[0], '::', $pos, $max);
}
if ($ip_parts[1] !== '')
{
return implode(':', $ip_parts);
}
else
{
return $ip_parts[0];
}
}
/**
* Splits an IPv6 address into the IPv6 and IPv4 representation parts
*
* RFC 4291 allows you to represent the last two parts of an IPv6 address
* using the standard IPv4 representation
*
* Example: 0:0:0:0:0:0:13.1.68.3
* 0:0:0:0:0:FFFF:129.144.52.38
*
* @param string $ip An IPv6 address
* @return array [0] contains the IPv6 represented part, and [1] the IPv4 represented part
*/
private static function split_v6_v4($ip)
{
if (strpos($ip, '.') !== false)
{
$pos = strrpos($ip, ':');
$ipv6_part = substr($ip, 0, $pos);
$ipv4_part = substr($ip, $pos + 1);
return array($ipv6_part, $ipv4_part);
}
else
{
return array($ip, '');
}
}
/**
* Checks an IPv6 address
*
* Checks if the given IP is a valid IPv6 address
*
* @param string $ip An IPv6 address
* @return bool true if $ip is a valid IPv6 address
*/
public static function check_ipv6($ip)
{
$ip = self::uncompress($ip);
list($ipv6, $ipv4) = self::split_v6_v4($ip);
$ipv6 = explode(':', $ipv6);
$ipv4 = explode('.', $ipv4);
if (count($ipv6) === 8 && count($ipv4) === 1 || count($ipv6) === 6 && count($ipv4) === 4)
{
foreach ($ipv6 as $ipv6_part)
{
// The section can't be empty
if ($ipv6_part === '')
return false;
// Nor can it be over four characters
if (strlen($ipv6_part) > 4)
return false;
// Remove leading zeros (this is safe because of the above)
$ipv6_part = ltrim($ipv6_part, '0');
if ($ipv6_part === '')
$ipv6_part = '0';
// Check the value is valid
$value = hexdec($ipv6_part);
if (dechex($value) !== strtolower($ipv6_part) || $value < 0 || $value > 0xFFFF)
return false;
}
if (count($ipv4) === 4)
{
foreach ($ipv4 as $ipv4_part)
{
$value = (int) $ipv4_part;
if ((string) $value !== $ipv4_part || $value < 0 || $value > 0xFF)
return false;
}
}
return true;
}
else
{
return false;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
Requests
========
Copyright (c) 2010-2012 Ryan McCue and contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ComplexPie IRI Parser
=====================
Copyright (c) 2007-2010, Geoffrey Sneddon and Steve Minutillo.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the SimplePie Team nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,35 @@
<?php
/**
* Proxy connection interface
*
* @package Requests
* @subpackage Proxy
* @since 1.6
*/
/**
* Proxy connection interface
*
* Implement this interface to handle proxy settings and authentication
*
* Parameters should be passed via the constructor where possible, as this
* makes it much easier for users to use your provider.
*
* @see Requests_Hooks
* @package Requests
* @subpackage Proxy
* @since 1.6
*/
interface Requests_Proxy {
/**
* Register hooks as needed
*
* This method is called in {@see Requests::request} when the user has set
* an instance as the 'auth' option. Use this callback to register all the
* hooks you'll need.
*
* @see Requests_Hooks::register
* @param Requests_Hooks $hooks Hook system
*/
public function register(Requests_Hooks &$hooks);
}

View File

@@ -0,0 +1,150 @@
<?php
/**
* HTTP Proxy connection interface
*
* @package Requests
* @subpackage Proxy
* @since 1.6
*/
/**
* HTTP Proxy connection interface
*
* Provides a handler for connection via an HTTP proxy
*
* @package Requests
* @subpackage Proxy
* @since 1.6
*/
class Requests_Proxy_HTTP implements Requests_Proxy {
/**
* Proxy host and port
*
* Notation: "host:port" (eg 127.0.0.1:8080 or someproxy.com:3128)
*
* @var string
*/
public $proxy;
/**
* Username
*
* @var string
*/
public $user;
/**
* Password
*
* @var string
*/
public $pass;
/**
* Do we need to authenticate? (ie username & password have been provided)
*
* @var boolean
*/
public $use_authentication;
/**
* Constructor
*
* @since 1.6
* @throws Requests_Exception On incorrect number of arguments (`authbasicbadargs`)
* @param array|null $args Array of user and password. Must have exactly two elements
*/
public function __construct($args = null) {
if (is_string($args)) {
$this->proxy = $args;
}
elseif (is_array($args)) {
if (count($args) == 1) {
list($this->proxy) = $args;
}
elseif (count($args) == 3) {
list($this->proxy, $this->user, $this->pass) = $args;
$this->use_authentication = true;
}
else {
throw new Requests_Exception( 'Invalid number of arguments', 'proxyhttpbadargs');
}
}
}
/**
* Register the necessary callbacks
*
* @since 1.6
* @see curl_before_send
* @see fsockopen_remote_socket
* @see fsockopen_remote_host_path
* @see fsockopen_header
* @param Requests_Hooks $hooks Hook system
*/
public function register(Requests_Hooks &$hooks) {
$hooks->register('curl.before_send', array(&$this, 'curl_before_send'));
$hooks->register('fsockopen.remote_socket', array(&$this, 'fsockopen_remote_socket'));
$hooks->register('fsockopen.remote_host_path', array(&$this, 'fsockopen_remote_host_path'));
if( $this->use_authentication ) {
$hooks->register('fsockopen.after_headers', array(&$this, 'fsockopen_header'));
}
}
/**
* Set cURL parameters before the data is sent
*
* @since 1.6
* @param resource $handle cURL resource
*/
public function curl_before_send(&$handle) {
curl_setopt($handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
curl_setopt($handle, CURLOPT_PROXY, $this->proxy);
if ($this->use_authentication) {
curl_setopt($handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
curl_setopt($handle, CURLOPT_PROXYUSERPWD, $this->get_auth_string());
}
}
/**
* Alter remote socket information before opening socket connection
*
* @since 1.6
* @param string $out HTTP header string
*/
public function fsockopen_remote_socket( &$remote_socket ) {
$remote_socket = $this->proxy;
}
/**
* Alter remote path before getting stream data
*
* @since 1.6
* @param string $out HTTP header string
*/
public function fsockopen_remote_host_path( &$path, $url ) {
$path = $url;
}
/**
* Add extra headers to the request before sending
*
* @since 1.6
* @param string $out HTTP header string
*/
public function fsockopen_header( &$out ) {
$out .= "Proxy-Authorization: Basic " . base64_encode($this->get_auth_string()) . "\r\n";
}
/**
* Get the authentication string (user:pass)
*
* @since 1.6
* @return string
*/
public function get_auth_string() {
return $this->user . ':' . $this->pass;
}
}

View File

@@ -0,0 +1,95 @@
<?php
/**
* HTTP response class
*
* Contains a response from Requests::request()
* @package Requests
*/
/**
* HTTP response class
*
* Contains a response from Requests::request()
* @package Requests
*/
class Requests_Response {
/**
* Constructor
*/
public function __construct() {
$this->headers = new Requests_Response_Headers();
}
/**
* Response body
* @var string
*/
public $body = '';
/**
* Raw HTTP data from the transport
* @var string
*/
public $raw = '';
/**
* Headers, as an associative array
* @var array
*/
public $headers = array();
/**
* Status code, false if non-blocking
* @var integer|boolean
*/
public $status_code = false;
/**
* Whether the request succeeded or not
* @var boolean
*/
public $success = false;
/**
* Number of redirects the request used
* @var integer
*/
public $redirects = 0;
/**
* URL requested
* @var string
*/
public $url = '';
/**
* Previous requests (from redirects)
* @var array Array of Requests_Response objects
*/
public $history = array();
/**
* Cookies from the request
*/
public $cookies = array();
/**
* Throws an exception if the request was not successful
*
* @throws Requests_Exception If `$allow_redirects` is false, and code is 3xx (`response.no_redirects`)
* @throws Requests_Exception_HTTP On non-successful status code. Exception class corresponds to code (e.g. {@see Requests_Exception_HTTP_404})
* @param boolean $allow_redirects Set to false to throw on a 3xx as well
*/
public function throw_for_status($allow_redirects = true) {
if ($this->status_code >= 300 && $this->status_code < 400) {
if (!$allow_redirects) {
throw new Requests_Exception('Redirection not allowed', 'response.no_redirects', $this);
}
}
elseif (!$this->success) {
$exception = Requests_Exception_HTTP::get_class($this->status_code);
throw new $exception(null, $this);
}
}
}

View File

@@ -0,0 +1,95 @@
<?php
/**
* Case-insensitive dictionary, suitable for HTTP headers
*
* @package Requests
*/
/**
* Case-insensitive dictionary, suitable for HTTP headers
*
* @package Requests
*/
class Requests_Response_Headers extends Requests_Utility_CaseInsensitiveDictionary {
/**
* Get the given header
*
* Unlike {@see self::getValues()}, this returns a string. If there are
* multiple values, it concatenates them with a comma as per RFC2616.
*
* Avoid using this where commas may be used unquoted in values, such as
* Set-Cookie headers.
*
* @param string $key
* @return string Header value
*/
public function offsetGet($key) {
$key = strtolower($key);
if (!isset($this->data[$key]))
return null;
return $this->flatten($this->data[$key]);
}
/**
* Set the given item
*
* @throws Requests_Exception On attempting to use dictionary as list (`invalidset`)
*
* @param string $key Item name
* @param string $value Item value
*/
public function offsetSet($key, $value) {
if ($key === null) {
throw new Requests_Exception('Object is a dictionary, not a list', 'invalidset');
}
$key = strtolower($key);
if (!isset($this->data[$key])) {
$this->data[$key] = array();
}
$this->data[$key][] = $value;
}
/**
* Get all values for a given header
*
* @param string $key
* @return array Header values
*/
public function getValues($key) {
$key = strtolower($key);
if (!isset($this->data[$key]))
return null;
return $this->data[$key];
}
/**
* Flattens a value into a string
*
* Converts an array into a string by imploding values with a comma, as per
* RFC2616's rules for folding headers.
*
* @param string|array $value Value to flatten
* @return string Flattened value
*/
public function flatten($value) {
if (is_array($value))
$value = implode(',', $value);
return $value;
}
/**
* Get an iterator for the data
*
* Converts the internal
* @return ArrayIterator
*/
public function getIterator() {
return new Requests_Utility_FilteredIterator($this->data, array($this, 'flatten'));
}
}

View File

@@ -0,0 +1,151 @@
<?php
/**
* SSL utilities for Requests
*
* @package Requests
* @subpackage Utilities
*/
/**
* SSL utilities for Requests
*
* Collection of utilities for working with and verifying SSL certificates.
*
* @package Requests
* @subpackage Utilities
*/
class Requests_SSL {
/**
* Verify the certificate against common name and subject alternative names
*
* Unfortunately, PHP doesn't check the certificate against the alternative
* names, leading things like 'https://www.github.com/' to be invalid.
* Instead
*
* @see http://tools.ietf.org/html/rfc2818#section-3.1 RFC2818, Section 3.1
*
* @throws Requests_Exception On not obtaining a match for the host (`fsockopen.ssl.no_match`)
* @param string $host Host name to verify against
* @param resource $context Stream context
* @return bool
*/
public static function verify_certificate($host, $cert) {
// Calculate the valid wildcard match if the host is not an IP address
$parts = explode('.', $host);
if (ip2long($host) === false) {
$parts[0] = '*';
}
$wildcard = implode('.', $parts);
$has_dns_alt = false;
// Check the subjectAltName
if (!empty($cert['extensions']) && !empty($cert['extensions']['subjectAltName'])) {
$altnames = explode(',', $cert['extensions']['subjectAltName']);
foreach ($altnames as $altname) {
$altname = trim($altname);
if (strpos($altname, 'DNS:') !== 0)
continue;
$has_dns_alt = true;
// Strip the 'DNS:' prefix and trim whitespace
$altname = trim(substr($altname, 4));
// Check for a match
if (self::match_domain($host, $altname) === true) {
return true;
}
}
}
// Fall back to checking the common name if we didn't get any dNSName
// alt names, as per RFC2818
if (!$has_dns_alt && !empty($cert['subject']['CN'])) {
// Check for a match
if (self::match_domain($host, $cert['subject']['CN']) === true) {
return true;
}
}
return false;
}
/**
* Verify that a reference name is valid
*
* Verifies a dNSName for HTTPS usage, (almost) as per Firefox's rules:
* - Wildcards can only occur in a name with more than 3 components
* - Wildcards can only occur as the last character in the first
* component
* - Wildcards may be preceded by additional characters
*
* We modify these rules to be a bit stricter and only allow the wildcard
* character to be the full first component; that is, with the exclusion of
* the third rule.
*
* @param string $reference Reference dNSName
* @return boolean Is the name valid?
*/
public static function verify_reference_name($reference) {
$parts = explode('.', $reference);
// Check the first part of the name
$first = array_shift($parts);
if (strpos($first, '*') !== false) {
// Check that the wildcard is the full part
if ($first !== '*') {
return false;
}
// Check that we have at least 3 components (including first)
if (count($parts) < 2) {
return false;
}
}
// Check the remaining parts
foreach ($parts as $part) {
if (strpos($part, '*') !== false) {
return false;
}
}
// Nothing found, verified!
return true;
}
/**
* Match a hostname against a dNSName reference
*
* @param string $host Requested host
* @param string $reference dNSName to match against
* @return boolean Does the domain match?
*/
public static function match_domain($host, $reference) {
// Check if the reference is blacklisted first
if (self::verify_reference_name($reference) !== true) {
return false;
}
// Check for a direct match
if ($host === $reference) {
return true;
}
// Calculate the valid wildcard match if the host is not an IP address
// Also validates that the host has 3 parts or more, as per Firefox's
// ruleset.
if (ip2long($host) === false) {
$parts = explode('.', $host);
$parts[0] = '*';
$wildcard = implode('.', $parts);
if ($wildcard === $reference) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,253 @@
<?php
/**
* Session handler for persistent requests and default parameters
*
* @package Requests
* @subpackage Session Handler
*/
/**
* Session handler for persistent requests and default parameters
*
* Allows various options to be set as default values, and merges both the
* options and URL properties together. A base URL can be set for all requests,
* with all subrequests resolved from this. Base options can be set (including
* a shared cookie jar), then overridden for individual requests.
*
* @package Requests
* @subpackage Session Handler
*/
class Requests_Session {
/**
* Base URL for requests
*
* URLs will be made absolute using this as the base
* @var string|null
*/
public $url = null;
/**
* Base headers for requests
* @var array
*/
public $headers = array();
/**
* Base data for requests
*
* If both the base data and the per-request data are arrays, the data will
* be merged before sending the request.
*
* @var array
*/
public $data = array();
/**
* Base options for requests
*
* The base options are merged with the per-request data for each request.
* The only default option is a shared cookie jar between requests.
*
* Values here can also be set directly via properties on the Session
* object, e.g. `$session->useragent = 'X';`
*
* @var array
*/
public $options = array();
/**
* Create a new session
*
* @param string|null $url Base URL for requests
* @param array $headers Default headers for requests
* @param array $data Default data for requests
* @param array $options Default options for requests
*/
public function __construct($url = null, $headers = array(), $data = array(), $options = array()) {
$this->url = $url;
$this->headers = $headers;
$this->data = $data;
$this->options = $options;
if (empty($this->options['cookies'])) {
$this->options['cookies'] = new Requests_Cookie_Jar();
}
}
/**
* Get a property's value
*
* @param string $key Property key
* @return mixed|null Property value, null if none found
*/
public function __get($key) {
if (isset($this->options[$key]))
return $this->options[$key];
return null;
}
/**
* Set a property's value
*
* @param string $key Property key
* @param mixed $value Property value
*/
public function __set($key, $value) {
$this->options[$key] = $value;
}
/**
* Remove a property's value
*
* @param string $key Property key
*/
public function __isset($key) {
return isset($this->options[$key]);
}
/**
* Remove a property's value
*
* @param string $key Property key
*/
public function __unset($key) {
$this->options[$key] = null;
}
/**#@+
* @see request()
* @param string $url
* @param array $headers
* @param array $options
* @return Requests_Response
*/
/**
* Send a GET request
*/
public function get($url, $headers = array(), $options = array()) {
return $this->request($url, $headers, null, Requests::GET, $options);
}
/**
* Send a HEAD request
*/
public function head($url, $headers = array(), $options = array()) {
return $this->request($url, $headers, null, Requests::HEAD, $options);
}
/**
* Send a DELETE request
*/
public function delete($url, $headers = array(), $options = array()) {
return $this->request($url, $headers, null, Requests::DELETE, $options);
}
/**#@-*/
/**#@+
* @see request()
* @param string $url
* @param array $headers
* @param array $data
* @param array $options
* @return Requests_Response
*/
/**
* Send a POST request
*/
public function post($url, $headers = array(), $data = array(), $options = array()) {
return $this->request($url, $headers, $data, Requests::POST, $options);
}
/**
* Send a PUT request
*/
public function put($url, $headers = array(), $data = array(), $options = array()) {
return $this->request($url, $headers, $data, Requests::PUT, $options);
}
/**
* Send a PATCH request
*
* Note: Unlike {@see post} and {@see put}, `$headers` is required, as the
* specification recommends that should send an ETag
*
* @link http://tools.ietf.org/html/rfc5789
*/
public function patch($url, $headers, $data = array(), $options = array()) {
return $this->request($url, $headers, $data, Requests::PATCH, $options);
}
/**#@-*/
/**
* Main interface for HTTP requests
*
* This method initiates a request and sends it via a transport before
* parsing.
*
* @see Requests::request()
*
* @throws Requests_Exception On invalid URLs (`nonhttp`)
*
* @param string $url URL to request
* @param array $headers Extra headers to send with the request
* @param array $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests
* @param string $type HTTP request type (use Requests constants)
* @param array $options Options for the request (see {@see Requests::request})
* @return Requests_Response
*/
public function request($url, $headers = array(), $data = array(), $type = Requests::GET, $options = array()) {
$request = $this->merge_request(compact('url', 'headers', 'data', 'options'));
return Requests::request($request['url'], $request['headers'], $request['data'], $type, $request['options']);
}
/**
* Send multiple HTTP requests simultaneously
*
* @see Requests::request_multiple()
*
* @param array $requests Requests data (see {@see Requests::request_multiple})
* @param array $options Global and default options (see {@see Requests::request})
* @return array Responses (either Requests_Response or a Requests_Exception object)
*/
public function request_multiple($requests, $options = array()) {
foreach ($requests as $key => $request) {
$requests[$key] = $this->merge_request($request, false);
}
$options = array_merge($this->options, $options);
// Disallow forcing the type, as that's a per request setting
unset($options['type']);
return Requests::request_multiple($requests, $options);
}
/**
* Merge a request's data with the default data
*
* @param array $request Request data (same form as {@see request_multiple})
* @param boolean $merge_options Should we merge options as well?
* @return array Request data
*/
protected function merge_request($request, $merge_options = true) {
if ($this->url !== null) {
$request['url'] = Requests_IRI::absolutize($this->url, $request['url']);
$request['url'] = $request['url']->uri;
}
$request['headers'] = array_merge($this->headers, $request['headers']);
if (is_array($request['data']) && is_array($this->data)) {
$request['data'] = array_merge($this->data, $request['data']);
}
if ($merge_options !== false) {
$request['options'] = array_merge($this->options, $request['options']);
// Disallow forcing the type, as that's a per request setting
unset($request['options']['type']);
}
return $request;
}
}

View File

@@ -0,0 +1,41 @@
<?php
/**
* Base HTTP transport
*
* @package Requests
* @subpackage Transport
*/
/**
* Base HTTP transport
*
* @package Requests
* @subpackage Transport
*/
interface Requests_Transport {
/**
* Perform a request
*
* @param string $url URL to request
* @param array $headers Associative array of request headers
* @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD
* @param array $options Request options, see {@see Requests::response()} for documentation
* @return string Raw HTTP result
*/
public function request($url, $headers = array(), $data = array(), $options = array());
/**
* Send multiple requests simultaneously
*
* @param array $requests Request data (array of 'url', 'headers', 'data', 'options') as per {@see Requests_Transport::request}
* @param array $options Global options, see {@see Requests::response()} for documentation
* @return array Array of Requests_Response objects (may contain Requests_Exception or string responses as well)
*/
public function request_multiple($requests, $options);
/**
* Self-test whether the transport can be used
* @return bool
*/
public static function test();
}

View File

@@ -0,0 +1,349 @@
<?php
/**
* cURL HTTP transport
*
* @package Requests
* @subpackage Transport
*/
/**
* cURL HTTP transport
*
* @package Requests
* @subpackage Transport
*/
class Requests_Transport_cURL implements Requests_Transport {
/**
* Raw HTTP data
*
* @var string
*/
public $headers = '';
/**
* Information on the current request
*
* @var array cURL information array, see {@see http://php.net/curl_getinfo}
*/
public $info;
/**
* Version string
*
* @var string
*/
public $version;
/**
* cURL handle
*
* @var resource
*/
protected $fp;
/**
* Have we finished the headers yet?
*
* @var boolean
*/
protected $done_headers = false;
/**
* If streaming to a file, keep the file pointer
*
* @var resource
*/
protected $stream_handle;
/**
* Constructor
*/
public function __construct() {
$curl = curl_version();
$this->version = $curl['version'];
$this->fp = curl_init();
curl_setopt($this->fp, CURLOPT_HEADER, false);
curl_setopt($this->fp, CURLOPT_RETURNTRANSFER, 1);
if (version_compare($this->version, '7.10.5', '>=')) {
curl_setopt($this->fp, CURLOPT_ENCODING, '');
}
if (version_compare($this->version, '7.19.4', '>=')) {
curl_setopt($this->fp, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
}
}
/**
* Perform a request
*
* @throws Requests_Exception On a cURL error (`curlerror`)
*
* @param string $url URL to request
* @param array $headers Associative array of request headers
* @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD
* @param array $options Request options, see {@see Requests::response()} for documentation
* @return string Raw HTTP result
*/
public function request($url, $headers = array(), $data = array(), $options = array()) {
$this->setup_handle($url, $headers, $data, $options);
$options['hooks']->dispatch('curl.before_send', array(&$this->fp));
if ($options['filename'] !== false) {
$this->stream_handle = fopen($options['filename'], 'wb');
curl_setopt($this->fp, CURLOPT_FILE, $this->stream_handle);
}
if (isset($options['verify'])) {
if ($options['verify'] === false) {
curl_setopt($this->fp, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($this->fp, CURLOPT_SSL_VERIFYPEER, 0);
} elseif (is_string($options['verify'])) {
curl_setopt($this->fp, CURLOPT_CAINFO, $options['verify']);
}
}
if (isset($options['verifyname']) && $options['verifyname'] === false) {
curl_setopt($this->fp, CURLOPT_SSL_VERIFYHOST, 0);
}
$response = curl_exec($this->fp);
$options['hooks']->dispatch('curl.after_send', array(&$fake_headers));
if (curl_errno($this->fp) === 23 || curl_errno($this->fp) === 61) {
curl_setopt($this->fp, CURLOPT_ENCODING, 'none');
$response = curl_exec($this->fp);
}
$this->process_response($response, $options);
return $this->headers;
}
/**
* Send multiple requests simultaneously
*
* @param array $requests Request data
* @param array $options Global options
* @return array Array of Requests_Response objects (may contain Requests_Exception or string responses as well)
*/
public function request_multiple($requests, $options) {
$multihandle = curl_multi_init();
$subrequests = array();
$subhandles = array();
$class = get_class($this);
foreach ($requests as $id => $request) {
$subrequests[$id] = new $class();
$subhandles[$id] = $subrequests[$id]->get_subrequest_handle($request['url'], $request['headers'], $request['data'], $request['options']);
$request['options']['hooks']->dispatch('curl.before_multi_add', array(&$subhandles[$id]));
curl_multi_add_handle($multihandle, $subhandles[$id]);
}
$completed = 0;
$responses = array();
$request['options']['hooks']->dispatch('curl.before_multi_exec', array(&$multihandle));
do {
$active = false;
do {
$status = curl_multi_exec($multihandle, $active);
}
while ($status === CURLM_CALL_MULTI_PERFORM);
$to_process = array();
// Read the information as needed
while ($done = curl_multi_info_read($multihandle)) {
$key = array_search($done['handle'], $subhandles, true);
if (!isset($to_process[$key])) {
$to_process[$key] = $done;
}
}
// Parse the finished requests before we start getting the new ones
foreach ($to_process as $key => $done) {
$options = $requests[$key]['options'];
$responses[$key] = $subrequests[$key]->process_response(curl_multi_getcontent($done['handle']), $options);
$options['hooks']->dispatch('transport.internal.parse_response', array(&$responses[$key], $requests[$key]));
curl_multi_remove_handle($multihandle, $done['handle']);
curl_close($done['handle']);
if (!is_string($responses[$key])) {
$options['hooks']->dispatch('multiple.request.complete', array(&$responses[$key], $key));
}
$completed++;
}
}
while ($active || $completed < count($subrequests));
$request['options']['hooks']->dispatch('curl.after_multi_exec', array(&$multihandle));
curl_multi_close($multihandle);
return $responses;
}
/**
* Get the cURL handle for use in a multi-request
*
* @param string $url URL to request
* @param array $headers Associative array of request headers
* @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD
* @param array $options Request options, see {@see Requests::response()} for documentation
* @return resource Subrequest's cURL handle
*/
public function &get_subrequest_handle($url, $headers, $data, $options) {
$this->setup_handle($url, $headers, $data, $options);
if ($options['filename'] !== false) {
$this->stream_handle = fopen($options['filename'], 'wb');
curl_setopt($this->fp, CURLOPT_FILE, $this->stream_handle);
}
return $this->fp;
}
/**
* Setup the cURL handle for the given data
*
* @param string $url URL to request
* @param array $headers Associative array of request headers
* @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD
* @param array $options Request options, see {@see Requests::response()} for documentation
*/
protected function setup_handle($url, $headers, $data, $options) {
$options['hooks']->dispatch('curl.before_request', array(&$this->fp));
$headers = Requests::flatten($headers);
if (in_array($options['type'], array(Requests::HEAD, Requests::GET, Requests::DELETE)) & !empty($data)) {
$url = self::format_get($url, $data);
}
elseif (!empty($data) && !is_string($data)) {
$data = http_build_query($data, null, '&');
}
switch ($options['type']) {
case Requests::POST:
curl_setopt($this->fp, CURLOPT_POST, true);
curl_setopt($this->fp, CURLOPT_POSTFIELDS, $data);
break;
case Requests::PATCH:
case Requests::PUT:
curl_setopt($this->fp, CURLOPT_CUSTOMREQUEST, $options['type']);
curl_setopt($this->fp, CURLOPT_POSTFIELDS, $data);
break;
case Requests::DELETE:
curl_setopt($this->fp, CURLOPT_CUSTOMREQUEST, 'DELETE');
break;
case Requests::HEAD:
curl_setopt($this->fp, CURLOPT_NOBODY, true);
break;
}
curl_setopt($this->fp, CURLOPT_URL, $url);
curl_setopt($this->fp, CURLOPT_TIMEOUT, $options['timeout']);
curl_setopt($this->fp, CURLOPT_CONNECTTIMEOUT, $options['timeout']);
curl_setopt($this->fp, CURLOPT_REFERER, $url);
curl_setopt($this->fp, CURLOPT_USERAGENT, $options['useragent']);
curl_setopt($this->fp, CURLOPT_HTTPHEADER, $headers);
if (true === $options['blocking']) {
curl_setopt($this->fp, CURLOPT_HEADERFUNCTION, array(&$this, 'stream_headers'));
}
}
public function process_response($response, $options) {
if ($options['blocking'] === false) {
curl_close($this->fp);
$fake_headers = '';
$options['hooks']->dispatch('curl.after_request', array(&$fake_headers));
return false;
}
if ($options['filename'] !== false) {
fclose($this->stream_handle);
$this->headers = trim($this->headers);
}
else {
$this->headers .= $response;
}
if (curl_errno($this->fp)) {
throw new Requests_Exception('cURL error ' . curl_errno($this->fp) . ': ' . curl_error($this->fp), 'curlerror', $this->fp);
return;
}
$this->info = curl_getinfo($this->fp);
curl_close($this->fp);
$options['hooks']->dispatch('curl.after_request', array(&$this->headers));
return $this->headers;
}
/**
* Collect the headers as they are received
*
* @param resource $handle cURL resource
* @param string $headers Header string
* @return integer Length of provided header
*/
protected function stream_headers($handle, $headers) {
// Why do we do this? cURL will send both the final response and any
// interim responses, such as a 100 Continue. We don't need that.
// (We may want to keep this somewhere just in case)
if ($this->done_headers) {
$this->headers = '';
$this->done_headers = false;
}
$this->headers .= $headers;
if ($headers === "\r\n") {
$this->done_headers = true;
}
return strlen($headers);
}
/**
* Format a URL given GET data
*
* @param string $url
* @param array|object $data Data to build query using, see {@see http://php.net/http_build_query}
* @return string URL with data
*/
protected static function format_get($url, $data) {
if (!empty($data)) {
$url_parts = parse_url($url);
if (empty($url_parts['query'])) {
$query = $url_parts['query'] = '';
}
else {
$query = $url_parts['query'];
}
$query .= '&' . http_build_query($data, null, '&');
$query = trim($query, '&');
if (empty($url_parts['query'])) {
$url .= '?' . $query;
}
else {
$url = str_replace($url_parts['query'], $query, $url);
}
}
return $url;
}
/**
* Whether this transport is valid
*
* @codeCoverageIgnore
* @return boolean True if the transport is valid, false otherwise.
*/
public static function test() {
return (function_exists('curl_init') && function_exists('curl_exec'));
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,381 @@
<?php
/**
* fsockopen HTTP transport
*
* @package Requests
* @subpackage Transport
*/
/**
* fsockopen HTTP transport
*
* @package Requests
* @subpackage Transport
*/
class Requests_Transport_fsockopen implements Requests_Transport {
/**
* Raw HTTP data
*
* @var string
*/
public $headers = '';
/**
* Stream metadata
*
* @var array Associative array of properties, see {@see http://php.net/stream_get_meta_data}
*/
public $info;
protected $connect_error = '';
/**
* Perform a request
*
* @throws Requests_Exception On failure to connect to socket (`fsockopenerror`)
* @throws Requests_Exception On socket timeout (`timeout`)
*
* @param string $url URL to request
* @param array $headers Associative array of request headers
* @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD
* @param array $options Request options, see {@see Requests::response()} for documentation
* @return string Raw HTTP result
*/
public function request($url, $headers = array(), $data = array(), $options = array()) {
$options['hooks']->dispatch('fsockopen.before_request');
$url_parts = parse_url($url);
$host = $url_parts['host'];
$context = stream_context_create();
$verifyname = false;
// HTTPS support
if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https') {
$remote_socket = 'ssl://' . $host;
$url_parts['port'] = 443;
$context_options = array(
'verify_peer' => true,
// 'CN_match' => $host,
'capture_peer_cert' => true
);
$verifyname = true;
// SNI, if enabled (OpenSSL >=0.9.8j)
if (defined('OPENSSL_TLSEXT_SERVER_NAME') && OPENSSL_TLSEXT_SERVER_NAME) {
$context_options['SNI_enabled'] = true;
if (isset($options['verifyname']) && $options['verifyname'] === false) {
$context_options['SNI_enabled'] = false;
}
}
if (isset($options['verify'])) {
if ($options['verify'] === false) {
$context_options['verify_peer'] = false;
} elseif (is_string($options['verify'])) {
$context_options['cafile'] = $options['verify'];
}
}
if (isset($options['verifyname']) && $options['verifyname'] === false) {
$verifyname = false;
}
stream_context_set_option($context, array('ssl' => $context_options));
}
else {
$remote_socket = 'tcp://' . $host;
}
$proxy = isset( $options['proxy'] );
$proxy_auth = $proxy && isset( $options['proxy_username'] ) && isset( $options['proxy_password'] );
if (!isset($url_parts['port'])) {
$url_parts['port'] = 80;
}
$remote_socket .= ':' . $url_parts['port'];
set_error_handler(array($this, 'connect_error_handler'), E_WARNING | E_NOTICE);
$options['hooks']->dispatch('fsockopen.remote_socket', array(&$remote_socket));
$fp = stream_socket_client($remote_socket, $errno, $errstr, $options['timeout'], STREAM_CLIENT_CONNECT, $context);
restore_error_handler();
if ($verifyname) {
if (!$this->verify_certificate_from_context($host, $context)) {
throw new Requests_Exception('SSL certificate did not match the requested domain name', 'ssl.no_match');
}
}
if (!$fp) {
if ($errno === 0) {
// Connection issue
throw new Requests_Exception(rtrim($this->connect_error), 'fsockopen.connect_error');
}
else {
throw new Requests_Exception($errstr, 'fsockopenerror');
return;
}
}
$request_body = '';
$out = '';
switch ($options['type']) {
case Requests::POST:
case Requests::PUT:
case Requests::PATCH:
if (isset($url_parts['path'])) {
$path = $url_parts['path'];
if (isset($url_parts['query'])) {
$path .= '?' . $url_parts['query'];
}
}
else {
$path = '/';
}
$options['hooks']->dispatch( 'fsockopen.remote_host_path', array( &$path, $url ) );
$out = $options['type'] . " $path HTTP/1.0\r\n";
if (is_array($data)) {
$request_body = http_build_query($data, null, '&');
}
else {
$request_body = $data;
}
if (empty($headers['Content-Length'])) {
$headers['Content-Length'] = strlen($request_body);
}
if (empty($headers['Content-Type'])) {
$headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
}
break;
case Requests::HEAD:
case Requests::GET:
case Requests::DELETE:
$path = self::format_get($url_parts, $data);
$options['hooks']->dispatch('fsockopen.remote_host_path', array(&$path, $url));
$out = $options['type'] . " $path HTTP/1.0\r\n";
break;
}
$out .= "Host: {$url_parts['host']}";
if ($url_parts['port'] !== 80) {
$out .= ":{$url_parts['port']}";
}
$out .= "\r\n";
$out .= "User-Agent: {$options['useragent']}\r\n";
$accept_encoding = $this->accept_encoding();
if (!empty($accept_encoding)) {
$out .= "Accept-Encoding: $accept_encoding\r\n";
}
$headers = Requests::flatten($headers);
if (!empty($headers)) {
$out .= implode($headers, "\r\n") . "\r\n";
}
$options['hooks']->dispatch('fsockopen.after_headers', array(&$out));
if (substr($out, -2) !== "\r\n") {
$out .= "\r\n";
}
$out .= "Connection: Close\r\n\r\n" . $request_body;
$options['hooks']->dispatch('fsockopen.before_send', array(&$out));
fwrite($fp, $out);
$options['hooks']->dispatch('fsockopen.after_send', array(&$fake_headers));
if (!$options['blocking']) {
fclose($fp);
$fake_headers = '';
$options['hooks']->dispatch('fsockopen.after_request', array(&$fake_headers));
return '';
}
stream_set_timeout($fp, $options['timeout']);
$this->info = stream_get_meta_data($fp);
$this->headers = '';
$this->info = stream_get_meta_data($fp);
if (!$options['filename']) {
while (!feof($fp)) {
$this->info = stream_get_meta_data($fp);
if ($this->info['timed_out']) {
throw new Requests_Exception('fsocket timed out', 'timeout');
}
$this->headers .= fread($fp, 1160);
}
}
else {
$download = fopen($options['filename'], 'wb');
$doingbody = false;
$response = '';
while (!feof($fp)) {
$this->info = stream_get_meta_data($fp);
if ($this->info['timed_out']) {
throw new Requests_Exception('fsocket timed out', 'timeout');
}
$block = fread($fp, 1160);
if ($doingbody) {
fwrite($download, $block);
}
else {
$response .= $block;
if (strpos($response, "\r\n\r\n")) {
list($this->headers, $block) = explode("\r\n\r\n", $response, 2);
$doingbody = true;
fwrite($download, $block);
}
}
}
fclose($download);
}
fclose($fp);
$options['hooks']->dispatch('fsockopen.after_request', array(&$this->headers));
return $this->headers;
}
/**
* Send multiple requests simultaneously
*
* @param array $requests Request data (array of 'url', 'headers', 'data', 'options') as per {@see Requests_Transport::request}
* @param array $options Global options, see {@see Requests::response()} for documentation
* @return array Array of Requests_Response objects (may contain Requests_Exception or string responses as well)
*/
public function request_multiple($requests, $options) {
$responses = array();
$class = get_class($this);
foreach ($requests as $id => $request) {
try {
$handler = new $class();
$responses[$id] = $handler->request($request['url'], $request['headers'], $request['data'], $request['options']);
$request['options']['hooks']->dispatch('transport.internal.parse_response', array(&$responses[$id], $request));
}
catch (Requests_Exception $e) {
$responses[$id] = $e;
}
if (!is_string($responses[$id])) {
$request['options']['hooks']->dispatch('multiple.request.complete', array(&$responses[$id], $id));
}
}
return $responses;
}
/**
* Retrieve the encodings we can accept
*
* @return string Accept-Encoding header value
*/
protected static function accept_encoding() {
$type = array();
if (function_exists('gzinflate')) {
$type[] = 'deflate;q=1.0';
}
if (function_exists('gzuncompress')) {
$type[] = 'compress;q=0.5';
}
$type[] = 'gzip;q=0.5';
return implode(', ', $type);
}
/**
* Format a URL given GET data
*
* @param array $url_parts
* @param array|object $data Data to build query using, see {@see http://php.net/http_build_query}
* @return string URL with data
*/
protected static function format_get($url_parts, $data) {
if (!empty($data)) {
if (empty($url_parts['query']))
$url_parts['query'] = '';
$url_parts['query'] .= '&' . http_build_query($data, null, '&');
$url_parts['query'] = trim($url_parts['query'], '&');
}
if (isset($url_parts['path'])) {
if (isset($url_parts['query'])) {
$get = $url_parts['path'] . '?' . $url_parts['query'];
}
else {
$get = $url_parts['path'];
}
}
else {
$get = '/';
}
return $get;
}
/**
* Error handler for stream_socket_client()
*
* @param int $errno Error number (e.g. E_WARNING)
* @param string $errstr Error message
*/
public function connect_error_handler($errno, $errstr) {
// Double-check we can handle it
if (($errno & E_WARNING) === 0 && ($errno & E_NOTICE) === 0) {
// Return false to indicate the default error handler should engage
return false;
}
$this->connect_error .= $errstr . "\n";
return true;
}
/**
* Verify the certificate against common name and subject alternative names
*
* Unfortunately, PHP doesn't check the certificate against the alternative
* names, leading things like 'https://www.github.com/' to be invalid.
* Instead
*
* @see http://tools.ietf.org/html/rfc2818#section-3.1 RFC2818, Section 3.1
*
* @throws Requests_Exception On failure to connect via TLS (`fsockopen.ssl.connect_error`)
* @throws Requests_Exception On not obtaining a match for the host (`fsockopen.ssl.no_match`)
* @param string $host Host name to verify against
* @param resource $context Stream context
* @return bool
*/
public function verify_certificate_from_context($host, $context) {
$meta = stream_context_get_options($context);
// If we don't have SSL options, then we couldn't make the connection at
// all
if (empty($meta) || empty($meta['ssl']) || empty($meta['ssl']['peer_certificate'])) {
throw new Requests_Exception(rtrim($this->connect_error), 'ssl.connect_error');
}
$cert = openssl_x509_parse($meta['ssl']['peer_certificate']);
return Requests_SSL::verify_certificate($host, $cert);
}
/**
* Whether this transport is valid
*
* @codeCoverageIgnore
* @return boolean True if the transport is valid, false otherwise.
*/
public static function test() {
return function_exists('fsockopen');
}
}

View File

@@ -0,0 +1,91 @@
<?php
/**
* Case-insensitive dictionary, suitable for HTTP headers
*
* @package Requests
* @subpackage Utilities
*/
/**
* Case-insensitive dictionary, suitable for HTTP headers
*
* @package Requests
* @subpackage Utilities
*/
class Requests_Utility_CaseInsensitiveDictionary implements ArrayAccess, IteratorAggregate {
/**
* Actual item data
*
* @var array
*/
protected $data = array();
/**
* Check if the given item exists
*
* @param string $key Item key
* @return boolean Does the item exist?
*/
public function offsetExists($key) {
$key = strtolower($key);
return isset($this->data[$key]);
}
/**
* Get the value for the item
*
* @param string $key Item key
* @return string Item value
*/
public function offsetGet($key) {
$key = strtolower($key);
if (!isset($this->data[$key]))
return null;
return $this->data[$key];
}
/**
* Set the given item
*
* @throws Requests_Exception On attempting to use dictionary as list (`invalidset`)
*
* @param string $key Item name
* @param string $value Item value
*/
public function offsetSet($key, $value) {
if ($key === null) {
throw new Requests_Exception('Object is a dictionary, not a list', 'invalidset');
}
$key = strtolower($key);
$this->data[$key] = $value;
}
/**
* Unset the given header
*
* @param string $key
*/
public function offsetUnset($key) {
unset($this->data[strtolower($key)]);
}
/**
* Get an iterator for the data
*
* @return ArrayIterator
*/
public function getIterator() {
return new ArrayIterator($this->data);
}
/**
* Get the headers as an array
*
* @return array Header data
*/
public function getAll() {
return $this->data;
}
}

View File

@@ -0,0 +1,38 @@
<?php
/**
* Iterator for arrays requiring filtered values
*
* @package Requests
* @subpackage Utilities
*/
/**
* Iterator for arrays requiring filtered values
*
* @package Requests
* @subpackage Utilities
*/
class Requests_Utility_FilteredIterator extends ArrayIterator {
/**
* Create a new iterator
*
* @param array $data
* @param callable $callback Callback to be called on each value
*/
public function __construct($data, $callback) {
parent::__construct($data);
$this->callback = $callback;
}
/**
* Get the current item's value after filtering
*
* @return string
*/
public function current() {
$value = parent::current();
$value = call_user_func($this->callback, $value);
return $value;
}
}

View File

@@ -0,0 +1,805 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Converts to and from JSON format.
*
* JSON (JavaScript Object Notation) is a lightweight data-interchange
* format. It is easy for humans to read and write. It is easy for machines
* to parse and generate. It is based on a subset of the JavaScript
* Programming Language, Standard ECMA-262 3rd Edition - December 1999.
* This feature can also be found in Python. JSON is a text format that is
* completely language independent but uses conventions that are familiar
* to programmers of the C-family of languages, including C, C++, C#, Java,
* JavaScript, Perl, TCL, and many others. These properties make JSON an
* ideal data-interchange language.
*
* This package provides a simple encoder and decoder for JSON notation. It
* is intended for use with client-side Javascript applications that make
* use of HTTPRequest to perform server communication functions - data can
* be encoded into JSON notation for use in a client-side javascript, or
* decoded from incoming Javascript requests. JSON format is native to
* Javascript, and can be directly eval()'ed with no further parsing
* overhead
*
* All strings should be in ASCII or UTF-8 format!
*
* LICENSE: Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met: Redistributions of source code must retain the
* above copyright notice, this list of conditions and the following
* disclaimer. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* @category
* @package Services_JSON
* @author Michal Migurski <mike-json@teczno.com>
* @author Matt Knapp <mdknapp[at]gmail[dot]com>
* @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
* @copyright 2005 Michal Migurski
* @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $
* @license http://www.opensource.org/licenses/bsd-license.php
* @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
*/
/**
* Marker constant for Services_JSON::decode(), used to flag stack state
*/
define('SERVICES_JSON_SLICE', 1);
/**
* Marker constant for Services_JSON::decode(), used to flag stack state
*/
define('SERVICES_JSON_IN_STR', 2);
/**
* Marker constant for Services_JSON::decode(), used to flag stack state
*/
define('SERVICES_JSON_IN_ARR', 3);
/**
* Marker constant for Services_JSON::decode(), used to flag stack state
*/
define('SERVICES_JSON_IN_OBJ', 4);
/**
* Marker constant for Services_JSON::decode(), used to flag stack state
*/
define('SERVICES_JSON_IN_CMT', 5);
/**
* Behavior switch for Services_JSON::decode()
*/
define('SERVICES_JSON_LOOSE_TYPE', 16);
/**
* Behavior switch for Services_JSON::decode()
*/
define('SERVICES_JSON_SUPPRESS_ERRORS', 32);
/**
* Converts to and from JSON format.
*
* Brief example of use:
*
* <code>
* // create a new instance of Services_JSON
* $json = new Services_JSON();
*
* // convert a complexe value to JSON notation, and send it to the browser
* $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
* $output = $json->encode($value);
*
* print($output);
* // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
*
* // accept incoming POST data, assumed to be in JSON notation
* $input = file_get_contents('php://input', 1000000);
* $value = $json->decode($input);
* </code>
*/
class Services_JSON
{
/**
* constructs a new JSON instance
*
* @param int $use object behavior flags; combine with boolean-OR
*
* possible values:
* - SERVICES_JSON_LOOSE_TYPE: loose typing.
* "{...}" syntax creates associative arrays
* instead of objects in decode().
* - SERVICES_JSON_SUPPRESS_ERRORS: error suppression.
* Values which can't be encoded (e.g. resources)
* appear as NULL instead of throwing errors.
* By default, a deeply-nested resource will
* bubble up with an error, so all return values
* from encode() should be checked with isError()
*/
function Services_JSON($use = 0)
{
$this->use = $use;
}
/**
* convert a string from one UTF-16 char to one UTF-8 char
*
* Normally should be handled by mb_convert_encoding, but
* provides a slower PHP-only method for installations
* that lack the multibye string extension.
*
* @param string $utf16 UTF-16 character
* @return string UTF-8 character
* @access private
*/
function utf162utf8($utf16)
{
// oh please oh please oh please oh please oh please
if(function_exists('mb_convert_encoding')) {
return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
}
$bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
switch(true) {
case ((0x7F & $bytes) == $bytes):
// this case should never be reached, because we are in ASCII range
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr(0x7F & $bytes);
case (0x07FF & $bytes) == $bytes:
// return a 2-byte UTF-8 character
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr(0xC0 | (($bytes >> 6) & 0x1F))
. chr(0x80 | ($bytes & 0x3F));
case (0xFFFF & $bytes) == $bytes:
// return a 3-byte UTF-8 character
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr(0xE0 | (($bytes >> 12) & 0x0F))
. chr(0x80 | (($bytes >> 6) & 0x3F))
. chr(0x80 | ($bytes & 0x3F));
}
// ignoring UTF-32 for now, sorry
return '';
}
/**
* convert a string from one UTF-8 char to one UTF-16 char
*
* Normally should be handled by mb_convert_encoding, but
* provides a slower PHP-only method for installations
* that lack the multibye string extension.
*
* @param string $utf8 UTF-8 character
* @return string UTF-16 character
* @access private
*/
function utf82utf16($utf8)
{
// oh please oh please oh please oh please oh please
if(function_exists('mb_convert_encoding')) {
return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
}
switch(strlen($utf8)) {
case 1:
// this case should never be reached, because we are in ASCII range
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return $utf8;
case 2:
// return a UTF-16 character from a 2-byte UTF-8 char
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr(0x07 & (ord($utf8{0}) >> 2))
. chr((0xC0 & (ord($utf8{0}) << 6))
| (0x3F & ord($utf8{1})));
case 3:
// return a UTF-16 character from a 3-byte UTF-8 char
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr((0xF0 & (ord($utf8{0}) << 4))
| (0x0F & (ord($utf8{1}) >> 2)))
. chr((0xC0 & (ord($utf8{1}) << 6))
| (0x7F & ord($utf8{2})));
}
// ignoring UTF-32 for now, sorry
return '';
}
/**
* encodes an arbitrary variable into JSON format
*
* @param mixed $var any number, boolean, string, array, or object to be encoded.
* see argument 1 to Services_JSON() above for array-parsing behavior.
* if var is a strng, note that encode() always expects it
* to be in ASCII or UTF-8 format!
*
* @return mixed JSON string representation of input var or an error if a problem occurs
* @access public
*/
function encode($var)
{
switch (gettype($var)) {
case 'boolean':
return $var ? 'true' : 'false';
case 'NULL':
return 'null';
case 'integer':
return (int) $var;
case 'double':
case 'float':
return (float) $var;
case 'string':
// STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
$ascii = '';
$strlen_var = strlen($var);
/*
* Iterate over every character in the string,
* escaping with a slash or encoding to UTF-8 where necessary
*/
for ($c = 0; $c < $strlen_var; ++$c) {
$ord_var_c = ord($var{$c});
switch (true) {
case $ord_var_c == 0x08:
$ascii .= '\b';
break;
case $ord_var_c == 0x09:
$ascii .= '\t';
break;
case $ord_var_c == 0x0A:
$ascii .= '\n';
break;
case $ord_var_c == 0x0C:
$ascii .= '\f';
break;
case $ord_var_c == 0x0D:
$ascii .= '\r';
break;
case $ord_var_c == 0x22:
case $ord_var_c == 0x2F:
case $ord_var_c == 0x5C:
// double quote, slash, slosh
$ascii .= '\\'.$var{$c};
break;
case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
// characters U-00000000 - U-0000007F (same as ASCII)
$ascii .= $var{$c};
break;
case (($ord_var_c & 0xE0) == 0xC0):
// characters U-00000080 - U-000007FF, mask 110XXXXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c, ord($var{$c + 1}));
$c += 1;
$utf16 = $this->utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xF0) == 0xE0):
// characters U-00000800 - U-0000FFFF, mask 1110XXXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c,
ord($var{$c + 1}),
ord($var{$c + 2}));
$c += 2;
$utf16 = $this->utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xF8) == 0xF0):
// characters U-00010000 - U-001FFFFF, mask 11110XXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c,
ord($var{$c + 1}),
ord($var{$c + 2}),
ord($var{$c + 3}));
$c += 3;
$utf16 = $this->utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xFC) == 0xF8):
// characters U-00200000 - U-03FFFFFF, mask 111110XX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c,
ord($var{$c + 1}),
ord($var{$c + 2}),
ord($var{$c + 3}),
ord($var{$c + 4}));
$c += 4;
$utf16 = $this->utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xFE) == 0xFC):
// characters U-04000000 - U-7FFFFFFF, mask 1111110X
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c,
ord($var{$c + 1}),
ord($var{$c + 2}),
ord($var{$c + 3}),
ord($var{$c + 4}),
ord($var{$c + 5}));
$c += 5;
$utf16 = $this->utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
}
}
return '"'.$ascii.'"';
case 'array':
/*
* As per JSON spec if any array key is not an integer
* we must treat the the whole array as an object. We
* also try to catch a sparsely populated associative
* array with numeric keys here because some JS engines
* will create an array with empty indexes up to
* max_index which can cause memory issues and because
* the keys, which may be relevant, will be remapped
* otherwise.
*
* As per the ECMA and JSON specification an object may
* have any string as a property. Unfortunately due to
* a hole in the ECMA specification if the key is a
* ECMA reserved word or starts with a digit the
* parameter is only accessible using ECMAScript's
* bracket notation.
*/
// treat as a JSON object
if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
$properties = array_map(array($this, 'name_value'),
array_keys($var),
array_values($var));
foreach($properties as $property) {
if(Services_JSON::isError($property)) {
return $property;
}
}
return '{' . join(',', $properties) . '}';
}
// treat it like a regular array
$elements = array_map(array($this, 'encode'), $var);
foreach($elements as $element) {
if(Services_JSON::isError($element)) {
return $element;
}
}
return '[' . join(',', $elements) . ']';
case 'object':
$vars = get_object_vars($var);
$properties = array_map(array($this, 'name_value'),
array_keys($vars),
array_values($vars));
foreach($properties as $property) {
if(Services_JSON::isError($property)) {
return $property;
}
}
return '{' . join(',', $properties) . '}';
default:
return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS)
? 'null'
: new Services_JSON_Error(gettype($var)." can not be encoded as JSON string");
}
}
/**
* array-walking function for use in generating JSON-formatted name-value pairs
*
* @param string $name name of key to use
* @param mixed $value reference to an array element to be encoded
*
* @return string JSON-formatted name-value pair, like '"name":value'
* @access private
*/
function name_value($name, $value)
{
$encoded_value = $this->encode($value);
if(Services_JSON::isError($encoded_value)) {
return $encoded_value;
}
return $this->encode(strval($name)) . ':' . $encoded_value;
}
/**
* reduce a string by removing leading and trailing comments and whitespace
*
* @param $str string string value to strip of comments and whitespace
*
* @return string string value stripped of comments and whitespace
* @access private
*/
function reduce_string($str)
{
$str = preg_replace(array(
// eliminate single line comments in '// ...' form
'#^\s*//(.+)$#m',
// eliminate multi-line comments in '/* ... */' form, at start of string
'#^\s*/\*(.+)\*/#Us',
// eliminate multi-line comments in '/* ... */' form, at end of string
'#/\*(.+)\*/\s*$#Us'
), '', $str);
// eliminate extraneous space
return trim($str);
}
/**
* decodes a JSON string into appropriate variable
*
* @param string $str JSON-formatted string
*
* @return mixed number, boolean, string, array, or object
* corresponding to given JSON input string.
* See argument 1 to Services_JSON() above for object-output behavior.
* Note that decode() always returns strings
* in ASCII or UTF-8 format!
* @access public
*/
function decode($str)
{
$str = $this->reduce_string($str);
switch (strtolower($str)) {
case 'true':
return true;
case 'false':
return false;
case 'null':
return null;
default:
$m = array();
if (is_numeric($str)) {
// Lookie-loo, it's a number
// This would work on its own, but I'm trying to be
// good about returning integers where appropriate:
// return (float)$str;
// Return float or int, as appropriate
return ((float)$str == (integer)$str)
? (integer)$str
: (float)$str;
} elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
// STRINGS RETURNED IN UTF-8 FORMAT
$delim = substr($str, 0, 1);
$chrs = substr($str, 1, -1);
$utf8 = '';
$strlen_chrs = strlen($chrs);
for ($c = 0; $c < $strlen_chrs; ++$c) {
$substr_chrs_c_2 = substr($chrs, $c, 2);
$ord_chrs_c = ord($chrs{$c});
switch (true) {
case $substr_chrs_c_2 == '\b':
$utf8 .= chr(0x08);
++$c;
break;
case $substr_chrs_c_2 == '\t':
$utf8 .= chr(0x09);
++$c;
break;
case $substr_chrs_c_2 == '\n':
$utf8 .= chr(0x0A);
++$c;
break;
case $substr_chrs_c_2 == '\f':
$utf8 .= chr(0x0C);
++$c;
break;
case $substr_chrs_c_2 == '\r':
$utf8 .= chr(0x0D);
++$c;
break;
case $substr_chrs_c_2 == '\\"':
case $substr_chrs_c_2 == '\\\'':
case $substr_chrs_c_2 == '\\\\':
case $substr_chrs_c_2 == '\\/':
if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
($delim == "'" && $substr_chrs_c_2 != '\\"')) {
$utf8 .= $chrs{++$c};
}
break;
case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
// single, escaped unicode character
$utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
. chr(hexdec(substr($chrs, ($c + 4), 2)));
$utf8 .= $this->utf162utf8($utf16);
$c += 5;
break;
case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
$utf8 .= $chrs{$c};
break;
case ($ord_chrs_c & 0xE0) == 0xC0:
// characters U-00000080 - U-000007FF, mask 110XXXXX
//see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 2);
++$c;
break;
case ($ord_chrs_c & 0xF0) == 0xE0:
// characters U-00000800 - U-0000FFFF, mask 1110XXXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 3);
$c += 2;
break;
case ($ord_chrs_c & 0xF8) == 0xF0:
// characters U-00010000 - U-001FFFFF, mask 11110XXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 4);
$c += 3;
break;
case ($ord_chrs_c & 0xFC) == 0xF8:
// characters U-00200000 - U-03FFFFFF, mask 111110XX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 5);
$c += 4;
break;
case ($ord_chrs_c & 0xFE) == 0xFC:
// characters U-04000000 - U-7FFFFFFF, mask 1111110X
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 6);
$c += 5;
break;
}
}
return $utf8;
} elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
// array, or object notation
if ($str{0} == '[') {
$stk = array(SERVICES_JSON_IN_ARR);
$arr = array();
} else {
if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
$stk = array(SERVICES_JSON_IN_OBJ);
$obj = array();
} else {
$stk = array(SERVICES_JSON_IN_OBJ);
$obj = new stdClass();
}
}
array_push($stk, array('what' => SERVICES_JSON_SLICE,
'where' => 0,
'delim' => false));
$chrs = substr($str, 1, -1);
$chrs = $this->reduce_string($chrs);
if ($chrs == '') {
if (reset($stk) == SERVICES_JSON_IN_ARR) {
return $arr;
} else {
return $obj;
}
}
//print("\nparsing {$chrs}\n");
$strlen_chrs = strlen($chrs);
for ($c = 0; $c <= $strlen_chrs; ++$c) {
$top = end($stk);
$substr_chrs_c_2 = substr($chrs, $c, 2);
if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
// found a comma that is not inside a string, array, etc.,
// OR we've reached the end of the character list
$slice = substr($chrs, $top['where'], ($c - $top['where']));
array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
//print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
if (reset($stk) == SERVICES_JSON_IN_ARR) {
// we are in an array, so just push an element onto the stack
array_push($arr, $this->decode($slice));
} elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
// we are in an object, so figure
// out the property name and set an
// element in an associative array,
// for now
$parts = array();
if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
// "name":value pair
$key = $this->decode($parts[1]);
$val = $this->decode($parts[2]);
if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
$obj[$key] = $val;
} else {
$obj->$key = $val;
}
} elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
// name:value pair, where name is unquoted
$key = $parts[1];
$val = $this->decode($parts[2]);
if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
$obj[$key] = $val;
} else {
$obj->$key = $val;
}
}
}
} elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
// found a quote, and we are not inside a string
array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
//print("Found start of string at {$c}\n");
} elseif (($chrs{$c} == $top['delim']) &&
($top['what'] == SERVICES_JSON_IN_STR) &&
((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) {
// found a quote, we're in a string, and it's not escaped
// we know that it's not escaped becase there is _not_ an
// odd number of backslashes at the end of the string so far
array_pop($stk);
//print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
} elseif (($chrs{$c} == '[') &&
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
// found a left-bracket, and we are in an array, object, or slice
array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
//print("Found start of array at {$c}\n");
} elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
// found a right-bracket, and we're in an array
array_pop($stk);
//print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
} elseif (($chrs{$c} == '{') &&
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
// found a left-brace, and we are in an array, object, or slice
array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
//print("Found start of object at {$c}\n");
} elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
// found a right-brace, and we're in an object
array_pop($stk);
//print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
} elseif (($substr_chrs_c_2 == '/*') &&
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
// found a comment start, and we are in an array, object, or slice
array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
$c++;
//print("Found start of comment at {$c}\n");
} elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
// found a comment end, and we're in one now
array_pop($stk);
$c++;
for ($i = $top['where']; $i <= $c; ++$i)
$chrs = substr_replace($chrs, ' ', $i, 1);
//print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
}
}
if (reset($stk) == SERVICES_JSON_IN_ARR) {
return $arr;
} elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
return $obj;
}
}
}
}
/**
* @todo Ultimately, this should just call PEAR::isError()
*/
function isError($data, $code = null)
{
if (class_exists('pear')) {
return PEAR::isError($data, $code);
} elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
is_subclass_of($data, 'services_json_error'))) {
return true;
}
return false;
}
}
if (class_exists('PEAR_Error')) {
class Services_JSON_Error extends PEAR_Error
{
function Services_JSON_Error($message = 'unknown error', $code = null,
$mode = null, $options = null, $userinfo = null)
{
parent::PEAR_Error($message, $code, $mode, $options, $userinfo);
}
}
} else {
/**
* @todo Ultimately, this class shall be descended from PEAR_Error
*/
class Services_JSON_Error
{
function Services_JSON_Error($message = 'unknown error', $code = null,
$mode = null, $options = null, $userinfo = null)
{
}
}
}

View File

@@ -0,0 +1,250 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Simplexml
{
var $result = array();
var $ignore_level = 0;
var $skip_empty_values = false;
var $php_errormsg;
var $evalCode="";
function xml_parse($data)
{
$php_errormsg="";
$this->result="";
$this->evalCode="";
$values="";
$encoding = 'UTF-8';
$parser = xml_parser_create($encoding);
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
$ok = xml_parse_into_struct($parser, $data, $values);
if (!$ok) {
$errmsg = sprintf("XML parse error %d '%s' at line %d, column %d (byte index %d)",
xml_get_error_code($parser),
xml_error_string(xml_get_error_code($parser)),
xml_get_current_line_number($parser),
xml_get_current_column_number($parser),
xml_get_current_byte_index($parser));
}
xml_parser_free($parser);
return $this->xml_reorganize($values);
}
function xml_reorganize($array)
{
$count = count($array);
$repeat = $this->xml_tags($array);
$repeatedone = false;
$tags = array();
$k = 0;
for ($i = 0; $i < $count; $i++) {
switch ($array[$i]['type']) {
case 'open':
array_push($tags, $array[$i]['tag']);
if ($i > 0 && ($array[$i]['tag'] == $array[$i-1]['tag']) && ($array[$i-1]['type'] == 'close'))
$k++;
if (isset($array[$i]['value']) && ($array[$i]['value'] || !$this->skip_empty_values)) {
array_push($tags, '@content');
$this->array_insert(count($tags), $tags, $array[$i]['value'], "open");
array_pop($tags);
}
if (in_array($array[$i]['tag'] . $array[$i]['level'], $repeat)) {
if (($repeatedone == $array[$i]['tag'] . $array[$i]['level']) && ($repeatedone)) {
array_push($tags, strval($k++));
} else {
$repeatedone = $array[$i]['tag'] . $array[$i]['level'];
array_push($tags, strval($k));
}
}
if (isset($array[$i]['attributes']) && $array[$i]['attributes'] && $array[$i]['level'] != $this->ignore_level) {
array_push($tags, '@attributes');
foreach ($array[$i]['attributes'] as $attrkey => $attr) {
array_push($tags, $attrkey);
$this->array_insert(count($tags), $tags, $attr, "open");
array_pop($tags);
}
array_pop($tags);
}
break;
case 'close':
array_pop($tags);
if (in_array($array[$i]['tag'] . $array[$i]['level'], $repeat)) {
if ($repeatedone == $array[$i]['tag'] . $array[$i]['level']) {
array_pop($tags);
} else {
$repeatedone = $array[$i + 1]['tag'] . $array[$i + 1]['level'];
array_pop($tags);
}
}
break;
case 'complete':
array_push($tags, $array[$i]['tag']);
if (in_array($array[$i]['tag'] . $array[$i]['level'], $repeat)) {
if ($repeatedone == $array[$i]['tag'] . $array[$i]['level'] && $repeatedone) {
array_push($tags, strval($k));
} else {
$repeatedone = $array[$i]['tag'] . $array[$i]['level'];
array_push($tags, strval($k));
}
}
if (isset($array[$i]['value']) && ($array[$i]['value'] || !$this->skip_empty_values)) {
if (isset($array[$i]['attributes']) && $array[$i]['attributes']) {
array_push($tags, '@content');
$this->array_insert(count($tags), $tags, $array[$i]['value'], "complete");
array_pop($tags);
} else {
$this->array_insert(count($tags), $tags, $array[$i]['value'], "complete");
}
}
if (isset($array[$i]['attributes']) && $array[$i]['attributes']) {
array_push($tags, '@attributes');
foreach ($array[$i]['attributes'] as $attrkey => $attr) {
array_push($tags, $attrkey);
$this->array_insert(count($tags), $tags, $attr, "complete");
array_pop($tags);
}
array_pop($tags);
}
if (in_array($array[$i]['tag'] . $array[$i]['level'], $repeat)) {
array_pop($tags);
$k++;
}
array_pop($tags);
break;
}
}
eval($this->evalCode);
$last = $this->array_reindex($this->result);
return $last;
}
function array_insert($level, $tags, $value, $type)
{
$temp = '';
for ($c = $this->ignore_level + 1; $c < $level + 1; $c++) {
if (isset($tags[$c]) && (is_numeric(trim($tags[$c])) || trim($tags[$c]))) {
if (is_numeric($tags[$c])) {
$temp .= '[' . $tags[$c] . ']';
} else {
$temp .= '["' . $tags[$c] . '"]';
}
}
}
$this->evalCode .= '$this->result' . $temp . "=\"" . addslashes($value) . "\";//(" . $type . ")\n";
#echo $code. "\n";
}
/**
* Define the repeated tags in XML file so we can set an index
*
* @param array $array
* @return array
*/
function xml_tags($array)
{ $repeats_temp = array();
$repeats_count = array();
$repeats = array();
if (is_array($array)) {
$n = count($array) - 1;
for ($i = 0; $i < $n; $i++) {
$idn = $array[$i]['tag'].$array[$i]['level'];
if(in_array($idn,$repeats_temp)){
$repeats_count[array_search($idn,$repeats_temp)]+=1;
}else{
array_push($repeats_temp,$idn);
$repeats_count[array_search($idn,$repeats_temp)]=1;
}
}
}
$n = count($repeats_count);
for($i=0;$i<$n;$i++){
if($repeats_count[$i]>1){
array_push($repeats,$repeats_temp[$i]);
}
}
unset($repeats_temp);
unset($repeats_count);
return array_unique($repeats);
}
/**
* Converts Array Variable to Object Variable
*
* @param array $arg_array
* @return $tmp
*/
function array2object ($arg_array)
{
if (is_array($arg_array)) {
$keys = array_keys($arg_array);
if(!is_numeric($keys[0])) $tmp = new Xml;
foreach ($keys as $key) {
if (is_numeric($key)) $has_number = true;
if (is_string($key)) $has_string = true;
}
if (isset($has_number) and !isset($has_string)) {
foreach ($arg_array as $key => $value) {
$tmp[] = $this->array2object($value);
}
} elseif (isset($has_string)) {
foreach ($arg_array as $key => $value) {
if (is_string($key))
$tmp->$key = $this->array2object($value);
}
}
} elseif (is_object($arg_array)) {
foreach ($arg_array as $key => $value) {
if (is_array($value) or is_object($value))
$tmp->$key = $this->array2object($value);
else
$tmp->$key = $value;
}
} else {
$tmp = $arg_array;
}
return $tmp; //return the object
}
/**
* Reindexes the whole array with ascending numbers
*
* @param array $array
* @return array
*/
function array_reindex($array)
{
if (is_array($array)) {
if(count($array) == 1 && $array[0]){
return $this->array_reindex($array[0]);
}else{
foreach($array as $keys => $items) {
if (is_array($items)) {
if (is_numeric($keys)) {
$array[$keys] = $this->array_reindex($items);
} else {
$array[$keys] = $this->array_reindex(array_merge(array(), $items));
}
}
}
}
}
return $array;
}
}

View File

@@ -0,0 +1,182 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Userlib class
*/
/**
* user table 을 관리하는 class 입니다.
*/
class Userlib extends CI_Controller
{
private $CI;
private $mb;
private $uesr_group;
function __construct()
{
$this->CI = & get_instance();
$this->CI->load->model( array('User_model'));
$this->CI->load->helper( array('array'));
}
/**
* 접속한 유저가 회원인지 아닌지를 판단합니다
*/
public function is_user()
{
if ($this->CI->session->userdata('user_id')) {
return $this->CI->session->userdata('user_id');
} else {
return false;
}
}
/**
* 접속한 유저가 관리자인지 아닌지를 판단합니다
*/
public function is_admin($check = array())
{
if ($this->item('user_is_admin') == '1') {
return 'super';
}
if ($this->item('user_is_admin') == '2') {
return 'general';
}
return false;
}
/**
* user, user_meta 테이블에서 정보를 가져옵니다
*/
public function get_user()
{
if ($this->is_user()) {
if (empty($this->mb)) {
$user = $this->CI->User_model->get_by_id($this->is_user());
$metas = $this->get_all_meta(element('user_id', $user));
if (is_array($metas)) {
$user = array_merge($user, $metas);
}
$user['social'] = $this->get_all_social_meta(element('user_id', $user));
$this->mb = $user;
}
return $this->mb;
} else {
return false;
}
}
/**
* get_user 에서 가져온 데이터의 item 을 보여줍니다
*/
public function item($column = '')
{
if (empty($column)) {
return false;
}
if (empty($this->mb)) {
$this->get_user();
}
if (empty($this->mb)) {
return false;
}
$user = $this->mb;
return isset($user[$column]) ? $user[$column] : false;
}
/**
* get_user 에서 가져온 데이터의 item 을 보여줍니다
*/
public function socialitem($column = '')
{
if (empty($column)) {
return false;
}
if (empty($this->mb)) {
$this->get_user();
}
if (empty($this->mb)) {
return false;
}
$user = $this->mb;
return isset($user['social']) && isset($user['social'][$column]) ? $user['social'][$column] : false;
}
/**
* user_meta 테이블에서 가져옵니다
*/
public function get_all_meta($user_id = 0)
{
$user_id = (int) $user_id;
if (empty($user_id) OR $user_id < 1) {
return false;
}
$this->CI->load->model('User_meta_model');
$result = $this->CI->User_meta_model->get_all_meta($user_id);
return $result;
}
/**
* social_meta 테이블에서 가져옵니다
*/
public function get_all_social_meta($user_id = 0)
{
$user_id = (int) $user_id;
if (empty($user_id) OR $user_id < 1) {
return false;
}
if ($this->CI->db->table_exists('social_meta') === false) {
return;
}
$this->CI->load->model('Social_meta_model');
$result = $this->CI->Social_meta_model->get_all_meta($user_id);
return $result;
}
/**
* 회원삭제 남깁니다
*/
public function delete_user($user_id = 0)
{
$user_id = (int) $user_id;
if (empty($user_id) OR $user_id < 1) {
return false;
}
$this->CI->load->model(
array(
'User_model', 'User_auth_email_model',
'User_meta_model', 'Social_meta_model',
)
);
$deletewhere = array(
'user_id' => $user_id,
);
$this->CI->User_model->delete_where($deletewhere);
$this->CI->User_auth_email_model->delete_where($deletewhere);
$this->CI->User_meta_model->delete_where($deletewhere);
$this->CI->Social_meta_model->delete_where($deletewhere);
return true;
}
}

View File

@@ -0,0 +1,58 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Appinfo
*/
class Appinfo extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$this->CI->load->model(array('Apps_model'));
$where = array(
'app_id' => $app_id,
);
$result = $this->CI->Apps_model->get_one('', '', $where);
if ( ! element('app_id', $result)) {
$this->CI->apilib->make_error("존재하지 않는 어플입니다");
}
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'app_package' => html_escape(element('app_package', $result)),
'app_name' => html_escape(element('app_name', $result)),
'app_sort' => html_escape(element('app_sort', $result)),
'app_policy' => nl2br(html_escape(element('app_policy', $result))),
);
return $arr;
}
}

View File

@@ -0,0 +1,70 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Apprank
*/
class Apprank extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$this->CI->load->model(array('Apps_model'));
$where = array(
'app_id' => $app_id,
);
$result = $this->CI->Apps_model->get_one('', '', $where);
if ( ! element('app_id', $result)) {
$this->CI->apilib->make_error("존재하지 않는 어플입니다");
}
$apprank = json_decode($result['app_rank'], true);
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'app_rank_1_title' => html_escape(element('app_rank_1_title', $apprank)),
'app_rank_1_desc' => html_escape(element('app_rank_1_desc', $apprank)),
'app_rank_1_link' => html_escape(element('app_rank_1_link', $apprank)),
'app_rank_1_image_url' => thumb_url('apprank', element('app_rank_1_image_url', $apprank), '50', '50'),
'app_rank_2_title' => html_escape(element('app_rank_2_title', $apprank)),
'app_rank_2_desc' => html_escape(element('app_rank_2_desc', $apprank)),
'app_rank_2_link' => html_escape(element('app_rank_2_link', $apprank)),
'app_rank_2_image_url' => thumb_url('apprank', element('app_rank_2_image_url', $apprank), '50', '50'),
'app_rank_3_title' => html_escape(element('app_rank_3_title', $apprank)),
'app_rank_3_desc' => html_escape(element('app_rank_3_desc', $apprank)),
'app_rank_3_link' => html_escape(element('app_rank_3_link', $apprank)),
'app_rank_3_image_url' => thumb_url('apprank', element('app_rank_3_image_url', $apprank), '50', '50'),
);
return $arr;
}
}

View File

@@ -0,0 +1,88 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Category
*/
class Category extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$allowed_depth = array('1', '2', '3', '4');
$q = $this->CI->input->get('q');
$depth = $this->CI->input->get('depth');
if ($depth) {
if ( ! is_numeric($depth)) {
$this->CI->apilib->make_error('Depth 값이 잘못 넘어왔습니다. 값이 비어있든지, 1,2,3,4 중 하나의 값만 허용됩니다.');
}
if ( ! in_array($depth, $allowed_depth)) {
$this->CI->apilib->make_error('Depth 값이 잘못 넘어왔습니다. 값이 비어있든지, 1,2,3,4 중 하나의 값만 허용됩니다.');
}
}
$this->CI->load->model(array('Contents_category_model'));
if ($q) {
$this->CI->db->like('cat_name', $q);
}
if ($depth) {
$this->CI->db->where('cat_depth', $depth);
}
$this->CI->db->where('app_id', $app_id);
$this->CI->db->order_by('cat_sort', 'desc');
$qry = $this->CI->db->get('contents_category');
$data = $qry->result_array();
$count = 0;
$result = array();
if ($data) {
foreach ($data as $key => $val) {
$cinfo = $this->CI->Contents_category_model->get_hierarchical_name($app_id, element('cat_id', $val));
$result[$key]['cat1id'] = element('1', element('id', $cinfo));
$result[$key]['cat2id'] = element('2', element('id', $cinfo));
$result[$key]['cat1code'] = element('1', element('code', $cinfo));
$result[$key]['cat2code'] = element('2', element('code', $cinfo));
$result[$key]['cat1name'] = element('1', element('name', $cinfo));
$result[$key]['cat2name'] = element('2', element('name', $cinfo));
$count++;
}
}
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'count' => $count,
'list' => $result,
);
return $arr;
}
}

View File

@@ -0,0 +1,80 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Comment_delete
*/
class Comment_delete extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$con_id = (int) trim($this->CI->input->post('con_id'));
if (empty($con_id)) {
$this->CI->apilib->make_error("데이터 고유 아이디가 넘어오지 않았습니다");
}
$com_id = (int) trim($this->CI->input->post('com_id'));
if (empty($com_id)) {
$this->CI->apilib->make_error("댓글 고유 아이디가 넘어오지 않았습니다");
}
$this->CI->load->model(array('Contents_model', 'Contents_comment_model'));
$sessionuser = $this->CI->User_model->get_by_token($app_id, $token);
if ( ! element('user_id', $sessionuser)) {
$this->CI->apilib->make_error("로그인 한 회원만 댓글을 삭제할 수 있습니다");
}
$contents = $this->CI->Contents_model->get_one($con_id);
if ( ! element('con_id', $contents)) {
$this->CI->apilib->make_error("존재하지 않는 컨텐츠입니다.");
}
$comment = $this->CI->Contents_comment_model->get_one($com_id);
if ( ! element('com_id', $comment)) {
$this->CI->apilib->make_error("존재하지 않는 댓글입니다.");
}
if (element('user_id', $comment) != element('user_id', $sessionuser)) {
$this->CI->apilib->make_error("본인의 댓글만 삭제가 가능합니다.");
}
$this->CI->Contents_comment_model->delete($com_id);
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'con_id' => $con_id,
'com_id' => $com_id,
'datetime' => cdate('Y-m-d H:i:s'),
);
return $arr;
}
}

View File

@@ -0,0 +1,88 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Comment_list
*/
class Comment_list extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$con_id = (int) trim($this->CI->input->get('con_id'));
if (empty($con_id)) {
$this->CI->apilib->make_error("데이터 고유 아이디가 넘어오지 않았습니다");
}
$this->CI->load->model(array('Contents_model', 'Contents_comment_model'));
$sessionuser = $this->CI->User_model->get_by_token($app_id, $token);
if ( ! element('user_id', $sessionuser)) {
//$this->CI->apilib->make_error("로그인 한 회원만 댓글을 보실 수 있습니다");
}
$contents = $this->CI->Contents_model->get_one($con_id);
if ( ! element('con_id', $contents)) {
$this->CI->apilib->make_error("존재하지 않는 컨텐츠입니다.");
}
$data = $this->CI->Contents_comment_model->get_api_list($app_id, $con_id);
$result = array();
$count = 0;
if ($data) {
foreach ($data as $key => $value) {
$result[$key]['com_id'] = html_escape(element('com_id', $value));
$result[$key]['con_id'] = html_escape(element('con_id', $value));
$result[$key]['user_id'] = html_escape(element('user_id', $value));
$result[$key]['user_name'] = html_escape(element('user_username', $value));
$result[$key]['user_photo'] = user_photo_url(element('user_photo', $value));
$result[$key]['com_content'] = html_escape(element('com_content', $value));
$result[$key]['com_created_at'] = html_escape(element('com_created_at', $value));
$result[$key]['com_updated_at'] = html_escape(element('com_updated_at', $value));
$result[$key]['com_reply_user_userid'] = '';
if (element('com_reply_user_id', $value)) {
$reply_user = $this->CI->User_model->get_one(element('com_reply_user_id', $value), 'user_userid');
$result[$key]['com_reply_user_userid'] = element('user_userid', $reply_user);
}
$count++;
}
}
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'count' => $count,
'list' => $result,
);
return $arr;
}
}

View File

@@ -0,0 +1,174 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Comment_write
*/
class Comment_write extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$con_id = (int) trim($this->CI->input->post('con_id'));
if (empty($con_id)) {
$this->CI->apilib->make_error("데이터 고유 아이디가 넘어오지 않았습니다");
}
$com_id = (int) trim($this->CI->input->post('com_id'));
$this->CI->load->model(array('Contents_model', 'Contents_comment_model'));
$sessionuser = $this->CI->User_model->get_by_token($app_id, $token);
if ( ! element('user_id', $sessionuser)) {
$this->CI->apilib->make_error("로그인 한 회원만 댓글을 입력할 수 있습니다");
}
$contents = $this->CI->Contents_model->get_one($con_id);
if ( ! element('con_id', $contents)) {
$this->CI->apilib->make_error("존재하지 않는 컨텐츠입니다.");
}
$reply_com_id = (int) trim($this->CI->input->post('reply_com_id'));
$com_content = trim($this->CI->input->post('com_content'));
if (empty($com_content)) {
$this->CI->apilib->make_error("댓글 내용이 입력되지 않았습니다");
}
// mode : new, modify, reply
$mode = 'new';
if ($com_id) {
$mode = 'modify';
}
else if ($reply_com_id) {
$mode = 'reply';
}
$comment = '';
if ($mode == 'modify') {
$comment = $this->CI->Contents_comment_model->get_one($com_id);
if ( ! element('com_id', $comment)) {
$this->CI->apilib->make_error("존재하지 않는 댓글입니다.");
}
if (element('user_id', $comment) != element('user_id', $sessionuser)) {
$this->CI->apilib->make_error("본인의 댓글만 수정이 가능합니다.");
}
}
$com_reply = '';
if ($mode == 'reply') {
$origin = $this->CI->Contents_comment_model->get_one($reply_com_id);
if ( ! element('com_id', $origin)) {
$this->CI->apilib->make_error("존재하지 않는 댓글에 답변을 달려고 시도하고 있습니다");
}
//if (element('com_reply', $origin)) {
// $this->CI->apilib->make_error("답변댓글에는 더 이상 답변댓글을 입력하실 수가 없습니다");
//}
$reply_len = strlen(element('com_reply', $origin)) + 1;
$begin_reply_char = 'A';
$end_reply_char = 'Z';
$reply_number = +1;
$this->CI->db->select('MAX(SUBSTRING(com_reply, ' . $reply_len . ', 1)) as reply', false);
$this->CI->db->where('com_num', element('com_num', $origin));
$this->CI->db->where('SUBSTRING(com_reply, ' . $reply_len . ', 1) <>', '');
if (element('com_id', $origin)) {
$this->CI->db->like('com_reply', element('com_reply', $origin), 'after');
}
$result = $this->CI->db->get('contents_comment');
$row = $result->row_array();
if ( ! element('reply', $row)) {
$reply_char = $begin_reply_char;
} elseif (element('reply', $row) === $end_reply_char) { // A~Z은 26 입니다.
$this->CI->apilib->make_error("더 이상 답변하실 수 없습니다.\\n답변은 26개 까지만 가능합니다");
} else {
$reply_char = chr(ord(element('reply', $row)) + $reply_number);
}
$com_reply = element('com_reply', $origin) . $reply_char;
$com_reply_user_id = element('user_id', $origin);
}
if ($mode == 'new') {
$com_num = $this->CI->Contents_comment_model->next_comment_num();
$insertdata = array(
'con_id' => $con_id,
'app_id' => $app_id,
'con_user_id' => element('user_id', $contents),
'user_id' => element('user_id', $sessionuser),
'com_num' => $com_num,
'com_reply' => '',
'com_content' => $com_content,
'com_created_at' => cdate('Y-m-d H:i:s'),
'com_updated_at' => cdate('Y-m-d H:i:s'),
);
$com_id = $this->CI->Contents_comment_model->insert($insertdata);
}
else if ($mode == 'reply') {
$com_num = element('com_num', $origin);
$insertdata = array(
'con_id' => $con_id,
'app_id' => $app_id,
'con_user_id' => element('user_id', $contents),
'user_id' => element('user_id', $sessionuser),
'com_num' => $com_num,
'com_reply' => $com_reply,
'com_reply_user_id' => $com_reply_user_id,
'com_content' => $com_content,
'com_created_at' => cdate('Y-m-d H:i:s'),
'com_updated_at' => cdate('Y-m-d H:i:s'),
);
$com_id = $this->CI->Contents_comment_model->insert($insertdata);
}
else if ($mode == 'modify') {
$updatedata = array(
'com_content' => $com_content,
'com_updated_at' => cdate('Y-m-d H:i:s'),
);
$this->CI->Contents_comment_model->update($com_id, $updatedata);
}
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'con_id' => $con_id,
'com_id' => $com_id,
);
return $arr;
}
}

View File

@@ -0,0 +1,108 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Contents
*/
class Contents extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$sessionuser = $this->CI->User_model->get_by_token($app_id, $token);
$this->CI->load->model(array('Contents_model', 'Contents_category_model', 'Contents_comment_model', 'Contents_like_model', 'Upload_file_model'));
$category = $this->CI->Contents_category_model->cat_list($app_id);
$cat1_id = $this->CI->input->get('cat1_id');
$cat2_id = $this->CI->input->get('cat2_id');
$cat3_id = $this->CI->input->get('cat3_id');
$cat4_id = $this->CI->input->get('cat4_id');
$tag = $this->CI->input->get('tag');
$sort = $this->CI->input->get('sort');
$is_bookmark = $this->CI->input->get('is_bookmark') == 'Y' ? '1' : '';
if ($sort == 'H') {
$data = $this->CI->Contents_model->get_api_popular_list($app_id, $is_bookmark, element('user_id', $sessionuser), $tag, $cat1_id, $cat2_id);
} else {
$data = $this->CI->Contents_model->get_api_list($app_id, $is_bookmark, element('user_id', $sessionuser), $tag, $cat1_id, $cat2_id);
}
$result = array();
$count = 0;
if ($data) {
foreach ($data as $key => $value) {
$result[$key]['con_id'] = html_escape(element('con_id', $value));
$result[$key]['con_sort'] = html_escape(element('con_sort', $value));
$result[$key]['cat1_id'] = html_escape(element('cat1_id', $value));
$result[$key]['cat2_id'] = html_escape(element('cat2_id', $value));
$result[$key]['cat3_id'] = html_escape(element('cat3_id', $value));
$result[$key]['cat4_id'] = html_escape(element('cat4_id', $value));
$result[$key]['cat1_code'] = element('cat1_id', $value) ? html_escape(element('cat_code', element(element('cat1_id', $value), $category))) : null;
$result[$key]['cat2_code'] = element('cat2_id', $value) ? html_escape(element('cat_code', element(element('cat2_id', $value), $category))) : null;
$result[$key]['cat3_code'] = element('cat3_id', $value) ? html_escape(element('cat_code', element(element('cat3_id', $value), $category))) : null;
$result[$key]['cat4_code'] = element('cat4_id', $value) ? html_escape(element('cat_code', element(element('cat4_id', $value), $category))) : null;
$result[$key]['cat1_name'] = element('cat1_id', $value) ? html_escape(element('cat_name', element(element('cat1_id', $value), $category))) : null;
$result[$key]['cat2_name'] = element('cat2_id', $value) ? html_escape(element('cat_name', element(element('cat2_id', $value), $category))) : null;
$result[$key]['cat3_name'] = element('cat3_id', $value) ? html_escape(element('cat_name', element(element('cat3_id', $value), $category))) : null;
$result[$key]['cat4_name'] = element('cat4_id', $value) ? html_escape(element('cat_name', element(element('cat4_id', $value), $category))) : null;
$result[$key]['user_id'] = html_escape(element('user_id', $value));
$result[$key]['user_name'] = html_escape(element('user_name', $value));
$result[$key]['con_title'] = html_escape(element('con_title', $value));
$result[$key]['con_content'] = html_escape('<meta name="viewport" content="width=320"><style>img, table {max-width:100% !important;}</style>'. element('con_content', $value));
$result[$key]['con_published_at'] = html_escape(element('con_published_at', $value));
$cwhere = array(
'app_id' => $app_id,
'con_id' => element('con_id', $value),
);
$result[$key]['comment_count'] = $this->CI->Contents_comment_model->count_by($cwhere);
$result[$key]['like_count'] = element('con_like', $value);
$result[$key]['share_count'] = element('con_share_count', $value);
$result[$key]['share_url'] = site_url('contents/view/'.element('con_id', $value));
$result[$key]['cnt'] = element('cnt', $value);
$filedata = array();
$files = $this->CI->Upload_file_model->get_files('contents', element('con_id', $value));
if ($files) {
foreach ($files as $fkey => $fval) {
$filedata[$fkey]['url'] = base_url('uploads/files/' . element('ufi_filename', $fval));
}
}
$result[$key]['files'] = $filedata;
$count++;
}
}
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'count' => $count,
'list' => $result,
);
return $arr;
}
}

View File

@@ -0,0 +1,67 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Contents_add_share_count
*/
class Contents_add_share_count extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$con_id = (int) trim($this->CI->input->post_get('con_id'));
if (empty($con_id)) {
$this->CI->apilib->make_error("데이터 고유 아이디가 넘어오지 않았습니다");
}
$this->CI->load->model(array('Contents_model', 'User_model'));
$sessionuser = $this->CI->User_model->get_by_token($app_id, $token);
//if ( ! element('user_id', $sessionuser)) {
// $this->CI->apilib->make_error("로그인 한 회원만 Like 할 수 있습니다");
//}
$contents = $this->CI->Contents_model->get_one($con_id);
if ( ! element('con_id', $contents)) {
$this->CI->apilib->make_error("존재하지 않는 컨텐츠입니다.");
}
$this->CI->Contents_model->update_share_count(element('con_id', $contents));
$share_count = element('con_share_count', $contents) + 1;
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'con_id' => $con_id,
'share_count' => $share_count,
);
return $arr;
}
}

View File

@@ -0,0 +1,90 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Contents_bookmark
*/
class Contents_bookmark extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$con_id = (int) trim($this->CI->input->post('con_id'));
if (empty($con_id)) {
$this->CI->apilib->make_error("데이터 고유 아이디가 넘어오지 않았습니다");
}
$this->CI->load->model(array('Contents_model', 'User_model', 'Contents_bookmark_model'));
$sessionuser = $this->CI->User_model->get_by_token($app_id, $token);
if ( ! element('user_id', $sessionuser)) {
$this->CI->apilib->make_error("로그인 한 회원만 북마크 할 수 있습니다");
}
$contents = $this->CI->Contents_model->get_one($con_id);
if ( ! element('con_id', $contents)) {
$this->CI->apilib->make_error("존재하지 않는 컨텐츠입니다.");
}
$bookmarkwhere = array(
'con_id' => $con_id,
'user_id' => element('user_id', $sessionuser),
);
$bookmark = $this->CI->Contents_bookmark_model->get_one('', '', $bookmarkwhere);
if (element('bookmark_id', $bookmark)) {
$this->CI->Contents_bookmark_model->delete(element('bookmark_id', $bookmark));
$type = 'N';
}
if ( ! element('bookmark_id', $bookmark)) {
$insertdata = array(
'con_id' => element('con_id', $contents),
'app_id' => $app_id,
'user_id' => element('user_id', $sessionuser),
'target_user_id' => element('user_id', $contents),
'bookmark_at' => cdate('Y-m-d H:i:s'),
);
$bookmark_id = $this->CI->Contents_bookmark_model->insert($insertdata);
$type = 'Y';
}
$cwhere = array(
'con_id' => element('con_id', $contents),
);
$bookmark_count = $this->CI->Contents_bookmark_model->count_by($cwhere);
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'con_id' => $con_id,
'type' => $type,
'bookmark_count' => $bookmark_count,
);
return $arr;
}
}

View File

@@ -0,0 +1,97 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Contents_get_count
*/
class Contents_get_count extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$sessionuser = $this->CI->User_model->get_by_token($app_id, $token);
$this->CI->load->model(array('Contents_model', 'Contents_category_model', 'Contents_comment_model', 'Contents_like_model', 'Upload_file_model'));
$category = $this->CI->Contents_category_model->cat_list($app_id);
$data = $this->CI->Contents_model->get_api_list($app_id, '', '', '', '', '', '1');
$result = array();
$count = 0;
if ($data) {
foreach ($data as $key => $value) {
$result[$key]['con_id'] = html_escape(element('con_id', $value));
$result[$key]['con_sort'] = html_escape(element('con_sort', $value));
$result[$key]['cat1_id'] = html_escape(element('cat1_id', $value));
$result[$key]['cat2_id'] = html_escape(element('cat2_id', $value));
$result[$key]['cat3_id'] = html_escape(element('cat3_id', $value));
$result[$key]['cat4_id'] = html_escape(element('cat4_id', $value));
$result[$key]['cat1_code'] = element('cat1_id', $value) ? html_escape(element('cat_code', element(element('cat1_id', $value), $category))) : null;
$result[$key]['cat2_code'] = element('cat2_id', $value) ? html_escape(element('cat_code', element(element('cat2_id', $value), $category))) : null;
$result[$key]['cat3_code'] = element('cat3_id', $value) ? html_escape(element('cat_code', element(element('cat3_id', $value), $category))) : null;
$result[$key]['cat4_code'] = element('cat4_id', $value) ? html_escape(element('cat_code', element(element('cat4_id', $value), $category))) : null;
$result[$key]['cat1_name'] = element('cat1_id', $value) ? html_escape(element('cat_name', element(element('cat1_id', $value), $category))) : null;
$result[$key]['cat2_name'] = element('cat2_id', $value) ? html_escape(element('cat_name', element(element('cat2_id', $value), $category))) : null;
$result[$key]['cat3_name'] = element('cat3_id', $value) ? html_escape(element('cat_name', element(element('cat3_id', $value), $category))) : null;
$result[$key]['cat4_name'] = element('cat4_id', $value) ? html_escape(element('cat_name', element(element('cat4_id', $value), $category))) : null;
$result[$key]['user_id'] = html_escape(element('user_id', $value));
$result[$key]['user_name'] = html_escape(element('user_name', $value));
$result[$key]['con_title'] = html_escape(element('con_title', $value));
$result[$key]['con_content'] = html_escape(element('con_content', $value));
$result[$key]['con_published_at'] = html_escape(element('con_published_at', $value));
$cwhere = array(
'app_id' => $app_id,
'con_id' => element('con_id', $value),
);
$result[$key]['comment_count'] = $this->CI->Contents_comment_model->count_by($cwhere);
$result[$key]['like_count'] = $this->CI->Contents_like_model->count_by($cwhere);
$result[$key]['share_count'] = element('con_share_count', $value);
$result[$key]['share_url'] = site_url('contents/view/'.element('con_id', $value));
$result[$key]['cnt'] = element('cnt', $value);
$filedata = array();
$files = $this->CI->Upload_file_model->get_files('contents', element('con_id', $value));
if ($files) {
foreach ($files as $fkey => $fval) {
$filedata[$fkey]['url'] = base_url('uploads/files/' . element('ufi_filename', $fval));
}
}
$result[$key]['files'] = $filedata;
$count++;
}
}
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'count' => $count,
'list' => $result,
);
return $arr;
}
}

View File

@@ -0,0 +1,92 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Contents_like
*/
class Contents_like extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$con_id = (int) trim($this->CI->input->post('con_id'));
if (empty($con_id)) {
$this->CI->apilib->make_error("데이터 고유 아이디가 넘어오지 않았습니다");
}
$this->CI->load->model(array('Contents_model', 'User_model', 'Contents_like_model'));
$sessionuser = $this->CI->User_model->get_by_token($app_id, $token);
//if ( ! element('user_id', $sessionuser)) {
// $this->CI->apilib->make_error("로그인 한 회원만 Like 할 수 있습니다");
//}
$contents = $this->CI->Contents_model->get_one($con_id);
if ( ! element('con_id', $contents)) {
$this->CI->apilib->make_error("존재하지 않는 컨텐츠입니다.");
}
$likewhere = array(
'con_id' => $con_id,
'user_token' => $token,
);
$like = $this->CI->Contents_like_model->get_one('', '', $likewhere);
if (element('like_id', $like)) {
$this->CI->Contents_like_model->delete(element('like_id', $like));
$type = 'N';
$this->CI->Contents_model->minus_like_count($con_id);
$like_count = element('con_like', $contents) - 1;
}
if ( ! element('like_id', $like)) {
$user_id = element('user_id', $sessionuser) ? element('user_id', $sessionuser) : 0;
$insertdata = array(
'con_id' => element('con_id', $contents),
'app_id' => $app_id,
'user_id' => $user_id,
'user_token' => $token,
'target_user_id' => element('user_id', $contents),
'like_at' => cdate('Y-m-d H:i:s'),
);
$like_id = $this->CI->Contents_like_model->insert($insertdata);
$type = 'Y';
$this->CI->Contents_model->plus_like_count($con_id);
$like_count = element('con_like', $contents) + 1;
}
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'con_id' => $con_id,
'type' => $type,
'like_count' => $like_count,
);
return $arr;
}
}

View File

@@ -0,0 +1,137 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Contents_view
*/
class Contents_view extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$con_id = (int) trim($this->CI->input->get('con_id'));
if (empty($con_id)) {
$this->CI->apilib->make_error("데이터 고유 아이디가 넘어오지 않았습니다");
}
$this->CI->load->model(array('Contents_model', 'Contents_category_model', 'Contents_comment_model', 'Contents_like_model', 'Upload_file_model', 'Contents_bookmark_model'));
$sessionuser = $this->CI->User_model->get_by_token($app_id, $token);
$where = array(
'app_id' => $app_id,
'con_id' => $con_id,
'is_open' => '1',
'is_del' => '0',
'con_published_at <=' => cdate('Y-m-d H:i:s'),
);
$result = $this->CI->Contents_model->get_one('', '', $where);
if ( ! element('con_id', $result)) {
$this->CI->apilib->make_error("존재하지 않는 데이터입니다");
}
if ( ! element('con_published_at', $result)) {
$this->CI->apilib->make_error("존재하지 않는 데이터입니다");
}
if ( ! $this->CI->session->userdata('con_hit_' . element('con_id', $result))) {
$this->CI->session->set_userdata('con_hit_' . element('con_id', $result), '1');
$this->CI->Contents_model->update_plus(element('con_id', $result), 'con_hit', '1');
}
$category = $this->CI->Contents_category_model->cat_list($app_id);
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'con_id' => html_escape(element('con_id', $result)),
'con_sort' => html_escape(element('con_sort', $result)),
'cat1_id' => html_escape(element('cat1_id', $result)),
'cat2_id' => html_escape(element('cat2_id', $result)),
'cat3_id' => html_escape(element('cat3_id', $result)),
'cat4_id' => html_escape(element('cat4_id', $result)),
'user_id' => html_escape(element('user_id', $result)),
'user_name' => html_escape(element('user_name', $result)),
'con_title' => html_escape(element('con_title', $result)),
'con_content' => nl2br(html_escape('<meta name="viewport" content="width=320"><style>img, table {max-width:100% !important;}</style>'. element('con_content', $result))),
'con_published_at' => html_escape(element('con_published_at', $result)),
);
$arr['cat1_code'] = element('cat1_id', $result) ? html_escape(element('cat_code', element(element('cat1_id', $result), $category))) : null;
$arr['cat2_code'] = element('cat2_id', $result) ? html_escape(element('cat_code', element(element('cat2_id', $result), $category))) : null;
$arr['cat3_code'] = element('cat3_id', $result) ? html_escape(element('cat_code', element(element('cat3_id', $result), $category))) : null;
$arr['cat4_code'] = element('cat4_id', $result) ? html_escape(element('cat_code', element(element('cat4_id', $result), $category))) : null;
$arr['cat1_name'] = element('cat1_id', $result) ? html_escape(element('cat_name', element(element('cat1_id', $result), $category))) : null;
$arr['cat2_name'] = element('cat2_id', $result) ? html_escape(element('cat_name', element(element('cat2_id', $result), $category))) : null;
$arr['cat3_name'] = element('cat3_id', $result) ? html_escape(element('cat_name', element(element('cat3_id', $result), $category))) : null;
$arr['cat4_name'] = element('cat4_id', $result) ? html_escape(element('cat_name', element(element('cat4_id', $result), $category))) : null;
$cwhere = array(
'app_id' => $app_id,
'con_id' => element('con_id', $result),
);
$arr['comment_count'] = $this->CI->Contents_comment_model->count_by($cwhere);
//$arr['like_count'] = $this->CI->Contents_like_model->count_by($cwhere);
$arr['like_count'] = element('con_like', $result);
$arr['share_count'] = element('con_share_count', $result);
$arr['share_url'] = site_url('contents/view/'.element('con_id', $result));
$filedata = array();
$files = $this->CI->Upload_file_model->get_files('contents', element('con_id', $result));
if ($files) {
foreach ($files as $fkey => $fval) {
$filedata[$fkey]['url'] = base_url('uploads/files/' . element('ufi_filename', $fval));
}
}
$arr['files'] = $filedata;
$where = array(
'app_id' => $app_id,
'con_id' => $con_id,
'user_token' => $token
);
$like = $this->CI->Contents_like_model->get_one('', '', $where);
$arr['i_like'] = (element('like_id', $like)) ? 1 : 0;
if (element('user_id', $sessionuser)) {
$where = array(
'app_id' => $app_id,
'con_id' => $con_id,
'user_id' => element('user_id', $sessionuser)
);
$bookmark = $this->CI->Contents_bookmark_model->get_one('', '', $where);
$arr['i_bookmark'] = (element('bookmark_id', $bookmark)) ? 1 : 0;
} else {
$arr['i_bookmark'] = 0;
}
return $arr;
}
}

View File

@@ -0,0 +1,109 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Find_my_password
*/
class Find_my_password extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
$this->CI->load->library(array('email'));
}
function main()
{
$this->CI->load->model('Apps_model');
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$email = trim($this->CI->input->post('email'));
if ( ! $email) {
$this->CI->apilib->make_error("이메일이 입력되지 않았습니다");
}
$this->CI->load->helper('string');
if ( ! function_exists('password_hash')) {
$this->CI->load->helper('password');
}
$userinfo = $this->CI->User_model->get_by_api_email($app_id, $email, 'user_id, user_email, user_denied, user_username, user_password');
if (element('user_denied', $userinfo)) {
$this->CI->apilib->make_error("회원님의 아이디는 접근이 금지된 아이디입니다");
}
if ( ! element('user_id', $userinfo)) {
$this->CI->apilib->make_error("일치하는 회원정보가 없습니다");
}
$user_id = element('user_id', $userinfo);
$new_password = rand(100000,999999);
$hash = password_hash($new_password, PASSWORD_BCRYPT);
$updatedata = array(
'user_password' => $hash,
);
$upwhere = array(
'app_id' => $app_id,
'user_id' => $user_id,
);
$this->CI->User_model->update('', $updatedata, $upwhere);
$appinfo = $this->CI->Apps_model->get_one($app_id);
$email_title = '[' . element('app_name', $appinfo) . '] 회원님의 패스워드가 변경되었습니다.';
$email_content = '<table width="100%" cellpadding="0" cellspacing="0" style="border-left: 1px solid rgb(226,226,225);border-right: 1px solid rgb(226,226,225);background-color: rgb(255,255,255);border-top:10px solid #348fe2; border-bottom:5px solid #348fe2;border-collapse: collapse;"><tbody><tr><td width="200" style="padding:20px 30px;font-family: Arial,sans-serif;color: rgb(0,0,0);font-size: 14px;line-height: 20px;">' . element('app_name', $appinfo) . '</td><td style="font-size:12px;padding:20px 30px;font-family: Arial,sans-serif;color: rgb(0,0,0);font-size: 14px;line-height: 20px;"><span style="font-size:14px;font-weight:bold;color:rgb(0,0,0)">안녕하세요 ' . html_escape(element('user_username', $userinfo)) . '님,</span><br>회원님의 패스워드 변경</td></tr><tr style="border-top:1px solid #e2e2e2; border-bottom:1px solid #e2e2e2;"><td colspan="2" style="padding:20px 30px;font-family: Arial,sans-serif;color: rgb(0,0,0);font-size: 14px;line-height: 20px;"><p>' . html_escape(element('user_username', $userinfo)) . '님, 안녕하세요!</p><p>&nbsp;</p><p>회원님의 패스워드가 변경되었습니다.</p><p>변경된 패스워드는 다음과 같습니다</p><p style="color:red;font-weight:bold;">' . $new_password . '</p><p>&nbsp;</p><p>감사합니다.</p></td></tr></tbody></table>';
include_once(FCPATH . 'plugin/PHPMailer/PHPMailerAutoload.php');
$mail = new PHPMailer;
$mail->SMTPDebug = 0; // Enable verbose debug output
$mail->CharSet = "euc-kr";
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = config_item('email_smtp_host'); // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = config_item('email_smtp_user'); // SMTP username
$mail->Password = config_item('email_smtp_pass'); // SMTP password
$mail->SMTPSecure = 'ssl'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 465; // TCP port to connect to
$mail->setFrom(config_item('email_smtp_user'), iconv("UTF-8", "EUC-KR", element('app_name', $appinfo)));
$mail->addAddress($email, element('user_username', $userinfo)); // Add a recipient
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = iconv("UTF-8", "EUC-KR", $email_title);
$mail->Body = iconv("UTF-8", "EUC-KR", $email_content);
if(!$mail->send()) {
$this->CI->apilib->make_error("메일을 발송할 수가 없습니다");
//echo 'Mailer Error: ' . $mail->ErrorInfo;
}
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'user_id' => element('user_id', $userinfo),
'user_email' => element('user_email', $userinfo),
);
return $arr;
}
}

View File

@@ -0,0 +1,95 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Login
*/
class Login extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$sessionuser = $this->CI->User_model->get_by_token($app_id, $token);
$this->CI->load->helper('email');
if ( ! $this->CI->input->post('user_email')) {
$this->CI->apilib->make_error("회원 이메일이 입력되지 않았습니다");
}
if ( ! valid_email($this->CI->input->post('user_email')) ) {
$this->CI->apilib->make_error("이메일이 형식에 맞지 않습니다.");
}
if ( ! $this->CI->input->post('user_password')) {
$this->CI->apilib->make_error("비밀번호를 입력해주십시오.");
}
if ( ! $this->CI->input->post('fcm_token')) {
//$this->CI->apilib->make_error("fcm_token 값이 입력되지 않았습니다");
}
$user_email = trim($this->CI->input->post('user_email'));
$user_password = trim($this->CI->input->post('user_password'));
$userinfo = $this->CI->User_model->get_by_api_email($app_id, $user_email, 'user_id, user_email, user_denied, user_password');
$hash = password_hash($user_password, PASSWORD_BCRYPT);
if ( ! element('user_id', $userinfo) OR ! element('user_password', $userinfo)) {
$this->CI->apilib->make_error("회원 아이디와 비밀번호가 일치하지 않습니다.");
} elseif ( ! password_verify($user_password, element('user_password', $userinfo))) {
$this->CI->apilib->make_error("회원 아이디와 비밀번호가 일치하지 않습니다.");
} elseif (element('user_denied', $userinfo)) {
$this->CI->apilib->make_error("회원님의 아이디는 접근이 금지된 아이디입니다");
}
$updatedata = array(
'user_token' => '',
);
$upwhere = array(
'user_token' => $token,
);
$this->CI->User_model->update('', $updatedata, $upwhere);
$updatedata = array(
'user_token' => $token,
'user_lastlogin_datetime' => cdate('Y-m-d H:i:s'),
);
$this->CI->User_model->update(element('user_id', $userinfo), $updatedata);
//fcm token 등록하기
if ($this->CI->input->post('fcm_token')) {
$this->CI->load->library('Fcm_library');
$this->CI->fcm_library->update_token(element('user_id', $userinfo), $this->CI->input->post('fcm_token'));
}
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'user_id' => element('user_id', $userinfo),
);
return $arr;
}
}

View File

@@ -0,0 +1,57 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Logout
*/
class Logout extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$sessionuser = $this->CI->User_model->get_by_token($app_id, $token);
$updatedata = array(
'user_token' => '',
);
$upwhere = array(
'app_id' => $app_id,
'user_token' => $token,
);
$this->CI->User_model->update('', $updatedata, $upwhere);
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
);
return $arr;
}
}

View File

@@ -0,0 +1,82 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Notice
*/
class Notice extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$this->CI->load->model(array('Notice_model', 'Upload_file_model'));
$where = array(
'app_id' => $app_id,
);
$data = $this->CI->Notice_model->get('', '', $where, '', '', 'notice_id', 'desc');
$result = array();
$count = 0;
if ($data) {
foreach ($data as $key => $value) {
$uploadwhere = array(
'origin_table' => 'notice',
'origin_id' => element('notice_id', $value),
);
$file = $this->CI->Upload_file_model->get('', '', $uploadwhere, '', '', 'ufi_id', 'ASC');
$files = array();
if ($file && is_array($file)) {
foreach ($file as $key2 => $val2) {
$files[] = site_url('uploads/files/' . element('ufi_filename', $val2));
}
}
$result[$key]['notice_id'] = html_escape(element('notice_id', $value));
$result[$key]['user_id'] = html_escape(element('user_id', $value));
$result[$key]['user_name'] = html_escape(element('user_name', $value));
$result[$key]['notice_title'] = html_escape(element('notice_title', $value));
$result[$key]['notice_content'] = html_escape(element('notice_content', $value));
$result[$key]['files'] = $files;
$result[$key]['created_at'] = html_escape(element('created_at', $value));
$result[$key]['updated_at'] = html_escape(element('updated_at', $value));
$count++;
}
}
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'count' => $count,
'list' => $result,
);
return $arr;
}
}

View File

@@ -0,0 +1,79 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Notice_view
*/
class Notice_view extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$notice_id = (int) trim($this->CI->input->get('notice_id'));
if (empty($notice_id)) {
$this->CI->apilib->make_error("공지사항 고유 아이디가 넘어오지 않았습니다");
}
$this->CI->load->model(array('Notice_model', 'Upload_file_model'));
$where = array(
'app_id' => $app_id,
'notice_id' => $notice_id,
);
$result = $this->CI->Notice_model->get_one('', '', $where);
if ( ! element('notice_id', $result)) {
$this->CI->apilib->make_error("존재하지 않는 공지사항입니다");
}
$uploadwhere = array(
'origin_table' => 'notice',
'origin_id' => element('notice_id', $result),
);
$file = $this->CI->Upload_file_model->get('', '', $uploadwhere, '', '', 'ufi_id', 'ASC');
$files = array();
if ($file && is_array($file)) {
foreach ($file as $key => $value) {
$files[] = site_url('uploads/files/' . element('ufi_filename', $value));
}
}
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'notice_id' => html_escape(element('notice_id', $result)),
'user_id' => html_escape(element('user_id', $result)),
'user_name' => html_escape(element('user_name', $result)),
'notice_title' => html_escape(element('notice_title', $result)),
'notice_content' => nl2br(html_escape(element('notice_content', $result))),
'files' => $files,
'created_at' => html_escape(element('created_at', $result)),
'updated_at' => html_escape(element('updated_at', $result)),
);
return $arr;
}
}

View File

@@ -0,0 +1,95 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Profile_change_info
*/
class Profile_change_info extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$sessionuser = $this->CI->User_model->get_by_token($app_id, $token);
if ( ! element('user_id', $sessionuser)) {
$this->CI->apilib->make_error("로그인 한 회원만 접근이 가능합니다");
}
$user_id = element('user_id', $sessionuser);
$this->CI->load->model(array('User_model'));
$user_username = $this->CI->input->post('user_username');
$user_old_pw = $this->CI->input->post('user_old_pw');
$user_pw1 = $this->CI->input->post('user_pw1');
$user_pw2 = $this->CI->input->post('user_pw2');
if ( ! $user_old_pw) {
$this->CI->apilib->make_error("이전 비밀번호가 입력되지 않았습니다");
}
if ( ! password_verify($user_old_pw, element('user_password', $sessionuser))) {
$this->CI->apilib->make_error("이전 비밀번호가 일치하지 않습니다");
}
if ( ! $user_username) {
$this->CI->apilib->make_error("닉네임이 입력되지 않았습니다");
}
if ($user_pw1 && $user_pw1 != $user_pw2) {
$this->CI->apilib->make_error("2개의 비밀번호가 일치하지 않아 업데이트할 수 없습니다");
}
if (mb_strlen($user_username) > 25) {
$this->CI->apilib->make_error("25자 이내로 입력해주세요");
}
if ($user_username != element('user_username', $sessionuser)) {
$userwhere = array(
'app_id' => $app_id,
'user_username' => $user_username,
);
$row = $this->CI->User_model->get_one('', 'user_id', $userwhere);
if (element('user_id', $row)) {
$this->CI->apilib->make_error("이미 사용중인 닉네임입니다. 다른 닉네임을 입력해주세요.");
}
}
$updatedata = array(
'user_username' => $user_username,
);
if ($user_pw1 && $user_pw1 == $user_pw2) {
$updatedata['user_password'] = password_hash($user_pw1, PASSWORD_BCRYPT);
}
$user = $this->CI->User_model->update(element('user_id', $sessionuser), $updatedata);
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'user_username' => $user_username,
'datetime' => cdate('Y-m-d H:i:s'),
);
return $arr;
}
}

View File

@@ -0,0 +1,58 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Profile_delete_photo
*/
class Profile_delete_photo extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$sessionuser = $this->CI->User_model->get_by_token($app_id, $token);
if ( ! element('user_id', $sessionuser)) {
$this->CI->apilib->make_error("로그인 한 회원만 접근이 가능합니다");
}
$user_id = element('user_id', $sessionuser);
if (element('user_photo', $sessionuser)) {
@unlink(config_item('uploads_dir') . '/user_photo/' . element('user_photo', $sessionuser));
}
$updatedata = array(
'user_photo' => '',
);
$this->CI->User_model->update($user_id, $updatedata);
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
);
return $arr;
}
}

View File

@@ -0,0 +1,114 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Profile_upload_photo
*/
class Profile_upload_photo extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$sessionuser = $this->CI->User_model->get_by_token($app_id, $token);
if ( ! element('user_id', $sessionuser)) {
$this->CI->apilib->make_error("로그인 한 회원만 접근이 가능합니다");
}
$user_id = element('user_id', $sessionuser);
$this->CI->load->library('upload');
$uploadfiledata = '';
if (isset($_FILES) && isset($_FILES['user_photo']) && isset($_FILES['user_photo']['name']) && $_FILES['user_photo']['name']) {
$upload_path = config_item('uploads_dir') . '/user_photo/';
if (is_dir($upload_path) === false) {
mkdir($upload_path, 0707);
$file = $upload_path . 'index.php';
$f = @fopen($file, 'w');
@fwrite($f, '');
@fclose($f);
@chmod($file, 0644);
}
$upload_path .= cdate('Y') . '/';
if (is_dir($upload_path) === false) {
mkdir($upload_path, 0707);
$file = $upload_path . 'index.php';
$f = @fopen($file, 'w');
@fwrite($f, '');
@fclose($f);
@chmod($file, 0644);
}
$upload_path .= cdate('m') . '/';
if (is_dir($upload_path) === false) {
mkdir($upload_path, 0707);
$file = $upload_path . 'index.php';
$f = @fopen($file, 'w');
@fwrite($f, '');
@fclose($f);
@chmod($file, 0644);
}
$uploadconfig = '';
$uploadconfig['upload_path'] = $upload_path;
$uploadconfig['allowed_types'] = 'jpg|jpeg|png|gif';
$uploadconfig['max_size'] = 1024 * 20;
$uploadconfig['encrypt_name'] = true;
$this->CI->upload->initialize($uploadconfig);
$_FILES['userfile']['name'] = $_FILES['user_photo']['name'];
$_FILES['userfile']['type'] = $_FILES['user_photo']['type'];
$_FILES['userfile']['tmp_name'] = $_FILES['user_photo']['tmp_name'];
$_FILES['userfile']['error'] = $_FILES['user_photo']['error'];
$_FILES['userfile']['size'] = $_FILES['user_photo']['size'];
if ($this->CI->upload->do_upload('user_photo')) {
$filedata = $this->CI->upload->data();
$image_name = cdate('Y') . '/' . cdate('m') . '/' . element('file_name', $filedata);
} else {
$file_error = $this->CI->upload->display_errors();
$this->CI->apilib->make_error($file_error);
}
} else {
$this->CI->apilib->make_error("파일이 업로드되지 않았습니다");
}
$updatedata = array(
'user_photo' => $image_name,
);
$this->CI->User_model->update($user_id, $updatedata);
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'photo_url' => user_photo_url($image_name),
);
return $arr;
}
}

View File

@@ -0,0 +1,91 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Qna
*/
class Qna extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$sessionuser = $this->CI->User_model->get_by_token($app_id, $token);
if ( ! element('user_id', $sessionuser)) {
$this->CI->apilib->make_error("로그인 한 회원만 접근이 가능합니다");
}
$user_id = element('user_id', $sessionuser);
$this->CI->load->model(array('Qna_model', 'Upload_file_model'));
$where = array(
'app_id' => $app_id,
'user_id' => $user_id,
);
$data = $this->CI->Qna_model->get('', '', $where, '', '', 'qna_id', 'desc');
$result = array();
$count = 0;
if ($data) {
foreach ($data as $key => $value) {
$uploadwhere = array(
'origin_table' => 'qna',
'origin_id' => element('qna_id', $value),
);
$file = $this->CI->Upload_file_model->get('', '', $uploadwhere, '', '', 'ufi_id', 'ASC');
$files = array();
if ($file && is_array($file)) {
foreach ($file as $key2 => $val2) {
$files[] = site_url('uploads/files/' . element('ufi_filename', $val2));
}
}
$result[$key]['qna_id'] = html_escape(element('qna_id', $value));
$result[$key]['user_id'] = html_escape(element('user_id', $value));
$result[$key]['user_name'] = html_escape(element('user_name', $value));
$result[$key]['qna_title'] = html_escape(element('qna_title', $value));
$result[$key]['qna_content'] = html_escape(element('qna_content', $value));
$result[$key]['qna_answer'] = html_escape(element('qna_answer', $value));
$result[$key]['files'] = $files;
$result[$key]['created_at'] = html_escape(element('created_at', $value));
$result[$key]['answer_at'] = html_escape(element('answer_at', $value));
$result[$key]['has_answer'] = element('has_answer', $value);
$count++;
}
}
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'count' => $count,
'list' => $result,
);
return $arr;
}
}

View File

@@ -0,0 +1,89 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Qna_view
*/
class Qna_view extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$qna_id = (int) trim($this->CI->input->get('qna_id'));
if (empty($qna_id)) {
$this->CI->apilib->make_error("문의사항 고유 아이디가 넘어오지 않았습니다");
}
$sessionuser = $this->CI->User_model->get_by_token($app_id, $token);
if ( ! element('user_id', $sessionuser)) {
$this->CI->apilib->make_error("로그인 한 회원만 접근이 가능합니다");
}
$user_id = element('user_id', $sessionuser);
$this->CI->load->model(array('Qna_model', 'Upload_file_model'));
$where = array(
'app_id' => $app_id,
'qna_id' => $qna_id,
);
$result = $this->CI->Qna_model->get_one('', '', $where);
if ( ! element('qna_id', $result)) {
$this->CI->apilib->make_error("존재하지 않는 문의사항입니다");
}
$uploadwhere = array(
'origin_table' => 'qna',
'origin_id' => element('v_id', $result),
);
$file = $this->CI->Upload_file_model->get('', '', $uploadwhere, '', '', 'ufi_id', 'ASC');
$files = array();
if ($file && is_array($file)) {
foreach ($file as $key => $value) {
$files[] = site_url('uploads/files/' . element('ufi_filename', $value));
}
}
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'qna_id' => html_escape(element('qna_id', $result)),
'user_id' => html_escape(element('user_id', $result)),
'user_name' => html_escape(element('user_name', $result)),
'qna_title' => html_escape(element('qna_title', $result)),
'qna_content' => nl2br(html_escape(element('qna_content', $result))),
'qna_answer' => nl2br(html_escape(element('qna_answer', $result))),
'files' => $files,
'created_at' => html_escape(element('created_at', $result)),
'answer_at' => html_escape(element('answer_at', $result)),
'has_answer' => element('has_answer', $result),
);
return $arr;
}
}

View File

@@ -0,0 +1,259 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Qna_write
*/
class Qna_write extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$this->CI->load->model(array('Qna_model', 'Upload_file_model'));
$sessionuser = $this->CI->User_model->get_by_token($app_id, $token);
if ( ! element('user_id', $sessionuser)) {
$this->CI->apilib->make_error("로그인 한 회원만 문의를 작성할 수 있습니다");
}
if ( ! $this->CI->input->post('qna_title')) {
$this->CI->apilib->make_error("문의 제목을 입력하여 주십시오.");
}
if ( ! $this->CI->input->post('qna_content')) {
$this->CI->apilib->make_error("문의 내용을 입력하여 주십시오.");
}
$uploadfiledata = '';
$uploadfiledata2 = '';
$this->CI->load->library('upload');
if (isset($_FILES) && isset($_FILES['upload_file']) && isset($_FILES['upload_file']['name']) && is_array($_FILES['upload_file']['name'])) {
$filecount = count($_FILES['upload_file']['name']);
$upload_path = config_item('uploads_dir') . '/files/';
if (is_dir($upload_path) === false) {
mkdir($upload_path, 0707);
$file = $upload_path . 'index.php';
$f = @fopen($file, 'w');
@fwrite($f, '');
@fclose($f);
@chmod($file, 0644);
}
$upload_path .= cdate('Y') . '/';
if (is_dir($upload_path) === false) {
mkdir($upload_path, 0707);
$file = $upload_path . 'index.php';
$f = @fopen($file, 'w');
@fwrite($f, '');
@fclose($f);
@chmod($file, 0644);
}
$upload_path .= cdate('m') . '/';
if (is_dir($upload_path) === false) {
mkdir($upload_path, 0707);
$file = $upload_path . 'index.php';
$f = @fopen($file, 'w');
@fwrite($f, '');
@fclose($f);
@chmod($file, 0644);
}
foreach ($_FILES['upload_file']['name'] as $i => $value) {
if ($value) {
$uploadconfig = '';
$uploadconfig['upload_path'] = $upload_path;
$uploadconfig['allowed_types'] = '*';
$uploadconfig['max_size'] = 10240;
$uploadconfig['encrypt_name'] = true;
$this->CI->upload->initialize($uploadconfig);
$_FILES['userfile']['name'] = $_FILES['upload_file']['name'][$i];
$_FILES['userfile']['type'] = $_FILES['upload_file']['type'][$i];
$_FILES['userfile']['tmp_name'] = $_FILES['upload_file']['tmp_name'][$i];
$_FILES['userfile']['error'] = $_FILES['upload_file']['error'][$i];
$_FILES['userfile']['size'] = $_FILES['upload_file']['size'][$i];
if ($this->CI->upload->do_upload()) {
$filedata = $this->CI->upload->data();
$uploadfiledata[$i]['ufi_filename'] = cdate('Y') . '/' . cdate('m') . '/' . element('file_name', $filedata);
$uploadfiledata[$i]['ufi_originname'] = element('orig_name', $filedata);
$uploadfiledata[$i]['ufi_filesize'] = intval(element('file_size', $filedata) * 1024);
$uploadfiledata[$i]['ufi_width'] = element('image_width', $filedata) ? element('image_width', $filedata) : 0;
$uploadfiledata[$i]['ufi_height'] = element('image_height', $filedata) ? element('image_height', $filedata) : 0;
$uploadfiledata[$i]['ufi_type'] = str_replace('.', '', element('file_ext', $filedata));
$uploadfiledata[$i]['is_image'] = element('is_image', $filedata) ? element('is_image', $filedata) : 0;
} else {
$file_error = $this->CI->upload->display_errors();
break;
}
}
}
}
if (isset($_FILES) && isset($_FILES['upload_file_update'])
&& isset($_FILES['upload_file_update']['name'])
&& is_array($_FILES['upload_file_update']['name'])
&& $file_error === '') {
$filecount = count($_FILES['upload_file_update']['name']);
$upload_path = config_item('uploads_dir') . '/files/';
if (is_dir($upload_path) === false) {
mkdir($upload_path, 0707);
$file = $upload_path . 'index.php';
$f = @fopen($file, 'w');
@fwrite($f, '');
@fclose($f);
@chmod($file, 0644);
}
$upload_path .= cdate('Y') . '/';
if (is_dir($upload_path) === false) {
mkdir($upload_path, 0707);
$file = $upload_path . 'index.php';
$f = @fopen($file, 'w');
@fwrite($f, '');
@fclose($f);
@chmod($file, 0644);
}
$upload_path .= cdate('m') . '/';
if (is_dir($upload_path) === false) {
mkdir($upload_path, 0707);
$file = $upload_path . 'index.php';
$f = @fopen($file, 'w');
@fwrite($f, '');
@fclose($f);
@chmod($file, 0644);
}
foreach ($_FILES['upload_file_update']['name'] as $i => $value) {
if ($value) {
$uploadconfig = '';
$uploadconfig['upload_path'] = $upload_path;
$uploadconfig['allowed_types'] = '*';
$uploadconfig['max_size'] = 10240;
$uploadconfig['encrypt_name'] = true;
$this->CI->upload->initialize($uploadconfig);
$_FILES['userfile']['name'] = $_FILES['upload_file_update']['name'][$i];
$_FILES['userfile']['type'] = $_FILES['upload_file_update']['type'][$i];
$_FILES['userfile']['tmp_name'] = $_FILES['upload_file_update']['tmp_name'][$i];
$_FILES['userfile']['error'] = $_FILES['upload_file_update']['error'][$i];
$_FILES['userfile']['size'] = $_FILES['upload_file_update']['size'][$i];
if ($this->CI->upload->do_upload()) {
$filedata = $this->CI->upload->data();
$olduploadfile = $this->CI->Upload_file_model->get_one($i);
if ((int) element('origin_id', $olduploadfile) !== (int) element('qna_id', $getdata)) {
alert('잘못된 접근입니다');
}
@unlink(config_item('uploads_dir') . '/files/' . element('ufi_filename', $oldpostfile));
$uploadfiledata2[$i]['ufi_id'] = $i;
$uploadfiledata2[$i]['ufi_filename'] = cdate('Y') . '/' . cdate('m') . '/' . element('file_name', $filedata);
$uploadfiledata2[$i]['ufi_originname'] = element('orig_name', $filedata);
$uploadfiledata2[$i]['ufi_filesize'] = intval(element('file_size', $filedata) * 1024);
$uploadfiledata2[$i]['ufi_width'] = element('image_width', $filedata)
? element('image_width', $filedata) : 0;
$uploadfiledata2[$i]['ufi_height'] = element('image_height', $filedata)
? element('image_height', $filedata) : 0;
$uploadfiledata2[$i]['ufi_type'] = str_replace('.', '', element('file_ext', $filedata));
$uploadfiledata2[$i]['is_image'] = element('is_image', $filedata)
? element('is_image', $filedata) : 0;
} else {
$file_error = $this->CI->upload->display_errors();
break;
}
}
}
}
$insertdata = array(
'app_id' => $app_id,
'user_id' => element('user_id', $sessionuser),
'user_name' => element('user_username', $sessionuser),
'qna_title' => $this->CI->input->post('qna_title'),
'qna_content' => $this->CI->input->post('qna_content'),
'created_at' => cdate('Y-m-d H:i:s'),
);
$qna_id = $this->CI->Qna_model->insert($insertdata);
$file_updated = false;
$file_changed = false;
if (is_array($uploadfiledata) && count($uploadfiledata) > 0) {
foreach ($uploadfiledata as $pkey => $pval) {
if ($pval) {
$fileupdate = array(
'origin_id' => $qna_id,
'origin_table' => 'qna',
'user_id' => $this->CI->userlib->item('user_id'),
'ufi_originname' => element('ufi_originname', $pval),
'ufi_filename' => element('ufi_filename', $pval),
'ufi_filesize' => element('ufi_filesize', $pval),
'ufi_width' => element('ufi_width', $pval),
'ufi_height' => element('ufi_height', $pval),
'ufi_type' => element('ufi_type', $pval),
'ufi_is_image' => element('is_image', $pval),
'ufi_datetime' => cdate('Y-m-d H:i:s'),
'ufi_ip' => $this->CI->input->ip_address(),
);
$file_id = $this->CI->Upload_file_model->insert($fileupdate);
$file_updated = true;
}
}
$file_changed = true;
}
if (is_array($uploadfiledata2) && count($uploadfiledata2) > 0) {
foreach ($uploadfiledata2 as $pkey => $pval) {
if ($pval) {
$fileupdate = array(
'user_id' => $this->userlib->item('user_id'),
'ufi_originname' => element('ufi_originname', $pval),
'ufi_filename' => element('ufi_filename', $pval),
'ufi_filesize' => element('ufi_filesize', $pval),
'ufi_width' => element('ufi_width', $pval),
'ufi_height' => element('ufi_height', $pval),
'ufi_type' => element('ufi_type', $pval),
'ufi_is_image' => element('is_image', $pval),
'ufi_datetime' => cdate('Y-m-d H:i:s'),
'ufi_ip' => $this->CI->input->ip_address(),
);
$this->CI->Upload_file_model->update($pkey, $fileupdate);
$file_changed = true;
}
}
}
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'datetime' => cdate('Y-m-d H:i:s'),
);
return $arr;
}
}

View File

@@ -0,0 +1,121 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Signup
*/
class Signup extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$sessionuser = $this->CI->User_model->get_by_token($app_id, $token);
if ( ! function_exists('password_hash')) {
$this->load->helper('password');
}
$this->CI->load->helper('email');
if ( ! $this->CI->input->post('user_email')) {
$this->CI->apilib->make_error("회원 이메일이 입력되지 않았습니다");
}
if ( ! valid_email($this->CI->input->post('user_email')) ) {
$this->CI->apilib->make_error("이메일이 형식에 맞지 않습니다.");
}
if ( ! $this->CI->input->post('user_username')) {
$this->CI->apilib->make_error("회원 닉네임이 입력되지 않았습니다");
}
if ( ! $this->CI->input->post('user_password')) {
$this->CI->apilib->make_error("비밀번호를 입력해주십시오.");
}
if ($this->CI->input->post('user_password') != $this->CI->input->post('user_password2')) {
$this->CI->apilib->make_error("비밀번호가 일치하지 않습니다. 다시 입력해주세요.");
}
$user_email = trim($this->CI->input->post('user_email'));
$user_username = trim($this->CI->input->post('user_username'));
$user_password = trim($this->CI->input->post('user_password'));
$userwhere = array(
'app_id' => $app_id,
'user_email' => $user_email,
);
$row = $this->CI->User_model->get_one('', 'user_id', $userwhere);
if (element('user_id', $row)) {
$this->CI->apilib->make_error("이미 사용중인 이메일입니다. 다른 이메일을 입력해주세요.");
}
$userwhere = array(
'app_id' => $app_id,
'user_username' => $user_username,
);
$row = $this->CI->User_model->get_one('', 'user_id', $userwhere);
if (element('user_id', $row)) {
$this->CI->apilib->make_error("이미 사용중인 닉네임입니다. 다른 닉네임을 입력해주세요.");
}
$insertdata = array(
'app_id' => $app_id,
'user_email' => $user_email,
'user_password' => password_hash($user_password, PASSWORD_BCRYPT),
'user_username' => $user_username,
'user_register_datetime' => cdate('Y-m-d H:i:s'),
'user_token' => $token,
);
$user_id = $this->CI->User_model->insert($insertdata);
$dwhere = array(
'app_id' => $app_id,
'user_id <>' => $user_id,
'user_token' => $token,
);
$this->CI->User_model->delete('', $dwhere);
//fcm token 등록하기
if ($this->CI->input->post('fcm_token')) {
$this->CI->load->library('Fcm_library');
$this->CI->fcm_library->update_token($user_id, $this->CI->input->post('fcm_token'));
}
//$this->CI->session->set_userdata('user_id', $user_id);
$arr = array(
'result' => 'ok',
'token' => $token,
'user_id' => $user_id,
'user_email' => $user_email,
'user_username' => $user_username,
'datetime' => cdate('Y-m-d H:i:s'),
);
return $arr;
}
}

View File

@@ -0,0 +1,66 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Signup_check_email
*/
class Signup_check_email extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$sessionuser = $this->CI->User_model->get_by_token($app_id, $token);
$this->CI->load->helper('email');
$user_email = $this->CI->input->post('user_email');
if ( ! $user_email) {
$this->CI->apilib->make_error("회원 이메일이 입력되지 않았습니다");
}
if ( ! valid_email($user_email) ) {
$this->CI->apilib->make_error("이메일 형식에 맞지 않습니다.");
}
$userwhere = array(
'app_id' => $app_id,
'user_email' => $user_email,
);
$row = $this->CI->User_model->get_one('', 'user_id', $userwhere);
if (element('user_id', $row)) {
$this->CI->apilib->make_error("이미 사용중인 이메일입니다. 다른 이메일을 입력해주세요.");
}
$arr = array(
'result' => 'ok',
'token' => $token,
'app_id' => $app_id,
'user_email' => $user_email,
);
return $arr;
}
}

View File

@@ -0,0 +1,55 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* User_myinfo
*/
class User_myinfo extends CI_Controller
{
private $CI;
function __construct()
{
$this->CI = & get_instance();
}
function main()
{
if ( ! $this->CI->input->post_get('token')) {
$this->CI->apilib->make_error("토큰 값이 넘어오지 않았습니다");
}
$token = $this->CI->input->post_get('token');
$app_id = (int) trim($this->CI->input->post_get('app_id'));
if (empty($app_id)) {
$this->CI->apilib->make_error("어플 아이디가 넘어오지 않았습니다");
}
$sessionuser = $this->CI->User_model->get_by_token($app_id, $token);
if ( ! element('user_id', $sessionuser)) {
$this->CI->apilib->make_error("로그인 한 회원만 회원정보를 열람할 수 있습니다");
}
$user_id = element('user_id', $sessionuser);
$this->CI->load->model(array('User_model'));
$user = $this->CI->User_model->get_one(element('user_id', $sessionuser));
$arr = array(
'result' => 'ok',
'token' => $token,
'user_id' => element('user_id', $user),
'user_email' => element('user_email', $user),
'user_username' => element('user_username', $user),
'user_photo' => user_photo_url(element('user_photo', $user)),
);
return $arr;
}
}