Version 3.4.5
This commit is contained in:
1 parent
fb6b5baabc
commit
e4478369d8
1360 files changed
+228921
-179445
No files matched your search
@@ -1,101 +1,102 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates a host according to the IPv4, IPv6 and DNS (future) specifications.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Instance of HTMLPurifier_AttrDef_URI_IPv4 sub-validator
|
||||
*/
|
||||
protected $ipv4;
|
||||
|
||||
/**
|
||||
* Instance of HTMLPurifier_AttrDef_URI_IPv6 sub-validator
|
||||
*/
|
||||
protected $ipv6;
|
||||
|
||||
public function __construct() {
|
||||
$this->ipv4 = new HTMLPurifier_AttrDef_URI_IPv4();
|
||||
$this->ipv6 = new HTMLPurifier_AttrDef_URI_IPv6();
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
$length = strlen($string);
|
||||
// empty hostname is OK; it's usually semantically equivalent:
|
||||
// the default host as defined by a URI scheme is used:
|
||||
//
|
||||
// If the URI scheme defines a default for host, then that
|
||||
// default applies when the host subcomponent is undefined
|
||||
// or when the registered name is empty (zero length).
|
||||
if ($string === '') return '';
|
||||
if ($length > 1 && $string[0] === '[' && $string[$length-1] === ']') {
|
||||
//IPv6
|
||||
$ip = substr($string, 1, $length - 2);
|
||||
$valid = $this->ipv6->validate($ip, $config, $context);
|
||||
if ($valid === false) return false;
|
||||
return '['. $valid . ']';
|
||||
}
|
||||
|
||||
// need to do checks on unusual encodings too
|
||||
$ipv4 = $this->ipv4->validate($string, $config, $context);
|
||||
if ($ipv4 !== false) return $ipv4;
|
||||
|
||||
// A regular domain name.
|
||||
|
||||
// This doesn't match I18N domain names, but we don't have proper IRI support,
|
||||
// so force users to insert Punycode.
|
||||
|
||||
// The productions describing this are:
|
||||
$a = '[a-z]'; // alpha
|
||||
$an = '[a-z0-9]'; // alphanum
|
||||
$and = '[a-z0-9-]'; // alphanum | "-"
|
||||
// domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
|
||||
$domainlabel = "$an($and*$an)?";
|
||||
// toplabel = alpha | alpha *( alphanum | "-" ) alphanum
|
||||
$toplabel = "$a($and*$an)?";
|
||||
// hostname = *( domainlabel "." ) toplabel [ "." ]
|
||||
if (preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string)) {
|
||||
return $string;
|
||||
}
|
||||
|
||||
// If we have Net_IDNA2 support, we can support IRIs by
|
||||
// punycoding them. (This is the most portable thing to do,
|
||||
// since otherwise we have to assume browsers support
|
||||
|
||||
if ($config->get('Core.EnableIDNA')) {
|
||||
$idna = new Net_IDNA2(array('encoding' => 'utf8', 'overlong' => false, 'strict' => true));
|
||||
// we need to encode each period separately
|
||||
$parts = explode('.', $string);
|
||||
try {
|
||||
$new_parts = array();
|
||||
foreach ($parts as $part) {
|
||||
$encodable = false;
|
||||
for ($i = 0, $c = strlen($part); $i < $c; $i++) {
|
||||
if (ord($part[$i]) > 0x7a) {
|
||||
$encodable = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$encodable) {
|
||||
$new_parts[] = $part;
|
||||
} else {
|
||||
$new_parts[] = $idna->encode($part);
|
||||
}
|
||||
}
|
||||
$string = implode('.', $new_parts);
|
||||
if (preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string)) {
|
||||
return $string;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// XXX error reporting
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates a host according to the IPv4, IPv6 and DNS (future) specifications.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Instance of HTMLPurifier_AttrDef_URI_IPv4 sub-validator
|
||||
*/
|
||||
protected $ipv4;
|
||||
|
||||
/**
|
||||
* Instance of HTMLPurifier_AttrDef_URI_IPv6 sub-validator
|
||||
*/
|
||||
protected $ipv6;
|
||||
|
||||
public function __construct() {
|
||||
$this->ipv4 = new HTMLPurifier_AttrDef_URI_IPv4();
|
||||
$this->ipv6 = new HTMLPurifier_AttrDef_URI_IPv6();
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
$length = strlen($string);
|
||||
// empty hostname is OK; it's usually semantically equivalent:
|
||||
// the default host as defined by a URI scheme is used:
|
||||
//
|
||||
// If the URI scheme defines a default for host, then that
|
||||
// default applies when the host subcomponent is undefined
|
||||
// or when the registered name is empty (zero length).
|
||||
if ($string === '') return '';
|
||||
if ($length > 1 && $string[0] === '[' && $string[$length-1] === ']') {
|
||||
//IPv6
|
||||
$ip = substr($string, 1, $length - 2);
|
||||
$valid = $this->ipv6->validate($ip, $config, $context);
|
||||
if ($valid === false) return false;
|
||||
return '['. $valid . ']';
|
||||
}
|
||||
|
||||
// need to do checks on unusual encodings too
|
||||
$ipv4 = $this->ipv4->validate($string, $config, $context);
|
||||
if ($ipv4 !== false) return $ipv4;
|
||||
|
||||
// A regular domain name.
|
||||
|
||||
// This doesn't match I18N domain names, but we don't have proper IRI support,
|
||||
// so force users to insert Punycode.
|
||||
|
||||
// The productions describing this are:
|
||||
$a = '[a-z]'; // alpha
|
||||
$an = '[a-z0-9]'; // alphanum
|
||||
$and = '[a-z0-9-]'; // alphanum | "-"
|
||||
// domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
|
||||
$domainlabel = "$an($and*$an)?";
|
||||
// toplabel = alpha | alpha *( alphanum | "-" ) alphanum
|
||||
$toplabel = "$a($and*$an)?";
|
||||
// hostname = *( domainlabel "." ) toplabel [ "." ]
|
||||
$uni=(IPS_DOC_CHAR_SET=="UTF-8")?"u":"";
|
||||
if (preg_match("/^($domainlabel\.)*$toplabel\.?$/i".$uni, $string)) {
|
||||
return $string;
|
||||
}
|
||||
|
||||
// If we have Net_IDNA2 support, we can support IRIs by
|
||||
// punycoding them. (This is the most portable thing to do,
|
||||
// since otherwise we have to assume browsers support
|
||||
|
||||
if ($config->get('Core.EnableIDNA')) {
|
||||
$idna = new Net_IDNA2(array('encoding' => 'utf8', 'overlong' => false, 'strict' => true));
|
||||
// we need to encode each period separately
|
||||
$parts = explode('.', $string);
|
||||
try {
|
||||
$new_parts = array();
|
||||
foreach ($parts as $part) {
|
||||
$encodable = false;
|
||||
for ($i = 0, $c = strlen($part); $i < $c; $i++) {
|
||||
if (ord($part[$i]) > 0x7a) {
|
||||
$encodable = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$encodable) {
|
||||
$new_parts[] = $part;
|
||||
} else {
|
||||
$new_parts[] = $idna->encode($part);
|
||||
}
|
||||
}
|
||||
$string = implode('.', $new_parts);
|
||||
if (preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string)) {
|
||||
return $string;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// XXX error reporting
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
@@ -26,7 +26,7 @@ class HTMLPurifier_AttrTransform_TargetBlank extends HTMLPurifier_AttrTransform
|
||||
$scheme = $url->getSchemeObj($config, $context);
|
||||
|
||||
if ($scheme->browsable && !$url->isBenign($config, $context)) {
|
||||
$attr['target'] = 'blank';
|
||||
$attr['target'] = '_blank';
|
||||
}
|
||||
|
||||
return $attr;
|
||||
|
||||
@@ -1,46 +1,99 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Injector that converts http, https and ftp text URLs to actual links.
|
||||
*/
|
||||
class HTMLPurifier_Injector_Linkify extends HTMLPurifier_Injector
|
||||
{
|
||||
|
||||
public $name = 'Linkify';
|
||||
public $needed = array('a' => array('href'));
|
||||
|
||||
public function handleText(&$token) {
|
||||
if (!$this->allowsElement('a')) return;
|
||||
|
||||
if (strpos($token->data, '://') === false) {
|
||||
// our really quick heuristic failed, abort
|
||||
// this may not work so well if we want to match things like
|
||||
// "google.com", but then again, most people don't
|
||||
return;
|
||||
}
|
||||
|
||||
// there is/are URL(s). Let's split the string:
|
||||
// Note: this regex is extremely permissive
|
||||
$bits = preg_split('#((?:https?|ftp)://[^\s\'"<>()]+)#S', $token->data, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
|
||||
$token = array();
|
||||
|
||||
// $i = index
|
||||
// $c = count
|
||||
// $l = is link
|
||||
for ($i = 0, $c = count($bits), $l = false; $i < $c; $i++, $l = !$l) {
|
||||
if (!$l) {
|
||||
if ($bits[$i] === '') continue;
|
||||
$token[] = new HTMLPurifier_Token_Text($bits[$i]);
|
||||
} else {
|
||||
$token[] = new HTMLPurifier_Token_Start('a', array('href' => $bits[$i]));
|
||||
$token[] = new HTMLPurifier_Token_Text($bits[$i]);
|
||||
$token[] = new HTMLPurifier_Token_End('a');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Injector that converts http, https and ftp text URLs to actual links.
|
||||
*/
|
||||
class HTMLPurifier_Injector_Linkify extends HTMLPurifier_Injector
|
||||
{
|
||||
|
||||
public $name = 'Linkify';
|
||||
public $needed = array('a' => array('href'));
|
||||
|
||||
public function handleText(&$token) {
|
||||
if (!$this->allowsElement('a')) return;
|
||||
|
||||
if (strpos($token->data, '://') === false) {
|
||||
// our really quick heuristic failed, abort
|
||||
// this may not work so well if we want to match things like
|
||||
// "google.com", but then again, most people don't
|
||||
return;
|
||||
}
|
||||
//print $token->data;
|
||||
// there is/are URL(s). Let's split the string:
|
||||
// Note: this regex is extremely permissive
|
||||
//$bits = preg_split('#((?:https?|ftp)://[^\s\'"<>()]+)#S', $token->data, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
/* MODIFIED April 26, 2013
|
||||
@link http://community.invisionpower.com/resources/bugs.html/_/ip-board/links-being-corrupted-or-malformed-in-board-and-nexus-r41993
|
||||
Test case:
|
||||
http://invisionpower.com,
|
||||
http://invisionpower.com.
|
||||
http://invisionpower.com
|
||||
https://invisionpower.com
|
||||
https://blah.gov/blah-blah.as
|
||||
http://en.wikipedia.org/wiki/Chi_(mythology)
|
||||
(http://google.com)
|
||||
*/
|
||||
$uni=(IPS_DOC_CHAR_SET=="UTF-8")?"u":"";
|
||||
preg_match_all( "#(.*?)(\()?((?:http|ftp|https):\/\/[\p{L}\-_]+(?:\.[\p{L}\-_]+)?(?:[\p{L}\-\.,\(\)@?^=%&:\/~\+\#]*[\p{L}\-\@?^=%&\/~\+\#]))(.*?)$#ims" . $uni, $token->data, $matches );
|
||||
//print_r($matches);exit;
|
||||
|
||||
//$token = array();
|
||||
|
||||
// $i = index
|
||||
// $c = count
|
||||
// $l = is link
|
||||
/*for ($i = 0, $c = count($bits), $l = false; $i < $c; $i++, $l = !$l) {
|
||||
if (!$l) {
|
||||
if ($bits[$i] === '') continue;
|
||||
$token[] = new HTMLPurifier_Token_Text($bits[$i]);
|
||||
} else {
|
||||
$token[] = new HTMLPurifier_Token_Start('a', array('href' => $bits[$i]));
|
||||
$token[] = new HTMLPurifier_Token_Text($bits[$i]);
|
||||
$token[] = new HTMLPurifier_Token_End('a');
|
||||
}
|
||||
}*/
|
||||
|
||||
if( is_array($matches) AND count($matches) )
|
||||
{
|
||||
$token = array();//by denchu 06062013
|
||||
foreach( $matches[0] as $k => $match )
|
||||
{
|
||||
if( !$matches[3][$k] )
|
||||
{
|
||||
$token[] = new HTMLPurifier_Token_Text($token->data);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( $matches[1][$k] )
|
||||
{
|
||||
$token[] = new HTMLPurifier_Token_Text($matches[1][$k]);
|
||||
}
|
||||
|
||||
if( $matches[2][$k] )
|
||||
{
|
||||
$token[] = new HTMLPurifier_Token_Text($matches[2][$k]);
|
||||
}
|
||||
|
||||
if( !$matches[2][$k] AND $matches[4][$k] == ')' )
|
||||
{
|
||||
$matches[3][$k] .= ')';
|
||||
unset($matches[4][$k]);
|
||||
}
|
||||
|
||||
$token[] = new HTMLPurifier_Token_Start('a', array('href' => $matches[3][$k]));
|
||||
$token[] = new HTMLPurifier_Token_Text($matches[3][$k]);
|
||||
$token[] = new HTMLPurifier_Token_End('a');
|
||||
|
||||
if( $matches[4][$k] )
|
||||
{
|
||||
$token[] = new HTMLPurifier_Token_Text($matches[4][$k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//print_r($token);exit;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
@@ -3901,4 +3901,3 @@ class HTML5TreeConstructer {
|
||||
return $this->dom;
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -48,7 +48,7 @@
|
||||
* @author Aleksander Machniak <alec@php.net>
|
||||
* @copyright 2003-2006 PEAR <pear-group@php.net>
|
||||
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
|
||||
* @version CVS: $Id: mime.php 8229 2011-03-31 10:17:44Z ips_terabyte $
|
||||
* @version CVS: $Id: mime.php 11977 2013-02-12 11:06:34Z mark $
|
||||
* @link http://pear.php.net/package/Mail_mime
|
||||
*
|
||||
* This class is based on HTML Mime Mail class from
|
||||
@@ -63,7 +63,7 @@
|
||||
*
|
||||
* This package depends on PEAR to raise errors.
|
||||
*/
|
||||
require_once 'PEAR.php';/*noLibHook*/
|
||||
require_once 'PEAR.php';
|
||||
|
||||
/**
|
||||
* require Mail_mimePart
|
||||
@@ -72,7 +72,7 @@ require_once 'PEAR.php';/*noLibHook*/
|
||||
* create all the different parts a mail can
|
||||
* consist of.
|
||||
*/
|
||||
require_once 'Mail/mimePart.php';/*noLibHook*/
|
||||
require_once 'Mail/mimePart.php';
|
||||
|
||||
|
||||
/**
|
||||
@@ -245,7 +245,7 @@ class Mail_mime
|
||||
}
|
||||
} else {
|
||||
$cont = $this->_file2str($data);
|
||||
if (PEAR::isError($cont)) {
|
||||
if ($this->_isError($cont)) {
|
||||
return $cont;
|
||||
}
|
||||
if (!$append) {
|
||||
@@ -286,7 +286,7 @@ class Mail_mime
|
||||
$this->_htmlbody = $data;
|
||||
} else {
|
||||
$cont = $this->_file2str($data);
|
||||
if (PEAR::isError($cont)) {
|
||||
if ($this->_isError($cont)) {
|
||||
return $cont;
|
||||
}
|
||||
$this->_htmlbody = $cont;
|
||||
@@ -336,7 +336,7 @@ class Mail_mime
|
||||
$filedata = null;
|
||||
$bodyfile = $file;
|
||||
} else {
|
||||
if (PEAR::isError($filedata = $this->_file2str($file))) {
|
||||
if ($this->_isError($filedata = $this->_file2str($file))) {
|
||||
return $filedata;
|
||||
}
|
||||
}
|
||||
@@ -387,6 +387,8 @@ class Mail_mime
|
||||
* @param string $description Content-Description header
|
||||
* @param string $h_charset The character set of the headers e.g. filename
|
||||
* If not specified, $charset will be used
|
||||
* @param array $add_headers Additional part headers. Array keys can be in form
|
||||
* of <header_name>:<parameter_name>
|
||||
*
|
||||
* @return mixed True on success or PEAR_Error object
|
||||
* @access public
|
||||
@@ -403,7 +405,8 @@ class Mail_mime
|
||||
$n_encoding = null,
|
||||
$f_encoding = null,
|
||||
$description = '',
|
||||
$h_charset = null
|
||||
$h_charset = null,
|
||||
$add_headers = array()
|
||||
) {
|
||||
$bodyfile = null;
|
||||
|
||||
@@ -413,12 +416,12 @@ class Mail_mime
|
||||
$filedata = null;
|
||||
$bodyfile = $file;
|
||||
} else {
|
||||
if (PEAR::isError($filedata = $this->_file2str($file))) {
|
||||
if ($this->_isError($filedata = $this->_file2str($file))) {
|
||||
return $filedata;
|
||||
}
|
||||
}
|
||||
// Force the name the user supplied, otherwise use $file
|
||||
$filename = ($name ? $name : $file);
|
||||
$filename = ($name ? $name : $this->_basename($file));
|
||||
} else {
|
||||
$filedata = $file;
|
||||
$filename = $name;
|
||||
@@ -429,7 +432,6 @@ class Mail_mime
|
||||
$err = PEAR::raiseError($msg);
|
||||
return $err;
|
||||
}
|
||||
$filename = $this->_basename($filename);
|
||||
|
||||
$this->_parts[] = array(
|
||||
'body' => $filedata,
|
||||
@@ -442,6 +444,7 @@ class Mail_mime
|
||||
'location' => $location,
|
||||
'disposition' => $disposition,
|
||||
'description' => $description,
|
||||
'add_headers' => $add_headers,
|
||||
'name_encoding' => $n_encoding,
|
||||
'filename_encoding' => $f_encoding,
|
||||
'headers_charset' => $h_charset,
|
||||
@@ -458,7 +461,7 @@ class Mail_mime
|
||||
* @return string Contents of $file_name
|
||||
* @access private
|
||||
*/
|
||||
function &_file2str($file_name)
|
||||
function _file2str($file_name)
|
||||
{
|
||||
// Check state of file and raise an error properly
|
||||
if (!file_exists($file_name)) {
|
||||
@@ -497,7 +500,7 @@ class Mail_mime
|
||||
* @return object The text mimePart object
|
||||
* @access private
|
||||
*/
|
||||
function &_addTextPart(&$obj, $text)
|
||||
function _addTextPart(&$obj, $text)
|
||||
{
|
||||
$params['content_type'] = 'text/plain';
|
||||
$params['encoding'] = $this->_build_params['text_encoding'];
|
||||
@@ -523,7 +526,7 @@ class Mail_mime
|
||||
* @return object The html mimePart object
|
||||
* @access private
|
||||
*/
|
||||
function &_addHtmlPart(&$obj)
|
||||
function _addHtmlPart(&$obj)
|
||||
{
|
||||
$params['content_type'] = 'text/html';
|
||||
$params['encoding'] = $this->_build_params['html_encoding'];
|
||||
@@ -547,7 +550,7 @@ class Mail_mime
|
||||
* @return object The multipart/mixed mimePart object
|
||||
* @access private
|
||||
*/
|
||||
function &_addMixedPart()
|
||||
function _addMixedPart()
|
||||
{
|
||||
$params = array();
|
||||
$params['content_type'] = 'multipart/mixed';
|
||||
@@ -569,7 +572,7 @@ class Mail_mime
|
||||
* @return object The multipart/mixed mimePart object
|
||||
* @access private
|
||||
*/
|
||||
function &_addAlternativePart(&$obj)
|
||||
function _addAlternativePart(&$obj)
|
||||
{
|
||||
$params['content_type'] = 'multipart/alternative';
|
||||
$params['eol'] = $this->_build_params['eol'];
|
||||
@@ -593,7 +596,7 @@ class Mail_mime
|
||||
* @return object The multipart/mixed mimePart object
|
||||
* @access private
|
||||
*/
|
||||
function &_addRelatedPart(&$obj)
|
||||
function _addRelatedPart(&$obj)
|
||||
{
|
||||
$params['content_type'] = 'multipart/related';
|
||||
$params['eol'] = $this->_build_params['eol'];
|
||||
@@ -616,7 +619,7 @@ class Mail_mime
|
||||
* @return object The image mimePart object
|
||||
* @access private
|
||||
*/
|
||||
function &_addHtmlImagePart(&$obj, $value)
|
||||
function _addHtmlImagePart(&$obj, $value)
|
||||
{
|
||||
$params['content_type'] = $value['c_type'];
|
||||
$params['encoding'] = 'base64';
|
||||
@@ -647,7 +650,7 @@ class Mail_mime
|
||||
* @return object The image mimePart object
|
||||
* @access private
|
||||
*/
|
||||
function &_addAttachmentPart(&$obj, $value)
|
||||
function _addAttachmentPart(&$obj, $value)
|
||||
{
|
||||
$params['eol'] = $this->_build_params['eol'];
|
||||
$params['filename'] = $value['name'];
|
||||
@@ -680,6 +683,9 @@ class Mail_mime
|
||||
if (!empty($value['description'])) {
|
||||
$params['description'] = $value['description'];
|
||||
}
|
||||
if (is_array($value['add_headers'])) {
|
||||
$params['headers'] = $value['add_headers'];
|
||||
}
|
||||
|
||||
$ret = $obj->addSubpart($value['body'], $params);
|
||||
return $ret;
|
||||
@@ -712,7 +718,7 @@ class Mail_mime
|
||||
|
||||
$body = $this->get($params);
|
||||
|
||||
if (PEAR::isError($body)) {
|
||||
if ($this->_isError($body)) {
|
||||
return $body;
|
||||
}
|
||||
|
||||
@@ -1013,7 +1019,7 @@ class Mail_mime
|
||||
if ($filename) {
|
||||
// Append mimePart message headers and body into file
|
||||
$headers = $message->encodeToFile($filename, $boundary, $skip_head);
|
||||
if (PEAR::isError($headers)) {
|
||||
if ($this->_isError($headers)) {
|
||||
return $headers;
|
||||
}
|
||||
$this->_headers = array_merge($this->_headers, $headers);
|
||||
@@ -1021,7 +1027,7 @@ class Mail_mime
|
||||
return $ret;
|
||||
} else {
|
||||
$output = $message->encode($boundary, $skip_head);
|
||||
if (PEAR::isError($output)) {
|
||||
if ($this->_isError($output)) {
|
||||
return $output;
|
||||
}
|
||||
$this->_headers = array_merge($this->_headers, $output['headers']);
|
||||
@@ -1142,8 +1148,8 @@ class Mail_mime
|
||||
? $this->_build_params['eol'] : "\r\n";
|
||||
|
||||
// add parameters
|
||||
$token_regexp = '#([^\x21,\x23-\x27,\x2A,\x2B,\x2D'
|
||||
. ',\x2E,\x30-\x39,\x41-\x5A,\x5E-\x7E])#';
|
||||
$token_regexp = '#([^\x21\x23-\x27\x2A\x2B\x2D'
|
||||
. '\x2E\x30-\x39\x41-\x5A\x5E-\x7E])#';
|
||||
if (is_array($params)) {
|
||||
foreach ($params as $name => $value) {
|
||||
if ($name == 'boundary') {
|
||||
@@ -1319,7 +1325,8 @@ class Mail_mime
|
||||
*/
|
||||
function encodeHeader($name, $value, $charset, $encoding)
|
||||
{
|
||||
return Mail_mimePart::encodeHeader(
|
||||
$mime_part = new Mail_mimePart;
|
||||
return $mime_part->encodeHeader(
|
||||
$name, $value, $charset, $encoding, $this->_build_params['eol']
|
||||
);
|
||||
}
|
||||
@@ -1465,4 +1472,22 @@ class Mail_mime
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PEAR::isError wrapper
|
||||
*
|
||||
* @param mixed $data Object
|
||||
*
|
||||
* @return bool True if object is an instance of PEAR_Error
|
||||
* @access private
|
||||
*/
|
||||
function _isError($data)
|
||||
{
|
||||
// PEAR::isError() is not PHP 5.4 compatible (see Bug #19473)
|
||||
if (is_object($data) && is_a($data, 'PEAR_Error')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of class
|
||||
@@ -52,7 +52,7 @@
|
||||
* @author Sean Coates <sean@php.net>
|
||||
* @copyright 2003-2006 PEAR <pear-group@php.net>
|
||||
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
|
||||
* @version CVS: $Id: mimeDecode.php 10914 2012-06-12 14:14:49Z bfarber $
|
||||
* @version CVS: $Id: mimeDecode.php 10705 2012-05-08 15:35:49Z mark $
|
||||
* @link http://pear.php.net/package/Mail_mime
|
||||
*/
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
* @author Aleksander Machniak <alec@php.net>
|
||||
* @copyright 2003-2006 PEAR <pear-group@php.net>
|
||||
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
|
||||
* @version CVS: $Id: mimePart.php 8229 2011-03-31 10:17:44Z ips_terabyte $
|
||||
* @version CVS: $Id: mimePart.php 11977 2013-02-12 11:06:34Z mark $
|
||||
* @link http://pear.php.net/package/Mail_mime
|
||||
*/
|
||||
|
||||
@@ -131,6 +131,7 @@ class Mail_mimePart
|
||||
*/
|
||||
var $_eol = "\r\n";
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@@ -144,7 +145,7 @@ class Mail_mimePart
|
||||
* charset - Content character set
|
||||
* cid - Content ID to apply
|
||||
* disposition - Content disposition, inline or attachment
|
||||
* dfilename - Filename parameter for content disposition
|
||||
* filename - Filename parameter for content disposition
|
||||
* description - Content description
|
||||
* name_encoding - Encoding of the attachment name (Content-Type)
|
||||
* By default filenames are encoded using RFC2231
|
||||
@@ -155,6 +156,8 @@ class Mail_mimePart
|
||||
* headers_charset - Charset of the headers e.g. filename, description.
|
||||
* If not set, 'charset' will be used
|
||||
* eol - End of line sequence. Default: "\r\n"
|
||||
* headers - Hash array with additional part headers. Array keys can be
|
||||
* in form of <header_name>:<parameter_name>
|
||||
* body_file - Location of file with part's body (instead of $body)
|
||||
*
|
||||
* @access public
|
||||
@@ -167,6 +170,11 @@ class Mail_mimePart
|
||||
$this->_eol = MAIL_MIMEPART_CRLF;
|
||||
}
|
||||
|
||||
// Additional part headers
|
||||
if (!empty($params['headers']) && is_array($params['headers'])) {
|
||||
$headers = $params['headers'];
|
||||
}
|
||||
|
||||
foreach ($params as $key => $value) {
|
||||
switch ($key) {
|
||||
case 'encoding':
|
||||
@@ -185,6 +193,11 @@ class Mail_mimePart
|
||||
case 'body_file':
|
||||
$this->_body_file = $value;
|
||||
break;
|
||||
|
||||
// for backward compatibility
|
||||
case 'dfilename':
|
||||
$params['filename'] = $value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,13 +223,17 @@ class Mail_mimePart
|
||||
$params['headers_charset'] = $params['charset'];
|
||||
}
|
||||
}
|
||||
|
||||
// header values encoding parameters
|
||||
$h_charset = !empty($params['headers_charset']) ? $params['headers_charset'] : 'US-ASCII';
|
||||
$h_language = !empty($params['language']) ? $params['language'] : null;
|
||||
$h_encoding = !empty($params['name_encoding']) ? $params['name_encoding'] : null;
|
||||
|
||||
|
||||
if (!empty($params['filename'])) {
|
||||
$headers['Content-Type'] .= ';' . $this->_eol;
|
||||
$headers['Content-Type'] .= $this->_buildHeaderParam(
|
||||
'name', $params['filename'],
|
||||
!empty($params['headers_charset']) ? $params['headers_charset'] : 'US-ASCII',
|
||||
!empty($params['language']) ? $params['language'] : null,
|
||||
!empty($params['name_encoding']) ? $params['name_encoding'] : null
|
||||
'name', $params['filename'], $h_charset, $h_language, $h_encoding
|
||||
);
|
||||
}
|
||||
|
||||
@@ -226,23 +243,41 @@ class Mail_mimePart
|
||||
if (!empty($params['filename'])) {
|
||||
$headers['Content-Disposition'] .= ';' . $this->_eol;
|
||||
$headers['Content-Disposition'] .= $this->_buildHeaderParam(
|
||||
'filename', $params['filename'],
|
||||
!empty($params['headers_charset']) ? $params['headers_charset'] : 'US-ASCII',
|
||||
!empty($params['language']) ? $params['language'] : null,
|
||||
'filename', $params['filename'], $h_charset, $h_language,
|
||||
!empty($params['filename_encoding']) ? $params['filename_encoding'] : null
|
||||
);
|
||||
}
|
||||
|
||||
// add attachment size
|
||||
$size = $this->_body_file ? filesize($this->_body_file) : strlen($body);
|
||||
if ($size) {
|
||||
$headers['Content-Disposition'] .= ';' . $this->_eol . ' size=' . $size;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($params['description'])) {
|
||||
$headers['Content-Description'] = $this->encodeHeader(
|
||||
'Content-Description', $params['description'],
|
||||
!empty($params['headers_charset']) ? $params['headers_charset'] : 'US-ASCII',
|
||||
!empty($params['name_encoding']) ? $params['name_encoding'] : 'quoted-printable',
|
||||
'Content-Description', $params['description'], $h_charset, $h_encoding,
|
||||
$this->_eol
|
||||
);
|
||||
}
|
||||
|
||||
// Search and add existing headers' parameters
|
||||
foreach ($headers as $key => $value) {
|
||||
$items = explode(':', $key);
|
||||
if (count($items) == 2) {
|
||||
$header = $items[0];
|
||||
$param = $items[1];
|
||||
if (isset($headers[$header])) {
|
||||
$headers[$header] .= ';' . $this->_eol;
|
||||
}
|
||||
$headers[$header] .= $this->_buildHeaderParam(
|
||||
$param, $value, $h_charset, $h_language, $h_encoding
|
||||
);
|
||||
unset($headers[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
// Default encoding
|
||||
if (!isset($this->_encoding)) {
|
||||
$this->_encoding = '7bit';
|
||||
@@ -280,7 +315,7 @@ class Mail_mimePart
|
||||
for ($i = 0; $i < count($this->_subparts); $i++) {
|
||||
$encoded['body'] .= '--' . $boundary . $eol;
|
||||
$tmp = $this->_subparts[$i]->encode();
|
||||
if (PEAR::isError($tmp)) {
|
||||
if ($this->_isError($tmp)) {
|
||||
return $tmp;
|
||||
}
|
||||
foreach ($tmp['headers'] as $key => $value) {
|
||||
@@ -303,7 +338,7 @@ class Mail_mimePart
|
||||
@ini_set('magic_quotes_runtime', $magic_quote_setting);
|
||||
}
|
||||
|
||||
if (PEAR::isError($body)) {
|
||||
if ($this->_isError($body)) {
|
||||
return $body;
|
||||
}
|
||||
$encoded['body'] = $body;
|
||||
@@ -355,7 +390,7 @@ class Mail_mimePart
|
||||
@ini_set('magic_quotes_runtime', $magic_quote_setting);
|
||||
}
|
||||
|
||||
return PEAR::isError($res) ? $res : $this->_headers;
|
||||
return $this->_isError($res) ? $res : $this->_headers;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -390,7 +425,7 @@ class Mail_mimePart
|
||||
for ($i = 0; $i < count($this->_subparts); $i++) {
|
||||
fwrite($fh, $f_eol . '--' . $boundary . $eol);
|
||||
$res = $this->_subparts[$i]->_encodePartToFile($fh);
|
||||
if (PEAR::isError($res)) {
|
||||
if ($this->_isError($res)) {
|
||||
return $res;
|
||||
}
|
||||
$f_eol = $eol;
|
||||
@@ -405,7 +440,7 @@ class Mail_mimePart
|
||||
$res = $this->_getEncodedDataFromFile(
|
||||
$this->_body_file, $this->_encoding, $fh
|
||||
);
|
||||
if (PEAR::isError($res)) {
|
||||
if ($this->_isError($res)) {
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
@@ -633,8 +668,8 @@ class Mail_mimePart
|
||||
// RFC 2045:
|
||||
// value needs encoding if contains non-ASCII chars or is longer than 78 chars
|
||||
if (!preg_match('#[^\x20-\x7E]#', $value)) {
|
||||
$token_regexp = '#([^\x21,\x23-\x27,\x2A,\x2B,\x2D'
|
||||
. ',\x2E,\x30-\x39,\x41-\x5A,\x5E-\x7E])#';
|
||||
$token_regexp = '#([^\x21\x23-\x27\x2A\x2B\x2D'
|
||||
. '\x2E\x30-\x39\x41-\x5A\x5E-\x7E])#';
|
||||
if (!preg_match($token_regexp, $value)) {
|
||||
// token
|
||||
if (strlen($name) + strlen($value) + 3 <= $maxLength) {
|
||||
@@ -656,7 +691,7 @@ class Mail_mimePart
|
||||
|
||||
// RFC2231:
|
||||
$encValue = preg_replace_callback(
|
||||
'/([^\x21,\x23,\x24,\x26,\x2B,\x2D,\x2E,\x30-\x39,\x41-\x5A,\x5E-\x7E])/',
|
||||
'/([^\x21\x23\x24\x26\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E])/',
|
||||
array($this, '_encodeReplaceCallback'), $value
|
||||
);
|
||||
$value = "$charset'$language'$encValue";
|
||||
@@ -780,6 +815,7 @@ class Mail_mimePart
|
||||
'from', 'to', 'cc', 'bcc', 'sender', 'reply-to',
|
||||
'resent-from', 'resent-to', 'resent-cc', 'resent-bcc',
|
||||
'resent-sender', 'resent-reply-to',
|
||||
'mail-reply-to', 'mail-followup-to',
|
||||
'return-receipt-to', 'disposition-notification-to',
|
||||
);
|
||||
$other_headers = array(
|
||||
@@ -800,6 +836,9 @@ class Mail_mimePart
|
||||
|
||||
// Structured header (make sure addr-spec inside is not encoded)
|
||||
if (!empty($separator)) {
|
||||
// Simple e-mail address regexp
|
||||
$email_regexp = '([^\s<]+|("[^\r\n"]+"))@\S+';
|
||||
|
||||
$parts = Mail_mimePart::_explodeQuotedString($separator, $value);
|
||||
$value = '';
|
||||
|
||||
@@ -817,12 +856,12 @@ class Mail_mimePart
|
||||
}
|
||||
|
||||
// let's find phrase (name) and/or addr-spec
|
||||
if (preg_match('/^<\S+@\S+>$/', $part)) {
|
||||
if (preg_match('/^<' . $email_regexp . '>$/', $part)) {
|
||||
$value .= $part;
|
||||
} else if (preg_match('/^\S+@\S+$/', $part)) {
|
||||
} else if (preg_match('/^' . $email_regexp . '$/', $part)) {
|
||||
// address without brackets and without name
|
||||
$value .= $part;
|
||||
} else if (preg_match('/<*\S+@\S+>*$/', $part, $matches)) {
|
||||
} else if (preg_match('/<*' . $email_regexp . '>*$/', $part, $matches)) {
|
||||
// address with name (handle name)
|
||||
$address = $matches[0];
|
||||
$word = str_replace($address, '', $part);
|
||||
@@ -1187,4 +1226,22 @@ class Mail_mimePart
|
||||
return sprintf('%%%02X', ord($matches[1]));
|
||||
}
|
||||
|
||||
/**
|
||||
* PEAR::isError wrapper
|
||||
*
|
||||
* @param mixed $data Object
|
||||
*
|
||||
* @return bool True if object is an instance of PEAR_Error
|
||||
* @access private
|
||||
*/
|
||||
function _isError($data)
|
||||
{
|
||||
// PEAR::isError() is not PHP 5.4 compatible (see Bug #19473)
|
||||
if (is_object($data) && is_a($data, 'PEAR_Error')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of class
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,4 @@
|
||||
<?php
|
||||
class Net_IDNA2_Exception extends Exception
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
require_once 'Net/IDNA2/Exception.php';
|
||||
|
||||
class Net_IDNA2_Exception_Nameprep extends Net_IDNA2_Exception
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
header( 'Content-Type: text/html; charset=UTF-8' );
|
||||
|
||||
require 'Net/IDNA.php';
|
||||
|
||||
|
||||
$idn = Net_IDNA::getInstance();
|
||||
|
||||
if (isset($_REQUEST['encode'])) {
|
||||
$decoded = isset($_REQUEST['decoded'])? $_REQUEST['decoded'] : '';
|
||||
|
||||
try {
|
||||
$encoded = $idn->encode($decoded);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
/* just swallow */
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_REQUEST['decode'])) {
|
||||
$encoded = isset($_REQUEST['encoded'])? $_REQUEST['encoded'] : '';
|
||||
|
||||
try {
|
||||
$decoded = $idn->decode($encoded);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
/* just swallow */
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($encoded)) {
|
||||
$encoded = '';
|
||||
}
|
||||
|
||||
if (!isset($decoded)) {
|
||||
$decoded = '';
|
||||
}
|
||||
|
||||
?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<title>Punycode Converter</title>
|
||||
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
body
|
||||
{
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
font-size: 10pt;
|
||||
background: rgb( 255, 255, 255 );
|
||||
}
|
||||
|
||||
#centered
|
||||
{
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#round
|
||||
{
|
||||
background-color: rgb( 240, 240, 240 );
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
#subhead
|
||||
{
|
||||
font-size: 8pt;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<table width="780" border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td id="centered">
|
||||
<div id="round">
|
||||
<strong>IDNA Converter</strong><br />
|
||||
|
||||
<span id="subhead">
|
||||
See <a href="http://faqs.org/rfcs/rfc3490.html" title="IDNA" target="_blank">RFC3490</a>,
|
||||
<a href="http://faqs.org/rfcs/rfc3491.html" title="Nameprep, a Stringprep profile" target="_blank">RFC3491</a>,
|
||||
<a href="http://faqs.org/rfcs/rfc3492.html" title="Punycode" target="_blank">RFC3492</a> and
|
||||
<a href="http://faqs.org/rfcs/rfc3454.html" title="Stringprep" target="_blank">RFC3454</a><br />
|
||||
</span>
|
||||
|
||||
<br />
|
||||
|
||||
This converter allows you to transfer domain names between the encoded (Punycode) notation and the
|
||||
decoded (UTF-8) notation.<br />
|
||||
|
||||
Just enter the domain name in the respective field and click on the button right beside it to have
|
||||
it converted. Please be aware, that you might even enter complete domain names (like jürgen-müller.de),
|
||||
but without the protocol (<strong>DO NOT</strong> enter http://müller.de) or an email address.<br />
|
||||
|
||||
Since the underlying library is still buggy, we cannot guarantee its usefulness and correctness. You should
|
||||
always doublecheck the results given here by converting them back to the original form.<br />
|
||||
|
||||
Any productive use is discouraged and prone to fail.<br />
|
||||
|
||||
<br />
|
||||
|
||||
Make sure, that your browser is capable of the <strong>UTF-8</strong> character encoding.<br />
|
||||
|
||||
<br />
|
||||
|
||||
<table border="0" cellpadding="2" cellspacing="2" align="center">
|
||||
<tr>
|
||||
<td class="thead" align="left">Original</td>
|
||||
<td class="thead" align="right">Punycode</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="GET">
|
||||
<input type="text" name="decoded" value="<?php echo $decoded; ?>" size="24" maxlength="255" />
|
||||
<input type="submit" name="encode" value="Encode >>" />
|
||||
</form>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="GET">
|
||||
<input type="submit" name="decode" value="<< Decode" />
|
||||
<input type="text" name="encoded" value="<?php echo $encoded; ?>" size="24" maxlength="255" />
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
if (!defined('PHPUnit2_MAIN_METHOD')) {
|
||||
define('PHPUnit2_MAIN_METHOD', 'Net_IDNA2_AllTests::main');
|
||||
}
|
||||
|
||||
require_once 'PHPUnit2/TextUI/TestRunner.php';
|
||||
|
||||
require_once 'Net_IDNA2Test.php';
|
||||
require_once 'draft-josefsson-idn-test-vectors.php';
|
||||
|
||||
class Net_IDNA2_AllTests
|
||||
{
|
||||
public static function main()
|
||||
{
|
||||
PHPUnit2_TextUI_TestRunner::run(self::suite());
|
||||
}
|
||||
|
||||
public static function suite()
|
||||
{
|
||||
$suite = new PHPUnit2_Framework_TestSuite('PEAR - Net_IDNA2');
|
||||
|
||||
$suite->addTestSuite('Net_IDNA2Test');
|
||||
$suite->addTestSuite('draft-josefsson-idn-test-vectors');
|
||||
|
||||
return $suite;
|
||||
}
|
||||
}
|
||||
|
||||
if (PHPUnit2_MAIN_METHOD == 'Net_IDNA2_AllTests::main') {
|
||||
Net_IDNA2_AllTests::main();
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
require_once 'Net/IDNA2.php';
|
||||
require_once 'PHPUnit2/Framework/TestCase.php';
|
||||
|
||||
class Net_IDNA2Test extends PHPUnit2_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* Initialise tests
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUp()
|
||||
{
|
||||
$this->idn = new Net_IDNA2();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a complete URL consisting also of port-number etc. will be decoded just fine, test 1
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testShouldDecodePortNumbersFragmentsAndUrisCorrectly1()
|
||||
{
|
||||
$result = $this->idn->decode('http://www.xn--ml-6kctd8d6a.org:8080/test.php?arg1=1&arg2=2#fragment');
|
||||
$this->assertSame("http://www.\xD0\xB5\xD1\x85\xD0\xB0m\xD1\x80l\xD0\xB5.org:8080/test.php?arg1=1&arg2=2#fragment", $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a complete URL consisting also of port-number etc. will be decoded just fine, test 2
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testShouldDecodePortNumbersFragmentsAndUrisCorrectly2()
|
||||
{
|
||||
$result = $this->idn->decode('http://xn--tst-qla.example.com:8080/test.php?arg1=1&arg2=2#fragment');
|
||||
$this->assertSame("http://täst.example.com:8080/test.php?arg1=1&arg2=2#fragment", $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test encoding of German letter Eszett according to the original standard (IDNA2003)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testEncodingForGermanEszettUsingIDNA2003()
|
||||
{
|
||||
// make sure to use 2003-encoding
|
||||
$this->idn->setParams('version', '2003');
|
||||
$result = $this->idn->encode('http://www.straße.example.com/');
|
||||
|
||||
$this->assertSame("http://www.strasse.example.com/", $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test encoding of German letter Eszett according to the "new" standard (IDNA2005/IDNAbis)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testEncodingForGermanEszettUsingIDNA2008()
|
||||
{
|
||||
// make sure to use 2008-encoding
|
||||
$this->idn->setParams('version', '2008');
|
||||
$result = $this->idn->encode('http://www.straße.example.com/');
|
||||
// switch back for other testcases
|
||||
$this->idn->setParams('version', '2003');
|
||||
|
||||
$this->assertSame("http://www.xn--strae-oqa.example.com/", $result);
|
||||
}
|
||||
}
|
||||
+426
-422
@@ -1,423 +1,427 @@
|
||||
<?php
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* AJAX input parsing and handling
|
||||
* Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/company/standards.php#license
|
||||
* @package IP.Board
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since Friday 19th May 2006 17:33
|
||||
* @version $Revision: 10914 $
|
||||
*/
|
||||
|
||||
|
||||
class classAjax
|
||||
{
|
||||
/**
|
||||
* XML output
|
||||
*
|
||||
* @var string Output
|
||||
*/
|
||||
public $xml_output;
|
||||
|
||||
/**
|
||||
* XML Header
|
||||
*
|
||||
* @var string XML doctype
|
||||
*/
|
||||
public $xml_header;
|
||||
|
||||
/**
|
||||
* Character sets
|
||||
*
|
||||
* @var array Charsets supported by html_entity_decode
|
||||
*/
|
||||
protected $decodeCharsets = array('iso-8859-1' => 'ISO-8859-1',
|
||||
'iso8859-1' => 'ISO-8859-1',
|
||||
'iso-8859-15' => 'ISO-8859-15',
|
||||
'iso8859-15' => 'ISO-8859-15',
|
||||
'utf-8' => 'UTF-8',
|
||||
'cp866' => 'cp866',
|
||||
'ibm866' => 'cp866',
|
||||
'cp1251' => 'windows-1251',
|
||||
'windows-1251' => 'windows-1251',
|
||||
'win-1251' => 'windows-1251',
|
||||
'cp1252' => 'windows-1252',
|
||||
'windows-1252' => 'windows-1252',
|
||||
'koi8-r' => 'KOI8-R',
|
||||
'koi8-ru' => 'KOI8-R',
|
||||
'koi8r' => 'KOI8-R',
|
||||
'big5' => 'BIG5',
|
||||
'gb2312' => 'GB2312',
|
||||
'big5-hkscs' => 'BIG5-HKSCS',
|
||||
'shift_jis' => 'Shift_JIS',
|
||||
'sjis' => 'Shift_JIS',
|
||||
'euc-jp' => 'EUC-JP',
|
||||
'eucjp' => 'EUC-JP' );
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @return @e void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ( ! defined( 'IPS_DOC_CHAR_SET' ) )
|
||||
{
|
||||
define( 'IPS_DOC_CHAR_SET', 'UTF-8' );
|
||||
}
|
||||
|
||||
$this->xml_header = "<?xml version=\"1.0\" encoding=\"" . IPS_DOC_CHAR_SET . "\"?".'>';
|
||||
|
||||
/* Convert incoming $_POST fields */
|
||||
array_walk_recursive( $_POST, array( $this, 'arrayWalkConvert' ) );
|
||||
|
||||
//-----------------------------------------
|
||||
// Using this code allows characters that ARE supported
|
||||
// within the character set to be recoded properly, instead
|
||||
// of as HTML entities when submitted via AJAX. The problem is,
|
||||
// any characters NOT supported in the charset are corrupted. :-\
|
||||
//-----------------------------------------
|
||||
//array_walk_recursive( $_POST, create_function( '&$value, $key', '$value = IPSText::convertCharsets( IPSText::convertUnicode($value, true), "utf-8", "' . IPS_DOC_CHAR_SET . '" );' ) );
|
||||
|
||||
// We use $_REQUEST in a lot of places, so we might need to do this, but based on the below comments I'll leave this
|
||||
// commented out for now...
|
||||
//array_walk_recursive( $_REQUEST, create_function( '&$value, $key', '$value = IPSText::convertUnicode($value);' ) );
|
||||
|
||||
/* Risky converting $_GET because it calls rawurldecode which could allow crafty users to hide html entities */
|
||||
//array_walk_recursive( $_GET , create_function( '&$value, $key', '$value = IPSText::convertUnicode($value);' ) );
|
||||
//array_walk_recursive( ipsRegistry::$request, create_function( '&$value, $key', '$value = IPSText::convertUnicode($value);' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to convert unicode and charset for AJAX requests
|
||||
*
|
||||
* @param mixed Value
|
||||
* @param string Key
|
||||
* @return @e void
|
||||
*/
|
||||
public function arrayWalkConvert( &$value, $key )
|
||||
{
|
||||
if( is_string( $value ) )
|
||||
{
|
||||
$value = IPSText::convertCharsets( IPSText::convertUnicode( $value ), "utf-8", IPS_DOC_CHAR_SET );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize the character set of incoming AJAX data and optionally parse the value through the parseCleanValue routine
|
||||
*
|
||||
* @param string Raw input string
|
||||
* @param boolean Run through parse_incoming routine
|
||||
* @see IPSText::parseCleanValue
|
||||
* @return @e string
|
||||
*/
|
||||
public function convertAndMakeSafe( $value, $parse_incoming=true )
|
||||
{
|
||||
$value = rawurldecode( $value );
|
||||
|
||||
//-----------------------------------------
|
||||
// \ char is passed as %5C so it won't be double
|
||||
// escaped if magic quotes is on - do it manually
|
||||
// @link http://community.invisionpower.com/tracker/issue-24971-status-update-issue/
|
||||
//-----------------------------------------
|
||||
|
||||
if( IPS_MAGIC_QUOTES )
|
||||
{
|
||||
$value = str_replace( "\\", "\\\\", $value );
|
||||
}
|
||||
|
||||
$value = $this->convertUnicode( $value );
|
||||
$value = $this->convertHtmlEntities( $value );
|
||||
|
||||
if( $parse_incoming )
|
||||
{
|
||||
$value = IPSText::parseCleanValue( $value );
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove hook comments and parse replacements
|
||||
*
|
||||
* @param string Output data
|
||||
* @return @e string
|
||||
*/
|
||||
public function cleanOutput( $string )
|
||||
{
|
||||
if ( ! IN_ACP )
|
||||
{
|
||||
$string = preg_replace( '#<!--hook\.([^\>]+?)-->#', '', $string );
|
||||
}
|
||||
|
||||
$string = ipsRegistry::getClass('output')->replaceMacros( $string );
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Print a generic error message
|
||||
*
|
||||
* @return @e void
|
||||
*/
|
||||
public function returnGenericError()
|
||||
{
|
||||
@header( "Content-type: text/xml" );
|
||||
$this->printNocacheHeaders();
|
||||
|
||||
$this->xml_output = $this->xml_header . "\r\n<errors>\r\n";
|
||||
$this->xml_output .= "<error><message>You must be logged in to access this feature</message></error>\r\n";
|
||||
$this->xml_output .= "</errors>";
|
||||
|
||||
print $this->xml_output;
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a NULL XML result
|
||||
*
|
||||
* @param mixed Value to send
|
||||
* @return @e void
|
||||
*/
|
||||
public function returnNull( $val=0 )
|
||||
{
|
||||
@header( "Content-type: text/xml" );
|
||||
$this->printNocacheHeaders();
|
||||
|
||||
$val = $this->parseAndCleanHooks( $val );
|
||||
|
||||
print $this->xml_header . "\r\n<null>{$val}</null>";
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string
|
||||
*
|
||||
* @param string String to output
|
||||
* @return @e void
|
||||
*/
|
||||
public function returnString( $string )
|
||||
{
|
||||
@header( "Content-type: text/plain;charset=" . IPS_DOC_CHAR_SET );
|
||||
$this->printNocacheHeaders();
|
||||
|
||||
echo $this->parseAndCleanHooks( $string );
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a JSON error message
|
||||
*
|
||||
* @param string Error message
|
||||
* @param string Content-type header to send
|
||||
* @return @e void
|
||||
*/
|
||||
public function returnJsonError( $message, $header="application/json" )
|
||||
{
|
||||
/* Just alias it... */
|
||||
$this->returnJsonArray( array( 'error' => $message ), false, $header );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a JSON object
|
||||
*
|
||||
* @param array Array of key => value fields
|
||||
* @param boolean Clean the data (used when passing HTML)
|
||||
* @param string Optional content-type header string (default application/json)
|
||||
* @param array Optional array (0 => template group, 1 => bit name) to pass JSON into a custom skin method
|
||||
* @return @e void
|
||||
*/
|
||||
public function returnJsonArray( $json=array(), $cleanData=false, $header="application/json", $templateWrapper=array() )
|
||||
{
|
||||
@header( "Content-type: " . $header . ";charset=" . IPS_DOC_CHAR_SET );
|
||||
$this->printNocacheHeaders();
|
||||
|
||||
/* Always return as UTF-8 */
|
||||
array_walk_recursive( $json, array( 'IPSText', 'arrayWalkCallbackConvert' ) );
|
||||
|
||||
if ( $cleanData )
|
||||
{
|
||||
array_walk_recursive( $json, array( $this, 'cleanHtml' ) );
|
||||
}
|
||||
|
||||
$result = json_encode( $json );
|
||||
$result = IPSText::convertCharsets($result, "UTF-8", IPS_DOC_CHAR_SET);
|
||||
|
||||
/* Print via a wrapper? */
|
||||
if ( is_array( $templateWrapper ) AND count( $templateWrapper ) )
|
||||
{
|
||||
print ipsRegistry::getClass('output')->getTemplate( $templateWrapper[0] )->$templateWrapper[1]( $result );
|
||||
}
|
||||
else
|
||||
{
|
||||
print $result;
|
||||
}
|
||||
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return HTML content
|
||||
*
|
||||
* @param string HTML to output
|
||||
* @param boolean Force returned output to UTF-8
|
||||
* @return @e void
|
||||
*/
|
||||
public function returnHtml( $string, $returnAsUtf8=false )
|
||||
{
|
||||
if ( $string )
|
||||
{
|
||||
$this->cleanHtml( $string );
|
||||
}
|
||||
|
||||
/* Always return as UTF-8 */
|
||||
if ( $returnAsUtf8 )
|
||||
{
|
||||
$string = IPSText::convertCharsets( $string, IPS_DOC_CHAR_SET, "UTF-8" );
|
||||
}
|
||||
|
||||
@header( "Content-type: text/html;charset=" . IPS_DOC_CHAR_SET );
|
||||
$this->printNocacheHeaders();
|
||||
|
||||
print $string;
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute template hooks and remove hook comments
|
||||
*
|
||||
* @param string $string
|
||||
* @return @e string
|
||||
*/
|
||||
public function parseAndCleanHooks( $string )
|
||||
{
|
||||
$string = ipsRegistry::getClass('output')->templateHooks( $string );
|
||||
$string = preg_replace( '#<!--hook\.([^\>]+?)-->#', '', $string );
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print 200 OK and nocache headers
|
||||
*
|
||||
* @return @e void
|
||||
*/
|
||||
public function printNocacheHeaders()
|
||||
{
|
||||
if ( isset( $_SERVER['SERVER_PROTOCOL'] ) AND strstr( $_SERVER['SERVER_PROTOCOL'], '/1.0' ) )
|
||||
{
|
||||
header( "HTTP/1.0 200 OK" );
|
||||
}
|
||||
else
|
||||
{
|
||||
header( "HTTP/1.1 200 OK" );
|
||||
}
|
||||
|
||||
header( "Cache-Control: no-cache, must-revalidate, max-age=0" );
|
||||
header( "Expires: 0" );
|
||||
header( "Pragma: no-cache" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert AJAX unicode to standard char codes
|
||||
*
|
||||
* @deprecated This function no longer does anything
|
||||
* @param string Input to convert
|
||||
* @return @e string
|
||||
*/
|
||||
public function convertUnicode( $t )
|
||||
{
|
||||
/* This is called at various stages through different ajax files but its no longer required */
|
||||
/* The ajax class cleans up (converts via IPSText::convertUnicode()) the post get and input vars in the constructor now so we don't need to manually use it */
|
||||
|
||||
return $t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert HTML entities into raw characters
|
||||
*
|
||||
* @param string Input to convert
|
||||
* @return @e string
|
||||
*/
|
||||
public function convertHtmlEntities($t)
|
||||
{
|
||||
//-----------------------------------------
|
||||
// Try and fix up HTML entities with missing ;
|
||||
//-----------------------------------------
|
||||
|
||||
$t = preg_replace( '/&#(\d+?)([^\d;])/i', "&#\\1;\\2", $t );
|
||||
|
||||
//-----------------------------------------
|
||||
// Continue...
|
||||
//-----------------------------------------
|
||||
|
||||
if ( strtolower(IPS_DOC_CHAR_SET) != 'iso-8859-1' && strtolower(IPS_DOC_CHAR_SET) != 'utf-8' )
|
||||
{
|
||||
if ( isset($this->decodeCharsets[ strtolower(IPS_DOC_CHAR_SET) ]) )
|
||||
{
|
||||
$IPS_DOC_CHAR_SET = $this->decodeCharsets[strtolower(IPS_DOC_CHAR_SET)];
|
||||
|
||||
$t = html_entity_decode( $t, ENT_NOQUOTES, IPS_DOC_CHAR_SET );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Take a crack at entities in other character sets
|
||||
|
||||
$t = str_replace( "&#", "&#", $t );
|
||||
|
||||
// If mb functions available, we can knock out html entities for a few more char sets
|
||||
|
||||
if( function_exists('mb_list_encodings') )
|
||||
{
|
||||
$valid_encodings = array();
|
||||
$valid_encodings = mb_list_encodings();
|
||||
|
||||
if( count($valid_encodings) )
|
||||
{
|
||||
if( in_array( strtoupper(IPS_DOC_CHAR_SET), $valid_encodings ) )
|
||||
{
|
||||
$t = mb_convert_encoding( $t, strtoupper(IPS_DOC_CHAR_SET), 'HTML-ENTITIES' );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats an HTML string for output. Fixes some browser-specific bugs, parses replacements and executes hooks
|
||||
*
|
||||
* @param string $string
|
||||
* @param string Array key (only necessary when executed from an array_walk callback)
|
||||
* @return @e string
|
||||
*/
|
||||
public function cleanHtml( &$string, $key='' )
|
||||
{
|
||||
// Fix IE bugs
|
||||
$string = str_ireplace( "§", "&sect", $string );
|
||||
|
||||
if ( strtolower( IPS_DOC_CHAR_SET ) == 'iso-8859-1' )
|
||||
{
|
||||
$string = str_replace( "ì", "“", $string );
|
||||
$string = str_replace( "î", "”", $string );
|
||||
}
|
||||
|
||||
// Other stuff
|
||||
$string = ipsRegistry::getClass('output')->replaceMacros( $string );
|
||||
$string = $this->parseAndCleanHooks( $string );
|
||||
|
||||
return $string;
|
||||
}
|
||||
<?php
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.4.5
|
||||
* AJAX input parsing and handling
|
||||
* Last Updated: $Date: 2012-08-28 17:56:22 -0400 (Tue, 28 Aug 2012) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/company/standards.php#license
|
||||
* @package IP.Board
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since Friday 19th May 2006 17:33
|
||||
* @version $Revision: 11296 $
|
||||
*/
|
||||
|
||||
|
||||
class classAjax
|
||||
{
|
||||
/**
|
||||
* XML output
|
||||
*
|
||||
* @var string Output
|
||||
*/
|
||||
public $xml_output;
|
||||
|
||||
/**
|
||||
* XML Header
|
||||
*
|
||||
* @var string XML doctype
|
||||
*/
|
||||
public $xml_header;
|
||||
|
||||
/**
|
||||
* Character sets
|
||||
*
|
||||
* @var array Charsets supported by html_entity_decode
|
||||
*/
|
||||
protected $decodeCharsets = array('iso-8859-1' => 'ISO-8859-1',
|
||||
'iso8859-1' => 'ISO-8859-1',
|
||||
'iso-8859-15' => 'ISO-8859-15',
|
||||
'iso8859-15' => 'ISO-8859-15',
|
||||
'utf-8' => 'UTF-8',
|
||||
'cp866' => 'cp866',
|
||||
'ibm866' => 'cp866',
|
||||
'cp1251' => 'windows-1251',
|
||||
'windows-1251' => 'windows-1251',
|
||||
'win-1251' => 'windows-1251',
|
||||
'cp1252' => 'windows-1252',
|
||||
'windows-1252' => 'windows-1252',
|
||||
'koi8-r' => 'KOI8-R',
|
||||
'koi8-ru' => 'KOI8-R',
|
||||
'koi8r' => 'KOI8-R',
|
||||
'big5' => 'BIG5',
|
||||
'gb2312' => 'GB2312',
|
||||
'big5-hkscs' => 'BIG5-HKSCS',
|
||||
'shift_jis' => 'Shift_JIS',
|
||||
'sjis' => 'Shift_JIS',
|
||||
'euc-jp' => 'EUC-JP',
|
||||
'eucjp' => 'EUC-JP' );
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @return @e void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ( ! defined( 'IPS_DOC_CHAR_SET' ) )
|
||||
{
|
||||
define( 'IPS_DOC_CHAR_SET', 'UTF-8' );
|
||||
}
|
||||
|
||||
$this->xml_header = "<?xml version=\"1.0\" encoding=\"" . IPS_DOC_CHAR_SET . "\"?".'>';
|
||||
|
||||
/* Convert incoming $_POST fields */
|
||||
array_walk_recursive( $_POST, array( $this, 'arrayWalkConvert' ) );
|
||||
|
||||
//-----------------------------------------
|
||||
// Using this code allows characters that ARE supported
|
||||
// within the character set to be recoded properly, instead
|
||||
// of as HTML entities when submitted via AJAX. The problem is,
|
||||
// any characters NOT supported in the charset are corrupted. :-\
|
||||
//-----------------------------------------
|
||||
//array_walk_recursive( $_POST, create_function( '&$value, $key', '$value = IPSText::convertCharsets( IPSText::convertUnicode($value, true), "utf-8", "' . IPS_DOC_CHAR_SET . '" );' ) );
|
||||
|
||||
// We use $_REQUEST in a lot of places, so we might need to do this, but based on the below comments I'll leave this
|
||||
// commented out for now...
|
||||
//array_walk_recursive( $_REQUEST, create_function( '&$value, $key', '$value = IPSText::convertUnicode($value);' ) );
|
||||
|
||||
/* Risky converting $_GET because it calls rawurldecode which could allow crafty users to hide html entities */
|
||||
//array_walk_recursive( $_GET , create_function( '&$value, $key', '$value = IPSText::convertUnicode($value);' ) );
|
||||
//array_walk_recursive( ipsRegistry::$request, create_function( '&$value, $key', '$value = IPSText::convertUnicode($value);' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to convert unicode and charset for AJAX requests
|
||||
*
|
||||
* @param mixed Value
|
||||
* @param string Key
|
||||
* @return @e void
|
||||
*/
|
||||
public function arrayWalkConvert( &$value, $key )
|
||||
{
|
||||
if( is_string( $value ) )
|
||||
{
|
||||
$value = IPSText::convertCharsets( IPSText::convertUnicode( $value ), "utf-8", IPS_DOC_CHAR_SET );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize the character set of incoming AJAX data and optionally parse the value through the parseCleanValue routine
|
||||
*
|
||||
* @param string Raw input string
|
||||
* @param boolean Run through parse_incoming routine
|
||||
* @see IPSText::parseCleanValue
|
||||
* @return @e string
|
||||
*/
|
||||
public function convertAndMakeSafe( $value, $parse_incoming=true )
|
||||
{
|
||||
$value = rawurldecode( $value );
|
||||
|
||||
//-----------------------------------------
|
||||
// \ char is passed as %5C so it won't be double
|
||||
// escaped if magic quotes is on - do it manually
|
||||
// @link http://community.invisionpower.com/tracker/issue-24971-status-update-issue/
|
||||
//-----------------------------------------
|
||||
|
||||
if( IPS_MAGIC_QUOTES )
|
||||
{
|
||||
$value = str_replace( "\\", "\\\\", $value );
|
||||
}
|
||||
|
||||
$value = $this->convertUnicode( $value );
|
||||
$value = $this->convertHtmlEntities( $value );
|
||||
|
||||
if( $parse_incoming )
|
||||
{
|
||||
$value = IPSText::parseCleanValue( $value );
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove hook comments and parse replacements
|
||||
*
|
||||
* @param string Output data
|
||||
* @return @e string
|
||||
*/
|
||||
public function cleanOutput( $string )
|
||||
{
|
||||
if ( ! IN_ACP )
|
||||
{
|
||||
$string = preg_replace( '#<!--hook\.([^\>]+?)-->#', '', $string );
|
||||
}
|
||||
|
||||
$string = ipsRegistry::getClass('output')->replaceMacros( $string );
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Print a generic error message
|
||||
*
|
||||
* @return @e void
|
||||
*/
|
||||
public function returnGenericError()
|
||||
{
|
||||
@header( "Content-type: text/xml" );
|
||||
$this->printNocacheHeaders();
|
||||
|
||||
$this->xml_output = $this->xml_header . "\r\n<errors>\r\n";
|
||||
$this->xml_output .= "<error><message>Вы должны быть залогинены для доступа к этой функции</message></error>\r\n";
|
||||
$this->xml_output .= "</errors>";
|
||||
|
||||
print $this->xml_output;
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a NULL XML result
|
||||
*
|
||||
* @param mixed Value to send
|
||||
* @return @e void
|
||||
*/
|
||||
public function returnNull( $val=0 )
|
||||
{
|
||||
@header( "Content-type: text/xml" );
|
||||
$this->printNocacheHeaders();
|
||||
|
||||
$val = $this->parseAndCleanHooks( $val );
|
||||
|
||||
print $this->xml_header . "\r\n<null>{$val}</null>";
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string
|
||||
*
|
||||
* @param string String to output
|
||||
* @return @e void
|
||||
*/
|
||||
public function returnString( $string )
|
||||
{
|
||||
@header( "Content-type: text/plain;charset=" . IPS_DOC_CHAR_SET );
|
||||
$this->printNocacheHeaders();
|
||||
|
||||
echo $this->parseAndCleanHooks( $string );
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a JSON error message
|
||||
*
|
||||
* @param string Error message
|
||||
* @param string Content-type header to send
|
||||
* @return @e void
|
||||
*/
|
||||
public function returnJsonError( $message, $header="application/json" )
|
||||
{
|
||||
/* Just alias it... */
|
||||
$this->returnJsonArray( array( 'error' => $message ), false, $header );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a JSON object
|
||||
*
|
||||
* @param array Array of key => value fields
|
||||
* @param boolean Clean the data (used when passing HTML)
|
||||
* @param string Optional content-type header string (default application/json)
|
||||
* @param array Optional array (0 => template group, 1 => bit name) to pass JSON into a custom skin method
|
||||
* @return @e void
|
||||
*/
|
||||
public function returnJsonArray( $json=array(), $cleanData=false, $header="application/json", $templateWrapper=array() )
|
||||
{
|
||||
@header( "Content-type: " . $header . ";charset=" . IPS_DOC_CHAR_SET );
|
||||
$this->printNocacheHeaders();
|
||||
|
||||
/* Always return as UTF-8 */
|
||||
array_walk_recursive( $json, array( 'IPSText', 'arrayWalkCallbackConvert' ) );
|
||||
|
||||
if ( $cleanData )
|
||||
{
|
||||
array_walk_recursive( $json, array( $this, 'cleanHtml' ) );
|
||||
}
|
||||
|
||||
$result = json_encode( $json );
|
||||
$result = IPSText::convertCharsets($result, "UTF-8", IPS_DOC_CHAR_SET);
|
||||
|
||||
/* Print via a wrapper? */
|
||||
if ( is_array( $templateWrapper ) AND count( $templateWrapper ) )
|
||||
{
|
||||
print ipsRegistry::getClass('output')->getTemplate( $templateWrapper[0] )->$templateWrapper[1]( $result );
|
||||
}
|
||||
else
|
||||
{
|
||||
print $result;
|
||||
}
|
||||
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return HTML content
|
||||
*
|
||||
* @param string HTML to output
|
||||
* @param boolean Force returned output to UTF-8
|
||||
* @return @e void
|
||||
*/
|
||||
public function returnHtml( $string, $returnAsUtf8=false )
|
||||
{
|
||||
if ( $string )
|
||||
{
|
||||
$this->cleanHtml( $string );
|
||||
}
|
||||
|
||||
/* Always return as UTF-8 */
|
||||
if ( $returnAsUtf8 )
|
||||
{
|
||||
$string = IPSText::convertCharsets( $string, IPS_DOC_CHAR_SET, "UTF-8" );
|
||||
}
|
||||
|
||||
@header( "Content-type: text/html;charset=" . IPS_DOC_CHAR_SET );
|
||||
$this->printNocacheHeaders();
|
||||
|
||||
print $string;
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute template hooks and remove hook comments
|
||||
*
|
||||
* @param string $string
|
||||
* @return @e string
|
||||
*/
|
||||
public function parseAndCleanHooks( $string )
|
||||
{
|
||||
$string = ipsRegistry::getClass('output')->templateHooks( $string );
|
||||
$string = preg_replace( '#<!--hook\.([^\>]+?)-->#', '', $string );
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print 200 OK and nocache headers
|
||||
*
|
||||
* @return @e void
|
||||
*/
|
||||
public function printNocacheHeaders()
|
||||
{
|
||||
if ( isset( $_SERVER['SERVER_PROTOCOL'] ) AND strstr( $_SERVER['SERVER_PROTOCOL'], '/1.0' ) )
|
||||
{
|
||||
header( "HTTP/1.0 200 OK" );
|
||||
}
|
||||
else
|
||||
{
|
||||
header( "HTTP/1.1 200 OK" );
|
||||
}
|
||||
|
||||
header( "Cache-Control: no-cache, must-revalidate, max-age=0" );
|
||||
header( "Expires: 0" );
|
||||
header( "Pragma: no-cache" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert AJAX unicode to standard char codes
|
||||
*
|
||||
* @deprecated This function no longer does anything
|
||||
* @param string Input to convert
|
||||
* @return @e string
|
||||
*/
|
||||
public function convertUnicode( $t )
|
||||
{
|
||||
/* This is called at various stages through different ajax files but its no longer required */
|
||||
/* The ajax class cleans up (converts via IPSText::convertUnicode()) the post get and input vars in the constructor now so we don't need to manually use it */
|
||||
|
||||
return $t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert HTML entities into raw characters
|
||||
*
|
||||
* @param string Input to convert
|
||||
* @return @e string
|
||||
*/
|
||||
public function convertHtmlEntities($t)
|
||||
{
|
||||
//-----------------------------------------
|
||||
// Try and fix up HTML entities with missing ;
|
||||
//-----------------------------------------
|
||||
|
||||
$t = preg_replace( '/&#(\d+?)([^\d;])/i', "&#\\1;\\2", $t );
|
||||
|
||||
//-----------------------------------------
|
||||
// Continue...
|
||||
//-----------------------------------------
|
||||
|
||||
if ( strtolower(IPS_DOC_CHAR_SET) != 'iso-8859-1' && strtolower(IPS_DOC_CHAR_SET) != 'utf-8' )
|
||||
{
|
||||
if ( isset($this->decodeCharsets[ strtolower(IPS_DOC_CHAR_SET) ]) )
|
||||
{
|
||||
$IPS_DOC_CHAR_SET = $this->decodeCharsets[strtolower(IPS_DOC_CHAR_SET)];
|
||||
|
||||
$t = html_entity_decode( $t, ENT_NOQUOTES, IPS_DOC_CHAR_SET );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Take a crack at entities in other character sets
|
||||
|
||||
$t = str_replace( "&#", "&#", $t );
|
||||
|
||||
// If mb functions available, we can knock out html entities for a few more char sets
|
||||
|
||||
if( function_exists('mb_list_encodings') )
|
||||
{
|
||||
$valid_encodings = array();
|
||||
$valid_encodings = mb_list_encodings();
|
||||
|
||||
if( count($valid_encodings) )
|
||||
{
|
||||
if( in_array( strtoupper(IPS_DOC_CHAR_SET), $valid_encodings ) )
|
||||
{
|
||||
$t = mb_convert_encoding( $t, strtoupper(IPS_DOC_CHAR_SET), 'HTML-ENTITIES' );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats an HTML string for output. Fixes some browser-specific bugs, parses replacements and executes hooks
|
||||
*
|
||||
* @param string $string
|
||||
* @param string Array key (only necessary when executed from an array_walk callback)
|
||||
* @return @e string
|
||||
*/
|
||||
public function cleanHtml( &$string, $key='' )
|
||||
{
|
||||
/* Is it really a string? */
|
||||
if ( is_string($string) )
|
||||
{
|
||||
// Fix IE bugs
|
||||
$string = str_ireplace( "§", "&sect", $string );
|
||||
|
||||
if ( strtolower( IPS_DOC_CHAR_SET ) == 'iso-8859-1' )
|
||||
{
|
||||
$string = str_replace( "ì", "“", $string );
|
||||
$string = str_replace( "î", "”", $string );
|
||||
}
|
||||
|
||||
// Other stuff
|
||||
$string = ipsRegistry::getClass('output')->replaceMacros( $string );
|
||||
$string = $this->parseAndCleanHooks( $string );
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,9 @@
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* IP.Board v3.4.5
|
||||
* This class can act as an API server, handling API requests
|
||||
* Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $
|
||||
* Last Updated: $Date: 2012-12-27 11:37:49 -0500 (Thu, 27 Dec 2012) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
@@ -15,7 +15,7 @@
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since Friday 6th January 2006 (12:24)
|
||||
* @version $Revision: 10914 $
|
||||
* @version $Revision: 11758 $
|
||||
*
|
||||
* Examples of sending and receiving API data
|
||||
* <code>
|
||||
@@ -557,7 +557,7 @@ class classApiServer
|
||||
*/
|
||||
protected function _encodeBase64Array( $array )
|
||||
{
|
||||
return base64_encode( serialize( $array ) );
|
||||
return base64_encode( json_encode( $array ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -577,7 +577,7 @@ class classApiServer
|
||||
* @link http://community.invisionpower.com/tracker/issue-18676-xml-rpcapiserver-params-not-unserialized/
|
||||
* base64 data types are properly base-64 decoded in the XML-RPC library now, so it is redundant to do so here now
|
||||
*/
|
||||
return unserialize( $data );
|
||||
return json_decode( $data, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* IP.Board v3.4.5
|
||||
* This class acts as a cache layer, allowing you to store and retrieve data in
|
||||
* external cache sources such as memcache or APC
|
||||
* Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $
|
||||
* Last Updated: $Date: 2012-05-10 16:10:13 -0400 (Thu, 10 May 2012) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
@@ -16,7 +16,7 @@
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since Friday 19th May 2006 17:33
|
||||
* @version $Revision: 10914 $
|
||||
* @version $Revision: 10721 $
|
||||
*
|
||||
* Basic Usage Examples
|
||||
* <code>
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* IP.Board v3.4.5
|
||||
* This class acts as a cache layer, allowing you to store and retrieve data in
|
||||
* external cache sources such as memcache or APC
|
||||
* Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $
|
||||
* Last Updated: $Date: 2012-05-10 16:10:13 -0400 (Thu, 10 May 2012) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
@@ -16,7 +16,7 @@
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since Friday 19th May 2006 17:33
|
||||
* @version $Revision: 10914 $
|
||||
* @version $Revision: 10721 $
|
||||
*
|
||||
* Basic Usage Examples
|
||||
* <code>
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* IP.Board v3.4.5
|
||||
* This class acts as a cache layer, allowing you to store and retrieve data in
|
||||
* external cache sources such as memcache or APC
|
||||
* Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $
|
||||
* Last Updated: $Date: 2012-05-10 16:10:13 -0400 (Thu, 10 May 2012) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
@@ -16,7 +16,7 @@
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since Friday 19th May 2006 17:33
|
||||
* @version $Revision: 10914 $
|
||||
* @version $Revision: 10721 $
|
||||
*
|
||||
* Basic Usage Examples
|
||||
* <code>
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* IP.Board v3.4.5
|
||||
* This class acts as a cache layer, allowing you to store and retrieve data in
|
||||
* external cache sources such as memcache or APC
|
||||
* Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $
|
||||
* Last Updated: $Date: 2012-05-10 16:10:13 -0400 (Thu, 10 May 2012) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
@@ -16,7 +16,7 @@
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since Friday 19th May 2006 17:33
|
||||
* @version $Revision: 10914 $
|
||||
* @version $Revision: 10721 $
|
||||
*
|
||||
* Basic Usage Examples
|
||||
* <code>
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* IP.Board v3.4.5
|
||||
* This class acts as a cache layer, allowing you to store and retrieve data in
|
||||
* external cache sources such as memcache or APC
|
||||
* Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $
|
||||
* Last Updated: $Date: 2012-05-10 16:10:13 -0400 (Thu, 10 May 2012) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
@@ -16,7 +16,7 @@
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since Friday 19th May 2006 17:33
|
||||
* @version $Revision: 10914 $
|
||||
* @version $Revision: 10721 $
|
||||
*
|
||||
* Basic Usage Examples
|
||||
* <code>
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* IP.Board v3.4.5
|
||||
* This class acts as a cache layer, allowing you to store and retrieve data in
|
||||
* external cache sources such as memcache or APC
|
||||
* Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $
|
||||
* Last Updated: $Date: 2012-05-10 16:10:13 -0400 (Thu, 10 May 2012) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
@@ -16,7 +16,7 @@
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since Friday 19th May 2006 17:33
|
||||
* @version $Revision: 10914 $
|
||||
* @version $Revision: 10721 $
|
||||
*
|
||||
* Basic Usage Examples
|
||||
* <code>
|
||||
|
||||
+101
-101
@@ -1,102 +1,102 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classCaptcha.php Provides methods to handle CAPTCHA abstraction - easily create, check and display CAPTHCA images
|
||||
*~TERABYTE_DOC_READY~
|
||||
* $Copyright: (c) 2001 - 2011 Invision Power Services, Inc.$
|
||||
* $License: http://www.invisionpower.com/company/standards.php#license$
|
||||
* $Author: bfarber $
|
||||
* @since Friday 19th May 2006 17:33
|
||||
* $LastChangedDate: 2012-02-10 20:05:52 -0500 (Fri, 10 Feb 2012) $
|
||||
* @version v3.3.4
|
||||
* $Revision: 10288 $
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @class classCaptcha
|
||||
* @brief Provides methods to handle CAPTCHA abstraction - easily create, check and display CAPTHCA images
|
||||
*
|
||||
*/
|
||||
class classCaptcha
|
||||
{
|
||||
/**
|
||||
* Registry Object
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
public $registry;
|
||||
|
||||
/**
|
||||
* Settings array
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $settings;
|
||||
|
||||
/**
|
||||
* Object that stored the plug in class
|
||||
*
|
||||
* @var $_plugInClass
|
||||
*/
|
||||
protected $_plugInClass;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param object $registry Registry Object
|
||||
* @return @e void
|
||||
*/
|
||||
public function __construct( ipsRegistry $registry )
|
||||
{
|
||||
$this->registry = $registry;
|
||||
$this->settings =& $this->registry->fetchSettings();
|
||||
|
||||
$plugin = $this->settings['bot_antispam_type'];
|
||||
|
||||
if ( ! is_file( IPS_KERNEL_PATH . 'classCaptchaPlugin/' . $plugin . '.php' ) )
|
||||
{
|
||||
$plugin = 'default';
|
||||
}
|
||||
|
||||
require_once( IPS_KERNEL_PATH . 'classCaptchaPlugin/' . $plugin . '.php' );/*noLibHook*/
|
||||
$this->_plugInClass = new captchaPlugIn( $registry );
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic __call method
|
||||
*
|
||||
* @param string $method Method name
|
||||
* @param mixed $arguments Method arguments
|
||||
* @return @e mixed
|
||||
*/
|
||||
public function __call( $method, $arguments )
|
||||
{
|
||||
if ( method_exists( $this->_plugInClass, $method ) )
|
||||
{
|
||||
return $this->_plugInClass->$method( $arguments );
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_error( $method . " does not exist", E_USER_ERROR );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic __get method
|
||||
*
|
||||
* @param string $name Property name
|
||||
* @return @e mixed
|
||||
*/
|
||||
public function __get( $name )
|
||||
{
|
||||
if ( property_exists( $this->_plugInClass, $name ) )
|
||||
{
|
||||
return $this->_plugInClass->$name;
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_error( $name . " does not exist", E_USER_ERROR );
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classCaptcha.php Provides methods to handle CAPTCHA abstraction - easily create, check and display CAPTHCA images
|
||||
*~TERABYTE_DOC_READY~
|
||||
* $Copyright: (c) 2001 - 2011 Invision Power Services, Inc.$
|
||||
* $License: http://www.invisionpower.com/company/standards.php#license$
|
||||
* $Author: bfarber $
|
||||
* @since Friday 19th May 2006 17:33
|
||||
* $LastChangedDate: 2012-02-10 20:05:52 -0500 (Fri, 10 Feb 2012) $
|
||||
* @version v3.4.5
|
||||
* $Revision: 10288 $
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @class classCaptcha
|
||||
* @brief Provides methods to handle CAPTCHA abstraction - easily create, check and display CAPTHCA images
|
||||
*
|
||||
*/
|
||||
class classCaptcha
|
||||
{
|
||||
/**
|
||||
* Registry Object
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
public $registry;
|
||||
|
||||
/**
|
||||
* Settings array
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $settings;
|
||||
|
||||
/**
|
||||
* Object that stored the plug in class
|
||||
*
|
||||
* @var $_plugInClass
|
||||
*/
|
||||
protected $_plugInClass;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param object $registry Registry Object
|
||||
* @return @e void
|
||||
*/
|
||||
public function __construct( ipsRegistry $registry )
|
||||
{
|
||||
$this->registry = $registry;
|
||||
$this->settings =& $this->registry->fetchSettings();
|
||||
|
||||
$plugin = $this->settings['bot_antispam_type'];
|
||||
|
||||
if ( ! is_file( IPS_KERNEL_PATH . 'classCaptchaPlugin/' . $plugin . '.php' ) )
|
||||
{
|
||||
$plugin = 'default';
|
||||
}
|
||||
|
||||
require_once( IPS_KERNEL_PATH . 'classCaptchaPlugin/' . $plugin . '.php' );/*noLibHook*/
|
||||
$this->_plugInClass = new captchaPlugIn( $registry );
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic __call method
|
||||
*
|
||||
* @param string $method Method name
|
||||
* @param mixed $arguments Method arguments
|
||||
* @return @e mixed
|
||||
*/
|
||||
public function __call( $method, $arguments )
|
||||
{
|
||||
if ( method_exists( $this->_plugInClass, $method ) )
|
||||
{
|
||||
return $this->_plugInClass->$method( $arguments );
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_error( $method . " не существует", E_USER_ERROR );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic __get method
|
||||
*
|
||||
* @param string $name Property name
|
||||
* @return @e mixed
|
||||
*/
|
||||
public function __get( $name )
|
||||
{
|
||||
if ( property_exists( $this->_plugInClass, $name ) )
|
||||
{
|
||||
return $this->_plugInClass->$name;
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_error( $name . " не существует", E_USER_ERROR );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
* $Author: bfarber $
|
||||
* @since Friday 19th May 2006 17:33
|
||||
* $LastChangedDate: 2012-02-10 20:05:52 -0500 (Fri, 10 Feb 2012) $
|
||||
* @version v3.3.4
|
||||
* @version v3.4.5
|
||||
* $Revision: 10288 $
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,262 @@
|
||||
<?php
|
||||
|
||||
|
||||
/**
|
||||
* The KeyCAPTCHA server URL's
|
||||
*/
|
||||
|
||||
if ( !class_exists('KeyCAPTCHA_CLASS') )
|
||||
{
|
||||
class KeyCAPTCHA_CLASS
|
||||
{
|
||||
private $c_kc_keyword = "accept";
|
||||
private $p_kc_visitor_ip = "";
|
||||
private $p_kc_session_id = "";
|
||||
private $p_kc_web_server_sign = "";
|
||||
private $p_kc_web_server_sign2 = "";
|
||||
private $p_kc_js_code = "";
|
||||
private $p_kc_private_key = "";
|
||||
private $p_kc_userID = 0;
|
||||
public function get_web_server_sign($use_visitor_ip = 0)
|
||||
{
|
||||
return md5($this->p_kc_session_id . (($use_visitor_ip) ? ($this->p_kc_visitor_ip) :("")) . $this->p_kc_private_key);
|
||||
}
|
||||
|
||||
function __construct($a_private_key='')
|
||||
{
|
||||
if ( $a_private_key != '' ) {
|
||||
$set = explode("0",trim($a_private_key),2);
|
||||
|
||||
if (sizeof($set)>1){
|
||||
$this->p_kc_private_key = trim($set[0]);
|
||||
$this->p_kc_userID = (int)$set[1];
|
||||
$this->p_kc_js_code =
|
||||
"<!-- KeyCAPTCHA code (www.keycaptcha.com)-->
|
||||
<script type=\"text/javascript\">
|
||||
var s_s_c_user_id = '".$this->p_kc_userID."';
|
||||
var s_s_c_session_id = '#KC_SESSION_ID#';
|
||||
var s_s_c_captcha_field_id = 'capcode';
|
||||
var s_s_c_submit_button_id = 'submit,Submit';
|
||||
var s_s_c_web_server_sign = '#KC_WSIGN#';
|
||||
var s_s_c_web_server_sign2 = '#KC_WSIGN2#';
|
||||
</script>
|
||||
<script type=\"text/javascript\" src=\"http://backs.keycaptcha.com/swfs/cap.js\"></script>
|
||||
<!-- end of KeyCAPTCHA code-->";
|
||||
}
|
||||
}
|
||||
|
||||
$this->p_kc_session_id = uniqid() . '-1.0.0.033';
|
||||
$this->p_kc_visitor_ip = $_SERVER["REMOTE_ADDR"];
|
||||
}
|
||||
|
||||
function http_get($path)
|
||||
{
|
||||
$arr = parse_url($path);
|
||||
$host = $arr['host'];
|
||||
$page = $arr['path'];
|
||||
if ( $page=='' ) {
|
||||
$page='/';
|
||||
}
|
||||
if ( isset( $arr['query'] ) ) {
|
||||
$page.='?'.$arr['query'];
|
||||
}
|
||||
$errno = 0;
|
||||
$errstr = '';
|
||||
$fp = fsockopen ($host, 80, $errno, $errstr, 30);
|
||||
if (!$fp){ return ""; }
|
||||
$request = "GET $page HTTP/1.0\r\n";
|
||||
$request .= "Host: $host\r\n";
|
||||
$request .= "Connection: close\r\n";
|
||||
$request .= "Cache-Control: no-store, no-cache\r\n";
|
||||
$request .= "Pragma: no-cache\r\n";
|
||||
$request .= "User-Agent: KeyCAPTCHA\r\n";
|
||||
$request .= "\r\n";
|
||||
|
||||
fwrite ($fp,$request);
|
||||
$out = '';
|
||||
|
||||
while (!feof($fp)) $out .= fgets($fp, 250);
|
||||
fclose($fp);
|
||||
$ov = explode("close\r\n\r\n", $out);
|
||||
|
||||
return $ov[1];
|
||||
}
|
||||
|
||||
public function check_result($response)
|
||||
{
|
||||
$kc_vars = explode("|", $response);
|
||||
if ( count( $kc_vars ) < 4 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ($kc_vars[0] == md5($this->c_kc_keyword . $kc_vars[1] . $this->p_kc_private_key . $kc_vars[2]))
|
||||
{
|
||||
if (stripos($kc_vars[2], "http://") !== 0)
|
||||
{
|
||||
$kc_current_time = time();
|
||||
$kc_var_time = split('[/ :]', $kc_vars[2]);
|
||||
$kc_submit_time = gmmktime($kc_var_time[3], $kc_var_time[4], $kc_var_time[5], $kc_var_time[1], $kc_var_time[2], $kc_var_time[0]);
|
||||
if (($kc_current_time - $kc_submit_time) < 15)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($this->http_get($kc_vars[2]) == "1")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function render_js ()
|
||||
{
|
||||
if ( isset($_SERVER['HTTPS']) && ( $_SERVER['HTTPS'] == 'on' ) )
|
||||
{
|
||||
$this->p_kc_js_code = str_replace ("http://","https://", $this->p_kc_js_code);
|
||||
}
|
||||
$this->p_kc_js_code = str_replace ("#KC_SESSION_ID#", $this->p_kc_session_id, $this->p_kc_js_code);
|
||||
$this->p_kc_js_code = str_replace ("#KC_WSIGN#", $this->get_web_server_sign(1), $this->p_kc_js_code);
|
||||
$this->p_kc_js_code = str_replace ("#KC_WSIGN2#", $this->get_web_server_sign(), $this->p_kc_js_code);
|
||||
return $this->p_kc_js_code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class captchaPlugin
|
||||
{
|
||||
/**
|
||||
* Registry object
|
||||
*
|
||||
* @access protected
|
||||
* @var object
|
||||
*/
|
||||
public $registry;
|
||||
|
||||
/**
|
||||
* Database object
|
||||
*
|
||||
* @access protected
|
||||
* @var object
|
||||
*/
|
||||
public $DB;
|
||||
|
||||
/**
|
||||
* Settings object
|
||||
*
|
||||
* @access protected
|
||||
* @var object
|
||||
*/
|
||||
public $settings;
|
||||
|
||||
/**
|
||||
* Request object
|
||||
*
|
||||
* @access protected
|
||||
* @var object
|
||||
*/
|
||||
public $request;
|
||||
|
||||
/**
|
||||
* Language object
|
||||
*
|
||||
* @access protected
|
||||
* @var object
|
||||
*/
|
||||
public $lang;
|
||||
|
||||
/**
|
||||
* Member object
|
||||
*
|
||||
* @access protected
|
||||
* @var object
|
||||
*/
|
||||
public $member;
|
||||
|
||||
/**
|
||||
* Member data object
|
||||
*
|
||||
* @access protected
|
||||
* @var object
|
||||
*/
|
||||
public $memberData;
|
||||
|
||||
/**
|
||||
* Error code from KeyCAPTCHA
|
||||
*
|
||||
* @access protected
|
||||
* @var string
|
||||
*/
|
||||
public $error;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @access public
|
||||
* @param object Registry Object
|
||||
* @return void
|
||||
*/
|
||||
public function __construct( ipsRegistry $registry )
|
||||
{
|
||||
$this->registry = $registry;
|
||||
$this->DB = $this->registry->DB();
|
||||
$this->settings =& $this->registry->fetchSettings();
|
||||
$this->request =& $this->registry->fetchRequest();
|
||||
$this->lang = $this->registry->getClass('class_localization');
|
||||
$this->member = $this->registry->member();
|
||||
$this->memberData =& $this->registry->member()->fetchMemberData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the challenge HTML (javascript and non-javascript version).
|
||||
* This is called from the browser, and the resulting KeyCAPTCHA HTML widget
|
||||
* is embedded within the HTML form it was called from.
|
||||
*
|
||||
* @access public
|
||||
* @return string Form HTML to display
|
||||
*/
|
||||
public function getTemplate()
|
||||
{
|
||||
$private_key = $this->settings['keycaptcha_privatekey'];
|
||||
|
||||
if ( ! $private_key )
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
$kc_o = new KeyCAPTCHA_CLASS($private_key );
|
||||
|
||||
return $this->registry->output->getTemplate('global_other')->captchaKeycaptcha( '<input type="hidden" id="capcode" name="capcode">'.$kc_o->render_js() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the input code
|
||||
*
|
||||
* @access public
|
||||
* @return boolean Validation successful
|
||||
* @since 1.0
|
||||
*/
|
||||
public function validate()
|
||||
{
|
||||
$private_key = $this->settings['keycaptcha_privatekey'];
|
||||
|
||||
if ( ! $private_key )
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
$capcode = $_REQUEST['capcode'];
|
||||
|
||||
$kc_o = new KeyCAPTCHA_CLASS( $private_key );
|
||||
|
||||
if (! $kc_o->check_result($capcode) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -47,11 +47,11 @@ define("RECAPTCHA_VERIFY_SERVER", "http://www.google.com");
|
||||
*~TERABYTE_DOC_READY~
|
||||
* $Copyright: (c) 2001 - 2011 Invision Power Services, Inc.$
|
||||
* $License: http://www.invisionpower.com/company/standards.php#license$
|
||||
* $Author: bfarber $
|
||||
* $Author: mark $
|
||||
* @since Friday 19th May 2006 17:33
|
||||
* $LastChangedDate: 2012-02-10 20:05:52 -0500 (Fri, 10 Feb 2012) $
|
||||
* @version v3.3.4
|
||||
* $Revision: 10288 $
|
||||
* $LastChangedDate: 2013-02-11 12:32:07 -0500 (Mon, 11 Feb 2013) $
|
||||
* @version v3.4.5
|
||||
* $Revision: 11975 $
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -118,7 +118,7 @@ class captchaPlugin
|
||||
/* Settings */
|
||||
$this->public_key = trim( $this->settings['recaptcha_public_key'] );
|
||||
$this->private_key = trim( $this->settings['recaptcha_private_key'] );
|
||||
$this->useSSL = $this->settings['logins_over_https'];
|
||||
$this->useSSL = ( $this->settings['logins_over_https'] or $this->registry->output->isHTTPS );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,7 +153,8 @@ class captchaPlugin
|
||||
$html .= "<script type='text/javascript'>
|
||||
var RecaptchaOptions = {
|
||||
lang : '{$this->settings['recaptcha_language']}',
|
||||
theme : '{$this->settings['recaptcha_theme']}'
|
||||
theme : '{$this->settings['recaptcha_theme']}',
|
||||
tabindex: 49
|
||||
};
|
||||
</script>";
|
||||
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* IP.Board v3.4.5
|
||||
* Character set conversion library
|
||||
* Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $
|
||||
* Last Updated: $Date: 2012-12-07 14:02:27 -0500 (Fri, 07 Dec 2012) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
@@ -17,7 +17,7 @@
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since Friday 2nd December 2005 10:18
|
||||
* @version $Revision: 10914 $
|
||||
* @version $Revision: 11687 $
|
||||
* @version 1.0 2004-07-27 00:37
|
||||
* @link http://www.unicode.org Unicode Homepage
|
||||
* @link http://www.mikkom.pl My Homepage
|
||||
@@ -234,17 +234,25 @@ class classConvertCharset
|
||||
*/
|
||||
if ($string_char_set != "utf-8")
|
||||
{
|
||||
/* Cache the conversion table to prevent rebuilding on every request */
|
||||
static $charsetTables = array();
|
||||
|
||||
/**
|
||||
* Now build table with both charsets for encoding change.
|
||||
*/
|
||||
if ($destination_char_set != "utf-8")
|
||||
{
|
||||
$charsetTable = $this->_makeConversionTable( $string_char_set, $destination_char_set );
|
||||
}
|
||||
else
|
||||
if( !$charsetTables[ $string_char_set ] )
|
||||
{
|
||||
$charsetTable = $this->_makeConversionTable( $string_char_set );
|
||||
if ($destination_char_set != "utf-8")
|
||||
{
|
||||
$charsetTables[ $string_char_set ] = $this->_makeConversionTable( $string_char_set, $destination_char_set );
|
||||
}
|
||||
else
|
||||
{
|
||||
$charsetTables[ $string_char_set ] = $this->_makeConversionTable( $string_char_set );
|
||||
}
|
||||
}
|
||||
|
||||
$charsetTable = $charsetTables[ $string_char_set ];
|
||||
|
||||
if( !count($charsetTable) )
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
+2035
-1932
File diff suppressed because it is too large.
Load diff
@@ -3,26 +3,29 @@
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* IP.Board v3.4.5
|
||||
* MySQL Database Driver :: Further loads mysql or mysqli client appropriately
|
||||
* Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $
|
||||
* Last Updated: $Date: 2012-09-17 11:58:03 -0400 (Mon, 17 Sep 2012) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
* @author $Author: mark $
|
||||
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/company/standards.php#license
|
||||
* @package IP.Board
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since Monday 28th February 2005 16:46
|
||||
* @version $Revision: 10914 $
|
||||
* @version $Revision: 11341 $
|
||||
*/
|
||||
|
||||
/**
|
||||
* 1 = Replace into
|
||||
* 2 = Insert into...on duplicate key update
|
||||
*/
|
||||
define( 'REPLACE_TYPE', 2 );
|
||||
if( !defined('REPLACE_TYPE') )
|
||||
{
|
||||
define( 'REPLACE_TYPE', 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle base class definitions
|
||||
@@ -112,23 +115,141 @@ abstract class db_main_mysql extends dbMain
|
||||
* @param string [Optional] Where clause
|
||||
* @param boolean [Optional] Run on shutdown
|
||||
* @param boolean [Optional] $set is already pre-formatted
|
||||
* @param array [Optional] Joined table data
|
||||
* @return @e resource
|
||||
*/
|
||||
public function update( $table, $set, $where='', $shutdown=false, $preformatted=false, $debug=false )
|
||||
public function update( $table, $set, $where='', $shutdown=false, $preformatted=false, $add_join=array() )
|
||||
{
|
||||
//-----------------------------------------
|
||||
// Form query
|
||||
// Normal
|
||||
//-----------------------------------------
|
||||
|
||||
if ( empty( $add_join ) )
|
||||
{
|
||||
/* Compile the update clause */
|
||||
$dba = $preformatted ? $set : $this->compileUpdateString( $set );
|
||||
|
||||
/* Put it together */
|
||||
$query = "UPDATE " . $this->obj['sql_tbl_prefix'] . $table . " SET " . $dba;
|
||||
|
||||
/* Add in a where clause if necessary (we don't want to something silly like delete all the tickets...) */
|
||||
if ( $where )
|
||||
{
|
||||
$query .= " WHERE " . $where;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
// With joins
|
||||
//-----------------------------------------
|
||||
|
||||
else
|
||||
{
|
||||
//-----------------------------------------
|
||||
// OK, here we go...
|
||||
//-----------------------------------------
|
||||
|
||||
$dba = $preformatted ? $set : $this->compileUpdateString( $set );
|
||||
$from_array = array();
|
||||
$joinleft_array = array();
|
||||
$where_array = array();
|
||||
$final_from = array();
|
||||
$from_array[] = $table;
|
||||
$hasLeft = false;
|
||||
$hasInner = false;
|
||||
|
||||
$query = "UPDATE " . $this->obj['sql_tbl_prefix'] . $table . " SET " . $dba;
|
||||
if ( $where )
|
||||
{
|
||||
$where_array[] = $where;
|
||||
}
|
||||
|
||||
if ( $where )
|
||||
{
|
||||
$query .= " WHERE " . $where;
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
// Loop through JOINs and sort info
|
||||
//-----------------------------------------
|
||||
|
||||
if ( is_array( $add_join ) and count( $add_join ) )
|
||||
{
|
||||
foreach( $add_join as $join )
|
||||
{
|
||||
if ( ! is_array( $join ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( empty($join['type']) OR $join['type'] == 'left' )
|
||||
{
|
||||
$hasLeft = true;
|
||||
# Join is left or not specified (assume left)
|
||||
$tmp = " LEFT JOIN ";
|
||||
|
||||
foreach( $join['from'] as $tbl => $alias )
|
||||
{
|
||||
$tmp .= $this->obj['sql_tbl_prefix'].$tbl.' '.$alias;
|
||||
}
|
||||
|
||||
if ( $join['where'] )
|
||||
{
|
||||
$tmp .= " ON ( ".$join['where']." ) ";
|
||||
}
|
||||
|
||||
$joinleft_array[] = $tmp;
|
||||
|
||||
unset( $tmp );
|
||||
}
|
||||
else if ( $join['type'] == 'inner' )
|
||||
{
|
||||
$hasInner = true;
|
||||
|
||||
# Join is inline
|
||||
$from_array[] = $join['from'];
|
||||
|
||||
if ( $join['where'] )
|
||||
{
|
||||
$where_array[] = $join['where'];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
# Not using any other type of join
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
// Build it..
|
||||
//-----------------------------------------
|
||||
|
||||
foreach( $from_array as $i )
|
||||
{
|
||||
foreach( $i as $tbl => $alias )
|
||||
{
|
||||
$final_from[] = $this->obj['sql_tbl_prefix'] . $tbl . ' ' . $alias;
|
||||
}
|
||||
}
|
||||
|
||||
#http://bugs.mysql.com/bug.php?id=37925
|
||||
$table = ( $hasLeft === true && $hasInner === true ) ? '(' . implode( ",", $final_from ) . ')' : implode( ",", $final_from );
|
||||
$where = implode( " AND " , $where_array );
|
||||
$join = implode( "\n" , $joinleft_array );
|
||||
|
||||
$query = "UPDATE {$table}";
|
||||
|
||||
if ( $join )
|
||||
{
|
||||
$query .= " " . $join . " ";
|
||||
}
|
||||
|
||||
$query .= "SET " . ( $preformatted ? $set : $this->compileUpdateString( $set ) );
|
||||
|
||||
if ( $where != "" )
|
||||
{
|
||||
$query .= " WHERE " . $where;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
// Run
|
||||
//-----------------------------------------
|
||||
|
||||
return $this->_determineShutdownAndRun( $query, $shutdown );
|
||||
}
|
||||
|
||||
@@ -1021,11 +1142,17 @@ abstract class db_main_mysql extends dbMain
|
||||
* @param string [Optional] Where clause
|
||||
* @param array [Optional] Joined table data
|
||||
* @param boolean Calculate total rows too
|
||||
* @param array [Optional] Force index
|
||||
* @return @e void
|
||||
*/
|
||||
protected function _buildSelect( $get, $table, $where, $add_join=array(), $calcRows=FALSE )
|
||||
protected function _buildSelect( $get, $table, $where, $add_join=array(), $calcRows=FALSE, $forceIndex=array() )
|
||||
{
|
||||
$_calcRows = ( $calcRows === TRUE ) ? 'SQL_CALC_FOUND_ROWS ' : '';
|
||||
|
||||
if ( !empty( $forceIndex ) )
|
||||
{
|
||||
$table .= ' FORCE INDEX('. implode( ',', array_map( create_function( '$v', 'return $v == \'PRIMARY\' ? $v : "'.$this->fieldNameEncapsulate.'{$v}'.$this->fieldNameEncapsulate.'";' ), $forceIndex ) ) .')';
|
||||
}
|
||||
|
||||
if( !count($add_join) )
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,436 +1,436 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* Compare and highlight differences between two strings or files
|
||||
* Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/company/standards.php#license
|
||||
* @package IP.Board
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since Thursday 10th February 2005 (10:47)
|
||||
* @version $Revision: 10914 $
|
||||
*/
|
||||
|
||||
if ( ! defined( 'IPS_CLASSES_PATH' ) )
|
||||
{
|
||||
/**
|
||||
* Define classes path
|
||||
*/
|
||||
define( 'IPS_CLASSES_PATH', dirname(__FILE__) );
|
||||
}
|
||||
|
||||
class classDifference
|
||||
{
|
||||
/**
|
||||
* Shell command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $diff_command = 'diff';
|
||||
|
||||
/**
|
||||
* Type of diff to use
|
||||
*
|
||||
* @var string [EXEC, PHP]
|
||||
*/
|
||||
public $method = 'EXEC';
|
||||
|
||||
/**
|
||||
* Differences found?
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $diff_found = 0;
|
||||
|
||||
/**
|
||||
* Post process DIFF result?
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $post_process = 1;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @return @e void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//-------------------------------
|
||||
// Server?
|
||||
//-------------------------------
|
||||
|
||||
if( strpos( strtolower( PHP_OS ), 'win' ) === 0 OR ( ! function_exists('exec') ) )
|
||||
{
|
||||
$this->method = 'PHP';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a text string showing the differences between the two supplied strings
|
||||
*
|
||||
* @param string Original string
|
||||
* @param string New string
|
||||
* @param string Inline or unified report (only supported by PHP method)
|
||||
* @return @e string
|
||||
*/
|
||||
public function getDifferences( $str1, $str2, $method='inline' )
|
||||
{
|
||||
$this->diff_found = 0;
|
||||
|
||||
if ( $this->method != 'PHP' )
|
||||
{
|
||||
$str1 = $this->_diffTagSpace($str1);
|
||||
$str2 = $this->_diffTagSpace($str2);
|
||||
$str1_lines = $this->_diffExplodeStringIntoWords($str1);
|
||||
$str2_lines = $this->_diffExplodeStringIntoWords($str2);
|
||||
}
|
||||
|
||||
if ( $this->method == 'PHP' )
|
||||
{
|
||||
$diff_res = $this->_getPhpDiff( $str1, $str2, $method );
|
||||
}
|
||||
else
|
||||
{
|
||||
$diff_res = $this->_getExecDiff( implode( chr(10), $str1_lines ) . chr(10), implode( chr(10), $str2_lines ) . chr(10) );
|
||||
}
|
||||
|
||||
//-------------------------------
|
||||
// Post process?
|
||||
//-------------------------------
|
||||
|
||||
if ( $this->post_process )
|
||||
{
|
||||
if ( is_array($diff_res) )
|
||||
{
|
||||
reset($diff_res);
|
||||
$c = 0;
|
||||
$diff_res_array = array();
|
||||
|
||||
foreach( $diff_res as $l_val )
|
||||
{
|
||||
if ( intval($l_val) )
|
||||
{
|
||||
$c = intval($l_val);
|
||||
$diff_res_array[$c]['changeInfo'] = $l_val;
|
||||
}
|
||||
|
||||
if (substr($l_val,0,1) == '<')
|
||||
{
|
||||
$diff_res_array[$c]['old'][] = substr($l_val,2);
|
||||
}
|
||||
|
||||
if (substr($l_val,0,1) == '>')
|
||||
{
|
||||
$diff_res_array[$c]['new'][] = substr($l_val,2);
|
||||
}
|
||||
}
|
||||
|
||||
$out_str = '';
|
||||
$clr_buffer = '';
|
||||
|
||||
for ( $a = -1; $a < count($str1_lines); $a++ )
|
||||
{
|
||||
if ( is_array( $diff_res_array[$a+1] ) )
|
||||
{
|
||||
if ( strstr( $diff_res_array[$a+1]['changeInfo'], 'a') )
|
||||
{
|
||||
$this->diff_found = 1;
|
||||
$clr_buffer .= htmlspecialchars($str1_lines[$a]).' ';
|
||||
}
|
||||
|
||||
$out_str .= $clr_buffer;
|
||||
$clr_buffer = '';
|
||||
|
||||
if (is_array($diff_res_array[$a+1]['old']))
|
||||
{
|
||||
$this->diff_found = 1;
|
||||
$out_str.='<del style="-ips-match:1">'.htmlspecialchars(implode(' ',$diff_res_array[$a+1]['old'])).'</del> ';
|
||||
}
|
||||
|
||||
if (is_array($diff_res_array[$a+1]['new']))
|
||||
{
|
||||
$this->diff_found = 1;
|
||||
$out_str.='<ins style="-ips-match:1">'.htmlspecialchars(implode(' ',$diff_res_array[$a+1]['new'])).'</ins> ';
|
||||
}
|
||||
|
||||
$cip = explode(',',$diff_res_array[$a+1]['changeInfo']);
|
||||
|
||||
if ( ! strcmp( $cip[0], $a + 1 ) )
|
||||
{
|
||||
$new_line = intval($cip[1])-1;
|
||||
|
||||
if ( $new_line > $a )
|
||||
{
|
||||
$a = $new_line;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$clr_buffer .= htmlspecialchars($str1_lines[$a]).' ';
|
||||
}
|
||||
}
|
||||
|
||||
$out_str .= $clr_buffer;
|
||||
|
||||
$out_str = str_replace(' ',chr(10),$out_str);
|
||||
|
||||
$out_str = $this->_diffTagSpace($out_str,1);
|
||||
|
||||
return $out_str;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return $diff_res;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds space character after HTML tags
|
||||
*
|
||||
* @param string String
|
||||
* @param integer [Optional][0=reverse, 1=normal]
|
||||
* @return @e string
|
||||
*/
|
||||
protected function _diffTagSpace( $str, $rev=0 )
|
||||
{
|
||||
if ( $rev )
|
||||
{
|
||||
return str_replace(' <','<',str_replace('> ','>',$str) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return str_replace('<',' <',str_replace('>','> ',$str) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Explodes input string into words
|
||||
*
|
||||
* @access protected
|
||||
* @param string Input string
|
||||
* @return @e array
|
||||
*/
|
||||
protected function _diffExplodeStringIntoWords( $str )
|
||||
{
|
||||
$str_array = $this->_explodeTrim( chr(10), $str );
|
||||
$out_array = array();
|
||||
|
||||
reset($str_array);
|
||||
|
||||
foreach( $str_array as $low )
|
||||
{
|
||||
$all_words = $this->_explodeTrim( ' ', $low, 1 );
|
||||
$out_array = array_merge($out_array, $all_words);
|
||||
$out_array[] = '';
|
||||
$out_array[] = '';
|
||||
}
|
||||
|
||||
return $out_array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Explode into array and trim
|
||||
*
|
||||
* @param string Delimiter
|
||||
* @param string String to check
|
||||
* @param integer [Optional] Remove blank lines
|
||||
* @return @e array
|
||||
*/
|
||||
protected function _explodeTrim( $delim, $str, $remove_blank=0 )
|
||||
{
|
||||
$tmp = explode( $delim, trim($str) );
|
||||
$final = array();
|
||||
|
||||
foreach( $tmp as $i )
|
||||
{
|
||||
if ( $remove_blank AND ( $i === '' OR $i === NULL ) ) //!$i AND $i !== 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
$final[] = trim($i);
|
||||
}
|
||||
}
|
||||
|
||||
return $final;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce differences using PHP
|
||||
*
|
||||
* @param string comapre string 1
|
||||
* @param string comapre string 2
|
||||
* @return @e string
|
||||
*/
|
||||
protected function _getPhpDiff( $str1 , $str2, $method='inline' )
|
||||
{
|
||||
$str1 = explode( "\n", str_replace( "\r\n", "\n", $str1 ) );
|
||||
$str2 = explode( "\n", str_replace( "\r\n", "\n", $str2 ) );
|
||||
|
||||
/* Set include path.. */
|
||||
@set_include_path( IPS_KERNEL_PATH . 'PEAR/' );/*noLibHook*/
|
||||
|
||||
/* OMG.. too many PHP 5 errors under strict standards */
|
||||
$oldReportLevel = error_reporting( 0 );
|
||||
error_reporting( $oldReportLevel ^ E_STRICT );
|
||||
|
||||
require_once 'Text/Diff.php';/*noLibHook*/
|
||||
require_once 'Text/Diff/Renderer.php';/*noLibHook*/
|
||||
|
||||
$diff = new Text_Diff( 'auto', array( $str1, $str2 ) );
|
||||
|
||||
if ( $method == 'inline' )
|
||||
{
|
||||
require_once 'Text/Diff/Renderer/inline.php';/*noLibHook*/
|
||||
$renderer = new Text_Diff_Renderer_inline();
|
||||
}
|
||||
else
|
||||
{
|
||||
require_once 'Text/Diff/Renderer/unified.php';/*noLibHook*/
|
||||
$renderer = new Text_Diff_Renderer_unified();
|
||||
$renderer->_leading_context_lines = 10000;
|
||||
$renderer->_trailing_context_lines = 10000;
|
||||
}
|
||||
|
||||
$result = $renderer->render($diff);
|
||||
|
||||
/* Go back to old reporting level */
|
||||
error_reporting( $oldReportLevel | E_STRICT );
|
||||
|
||||
$result = str_replace( "<ins>", '<ins style="-ips-match:1">', $result );
|
||||
$result = str_replace( "<del>", '<del style="-ips-match:1">', $result );
|
||||
|
||||
# Got a match?
|
||||
if ( strstr( $result, 'style="-ips-match:1"' ) )
|
||||
{
|
||||
$this->diff_found = 1;
|
||||
}
|
||||
|
||||
# No post processing please
|
||||
$this->post_process = 0;
|
||||
|
||||
# Convert lines to a space, and two spaces to a single line
|
||||
//$result = str_replace(' ', chr(10), str_replace( "\n", " ", $result ) );
|
||||
//$result = $this->_diffTagSpace($result,1);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce differences using unix diff
|
||||
*
|
||||
* @param string comapre string 1
|
||||
* @param string comapre string 2
|
||||
* @return @e string
|
||||
*/
|
||||
protected function _getExecDiff( $str1, $str2 )
|
||||
{
|
||||
//-------------------------------
|
||||
// Write the tmp files
|
||||
//-------------------------------
|
||||
|
||||
$file1 = IPS_ROOT_PATH . 'uploads/'.time().'-1';
|
||||
$file2 = IPS_ROOT_PATH . 'uploads/'.time().'-2';
|
||||
|
||||
if ( $FH1 = @fopen( $file1, 'w' ) )
|
||||
{
|
||||
@fwrite( $FH1, $str1, strlen($str1) );
|
||||
@fclose( $FH1 );
|
||||
}
|
||||
|
||||
if ( $FH2 = @fopen( $file2, 'w' ) )
|
||||
{
|
||||
@fwrite( $FH2, $str2, strlen($str2) );
|
||||
@fclose( $FH2 );
|
||||
}
|
||||
|
||||
//-------------------------------
|
||||
// Check
|
||||
//-------------------------------
|
||||
|
||||
if ( is_file( $file1 ) and is_file( $file2 ) )
|
||||
{
|
||||
exec( $this->diff_command.' '.$file1.' '.$file2, $result );
|
||||
|
||||
@unlink( $file1 );
|
||||
@unlink( $file2 );
|
||||
|
||||
return $result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Error, files not written to disk";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format differences for output (common)
|
||||
*
|
||||
* @param string Differences report
|
||||
* @param string Format method (inline|unified)
|
||||
* @param bool Wrap in pre tags (true) or nl2br for output (false)
|
||||
* @return @e string
|
||||
*/
|
||||
public function formatDifferenceReport( $result, $method='inline', $pre=true )
|
||||
{
|
||||
if( $result )
|
||||
{
|
||||
if( $method == 'unified' )
|
||||
{
|
||||
$result = str_replace( array( "\r\n", "\r" ), "\n", $result );
|
||||
$result = preg_replace( '#(^|\n)(\-|\+)([^\n]+?)\n#', "\n\\1\\2\\3\n\n", $result );
|
||||
$result = htmlspecialchars( $result );
|
||||
$result = preg_replace( '#^@@([^@]+?)@@#m', '', $result );
|
||||
$result = preg_replace( '#(^|\n)\-([^\n]+?)\n#', "\\1<del>\\2</del>\n", $result );
|
||||
$result = preg_replace( '#(^|\n)\+([^\n]+?)\n#', "\\1<ins>\\2</ins>\n", $result );
|
||||
$result = str_replace( "</ins>\n\n", "</ins>\n", $result );
|
||||
$result = str_replace( "</del>\n", '</del>', $result );
|
||||
$result = str_replace( "\n\n<ins>", "\n<ins>", $result );
|
||||
$result = str_replace( "\n\n<del>", "\n<del>", $result );
|
||||
$result = str_replace( "\n+\n", "\n\n", $result );
|
||||
$result = str_replace( "\n-\n", "\n\n", $result );
|
||||
|
||||
if( $pre )
|
||||
{
|
||||
$result = '<pre>' . $result . '</pre>';
|
||||
}
|
||||
else
|
||||
{
|
||||
$result = str_replace( "\t", " ", $result );
|
||||
$result = str_replace( ' ', ' ', $result );
|
||||
$result = nl2br( $result );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$result = str_replace( "\n", "<br>", $result );
|
||||
$result = str_replace( "><", ">\n<", $result );
|
||||
$result = preg_replace( "#(?<!(\<del|\<ins)) {1}(?!:style)#i", " ", $result );
|
||||
|
||||
if( $pre )
|
||||
{
|
||||
$result = '<pre>' . $result . '</pre>';
|
||||
}
|
||||
else
|
||||
{
|
||||
$result = str_replace( "\t", " ", $result );
|
||||
$result = str_replace( ' ', ' ', $result );
|
||||
$result = nl2br( $result );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
<?php
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.4.5
|
||||
* Compare and highlight differences between two strings or files
|
||||
* Last Updated: $Date: 2012-05-10 16:10:13 -0400 (Thu, 10 May 2012) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/company/standards.php#license
|
||||
* @package IP.Board
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since Thursday 10th February 2005 (10:47)
|
||||
* @version $Revision: 10721 $
|
||||
*/
|
||||
|
||||
if ( ! defined( 'IPS_CLASSES_PATH' ) )
|
||||
{
|
||||
/**
|
||||
* Define classes path
|
||||
*/
|
||||
define( 'IPS_CLASSES_PATH', dirname(__FILE__) );
|
||||
}
|
||||
|
||||
class classDifference
|
||||
{
|
||||
/**
|
||||
* Shell command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $diff_command = 'diff';
|
||||
|
||||
/**
|
||||
* Type of diff to use
|
||||
*
|
||||
* @var string [EXEC, PHP]
|
||||
*/
|
||||
public $method = 'EXEC';
|
||||
|
||||
/**
|
||||
* Differences found?
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $diff_found = 0;
|
||||
|
||||
/**
|
||||
* Post process DIFF result?
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $post_process = 1;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @return @e void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//-------------------------------
|
||||
// Server?
|
||||
//-------------------------------
|
||||
|
||||
if( strpos( strtolower( PHP_OS ), 'win' ) === 0 OR ( ! function_exists('exec') ) )
|
||||
{
|
||||
$this->method = 'PHP';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a text string showing the differences between the two supplied strings
|
||||
*
|
||||
* @param string Original string
|
||||
* @param string New string
|
||||
* @param string Inline or unified report (only supported by PHP method)
|
||||
* @return @e string
|
||||
*/
|
||||
public function getDifferences( $str1, $str2, $method='inline' )
|
||||
{
|
||||
$this->diff_found = 0;
|
||||
|
||||
if ( $this->method != 'PHP' )
|
||||
{
|
||||
$str1 = $this->_diffTagSpace($str1);
|
||||
$str2 = $this->_diffTagSpace($str2);
|
||||
$str1_lines = $this->_diffExplodeStringIntoWords($str1);
|
||||
$str2_lines = $this->_diffExplodeStringIntoWords($str2);
|
||||
}
|
||||
|
||||
if ( $this->method == 'PHP' )
|
||||
{
|
||||
$diff_res = $this->_getPhpDiff( $str1, $str2, $method );
|
||||
}
|
||||
else
|
||||
{
|
||||
$diff_res = $this->_getExecDiff( implode( chr(10), $str1_lines ) . chr(10), implode( chr(10), $str2_lines ) . chr(10) );
|
||||
}
|
||||
|
||||
//-------------------------------
|
||||
// Post process?
|
||||
//-------------------------------
|
||||
|
||||
if ( $this->post_process )
|
||||
{
|
||||
if ( is_array($diff_res) )
|
||||
{
|
||||
reset($diff_res);
|
||||
$c = 0;
|
||||
$diff_res_array = array();
|
||||
|
||||
foreach( $diff_res as $l_val )
|
||||
{
|
||||
if ( intval($l_val) )
|
||||
{
|
||||
$c = intval($l_val);
|
||||
$diff_res_array[$c]['changeInfo'] = $l_val;
|
||||
}
|
||||
|
||||
if (substr($l_val,0,1) == '<')
|
||||
{
|
||||
$diff_res_array[$c]['old'][] = substr($l_val,2);
|
||||
}
|
||||
|
||||
if (substr($l_val,0,1) == '>')
|
||||
{
|
||||
$diff_res_array[$c]['new'][] = substr($l_val,2);
|
||||
}
|
||||
}
|
||||
|
||||
$out_str = '';
|
||||
$clr_buffer = '';
|
||||
|
||||
for ( $a = -1; $a < count($str1_lines); $a++ )
|
||||
{
|
||||
if ( is_array( $diff_res_array[$a+1] ) )
|
||||
{
|
||||
if ( strstr( $diff_res_array[$a+1]['changeInfo'], 'a') )
|
||||
{
|
||||
$this->diff_found = 1;
|
||||
$clr_buffer .= htmlspecialchars($str1_lines[$a]).' ';
|
||||
}
|
||||
|
||||
$out_str .= $clr_buffer;
|
||||
$clr_buffer = '';
|
||||
|
||||
if (is_array($diff_res_array[$a+1]['old']))
|
||||
{
|
||||
$this->diff_found = 1;
|
||||
$out_str.='<del style="-ips-match:1">'.htmlspecialchars(implode(' ',$diff_res_array[$a+1]['old'])).'</del> ';
|
||||
}
|
||||
|
||||
if (is_array($diff_res_array[$a+1]['new']))
|
||||
{
|
||||
$this->diff_found = 1;
|
||||
$out_str.='<ins style="-ips-match:1">'.htmlspecialchars(implode(' ',$diff_res_array[$a+1]['new'])).'</ins> ';
|
||||
}
|
||||
|
||||
$cip = explode(',',$diff_res_array[$a+1]['changeInfo']);
|
||||
|
||||
if ( ! strcmp( $cip[0], $a + 1 ) )
|
||||
{
|
||||
$new_line = intval($cip[1])-1;
|
||||
|
||||
if ( $new_line > $a )
|
||||
{
|
||||
$a = $new_line;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$clr_buffer .= htmlspecialchars($str1_lines[$a]).' ';
|
||||
}
|
||||
}
|
||||
|
||||
$out_str .= $clr_buffer;
|
||||
|
||||
$out_str = str_replace(' ',chr(10),$out_str);
|
||||
|
||||
$out_str = $this->_diffTagSpace($out_str,1);
|
||||
|
||||
return $out_str;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return $diff_res;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds space character after HTML tags
|
||||
*
|
||||
* @param string String
|
||||
* @param integer [Optional][0=reverse, 1=normal]
|
||||
* @return @e string
|
||||
*/
|
||||
protected function _diffTagSpace( $str, $rev=0 )
|
||||
{
|
||||
if ( $rev )
|
||||
{
|
||||
return str_replace(' <','<',str_replace('> ','>',$str) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return str_replace('<',' <',str_replace('>','> ',$str) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Explodes input string into words
|
||||
*
|
||||
* @access protected
|
||||
* @param string Input string
|
||||
* @return @e array
|
||||
*/
|
||||
protected function _diffExplodeStringIntoWords( $str )
|
||||
{
|
||||
$str_array = $this->_explodeTrim( chr(10), $str );
|
||||
$out_array = array();
|
||||
|
||||
reset($str_array);
|
||||
|
||||
foreach( $str_array as $low )
|
||||
{
|
||||
$all_words = $this->_explodeTrim( ' ', $low, 1 );
|
||||
$out_array = array_merge($out_array, $all_words);
|
||||
$out_array[] = '';
|
||||
$out_array[] = '';
|
||||
}
|
||||
|
||||
return $out_array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Explode into array and trim
|
||||
*
|
||||
* @param string Delimiter
|
||||
* @param string String to check
|
||||
* @param integer [Optional] Remove blank lines
|
||||
* @return @e array
|
||||
*/
|
||||
protected function _explodeTrim( $delim, $str, $remove_blank=0 )
|
||||
{
|
||||
$tmp = explode( $delim, trim($str) );
|
||||
$final = array();
|
||||
|
||||
foreach( $tmp as $i )
|
||||
{
|
||||
if ( $remove_blank AND ( $i === '' OR $i === NULL ) ) //!$i AND $i !== 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
$final[] = trim($i);
|
||||
}
|
||||
}
|
||||
|
||||
return $final;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce differences using PHP
|
||||
*
|
||||
* @param string comapre string 1
|
||||
* @param string comapre string 2
|
||||
* @return @e string
|
||||
*/
|
||||
protected function _getPhpDiff( $str1 , $str2, $method='inline' )
|
||||
{
|
||||
$str1 = explode( "\n", str_replace( "\r\n", "\n", $str1 ) );
|
||||
$str2 = explode( "\n", str_replace( "\r\n", "\n", $str2 ) );
|
||||
|
||||
/* Set include path.. */
|
||||
@set_include_path( IPS_KERNEL_PATH . 'PEAR/' );/*noLibHook*/
|
||||
|
||||
/* OMG.. too many PHP 5 errors under strict standards */
|
||||
$oldReportLevel = error_reporting( 0 );
|
||||
error_reporting( $oldReportLevel ^ E_STRICT );
|
||||
|
||||
require_once 'Text/Diff.php';/*noLibHook*/
|
||||
require_once 'Text/Diff/Renderer.php';/*noLibHook*/
|
||||
|
||||
$diff = new Text_Diff( 'auto', array( $str1, $str2 ) );
|
||||
|
||||
if ( $method == 'inline' )
|
||||
{
|
||||
require_once 'Text/Diff/Renderer/inline.php';/*noLibHook*/
|
||||
$renderer = new Text_Diff_Renderer_inline();
|
||||
}
|
||||
else
|
||||
{
|
||||
require_once 'Text/Diff/Renderer/unified.php';/*noLibHook*/
|
||||
$renderer = new Text_Diff_Renderer_unified();
|
||||
$renderer->_leading_context_lines = 10000;
|
||||
$renderer->_trailing_context_lines = 10000;
|
||||
}
|
||||
|
||||
$result = $renderer->render($diff);
|
||||
|
||||
/* Go back to old reporting level */
|
||||
error_reporting( $oldReportLevel | E_STRICT );
|
||||
|
||||
$result = str_replace( "<ins>", '<ins style="-ips-match:1">', $result );
|
||||
$result = str_replace( "<del>", '<del style="-ips-match:1">', $result );
|
||||
|
||||
# Got a match?
|
||||
if ( strstr( $result, 'style="-ips-match:1"' ) )
|
||||
{
|
||||
$this->diff_found = 1;
|
||||
}
|
||||
|
||||
# No post processing please
|
||||
$this->post_process = 0;
|
||||
|
||||
# Convert lines to a space, and two spaces to a single line
|
||||
//$result = str_replace(' ', chr(10), str_replace( "\n", " ", $result ) );
|
||||
//$result = $this->_diffTagSpace($result,1);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce differences using unix diff
|
||||
*
|
||||
* @param string comapre string 1
|
||||
* @param string comapre string 2
|
||||
* @return @e string
|
||||
*/
|
||||
protected function _getExecDiff( $str1, $str2 )
|
||||
{
|
||||
//-------------------------------
|
||||
// Write the tmp files
|
||||
//-------------------------------
|
||||
|
||||
$file1 = IPS_ROOT_PATH . 'uploads/'.time().'-1';
|
||||
$file2 = IPS_ROOT_PATH . 'uploads/'.time().'-2';
|
||||
|
||||
if ( $FH1 = @fopen( $file1, 'w' ) )
|
||||
{
|
||||
@fwrite( $FH1, $str1, strlen($str1) );
|
||||
@fclose( $FH1 );
|
||||
}
|
||||
|
||||
if ( $FH2 = @fopen( $file2, 'w' ) )
|
||||
{
|
||||
@fwrite( $FH2, $str2, strlen($str2) );
|
||||
@fclose( $FH2 );
|
||||
}
|
||||
|
||||
//-------------------------------
|
||||
// Check
|
||||
//-------------------------------
|
||||
|
||||
if ( is_file( $file1 ) and is_file( $file2 ) )
|
||||
{
|
||||
exec( $this->diff_command.' '.$file1.' '.$file2, $result );
|
||||
|
||||
@unlink( $file1 );
|
||||
@unlink( $file2 );
|
||||
|
||||
return $result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Ошибка, файлы не были записаны на диск";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format differences for output (common)
|
||||
*
|
||||
* @param string Differences report
|
||||
* @param string Format method (inline|unified)
|
||||
* @param bool Wrap in pre tags (true) or nl2br for output (false)
|
||||
* @return @e string
|
||||
*/
|
||||
public function formatDifferenceReport( $result, $method='inline', $pre=true )
|
||||
{
|
||||
if( $result )
|
||||
{
|
||||
if( $method == 'unified' )
|
||||
{
|
||||
$result = str_replace( array( "\r\n", "\r" ), "\n", $result );
|
||||
$result = preg_replace( '#(^|\n)(\-|\+)([^\n]+?)\n#', "\n\\1\\2\\3\n\n", $result );
|
||||
$result = htmlspecialchars( $result );
|
||||
$result = preg_replace( '#^@@([^@]+?)@@#m', '', $result );
|
||||
$result = preg_replace( '#(^|\n)\-([^\n]+?)\n#', "\\1<del>\\2</del>\n", $result );
|
||||
$result = preg_replace( '#(^|\n)\+([^\n]+?)\n#', "\\1<ins>\\2</ins>\n", $result );
|
||||
$result = str_replace( "</ins>\n\n", "</ins>\n", $result );
|
||||
$result = str_replace( "</del>\n", '</del>', $result );
|
||||
$result = str_replace( "\n\n<ins>", "\n<ins>", $result );
|
||||
$result = str_replace( "\n\n<del>", "\n<del>", $result );
|
||||
$result = str_replace( "\n+\n", "\n\n", $result );
|
||||
$result = str_replace( "\n-\n", "\n\n", $result );
|
||||
|
||||
if( $pre )
|
||||
{
|
||||
$result = '<pre>' . $result . '</pre>';
|
||||
}
|
||||
else
|
||||
{
|
||||
$result = str_replace( "\t", " ", $result );
|
||||
$result = str_replace( ' ', ' ', $result );
|
||||
$result = nl2br( $result );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$result = str_replace( "\n", "<br>", $result );
|
||||
$result = str_replace( "><", ">\n<", $result );
|
||||
$result = preg_replace( "#(?<!(\<del|\<ins)) {1}(?!:style)#i", " ", $result );
|
||||
|
||||
if( $pre )
|
||||
{
|
||||
$result = '<pre>' . $result . '</pre>';
|
||||
}
|
||||
else
|
||||
{
|
||||
$result = str_replace( "\t", " ", $result );
|
||||
$result = str_replace( ' ', ' ', $result );
|
||||
$result = nl2br( $result );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
+1371
-1371
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* IP.Board v3.4.5
|
||||
* FTP Class
|
||||
* Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $ BY $Author: bfarber $
|
||||
* Last Updated: $Date: 2013-02-06 10:51:28 -0500 (Wed, 06 Feb 2013) $ BY $Author: mark $
|
||||
* </pre>
|
||||
*
|
||||
* @author Mark Wade
|
||||
@@ -12,7 +12,7 @@
|
||||
* @license http://www.invisionpower.com/company/standards.php#license
|
||||
* @package IP.Board
|
||||
* @link http://www.invisionpower.com
|
||||
* @version $Rev: 10914 $
|
||||
* @version $Rev: 11945 $
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -68,7 +68,7 @@ class classFtp
|
||||
}
|
||||
|
||||
/* Connect */
|
||||
if ( !( $this->stream = ftp_connect( $host, $port, $timeout ) ) )
|
||||
if ( !( $this->stream = @ftp_connect( $host, $port, $timeout ) ) )
|
||||
{
|
||||
throw new Exception( 'CONNECT_FAIL' );
|
||||
}
|
||||
@@ -123,7 +123,13 @@ class classFtp
|
||||
{
|
||||
if ( $dir == '..' )
|
||||
{
|
||||
$currentDir = @ftp_pwd( $this->stream );
|
||||
$chdir = @ftp_cdup( $this->stream );
|
||||
|
||||
if ( $currentDir === @ftp_pwd( $this->stream ) )
|
||||
{
|
||||
$chdir = false;
|
||||
}
|
||||
}
|
||||
elseif ( substr( $dir, 0, 1 ) !== '/' )
|
||||
{
|
||||
@@ -139,7 +145,7 @@ class classFtp
|
||||
{
|
||||
throw new Exception( 'CHDIR_FAILED' );
|
||||
}
|
||||
$this->directory = $dir;
|
||||
$this->directory = @ftp_pwd( $this->stream );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3082
-3082
File diff suppressed because it is too large.
Load diff
@@ -3,9 +3,9 @@
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* IP.Board v3.4.5
|
||||
* Image Handler: create thumbnails, apply watermarks and copyright tests, save or display final image
|
||||
* Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $
|
||||
* Last Updated: $Date: 2012-05-10 16:10:13 -0400 (Thu, 10 May 2012) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
@@ -15,7 +15,7 @@
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since Monday 5th May 2008 14:00
|
||||
* @version $Revision: 10914 $
|
||||
* @version $Revision: 10721 $
|
||||
*
|
||||
* GD Example
|
||||
* <code>
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* IP.Board v3.4.5
|
||||
* Image Handler: GD2 Library
|
||||
* Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $
|
||||
* Last Updated: $Date: 2013-02-06 19:48:42 -0500 (Wed, 06 Feb 2013) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
@@ -15,7 +15,7 @@
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since Monday 5th May 2008 14:00
|
||||
* @version $Revision: 10914 $
|
||||
* @version $Revision: 11951 $
|
||||
*
|
||||
* GD Example
|
||||
* <code>
|
||||
@@ -251,9 +251,9 @@ class classImageGd extends classImage implements interfaceImage
|
||||
*/
|
||||
public function resizeImage( $width, $height, $secondPass=false, $returnIfUnnecessary=false, $canvas=array() )
|
||||
{
|
||||
//---------------------------------------------------------
|
||||
// Get proportionate dimensions and store
|
||||
//---------------------------------------------------------
|
||||
//---------------------------------------------------------
|
||||
// Get proportionate dimensions and store
|
||||
//---------------------------------------------------------
|
||||
|
||||
$dst_x = 0;
|
||||
$dst_y = 0;
|
||||
@@ -261,12 +261,22 @@ class classImageGd extends classImage implements interfaceImage
|
||||
if ( ! $secondPass )
|
||||
{
|
||||
$new_dims = $this->_getResizeDimensions( $width, $height );
|
||||
|
||||
if( !$new_dims['img_width'] )
|
||||
{
|
||||
$new_dims = array(
|
||||
'img_width' => $this->cur_dimensions['width'],
|
||||
'img_height' => $this->cur_dimensions['height'],
|
||||
'cur_width' => $this->cur_dimensions['width'],
|
||||
'cur_height' => $this->cur_dimensions['height'],
|
||||
);
|
||||
}
|
||||
|
||||
/* Canvas? */
|
||||
if ( is_array( $canvas ) && count( $canvas ) )
|
||||
{
|
||||
$storedNewDims = $new_dims;
|
||||
$new_dims = array( 'img_width' => $canvas[0], 'img_height' => $canvas[1] );
|
||||
$new_dims = array( 'img_width' => $canvas[0], 'img_height' => $canvas[1], 'cur_width' => $new_dims['cur_width'] ? $new_dims['cur_width'] : $this->cur_dimensions['width'], 'cur_height' => $new_dims['cur_height'] ? $new_dims['cur_height'] : $this->cur_dimensions['height'] );
|
||||
|
||||
if ( $storedNewDims['img_width'] < $canvas[0] )
|
||||
{
|
||||
@@ -284,7 +294,26 @@ class classImageGd extends classImage implements interfaceImage
|
||||
$new_dims['img_width'] = $width;
|
||||
$new_dims['img_height'] = $height;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------
|
||||
// If new image is same size as original, just return original
|
||||
// This preserves GIF animation and allows images not to be "compressed" unnecessarily
|
||||
//---------------------------------------------------------
|
||||
|
||||
if ( $returnIfUnnecessary AND ! $this->force_resize )
|
||||
{
|
||||
if ( ( $this->orig_dimensions['width'] <= $width ) AND ( $this->orig_dimensions['height'] <= $height ) )
|
||||
{
|
||||
return array(
|
||||
'originalWidth' => $this->orig_dimensions['width'],
|
||||
'originalHeight' => $this->orig_dimensions['height'],
|
||||
'newWidth' => $this->orig_dimensions['width'],
|
||||
'newHeight' => $this->orig_dimensions['height'],
|
||||
'noResize' => true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if( ! is_array($new_dims) OR !count($new_dims) OR !$new_dims['img_width'] )
|
||||
{
|
||||
if( ! $this->force_resize )
|
||||
@@ -655,7 +684,7 @@ class classImageGd extends classImage implements interfaceImage
|
||||
}
|
||||
else
|
||||
{
|
||||
@imagecopymerge( $this->image, $mark, $locate_x, $locate_y, 0, 0, $img_info[0], $img_info[1], $opacity );
|
||||
@imagecopymerge( $this->image, $mark, $locate_x, $locate_y, 0, 0, $img_info[0], $img_info[1], intval($opacity) );
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* IP.Board v3.4.5
|
||||
* Image Handler: ImageMagick Library
|
||||
* Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $
|
||||
* Last Updated: $Date: 2013-02-20 19:45:47 -0500 (Wed, 20 Feb 2013) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
@@ -15,7 +15,7 @@
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since Monday 5th May 2008 14:00
|
||||
* @version $Revision: 10914 $
|
||||
* @version $Revision: 12007 $
|
||||
*
|
||||
* ImageMagick Example
|
||||
* <code>
|
||||
@@ -318,15 +318,15 @@ class classImageImagemagick extends classImage implements interfaceImage
|
||||
$border = array( 0, 0 );
|
||||
$borderStmt = '';
|
||||
|
||||
/* Figure out border */
|
||||
/* Figure out border - round/str_replace are to ensure locales do not result in "39,5x0" */
|
||||
if ( $new_dims['img_width'] < $width )
|
||||
{
|
||||
$border[0] = ( $width - $new_dims['img_width'] ) / 2;
|
||||
$border[0] = round( str_replace( ',', '.', ( $width - $new_dims['img_width'] ) / 2 ) );
|
||||
}
|
||||
|
||||
if ( $new_dims['img_height'] < $height )
|
||||
{
|
||||
$border[1] = ( $height - $new_dims['img_height'] ) / 2;
|
||||
$border[1] = round( str_replace( ',', '.', ( $height - $new_dims['img_height'] ) / 2 ) );
|
||||
}
|
||||
|
||||
if ( count( $border ) )
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* IP.Board v3.4.5
|
||||
* Three Way Merge Class
|
||||
* Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $ BY $author$
|
||||
* Last Updated: $Date: 2012-05-10 16:10:13 -0400 (Thu, 10 May 2012) $ BY $author$
|
||||
* </pre>
|
||||
*
|
||||
* @author Matt Mecham
|
||||
@@ -12,7 +12,7 @@
|
||||
* @license http://www.invisionpower.com/company/standards.php#license
|
||||
* @package IP.Board
|
||||
* @link http://www.invisionpower.com
|
||||
* @version $Rev: 10914 $
|
||||
* @version $Rev: 10721 $
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+1194
-1122
File diff suppressed because it is too large.
Load diff
@@ -3,9 +3,9 @@
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* IP.Board v3.4.5
|
||||
* Template Parser : Converts HTML "logic" into PHP code
|
||||
* Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $
|
||||
* Last Updated: $Date: 2012-10-18 10:27:08 -0400 (Thu, 18 Oct 2012) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
@@ -15,7 +15,7 @@
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since Wednesday 23rd February 2005 13:53
|
||||
* @version $Revision: 10914 $
|
||||
* @version $Revision: 11481 $
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -174,9 +174,9 @@ class classTemplate
|
||||
//-----------------------------------------
|
||||
|
||||
$this->_skinGroup = preg_replace( '#^(.*)_\d+?$#', "\\1", $full_class_name );
|
||||
|
||||
|
||||
$final_content = $this->_returnFunctionData( $data );
|
||||
|
||||
|
||||
//-----------------------------------------
|
||||
// Function Hooks
|
||||
//------------------------------------------
|
||||
@@ -236,7 +236,7 @@ EOF;
|
||||
// Remove PHP tags
|
||||
//-----------------------------------------
|
||||
|
||||
$data = preg_replace( "#<".'\?php\n+?(.*)\n+?\?>#is', "\\1", $data );
|
||||
$data = preg_replace( "#<".'\?php\n+?(.*)\n+?(\?>|$)#is', "\\1", $data );
|
||||
|
||||
//-----------------------------------------
|
||||
// Pick through and get all function names
|
||||
@@ -1455,7 +1455,7 @@ EOF;
|
||||
//$_false = trim( $_false );
|
||||
|
||||
$php_statement = "{$hook_pre_startif}\" . (($statement) ? (\"{$hook_post_startif}{$_true}{$hook_pre_endif}\") : (\"{$hook_pre_else}{$_false}{$hook_post_else}\")) . \"{$hook_post_endif}";
|
||||
|
||||
|
||||
$template = substr_replace( $template, $php_statement, $found_if, $found_end_if + strlen($tag_end_if) - $found_if);
|
||||
|
||||
$found_end_if = $found_if + strlen($php_statement) - 1;
|
||||
|
||||
@@ -3,19 +3,19 @@
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* IP.Board v3.4.5
|
||||
* Upload handler : Handles $_FILES and checks for security
|
||||
* Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $
|
||||
* Last Updated: $Date: 2013-02-19 06:02:12 -0500 (Tue, 19 Feb 2013) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
* @author $Author: mmecham $
|
||||
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/company/standards.php#license
|
||||
* @package IP.Board
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since 15th March 2004
|
||||
* @version $Revision: 10914 $
|
||||
* @version $Revision: 12001 $
|
||||
*
|
||||
*
|
||||
* Example Usage:
|
||||
@@ -472,7 +472,7 @@ class classUpload
|
||||
return false;
|
||||
}
|
||||
# Thanks to Nicolas Grekas from comments at www.splitbrain.org for helping to identify all vulnerable HTML tags
|
||||
else if( preg_match( '#<script|<html|<head|<title|<body|<pre|<table|<a\s+href|<img|<plaintext|<cross\-domain\-policy#si', $file_check ) )
|
||||
else if( preg_match( '#(<script|<html|<head|<title|<body|<pre|<table|<a\s+href|<img|<plaintext|<cross\-domain\-policy)(\s|=|>)#si', $file_check ) )
|
||||
{
|
||||
@unlink( $this->saved_upload_name );
|
||||
$this->error_no = 5;
|
||||
|
||||
@@ -3,20 +3,20 @@
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* IP.Board v3.4.5
|
||||
* XML Handler: Rewritten for PHP5
|
||||
* By Matt Mecham
|
||||
* Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $
|
||||
* Last Updated: $Date: 2012-07-27 11:43:25 -0400 (Fri, 27 Jul 2012) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
* @author $Author: mark $
|
||||
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/company/standards.php#license
|
||||
* @package IP.Board
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since 25th February 2004
|
||||
* @version $Revision: 10914 $
|
||||
* @version $Revision: 11149 $
|
||||
*
|
||||
*
|
||||
* Example Usage:
|
||||
@@ -225,11 +225,12 @@ class classXML
|
||||
* @param string Name of tag to create
|
||||
* @param string [Name of parent tag (optional)]
|
||||
* @param array [Attributes]
|
||||
* @param string [Namespace URI]
|
||||
* @return @e void
|
||||
*/
|
||||
public function addElement( $tag, $parentTag='', $attributes=array() )
|
||||
public function addElement( $tag, $parentTag='', $attributes=array(), $namespaceUri='' )
|
||||
{
|
||||
$this->_domObjects[ $tag ] = $this->_node( $parentTag )->appendChild( new DOMElement( $tag ) );
|
||||
$this->_domObjects[ $tag ] = $this->_node( $parentTag )->appendChild( new DOMElement( $tag, '', $namespaceUri ) );
|
||||
$this->addAttributes( $tag, $attributes );
|
||||
}
|
||||
|
||||
@@ -243,9 +244,10 @@ class classXML
|
||||
* @param string Name of parent tag
|
||||
* @param mixed Tag wrapper
|
||||
* @param array Array of data to add
|
||||
* @param string [Namespace URI]
|
||||
* @return @e void
|
||||
*/
|
||||
public function addElementAsRecord( $parentTag, $tag, $data )
|
||||
public function addElementAsRecord( $parentTag, $tag, $data, $namespaceUri='' )
|
||||
{
|
||||
/* A little set up if you please... */
|
||||
$_tag = $tag;
|
||||
@@ -257,7 +259,7 @@ class classXML
|
||||
$_tag_attr = $tag[1];
|
||||
}
|
||||
|
||||
$record = $this->_node( $parentTag )->appendChild( new DOMElement( $_tag ) );
|
||||
$record = $this->_node( $parentTag )->appendChild( new DOMElement( $_tag, ( is_array( $data ) ? NULL : $data ), $namespaceUri ) );
|
||||
|
||||
if ( is_array( $_tag_attr ) AND count( $_tag_attr ) )
|
||||
{
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* IP.Board v3.4.5
|
||||
* XML Archive Hanlder: Can create XML Archives (gzips) of multiple files, binary and ascii
|
||||
* Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $
|
||||
* Last Updated: $Date: 2012-05-10 16:10:13 -0400 (Thu, 10 May 2012) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
@@ -15,7 +15,7 @@
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since 25th February 2004
|
||||
* @version $Revision: 10914 $
|
||||
* @version $Revision: 10721 $
|
||||
*
|
||||
*
|
||||
* Example Usage:
|
||||
|
||||
+1054
-1054
File diff suppressed because it is too large.
Load diff
+1481
-1481
File diff suppressed because it is too large.
Load diff
@@ -5,11 +5,11 @@
|
||||
*~TERABYTE_DOC_READY~
|
||||
* $Copyright: (c) 2001 - 2011 Invision Power Services, Inc.$
|
||||
* $License: http://www.invisionpower.com/company/standards.php#license$
|
||||
* $Author: bfarber $
|
||||
* $Author: AndyMillne $
|
||||
* @since Tuesday 1st March 2005 15:40
|
||||
* $LastChangedDate: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $
|
||||
* @version v3.3.4
|
||||
* $Revision: 10914 $
|
||||
* $LastChangedDate: 2013-05-07 11:14:15 -0400 (Tue, 07 May 2013) $
|
||||
* @version v3.4.5
|
||||
* $Revision: 12235 $
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -89,7 +89,7 @@ class db_tools
|
||||
$final_primary = array();
|
||||
|
||||
/* Remove backticks */
|
||||
$definition = str_replace( '`', '', $definition );
|
||||
$definition = $this->_sqlStripTicks( $definition );
|
||||
|
||||
$definition = preg_replace( "#CREATE\s+TABLE\s+IF\s+NOT\s+EXISTS\s+#i", "CREATE TABLE ", $definition );
|
||||
|
||||
@@ -141,7 +141,7 @@ class db_tools
|
||||
// Now find all non-primary keys
|
||||
//-----------------------------------------
|
||||
|
||||
if ( preg_match_all( "#\s+?(UNIQUE KEY|KEY|INDEX|UNIQUE)\s+?(?:(\w+?)\s+?)?\(\s*(.+?)\s*\)(\n|,\n)#is", $definition, $fields ) )
|
||||
if ( preg_match_all( "#\s+?(UNIQUE KEY|KEY|INDEX|UNIQUE)\s+?(?:(\w+?)\s+?)?\(\s*(.+?)\s*\)(?:\s+using (?:btree|hash))?(\n|,\n)#is", $definition, $fields ) )
|
||||
{
|
||||
//-----------------------------------------
|
||||
// We got some fields!
|
||||
@@ -209,8 +209,10 @@ class db_tools
|
||||
// Get table schematics and clean it
|
||||
//-----------------------------------------
|
||||
|
||||
$row = ipsRegistry::DB()->getTableSchematic( $data['table'] );
|
||||
$tbl = $this->_sqlStripTicks( $row['Create Table'] );
|
||||
$row = ipsRegistry::DB()->getTableSchematic( $data['table'] );
|
||||
$tbl = $this->_sqlStripTicks( $row['Create Table'] );
|
||||
|
||||
$tbl = preg_replace( "#(USING BTREE|USING HASH)#i", "", $tbl );
|
||||
|
||||
//-----------------------------------------
|
||||
// Start output (one per index)
|
||||
@@ -357,7 +359,7 @@ class db_tools
|
||||
$ok = 0;
|
||||
|
||||
/* MySql seems to name multi-column indexes by the first field name regardless of what KEY NAME you specify. I know, nice isn't it. */
|
||||
if ( strstr( $index_cols, ',' ) AND ! preg_match( "#\n\s*?(?:UNIQUE KEY|KEY|INDEX|UNIQUE)\s+?{$_checkName}\s+?(\(\s*(.+?)\s*\))(\n|,\n)#is", $tbl, $match ) )
|
||||
if ( strstr( $index_cols, ',' ) AND ! preg_match( "#\n\s*?(?:UNIQUE KEY|KEY|INDEX|UNIQUE)\s+?{$_checkName}\s+?(\(\s*(.+?)\s*\))(?:\s+using (?:btree|hash))?(\s|,\s)#is", $tbl, $match ) )
|
||||
{
|
||||
list( $_checkName, ) = explode( ',', $index_cols );
|
||||
|
||||
@@ -372,7 +374,7 @@ class db_tools
|
||||
// Is the key there?
|
||||
//-----------------------------------------
|
||||
|
||||
if ( preg_match( "#\n\s*?(?:UNIQUE KEY|KEY|INDEX|UNIQUE)\s+?{$_checkName}\s+?(\(\s*(.+?)\s*\))(\n|,\n)#is", $tbl, $match ) )
|
||||
if ( preg_match( "#\n\s*?(?:UNIQUE KEY|KEY|INDEX|UNIQUE)\s+?{$_checkName}\s+?(\(\s*(.+?)\s*\))(?:\s+using (?:btree|hash))?(\s|,\s)#is", $tbl, $match ) )
|
||||
{
|
||||
$ok = 1;
|
||||
|
||||
@@ -524,7 +526,7 @@ class db_tools
|
||||
$missing_columns = array();
|
||||
|
||||
/* Remove backticks */
|
||||
$the_table = str_replace( '`', '', $the_table );
|
||||
$the_table = $this->_sqlStripTicks( $the_table );
|
||||
|
||||
$the_table = preg_replace( "#CREATE\s+TABLE\s+IF\s+NOT\s+EXISTS\s+#i", "CREATE TABLE ", $the_table );
|
||||
|
||||
@@ -780,7 +782,7 @@ class db_tools
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove ticks from statement
|
||||
* Remove ticks and double quotes from statement
|
||||
*
|
||||
* @param string $data String to clean
|
||||
* @return @e string
|
||||
@@ -792,6 +794,9 @@ class db_tools
|
||||
*/
|
||||
protected function _sqlStripTicks( $data )
|
||||
{
|
||||
return str_replace( "`", "", $data );
|
||||
$data = str_replace( '`', '', $data );
|
||||
$data = str_replace( '"', '', $data );
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
require_once "base_facebook.php";/*noLibHook*/
|
||||
require_once( IPS_KERNEL_PATH . 'facebook/base_facebook.php' );/*noLibHook*/
|
||||
|
||||
/**
|
||||
* Extends the BaseFacebook class with the intent of using
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* IP.Board v3.4.5
|
||||
* This class acts as a cache layer, allowing you to store and retrieve data in
|
||||
* external cache sources such as memcache or APC
|
||||
* Last Updated: $Date: 2012-06-12 10:14:49 -0400 (Tue, 12 Jun 2012) $
|
||||
* Last Updated: $Date: 2012-05-10 16:10:13 -0400 (Thu, 10 May 2012) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
@@ -16,7 +16,7 @@
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since Friday 19th May 2006 17:33
|
||||
* @version $Revision: 10914 $
|
||||
* @version $Revision: 10721 $
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ class TwitterOAuth {
|
||||
/* Contains the last API call */
|
||||
public $last_api_call;
|
||||
/* Set up the API root URL */
|
||||
public $host = "https://api.twitter.com/1/";
|
||||
public $host = "https://api.twitter.com/1.1/";
|
||||
/* Set timeout default */
|
||||
public $timeout = 30;
|
||||
/* Set connect timeout */
|
||||
@@ -259,7 +259,7 @@ class TwitterOAuth {
|
||||
$path = "/";
|
||||
}
|
||||
|
||||
$header = "$method {$path} HTTP/1.0\r\n";
|
||||
$header = "$method {$path} HTTP/1.1\r\n";
|
||||
$header .= "User-Agent: Twitter\r\n";
|
||||
$header .= "Host: " . str_replace( array( 'http://', 'https://', 'ssl://' ), '', $host ) . "\r\n";
|
||||
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
|
||||
|
||||
@@ -0,0 +1,799 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The default Cache Lifetime (in seconds).
|
||||
*/
|
||||
define("OAUTH2_DEFAULT_EXPIRES_IN", 3600*60*60*24);
|
||||
|
||||
/**
|
||||
* The default Base domain for the Cookie.
|
||||
*/
|
||||
define("OAUTH2_DEFAULT_BASE_DOMAIN", '');
|
||||
|
||||
/**
|
||||
* OAuth2.0 draft v10 client-side implementation.
|
||||
*
|
||||
* @author Originally written by Naitik Shah <naitik@facebook.com>.
|
||||
* @author Update to draft v10 by Edison Wong <hswong3i@pantarei-design.com>.
|
||||
*
|
||||
* @sa <a href="https://github.com/facebook/php-sdk">Facebook PHP SDK</a>.
|
||||
*/
|
||||
abstract class OAuth2Client {
|
||||
|
||||
/**
|
||||
* Array of persistent variables stored.
|
||||
*/
|
||||
protected $conf = array();
|
||||
|
||||
/**
|
||||
* Returns a persistent variable.
|
||||
*
|
||||
* To avoid problems, always use lower case for persistent variable names.
|
||||
*
|
||||
* @param $name
|
||||
* The name of the variable to return.
|
||||
* @param $default
|
||||
* The default value to use if this variable has never been set.
|
||||
*
|
||||
* @return
|
||||
* The value of the variable.
|
||||
*/
|
||||
public function getVariable($name, $default = NULL) {
|
||||
return isset($this->conf[$name]) ? $this->conf[$name] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a persistent variable.
|
||||
*
|
||||
* To avoid problems, always use lower case for persistent variable names.
|
||||
*
|
||||
* @param $name
|
||||
* The name of the variable to set.
|
||||
* @param $value
|
||||
* The value to set.
|
||||
*/
|
||||
public function setVariable($name, $value) {
|
||||
$this->conf[$name] = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Stuff that should get overridden by subclasses.
|
||||
//
|
||||
// I don't want to make these abstract, because then subclasses would have
|
||||
// to implement all of them, which is too much work.
|
||||
//
|
||||
// So they're just stubs. Override the ones you need.
|
||||
|
||||
/**
|
||||
* Initialize a Drupal OAuth2.0 Application.
|
||||
*
|
||||
* @param $config
|
||||
* An associative array as below:
|
||||
* - base_uri: The base URI for the OAuth2.0 endpoints.
|
||||
* - code: (optional) The authorization code.
|
||||
* - username: (optional) The username.
|
||||
* - password: (optional) The password.
|
||||
* - client_id: (optional) The application ID.
|
||||
* - client_secret: (optional) The application secret.
|
||||
* - authorize_uri: (optional) The end-user authorization endpoint URI.
|
||||
* - access_token_uri: (optional) The token endpoint URI.
|
||||
* - services_uri: (optional) The services endpoint URI.
|
||||
* - cookie_support: (optional) TRUE to enable cookie support.
|
||||
* - base_domain: (optional) The domain for the cookie.
|
||||
* - file_upload_support: (optional) TRUE if file uploads are enabled.
|
||||
*/
|
||||
public function __construct($config = array()) {
|
||||
// We must set base_uri first.
|
||||
$this->setVariable('base_uri', $config['base_uri']);
|
||||
unset($config['base_uri']);
|
||||
|
||||
// Use predefined OAuth2.0 params, or get it from $_REQUEST.
|
||||
foreach (array('code', 'username', 'password') as $name) {
|
||||
if (isset($config[$name]))
|
||||
$this->setVariable($name, $config[$name]);
|
||||
else if (isset($_REQUEST[$name]) && !empty($_REQUEST[$name]))
|
||||
$this->setVariable($name, $_REQUEST[$name]);
|
||||
unset($config[$name]);
|
||||
}
|
||||
|
||||
// Endpoint URIs.
|
||||
foreach (array('authorize_uri', 'access_token_uri', 'services_uri') as $name) {
|
||||
if (isset($config[$name]))
|
||||
if (substr($config[$name], 0, 4) == "http")
|
||||
$this->setVariable($name, $config[$name]);
|
||||
else
|
||||
$this->setVariable($name, $this->getVariable('base_uri') . $config[$name]);
|
||||
unset($config[$name]);
|
||||
}
|
||||
|
||||
// Other else configurations.
|
||||
foreach ($config as $name => $value) {
|
||||
$this->setVariable($name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to get session object from custom method.
|
||||
*
|
||||
* By default we generate session object based on access_token response, or
|
||||
* if it is provided from server with $_REQUEST. For sure, if it is provided
|
||||
* by server it should follow our session object format.
|
||||
*
|
||||
* Session object provided by server can ensure the correct expires and
|
||||
* base_domain setup as predefined in server, also you may get more useful
|
||||
* information for custom functionality, too. BTW, this may require for
|
||||
* additional remote call overhead.
|
||||
*
|
||||
* You may wish to override this function with your custom version due to
|
||||
* your own server-side implementation.
|
||||
*
|
||||
* @param $access_token
|
||||
* (optional) A valid access token in associative array as below:
|
||||
* - access_token: A valid access_token generated by OAuth2.0
|
||||
* authorization endpoint.
|
||||
* - expires_in: (optional) A valid expires_in generated by OAuth2.0
|
||||
* authorization endpoint.
|
||||
* - refresh_token: (optional) A valid refresh_token generated by OAuth2.0
|
||||
* authorization endpoint.
|
||||
* - scope: (optional) A valid scope generated by OAuth2.0
|
||||
* authorization endpoint.
|
||||
*
|
||||
* @return
|
||||
* A valid session object in associative array for setup cookie, and
|
||||
* NULL if not able to generate it with custom method.
|
||||
*/
|
||||
protected function getSessionObject($access_token = NULL) {
|
||||
$session = NULL;
|
||||
|
||||
// Try generate local version of session cookie.
|
||||
if (!empty($access_token) && isset($access_token['access_token'])) {
|
||||
$session['access_token'] = $access_token['access_token'];
|
||||
$session['base_domain'] = $this->getVariable('base_domain', OAUTH2_DEFAULT_BASE_DOMAIN);
|
||||
$session['expires'] = isset($access_token['expires_in']) ? time() + $access_token['expires_in'] : time() + $this->getVariable('expires_in', OAUTH2_DEFAULT_EXPIRES_IN);
|
||||
$session['refresh_token'] = isset($access_token['refresh_token']) ? $access_token['refresh_token'] : '';
|
||||
$session['scope'] = isset($access_token['scope']) ? $access_token['scope'] : '';
|
||||
$session['secret'] = md5(base64_encode(pack('N6', mt_rand(), mt_rand(), mt_rand(), mt_rand(), mt_rand(), uniqid())));
|
||||
|
||||
// Provide our own signature.
|
||||
$sig = self::generateSignature(
|
||||
$session,
|
||||
$this->getVariable('client_secret')
|
||||
);
|
||||
$session['sig'] = $sig;
|
||||
}
|
||||
|
||||
// Try loading session from $_REQUEST.
|
||||
if (!$session && isset($_REQUEST['session'])) {
|
||||
$session = json_decode(
|
||||
get_magic_quotes_gpc()
|
||||
? stripslashes($_REQUEST['session'])
|
||||
: $_REQUEST['session'],
|
||||
TRUE
|
||||
);
|
||||
}
|
||||
|
||||
return $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an API call.
|
||||
*
|
||||
* Support both OAuth2.0 or normal GET/POST API call, with relative
|
||||
* or absolute URI.
|
||||
*
|
||||
* If no valid OAuth2.0 access token found in session object, this function
|
||||
* will automatically switch as normal remote API call without "oauth_token"
|
||||
* parameter.
|
||||
*
|
||||
* Assume server reply in JSON object and always decode during return. If
|
||||
* you hope to issue a raw query, please use makeRequest().
|
||||
*
|
||||
* @param $path
|
||||
* The target path, relative to base_path/service_uri or an absolute URI.
|
||||
* @param $method
|
||||
* (optional) The HTTP method (default 'GET').
|
||||
* @param $params
|
||||
* (optional The GET/POST parameters.
|
||||
*
|
||||
* @return
|
||||
* The JSON decoded response object.
|
||||
*
|
||||
* @throws OAuth2Exception
|
||||
*/
|
||||
public function api($path, $method = 'GET', $params = array()) {
|
||||
if (is_array($method) && empty($params)) {
|
||||
$params = $method;
|
||||
$method = 'GET';
|
||||
}
|
||||
|
||||
// json_encode all params values that are not strings.
|
||||
foreach ($params as $key => $value) {
|
||||
if (!is_string($value)) {
|
||||
$params[$key] = json_encode($value);
|
||||
}
|
||||
}
|
||||
|
||||
$result = json_decode($this->makeOAuth2Request(
|
||||
$this->getUri($path),
|
||||
$method,
|
||||
$params
|
||||
), TRUE);
|
||||
|
||||
// Results are returned, errors are thrown.
|
||||
if (is_array($result) && isset($result['error'])) {
|
||||
$e = new OAuth2Exception($result);
|
||||
switch ($e->getType()) {
|
||||
// OAuth 2.0 Draft 10 style.
|
||||
case 'invalid_token':
|
||||
$this->setSession(NULL);
|
||||
default:
|
||||
$this->setSession(NULL);
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
// End stuff that should get overridden.
|
||||
|
||||
/**
|
||||
* Default options for cURL.
|
||||
*/
|
||||
public static $CURL_OPTS = array(
|
||||
CURLOPT_CONNECTTIMEOUT => 10,
|
||||
CURLOPT_RETURNTRANSFER => TRUE,
|
||||
CURLOPT_HEADER => TRUE,
|
||||
CURLOPT_TIMEOUT => 60,
|
||||
CURLOPT_USERAGENT => 'oauth2-draft-v10',
|
||||
CURLOPT_HTTPHEADER => array("Accept: application/json"),
|
||||
);
|
||||
|
||||
/**
|
||||
* Set the Session.
|
||||
*
|
||||
* @param $session
|
||||
* (optional) The session object to be set. NULL if hope to frush existing
|
||||
* session object.
|
||||
* @param $write_cookie
|
||||
* (optional) TRUE if a cookie should be written. This value is ignored
|
||||
* if cookie support has been disabled.
|
||||
*
|
||||
* @return
|
||||
* The current OAuth2.0 client-side instance.
|
||||
*/
|
||||
public function setSession($session = NULL, $write_cookie = TRUE) {
|
||||
$this->setVariable('_session', $this->validateSessionObject($session));
|
||||
$this->setVariable('_session_loaded', TRUE);
|
||||
if ($write_cookie) {
|
||||
$this->setCookieFromSession($this->getVariable('_session'));
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the session object.
|
||||
*
|
||||
* This will automatically look for a signed session via custom method,
|
||||
* OAuth2.0 grant type with authorization_code, OAuth2.0 grant type with
|
||||
* password, or cookie that we had already setup.
|
||||
*
|
||||
* @return
|
||||
* The valid session object with OAuth2.0 infomration, and NULL if not
|
||||
* able to discover any cases.
|
||||
*/
|
||||
public function getSession() {
|
||||
if (!$this->getVariable('_session_loaded')) {
|
||||
$session = NULL;
|
||||
$write_cookie = TRUE;
|
||||
|
||||
// Try obtain login session by custom method.
|
||||
// $session = $this->getSessionObject(NULL);
|
||||
// $session = $this->validateSessionObject($session);
|
||||
|
||||
// grant_type == authorization_code.
|
||||
if (!$session && $this->getVariable('code')) {
|
||||
$access_token = $this->getAccessTokenFromAuthorizationCode($this->getVariable('code'));
|
||||
$session = $this->getSessionObject($access_token);
|
||||
$session = $this->validateSessionObject($session);
|
||||
}
|
||||
|
||||
// grant_type == password.
|
||||
if (!$session && $this->getVariable('username') && $this->getVariable('password')) {
|
||||
$access_token = $this->getAccessTokenFromPassword($this->getVariable('username'), $this->getVariable('password'));
|
||||
$session = $this->getSessionObject($access_token);
|
||||
$session = $this->validateSessionObject($session);
|
||||
}
|
||||
|
||||
// Try loading session from cookie if necessary.
|
||||
if (!$session && $this->getVariable('cookie_support')) {
|
||||
$cookie_name = $this->getSessionCookieName();
|
||||
if (isset($_COOKIE[$cookie_name])) {
|
||||
$session = array();
|
||||
parse_str(trim(
|
||||
get_magic_quotes_gpc()
|
||||
? stripslashes($_COOKIE[$cookie_name])
|
||||
: $_COOKIE[$cookie_name],
|
||||
'"'
|
||||
), $session);
|
||||
$session = $this->validateSessionObject($session);
|
||||
// Write only if we need to delete a invalid session cookie.
|
||||
$write_cookie = empty($session);
|
||||
}
|
||||
}
|
||||
|
||||
$this->setSession($session, $write_cookie);
|
||||
}
|
||||
|
||||
return $this->getVariable('_session');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an OAuth2.0 access token from session.
|
||||
*
|
||||
* This will trigger getSession() and so we MUST initialize with required
|
||||
* configuration.
|
||||
*
|
||||
* @return
|
||||
* The valid OAuth2.0 access token, and NULL if not exists in session.
|
||||
*/
|
||||
public function getAccessToken() {
|
||||
$session = $this->getSession();
|
||||
return isset($session['access_token']) ? $session['access_token'] : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get access token from OAuth2.0 token endpoint with authorization code.
|
||||
*
|
||||
* This function will only be activated if both access token URI, client
|
||||
* identifier and client secret are setup correctly.
|
||||
*
|
||||
* @param $code
|
||||
* Authorization code issued by authorization server's authorization
|
||||
* endpoint.
|
||||
*
|
||||
* @return
|
||||
* A valid OAuth2.0 JSON decoded access token in associative array, and
|
||||
* NULL if not enough parameters or JSON decode failed.
|
||||
*/
|
||||
private function getAccessTokenFromAuthorizationCode($code) {
|
||||
if ($this->getVariable('access_token_uri') && $this->getVariable('client_id') && $this->getVariable('client_secret')) {
|
||||
$result = json_decode($this->makeRequest(
|
||||
$this->getVariable('access_token_uri'),
|
||||
'POST',
|
||||
array(
|
||||
'grant_type' => 'authorization_code',
|
||||
'client_id' => $this->getVariable('client_id'),
|
||||
'client_secret' => $this->getVariable('client_secret'),
|
||||
'code' => $code,
|
||||
'redirect_uri' => $this->getVariable( 'authorize_callback_uri') //$this->getCurrentUri(),
|
||||
)
|
||||
), TRUE);
|
||||
return $result;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get access token from OAuth2.0 token endpoint with basic user
|
||||
* credentials.
|
||||
*
|
||||
* This function will only be activated if both username and password
|
||||
* are setup correctly.
|
||||
*
|
||||
* @param $username
|
||||
* Username to be check with.
|
||||
* @param $password
|
||||
* Password to be check with.
|
||||
*
|
||||
* @return
|
||||
* A valid OAuth2.0 JSON decoded access token in associative array, and
|
||||
* NULL if not enough parameters or JSON decode failed.
|
||||
*/
|
||||
private function getAccessTokenFromPassword($username, $password) {
|
||||
if ($this->getVariable('access_token_uri') && $this->getVariable('client_id') && $this->getVariable('client_secret')) {
|
||||
return json_decode($this->makeRequest(
|
||||
$this->getVariable('access_token_uri'),
|
||||
'POST',
|
||||
array(
|
||||
'grant_type' => 'password',
|
||||
'client_id' => $this->getVariable('client_id'),
|
||||
'client_secret' => $this->getVariable('client_secret'),
|
||||
'username' => $username,
|
||||
'password' => $password,
|
||||
)
|
||||
), TRUE);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an OAuth2.0 Request.
|
||||
*
|
||||
* Automatically append "oauth_token" in query parameters if not yet
|
||||
* exists and able to discover a valid access token from session. Otherwise
|
||||
* just ignore setup with "oauth_token" and handle the API call AS-IS, and
|
||||
* so may issue a plain API call without OAuth2.0 protection.
|
||||
*
|
||||
* @param $path
|
||||
* The target path, relative to base_path/service_uri or an absolute URI.
|
||||
* @param $method
|
||||
* (optional) The HTTP method (default 'GET').
|
||||
* @param $params
|
||||
* (optional The GET/POST parameters.
|
||||
*
|
||||
* @return
|
||||
* The JSON decoded response object.
|
||||
*
|
||||
* @throws OAuth2Exception
|
||||
*/
|
||||
protected function makeOAuth2Request($path, $method = 'GET', $params = array()) {
|
||||
if ((!isset($params['oauth_token']) || empty($params['oauth_token'])) && $oauth_token = $this->getAccessToken()) {
|
||||
$params['oauth_token'] = $oauth_token;
|
||||
}
|
||||
return $this->makeRequest($path, $method, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes an HTTP request.
|
||||
*
|
||||
* This method can be overriden by subclasses if developers want to do
|
||||
* fancier things or use something other than cURL to make the request.
|
||||
*
|
||||
* @param $path
|
||||
* The target path, relative to base_path/service_uri or an absolute URI.
|
||||
* @param $method
|
||||
* (optional) The HTTP method (default 'GET').
|
||||
* @param $params
|
||||
* (optional The GET/POST parameters.
|
||||
* @param $ch
|
||||
* (optional) An initialized curl handle
|
||||
*
|
||||
* @return
|
||||
* The JSON decoded response object.
|
||||
*/
|
||||
protected function makeRequest($path, $method = 'GET', $params = array(), $ch = NULL) {
|
||||
if (!$ch)
|
||||
$ch = curl_init();
|
||||
|
||||
$opts = self::$CURL_OPTS;
|
||||
if ($params) {
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
$path .= '?' . http_build_query($params, NULL, '&');
|
||||
break;
|
||||
// Method override as we always do a POST.
|
||||
default:
|
||||
if ($this->getVariable('file_upload_support')) {
|
||||
$opts[CURLOPT_POSTFIELDS] = $params;
|
||||
}
|
||||
else {
|
||||
$opts[CURLOPT_POSTFIELDS] = http_build_query($params, NULL, '&');
|
||||
}
|
||||
}
|
||||
}
|
||||
$opts[CURLOPT_URL] = $path;
|
||||
|
||||
// Disable the 'Expect: 100-continue' behaviour. This causes CURL to wait
|
||||
// for 2 seconds if the server does not support this header.
|
||||
if (isset($opts[CURLOPT_HTTPHEADER])) {
|
||||
$existing_headers = $opts[CURLOPT_HTTPHEADER];
|
||||
$existing_headers[] = 'Expect:';
|
||||
$opts[CURLOPT_HTTPHEADER] = $existing_headers;
|
||||
}
|
||||
else {
|
||||
$opts[CURLOPT_HTTPHEADER] = array('Expect:');
|
||||
}
|
||||
|
||||
curl_setopt_array($ch, $opts);
|
||||
$result = curl_exec($ch);
|
||||
|
||||
if (curl_errno($ch) == 60) { // CURLE_SSL_CACERT
|
||||
error_log('Invalid or no certificate authority found, using bundled information');
|
||||
curl_setopt($ch, CURLOPT_CAINFO,
|
||||
dirname(__FILE__) . '/fb_ca_chain_bundle.crt');
|
||||
$result = curl_exec($ch);
|
||||
}
|
||||
|
||||
if ($result === FALSE) {
|
||||
$e = new OAuth2Exception(array(
|
||||
'code' => curl_errno($ch),
|
||||
'message' => curl_error($ch),
|
||||
));
|
||||
curl_close($ch);
|
||||
throw $e;
|
||||
}
|
||||
curl_close($ch);
|
||||
|
||||
// Split the HTTP response into header and body.
|
||||
list($headers, $body) = explode("\r\n\r\n", $result);
|
||||
$headers = explode("\r\n", $headers);
|
||||
|
||||
// We catch HTTP/1.1 4xx or HTTP/1.1 5xx error response.
|
||||
if (strpos($headers[0], 'HTTP/1.1 4') !== FALSE || strpos($headers[0], 'HTTP/1.1 5') !== FALSE) {
|
||||
$result = array(
|
||||
'code' => 0,
|
||||
'message' => '',
|
||||
);
|
||||
|
||||
if (preg_match('/^HTTP\/1.1 ([0-9]{3,3}) (.*)$/', $headers[0], $matches)) {
|
||||
$result['code'] = $matches[1];
|
||||
$result['message'] = $matches[2];
|
||||
}
|
||||
|
||||
// In case retrun with WWW-Authenticate replace the description.
|
||||
foreach ($headers as $header) {
|
||||
if (preg_match("/^WWW-Authenticate:.*error='(.*)'/", $header, $matches)) {
|
||||
$result['error'] = $matches[1];
|
||||
}
|
||||
}
|
||||
|
||||
return json_encode($result);
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the cookie that contains the session object.
|
||||
*
|
||||
* @return
|
||||
* The cookie name.
|
||||
*/
|
||||
private function getSessionCookieName() {
|
||||
return 'oauth2_' . $this->getVariable('client_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a JS Cookie based on the _passed in_ session.
|
||||
*
|
||||
* It does not use the currently stored session - you need to explicitly
|
||||
* pass it in.
|
||||
*
|
||||
* @param $session
|
||||
* The session to use for setting the cookie.
|
||||
*/
|
||||
protected function setCookieFromSession($session = NULL) {
|
||||
if (!$this->getVariable('cookie_support'))
|
||||
return;
|
||||
|
||||
$cookie_name = $this->getSessionCookieName();
|
||||
$value = 'deleted';
|
||||
$expires = time() - 3600;
|
||||
$base_domain = $this->getVariable('base_domain', OAUTH2_DEFAULT_BASE_DOMAIN);
|
||||
|
||||
if ($session) {
|
||||
$value = '"' . http_build_query($session, NULL, '&') . '"';
|
||||
$base_domain = isset($session['base_domain']) ? $session['base_domain'] : $base_domain;
|
||||
$expires = isset($session['expires']) ? $session['expires'] : time() + $this->getVariable('expires_in', OAUTH2_DEFAULT_EXPIRES_IN);
|
||||
}
|
||||
|
||||
// Prepend dot if a domain is found.
|
||||
if ($base_domain)
|
||||
$base_domain = '.' . $base_domain;
|
||||
|
||||
// If an existing cookie is not set, we dont need to delete it.
|
||||
if ($value == 'deleted' && empty($_COOKIE[$cookie_name]))
|
||||
return;
|
||||
|
||||
if (headers_sent())
|
||||
error_log('Could not set cookie. Headers already sent.');
|
||||
else
|
||||
setcookie($cookie_name, $value, $expires, '/', $base_domain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a session_version = 3 style session object.
|
||||
*
|
||||
* @param $session
|
||||
* The session object.
|
||||
*
|
||||
* @return
|
||||
* The session object if it validates, NULL otherwise.
|
||||
*/
|
||||
protected function validateSessionObject($session) {
|
||||
// Make sure some essential fields exist.
|
||||
if (is_array($session) && isset($session['access_token']) && isset($session['sig'])) {
|
||||
// Validate the signature.
|
||||
$session_without_sig = $session;
|
||||
unset($session_without_sig['sig']);
|
||||
|
||||
$expected_sig = self::generateSignature(
|
||||
$session_without_sig,
|
||||
$this->getVariable('client_secret')
|
||||
);
|
||||
|
||||
if ($session['sig'] != $expected_sig) {
|
||||
error_log('Got invalid session signature in cookie.');
|
||||
$session = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$session = NULL;
|
||||
}
|
||||
return $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Since $_SERVER['REQUEST_URI'] is only available on Apache, we
|
||||
* generate an equivalent using other environment variables.
|
||||
*/
|
||||
function getRequestUri() {
|
||||
if (isset($_SERVER['REQUEST_URI'])) {
|
||||
$uri = $_SERVER['REQUEST_URI'];
|
||||
}
|
||||
else {
|
||||
if (isset($_SERVER['argv'])) {
|
||||
$uri = $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['argv'][0];
|
||||
}
|
||||
elseif (isset($_SERVER['QUERY_STRING'])) {
|
||||
$uri = $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['QUERY_STRING'];
|
||||
}
|
||||
else {
|
||||
$uri = $_SERVER['SCRIPT_NAME'];
|
||||
}
|
||||
}
|
||||
// Prevent multiple slashes to avoid cross site requests via the Form API.
|
||||
$uri = '/' . ltrim($uri, '/');
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Current URL.
|
||||
*
|
||||
* @return
|
||||
* The current URL.
|
||||
*/
|
||||
protected function getCurrentUri() {
|
||||
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on'
|
||||
? 'https://'
|
||||
: 'http://';
|
||||
$current_uri = $protocol . $_SERVER['HTTP_HOST'] . $this->getRequestUri();
|
||||
$parts = parse_url($current_uri);
|
||||
|
||||
$query = '';
|
||||
if (!empty($parts['query'])) {
|
||||
$params = array();
|
||||
parse_str($parts['query'], $params);
|
||||
$params = array_filter($params);
|
||||
if (!empty($params)) {
|
||||
$query = '?' . http_build_query($params, NULL, '&');
|
||||
}
|
||||
}
|
||||
|
||||
// Use port if non default.
|
||||
$port = isset($parts['port']) &&
|
||||
(($protocol === 'http://' && $parts['port'] !== 80) || ($protocol === 'https://' && $parts['port'] !== 443))
|
||||
? ':' . $parts['port'] : '';
|
||||
|
||||
// Rebuild.
|
||||
return $protocol . $parts['host'] . $port . $parts['path'] . $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the URL for given path and parameters.
|
||||
*
|
||||
* @param $path
|
||||
* (optional) The path.
|
||||
* @param $params
|
||||
* (optional) The query parameters in associative array.
|
||||
*
|
||||
* @return
|
||||
* The URL for the given parameters.
|
||||
*/
|
||||
protected function getUri($path = '', $params = array()) {
|
||||
$url = $this->getVariable('services_uri') ? $this->getVariable('services_uri') : $this->getVariable('base_uri');
|
||||
|
||||
if (!empty($path))
|
||||
if (substr($path, 0, 4) == "http")
|
||||
$url = $path;
|
||||
else
|
||||
$url = rtrim($url, '/') . '/' . ltrim($path, '/');
|
||||
|
||||
if (!empty($params))
|
||||
$url .= '?' . http_build_query($params, NULL, '&');
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a signature for the given params and secret.
|
||||
*
|
||||
* @param $params
|
||||
* The parameters to sign.
|
||||
* @param $secret
|
||||
* The secret to sign with.
|
||||
*
|
||||
* @return
|
||||
* The generated signature
|
||||
*/
|
||||
protected function generateSignature($params, $secret) {
|
||||
// Work with sorted data.
|
||||
ksort($params);
|
||||
|
||||
// Generate the base string.
|
||||
$base_string = '';
|
||||
foreach ($params as $key => $value) {
|
||||
$base_string .= $key . '=' . $value;
|
||||
}
|
||||
$base_string .= $secret;
|
||||
|
||||
return md5($base_string);
|
||||
}
|
||||
}
|
||||
|
||||
class OAuth2Exception extends Exception {
|
||||
|
||||
/**
|
||||
* The result from the API server that represents the exception information.
|
||||
*/
|
||||
protected $result;
|
||||
|
||||
/**
|
||||
* Make a new API Exception with the given result.
|
||||
*
|
||||
* @param $result
|
||||
* The result from the API server.
|
||||
*/
|
||||
public function __construct($result) {
|
||||
$this->result = $result;
|
||||
|
||||
$code = isset($result['code']) ? $result['code'] : 0;
|
||||
|
||||
if (isset($result['error'])) {
|
||||
// OAuth 2.0 Draft 10 style
|
||||
$message = $result['error'];
|
||||
}
|
||||
elseif (isset($result['message'])) {
|
||||
// cURL style
|
||||
$message = $result['message'];
|
||||
}
|
||||
else {
|
||||
$message = 'Unknown Error. Check getResult()';
|
||||
}
|
||||
|
||||
parent::__construct($message, $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the associated result object returned by the API server.
|
||||
*
|
||||
* @returns
|
||||
* The result from the API server.
|
||||
*/
|
||||
public function getResult() {
|
||||
return $this->result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the associated type for the error. This will default to
|
||||
* 'Exception' when a type is not available.
|
||||
*
|
||||
* @return
|
||||
* The type for the error.
|
||||
*/
|
||||
public function getType() {
|
||||
if (isset($this->result['error'])) {
|
||||
$message = $this->result['error'];
|
||||
if (is_string($message)) {
|
||||
// OAuth 2.0 Draft 10 style
|
||||
return $message;
|
||||
}
|
||||
}
|
||||
return 'Exception';
|
||||
}
|
||||
|
||||
/**
|
||||
* To make debugging easier.
|
||||
*
|
||||
* @returns
|
||||
* The string representation of the error.
|
||||
*/
|
||||
public function __toString() {
|
||||
$str = $this->getType() . ': ';
|
||||
if ($this->code != 0) {
|
||||
$str .= $this->code . ': ';
|
||||
}
|
||||
return $str . $this->message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,802 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The default Cache Lifetime (in seconds).
|
||||
*/
|
||||
define("OAUTH2_DEFAULT_EXPIRES_IN", 3600*60*60*24);
|
||||
|
||||
/**
|
||||
* The default Base domain for the Cookie.
|
||||
*/
|
||||
define("OAUTH2_DEFAULT_BASE_DOMAIN", '');
|
||||
|
||||
/**
|
||||
* OAuth2.0 draft v10 client-side implementation.
|
||||
*
|
||||
* @author Originally written by Naitik Shah <naitik@facebook.com>.
|
||||
* @author Update to draft v10 by Edison Wong <hswong3i@pantarei-design.com>.
|
||||
*
|
||||
* @sa <a href="https://github.com/facebook/php-sdk">Facebook PHP SDK</a>.
|
||||
*/
|
||||
abstract class OAuth2Client {
|
||||
|
||||
/**
|
||||
* Array of persistent variables stored.
|
||||
*/
|
||||
protected $conf = array();
|
||||
|
||||
/**
|
||||
* Returns a persistent variable.
|
||||
*
|
||||
* To avoid problems, always use lower case for persistent variable names.
|
||||
*
|
||||
* @param $name
|
||||
* The name of the variable to return.
|
||||
* @param $default
|
||||
* The default value to use if this variable has never been set.
|
||||
*
|
||||
* @return
|
||||
* The value of the variable.
|
||||
*/
|
||||
public function getVariable($name, $default = NULL) {
|
||||
return isset($this->conf[$name]) ? $this->conf[$name] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a persistent variable.
|
||||
*
|
||||
* To avoid problems, always use lower case for persistent variable names.
|
||||
*
|
||||
* @param $name
|
||||
* The name of the variable to set.
|
||||
* @param $value
|
||||
* The value to set.
|
||||
*/
|
||||
public function setVariable($name, $value) {
|
||||
$this->conf[$name] = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Stuff that should get overridden by subclasses.
|
||||
//
|
||||
// I don't want to make these abstract, because then subclasses would have
|
||||
// to implement all of them, which is too much work.
|
||||
//
|
||||
// So they're just stubs. Override the ones you need.
|
||||
|
||||
/**
|
||||
* Initialize a Drupal OAuth2.0 Application.
|
||||
*
|
||||
* @param $config
|
||||
* An associative array as below:
|
||||
* - base_uri: The base URI for the OAuth2.0 endpoints.
|
||||
* - code: (optional) The authorization code.
|
||||
* - username: (optional) The username.
|
||||
* - password: (optional) The password.
|
||||
* - client_id: (optional) The application ID.
|
||||
* - client_secret: (optional) The application secret.
|
||||
* - authorize_uri: (optional) The end-user authorization endpoint URI.
|
||||
* - access_token_uri: (optional) The token endpoint URI.
|
||||
* - services_uri: (optional) The services endpoint URI.
|
||||
* - cookie_support: (optional) TRUE to enable cookie support.
|
||||
* - base_domain: (optional) The domain for the cookie.
|
||||
* - file_upload_support: (optional) TRUE if file uploads are enabled.
|
||||
*/
|
||||
public function __construct($config = array()) {
|
||||
// We must set base_uri first.
|
||||
$this->setVariable('base_uri', $config['base_uri']);
|
||||
unset($config['base_uri']);
|
||||
|
||||
// Use predefined OAuth2.0 params, or get it from $_REQUEST.
|
||||
foreach (array('code', 'username', 'password') as $name) {
|
||||
if (isset($config[$name]))
|
||||
$this->setVariable($name, $config[$name]);
|
||||
else if (isset($_REQUEST[$name]) && !empty($_REQUEST[$name]))
|
||||
$this->setVariable($name, $_REQUEST[$name]);
|
||||
unset($config[$name]);
|
||||
}
|
||||
|
||||
// Endpoint URIs.
|
||||
foreach (array('authorize_uri', 'access_token_uri', 'services_uri') as $name) {
|
||||
if (isset($config[$name]))
|
||||
if (substr($config[$name], 0, 4) == "http")
|
||||
$this->setVariable($name, $config[$name]);
|
||||
else
|
||||
$this->setVariable($name, $this->getVariable('base_uri') . $config[$name]);
|
||||
unset($config[$name]);
|
||||
}
|
||||
|
||||
// Other else configurations.
|
||||
foreach ($config as $name => $value) {
|
||||
$this->setVariable($name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to get session object from custom method.
|
||||
*
|
||||
* By default we generate session object based on access_token response, or
|
||||
* if it is provided from server with $_REQUEST. For sure, if it is provided
|
||||
* by server it should follow our session object format.
|
||||
*
|
||||
* Session object provided by server can ensure the correct expires and
|
||||
* base_domain setup as predefined in server, also you may get more useful
|
||||
* information for custom functionality, too. BTW, this may require for
|
||||
* additional remote call overhead.
|
||||
*
|
||||
* You may wish to override this function with your custom version due to
|
||||
* your own server-side implementation.
|
||||
*
|
||||
* @param $access_token
|
||||
* (optional) A valid access token in associative array as below:
|
||||
* - access_token: A valid access_token generated by OAuth2.0
|
||||
* authorization endpoint.
|
||||
* - expires_in: (optional) A valid expires_in generated by OAuth2.0
|
||||
* authorization endpoint.
|
||||
* - refresh_token: (optional) A valid refresh_token generated by OAuth2.0
|
||||
* authorization endpoint.
|
||||
* - scope: (optional) A valid scope generated by OAuth2.0
|
||||
* authorization endpoint.
|
||||
*
|
||||
* @return
|
||||
* A valid session object in associative array for setup cookie, and
|
||||
* NULL if not able to generate it with custom method.
|
||||
*/
|
||||
protected function getSessionObject($access_token = NULL) {
|
||||
$session = NULL;
|
||||
|
||||
// Try generate local version of session cookie.
|
||||
if (!empty($access_token) && isset($access_token['access_token'])) {
|
||||
$session['access_token'] = $access_token['access_token'];
|
||||
$session['base_domain'] = $this->getVariable('base_domain', OAUTH2_DEFAULT_BASE_DOMAIN);
|
||||
$session['expires'] = isset($access_token['expires_in']) ? time() + $access_token['expires_in'] : time() + $this->getVariable('expires_in', OAUTH2_DEFAULT_EXPIRES_IN);
|
||||
$session['refresh_token'] = isset($access_token['refresh_token']) ? $access_token['refresh_token'] : '';
|
||||
$session['scope'] = isset($access_token['scope']) ? $access_token['scope'] : '';
|
||||
$session['secret'] = md5(base64_encode(pack('N6', mt_rand(), mt_rand(), mt_rand(), mt_rand(), mt_rand(), uniqid())));
|
||||
|
||||
// Provide our own signature.
|
||||
$sig = self::generateSignature(
|
||||
$session,
|
||||
$this->getVariable('client_secret')
|
||||
);
|
||||
$session['sig'] = $sig;
|
||||
}
|
||||
|
||||
// Try loading session from $_REQUEST.
|
||||
if (!$session && isset($_REQUEST['session'])) {
|
||||
$session = json_decode(
|
||||
get_magic_quotes_gpc()
|
||||
? stripslashes($_REQUEST['session'])
|
||||
: $_REQUEST['session'],
|
||||
TRUE
|
||||
);
|
||||
}
|
||||
|
||||
return $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an API call.
|
||||
*
|
||||
* Support both OAuth2.0 or normal GET/POST API call, with relative
|
||||
* or absolute URI.
|
||||
*
|
||||
* If no valid OAuth2.0 access token found in session object, this function
|
||||
* will automatically switch as normal remote API call without "oauth_token"
|
||||
* parameter.
|
||||
*
|
||||
* Assume server reply in JSON object and always decode during return. If
|
||||
* you hope to issue a raw query, please use makeRequest().
|
||||
*
|
||||
* @param $path
|
||||
* The target path, relative to base_path/service_uri or an absolute URI.
|
||||
* @param $method
|
||||
* (optional) The HTTP method (default 'GET').
|
||||
* @param $params
|
||||
* (optional The GET/POST parameters.
|
||||
*
|
||||
* @return
|
||||
* The JSON decoded response object.
|
||||
*
|
||||
* @throws OAuth2Exception
|
||||
*/
|
||||
public function api($path, $method = 'GET', $params = array()) {
|
||||
if (is_array($method) && empty($params)) {
|
||||
$params = $method;
|
||||
$method = 'GET';
|
||||
}
|
||||
|
||||
// json_encode all params values that are not strings.
|
||||
foreach ($params as $key => $value) {
|
||||
if (!is_string($value)) {
|
||||
$params[$key] = json_encode($value);
|
||||
}
|
||||
}
|
||||
|
||||
$result = json_decode($this->makeOAuth2Request(
|
||||
$this->getUri($path),
|
||||
$method,
|
||||
$params
|
||||
), TRUE);
|
||||
|
||||
// Results are returned, errors are thrown.
|
||||
if (is_array($result) && isset($result['error'])) {
|
||||
$e = new OAuth2Exception($result);
|
||||
switch ($e->getType()) {
|
||||
// OAuth 2.0 Draft 10 style.
|
||||
case 'invalid_token':
|
||||
$this->setSession(NULL);
|
||||
default:
|
||||
$this->setSession(NULL);
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
// End stuff that should get overridden.
|
||||
|
||||
/**
|
||||
* Default options for cURL.
|
||||
*/
|
||||
public static $CURL_OPTS = array(
|
||||
CURLOPT_CONNECTTIMEOUT => 10,
|
||||
CURLOPT_RETURNTRANSFER => TRUE,
|
||||
CURLOPT_HEADER => TRUE,
|
||||
CURLOPT_TIMEOUT => 60,
|
||||
CURLOPT_USERAGENT => 'oauth2-draft-v10',
|
||||
CURLOPT_HTTPHEADER => array("Accept: application/json"),
|
||||
CURLOPT_SSL_VERIFYPEER => FALSE,
|
||||
CURLOPT_SSL_VERIFYHOST => FALSE
|
||||
|
||||
);
|
||||
|
||||
/**
|
||||
* Set the Session.
|
||||
*
|
||||
* @param $session
|
||||
* (optional) The session object to be set. NULL if hope to frush existing
|
||||
* session object.
|
||||
* @param $write_cookie
|
||||
* (optional) TRUE if a cookie should be written. This value is ignored
|
||||
* if cookie support has been disabled.
|
||||
*
|
||||
* @return
|
||||
* The current OAuth2.0 client-side instance.
|
||||
*/
|
||||
public function setSession($session = NULL, $write_cookie = TRUE) {
|
||||
$this->setVariable('_session', $this->validateSessionObject($session));
|
||||
$this->setVariable('_session_loaded', TRUE);
|
||||
if ($write_cookie) {
|
||||
$this->setCookieFromSession($this->getVariable('_session'));
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the session object.
|
||||
*
|
||||
* This will automatically look for a signed session via custom method,
|
||||
* OAuth2.0 grant type with authorization_code, OAuth2.0 grant type with
|
||||
* password, or cookie that we had already setup.
|
||||
*
|
||||
* @return
|
||||
* The valid session object with OAuth2.0 infomration, and NULL if not
|
||||
* able to discover any cases.
|
||||
*/
|
||||
public function getSession() {
|
||||
if (!$this->getVariable('_session_loaded')) {
|
||||
$session = NULL;
|
||||
$write_cookie = TRUE;
|
||||
|
||||
// Try obtain login session by custom method.
|
||||
// $session = $this->getSessionObject(NULL);
|
||||
// $session = $this->validateSessionObject($session);
|
||||
|
||||
// grant_type == authorization_code.
|
||||
if (!$session && $this->getVariable('code')) {
|
||||
$access_token = $this->getAccessTokenFromAuthorizationCode($this->getVariable('code'));
|
||||
$session = $this->getSessionObject($access_token);
|
||||
$session = $this->validateSessionObject($session);
|
||||
}
|
||||
|
||||
// grant_type == password.
|
||||
if (!$session && $this->getVariable('username') && $this->getVariable('password')) {
|
||||
$access_token = $this->getAccessTokenFromPassword($this->getVariable('username'), $this->getVariable('password'));
|
||||
$session = $this->getSessionObject($access_token);
|
||||
$session = $this->validateSessionObject($session);
|
||||
}
|
||||
|
||||
// Try loading session from cookie if necessary.
|
||||
if (!$session && $this->getVariable('cookie_support')) {
|
||||
$cookie_name = $this->getSessionCookieName();
|
||||
if (isset($_COOKIE[$cookie_name])) {
|
||||
$session = array();
|
||||
parse_str(trim(
|
||||
get_magic_quotes_gpc()
|
||||
? stripslashes($_COOKIE[$cookie_name])
|
||||
: $_COOKIE[$cookie_name],
|
||||
'"'
|
||||
), $session);
|
||||
$session = $this->validateSessionObject($session);
|
||||
// Write only if we need to delete a invalid session cookie.
|
||||
$write_cookie = empty($session);
|
||||
}
|
||||
}
|
||||
|
||||
$this->setSession($session, $write_cookie);
|
||||
}
|
||||
|
||||
return $this->getVariable('_session');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an OAuth2.0 access token from session.
|
||||
*
|
||||
* This will trigger getSession() and so we MUST initialize with required
|
||||
* configuration.
|
||||
*
|
||||
* @return
|
||||
* The valid OAuth2.0 access token, and NULL if not exists in session.
|
||||
*/
|
||||
public function getAccessToken() {
|
||||
$session = $this->getSession();
|
||||
return isset($session['access_token']) ? $session['access_token'] : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get access token from OAuth2.0 token endpoint with authorization code.
|
||||
*
|
||||
* This function will only be activated if both access token URI, client
|
||||
* identifier and client secret are setup correctly.
|
||||
*
|
||||
* @param $code
|
||||
* Authorization code issued by authorization server's authorization
|
||||
* endpoint.
|
||||
*
|
||||
* @return
|
||||
* A valid OAuth2.0 JSON decoded access token in associative array, and
|
||||
* NULL if not enough parameters or JSON decode failed.
|
||||
*/
|
||||
private function getAccessTokenFromAuthorizationCode($code) {
|
||||
if ($this->getVariable('access_token_uri') && $this->getVariable('client_id') && $this->getVariable('client_secret')) {
|
||||
$result = json_decode($this->makeRequest(
|
||||
$this->getVariable('access_token_uri'),
|
||||
'POST',
|
||||
array(
|
||||
'grant_type' => 'authorization_code',
|
||||
'client_id' => $this->getVariable('client_id'),
|
||||
'client_secret' => $this->getVariable('client_secret'),
|
||||
'code' => $code,
|
||||
'redirect_uri' => $this->getVariable( 'authorize_callback_uri') //$this->getCurrentUri(),
|
||||
)
|
||||
), TRUE);
|
||||
return $result;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get access token from OAuth2.0 token endpoint with basic user
|
||||
* credentials.
|
||||
*
|
||||
* This function will only be activated if both username and password
|
||||
* are setup correctly.
|
||||
*
|
||||
* @param $username
|
||||
* Username to be check with.
|
||||
* @param $password
|
||||
* Password to be check with.
|
||||
*
|
||||
* @return
|
||||
* A valid OAuth2.0 JSON decoded access token in associative array, and
|
||||
* NULL if not enough parameters or JSON decode failed.
|
||||
*/
|
||||
private function getAccessTokenFromPassword($username, $password) {
|
||||
if ($this->getVariable('access_token_uri') && $this->getVariable('client_id') && $this->getVariable('client_secret')) {
|
||||
return json_decode($this->makeRequest(
|
||||
$this->getVariable('access_token_uri'),
|
||||
'POST',
|
||||
array(
|
||||
'grant_type' => 'password',
|
||||
'client_id' => $this->getVariable('client_id'),
|
||||
'client_secret' => $this->getVariable('client_secret'),
|
||||
'username' => $username,
|
||||
'password' => $password,
|
||||
)
|
||||
), TRUE);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an OAuth2.0 Request.
|
||||
*
|
||||
* Automatically append "oauth_token" in query parameters if not yet
|
||||
* exists and able to discover a valid access token from session. Otherwise
|
||||
* just ignore setup with "oauth_token" and handle the API call AS-IS, and
|
||||
* so may issue a plain API call without OAuth2.0 protection.
|
||||
*
|
||||
* @param $path
|
||||
* The target path, relative to base_path/service_uri or an absolute URI.
|
||||
* @param $method
|
||||
* (optional) The HTTP method (default 'GET').
|
||||
* @param $params
|
||||
* (optional The GET/POST parameters.
|
||||
*
|
||||
* @return
|
||||
* The JSON decoded response object.
|
||||
*
|
||||
* @throws OAuth2Exception
|
||||
*/
|
||||
protected function makeOAuth2Request($path, $method = 'GET', $params = array()) {
|
||||
if ((!isset($params['oauth_token']) || empty($params['oauth_token'])) && $oauth_token = $this->getAccessToken()) {
|
||||
$params['oauth_token'] = $oauth_token;
|
||||
}
|
||||
return $this->makeRequest($path, $method, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes an HTTP request.
|
||||
*
|
||||
* This method can be overriden by subclasses if developers want to do
|
||||
* fancier things or use something other than cURL to make the request.
|
||||
*
|
||||
* @param $path
|
||||
* The target path, relative to base_path/service_uri or an absolute URI.
|
||||
* @param $method
|
||||
* (optional) The HTTP method (default 'GET').
|
||||
* @param $params
|
||||
* (optional The GET/POST parameters.
|
||||
* @param $ch
|
||||
* (optional) An initialized curl handle
|
||||
*
|
||||
* @return
|
||||
* The JSON decoded response object.
|
||||
*/
|
||||
protected function makeRequest($path, $method = 'GET', $params = array(), $ch = NULL) {
|
||||
if (!$ch)
|
||||
$ch = curl_init();
|
||||
|
||||
$opts = self::$CURL_OPTS;
|
||||
if ($params) {
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
$path .= '?' . http_build_query($params, NULL, '&');
|
||||
break;
|
||||
// Method override as we always do a POST.
|
||||
default:
|
||||
if ($this->getVariable('file_upload_support')) {
|
||||
$opts[CURLOPT_POSTFIELDS] = $params;
|
||||
}
|
||||
else {
|
||||
$opts[CURLOPT_POSTFIELDS] = http_build_query($params, NULL, '&');
|
||||
}
|
||||
}
|
||||
}
|
||||
$opts[CURLOPT_URL] = $path;
|
||||
|
||||
// Disable the 'Expect: 100-continue' behaviour. This causes CURL to wait
|
||||
// for 2 seconds if the server does not support this header.
|
||||
if (isset($opts[CURLOPT_HTTPHEADER])) {
|
||||
$existing_headers = $opts[CURLOPT_HTTPHEADER];
|
||||
$existing_headers[] = 'Expect:';
|
||||
$opts[CURLOPT_HTTPHEADER] = $existing_headers;
|
||||
}
|
||||
else {
|
||||
$opts[CURLOPT_HTTPHEADER] = array('Expect:');
|
||||
}
|
||||
|
||||
curl_setopt_array($ch, $opts);
|
||||
$result = curl_exec($ch);
|
||||
|
||||
if (curl_errno($ch) == 60) { // CURLE_SSL_CACERT
|
||||
error_log('Invalid or no certificate authority found, using bundled information');
|
||||
curl_setopt($ch, CURLOPT_CAINFO,
|
||||
dirname(__FILE__) . '/fb_ca_chain_bundle.crt');
|
||||
$result = curl_exec($ch);
|
||||
}
|
||||
|
||||
if ($result === FALSE) {
|
||||
$e = new OAuth2Exception(array(
|
||||
'code' => curl_errno($ch),
|
||||
'message' => curl_error($ch),
|
||||
));
|
||||
curl_close($ch);
|
||||
throw $e;
|
||||
}
|
||||
curl_close($ch);
|
||||
|
||||
// Split the HTTP response into header and body.
|
||||
list($headers, $body) = explode("\r\n\r\n", $result);
|
||||
$headers = explode("\r\n", $headers);
|
||||
|
||||
// We catch HTTP/1.1 4xx or HTTP/1.1 5xx error response.
|
||||
if (strpos($headers[0], 'HTTP/1.1 4') !== FALSE || strpos($headers[0], 'HTTP/1.1 5') !== FALSE) {
|
||||
$result = array(
|
||||
'code' => 0,
|
||||
'message' => '',
|
||||
);
|
||||
|
||||
if (preg_match('/^HTTP\/1.1 ([0-9]{3,3}) (.*)$/', $headers[0], $matches)) {
|
||||
$result['code'] = $matches[1];
|
||||
$result['message'] = $matches[2];
|
||||
}
|
||||
|
||||
// In case retrun with WWW-Authenticate replace the description.
|
||||
foreach ($headers as $header) {
|
||||
if (preg_match("/^WWW-Authenticate:.*error='(.*)'/", $header, $matches)) {
|
||||
$result['error'] = $matches[1];
|
||||
}
|
||||
}
|
||||
|
||||
return json_encode($result);
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the cookie that contains the session object.
|
||||
*
|
||||
* @return
|
||||
* The cookie name.
|
||||
*/
|
||||
private function getSessionCookieName() {
|
||||
return 'oauth2_' . $this->getVariable('client_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a JS Cookie based on the _passed in_ session.
|
||||
*
|
||||
* It does not use the currently stored session - you need to explicitly
|
||||
* pass it in.
|
||||
*
|
||||
* @param $session
|
||||
* The session to use for setting the cookie.
|
||||
*/
|
||||
protected function setCookieFromSession($session = NULL) {
|
||||
if (!$this->getVariable('cookie_support'))
|
||||
return;
|
||||
|
||||
$cookie_name = $this->getSessionCookieName();
|
||||
$value = 'deleted';
|
||||
$expires = time() - 3600;
|
||||
$base_domain = $this->getVariable('base_domain', OAUTH2_DEFAULT_BASE_DOMAIN);
|
||||
|
||||
if ($session) {
|
||||
$value = '"' . http_build_query($session, NULL, '&') . '"';
|
||||
$base_domain = isset($session['base_domain']) ? $session['base_domain'] : $base_domain;
|
||||
$expires = isset($session['expires']) ? $session['expires'] : time() + $this->getVariable('expires_in', OAUTH2_DEFAULT_EXPIRES_IN);
|
||||
}
|
||||
|
||||
// Prepend dot if a domain is found.
|
||||
if ($base_domain)
|
||||
$base_domain = '.' . $base_domain;
|
||||
|
||||
// If an existing cookie is not set, we dont need to delete it.
|
||||
if ($value == 'deleted' && empty($_COOKIE[$cookie_name]))
|
||||
return;
|
||||
|
||||
if (headers_sent())
|
||||
error_log('Could not set cookie. Headers already sent.');
|
||||
else
|
||||
setcookie($cookie_name, $value, $expires, '/', $base_domain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a session_version = 3 style session object.
|
||||
*
|
||||
* @param $session
|
||||
* The session object.
|
||||
*
|
||||
* @return
|
||||
* The session object if it validates, NULL otherwise.
|
||||
*/
|
||||
protected function validateSessionObject($session) {
|
||||
// Make sure some essential fields exist.
|
||||
if (is_array($session) && isset($session['access_token']) && isset($session['sig'])) {
|
||||
// Validate the signature.
|
||||
$session_without_sig = $session;
|
||||
unset($session_without_sig['sig']);
|
||||
|
||||
$expected_sig = self::generateSignature(
|
||||
$session_without_sig,
|
||||
$this->getVariable('client_secret')
|
||||
);
|
||||
|
||||
if ($session['sig'] != $expected_sig) {
|
||||
error_log('Got invalid session signature in cookie.');
|
||||
$session = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$session = NULL;
|
||||
}
|
||||
return $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Since $_SERVER['REQUEST_URI'] is only available on Apache, we
|
||||
* generate an equivalent using other environment variables.
|
||||
*/
|
||||
function getRequestUri() {
|
||||
if (isset($_SERVER['REQUEST_URI'])) {
|
||||
$uri = $_SERVER['REQUEST_URI'];
|
||||
}
|
||||
else {
|
||||
if (isset($_SERVER['argv'])) {
|
||||
$uri = $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['argv'][0];
|
||||
}
|
||||
elseif (isset($_SERVER['QUERY_STRING'])) {
|
||||
$uri = $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['QUERY_STRING'];
|
||||
}
|
||||
else {
|
||||
$uri = $_SERVER['SCRIPT_NAME'];
|
||||
}
|
||||
}
|
||||
// Prevent multiple slashes to avoid cross site requests via the Form API.
|
||||
$uri = '/' . ltrim($uri, '/');
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Current URL.
|
||||
*
|
||||
* @return
|
||||
* The current URL.
|
||||
*/
|
||||
protected function getCurrentUri() {
|
||||
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on'
|
||||
? 'https://'
|
||||
: 'http://';
|
||||
$current_uri = $protocol . $_SERVER['HTTP_HOST'] . $this->getRequestUri();
|
||||
$parts = parse_url($current_uri);
|
||||
|
||||
$query = '';
|
||||
if (!empty($parts['query'])) {
|
||||
$params = array();
|
||||
parse_str($parts['query'], $params);
|
||||
$params = array_filter($params);
|
||||
if (!empty($params)) {
|
||||
$query = '?' . http_build_query($params, NULL, '&');
|
||||
}
|
||||
}
|
||||
|
||||
// Use port if non default.
|
||||
$port = isset($parts['port']) &&
|
||||
(($protocol === 'http://' && $parts['port'] !== 80) || ($protocol === 'https://' && $parts['port'] !== 443))
|
||||
? ':' . $parts['port'] : '';
|
||||
|
||||
// Rebuild.
|
||||
return $protocol . $parts['host'] . $port . $parts['path'] . $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the URL for given path and parameters.
|
||||
*
|
||||
* @param $path
|
||||
* (optional) The path.
|
||||
* @param $params
|
||||
* (optional) The query parameters in associative array.
|
||||
*
|
||||
* @return
|
||||
* The URL for the given parameters.
|
||||
*/
|
||||
protected function getUri($path = '', $params = array()) {
|
||||
$url = $this->getVariable('services_uri') ? $this->getVariable('services_uri') : $this->getVariable('base_uri');
|
||||
|
||||
if (!empty($path))
|
||||
if (substr($path, 0, 4) == "http")
|
||||
$url = $path;
|
||||
else
|
||||
$url = rtrim($url, '/') . '/' . ltrim($path, '/');
|
||||
|
||||
if (!empty($params))
|
||||
$url .= '?' . http_build_query($params, NULL, '&');
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a signature for the given params and secret.
|
||||
*
|
||||
* @param $params
|
||||
* The parameters to sign.
|
||||
* @param $secret
|
||||
* The secret to sign with.
|
||||
*
|
||||
* @return
|
||||
* The generated signature
|
||||
*/
|
||||
protected function generateSignature($params, $secret) {
|
||||
// Work with sorted data.
|
||||
ksort($params);
|
||||
|
||||
// Generate the base string.
|
||||
$base_string = '';
|
||||
foreach ($params as $key => $value) {
|
||||
$base_string .= $key . '=' . $value;
|
||||
}
|
||||
$base_string .= $secret;
|
||||
|
||||
return md5($base_string);
|
||||
}
|
||||
}
|
||||
|
||||
class OAuth2Exception extends Exception {
|
||||
|
||||
/**
|
||||
* The result from the API server that represents the exception information.
|
||||
*/
|
||||
protected $result;
|
||||
|
||||
/**
|
||||
* Make a new API Exception with the given result.
|
||||
*
|
||||
* @param $result
|
||||
* The result from the API server.
|
||||
*/
|
||||
public function __construct($result) {
|
||||
$this->result = $result;
|
||||
|
||||
$code = isset($result['code']) ? $result['code'] : 0;
|
||||
|
||||
if (isset($result['error'])) {
|
||||
// OAuth 2.0 Draft 10 style
|
||||
$message = $result['error'];
|
||||
}
|
||||
elseif (isset($result['message'])) {
|
||||
// cURL style
|
||||
$message = $result['message'];
|
||||
}
|
||||
else {
|
||||
$message = 'Unknown Error. Check getResult()';
|
||||
}
|
||||
|
||||
parent::__construct($message, $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the associated result object returned by the API server.
|
||||
*
|
||||
* @returns
|
||||
* The result from the API server.
|
||||
*/
|
||||
public function getResult() {
|
||||
return $this->result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the associated type for the error. This will default to
|
||||
* 'Exception' when a type is not available.
|
||||
*
|
||||
* @return
|
||||
* The type for the error.
|
||||
*/
|
||||
public function getType() {
|
||||
if (isset($this->result['error'])) {
|
||||
$message = $this->result['error'];
|
||||
if (is_string($message)) {
|
||||
// OAuth 2.0 Draft 10 style
|
||||
return $message;
|
||||
}
|
||||
}
|
||||
return 'Exception';
|
||||
}
|
||||
|
||||
/**
|
||||
* To make debugging easier.
|
||||
*
|
||||
* @returns
|
||||
* The string representation of the error.
|
||||
*/
|
||||
public function __toString() {
|
||||
$str = $this->getType() . ': ';
|
||||
if ($this->code != 0) {
|
||||
$str .= $this->code . ': ';
|
||||
}
|
||||
return $str . $this->message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
require_once( dirname(__FILE__) . '/OAuth2Client.php' );
|
||||
|
||||
class vkClient extends OAuth2Client
|
||||
{
|
||||
|
||||
private $_allowed_scopes = array(
|
||||
'notify', // Пользователь разрешил отправлять ему уведомления.
|
||||
'friends', // Доступ к друзьям.
|
||||
'photos', // Доступ к фотографиям.
|
||||
'audio', // Доступ к аудиозаписям.
|
||||
'video', // Доступ к видеозаписям.
|
||||
'notes', // Доступ заметкам пользователя.
|
||||
'pages', // Доступ к wiki-страницам.
|
||||
'offers', // Доступ к предложениям (устаревшие методы).
|
||||
'questions', // Доступ к вопросам (устаревшие методы).
|
||||
'wall', // Доступ к обычным и расширенным методам работы со стеной.
|
||||
'messages', // (для Standalone-приложений) Доступ к расширенным методам работы с сообщениями.
|
||||
'offline', // Доступ к API в любое время со стороннего сервера.
|
||||
);
|
||||
|
||||
public function __construct($config = array())
|
||||
{
|
||||
$configured_scopes = array( 'offline' );
|
||||
|
||||
if ( isset($config['scope']) )
|
||||
{
|
||||
$config_scopes = array_map( 'trim', explode(',', $config['scope']) );
|
||||
|
||||
foreach( $config_scopes as $scope )
|
||||
{
|
||||
if ( in_array( $scope, $this->_allowed_scopes ) )
|
||||
{
|
||||
$configured_scopes[] = $scope;
|
||||
}
|
||||
}
|
||||
|
||||
unset( $config['scope'] );
|
||||
}
|
||||
|
||||
$this->setVariable( 'scope', implode(',', $configured_scopes) );
|
||||
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Получение ссылки на авторизацию
|
||||
*
|
||||
* @link http://vk.com/developers.php?o=-1&p=%C0%E2%F2%EE%F0%E8%E7%E0%F6%E8%FF%20%F1%E0%E9%F2%EE%E2
|
||||
*/
|
||||
public function getAuthorizeUrl($params = array())
|
||||
{
|
||||
$params = array_merge(
|
||||
array(
|
||||
'client_id' => $this->getVariable('client_id'),
|
||||
// здесь возможно нужен urlencode + уникальный ключ пользователя
|
||||
'redirect_uri' => $this->getVariable('authorize_callback_uri'),
|
||||
'response_type' => ( $this->getVariable('logintype') == 'client' ) ? 'token' : 'code',
|
||||
'scope' => $this->getVariable( 'scope' ),
|
||||
), $params);
|
||||
|
||||
return $this->getUri( $this->getVariable('authorize_uri'), $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Авторизационный сервер vkontakte нам какбы отвечает
|
||||
* {"access_token":"533bacf01e11f55b536a565b57531ac114461ae8736d6506a3", "expires_in":43200, "user_id":6492}
|
||||
*
|
||||
* @link http://vk.com/developers.php?o=-1&p=%C0%E2%F2%EE%F0%E8%E7%E0%F6%E8%FF%20%F1%E0%E9%F2%EE%E2
|
||||
*/
|
||||
protected function getSessionObject($access_token = NULL)
|
||||
{
|
||||
$session = NULL;
|
||||
|
||||
// Готовим данные для куки
|
||||
if (!empty($access_token) && isset($access_token['access_token'])) {
|
||||
$session['access_token'] = $access_token['access_token'];
|
||||
$session['expires'] = ( isset($access_token['expires_in']) && $access_token['expires_in'] ) ? time() + $access_token['expires_in'] : time() + $this->getVariable('expires_in', OAUTH2_DEFAULT_EXPIRES_IN);
|
||||
$session['refresh_token'] = isset($access_token['refresh_token']) ? $access_token['refresh_token'] : '';
|
||||
$session['user_id'] = isset($access_token['user_id']) ? $access_token['user_id'] : 0;
|
||||
|
||||
$sig = self::generateSignature(
|
||||
$session,
|
||||
$this->getVariable('client_secret')
|
||||
);
|
||||
$session['sig'] = $sig;
|
||||
}
|
||||
|
||||
return $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* У vkontakte вместо oauth_token имеем access_token
|
||||
*
|
||||
* @link http://vk.com/developers.php?o=-1&p=%C2%FB%EF%EE%EB%ED%E5%ED%E8%E5%20%E7%E0%EF%F0%EE%F1%EE%E2%20%EA%20API
|
||||
*/
|
||||
protected function makeOAuth2Request($path, $method = 'GET', $params = array())
|
||||
{
|
||||
if ((!isset($params['access_token']) || empty($params['access_token'])) && $oauth_token = $this->getAccessToken())
|
||||
{
|
||||
$params['access_token'] = $oauth_token;
|
||||
}
|
||||
return $this->makeRequest($path, $method, $params);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user