Initial import from local backup (Documents-Playground/pakerpale)
This commit is contained in:
152
application/libraries/Accesslevel.php
Normal file
152
application/libraries/Accesslevel.php
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* Accesslevel class
|
||||
*
|
||||
* Copyright (c) CIBoard <www.ciboard.co.kr>
|
||||
*
|
||||
* @author CIBoard (develop@ciboard.co.kr)
|
||||
*/
|
||||
|
||||
/**
|
||||
* 권한이 있는지 없는지 판단하는 class 입니다.
|
||||
*/
|
||||
class Accesslevel extends CI_Controller
|
||||
{
|
||||
|
||||
private $CI;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
$this->CI = & get_instance();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 접근권한이 있는지를 판단합니다
|
||||
*/
|
||||
public function is_accessable($access_type = '', $level = '', $group = '', $check = array())
|
||||
{
|
||||
$access_type = (string) $access_type;
|
||||
if (empty($access_type)) { // 모든 사용자
|
||||
return true;
|
||||
} elseif ($access_type === '1') { // 로그인 사용자
|
||||
if ($this->CI->member->is_member() === false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} elseif ($access_type === '100') { // 관리자
|
||||
if ($this->CI->member->is_admin($check) === false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} elseif ($access_type === '2') { // 특정그룹사용자
|
||||
if ($this->CI->member->is_admin($check) !== false) {
|
||||
return true;
|
||||
}
|
||||
if ($this->CI->member->is_member() === false) {
|
||||
return false;
|
||||
}
|
||||
$mygroup = $this->CI->member->group();
|
||||
$groups = json_decode($group, true);
|
||||
$_flag = false;
|
||||
if ($mygroup && is_array($mygroup)) {
|
||||
foreach ($mygroup as $key => $value) {
|
||||
if (is_array($groups) && in_array(element('mgr_id', $value), $groups)) {
|
||||
$_flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($_flag === false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} elseif ($access_type === '3') { // 특정레벨이상인자
|
||||
if ($this->CI->member->is_admin($check) !== false) {
|
||||
return true;
|
||||
}
|
||||
if ($this->CI->member->is_member() === false) {
|
||||
return false;
|
||||
}
|
||||
if ($this->CI->member->item('mem_level') < $level) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
} elseif ($access_type === '4') { // 특정그룹 OR 특정레벨
|
||||
if ($this->CI->member->is_admin($check) !== false) {
|
||||
return true;
|
||||
}
|
||||
if ($this->CI->member->is_member() === false) {
|
||||
return false;
|
||||
}
|
||||
$_flag = false;
|
||||
if ($this->CI->member->item('mem_level') >= $level) {
|
||||
$_flag = true;
|
||||
}
|
||||
if ($_flag === false) {
|
||||
$mygroup = $this->CI->member->group();
|
||||
$groups = json_decode($group, true);
|
||||
if ($mygroup && is_array($mygroup)) {
|
||||
foreach ($mygroup as $key => $value) {
|
||||
if (is_array($groups) && in_array(element('mgr_id', $value), $groups)) {
|
||||
$_flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($_flag === false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
} elseif ($access_type === '5') { // 특정그룹 AND 특정레벨
|
||||
if ($this->CI->member->is_admin($check) !== false) {
|
||||
return true;
|
||||
}
|
||||
if ($this->CI->member->is_member() === false) {
|
||||
return false;
|
||||
}
|
||||
if ($this->CI->member->item('mem_level') < $level) {
|
||||
return false;
|
||||
}
|
||||
$_flag = false;
|
||||
$mygroup = $this->CI->member->group();
|
||||
$groups = json_decode($group, true);
|
||||
if ($mygroup && is_array($mygroup)) {
|
||||
foreach ($mygroup as $key => $value) {
|
||||
if (is_array($groups) && in_array(element('mgr_id', $value), $groups)) {
|
||||
$_flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($_flag === false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 접근권한이 없으면 alert 를 띄웁니다
|
||||
*/
|
||||
public function check($access_type = '', $level = '', $group = '', $alertmessage = '', $check = array())
|
||||
{
|
||||
if (empty($alertmessage)) {
|
||||
$alertmessage = '접근 권한이 없습니다';
|
||||
}
|
||||
$accessable = $this->is_accessable($access_type, $level, $group, $check);
|
||||
|
||||
if ($accessable) {
|
||||
return true;
|
||||
} else {
|
||||
alert($alertmessage);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
836
application/libraries/Board.php
Normal file
836
application/libraries/Board.php
Normal file
@@ -0,0 +1,836 @@
|
||||
<?php
|
||||
defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* Board class
|
||||
*
|
||||
* Copyright (c) CIBoard <www.ciboard.co.kr>
|
||||
*
|
||||
* @author CIBoard (develop@ciboard.co.kr)
|
||||
*/
|
||||
|
||||
/**
|
||||
* board table 을 주로 관리하는 class 입니다.
|
||||
*/
|
||||
class Board extends CI_Controller
|
||||
{
|
||||
|
||||
private $CI;
|
||||
private $board_id;
|
||||
private $board_key;
|
||||
private $group;
|
||||
private $admin;
|
||||
private $call_admin;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
$this->CI = & get_instance();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* board table 의 정보를 얻습니다
|
||||
*/
|
||||
public function get_board($brd_id = 0, $brd_key = '')
|
||||
{
|
||||
if (empty($brd_id) && empty($brd_key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($brd_id) {
|
||||
$this->CI->load->model('Board_model');
|
||||
$board = $this->CI->Board_model->get_one($brd_id);
|
||||
} elseif ($brd_key) {
|
||||
$where = array(
|
||||
'brd_key' => $brd_key,
|
||||
);
|
||||
$this->CI->load->model('Board_model');
|
||||
$board = $this->CI->Board_model->get_one('', '', $where);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
$board['board_name'] = ($this->CI->cbconfig->get_device_view_type() === 'mobile' && $board['brd_mobile_name'])
|
||||
? $board['brd_mobile_name'] : $board['brd_name'];
|
||||
if (element('brd_id', $board)) {
|
||||
$board_meta = $this->get_all_meta(element('brd_id', $board));
|
||||
if (is_array($board_meta)) {
|
||||
$board = array_merge($board, $board_meta);
|
||||
}
|
||||
}
|
||||
|
||||
if (element('brd_id', $board)) {
|
||||
$this->board_id[element('brd_id', $board)] = $board;
|
||||
}
|
||||
if (element('brd_key', $board)) {
|
||||
$this->board_key[element('brd_key', $board)] = $board;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* board meta table 의 정보를 얻습니다
|
||||
*/
|
||||
public function get_all_meta($brd_id = 0)
|
||||
{
|
||||
$brd_id = (int) $brd_id;
|
||||
if (empty($brd_id) OR $brd_id < 1) {
|
||||
return false;
|
||||
}
|
||||
$this->CI->load->model('Board_meta_model');
|
||||
$result = $this->CI->Board_meta_model->get_all_meta($brd_id);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* board group meta table 의 정보를 얻습니다
|
||||
*/
|
||||
public function get_all_group_meta($bgr_id = 0)
|
||||
{
|
||||
$bgr_id = (int) $bgr_id;
|
||||
if (empty($bgr_id) OR $bgr_id < 1) {
|
||||
return false;
|
||||
}
|
||||
$this->CI->load->model('Board_group_meta_model');
|
||||
$result = $this->CI->Board_group_meta_model->get_all_meta($bgr_id);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* item 을 brd_id 에 기반하여 얻습니다
|
||||
*/
|
||||
public function item_id($column = '', $brd_id = 0)
|
||||
{
|
||||
if (empty($column)) {
|
||||
return false;
|
||||
}
|
||||
$brd_id = (int) $brd_id;
|
||||
if (empty($brd_id) OR $brd_id < 1) {
|
||||
return false;
|
||||
}
|
||||
if ( ! isset($this->board_id[$brd_id])) {
|
||||
$this->get_board($brd_id, '');
|
||||
}
|
||||
if ( ! isset($this->board_id[$brd_id])) {
|
||||
return false;
|
||||
}
|
||||
$board = $this->board_id[$brd_id];
|
||||
|
||||
return isset($board[$column]) ? $board[$column] : false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* item 을 brd_key 에 기반하여 얻습니다
|
||||
*/
|
||||
public function item_key($column = '', $brd_key = '')
|
||||
{
|
||||
if (empty($column)) {
|
||||
return false;
|
||||
}
|
||||
if (empty($brd_key)) {
|
||||
return false;
|
||||
}
|
||||
if ( ! isset($this->board_key[$brd_key])) {
|
||||
$this->get_board('', $brd_key);
|
||||
}
|
||||
if ( ! isset($this->board_key[$brd_key])) {
|
||||
return false;
|
||||
}
|
||||
$board = $this->board_key[$brd_key];
|
||||
|
||||
return isset($board[$column]) ? $board[$column] : false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 모든 item 을 brd_id 에 기반하여 얻습니다
|
||||
*/
|
||||
public function item_all($brd_id = 0)
|
||||
{
|
||||
$brd_id = (int) $brd_id;
|
||||
if (empty($brd_id) OR $brd_id < 1) {
|
||||
return false;
|
||||
}
|
||||
if ( ! isset($this->board_id[$brd_id])) {
|
||||
$this->get_board($brd_id, '');
|
||||
}
|
||||
if ( ! isset($this->board_id[$brd_id])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->board_id[$brd_id];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 그룹 정보를 얻습니다
|
||||
*/
|
||||
public function get_group($bgr_id = 0)
|
||||
{
|
||||
$bgr_id = (int) $bgr_id;
|
||||
if (empty($bgr_id) OR $bgr_id < 1) {
|
||||
return false;
|
||||
}
|
||||
if ($bgr_id) {
|
||||
$this->CI->load->model('Board_group_model');
|
||||
$group = $this->CI->Board_group_model->get_one($bgr_id);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
$group_meta = $this->get_all_group_meta($bgr_id);
|
||||
if (is_array($group_meta)) {
|
||||
$group = array_merge($group, $group_meta);
|
||||
}
|
||||
$this->group[$bgr_id] = $group;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 게시글 삭제시 삭제되어야하는 모든 테이블데이터입니다
|
||||
*/
|
||||
public function delete_post($post_id = 0)
|
||||
{
|
||||
$post_id = (int) $post_id;
|
||||
if (empty($post_id) OR $post_id < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->CI->load->model(
|
||||
array(
|
||||
'Post_model', 'Blame_model', 'Like_model',
|
||||
'Post_extra_vars_model', 'Post_file_model', 'Post_file_download_log_model',
|
||||
'Post_history_model', 'Post_link_model', 'Post_link_click_log_model',
|
||||
'Post_meta_model', 'Post_tag_model', 'Scrap_model',
|
||||
'Comment_model'
|
||||
)
|
||||
);
|
||||
|
||||
$post = $this->CI->Post_model->get_one($post_id);
|
||||
|
||||
if ( ! element('post_id', $post)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$board = $this->CI->board->item_all(element('brd_id', $post));
|
||||
|
||||
$this->CI->Post_model->delete($post_id);
|
||||
|
||||
$deletewhere = array(
|
||||
'target_id' => $post_id,
|
||||
'target_type' => 1,
|
||||
);
|
||||
$this->CI->Blame_model->delete_where($deletewhere);
|
||||
$this->CI->Like_model->delete_where($deletewhere);
|
||||
|
||||
$deletewhere = array(
|
||||
'post_id' => $post_id,
|
||||
);
|
||||
|
||||
// 첨부 파일 삭제
|
||||
$postfiles = $this->CI->Post_file_model->get('', '', $deletewhere);
|
||||
if ($postfiles) {
|
||||
foreach ($postfiles as $postfile) {
|
||||
@unlink(config_item('uploads_dir') . '/post/' . element('pfi_filename', $postfile));
|
||||
}
|
||||
}
|
||||
|
||||
$this->CI->Post_extra_vars_model->delete_where($deletewhere);
|
||||
$this->CI->Post_file_model->delete_where($deletewhere);
|
||||
$this->CI->Post_file_download_log_model->delete_where($deletewhere);
|
||||
$this->CI->Post_history_model->delete_where($deletewhere);
|
||||
$this->CI->Post_link_model->delete_where($deletewhere);
|
||||
$this->CI->Post_link_click_log_model->delete_where($deletewhere);
|
||||
$this->CI->Post_meta_model->deletemeta($post_id);
|
||||
$this->CI->Post_tag_model->delete_where($deletewhere);
|
||||
$this->CI->Scrap_model->delete_where($deletewhere);
|
||||
|
||||
$where = array(
|
||||
'post_id' => $post_id,
|
||||
);
|
||||
$comment = $this->CI->Comment_model->get('', 'cmt_id', $where);
|
||||
if ($comment && is_array($comment)) {
|
||||
foreach ($comment as $cval) {
|
||||
if (element('cmt_id', $cval)) {
|
||||
$this->delete_comment(element('cmt_id', $cval));
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->CI->load->library('point');
|
||||
$this->CI->point->delete_point(
|
||||
abs(element('mem_id', $post)),
|
||||
'post',
|
||||
$post_id,
|
||||
'게시글 작성'
|
||||
);
|
||||
if (element('point_post_delete', $board)
|
||||
&& $this->CI->member->item('mem_id') === abs(element('mem_id', $post))) {
|
||||
|
||||
$point_delete = 0 - abs(element('point_post_delete', $board));
|
||||
|
||||
$this->CI->point->insert_point(
|
||||
abs(element('mem_id', $post)),
|
||||
$point_delete,
|
||||
element('brd_name', $board) . ' ' . $post_id . ' 게시글 삭제',
|
||||
'post_delete',
|
||||
$post_id,
|
||||
'게시글 삭제'
|
||||
);
|
||||
|
||||
} elseif (element('point_admin_post_delete', $board)
|
||||
&& $this->CI->member->item('mem_id') !== abs(element('mem_id', $post))) {
|
||||
$point_delete = 0 - abs(element('point_admin_post_delete', $board));
|
||||
|
||||
$this->CI->point->insert_point(
|
||||
abs(element('mem_id', $post)),
|
||||
$point_delete,
|
||||
element('brd_name', $board) . ' ' . $post_id . ' 게시글 삭제',
|
||||
'admin_post_delete',
|
||||
$post_id,
|
||||
'게시글 삭제'
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 코멘트 삭제시 삭제되어야하는 모든 테이블데이터입니다
|
||||
*/
|
||||
public function delete_comment($cmt_id = 0)
|
||||
{
|
||||
$cmt_id = (int) $cmt_id;
|
||||
if (empty($cmt_id) OR $cmt_id < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->CI->load->model( array('Post_model', 'Blame_model', 'Like_model', 'Comment_model', 'Comment_meta_model'));
|
||||
|
||||
$comment = $this->CI->Comment_model->get_one($cmt_id);
|
||||
|
||||
if ( ! element('cmt_id', $comment)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$post = $this->CI->Post_model->get_one(element('post_id', $comment));
|
||||
$board = $this->CI->board->item_all(element('brd_id', $post));
|
||||
|
||||
$this->CI->Comment_model->delete($cmt_id);
|
||||
$deletewhere = array(
|
||||
'target_id' => $cmt_id,
|
||||
'target_type' => 2,
|
||||
);
|
||||
$this->CI->Blame_model->delete_where($deletewhere);
|
||||
$this->CI->Like_model->delete_where($deletewhere);
|
||||
|
||||
$deletewhere = array(
|
||||
'cmt_id' => $cmt_id,
|
||||
);
|
||||
$this->CI->Comment_meta_model->delete_where($deletewhere);
|
||||
$this->CI->Post_model->update_plus(element('post_id', $comment), 'post_comment_count', '-1');
|
||||
|
||||
$this->CI->load->library('point');
|
||||
$this->CI->point->delete_point(
|
||||
abs(element('mem_id', $comment)),
|
||||
'comment',
|
||||
$cmt_id,
|
||||
'댓글 작성'
|
||||
);
|
||||
$this->CI->point->delete_point(
|
||||
abs(element('mem_id', $comment)),
|
||||
'lucky-comment',
|
||||
$cmt_id,
|
||||
'럭키포인트'
|
||||
);
|
||||
|
||||
if (element('point_comment_delete', $board) && $this->CI->member->item('mem_id') === abs(element('mem_id', $comment))) {
|
||||
$point_delete = 0 - abs(element('point_comment_delete', $board));
|
||||
|
||||
$this->CI->point->insert_point(
|
||||
abs(element('mem_id', $comment)),
|
||||
$point_delete,
|
||||
element('brd_name', $board) . ' ' . $cmt_id . ' 댓글 삭제',
|
||||
'comment_delete',
|
||||
$cmt_id,
|
||||
'댓글 삭제'
|
||||
);
|
||||
|
||||
} elseif (element('point_admin_comment_delete', $board) && $this->CI->member->item('mem_id') !== abs(element('mem_id', $comment))) {
|
||||
$point_delete = 0 - abs(element('point_admin_comment_delete', $board));
|
||||
|
||||
$this->CI->point->insert_point(
|
||||
abs(element('mem_id', $comment)),
|
||||
$point_delete,
|
||||
element('brd_name', $board) . ' ' . $cmt_id . ' 댓글 삭제',
|
||||
'admin_comment_delete',
|
||||
$cmt_id,
|
||||
'댓글 삭제'
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 댓글 삭제시 삭제가능한 권한이 있는지 체크합니다
|
||||
*/
|
||||
public function delete_comment_check($cmt_id = 0, $password = '', $realdelete = false)
|
||||
{
|
||||
$cmt_id = (int) $cmt_id;
|
||||
if (empty($cmt_id) OR $cmt_id < 1) {
|
||||
$result = array('error' => '올바르지 않은 접근입니다');
|
||||
return json_encode($result);
|
||||
}
|
||||
|
||||
$this->CI->load->model( array('Post_model', 'Comment_model', 'Comment_meta_model'));
|
||||
|
||||
$comment = $this->CI->Comment_model->get_one($cmt_id);
|
||||
$post = $this->CI->Post_model->get_one(element('post_id', $comment));
|
||||
$board = $this->CI->board->item_all(element('brd_id', $post));
|
||||
|
||||
if ( ! $this->CI->session->userdata('post_id_' . element('post_id', $post))) {
|
||||
$result = array('error' => '해당 게시물에서만 접근 가능합니다');
|
||||
return json_encode($result);
|
||||
}
|
||||
|
||||
$is_admin = $this->CI->member->is_admin(
|
||||
array(
|
||||
'board_id' => element('brd_id', $board),
|
||||
'group_id' => element('bgr_id', $board),
|
||||
)
|
||||
);
|
||||
$can_delete_comment = false;
|
||||
|
||||
if (element('block_delete', $board) && $is_admin === false) {
|
||||
$result = array('error' => '이 게시판의 글은 관리자에 의해서만 삭제가 가능합니다');
|
||||
return json_encode($result);
|
||||
}
|
||||
|
||||
if ($is_admin === false) {
|
||||
$count_comment_reply = $this->CI->Comment_model->count_reply_comment(
|
||||
element('cmt_id', $comment),
|
||||
element('post_id', $comment),
|
||||
element('cmt_num', $comment),
|
||||
element('cmt_reply', $comment)
|
||||
);
|
||||
|
||||
if ($count_comment_reply > 0) {
|
||||
$result = array('error' => '이 댓글에 답변댓글이 있으므로 댓글을 삭제할 수 없습니다');
|
||||
return json_encode($result);
|
||||
}
|
||||
}
|
||||
|
||||
if (element('protect_comment_day', $board) > 0 && $is_admin === false) {
|
||||
if (ctimestamp() - strtotime(element('cmt_datetime', $comment)) >= element('protect_comment_day', $board) * 86400) {
|
||||
$result = array('error' => '이 게시판은 ' . element('protect_comment_day', $board) . '일 이상된 댓글의 삭제를 금지합니다');
|
||||
return json_encode($result);
|
||||
}
|
||||
}
|
||||
if (element('mem_id', $comment)) {
|
||||
if ($is_admin === false && (int) $this->CI->member->item('mem_id') !== abs(element('mem_id', $comment))) {
|
||||
$result = array('error' => '회원님은 이 글을 삭제할 권한이 없습니다');
|
||||
return json_encode($result);
|
||||
}
|
||||
} else {
|
||||
|
||||
$this->CI->session->keep_flashdata('can_delete_comment_' . element('cmt_id', $comment));
|
||||
if ($is_admin) {
|
||||
$this->CI->session->set_flashdata(
|
||||
'can_delete_comment_' . element('cmt_id', $comment),
|
||||
'1'
|
||||
);
|
||||
}
|
||||
if ( ! $this->CI->session->flashdata('can_delete_comment_' . element('cmt_id', $comment)) && $password) {
|
||||
|
||||
if ( ! function_exists('password_hash')) {
|
||||
$this->CI->load->helper('password');
|
||||
}
|
||||
if (password_verify($password, element('cmt_password', $comment))) {
|
||||
$can_delete_comment = true;
|
||||
$this->CI->session->set_flashdata(
|
||||
'can_delete_comment_' . element('cmt_id', $comment),
|
||||
'1'
|
||||
);
|
||||
} else {
|
||||
$result = array('error' => '패스워드가 잘못 입력되었습니다');
|
||||
return json_encode($result);
|
||||
}
|
||||
}
|
||||
if ( ! $this->CI->session->flashdata('can_delete_comment_' . element('cmt_id', $comment)) && $can_delete_comment === false) {
|
||||
|
||||
$result = array('password' => '패스워드가 확인이 필요합니다');
|
||||
return json_encode($result);
|
||||
}
|
||||
}
|
||||
|
||||
if (element('use_comment_delete_log', $board) && $realdelete === false) {
|
||||
$updatedata = array(
|
||||
'cmt_del' => 1,
|
||||
);
|
||||
$this->CI->Comment_model->update(element('cmt_id', $comment), $updatedata);
|
||||
$metadata = array(
|
||||
'delete_mem_id' => $this->CI->member->item('mem_id'),
|
||||
'delete_mem_nickname' => $this->CI->member->item('mem_nickname'),
|
||||
'delete_datetime' => cdate('Y-m-d H:i:s'),
|
||||
'delete_ip' => $this->CI->input->ip_address(),
|
||||
);
|
||||
$this->CI->Comment_meta_model->save(element('cmt_id', $comment), $metadata);
|
||||
} else {
|
||||
$this->CI->board->delete_comment($cmt_id);
|
||||
}
|
||||
$result = array('success' => '댓글이 삭제되었습니다');
|
||||
return json_encode($result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 최근게시물을 가져옵니다
|
||||
*/
|
||||
public function latest($config)
|
||||
{
|
||||
$view = array();
|
||||
$view['view'] = array();
|
||||
|
||||
$this->CI->load->model( array('Board_category_model', 'Post_file_model'));
|
||||
|
||||
$skin = element('skin', $config);
|
||||
$brd_id = element('brd_id', $config);
|
||||
$brd_key = element('brd_key', $config);
|
||||
$exclude_brd_id = element('exclude_brd_id', $config);
|
||||
$exclude_brd_key = element('exclude_brd_key', $config);
|
||||
$findex = element('findex', $config) ? element('findex', $config) : 'post_id';
|
||||
$forder = element('forder', $config) ? element('forder', $config) : 'DESC';
|
||||
$limit = element('limit', $config);
|
||||
$length = element('length', $config);
|
||||
$is_gallery = element('is_gallery', $config);
|
||||
$image_width = element('image_width', $config);
|
||||
$image_height = element('image_height', $config);
|
||||
$period_second = element('period_second', $config);
|
||||
$cache_minute = element('cache_minute', $config);
|
||||
|
||||
if ($limit <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($cache_minute> 0) {
|
||||
$cache_brd_id = is_array($brd_id) ? implode('-', $brd_id) : $brd_id;
|
||||
$cache_brd_key = is_array($brd_key) ? implode('-', $brd_key) : $brd_key;
|
||||
$cache_exclude_brd_id = is_array($exclude_brd_id) ? implode('-', $exclude_brd_id) : $exclude_brd_id;
|
||||
$cache_exclude_brd_key = is_array($exclude_brd_key) ? implode('-', $exclude_brd_key) : $exclude_brd_key;
|
||||
$cachename = 'latest/latest-s-' . $skin . '-i-' . $cache_brd_id . '-k-' . $cache_brd_key . '-l-' . $cache_exclude_brd_id . '-k-' . $cache_exclude_brd_key . '-l-' . $limit . '-t-' . $length . '-g-' . $is_gallery . '-w-' . $image_width . '-h-' . $image_height . '-p-' . $period_second;
|
||||
$html = $this->CI->cache->get($cachename);
|
||||
if ($html) {
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($skin)) {
|
||||
$skin = 'basic';
|
||||
}
|
||||
$view['view']['config'] = $config;
|
||||
$view['view']['length'] = $length;
|
||||
if ($brd_key) {
|
||||
if (is_array($brd_key)) {
|
||||
foreach ($brd_key as $v) {
|
||||
$brd_id[] = $this->CI->board->item_key('brd_id', $v);
|
||||
}
|
||||
} else {
|
||||
$brd_id = $this->CI->board->item_key('brd_id', $brd_key);
|
||||
}
|
||||
}
|
||||
if ($exclude_brd_key) {
|
||||
if (is_array($exclude_brd_key)) {
|
||||
foreach ($exclude_brd_key as $v) {
|
||||
$exclude_brd_id[] = $this->CI->board->item_key('brd_id', $v);
|
||||
}
|
||||
} else {
|
||||
$exclude_brd_id = $this->CI->board->item_key('brd_id', $exclude_brd_key);
|
||||
}
|
||||
}
|
||||
if ($brd_id && ! is_array($brd_id)) {
|
||||
$view['view']['board'] = $this->CI->board->item_all($brd_id);
|
||||
}
|
||||
$where = array();
|
||||
$where['post_del'] = 0;
|
||||
$where['post_secret'] = 0;
|
||||
|
||||
$this->CI->db->from('post');
|
||||
$this->CI->db->where($where);
|
||||
|
||||
if ($brd_id) {
|
||||
if (is_array($brd_id)) {
|
||||
$this->CI->db->group_start();
|
||||
foreach ($brd_id as $v) {
|
||||
$this->CI->db->or_where('brd_id', $v);
|
||||
}
|
||||
$this->CI->db->group_end();
|
||||
} else {
|
||||
$this->CI->db->where('brd_id', $brd_id);
|
||||
}
|
||||
}
|
||||
|
||||
if ($exclude_brd_id) {
|
||||
if (is_array($exclude_brd_id)) {
|
||||
foreach ($exclude_brd_id as $v) {
|
||||
$this->CI->db->where('brd_id <>', $v);
|
||||
}
|
||||
} else {
|
||||
$this->CI->db->where('brd_id <>', $exclude_brd_id);
|
||||
}
|
||||
}
|
||||
|
||||
if ($period_second) {
|
||||
$post_start_datetime = cdate('Y-m-d H:i:s', ctimestamp() - $period_second);
|
||||
$this->CI->db->where('post_datetime >=', $post_start_datetime);
|
||||
}
|
||||
|
||||
if ($findex && $forder) {
|
||||
$forder = (strtoupper($forder) === 'ASC') ? 'ASC' : 'DESC';
|
||||
$this->CI->db->order_by($findex, $forder);
|
||||
}
|
||||
if (is_numeric($limit)) {
|
||||
$this->CI->db->limit($limit);
|
||||
}
|
||||
$result = $this->CI->db->get();
|
||||
$view['view']['latest'] = $latest = $result->result_array();
|
||||
|
||||
$view['view']['latest_limit'] = $limit;
|
||||
if ($latest && is_array($latest)) {
|
||||
foreach ($latest as $key => $value) {
|
||||
$view['view']['latest'][$key]['name'] = display_username(
|
||||
element('post_userid', $value),
|
||||
element('post_nickname', $value)
|
||||
);
|
||||
$brd_key = $this->CI->board->item_id('brd_key', element('brd_id', $value));
|
||||
$view['view']['latest'][$key]['url'] = post_url($brd_key, element('post_id', $value));
|
||||
$view['view']['latest'][$key]['title'] = $length ? cut_str(element('post_title', $value), $length) : element('post_title', $value);
|
||||
$view['view']['latest'][$key]['display_datetime'] = display_datetime(element('post_datetime', $value), '');
|
||||
$view['view']['latest'][$key]['category'] = '';
|
||||
if (element('post_category', $value)) {
|
||||
$view['view']['latest'][$key]['category'] = $this->CI->Board_category_model->get_category_info(element('brd_id', $value), element('post_category', $value));
|
||||
}
|
||||
if ($is_gallery) {
|
||||
if (element('post_image', $value)) {
|
||||
$imagewhere = array(
|
||||
'post_id' => element('post_id', $value),
|
||||
'pfi_is_image' => 1,
|
||||
);
|
||||
$file = $this->CI->Post_file_model->get_one('', '', $imagewhere, '', '', 'pfi_id', 'ASC');
|
||||
if (element('pfi_filename', $file)) {
|
||||
$view['view']['latest'][$key]['thumb_url'] = thumb_url('post', element('pfi_filename', $file), $image_width, $image_height);
|
||||
}
|
||||
} else {
|
||||
$thumb_url = get_post_image_url(element('post_content', $value), $image_width, $image_height);
|
||||
$view['view']['latest'][$key]['thumb_url'] = $thumb_url ? $thumb_url : thumb_url('', '', $image_width, $image_height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$view['view']['skinurl'] = base_url( VIEW_DIR . 'latest/' . $skin);
|
||||
$html = $this->CI->load->view('latest/' . $skin . '/latest', $view, true);
|
||||
|
||||
if ($cache_minute> 0) {
|
||||
check_cache_dir('latest');
|
||||
$this->CI->cache->save($cachename, $html, $cache_minute);
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 최근 댓글을 가져옵니다
|
||||
*/
|
||||
public function latest_comment($config)
|
||||
{
|
||||
$view = array();
|
||||
$view['view'] = array();
|
||||
|
||||
$this->CI->load->model( array('Comment_model'));
|
||||
|
||||
$skin = element('skin', $config);
|
||||
$brd_id = element('brd_id', $config);
|
||||
$brd_key = element('brd_key', $config);
|
||||
$exclude_brd_id = element('exclude_brd_id', $config);
|
||||
$exclude_brd_key = element('exclude_brd_key', $config);
|
||||
$findex = element('findex', $config) ? element('findex', $config) : 'cmt_id';
|
||||
$forder = element('forder', $config) ? element('forder', $config) : 'DESC';
|
||||
$limit = element('limit', $config);
|
||||
$length = element('length', $config);
|
||||
$period_second = element('period_second', $config);
|
||||
$cache_minute = element('cache_minute', $config);
|
||||
|
||||
if ($limit <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($cache_minute> 0) {
|
||||
$cache_brd_id = is_array($brd_id) ? implode('-', $brd_id) : $brd_id;
|
||||
$cache_brd_key = is_array($brd_key) ? implode('-', $brd_key) : $brd_key;
|
||||
$cache_exclude_brd_id = is_array($exclude_brd_id) ? implode('-', $exclude_brd_id) : $exclude_brd_id;
|
||||
$cache_exclude_brd_key = is_array($exclude_brd_key) ? implode('-', $exclude_brd_key) : $exclude_brd_key;
|
||||
$cachename = 'latest_comment/latest-comment-s-' . $skin . '-i-' . $cache_brd_id . '-k-' . $cache_brd_key . '-l-' . $cache_exclude_brd_id . '-k-' . $cache_exclude_brd_key . '-l-' . $limit . '-t-' . $length . '-p-' . $period_second;
|
||||
$html = $this->CI->cache->get($cachename);
|
||||
if ($html) {
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($skin)) {
|
||||
$skin = 'basic';
|
||||
}
|
||||
$view['view']['config'] = $config;
|
||||
$view['view']['length'] = $length;
|
||||
if ($brd_key) {
|
||||
if (is_array($brd_key)) {
|
||||
foreach ($brd_key as $v) {
|
||||
$brd_id[] = $this->CI->board->item_key('brd_id', $v);
|
||||
}
|
||||
} else {
|
||||
$brd_id = $this->CI->board->item_key('brd_id', $brd_key);
|
||||
}
|
||||
}
|
||||
if ($exclude_brd_key) {
|
||||
if (is_array($exclude_brd_key)) {
|
||||
foreach ($exclude_brd_key as $v) {
|
||||
$exclude_brd_id[] = $this->CI->board->item_key('brd_id', $v);
|
||||
}
|
||||
} else {
|
||||
$exclude_brd_id = $this->CI->board->item_key('brd_id', $exclude_brd_key);
|
||||
}
|
||||
}
|
||||
if ($brd_id && ! is_array($brd_id)) {
|
||||
$view['view']['board'] = $this->CI->board->item_all($brd_id);
|
||||
}
|
||||
$where = array();
|
||||
$where['cmt_del'] = 0;
|
||||
$where['cmt_secret'] = 0;
|
||||
$where['post_secret'] = 0;
|
||||
$where['post_del'] = 0;
|
||||
|
||||
$this->CI->db->from('comment');
|
||||
$this->CI->db->join('post', 'post.post_id=comment.post_id', 'inner');
|
||||
$this->CI->db->where($where);
|
||||
|
||||
if ($brd_id) {
|
||||
if (is_array($brd_id)) {
|
||||
$this->CI->db->group_start();
|
||||
foreach ($brd_id as $v) {
|
||||
$this->CI->db->or_where('comment.brd_id', $v);
|
||||
}
|
||||
$this->CI->db->group_end();
|
||||
} else {
|
||||
$this->CI->db->where('comment.brd_id', $brd_id);
|
||||
}
|
||||
}
|
||||
|
||||
if ($exclude_brd_id) {
|
||||
if (is_array($exclude_brd_id)) {
|
||||
foreach ($exclude_brd_id as $v) {
|
||||
$this->CI->db->where('comment.brd_id <>', $v);
|
||||
}
|
||||
} else {
|
||||
$this->CI->db->where('comment.brd_id <>', $exclude_brd_id);
|
||||
}
|
||||
}
|
||||
|
||||
if ($period_second) {
|
||||
$comment_start_datetime = cdate('Y-m-d H:i:s', ctimestamp() - $period_second);
|
||||
$this->CI->db->where('cmt_datetime >=', $comment_start_datetime);
|
||||
}
|
||||
|
||||
if ($findex && $forder) {
|
||||
$forder = (strtoupper($forder) === 'ASC') ? 'ASC' : 'DESC';
|
||||
$this->CI->db->order_by($findex, $forder);
|
||||
}
|
||||
if (is_numeric($limit)) {
|
||||
$this->CI->db->limit($limit);
|
||||
}
|
||||
$result = $this->CI->db->get();
|
||||
$view['view']['latest'] = $latest = $result->result_array();
|
||||
|
||||
$view['view']['latest_limit'] = $limit;
|
||||
if ($latest && is_array($latest)) {
|
||||
foreach ($latest as $key => $value) {
|
||||
$view['view']['latest'][$key]['name'] = display_username(
|
||||
element('cmt_userid', $value),
|
||||
element('cmt_nickname', $value)
|
||||
);
|
||||
$brd_key = $this->CI->board->item_id('brd_key', element('brd_id', $value));
|
||||
$view['view']['latest'][$key]['url'] = post_url($brd_key, element('post_id', $value)) . '#comment_' . element('cmt_id', $value);
|
||||
$view['view']['latest'][$key]['title'] = $length ? cut_str(strip_tags(element('cmt_content', $value)), $length) : strip_tags(element('cmt_content', $value));
|
||||
$view['view']['latest'][$key]['display_datetime'] = display_datetime(element('cmt_datetime', $value), '');
|
||||
}
|
||||
}
|
||||
$view['view']['skinurl'] = base_url( VIEW_DIR . 'latest/' . $skin);
|
||||
$html = $this->CI->load->view('latest/' . $skin . '/latest', $view, true);
|
||||
|
||||
if ($cache_minute> 0) {
|
||||
check_cache_dir('latest_comment');
|
||||
$this->CI->cache->save($cachename, $html, $cache_minute);
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 인기태그를 가져옵니다
|
||||
*/
|
||||
public function get_popular_tags($start_date = '', $limit = '')
|
||||
{
|
||||
$cachename = 'latest/get_popular_tags_' . $start_date . '_' . $limit;
|
||||
$data = array();
|
||||
|
||||
if ( ! $data = $this->CI->cache->get($cachename)) {
|
||||
|
||||
$this->CI->load->model( array('Post_tag_model'));
|
||||
$result = $this->CI->Post_tag_model->get_popular_tags($start_date, $limit);
|
||||
|
||||
$data['result'] = $result;
|
||||
$data['cached'] = '1';
|
||||
check_cache_dir('latest');
|
||||
$this->CI->cache->save($cachename, $data, 60);
|
||||
|
||||
}
|
||||
return isset($data['result']) ? $data['result'] : false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 어드민인지 체크합니다
|
||||
*/
|
||||
public function is_admin($brd_id = 0)
|
||||
{
|
||||
$brd_id = (int) $brd_id;
|
||||
if (empty($brd_id) OR $brd_id < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! $this->CI->member->item('mem_id')) {
|
||||
return false;
|
||||
}
|
||||
if ($this->call_admin) {
|
||||
return $this->admin;
|
||||
}
|
||||
$this->call_admin = true;
|
||||
$countwhere = array(
|
||||
'brd_id' => $brd_id,
|
||||
'mem_id' => $this->CI->member->item('mem_id'),
|
||||
);
|
||||
$this->CI->load->model('Board_admin_model');
|
||||
$count = $this->CI->Board_admin_model->count_by($countwhere);
|
||||
if ($count) {
|
||||
$this->admin = true;
|
||||
} else {
|
||||
$this->admin = false;
|
||||
}
|
||||
return $this->admin;
|
||||
}
|
||||
}
|
||||
199
application/libraries/Board_group.php
Normal file
199
application/libraries/Board_group.php
Normal file
@@ -0,0 +1,199 @@
|
||||
<?php
|
||||
defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* Board group class
|
||||
*
|
||||
* Copyright (c) CIBoard <www.ciboard.co.kr>
|
||||
*
|
||||
* @author CIBoard (develop@ciboard.co.kr)
|
||||
*/
|
||||
|
||||
/**
|
||||
* board group table 을 주로 관리하는 class 입니다.
|
||||
*/
|
||||
class Board_group extends CI_Controller
|
||||
{
|
||||
|
||||
private $CI;
|
||||
private $group_id;
|
||||
private $group_key;
|
||||
private $group;
|
||||
private $admin;
|
||||
private $call_admin;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
$this->CI = & get_instance();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* board group 테이블에서 가져옵니다
|
||||
*/
|
||||
public function get_board_group($bgr_id = 0, $bgr_key = '')
|
||||
{
|
||||
if (empty($bgr_id) && empty($bgr_key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->CI->load->model('Board_group_model');
|
||||
if ($bgr_id) {
|
||||
$group = $this->CI->Board_group_model->get_one($bgr_id);
|
||||
} elseif ($bgr_key) {
|
||||
$where = array(
|
||||
'bgr_key' => $bgr_key,
|
||||
);
|
||||
$group = $this->CI->Board_group_model->get_one('', '', $where);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (element('bgr_id', $group)) {
|
||||
$group_meta = $this->get_all_meta(element('bgr_id', $group));
|
||||
if (is_array($group_meta)) {
|
||||
$group = array_merge($group, $group_meta);
|
||||
}
|
||||
}
|
||||
if (element('bgr_id', $group)) {
|
||||
$this->group_id[element('bgr_id', $group)] = $group;
|
||||
}
|
||||
if (element('bgr_key', $group)) {
|
||||
$this->group_key[element('bgr_key', $group)] = $group;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* board group 의 모든 meta 정보를 가져옵니다 테이블에서 가져옵니다
|
||||
*/
|
||||
public function get_all_meta($bgr_id = 0)
|
||||
{
|
||||
$bgr_id = (int) $bgr_id;
|
||||
if (empty($bgr_id) OR $bgr_id < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->CI->load->model('Board_group_meta_model');
|
||||
$result = $this->CI->Board_group_meta_model->get_all_meta($bgr_id);
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* group 의 item 을 bgr_id 기반으로 얻습니다
|
||||
*/
|
||||
public function item_id($column = '', $bgr_id = 0)
|
||||
{
|
||||
if (empty($column)) {
|
||||
return false;
|
||||
}
|
||||
$bgr_id = (int) $bgr_id;
|
||||
if (empty($bgr_id) OR $bgr_id < 1) {
|
||||
return false;
|
||||
}
|
||||
if (empty($this->group_id[$bgr_id])) {
|
||||
$this->get_board_group($bgr_id, '');
|
||||
}
|
||||
if (empty($this->group_id[$bgr_id])) {
|
||||
return false;
|
||||
}
|
||||
$group = $this->group_id[$bgr_id];
|
||||
return isset($group[$column]) ? $group[$column] : false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* group 의 item 을 bgr_key 기반으로 얻습니다
|
||||
*/
|
||||
public function item_key($column = '', $bgr_key = '')
|
||||
{
|
||||
if (empty($column)) {
|
||||
return false;
|
||||
}
|
||||
if (empty($bgr_key)) {
|
||||
return false;
|
||||
}
|
||||
if (empty($this->group_key[$bgr_key])) {
|
||||
$this->get_board_group('', $bgr_key);
|
||||
}
|
||||
if (empty($this->group_key[$bgr_key])) {
|
||||
return false;
|
||||
}
|
||||
$group = $this->group_key[$bgr_key];
|
||||
return isset($group[$column]) ? $group[$column] : false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* group 의 모든 item 을 bgr_id 기반으로 얻습니다
|
||||
*/
|
||||
public function item_all($bgr_id = 0)
|
||||
{
|
||||
$bgr_id = (int) $bgr_id;
|
||||
if (empty($bgr_id) OR $bgr_id < 1) {
|
||||
return false;
|
||||
}
|
||||
if (empty($this->group_id[$bgr_id])) {
|
||||
$this->get_board_group($bgr_id, '');
|
||||
}
|
||||
if (empty($this->group_id[$bgr_id])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->group_id[$bgr_id];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* group 의 모든 정보를 얻습니다
|
||||
*/
|
||||
public function get_group($bgr_id = 0)
|
||||
{
|
||||
$bgr_id = (int) $bgr_id;
|
||||
if (empty($bgr_id) OR $bgr_id < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->CI->load->model('Board_group_model');
|
||||
$group = $this->CI->Board_group_model->get_one($bgr_id);
|
||||
$group_meta = $this->get_all_meta($bgr_id);
|
||||
if (is_array($group_meta)) {
|
||||
$group = array_merge($group, $group_meta);
|
||||
}
|
||||
$this->group[$bgr_id] = $group;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* group 의 admin 인지를 판단합니다
|
||||
*/
|
||||
public function is_admin($bgr_id = 0)
|
||||
{
|
||||
$bgr_id = (int) $bgr_id;
|
||||
if (empty($bgr_id) OR $bgr_id < 1) {
|
||||
return false;
|
||||
}
|
||||
if ( ! $this->CI->member->item('mem_id')) {
|
||||
return false;
|
||||
}
|
||||
if ($this->call_admin) {
|
||||
return $this->admin;
|
||||
}
|
||||
$this->call_admin = true;
|
||||
$countwhere = array(
|
||||
'bgr_id' => $bgr_id,
|
||||
'mem_id' => $this->CI->member->item('mem_id'),
|
||||
);
|
||||
$this->CI->load->model('Board_group_admin_model');
|
||||
$count = $this->CI->Board_group_admin_model->count_by($countwhere);
|
||||
if ($count) {
|
||||
$this->admin = true;
|
||||
} else {
|
||||
$this->admin = false;
|
||||
}
|
||||
|
||||
return $this->admin;
|
||||
}
|
||||
}
|
||||
75
application/libraries/CB_Email.php
Normal file
75
application/libraries/CB_Email.php
Normal 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 CB_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';
|
||||
}
|
||||
}
|
||||
135
application/libraries/CB_Form_validation.php
Normal file
135
application/libraries/CB_Form_validation.php
Normal 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 CB_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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
83
application/libraries/CB_Pagination.php
Normal file
83
application/libraries/CB_Pagination.php
Normal 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 CB_Pagination extends CI_Pagination
|
||||
{
|
||||
|
||||
public $num_links = 5;
|
||||
public $cur_page = 1;
|
||||
public $use_page_numbers = true;
|
||||
public $first_link = '<span aria-hidden="true">«</span>';
|
||||
public $next_link = '<span aria-hidden="true">></span>';
|
||||
public $prev_link = '<span aria-hidden="true"><</span>';
|
||||
public $last_link = '<span aria-hidden="true">»</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();
|
||||
}
|
||||
}
|
||||
93
application/libraries/Cbconfig.php
Normal file
93
application/libraries/Cbconfig.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* Cbconfig class
|
||||
*
|
||||
* Copyright (c) CIBoard <www.ciboard.co.kr>
|
||||
*
|
||||
* @author CIBoard (develop@ciboard.co.kr)
|
||||
*/
|
||||
|
||||
/**
|
||||
* config table 을 관리하는 class 입니다.
|
||||
*/
|
||||
class Cbconfig 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;
|
||||
}
|
||||
}
|
||||
172
application/libraries/Events.php
Normal file
172
application/libraries/Events.php
Normal file
@@ -0,0 +1,172 @@
|
||||
<?php
|
||||
defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* Events
|
||||
*
|
||||
* A simple events system for CodeIgniter.
|
||||
*
|
||||
* @package CodeIgniter
|
||||
* @subpackage Events
|
||||
* @version 1.0
|
||||
* @author Eric Barnes <http://ericlbarnes.com>
|
||||
* @author Dan Horrigan <http://dhorrigan.com>
|
||||
* @license Apache License v2.0
|
||||
* @copyright 2010 Dan Horrigan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Events Library
|
||||
*/
|
||||
class Events
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array An array of listeners
|
||||
*/
|
||||
protected static $_listeners = array();
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Register
|
||||
*
|
||||
* Registers a Callback for a given event
|
||||
*
|
||||
* @access public
|
||||
* @param string The name of the event
|
||||
* @param array The callback for the Event
|
||||
* @return void
|
||||
*/
|
||||
public static function register($event, array $callback)
|
||||
{
|
||||
$key = get_class($callback[0]) . '::' . $callback[1];
|
||||
self::$_listeners[$event][$key] = $callback;
|
||||
self::log_message('debug', 'Events::register() - Registered "' . $key . ' with event "' . $event . '"');
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Trigger
|
||||
*
|
||||
* Triggers an event and returns the results. The results can be returned
|
||||
* in the following formats:
|
||||
*
|
||||
* 'array'
|
||||
* 'json'
|
||||
* 'serialized'
|
||||
* 'string'
|
||||
*
|
||||
* @access public
|
||||
* @param string The name of the event
|
||||
* @param mixed Any data that is to be passed to the listener
|
||||
* @param string The return type
|
||||
* @return mixed The return of the listeners, in the return type
|
||||
*/
|
||||
public static function trigger($event, $data = '', $return_type = 'array')
|
||||
{
|
||||
self::log_message('debug', 'Events::trigger() - Triggering event "' . $event . '"');
|
||||
|
||||
$calls = array();
|
||||
|
||||
if (self::has_listeners($event)) {
|
||||
foreach (self::$_listeners[$event] as $listener) {
|
||||
if (is_callable($listener)) {
|
||||
$calls[] = call_user_func($listener, $data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self::_format_return($calls, $return_type);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Format Return
|
||||
*
|
||||
* Formats the return in the given type
|
||||
*
|
||||
* @access protected
|
||||
* @param array The array of returns
|
||||
* @param string The return type
|
||||
* @return mixed The formatted return
|
||||
*/
|
||||
protected static function _format_return(array $calls, $return_type)
|
||||
{
|
||||
self::log_message('debug', 'Events::_format_return() - Formating calls in type "' . $return_type . '"');
|
||||
|
||||
switch ($return_type) {
|
||||
case 'json':
|
||||
return json_encode($calls);
|
||||
break;
|
||||
case 'serialized':
|
||||
return serialize($calls);
|
||||
break;
|
||||
case 'string':
|
||||
$str = '';
|
||||
foreach ($calls as $call) {
|
||||
$str .= $call;
|
||||
}
|
||||
return $str;
|
||||
break;
|
||||
default:
|
||||
return $calls;
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Has Listeners
|
||||
*
|
||||
* Checks if the event has listeners
|
||||
*
|
||||
* @access public
|
||||
* @param string The name of the event
|
||||
* @return bool Whether the event has listeners
|
||||
*/
|
||||
public static function has_listeners($event)
|
||||
{
|
||||
self::log_message('debug', 'Events::has_listeners() - Checking if event "' . $event . '" has listeners.');
|
||||
|
||||
if (isset(self::$_listeners[$event]) AND count(self::$_listeners[$event]) > 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Log Message
|
||||
*
|
||||
* Pulled out for unit testing
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $message
|
||||
* @return void
|
||||
*/
|
||||
public static function log_message($type = 'debug', $message = '')
|
||||
{
|
||||
if (function_exists('log_message')) {
|
||||
log_message($type, $message);
|
||||
}
|
||||
}
|
||||
}
|
||||
118
application/libraries/Imagelib.php
Normal file
118
application/libraries/Imagelib.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* Imagelib class
|
||||
*
|
||||
* Copyright (c) CIBoard <www.ciboard.co.kr>
|
||||
*
|
||||
* @author CIBoard (develop@ciboard.co.kr)
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
72
application/libraries/Ipfilter.php
Normal file
72
application/libraries/Ipfilter.php
Normal 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;
|
||||
}
|
||||
}
|
||||
378
application/libraries/Managelayout.php
Normal file
378
application/libraries/Managelayout.php
Normal file
@@ -0,0 +1,378 @@
|
||||
<?php
|
||||
defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* Managelayout class
|
||||
*
|
||||
* Copyright (c) CIBoard <www.ciboard.co.kr>
|
||||
*
|
||||
* @author CIBoard (develop@ciboard.co.kr)
|
||||
*/
|
||||
|
||||
/**
|
||||
* 레이아웃을 관리하는 class 입니다.
|
||||
*/
|
||||
class Managelayout extends CI_Controller
|
||||
{
|
||||
|
||||
private $css = array();
|
||||
private $js = array();
|
||||
|
||||
function __construct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 관리자페이지 레이아웃관리합니다
|
||||
*/
|
||||
function admin($config = array(), $device_view_type = '')
|
||||
{
|
||||
$data = array();
|
||||
$CI = & get_instance();
|
||||
$tmp = dir(APPPATH . 'config');
|
||||
$menu_files = array();
|
||||
while ($entry = $tmp->read()) {
|
||||
if (!preg_match('/^admin_menu_([0-9]{3}).*\.php$/', $entry, $m))
|
||||
continue;
|
||||
|
||||
$entry = substr($entry , 0, -4);
|
||||
$menu_files[] = $entry;
|
||||
}
|
||||
if ($menu_files) {
|
||||
asort($menu_files);
|
||||
}
|
||||
$data['admin_page_menu'] = array();
|
||||
foreach($menu_files as $file){
|
||||
$CI->load->config($file);
|
||||
$res = config_item('admin_page_menu');
|
||||
$data['admin_page_menu'] += config_item('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(0, 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/' . ADMIN_SKIN;
|
||||
$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->cbconfig->item('site_favicon') ? site_url(config_item('uploads_dir') . '/favicon/' . $CI->cbconfig->item('site_favicon')) : '';
|
||||
|
||||
$cachename = 'check_latest_version_from_ciboard_api';
|
||||
$cachetime = 10800;
|
||||
if ( ! $result = $CI->cache->get($cachename)) {
|
||||
$CI->load->library('Requests');
|
||||
$requests = new Requests();
|
||||
$requests->register_autoloader();
|
||||
$headers = array('Accept' => 'application/json');
|
||||
$postdata = array('requesturl' => current_full_url(), 'package' => CB_PACKAGE, 'version' => CB_VERSION);
|
||||
$request = $requests->post(config_item('ciboard_check_latest_version'), $headers, $postdata);
|
||||
$result['latest_versions'] = json_decode($request->body, true);
|
||||
if (strtolower(CB_PACKAGE) === 'pro') {
|
||||
$result['latest_version_name'] = $result['latest_versions']['pro_version'];
|
||||
$result['latest_download_url'] = $result['latest_versions']['pro_downloadurl'];
|
||||
} else {
|
||||
$result['latest_version_name'] = $result['latest_versions']['lite_version'];
|
||||
$result['latest_download_url'] = $result['latest_versions']['lite_downloadurl'];
|
||||
}
|
||||
$CI->cache->save($cachename, $result, $cachetime);
|
||||
|
||||
}
|
||||
$data['version_latest'] = $result;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 프론트페이지 레이아웃관리합니다
|
||||
*/
|
||||
function front($config = array(), $device_view_type = '')
|
||||
{
|
||||
$data = array();
|
||||
$CI = & get_instance();
|
||||
|
||||
if ($CI->uri->segment(1) === config_item('uri_segment_admin') && $CI->uri->segment(2) === 'preview') {
|
||||
return $this->preview($config);
|
||||
}
|
||||
|
||||
$searchconfig = array(
|
||||
'{홈페이지제목}',
|
||||
'{현재주소}',
|
||||
'{회원아이디}',
|
||||
'{회원닉네임}',
|
||||
'{회원레벨}',
|
||||
'{회원포인트}',
|
||||
);
|
||||
$replaceconfig = array(
|
||||
$CI->cbconfig->item('site_title'),
|
||||
current_full_url(),
|
||||
$CI->member->item('mem_userid'),
|
||||
$CI->member->item('mem_nickname'),
|
||||
$CI->member->item('mem_level'),
|
||||
$CI->member->item('mem_point'),
|
||||
);
|
||||
|
||||
$page_title = element('page_title', $config) ? element('page_title', $config) : $CI->cbconfig->item('site_meta_title_default');
|
||||
$meta_description = element('meta_description', $config) ? element('meta_description', $config) : $CI->cbconfig->item('site_meta_description_default');
|
||||
$meta_keywords = element('meta_keywords', $config) ? element('meta_keywords', $config) : $CI->cbconfig->item('site_meta_keywords_default');
|
||||
$meta_author = element('meta_author', $config) ? element('meta_author', $config) : $CI->cbconfig->item('site_meta_author_default');
|
||||
$page_name = element('page_name', $config) ? element('page_name', $config) : $CI->cbconfig->item('site_page_name_default');
|
||||
|
||||
$data['page_title'] = $page_title = str_replace($searchconfig, $replaceconfig, $page_title);
|
||||
$data['meta_description'] = $meta_description = str_replace($searchconfig, $replaceconfig, $meta_description);
|
||||
$data['meta_keywords'] = $meta_keywords = str_replace($searchconfig, $replaceconfig, $meta_keywords);
|
||||
$data['meta_author'] = $meta_author = str_replace($searchconfig, $replaceconfig, $meta_author);
|
||||
$data['page_name'] = $page_name = str_replace($searchconfig, $replaceconfig, $page_name);
|
||||
|
||||
$layoutdirname = $device_view_type === 'mobile' ? element('mobile_layout_dir', $config) : element('layout_dir', $config);
|
||||
if (empty($layoutdirname)) {
|
||||
$layoutdirname = $device_view_type === 'mobile' ? $CI->cbconfig->item('mobile_layout_default') : $CI->cbconfig->item('layout_default');
|
||||
}
|
||||
if (empty($layoutdirname)) {
|
||||
$layoutdirname = 'basic';
|
||||
}
|
||||
$layout = '_layout/' . $layoutdirname;
|
||||
$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;
|
||||
|
||||
$skindir = $device_view_type === 'mobile' ? element('mobile_skin_dir', $config) : element('skin_dir', $config);
|
||||
if (empty($skindir)) {
|
||||
$skindir = $device_view_type === 'mobile' ? $CI->cbconfig->item('mobile_skin_default') : $CI->cbconfig->item('skin_default');
|
||||
}
|
||||
if (empty($skindir)) {
|
||||
$skindir = 'basic';
|
||||
}
|
||||
$skin = '';
|
||||
if (element('path', $config)) {
|
||||
$skin .= element('path', $config) . '/';
|
||||
}
|
||||
$skin .= $skindir;
|
||||
$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;
|
||||
|
||||
$user_sidebar = $device_view_type === 'mobile' ? element('use_mobile_sidebar', $config) : element('use_sidebar', $config);
|
||||
if ($user_sidebar === '1') {
|
||||
$data['use_sidebar'] = '1';
|
||||
} elseif ($user_sidebar === '2') {
|
||||
$data['use_sidebar'] = '';
|
||||
} else {
|
||||
$user_sidebar = $device_view_type === 'mobile' ? $CI->cbconfig->item('mobile_sidebar_default') : $CI->cbconfig->item('sidebar_default');
|
||||
if ($user_sidebar === '1') {
|
||||
$data['use_sidebar'] = '1';
|
||||
} elseif ($user_sidebar === '2') {
|
||||
$data['use_sidebar'] = '';
|
||||
} else {
|
||||
$data['use_sidebar'] = '';
|
||||
}
|
||||
}
|
||||
|
||||
$data['favicon'] = $CI->cbconfig->item('site_favicon') ? site_url(config_item('uploads_dir') . '/favicon/' . $CI->cbconfig->item('site_favicon')) : '';
|
||||
|
||||
$mem_id = (int) $CI->member->item('mem_id');
|
||||
|
||||
if ($CI->input->is_ajax_request() === false) {
|
||||
|
||||
// 현재 접속자
|
||||
$CI->load->model('Currentvisitor_model');
|
||||
$currentpage = $page_name ? $page_name : $page_title;
|
||||
$currentpage = $currentpage ? $currentpage : $CI->cbconfig->item('site_title');
|
||||
$agent_referrer = $CI->agent->referrer() ? $CI->agent->referrer() : '';
|
||||
$agent_string = $CI->agent->agent_string() ? $CI->agent->agent_string() : '';
|
||||
$CI->Currentvisitor_model->add_visitor($CI->input->ip_address(), $mem_id,
|
||||
$CI->member->item('mem_nickname'), cdate('Y-m-d H:i:s'), $currentpage, current_full_url(), $agent_referrer, $agent_string);
|
||||
if ($CI->cbconfig->item('open_currentvisitor') OR $CI->member->is_admin() === 'super') {
|
||||
|
||||
$minute = (int) $CI->cbconfig->item('currentvisitor_minute');
|
||||
if ($minute < 1) {
|
||||
$minute = 10;
|
||||
}
|
||||
$curdatetime = cdate('Y-m-d H:i:s', ctimestamp() - $minute * 60);
|
||||
$data['current_visitor_num'] = $CI->Currentvisitor_model->get_current_count($curdatetime);
|
||||
}
|
||||
|
||||
// 알림
|
||||
$data['notification_num'] = 0;
|
||||
if ($CI->cbconfig->item('use_notification')) {
|
||||
if ($CI->member->is_member()) {
|
||||
$CI->load->model('Notification_model');
|
||||
$data['notification_num'] = $CI->Notification_model->unread_notification_num($mem_id);
|
||||
}
|
||||
}
|
||||
|
||||
// 메뉴관리
|
||||
$CI->load->model('Menu_model');
|
||||
$data['menu'] = $CI->Menu_model->get_all_menu($device_view_type);
|
||||
|
||||
//팝업관리
|
||||
$CI->load->library('popuplib');
|
||||
$data['popup'] = $CI->popuplib->display_popup();
|
||||
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 프리뷰 페이지를 위한 레이아웃관리입니다
|
||||
*/
|
||||
function preview($config = array())
|
||||
{
|
||||
|
||||
$data = array();
|
||||
$CI = & get_instance();
|
||||
|
||||
if ($CI->input->get('is_mobile')) {
|
||||
$CI->cbconfig->set_device_view_type('mobile');
|
||||
} else {
|
||||
$CI->cbconfig->set_device_view_type('pc');
|
||||
}
|
||||
|
||||
$device_view_type = $CI->cbconfig->get_device_view_type();
|
||||
$layoutdirname = $CI->input->get('layout');
|
||||
if (empty($layoutdirname)) {
|
||||
$layoutdirname = $device_view_type === 'mobile' ? $CI->cbconfig->item('mobile_layout_default') : $CI->cbconfig->item('layout_default');
|
||||
}
|
||||
if (empty($layoutdirname)) {
|
||||
$layoutdirname = 'basic';
|
||||
}
|
||||
$layout = '_layout/' . $layoutdirname;
|
||||
$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;
|
||||
|
||||
$skindir = $CI->input->get('skin');
|
||||
if (empty($skindir)) {
|
||||
$skindir = $device_view_type === 'mobile' ? $CI->cbconfig->item('mobile_skin_default') : $CI->cbconfig->item('skin_default');
|
||||
}
|
||||
if (empty($skindir)) {
|
||||
$skindir = 'basic';
|
||||
}
|
||||
$skin = '';
|
||||
if (element('path', $config)) {
|
||||
$skin .= element('path', $config) . '/';
|
||||
}
|
||||
$skin .= $skindir;
|
||||
$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;
|
||||
|
||||
$user_sidebar = $CI->input->get('sidebar');
|
||||
if ($user_sidebar === '1') {
|
||||
$data['use_sidebar'] = '1';
|
||||
} elseif ($user_sidebar === '2') {
|
||||
$data['use_sidebar'] = '';
|
||||
} else {
|
||||
$user_sidebar = $device_view_type === 'mobile' ? $CI->cbconfig->item('mobile_sidebar_default') : $CI->cbconfig->item('sidebar_default');
|
||||
if ($user_sidebar === '1') {
|
||||
$data['use_sidebar'] = '1';
|
||||
} elseif ($user_sidebar === '2') {
|
||||
$data['use_sidebar'] = '';
|
||||
} else {
|
||||
$data['use_sidebar'] = '';
|
||||
}
|
||||
}
|
||||
|
||||
// 메뉴관리
|
||||
$CI->load->model('Menu_model');
|
||||
$data['menu'] = $CI->Menu_model->get_all_menu($device_view_type);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
339
application/libraries/Member.php
Normal file
339
application/libraries/Member.php
Normal file
@@ -0,0 +1,339 @@
|
||||
<?php
|
||||
defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* Member class
|
||||
*
|
||||
* Copyright (c) CIBoard <www.ciboard.co.kr>
|
||||
*
|
||||
* @author CIBoard (develop@ciboard.co.kr)
|
||||
*/
|
||||
|
||||
/**
|
||||
* member table 을 관리하는 class 입니다.
|
||||
*/
|
||||
class Member extends CI_Controller
|
||||
{
|
||||
|
||||
private $CI;
|
||||
|
||||
private $mb;
|
||||
|
||||
private $member_group;
|
||||
|
||||
|
||||
function __construct()
|
||||
{
|
||||
$this->CI = & get_instance();
|
||||
$this->CI->load->model( array('Member_model'));
|
||||
$this->CI->load->helper( array('array'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 접속한 유저가 회원인지 아닌지를 판단합니다
|
||||
*/
|
||||
public function is_member()
|
||||
{
|
||||
if ($this->CI->session->userdata('mem_id')) {
|
||||
return $this->CI->session->userdata('mem_id');
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 접속한 유저가 관리자인지 아닌지를 판단합니다
|
||||
*/
|
||||
public function is_admin($check = array())
|
||||
{
|
||||
if ($this->item('mem_is_admin')) {
|
||||
return 'super';
|
||||
}
|
||||
if (element('group_id', $check)) {
|
||||
$this->CI->load->library('board_group');
|
||||
$is_group_admin = $this->CI->board_group->is_admin(element('group_id', $check));
|
||||
if ($is_group_admin) {
|
||||
return 'group';
|
||||
}
|
||||
}
|
||||
if (element('board_id', $check)) {
|
||||
$this->CI->load->library('board');
|
||||
$is_board_admin = $this->CI->board->is_admin(element('board_id', $check));
|
||||
if ($is_board_admin) {
|
||||
return 'board';
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* member, member_extra_vars, member_meta 테이블에서 정보를 가져옵니다
|
||||
*/
|
||||
public function get_member()
|
||||
{
|
||||
if ($this->is_member()) {
|
||||
if (empty($this->mb)) {
|
||||
$member = $this->CI->Member_model->get_by_memid($this->is_member());
|
||||
$extras = $this->get_all_extras(element('mem_id', $member));
|
||||
if (is_array($extras)) {
|
||||
$member = array_merge($member, $extras);
|
||||
}
|
||||
$metas = $this->get_all_meta(element('mem_id', $member));
|
||||
if (is_array($metas)) {
|
||||
$member = array_merge($member, $metas);
|
||||
}
|
||||
$member['social'] = $this->get_all_social_meta(element('mem_id', $member));
|
||||
$this->mb = $member;
|
||||
}
|
||||
return $this->mb;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get_member 에서 가져온 데이터의 item 을 보여줍니다
|
||||
*/
|
||||
public function item($column = '')
|
||||
{
|
||||
if (empty($column)) {
|
||||
return false;
|
||||
}
|
||||
if (empty($this->mb)) {
|
||||
$this->get_member();
|
||||
}
|
||||
if (empty($this->mb)) {
|
||||
return false;
|
||||
}
|
||||
$member = $this->mb;
|
||||
|
||||
return isset($member[$column]) ? $member[$column] : false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get_member 에서 가져온 데이터의 item 을 보여줍니다
|
||||
*/
|
||||
public function socialitem($column = '')
|
||||
{
|
||||
if (empty($column)) {
|
||||
return false;
|
||||
}
|
||||
if (empty($this->mb)) {
|
||||
$this->get_member();
|
||||
}
|
||||
if (empty($this->mb)) {
|
||||
return false;
|
||||
}
|
||||
$member = $this->mb;
|
||||
|
||||
return isset($member['social']) && isset($member['social'][$column]) ? $member['social'][$column] : false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 회원이 속한 그룹 정보를 가져옵니다
|
||||
*/
|
||||
public function group()
|
||||
{
|
||||
if (empty($this->member_group)) {
|
||||
$where = array(
|
||||
'mem_id' => $this->item('mem_id'),
|
||||
);
|
||||
$this->CI->load->model('Member_group_member_model');
|
||||
$this->member_group = $this->CI->Member_group_member_model->get('', '', $where, '', 0, 'mgm_id', 'ASC');
|
||||
}
|
||||
return $this->member_group;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* member_extra_vars 테이블에서 가져옵니다
|
||||
*/
|
||||
public function get_all_extras($mem_id = 0)
|
||||
{
|
||||
if (empty($mem_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->CI->load->model('Member_extra_vars_model');
|
||||
$result = $this->CI->Member_extra_vars_model->get_all_meta($mem_id);
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* member_meta 테이블에서 가져옵니다
|
||||
*/
|
||||
public function get_all_meta($mem_id = 0)
|
||||
{
|
||||
$mem_id = (int) $mem_id;
|
||||
if (empty($mem_id) OR $mem_id < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->CI->load->model('Member_meta_model');
|
||||
$result = $this->CI->Member_meta_model->get_all_meta($mem_id);
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* social_meta 테이블에서 가져옵니다
|
||||
*/
|
||||
public function get_all_social_meta($mem_id = 0)
|
||||
{
|
||||
$mem_id = (int) $mem_id;
|
||||
if (empty($mem_id) OR $mem_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($mem_id);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 로그인 기록을 남깁니다
|
||||
*/
|
||||
public function update_login_log($mem_id= 0, $userid = '', $success= 0, $reason = '')
|
||||
{
|
||||
$success = $success ? 1 : 0;
|
||||
$mem_id = (int) $mem_id ? (int) $mem_id : 0;
|
||||
$reason = isset($reason) ? $reason : '';
|
||||
$referer = $this->CI->input->get_post('url', null, '');
|
||||
$loginlog = array(
|
||||
'mll_success' => $success,
|
||||
'mem_id' => $mem_id,
|
||||
'mll_userid' => $userid,
|
||||
'mll_datetime' => cdate('Y-m-d H:i:s'),
|
||||
'mll_ip' => $this->CI->input->ip_address(),
|
||||
'mll_reason' => $reason,
|
||||
'mll_useragent' => $this->CI->agent->agent_string(),
|
||||
'mll_url' => current_full_url(),
|
||||
'mll_referer' => $referer,
|
||||
);
|
||||
$this->CI->load->model('Member_login_log_model');
|
||||
$this->CI->Member_login_log_model->insert($loginlog);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 회원삭제 남깁니다
|
||||
*/
|
||||
public function delete_member($mem_id = 0)
|
||||
{
|
||||
$mem_id = (int) $mem_id;
|
||||
if (empty($mem_id) OR $mem_id < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->CI->load->model(
|
||||
array(
|
||||
'Autologin_model', 'Board_admin_model', 'Board_group_admin_model', 'Follow_model',
|
||||
'Member_model', 'Member_auth_email_model', 'Member_dormant_model',
|
||||
'Member_dormant_notify_model', 'Member_extra_vars_model', 'Member_group_member_model',
|
||||
'Member_level_history_model', 'Member_login_log_model', 'Member_meta_model',
|
||||
'Member_register_model', 'Notification_model', 'Point_model',
|
||||
'Scrap_model', 'Social_meta_model',
|
||||
'Tempsave_model', 'Member_userid_model',
|
||||
)
|
||||
);
|
||||
|
||||
$deletewhere = array(
|
||||
'mem_id' => $mem_id,
|
||||
);
|
||||
$this->CI->Autologin_model->delete_where($deletewhere);
|
||||
$this->CI->Board_admin_model->delete_where($deletewhere);
|
||||
$this->CI->Board_group_admin_model->delete_where($deletewhere);
|
||||
$this->CI->Follow_model->delete_where($deletewhere);
|
||||
$this->CI->Member_model->delete_where($deletewhere);
|
||||
$this->CI->Member_auth_email_model->delete_where($deletewhere);
|
||||
$this->CI->Member_dormant_model->delete_where($deletewhere);
|
||||
$this->CI->Member_dormant_notify_model->delete_where($deletewhere);
|
||||
$this->CI->Member_extra_vars_model->delete_where($deletewhere);
|
||||
$this->CI->Member_group_member_model->delete_where($deletewhere);
|
||||
$this->CI->Member_level_history_model->delete_where($deletewhere);
|
||||
$this->CI->Member_login_log_model->delete_where($deletewhere);
|
||||
$this->CI->Member_meta_model->delete_where($deletewhere);
|
||||
$this->CI->Member_register_model->delete_where($deletewhere);
|
||||
$this->CI->Notification_model->delete_where($deletewhere);
|
||||
$this->CI->Point_model->delete_where($deletewhere);
|
||||
$this->CI->Scrap_model->delete_where($deletewhere);
|
||||
$this->CI->Social_meta_model->delete_where($deletewhere);
|
||||
$this->CI->Tempsave_model->delete_where($deletewhere);
|
||||
|
||||
$this->CI->Member_userid_model->update($mem_id, array('mem_status' => 1));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 휴면처리시 별도의 저장소로 이동하는 프로세스입니다
|
||||
*/
|
||||
public function archive_to_dormant($mem_id = 0)
|
||||
{
|
||||
$mem_id = (int) $mem_id;
|
||||
if (empty($mem_id) OR $mem_id < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->CI->load->model(array('Member_model', 'Member_dormant_model', 'Member_meta_model', 'Member_userid_model'));
|
||||
|
||||
$data = $this->CI->Member_model->get_one($mem_id);
|
||||
$cleanpoint = (-1) * element('mem_point', $data);
|
||||
$point_content = '휴면회원 전환으로 인한 포인트 초기화 (' . cdate('Y-m-d H:i:s') . ')';
|
||||
|
||||
if ($this->CI->cbconfig->item('member_dormant_reset_point')) {
|
||||
$this->CI->load->library('point');
|
||||
$point = $this->CI->point->insert_point(
|
||||
$mem_id,
|
||||
$cleanpoint,
|
||||
$point_content,
|
||||
'@member_dormant',
|
||||
$mem_id,
|
||||
$mem_id . '-' . uniqid('')
|
||||
);
|
||||
}
|
||||
|
||||
$this->CI->Member_dormant_model->insert($data);
|
||||
$this->CI->Member_model->delete($mem_id);
|
||||
$metadata = array('archived_dormant_datetime' => cdate('Y-m-d H:i:s'));
|
||||
$this->CI->Member_meta_model->save($mem_id, $metadata);
|
||||
$this->CI->Member_userid_model->update($mem_id, array('mem_status' => 2));
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 휴면상태에 있던 회원을 원래 회원 디비로 복원하는 프로세스입니다
|
||||
*/
|
||||
public function recover_from_dormant($mem_id = 0)
|
||||
{
|
||||
$mem_id = (int) $mem_id;
|
||||
if (empty($mem_id) OR $mem_id < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->CI->load->model(array('Member_model', 'Member_dormant_model', 'Member_meta_model', 'Member_userid_model'));
|
||||
|
||||
$data = $this->CI->Member_dormant_model->get_one($mem_id);
|
||||
$this->CI->Member_model->insert($data);
|
||||
$this->CI->Member_dormant_model->delete($mem_id);
|
||||
$metadata = array('archived_dormant_datetime' => '');
|
||||
$this->CI->Member_meta_model->save($mem_id, $metadata);
|
||||
$this->CI->Member_userid_model->update($mem_id, array('mem_status' => 0));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
1436
application/libraries/Mobile_detect.php
Normal file
1436
application/libraries/Mobile_detect.php
Normal file
File diff suppressed because one or more lines are too long
191
application/libraries/Notelib.php
Normal file
191
application/libraries/Notelib.php
Normal file
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* Notelib class
|
||||
*
|
||||
* Copyright (c) CIBoard <www.ciboard.co.kr>
|
||||
*
|
||||
* @author CIBoard (develop@ciboard.co.kr)
|
||||
*/
|
||||
|
||||
/**
|
||||
* 쪽지 발송을 관리하는 class 입니다.
|
||||
*/
|
||||
class Notelib extends CI_Controller
|
||||
{
|
||||
|
||||
private $CI;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
$this->CI = & get_instance();
|
||||
$this->CI->load->model( array('Note_model', 'Member_meta_model'));
|
||||
$this->CI->load->helper( array('array'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 쪽지를 발송하는 함수입니다
|
||||
*/
|
||||
public function send_note($sender = '', $receiver = '', $title = '', $content = '', $content_type = '', $originfilename = '', $uploadfilename = '')
|
||||
{
|
||||
// 포인트 사용을 하지 않는다면 return
|
||||
if ( ! $this->CI->cbconfig->item('use_note')) {
|
||||
$result = json_encode( array('error' => '쪽지를 사용하지 않는 사이트입니다'));
|
||||
return $result;
|
||||
}
|
||||
if ($sender && ! is_numeric($sender)) {
|
||||
$result = json_encode( array('error' => '보내는 이가 잘못되었습니다'));
|
||||
return $result;
|
||||
}
|
||||
if (empty($sender)) {
|
||||
$sender = 0; // 사이트 관리자가 보낸 경우임
|
||||
}
|
||||
if (empty($receiver)) {
|
||||
$result = json_encode( array('error' => '받는이가 지정되지 않았습니다'));
|
||||
return $result;
|
||||
}
|
||||
if (empty($title)) {
|
||||
$result = json_encode( array('error' => '쪽지 제목이 존재하지 않습니다'));
|
||||
return $result;
|
||||
}
|
||||
if (empty($content)) {
|
||||
$result = json_encode( array('error' => '쪽지 내용이 존재하지 않습니다'));
|
||||
return $result;
|
||||
}
|
||||
if ( ! $this->CI->cbconfig->item('use_note_file')) {
|
||||
if ($originfilename OR $uploadfilename) {
|
||||
$result = json_encode( array('error' => '쪽지에 첨부파일 기능을 지원하지 않습니다'));
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
$point_note = $this->CI->cbconfig->item('use_point')
|
||||
? $this->CI->cbconfig->item('point_note') : 0;
|
||||
|
||||
$point_note_file = ($uploadfilename && $this->CI->cbconfig->item('use_point'))
|
||||
? $this->CI->cbconfig->item('point_note_file') : 0;
|
||||
|
||||
$send_member = '';
|
||||
if ($sender) {
|
||||
$select = 'mem_id, mem_point, mem_use_note, mem_is_admin, mem_nickname';
|
||||
$send_member = $this->CI->Member_model->get_by_memid($sender, $select);
|
||||
if ( ! element('mem_id', $send_member)) {
|
||||
$result = json_encode( array('error' => '보내는이가 존재하지 않습니다'));
|
||||
return $result;
|
||||
}
|
||||
if ( ! element('mem_use_note', $send_member) && ! element('mem_is_admin', $send_member)) {
|
||||
$result = json_encode( array('error' => '보내는이가 쪽지기능을 사용하지 않습니다'));
|
||||
return $result;
|
||||
}
|
||||
if ((element('mem_point', $send_member) < $point_note) && $this->CI->member->is_admin() !== 'super') {
|
||||
$result = json_encode( array('error' => '보유하신 포인트가 모자라 쪽지를 보낼 수 없습니다, 쪽지발송에는 ' . number_format($point_note) . '점이 필요합니다'));
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
$recv_member = '';
|
||||
if ($receiver) {
|
||||
$select = 'mem_id, mem_point, mem_use_note, mem_nickname, mem_denied';
|
||||
$recv_member = $this->CI->Member_model->get_by_memid($receiver, $select);
|
||||
if ( ! element('mem_id', $recv_member)) {
|
||||
$result = json_encode( array('error' => '받는이가 존재하지 않습니다'));
|
||||
return $result;
|
||||
}
|
||||
if (element('mem_denied', $recv_member)) {
|
||||
$result = json_encode( array('error' => '받는이가 존재하지 않습니다'));
|
||||
return $result;
|
||||
}
|
||||
if ( ! element('mem_use_note', $recv_member)) {
|
||||
$result = json_encode( array('error' => '받는이가 쪽지기능을 사용하지 않습니다'));
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($content_type)) {
|
||||
$content_type = 0;
|
||||
}
|
||||
$nte_content_html_type = $content_type;
|
||||
$insertdata = array(
|
||||
'send_mem_id' => $sender,
|
||||
'recv_mem_id' => $receiver,
|
||||
'nte_type' => 1,
|
||||
'nte_title' => $title,
|
||||
'nte_content' => $content,
|
||||
'nte_content_html_type' => $nte_content_html_type,
|
||||
'nte_datetime' => cdate('Y-m-d H:i:s'),
|
||||
'nte_originname' => $originfilename,
|
||||
'nte_filename' => $uploadfilename,
|
||||
);
|
||||
$note_id = $this->CI->Note_model->insert($insertdata);
|
||||
|
||||
$unread_note_num = $this->CI->Member_meta_model->item($receiver, 'meta_unread_note_num') + 1;
|
||||
$metadata = array(
|
||||
'meta_note_received_datetime' => cdate('Y-m-d H:i:s'),
|
||||
'meta_note_received_from_id' => $sender,
|
||||
'meta_note_received_from_nickname' => element('mem_nickname', $send_member),
|
||||
'meta_unread_note_num' => $unread_note_num,
|
||||
);
|
||||
$this->CI->Member_meta_model->save($receiver, $metadata);
|
||||
|
||||
if ($sender) {
|
||||
$insertdata = array(
|
||||
'send_mem_id' => $sender,
|
||||
'recv_mem_id' => $receiver,
|
||||
'nte_type' => 2,
|
||||
'related_note_id' => $note_id,
|
||||
'nte_title' => $title,
|
||||
'nte_content' => $content,
|
||||
'nte_content_html_type' => $nte_content_html_type,
|
||||
'nte_datetime' => cdate('Y-m-d H:i:s'),
|
||||
'nte_originname' => $originfilename,
|
||||
'nte_filename' => $uploadfilename,
|
||||
);
|
||||
$note_id2 = $this->CI->Note_model->insert($insertdata);
|
||||
|
||||
if ($this->CI->cbconfig->item('use_point') && $point_note && $point_note > 0) {
|
||||
$point = 0 - $point_note;
|
||||
$this->CI->load->library('point');
|
||||
$this->CI->point->insert_point(
|
||||
$sender,
|
||||
$point,
|
||||
element('mem_nickname', $recv_member) . '님께 쪽지 발송',
|
||||
'note',
|
||||
$note_id,
|
||||
$note_id . ' 쪽지 발송'
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->CI->cbconfig->item('use_point') && $point_note_file && $point_note_file > 0) {
|
||||
$point = 0 - $point_note_file;
|
||||
$this->CI->load->library('point');
|
||||
$this->CI->point->insert_point(
|
||||
$sender,
|
||||
$point,
|
||||
element('mem_nickname', $recv_member) . '님께 발송한 쪽지에 파일첨부',
|
||||
'note',
|
||||
$note_id,
|
||||
$note_id . ' 쪽지 발송 파일첨부'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->CI->cbconfig->item('use_notification') && $this->CI->cbconfig->item('notification_note')) {
|
||||
$this->CI->load->library('notificationlib');
|
||||
$sender_name = $sender ? element('mem_nickname', $send_member) : '알림';
|
||||
$not_message = $sender_name . '님께서 [' . $title . '] 쪽지를 남기셨습니다';
|
||||
$not_url = site_url('note/view/recv/' . $note_id);
|
||||
$return = $this->CI->notificationlib->set_noti(
|
||||
$receiver,
|
||||
$sender,
|
||||
'note',
|
||||
$note_id,
|
||||
$not_message,
|
||||
$not_url
|
||||
);
|
||||
}
|
||||
|
||||
$result = json_encode( array('success' => element('mem_nickname', $recv_member) . '님께 쪽지를 발송하였습니다'));
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
111
application/libraries/Notificationlib.php
Normal file
111
application/libraries/Notificationlib.php
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* Notificationlib class
|
||||
*
|
||||
* Copyright (c) CIBoard <www.ciboard.co.kr>
|
||||
*
|
||||
* @author CIBoard (develop@ciboard.co.kr)
|
||||
*/
|
||||
|
||||
/**
|
||||
* 알림 기능을 관리하는 class 입니다.
|
||||
*/
|
||||
class Notificationlib extends CI_Controller
|
||||
{
|
||||
|
||||
private $CI;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
$this->CI = & get_instance();
|
||||
$this->CI->load->model( array('Notification_model'));
|
||||
$this->CI->load->helper( array('array'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 알림 내용을 인서트하는 함수입니다
|
||||
*/
|
||||
public function set_noti($mem_id = 0, $target_mem_id = 0, $not_type = '', $not_content_id = '', $not_message = '', $not_url = '')
|
||||
{
|
||||
$mem_id = (int) $mem_id;
|
||||
$target_mem_id = (int) $target_mem_id;
|
||||
|
||||
if (empty($mem_id) OR $mem_id < 1) {
|
||||
$result = json_encode( array('error' => 'mem_id 가 존재하지 않습니다'));
|
||||
return $result;
|
||||
}
|
||||
if (empty($not_type)) {
|
||||
$result = json_encode( array('error' => 'not_type 가 존재하지 않습니다'));
|
||||
return $result;
|
||||
}
|
||||
if (empty($not_content_id)) {
|
||||
$result = json_encode( array('error' => 'not_content_id 가 존재하지 않습니다'));
|
||||
return $result;
|
||||
}
|
||||
if ($mem_id === $target_mem_id) {
|
||||
$result = json_encode( array('error' => 'mem_id 와 target_mem_id 이 같으므로 알림을 저장하지 않습니다'));
|
||||
return $result;
|
||||
}
|
||||
if (empty($not_message)) {
|
||||
$result = json_encode( array('error' => '알림 내용이 존재하지 않습니다'));
|
||||
return $result;
|
||||
}
|
||||
if (empty($not_url)) {
|
||||
$result = json_encode( array('error' => '알림 URL이 존재하지 않습니다'));
|
||||
return $result;
|
||||
}
|
||||
|
||||
// 알림 기능을 사용을 하지 않는다면 return
|
||||
if ( ! $this->CI->cbconfig->item('use_notification')) {
|
||||
$result = json_encode( array('error' => '알림을 사용하지 않는 사이트입니다'));
|
||||
return $result;
|
||||
}
|
||||
switch ($not_type) {
|
||||
case 'reply':
|
||||
if ( ! $this->CI->cbconfig->item('notification_reply')) {
|
||||
$result = json_encode( array('error' => '답변글에 알림 기능을 사용하지 않습니다'));
|
||||
return $result;
|
||||
}
|
||||
break;
|
||||
case 'comment':
|
||||
if ( ! $this->CI->cbconfig->item('notification_comment')) {
|
||||
$result = json_encode( array('error' => '댓글에 알림 기능을 사용하지 않습니다'));
|
||||
return $result;
|
||||
}
|
||||
break;
|
||||
case 'comment_comment':
|
||||
if ( ! $this->CI->cbconfig->item('notification_comment_comment')) {
|
||||
$result = json_encode( array('error' => '댓글의 댓글에 알림 기능을 사용하지 않습니다'));
|
||||
return $result;
|
||||
}
|
||||
break;
|
||||
case 'note':
|
||||
if ( ! $this->CI->cbconfig->item('notification_note')) {
|
||||
$result = json_encode( array('error' => '쪽지에 알림 기능을 사용하지 않습니다'));
|
||||
return $result;
|
||||
}
|
||||
break;
|
||||
default :
|
||||
$result = json_encode( array('error' => 'TYPE 이 잘못되었습니다'));
|
||||
return $result;
|
||||
|
||||
}
|
||||
$insertdata = array(
|
||||
'mem_id' => $mem_id,
|
||||
'target_mem_id' => $target_mem_id,
|
||||
'not_type' => $not_type,
|
||||
'not_content_id' => $not_content_id,
|
||||
'not_message' => $not_message,
|
||||
'not_url' => $not_url,
|
||||
'not_datetime' => cdate('Y-m-d H:i:s'),
|
||||
);
|
||||
$not_id = $this->CI->Notification_model->insert($insertdata);
|
||||
|
||||
$result = json_encode( array('success' => '알림이 저장되었습니다'));
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
252
application/libraries/PasswordHash.php
Normal file
252
application/libraries/PasswordHash.php
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
196
application/libraries/Phpuseragent.php
Normal file
196
application/libraries/Phpuseragent.php
Normal 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']);
|
||||
}
|
||||
|
||||
}
|
||||
323
application/libraries/Phpuseragentstringparser.php
Normal file
323
application/libraries/Phpuseragentstringparser.php
Normal 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']);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
166
application/libraries/Point.php
Normal file
166
application/libraries/Point.php
Normal file
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* Point class
|
||||
*
|
||||
* Copyright (c) CIBoard <www.ciboard.co.kr>
|
||||
*
|
||||
* @author CIBoard (develop@ciboard.co.kr)
|
||||
*/
|
||||
|
||||
/**
|
||||
* 포인트 추가 및 삭제를 관리하는 class 입니다.
|
||||
*/
|
||||
class Point extends CI_Controller
|
||||
{
|
||||
|
||||
private $CI;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
$this->CI = & get_instance();
|
||||
$this->CI->load->helper( array('array'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 포인트를 추가합니다
|
||||
*/
|
||||
public function insert_point($mem_id = 0, $point = 0, $content = '', $poi_type = '', $poi_related_id = '', $poi_action = '')
|
||||
{
|
||||
// 포인트 사용을 하지 않는다면 return
|
||||
if ( ! $this->CI->cbconfig->item('use_point')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 포인트가 없다면 업데이트 할 필요 없음
|
||||
$point = (int) $point;
|
||||
if (empty($point)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 회원아이디가 없다면 업데이트 할 필요 없음
|
||||
$mem_id = (int) $mem_id;
|
||||
if (empty($mem_id) OR $mem_id < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($content)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($poi_type) && empty($poi_related_id) && empty($poi_action)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$member = $this->CI->Member_model->get_by_memid($mem_id, 'mem_id');
|
||||
|
||||
if ( ! element('mem_id', $member)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->CI->load->model('Point_model');
|
||||
|
||||
// 이미 등록된 내역이라면 건너뜀
|
||||
if ($poi_type OR $poi_related_id OR $poi_action) {
|
||||
$where = array(
|
||||
'mem_id' => $mem_id,
|
||||
'poi_type' => $poi_type,
|
||||
'poi_related_id' => $poi_related_id,
|
||||
'poi_action' => $poi_action,
|
||||
);
|
||||
$cnt = $this->CI->Point_model->count_by($where);
|
||||
|
||||
if ($cnt > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$insertdata = array(
|
||||
'mem_id' => $mem_id,
|
||||
'poi_datetime' => cdate('Y-m-d H:i:s'),
|
||||
'poi_content' => $content,
|
||||
'poi_point' => $point,
|
||||
'poi_type' => $poi_type,
|
||||
'poi_related_id' => $poi_related_id,
|
||||
'poi_action' => $poi_action,
|
||||
);
|
||||
$this->CI->Point_model->insert($insertdata);
|
||||
|
||||
$sum = $this->CI->Point_model->get_point_sum($mem_id);
|
||||
|
||||
$updatedata = array(
|
||||
'mem_point' => $sum,
|
||||
);
|
||||
$this->CI->Member_model->update($mem_id, $updatedata);
|
||||
|
||||
return $sum;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 포인트를 삭제합니다
|
||||
*/
|
||||
public function delete_point($mem_id = 0, $poi_type = '', $poi_related_id = '', $poi_action = '')
|
||||
{
|
||||
$mem_id = (int) $mem_id;
|
||||
if (empty($mem_id) OR $mem_id < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($poi_type OR $poi_related_id OR $poi_action) {
|
||||
$this->CI->load->model('Point_model');
|
||||
|
||||
$where = array(
|
||||
'mem_id' => $mem_id,
|
||||
'poi_type' => $poi_type,
|
||||
'poi_related_id' => $poi_related_id,
|
||||
'poi_action' => $poi_action,
|
||||
);
|
||||
$this->CI->Point_model->delete_where($where);
|
||||
|
||||
// 포인트 내역의 합을 구하고
|
||||
$sum = $this->CI->Point_model->get_point_sum($mem_id);
|
||||
$updatedata = array(
|
||||
'mem_point' => $sum,
|
||||
);
|
||||
$this->CI->Member_model->update($mem_id, $updatedata);
|
||||
|
||||
return $sum;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 포인트 PK 를 이용한 포인트 삭제입니다.
|
||||
*/
|
||||
public function delete_point_by_pk($poi_id = 0)
|
||||
{
|
||||
$poi_id = (int) $poi_id;
|
||||
if (empty($poi_id) OR $poi_id < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->CI->load->model('Point_model');
|
||||
|
||||
$result = $this->CI->Point_model->get_one($poi_id, 'mem_id');
|
||||
$this->CI->Point_model->delete($poi_id);
|
||||
|
||||
if (element('mem_id', $result)) {
|
||||
$mem_id = element('mem_id', $result);
|
||||
// 포인트 내역의 합을 구하고
|
||||
$sum = $this->CI->Point_model->get_point_sum($mem_id);
|
||||
$updatedata = array(
|
||||
'mem_point' => $sum,
|
||||
);
|
||||
$this->CI->Member_model->update($mem_id, $updatedata);
|
||||
|
||||
return $sum;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
114
application/libraries/Popuplib.php
Normal file
114
application/libraries/Popuplib.php
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* Popuplib class
|
||||
*
|
||||
* Copyright (c) CIBoard <www.ciboard.co.kr>
|
||||
*
|
||||
* @author CIBoard (develop@ciboard.co.kr)
|
||||
*/
|
||||
|
||||
/**
|
||||
* 팝업을 관리하는 class 입니다.
|
||||
*/
|
||||
class Popuplib extends CI_Controller
|
||||
{
|
||||
|
||||
private $CI;
|
||||
private $today_popup_data;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
$this->CI = & get_instance();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 오늘 보여줘야할 팝업이 있는지를 체크합니다
|
||||
*/
|
||||
public function get_today_popup_data()
|
||||
{
|
||||
if (empty($this->today_popup_data)) {
|
||||
$this->CI->load->model( array('Popup_model'));
|
||||
$this->today_popup_data = $this->CI->Popup_model->get_today_list();
|
||||
}
|
||||
|
||||
return $this->today_popup_data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 팝업을 보여줍니다
|
||||
*/
|
||||
public function display_popup()
|
||||
{
|
||||
/**
|
||||
* 레이아웃을 정의합니다
|
||||
*/
|
||||
$pagetitle = '팝업알림';
|
||||
$skin_file = 'popup';
|
||||
|
||||
$skindir = ($this->CI->cbconfig->get_device_view_type() === 'mobile')
|
||||
? $this->CI->cbconfig->item('mobile_skin_popup')
|
||||
: $this->CI->cbconfig->item('skin_popup');
|
||||
if (empty($skindir)) {
|
||||
$skindir = ($this->CI->cbconfig->get_device_view_type() === 'mobile')
|
||||
? $this->CI->cbconfig->item('mobile_skin_default')
|
||||
: $this->CI->cbconfig->item('skin_default');
|
||||
}
|
||||
|
||||
$view_skin_file = 'popup/' . $skindir . '/' . $skin_file;
|
||||
|
||||
$view = array();
|
||||
$view['view'] = array();
|
||||
|
||||
$view['view'] = $this->get_today_popup_data();
|
||||
$list = array();
|
||||
if (element('list', element('view', $view))) {
|
||||
foreach (element('list', element('view', $view)) as $key => $value) {
|
||||
if (get_cookie('popup_layer_' . element('pop_id', $value))) {
|
||||
continue;
|
||||
}
|
||||
if ($this->CI->cbconfig->get_device_view_type() === 'mobile'
|
||||
&& element('pop_device', $value) === 'pc') {
|
||||
continue;
|
||||
}
|
||||
if ($this->CI->cbconfig->get_device_view_type() !== 'mobile'
|
||||
&& element('pop_device', $value) === 'mobile') {
|
||||
continue;
|
||||
}
|
||||
if ( ! element('pop_page', $value)
|
||||
&& $this->CI->uri->segment(1)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$content = element('pop_content', $value);
|
||||
$thumb_width = ($this->CI->cbconfig->get_device_view_type() === 'mobile')
|
||||
? $this->CI->cbconfig->item('popup_mobile_thumb_width')
|
||||
: $this->CI->cbconfig->item('popup_thumb_width');
|
||||
$autolink = ($this->CI->cbconfig->get_device_view_type() === 'mobile')
|
||||
? $this->CI->cbconfig->item('use_popup_mobile_auto_url')
|
||||
: $this->CI->cbconfig->item('use_popup_auto_url');
|
||||
$popup = ($this->CI->cbconfig->get_device_view_type() === 'mobile')
|
||||
? $this->CI->cbconfig->item('popup_mobile_content_target_blank')
|
||||
: $this->CI->cbconfig->item('popup_content_target_blank');
|
||||
|
||||
$value['content'] = display_html_content(
|
||||
$content,
|
||||
element('pop_content_html_type', $value),
|
||||
$thumb_width,
|
||||
$autolink,
|
||||
$popup,
|
||||
$writer_is_admin = true
|
||||
);
|
||||
|
||||
$list[] = $value;
|
||||
}
|
||||
}
|
||||
$view['view']['popup'] = $list;
|
||||
if ($list) {
|
||||
return $this->CI->load->view($view_skin_file, $view, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
62
application/libraries/Querystring.php
Normal file
62
application/libraries/Querystring.php
Normal 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', '')) . '&findex=' . $findex . '&forder=' . $forder;
|
||||
}
|
||||
|
||||
return '?' . $param_qstr;
|
||||
}
|
||||
}
|
||||
872
application/libraries/Requests.php
Normal file
872
application/libraries/Requests.php
Normal 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, Ruby’s 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;
|
||||
}
|
||||
}
|
||||
33
application/libraries/Requests/Auth.php
Normal file
33
application/libraries/Requests/Auth.php
Normal 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);
|
||||
}
|
||||
88
application/libraries/Requests/Auth/Basic.php
Normal file
88
application/libraries/Requests/Auth/Basic.php
Normal 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;
|
||||
}
|
||||
}
|
||||
171
application/libraries/Requests/Cookie.php
Normal file
171
application/libraries/Requests/Cookie.php
Normal 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;
|
||||
}
|
||||
}
|
||||
146
application/libraries/Requests/Cookie/Jar.php
Normal file
146
application/libraries/Requests/Cookie/Jar.php
Normal 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;
|
||||
}
|
||||
}
|
||||
62
application/libraries/Requests/Exception.php
Normal file
62
application/libraries/Requests/Exception.php
Normal 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;
|
||||
}
|
||||
}
|
||||
67
application/libraries/Requests/Exception/HTTP.php
Normal file
67
application/libraries/Requests/Exception/HTTP.php
Normal 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';
|
||||
}
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/400.php
Normal file
27
application/libraries/Requests/Exception/HTTP/400.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/401.php
Normal file
27
application/libraries/Requests/Exception/HTTP/401.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/402.php
Normal file
27
application/libraries/Requests/Exception/HTTP/402.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/403.php
Normal file
27
application/libraries/Requests/Exception/HTTP/403.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/404.php
Normal file
27
application/libraries/Requests/Exception/HTTP/404.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/405.php
Normal file
27
application/libraries/Requests/Exception/HTTP/405.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/406.php
Normal file
27
application/libraries/Requests/Exception/HTTP/406.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/407.php
Normal file
27
application/libraries/Requests/Exception/HTTP/407.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/408.php
Normal file
27
application/libraries/Requests/Exception/HTTP/408.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/409.php
Normal file
27
application/libraries/Requests/Exception/HTTP/409.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/410.php
Normal file
27
application/libraries/Requests/Exception/HTTP/410.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/411.php
Normal file
27
application/libraries/Requests/Exception/HTTP/411.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/412.php
Normal file
27
application/libraries/Requests/Exception/HTTP/412.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/413.php
Normal file
27
application/libraries/Requests/Exception/HTTP/413.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/414.php
Normal file
27
application/libraries/Requests/Exception/HTTP/414.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/415.php
Normal file
27
application/libraries/Requests/Exception/HTTP/415.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/416.php
Normal file
27
application/libraries/Requests/Exception/HTTP/416.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/417.php
Normal file
27
application/libraries/Requests/Exception/HTTP/417.php
Normal 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';
|
||||
}
|
||||
29
application/libraries/Requests/Exception/HTTP/418.php
Normal file
29
application/libraries/Requests/Exception/HTTP/418.php
Normal 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";
|
||||
}
|
||||
29
application/libraries/Requests/Exception/HTTP/428.php
Normal file
29
application/libraries/Requests/Exception/HTTP/428.php
Normal 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';
|
||||
}
|
||||
29
application/libraries/Requests/Exception/HTTP/429.php
Normal file
29
application/libraries/Requests/Exception/HTTP/429.php
Normal 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';
|
||||
}
|
||||
29
application/libraries/Requests/Exception/HTTP/431.php
Normal file
29
application/libraries/Requests/Exception/HTTP/431.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/500.php
Normal file
27
application/libraries/Requests/Exception/HTTP/500.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/501.php
Normal file
27
application/libraries/Requests/Exception/HTTP/501.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/502.php
Normal file
27
application/libraries/Requests/Exception/HTTP/502.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/503.php
Normal file
27
application/libraries/Requests/Exception/HTTP/503.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/504.php
Normal file
27
application/libraries/Requests/Exception/HTTP/504.php
Normal 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';
|
||||
}
|
||||
27
application/libraries/Requests/Exception/HTTP/505.php
Normal file
27
application/libraries/Requests/Exception/HTTP/505.php
Normal 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';
|
||||
}
|
||||
29
application/libraries/Requests/Exception/HTTP/511.php
Normal file
29
application/libraries/Requests/Exception/HTTP/511.php
Normal 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';
|
||||
}
|
||||
44
application/libraries/Requests/Exception/HTTP/Unknown.php
Normal file
44
application/libraries/Requests/Exception/HTTP/Unknown.php
Normal 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);
|
||||
}
|
||||
}
|
||||
33
application/libraries/Requests/Hooker.php
Normal file
33
application/libraries/Requests/Hooker.php
Normal 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());
|
||||
}
|
||||
61
application/libraries/Requests/Hooks.php
Normal file
61
application/libraries/Requests/Hooks.php
Normal 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;
|
||||
}
|
||||
}
|
||||
390
application/libraries/Requests/IDNAEncoder.php
Normal file
390
application/libraries/Requests/IDNAEncoder.php
Normal 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));
|
||||
}
|
||||
}
|
||||
221
application/libraries/Requests/IPv6.php
Normal file
221
application/libraries/Requests/IPv6.php
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
1220
application/libraries/Requests/IRI.php
Normal file
1220
application/libraries/Requests/IRI.php
Normal file
File diff suppressed because it is too large
Load Diff
49
application/libraries/Requests/LICENSE
Normal file
49
application/libraries/Requests/LICENSE
Normal 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.
|
||||
35
application/libraries/Requests/Proxy.php
Normal file
35
application/libraries/Requests/Proxy.php
Normal 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);
|
||||
}
|
||||
150
application/libraries/Requests/Proxy/HTTP.php
Normal file
150
application/libraries/Requests/Proxy/HTTP.php
Normal 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;
|
||||
}
|
||||
}
|
||||
95
application/libraries/Requests/Response.php
Normal file
95
application/libraries/Requests/Response.php
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
95
application/libraries/Requests/Response/Headers.php
Normal file
95
application/libraries/Requests/Response/Headers.php
Normal 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'));
|
||||
}
|
||||
}
|
||||
151
application/libraries/Requests/SSL.php
Normal file
151
application/libraries/Requests/SSL.php
Normal 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;
|
||||
}
|
||||
}
|
||||
253
application/libraries/Requests/Session.php
Normal file
253
application/libraries/Requests/Session.php
Normal 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;
|
||||
}
|
||||
}
|
||||
41
application/libraries/Requests/Transport.php
Normal file
41
application/libraries/Requests/Transport.php
Normal 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();
|
||||
}
|
||||
349
application/libraries/Requests/Transport/cURL.php
Normal file
349
application/libraries/Requests/Transport/cURL.php
Normal 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'));
|
||||
}
|
||||
}
|
||||
3554
application/libraries/Requests/Transport/cacert.pem
Normal file
3554
application/libraries/Requests/Transport/cacert.pem
Normal file
File diff suppressed because it is too large
Load Diff
381
application/libraries/Requests/Transport/fsockopen.php
Normal file
381
application/libraries/Requests/Transport/fsockopen.php
Normal 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');
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
38
application/libraries/Requests/Utility/FilteredIterator.php
Normal file
38
application/libraries/Requests/Utility/FilteredIterator.php
Normal 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;
|
||||
}
|
||||
}
|
||||
29
application/libraries/Scheduler/Sample_scheduler.php
Normal file
29
application/libraries/Scheduler/Sample_scheduler.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* Sample_scheduler class
|
||||
*
|
||||
* Copyright (c) CIBoard <www.ciboard.co.kr>
|
||||
*
|
||||
* @author CIBoard (develop@ciboard.co.kr)
|
||||
*/
|
||||
|
||||
/**
|
||||
* 스케쥴러를 통해 실행되는 샘플 class 입니다.
|
||||
*/
|
||||
class Sample_scheduler extends CI_Controller
|
||||
{
|
||||
private $CI;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
$this->CI = & get_instance();
|
||||
}
|
||||
|
||||
public function scheduler()
|
||||
{
|
||||
$ip = $this->CI->input->ip_address();
|
||||
log_message('debug', $ip . '에서 Sample_scheduler 가 실행되었습니다.');
|
||||
}
|
||||
}
|
||||
805
application/libraries/Services_json.php
Normal file
805
application/libraries/Services_json.php
Normal 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)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
250
application/libraries/Simplexml.php
Normal file
250
application/libraries/Simplexml.php
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
446
application/libraries/Videoplayer.php
Normal file
446
application/libraries/Videoplayer.php
Normal file
@@ -0,0 +1,446 @@
|
||||
<?php
|
||||
defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* Videoplayer class
|
||||
*
|
||||
* Copyright (c) CIBoard <www.ciboard.co.kr>
|
||||
*
|
||||
* @author CIBoard (develop@ciboard.co.kr)
|
||||
*/
|
||||
|
||||
/**
|
||||
* 비디오 플레이어 관련 함수 모음입니다.
|
||||
* 그누보드 기반의 아미나보드 참조
|
||||
* http://www.amina.co.kr
|
||||
*/
|
||||
class Videoplayer extends CI_Controller
|
||||
{
|
||||
|
||||
private $CI;
|
||||
private $today_popup_data;
|
||||
|
||||
|
||||
function __construct()
|
||||
{
|
||||
$this->CI = & get_instance();
|
||||
$this->CI->load->helper('string');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* JWPlayer 를 실행합니다
|
||||
*/
|
||||
function get_jwplayer($file = '', $max_width = '')
|
||||
{
|
||||
if (empty($file)) {
|
||||
return;
|
||||
}
|
||||
$ext = get_extension($file);
|
||||
if (empty($ext)) {
|
||||
return;
|
||||
}
|
||||
if (empty($max_width)) {
|
||||
$max_width = 600;
|
||||
}
|
||||
|
||||
$video = array('mp4', 'm4v', 'f4v', 'mov', 'flv', 'webm');
|
||||
$audio = array('acc', 'm4a', 'f4a', 'mp3', 'ogg', 'oga');
|
||||
|
||||
if ($ext === 'rss') {
|
||||
$is_type = 'plist';
|
||||
$cnt = $this->get_jwplayer_list($file);
|
||||
if ($cnt > 0) {
|
||||
;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} elseif (in_array($ext, $audio)) {
|
||||
$is_type = 'audio';
|
||||
} elseif (in_array($ext, $video)) {
|
||||
$is_type = 'video';
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
$jwplayer = '';
|
||||
if ( ! defined('JS_JWPLAYER6')) {
|
||||
define('JS_JWPLAYER6', true);
|
||||
$jwplayer .= '<script type="text/javascript" src="' . base_url('plugin/jwplayer/jwplayer.js') . '"></script>' . PHP_EOL;
|
||||
$jwplayer .= '<script type="text/javascript">jwplayer.key="' . $this->CI->cbconfig->item('jwplayer6_key') . '";</script>' . PHP_EOL;
|
||||
}
|
||||
|
||||
$jw_id = random_string('alnum');
|
||||
$jwplayer .= '<div id="' . $jw_id . '">Loading the player...</div>' . PHP_EOL;
|
||||
if ($is_type === 'audio') {
|
||||
$jwplayer .= '<script type="text/javascript">
|
||||
jwplayer("' . $jw_id . '").setup({
|
||||
file: "' . $file . '",
|
||||
width: "100%",
|
||||
height: "40",
|
||||
repeat: "file"
|
||||
});
|
||||
</script>' . PHP_EOL;
|
||||
$jwplayer = '<div style="margin-bottom:15px;">' . $jwplayer . '</div>' . PHP_EOL;
|
||||
} elseif ($is_type === 'plist') {
|
||||
$plist_set = 'aspectratio: "16:9"';
|
||||
$padding = '56.25';
|
||||
if ($cnt > 1) {
|
||||
$plist_set = $this->CI->cbconfig->get_device_view_type() === 'mobile' ? 'aspectratio: "16:9", listbar: { position: "right", size:150 }' : 'aspectratio: "16:9", listbar: { position: "right", size:200 }';
|
||||
$padding = '37.5';
|
||||
}
|
||||
$jwplayer .= '<script type="text/javascript">
|
||||
jwplayer("' . $jw_id . '").setup({
|
||||
playlist: "' . $file . '",
|
||||
width: "100%",
|
||||
' . $plist_set . '
|
||||
});
|
||||
</script>' . PHP_EOL;
|
||||
$jwplayer = '<div class="autowrap" style="max-width:' . $max_width . 'px;"><div class="autosize" style="padding-bottom: ' . $padding . '%;">' . $jwplayer . '</div></div>' . PHP_EOL;
|
||||
} else {
|
||||
$jwplayer .= '<script type="text/javascript">
|
||||
jwplayer("' . $jw_id . '").setup({
|
||||
file: "' . $file . '",
|
||||
aspectratio: "4:3",
|
||||
width: "100%"
|
||||
});
|
||||
</script>' . PHP_EOL;
|
||||
$jwplayer = '<div class="autowrap" style="max-width:' . $max_width . 'px;"><div class="autosize" style="padding-bottom: 75%;">' . $jwplayer . '</div></div>' . PHP_EOL;
|
||||
}
|
||||
|
||||
return $jwplayer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* JWPlayer LIST 를 얻습니다
|
||||
*/
|
||||
function get_jwplayer_list($url)
|
||||
{
|
||||
if (empty($url)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
@curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_setopt($ch, CURLOPT_HEADER, 0);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
||||
$xml = trim(curl_exec($ch));
|
||||
curl_close($ch);
|
||||
|
||||
if (empty($xml)) {
|
||||
return;
|
||||
}
|
||||
|
||||
preg_match_all("/<item>(.*)<\/item>/iUs", $xml, $matchs);
|
||||
|
||||
return count($matchs[1]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Video Player 를 보여줍니다
|
||||
*/
|
||||
function get_video($vid = '')
|
||||
{
|
||||
if (empty($vid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$video = array();
|
||||
$vid = str_replace(" ", " ", $vid);
|
||||
$video = $this->get_video_info($vid);
|
||||
|
||||
switch (element('type', $video)) {
|
||||
case 'vimeo':
|
||||
$video['width'] = 717;
|
||||
$video['height'] = 403;
|
||||
break;
|
||||
case 'nate':
|
||||
$video['width'] = 640;
|
||||
$video['height'] = 384;
|
||||
break;
|
||||
case 'tagstory':
|
||||
$video['width'] = 720;
|
||||
$video['height'] = 480;
|
||||
break;
|
||||
case 'tvcast':
|
||||
$video['width'] = 720;
|
||||
$video['height'] = 410;
|
||||
break;
|
||||
case 'naver':
|
||||
$video['width'] = 720;
|
||||
$video['height'] = 438;
|
||||
break;
|
||||
case 'slidershare':
|
||||
$video['width'] = 425;
|
||||
$video['height'] = 355;
|
||||
break;
|
||||
default:
|
||||
$video['width'] = 640;
|
||||
$video['height'] = 360;
|
||||
break;
|
||||
}
|
||||
|
||||
$ratio = round((element('height', $video) / element('width', $video)), 4) * 100;
|
||||
|
||||
$video_show = '';
|
||||
|
||||
if (element('type', $video) === 'file') { //JWPLAYER
|
||||
$show = $this->get_jwplayer(element('video', $video));
|
||||
|
||||
if ($show) {
|
||||
return $show;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
$show = '';
|
||||
|
||||
if (element('type', $video) === 'youtube') { //유튜브
|
||||
$vlist = element('vlist', $video) ? '&list=' . element('vlist', $video) : '';
|
||||
$autoplay = (element('auto', $video)) ? '&autoplay=1' : '';
|
||||
$show = '<iframe width="' . element('width', $video) . '" height="' . element('height', $video) . '" src="//www.youtube.com/embed/' . element('vid', $video) . '?autohide=1&vq=hd720' . $vlist . $autoplay . '" frameborder="0" allowfullscreen></iframe>';
|
||||
} elseif (element('type', $video) === 'vimeo') { //비메오
|
||||
$autoplay = (element('auto', $video)) ? '&autoplay=1' : '';
|
||||
$show = '<iframe src="http://player.vimeo.com/video/' . element('vid', $video) . '?title=0&byline=0&portrait=0&color=ffffff' . $autoplay . '&wmode=opaque" width="' . element('width', $video) . '" height="' . element('height', $video) . '" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>';
|
||||
} elseif (element('type', $video) === 'ted') { //테드
|
||||
$show = '<iframe src="http://embed.ted.com' . element('rid', $video) . '?&wmode=opaque" width="' . element('width', $video) . '" height="' . element('height', $video) . '" frameborder="0" scrolling="no" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>';
|
||||
} elseif (element('type', $video) === 'daum') { //다음TV
|
||||
$autoplay = (element('auto', $video)) ? '&autoPlay=1' : '';
|
||||
$show = '<iframe width="' . element('width', $video) . '" height="' . element('height', $video) . '" src="http://videofarm.daum.net/controller/video/viewer/Video.html?vid=' . element('rid', $video) . '&play_loc=undefined' . $autoplay . '&wmode=opaque" frameborder="0" scrolling="no"></iframe>';
|
||||
} elseif (element('type', $video) === 'dailymotion') { //Dailymotion
|
||||
$show = '<iframe frameborder="0" width="' . element('width', $video) . '" height="' . element('height', $video) . '" src="http://www.dailymotion.com/embed/video/' . element('vid', $video) . '?&wmode=opaque"></iframe>';
|
||||
} elseif (element('type', $video) === 'pandora') { //판도라TV
|
||||
if (element('auto', $video)) {
|
||||
$auto = "&autoPlay=true";
|
||||
}
|
||||
$show = '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,0,0" width="' . element('width', $video) . '" height="' . element('height', $video) . '" id="movie" align="middle">';
|
||||
$show .= '<param name="quality" value="high" /><param name="movie" value="http://flvr.pandora.tv/flv2pan/flvmovie.dll/userid=' . element('ch_userid', $video) . '&prgid=' . element('prgid', $video) . '&skin=1' . $auto . '&share=on&countryChk=ko" /><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="true" /><param name="wmode" value="transparent" />';
|
||||
$show .= '<embed src="http://flvr.pandora.tv/flv2pan/flvmovie.dll/userid=' . element('ch_userid', $video) . '&prgid=' . element('prgid', $video) . '&skin=1' . $auto . '&share=on&countryChk=ko" type="application/x-shockwave-flash" wmode="transparent" allowScriptAccess="always" allowFullScreen="true" pluginspage="http://www.macromedia.com/go/getflashplayer" width="' . element('width', $video) . '" height="' . element('height', $video) . '" /></embed></object>';
|
||||
} elseif (element('type', $video) === 'nate') { //네이트TV
|
||||
$autoplay = (element('auto', $video)) ? '&autoPlay=1' : '';
|
||||
$show = '<object id="skplayer" name="skplayer" width="' . element('width', $video) . '" height="' . element('height', $video) . '" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9.0.115.00">';
|
||||
$show .= '<param name="movie" value="http://v.nate.com/v.sk/movie/' . element('vs_keys', $video) . '/' . element('mov_id', $video) . $autoplay . '" /><param name="allowFullscreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="wmode" value="transparent" />';
|
||||
$show .= '<embed src="http://v.nate.com/v.sk/movie/' . element('vs_keys', $video) . '/' . element('mov_id', $video) . '" wmode="transparent" allowScriptAccess="always" allowFullscreen="true" name="skplayer" width="' . element('width', $video) . '" height="' . element('height', $video) . '" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" /></object>';
|
||||
} elseif (element('type', $video) === 'tagstory') { //Tagstory
|
||||
$show = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,16,0" width="' . element('width', $video) . '" height="' . element('height', $video) . '" id="ScrapPlayer" >';
|
||||
$show .= '<param name="movie" value="http://www.tagstory.com/player/basic/' . element('vid', $video) . '" /><param name="wmode" value="transparent" /><param name="quality" value="high" /><param name="allowScriptAccess" value="always" /><param name="allowNetworking" value="all" /><param name="allowFullScreen" value="true" />';
|
||||
$show .= '<embed src="http://www.tagstory.com/player/basic/' . element('vid', $video) . '" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,16,0" id="ScrapPlayer" name="ScrapPlayer" width="' . element('width', $video) . '" height="' . element('height', $video) . '" wmode="transparent" quality="high" allowScriptAccess="always" allowNetworking="all" allowFullScreen="true" /></object>';
|
||||
} elseif (element('type', $video) === 'slidershare') { // SliderShare
|
||||
$show = '<iframe src="' . element('play_url', $video) . '" width="' . element('width', $video) . '" height="' . element('height', $video) . '" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" allowfullscreen></iframe>';
|
||||
} elseif (element('type', $video) === 'facebook') { // Facebook - 라니안님 코드 반영
|
||||
$show = '<iframe src="https://www.facebook.com/video/embed?video_id=' . urlencode(element('vid', $video)) . '" width="' . element('width', $video) . '" height="' . element('height', $video) . '" frameborder="0"></iframe>';
|
||||
} elseif (element('type', $video) === 'naver') { // Naver - 라니안님 코드 반영
|
||||
$autoplay = (element('auto', $video)) ? '&isp=1' : '';
|
||||
$show = '<iframe width="' . element('width', $video) . '" height="' . element('height', $video) . '" src="http://serviceapi.nmv.naver.com/flash/convertIframeTag.nhn?vid=' . element('vid', $video) . '&outKey=' . element('outKey', $video) . $autoplay . '" frameborder="no" scrolling="no"></iframe>';
|
||||
} elseif (element('type', $video) === 'tvcast') { // Naver Tvcast - 라니안님 코드 반영
|
||||
$autoplay = (element('auto', $video)) ? '&isp=1' : '';
|
||||
$show = '<iframe width="' . element('width', $video) . '" height="' . element('height', $video) . '" src="http://serviceapi.rmcnmv.naver.com/flash/outKeyPlayer.nhn?vid=' . element('vid', $video) . '&outKey=' . element('outKey', $video) . '&controlBarMovable=true&jsCallable=true&skinName=tvcast_black' . $autoplay . '" frameborder="no" scrolling="no" marginwidth="0" marginheight="0"></iframe>';
|
||||
}
|
||||
|
||||
if ($show) {
|
||||
$video_show .= '<div class="autowrap"><div class="autosize" style="padding-bottom: ' . $ratio . '%;">' . PHP_EOL;
|
||||
$video_show .= $show . PHP_EOL;
|
||||
$video_show .= '</div></div>' . PHP_EOL;
|
||||
}
|
||||
}
|
||||
return $video_show;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 동영상 종류를 파악합니다
|
||||
*/
|
||||
function get_video_info($video_url)
|
||||
{
|
||||
$video = array();
|
||||
$query = array();
|
||||
$video_url = trim(strip_tags($video_url));
|
||||
$url = trim($video_url);
|
||||
|
||||
if ($url) {
|
||||
if ( ! preg_match('/(http|https)\:\/\//i', $url)) {
|
||||
$url = 'http:' . $url;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
$video['video'] = str_replace(array(' ', ' '), array('', ''), $url);
|
||||
$video['video_url'] = str_replace(array(' ', '&', ' '), array('', '&', ''), $url);
|
||||
|
||||
$info = parse_url(element('video_url', $video));
|
||||
if (element('query', $info)) parse_str(element('query', $info), $query);
|
||||
|
||||
if (element('host', $info) === 'youtu.be') { //유튜브
|
||||
$video['type'] = 'youtube';
|
||||
$video['vid'] = trim(str_replace('/', '', element('path', $info)));
|
||||
$video['vid'] = substr(element('vid', $video), 0, 11);
|
||||
$video['vlist'] = element('list', $query);
|
||||
$video['auto'] = element('autoplay', $query);
|
||||
} elseif (element('host', $info) === 'www.youtube.com') { //유튜브
|
||||
$video['type'] = 'youtube';
|
||||
if (preg_match('/\/embed\//i', element('video_url', $video))) {
|
||||
list($youtube_url, $youtube_opt) = explode('/embed/', element('video_url', $video));
|
||||
$vids = explode('?', $youtube_opt);
|
||||
$video['vid'] = element(0, $vids);
|
||||
} else {
|
||||
$video['vid'] = element('v', $query);
|
||||
$video['vlist'] = element('list', $query);
|
||||
}
|
||||
} elseif (element('host', $info) === 'vimeo.com') { //비메오
|
||||
$video['type'] = 'vimeo';
|
||||
$vquery = explode('/', element('video_url', $video));
|
||||
$num = count($vquery) - 1;
|
||||
list($video['vid']) = explode('#', element($num, $vquery));
|
||||
} elseif (element('host', $info) === 'www.ted.com') { //테드
|
||||
$video['type'] = 'ted';
|
||||
$vquery = explode('/', element('video_url', $video));
|
||||
$num = count($vquery) - 1;
|
||||
list($video['vid']) = explode('.', element($num, $vquery));
|
||||
$video['rid'] = trim(element('path', $info));
|
||||
} elseif (element('host', $info) === 'tvpot.daum.net') { //다음tv
|
||||
$video['type'] = 'daum';
|
||||
if (element('vid', $query)) {
|
||||
$video['vid'] = element('vid', $query);
|
||||
$video['rid'] = element('list', $video);
|
||||
} else {
|
||||
if (element('clipid', $query)) {
|
||||
$video['vid'] = element('clipid', $query);
|
||||
} else {
|
||||
$video['vid'] = trim(str_replace('/v/', '', element('path', $info)));
|
||||
}
|
||||
$play = $this->get_video_id(element('video_url', $video), element('vid', $video), element('type', $video));
|
||||
$video['rid'] = $play['rid'];
|
||||
}
|
||||
} elseif (element('host', $info) === 'channel.pandora.tv') { //판도라tv
|
||||
$video['type'] = 'pandora';
|
||||
$video['ch_userid'] = element('ch_userid', $query);
|
||||
$video['prgid'] = element('prgid', $query);
|
||||
$video['vid'] = element('ch_userid', $video) . '_' . element('prgid', $video);
|
||||
} elseif (element('host', $info) === 'pann.nate.com') { //네이트tv
|
||||
$video['type'] = 'nate';
|
||||
$video['vid'] = trim(str_replace('/video/', '', element('path', $info)));
|
||||
$play = $this->get_video_id(element('video_url', $video), element('vid', $video), element('type', $video));
|
||||
$video['mov_id'] = element('mov_id', $play);
|
||||
$video['vs_keys'] = element('vs_keys', $play);
|
||||
} elseif (element('host', $info) === 'www.tagstory.com') { //Tagstory
|
||||
$video['type'] = 'tagstory';
|
||||
$vquery = explode('/', element('video_url', $video));
|
||||
$num = count($vquery) - 1;
|
||||
$video['vid'] = element($num, $vquery);
|
||||
} elseif (element('host', $info) === 'www.dailymotion.com') { //Dailymotion
|
||||
$video['type'] = 'dailymotion';
|
||||
$vquery = explode('/', element('video_url', $video));
|
||||
$num = count($vquery) - 1;
|
||||
list($video['vid']) = explode('_', element($num, $vquery));
|
||||
} elseif (element('host', $info) === 'www.facebook.com') { //Facebook
|
||||
$video['type'] = 'facebook';
|
||||
if (element('video_id', $query)) {
|
||||
$video['vid'] = element('video_id', $query);
|
||||
} else {
|
||||
$video['vid'] = element('v', $query);
|
||||
}
|
||||
if ( ! is_numeric(element('vid', $video))) {
|
||||
$video = null;
|
||||
}
|
||||
} elseif (element('host', $info) === 'serviceapi.nmv.naver.com') { // 네이버
|
||||
$video['type'] = 'naver';
|
||||
$video['vid'] = element('vid', $query);
|
||||
$video['outKey'] = element('outKey', $query);
|
||||
} elseif (element('host', $info) === 'serviceapi.rmcnmv.naver.com') { // 네이버
|
||||
$video['type'] = 'tvcast';
|
||||
$video['vid'] = element('vid', $query);
|
||||
$video['outKey'] = element('outKey', $query);
|
||||
} elseif (element('host', $info) === 'tvcast.naver.com') {
|
||||
$video['type'] = 'tvcast';
|
||||
$video['clipNo'] = trim(str_replace('/v/', '', element('path', $info)));
|
||||
$play = $this->get_video_id(element('video_url', $video), element('clipNo', $video), element('type', $video));
|
||||
$video['vid'] = element('vid', $play);
|
||||
$video['outKey'] = element('outKey', $play);
|
||||
} elseif (element('host', $info) === 'www.slideshare.net') { // slidershare
|
||||
$video['type'] = 'slidershare';
|
||||
$play = $this->get_video_id(element('video_url', $video), 1, element('type', $video));
|
||||
$video['play_url'] = element('play_url', $play);
|
||||
$video['vid'] = element('vid', $play);
|
||||
}
|
||||
|
||||
return $video;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 동영상 실제 아이디 가져오기
|
||||
*/
|
||||
function get_video_id($url, $vid, $type)
|
||||
{
|
||||
$play = array();
|
||||
$info = array();
|
||||
$query = array();
|
||||
|
||||
if (empty($url) OR empty($vid) OR empty($type) OR ($type === 'file')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
@curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_setopt($ch, CURLOPT_HEADER, 0);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
||||
$output = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($type === 'daum') {
|
||||
preg_match('/\<meta property=\"og\:video\"([^\<\>])*\>/i', $output, $video);
|
||||
if ($video) {
|
||||
$video = change_key_case(element(0, $video));
|
||||
$video['content'] = preg_replace("/&/", "&", element('content', $video));
|
||||
$info = parse_url($video['content']);
|
||||
parse_str(element('query', $info), $query);
|
||||
$play['rid'] = element('vid', $query);
|
||||
}
|
||||
} elseif ($type === 'nate') {
|
||||
preg_match('/mov_id = \"([^\"]*)\"/i', $output, $video);
|
||||
$play['mov_id'] = element(0, $video);
|
||||
|
||||
preg_match('/vs_keys = \"([^\"]*)\"/i', $output, $video);
|
||||
$play['vs_keys'] = element(0, $video);
|
||||
|
||||
if ($play) {
|
||||
$meta = "<meta {$play[mov_id]} {$play[vs_keys]} >";
|
||||
$video = change_key_case($meta);
|
||||
$play['mov_id'] = element('mov_id', $video);
|
||||
$play['vs_keys'] = element('vs_keys', $video);
|
||||
}
|
||||
} elseif ($type === 'tvcast') {
|
||||
preg_match('/nhn.rmcnmv.RMCVideoPlayer\("(?P<vid>[A-Z0-9]+)", "(?P<inKey>[a-z0-9]+)"/i', $output, $video);
|
||||
|
||||
$play['vid'] = element('vid', $video);
|
||||
$play['inkey'] = element('inKey', $video);
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, 'http://serviceapi.rmcnmv.naver.com/flash/getExternSwfUrl.nhn?vid=' . element('vid', $video) . '&inKey=' . element('inKey', $video));
|
||||
curl_setopt($ch, CURLOPT_HEADER, 0);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
||||
$output = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
preg_match('/&outKey=(?P<outKey>[a-zA-Z0-9]+)&/i', $output, $video);
|
||||
|
||||
$play['outKey'] = element('outKey', $video);
|
||||
} elseif ($type === 'slidershare') {
|
||||
preg_match('/\<meta class=\"twitter_player\"([^\<\>])*\>/i', $output, $video);
|
||||
if ($video) {
|
||||
$video = change_key_case(element(0, $video));
|
||||
$play['play_url'] = preg_replace("/&/", "&", element('value', $video));
|
||||
$info = parse_url(element('play_url', $play));
|
||||
$play['vid'] = trim(str_replace('/slideshow/embed_code/', '', element('path', $info)));
|
||||
}
|
||||
}
|
||||
return $play;
|
||||
}
|
||||
}
|
||||
10
application/libraries/index.html
Normal file
10
application/libraries/index.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>403 Forbidden</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>Directory access is forbidden.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user