diff --git a/var/IXR/Base64.php b/var/IXR/Base64.php index 0afe16ea..d009ebef 100644 --- a/var/IXR/Base64.php +++ b/var/IXR/Base64.php @@ -1,18 +1,13 @@ htmlspecialchars) - Site: http://scripts.incutio.com/xmlrpc/ - Manual: http://scripts.incutio.com/xmlrpc/manual.php - Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php -*/ + +namespace IXR; /** * IXR Base64编码 * * @package IXR */ -class IXR_Base64 +class Base64 { /** * 编码数据 @@ -26,7 +21,7 @@ class IXR_Base64 * * @param string $data */ - public function __construct($data) + public function __construct(string $data) { $this->data = $data; } diff --git a/var/IXR/Client.php b/var/IXR/Client.php index e0e47f01..9235d2de 100644 --- a/var/IXR/Client.php +++ b/var/IXR/Client.php @@ -1,11 +1,9 @@ htmlspecialchars) - Site: http://scripts.incutio.com/xmlrpc/ - Manual: http://scripts.incutio.com/xmlrpc/manual.php - Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php -*/ + +namespace IXR; + +use Typecho\Common; +use Typecho\Http\Client as HttpClient; /** * IXR客户端 @@ -13,10 +11,10 @@ * * @package IXR */ -class IXR_Client +class Client { /** 默认客户端 */ - const DEFAULT_USERAGENT = 'The Incutio XML-RPC PHP Library(Reload By Typecho)'; + private const DEFAULT_USERAGENT = 'Typecho XML-RPC PHP Library'; /** * 服务端地址 @@ -58,21 +56,12 @@ class IXR_Client */ private $useragent; - /** - * 回执结构体 - * - * @access private - * @var string - */ - private $response; - /** * 消息体 * - * @access private - * @var string + * @var Message */ - private $message = false; + private $message; /** * 调试开关 @@ -86,48 +75,53 @@ class IXR_Client * 请求前缀 * * @access private - * @var string + * @var string|null */ - private $prefix = NULL; + private $prefix = null; - // Storage place for an error message - private $error = false; + /** + * @var Error + */ + private $error; /** * 客户端构造函数 * * @access public * @param string $server 服务端地址 - * @param string $path 路径名称 + * @param string|null $path 路径名称 * @param integer $port 端口名称 - * @param string $useragent 客户端 + * @param string|null $useragent 客户端 + * @param string|null $prefix * @return void */ - public function __construct($server, $path = false, $port = 80, $useragent = self::DEFAULT_USERAGENT, $prefix = NULL) - { + public function construct( + string $server, + ?string $path = null, + int $port = 80, + string $useragent = self::DEFAULT_USERAGENT, + ?string $prefix = null + ) { if (!$path) { $this->url = $server; // Assume we have been given a Url instead $bits = parse_url($server); $this->server = $bits['host']; - $this->port = isset($bits['port']) ? $bits['port'] : 80; - $this->path = isset($bits['path']) ? $bits['path'] : '/'; + $this->port = $bits['port'] ?? 80; + $this->path = $bits['path'] ?? '/'; // Make absolutely sure we have a path if (isset($bits['query'])) { $this->path .= '?' . $bits['query']; } } else { - /** Typecho_Common */ - require_once 'Typecho/Common.php'; - - $this->url = Typecho_Common::buildUrl(array( - 'scheme' => 'http', - 'host' => $server, - 'path' => $path, - 'port' => $port - )); + $this->url = Common::buildUrl([ + 'scheme' => 'http', + 'host' => $server, + 'path' => $path, + 'port' => $port + ]); $this->server = $server; $this->path = $path; @@ -144,7 +138,7 @@ class IXR_Client * @access public * @return void */ - public function __setDebug() + public function setDebug() { $this->debug = true; } @@ -152,44 +146,44 @@ class IXR_Client /** * 执行请求 * - * @access public - * @return void + * @param string $method + * @param ...$args + * @return bool + * @throws HttpClient\Exception */ - public function __rpcCall() + private function rpcCall(string $method, ...$args): bool { - $args = func_get_args(); - $method = array_shift($args); - $request = new IXR_Request($method, $args); + $request = new Request($method, $args); $xml = $request->getXml(); - $client = Typecho_Http_Client::get(); + $client = HttpClient::get(); if (!$client) { - $this->error = new IXR_Error(-32300, 'transport error - could not open socket'); + $this->error = new Error(-32300, 'transport error - could not open socket'); return false; } $client->setHeader('Content-Type', 'text/xml') - ->setHeader('User-Agent', $this->useragent) - ->setData($xml) - ->send($this->url); + ->setHeader('User-Agent', $this->useragent) + ->setData($xml) + ->send($this->url); $contents = $client->getResponseBody(); if ($this->debug) { - echo '
'.htmlspecialchars($contents)."\n
\n\n"; + echo '
' . htmlspecialchars($contents) . "\n
\n\n"; } // Now parse what we've got back - $this->message = new IXR_Message($contents); + $this->message = new Message($contents); if (!$this->message->parse()) { // XML error - $this->error = new IXR_Error(-32700, 'parse error. not well formed'); + $this->error = new Error(-32700, 'parse error. not well formed'); return false; } // Is the message a fault? if ($this->message->messageType == 'fault') { - $this->error = new IXR_Error($this->message->faultCode, $this->message->faultString); + $this->error = new Error($this->message->faultCode, $this->message->faultString); return false; } @@ -205,40 +199,38 @@ class IXR_Client * * @access public * @param string $prefix 前缀 - * @return IXR_Client + * @return Client */ - public function __get($prefix) + public function get(string $prefix): Client { - return new IXR_Client($this->server, $this->path, $this->port, $this->useragent, $this->prefix . $prefix . '.'); + return new self($this->server, $this->path, $this->port, $this->useragent, $this->prefix . $prefix . '.'); } /** * 增加魔术特性 * by 70 * - * @access public * @return mixed + * @throws Exception */ public function __call($method, $args) { array_unshift($args, $this->prefix . $method); - $return = call_user_func_array(array($this, '__rpcCall'), $args); + $return = call_user_func_array([$this, 'rpcCall'], $args); if ($return) { - return $this->__getResponse(); + return $this->getResponse(); } else { - require_once 'IXR/Exception.php'; - throw new IXR_Exception($this->__getErrorMessage(), $this->__getErrorCode()); + throw new Exception($this->getErrorMessage(), $this->getErrorCode()); } } /** * 获得返回值 * - * @access public - * @return void + * @return mixed */ - public function __getResponse() + public function getResponse() { // methodResponses can only have one param - return that return $this->message->params[0]; @@ -247,21 +239,19 @@ class IXR_Client /** * 是否为错误 * - * @access public - * @return void + * @return bool */ - public function __isError() + public function isError(): bool { - return (is_object($this->error)); + return isset($this->error); } /** * 获取错误代码 * - * @access public - * @return void + * @return int */ - public function __getErrorCode() + private function getErrorCode(): int { return $this->error->code; } @@ -269,10 +259,9 @@ class IXR_Client /** * 获取错误消息 * - * @access public - * @return void + * @return string */ - public function __getErrorMessage() + private function getErrorMessage(): string { return $this->error->message; } diff --git a/var/IXR/Date.php b/var/IXR/Date.php index 3cf7feee..f057f3de 100644 --- a/var/IXR/Date.php +++ b/var/IXR/Date.php @@ -1,33 +1,44 @@ htmlspecialchars) - Site: http://scripts.incutio.com/xmlrpc/ - Manual: http://scripts.incutio.com/xmlrpc/manual.php - Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php -*/ + +namespace IXR; /** * IXR日期 * * @package IXR */ -class IXR_Date { - var $year; - var $month; - var $day; - var $hour; - var $minute; - var $second; - function __construct($time) { +class Date +{ + private $year; + + private $month; + + private $day; + + private $hour; + + private $minute; + + private $second; + + /** + * @param int|string $time + */ + public function __construct($time) + { // $time can be a PHP timestamp or an ISO one if (is_numeric($time)) { - $this->parseTimestamp($time); + $this->parseTimestamp(intval($time)); } else { $this->parseIso($time); } } - function parseTimestamp($timestamp) { + + /** + * @param int $timestamp + */ + private function parseTimestamp(int $timestamp) + { $this->year = date('Y', $timestamp); $this->month = date('m', $timestamp); $this->day = date('d', $timestamp); @@ -35,7 +46,12 @@ class IXR_Date { $this->minute = date('i', $timestamp); $this->second = date('s', $timestamp); } - function parseIso($iso) { + + /** + * @param string $iso + */ + private function parseIso(string $iso) + { $this->year = substr($iso, 0, 4); $this->month = substr($iso, 4, 2); $this->day = substr($iso, 6, 2); @@ -43,13 +59,28 @@ class IXR_Date { $this->minute = substr($iso, 12, 2); $this->second = substr($iso, 15, 2); } - function getIso() { - return $this->year.$this->month.$this->day.'T'.$this->hour.':'.$this->minute.':'.$this->second; + + /** + * @return string + */ + public function getIso(): string + { + return $this->year . $this->month . $this->day . 'T' . $this->hour . ':' . $this->minute . ':' . $this->second; } - function getXml() { - return ''.$this->getIso().''; + + /** + * @return string + */ + public function getXml(): string + { + return '' . $this->getIso() . ''; } - function getTimestamp() { + + /** + * @return false|int + */ + public function getTimestamp() + { return mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year); } } diff --git a/var/IXR/Error.php b/var/IXR/Error.php index cfc7aaad..ec2b1013 100644 --- a/var/IXR/Error.php +++ b/var/IXR/Error.php @@ -1,18 +1,13 @@ htmlspecialchars) - Site: http://scripts.incutio.com/xmlrpc/ - Manual: http://scripts.incutio.com/xmlrpc/manual.php - Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php -*/ + +namespace IXR; /** * IXR错误 * * @package IXR */ -class IXR_Error +class Error { /** * 错误代码 @@ -26,7 +21,7 @@ class IXR_Error * 错误消息 * * @access public - * @var string + * @var string|null */ public $message; @@ -35,10 +30,10 @@ class IXR_Error * * @access public * @param integer $code 错误代码 - * @param string $message 错误消息 + * @param string|null $message 错误消息 * @return void */ - public function __construct($code, $message) + public function __construct(int $code, ?string $message) { $this->code = $code; $this->message = $message; @@ -52,7 +47,7 @@ class IXR_Error */ public function getXml() { - $xml = << @@ -71,6 +66,5 @@ class IXR_Error EOD; - return $xml; } } diff --git a/var/IXR/Exception.php b/var/IXR/Exception.php index 682c42a2..9002a5de 100644 --- a/var/IXR/Exception.php +++ b/var/IXR/Exception.php @@ -1,17 +1,16 @@ htmlspecialchars) - Site: http://scripts.incutio.com/xmlrpc/ - Manual: http://scripts.incutio.com/xmlrpc/manual.php - Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php -*/ + +namespace IXR; + +if (!defined('__TYPECHO_ROOT_DIR__')) { + exit; +} /** * IXR异常类 * * @package IXR */ -class IXR_Exception extends Exception -{} +class Exception extends \Exception +{ +} diff --git a/var/IXR/Message.php b/var/IXR/Message.php index 933f0640..29ace229 100644 --- a/var/IXR/Message.php +++ b/var/IXR/Message.php @@ -1,57 +1,79 @@ htmlspecialchars) - Site: http://scripts.incutio.com/xmlrpc/ - Manual: http://scripts.incutio.com/xmlrpc/manual.php - Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php -*/ + +namespace IXR; /** * IXR消息 * * @package IXR */ -class IXR_Message { - var $message; - var $messageType; // methodCall / methodResponse / fault - var $faultCode; - var $faultString; - var $methodName; - var $params; +class Message +{ + /** + * @var string + */ + public $message; + + /** + * @var string + */ + public $messageType; // methodCall / methodResponse / fault + + public $faultCode; + + public $faultString; + + /** + * @var string + */ + public $methodName; + + /** + * @var array + */ + public $params = []; + // Current variable stacks - var $_arraystructs = array(); // The stack used to keep track of the current array/struct - var $_arraystructstypes = array(); // Stack keeping track of if things are structs or array - var $_currentStructName = array(); // A stack as well - var $_param; - var $_value; - var $_currentTag; - var $_currentTagContents; - // The XML parser - var $_parser; - function __construct ($message) { + private $arrayStructs = []; // The stack used to keep track of the current array/struct + + private $arrayStructsTypes = []; // Stack keeping track of if things are structs or array + + private $currentStructName = []; // A stack as well + + private $currentTagContents; + + /** + * @param string $message + */ + public function __construct(string $message) + { $this->message = $message; } - function parse() { + + /** + * @return bool + */ + public function parse(): bool + { // first remove the XML declaration - $this->message = preg_replace('/<\?xml(.*)?\?'.'>/', '', $this->message); + $this->message = preg_replace('/<\?xml(.*)?\?' . '>/', '', $this->message); if (trim($this->message) == '') { return false; } - $this->_parser = xml_parser_create(); + $parser = xml_parser_create(); // Set XML parser to take the case of tags in to account - xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false); + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false); // Set XML parser callback functions - xml_set_object($this->_parser, $this); - xml_set_element_handler($this->_parser, 'tag_open', 'tag_close'); - xml_set_character_data_handler($this->_parser, 'cdata'); - if (!xml_parse($this->_parser, $this->message)) { + xml_set_object($parser, $this); + xml_set_element_handler($parser, [$this, 'tagOpen'], [$this, 'tagClose']); + xml_set_character_data_handler($parser, [$this, 'cdata']); + if (!xml_parse($parser, $this->message)) { /* die(sprintf('XML error: %s at line %d', - xml_error_string(xml_get_error_code($this->_parser)), - xml_get_current_line_number($this->_parser))); */ + xml_error_string(xml_get_error_code($this->parser)), + xml_get_current_line_number($this->parser))); */ return false; } - xml_parser_free($this->_parser); + xml_parser_free($parser); // Grab the error messages, if any if ($this->messageType == 'fault') { $this->faultCode = $this->params[0]['faultCode']; @@ -59,9 +81,15 @@ class IXR_Message { } return true; } - function tag_open($parser, $tag, $attr) { - $this->currentTag = $tag; - switch($tag) { + + /** + * @param $parser + * @param $tag + * @param $attr + */ + private function tagOpen($parser, string $tag, $attr) + { + switch ($tag) { case 'methodCall': case 'methodResponse': case 'fault': @@ -69,94 +97,98 @@ class IXR_Message { break; /* Deal with stacks of arrays and structs */ case 'data': // data is to all intents and puposes more interesting than array - $this->_arraystructstypes[] = 'array'; - $this->_arraystructs[] = array(); + $this->arrayStructsTypes[] = 'array'; + $this->arrayStructs[] = []; break; case 'struct': - $this->_arraystructstypes[] = 'struct'; - $this->_arraystructs[] = array(); + $this->arrayStructsTypes[] = 'struct'; + $this->arrayStructs[] = []; break; } } - function cdata($parser, $cdata) { - $this->_currentTagContents .= $cdata; + + /** + * @param $parser + * @param string $cdata + */ + private function cdata($parser, string $cdata) + { + $this->currentTagContents .= $cdata; } - function tag_close($parser, $tag) { - $valueFlag = false; - switch($tag) { + + /** + * @param $parser + * @param string $tag + */ + private function tagClose($parser, string $tag) + { + switch ($tag) { case 'int': case 'i4': - $value = (int)trim($this->_currentTagContents); - $this->_currentTagContents = ''; - $valueFlag = true; + $value = (int) trim($this->currentTagContents); + $this->currentTagContents = ''; break; case 'double': - $value = (double)trim($this->_currentTagContents); - $this->_currentTagContents = ''; - $valueFlag = true; + $value = (double) trim($this->currentTagContents); + $this->currentTagContents = ''; break; case 'string': - $value = (string)trim($this->_currentTagContents); - $this->_currentTagContents = ''; - $valueFlag = true; + $value = (string)trim($this->currentTagContents); + $this->currentTagContents = ''; break; case 'dateTime.iso8601': - $value = new IXR_Date(trim($this->_currentTagContents)); + $value = new Date(trim($this->currentTagContents)); // $value = $iso->getTimestamp(); - $this->_currentTagContents = ''; - $valueFlag = true; + $this->currentTagContents = ''; break; case 'value': // "If no type is indicated, the type is string." - if (trim($this->_currentTagContents) != '') { - $value = (string)$this->_currentTagContents; - $this->_currentTagContents = ''; - $valueFlag = true; + if (trim($this->currentTagContents) != '') { + $value = (string) $this->currentTagContents; + $this->currentTagContents = ''; } break; case 'boolean': - $value = (boolean)trim($this->_currentTagContents); - $this->_currentTagContents = ''; - $valueFlag = true; + $value = (bool) trim($this->currentTagContents); + $this->currentTagContents = ''; break; case 'base64': - $value = base64_decode($this->_currentTagContents); - $this->_currentTagContents = ''; - $valueFlag = true; + $value = base64_decode($this->currentTagContents); + $this->currentTagContents = ''; break; /* Deal with stacks of arrays and structs */ case 'data': case 'struct': - $value = array_pop($this->_arraystructs); - array_pop($this->_arraystructstypes); - $valueFlag = true; + $value = array_pop($this->arrayStructs); + array_pop($this->arrayStructsTypes); break; case 'member': - array_pop($this->_currentStructName); + array_pop($this->currentStructName); break; case 'name': - $this->_currentStructName[] = trim($this->_currentTagContents); - $this->_currentTagContents = ''; + $this->currentStructName[] = trim($this->currentTagContents); + $this->currentTagContents = ''; break; case 'methodName': - $this->methodName = trim($this->_currentTagContents); - $this->_currentTagContents = ''; + $this->methodName = trim($this->currentTagContents); + $this->currentTagContents = ''; break; } - if ($valueFlag) { + if (isset($value)) { /* if (!is_array($value) && !is_object($value)) { $value = trim($value); } */ - if (count($this->_arraystructs) > 0) { + if (count($this->arrayStructs) > 0) { // Add value to struct or array - if ($this->_arraystructstypes[count($this->_arraystructstypes)-1] == 'struct') { + if ($this->arrayStructsTypes[count($this->arrayStructsTypes) - 1] == 'struct') { // Add to struct - $this->_arraystructs[count($this->_arraystructs)-1][$this->_currentStructName[count($this->_currentStructName)-1]] = $value; + $this->arrayStructs[count($this->arrayStructs) - 1] + [$this->currentStructName[count($this->currentStructName) - 1]] = $value; } else { // Add to array - $this->_arraystructs[count($this->_arraystructs)-1][] = $value; + $this->arrayStructs[count($this->arrayStructs) - 1][] = $value; } } else { // Just add as a paramater diff --git a/var/IXR/Request.php b/var/IXR/Request.php index 12057ecd..4ef77845 100644 --- a/var/IXR/Request.php +++ b/var/IXR/Request.php @@ -1,43 +1,55 @@ htmlspecialchars) - Site: http://scripts.incutio.com/xmlrpc/ - Manual: http://scripts.incutio.com/xmlrpc/manual.php - Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php -*/ + +namespace IXR; /** * IXR请求体 * * @package IXR */ -class IXR_Request { - var $method; - var $args; - var $xml; - function __construct($method, $args) { - $this->method = $method; - $this->args = $args; +class Request +{ + /** + * @var string + */ + private $xml; + + /** + * @param string $method + * @param array $args + */ + public function __construct(string $method, array $args) + { $this->xml = << -{$this->method} +{$method} EOD; - foreach ($this->args as $arg) { + foreach ($args as $arg) { $this->xml .= ''; - $v = new IXR_Value($arg); + $v = new Value($arg); $this->xml .= $v->getXml(); $this->xml .= "\n"; } + $this->xml .= ''; } - function getLength() { + + /** + * @return int + */ + public function getLength(): int + { return strlen($this->xml); } - function getXml() { + + /** + * @return string + */ + public function getXml(): string + { return $this->xml; } } diff --git a/var/IXR/Server.php b/var/IXR/Server.php index b3d47a2b..3b3f069c 100644 --- a/var/IXR/Server.php +++ b/var/IXR/Server.php @@ -1,42 +1,20 @@ htmlspecialchars) - Site: http://scripts.incutio.com/xmlrpc/ - Manual: http://scripts.incutio.com/xmlrpc/manual.php - Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php -*/ + +namespace IXR; /** * IXR服务器 * * @package IXR */ -class IXR_Server +class Server { - /** - * 输入参数 - * - * @access private - * @var array - */ - private $data; - /** * 回调函数 * - * @access private * @var array */ - private $callbacks = array(); - - /** - * 消息体 - * - * @access private - * @var IXR_Message - */ - private $message; + private $callbacks; /** * 默认参数 @@ -49,234 +27,23 @@ class IXR_Server /** * 构造函数 * - * @access public - * @param mixed $callbacks 回调函数 - * @param mixed $data 输入参数 - * @return void + * @param array $callbacks 回调函数 */ - public function __construct($callbacks = false, $data = false) + public function __construct(array $callbacks = []) { $this->setCapabilities(); - if ($callbacks) { - $this->callbacks = $callbacks; - } + $this->callbacks = $callbacks; $this->setCallbacks(); - $this->serve($data); - } - - /** - * 呼叫内部方法 - * - * @access private - * @param string $methodname 方法名 - * @param mixed $args 参数 - * @return mixed - */ - private function call($methodname, $args) - { - // hook - if (0 !== strpos($methodname, 'hook.') && $this->hasMethod('hook.beforeCall')) { - $this->call('hook.beforeCall', array($methodname)); - } - - if (!$this->hasMethod($methodname)) { - return new IXR_Error(-32601, 'server error. requested method '.$methodname.' does not exist.'); - } - $method = $this->callbacks[$methodname]; - - // Are we dealing with a function or a method? - if (is_string($method) && substr($method, 0, 5) == 'this:') { - // It's a class method - check it exists - $method = substr($method, 5); - if (!method_exists($this, $method)) { - return new IXR_Error(-32601, 'server error. requested class method "'.$method.'" does not exist.'); - } - // Call the method - $result = $this->$method($args); - } else { - if (is_array($method)) { - list($object, $func) = $method; - if (!is_callable($method)) { - return new IXR_Error(-32601, 'server error. requested class method "'.$object . '.' . $func.'" does not exist.'); - } - - $result = call_user_func_array(array($object, $func), $args); - } elseif (!function_exists($method)) { - // It's a function - does it exist? - return new IXR_Error(-32601, 'server error. requested function "'.$method.'" does not exist.'); - } else { - // Call the function - $result = $method($args); - } - } - - // hook - if (0 !== strpos($methodname, 'hook.') && $this->hasMethod('hook.afterCall')) { - $this->call('hook.afterCall', array($methodname)); - } - - return $result; - } - - /** - * 抛出错误 - * - * @access private - * @param integer $error 错误代码 - * @param string $message 错误消息 - * @return void - */ - private function error($error, $message = false) - { - // Accepts either an error object or an error code and message - if ($message && !is_object($error)) { - $error = new IXR_Error($error, $message); - } - $this->output($error->getXml()); - } - - /** - * 输出xml - * - * @access private - * @param string $xml 输出xml - * @return 输出xml - */ - private function output($xml) - { - $xml = ''."\n".$xml; - $length = strlen($xml); - header('Connection: close'); - header('Content-Length: '.$length); - header('Content-Type: text/xml'); - header('Date: '.date('r')); - echo $xml; - exit; - } - - /** - * 是否存在方法 - * - * @access private - * @param string $method 方法名 - * @return mixed - */ - private function hasMethod($method) - { - return in_array($method, array_keys($this->callbacks)); - } - - /** - * 设置默认参数 - * - * @access public - * @return void - */ - private function setCapabilities() - { - // Initialises capabilities array - $this->capabilities = array( - 'xmlrpc' => array( - 'specUrl' => 'http://www.xmlrpc.com/spec', - 'specVersion' => 1 - ), - 'faults_interop' => array( - 'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php', - 'specVersion' => 20010516 - ), - 'system.multicall' => array( - 'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208', - 'specVersion' => 1 - ), - ); - } - - /** - * 设置默认方法 - * - * @access private - * @return void - */ - private function setCallbacks() - { - $this->callbacks['system.getCapabilities'] = 'this:getCapabilities'; - $this->callbacks['system.listMethods'] = 'this:listMethods'; - $this->callbacks['system.multicall'] = 'this:multiCall'; - } - - /** - * 服务入口 - * - * @access private - * @param mixed $data 输入参数 - * @return void - */ - private function serve($data = false) - { - if (!isset($GLOBALS['HTTP_RAW_POST_DATA'])) { - $GLOBALS['HTTP_RAW_POST_DATA'] = file_get_contents("php://input"); - } - if (isset($GLOBALS['HTTP_RAW_POST_DATA'])) { - $GLOBALS['HTTP_RAW_POST_DATA'] = trim($GLOBALS['HTTP_RAW_POST_DATA']); - } - - if (!$data) { - global $HTTP_RAW_POST_DATA; - if (!$HTTP_RAW_POST_DATA) { - die('XML-RPC server accepts POST requests only.'); - } - $data = $HTTP_RAW_POST_DATA; - } - $this->message = new IXR_Message($data); - if (!$this->message->parse()) { - $this->error(-32700, 'parse error. not well formed'); - } - if ($this->message->messageType != 'methodCall') { - $this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall'); - } - - if (0 === strpos($this->message->methodName, 'hook.')) { - die('THIS METHOD MUST BE CALLED INSIDE.'); - } - - $result = $this->call($this->message->methodName, $this->message->params); - // Is the result an error? - if (is_a($result, 'IXR_Error')) { - $this->error($result); - } - // Encode the result - $r = new IXR_Value($result); - $resultxml = $r->getXml(); - // Create the XML - $xml = << - - - - $resultxml - - - - - -EOD; - // hook - if ($this->hasMethod('hook.beforeOutput')) { - $this->call('hook.beforeOutput', array()); - } - - // Send it - $this->output($xml); + $this->serve(); } /** * 获取默认参数 * * @access public - * @param mixed $args 输入参数 * @return array */ - public function getCapabilities($args) + public function getCapabilities(): array { return $this->capabilities; } @@ -285,10 +52,9 @@ EOD; * 列出所有方法 * * @access public - * @param mixed $args 输入参数 - * @return mixed + * @return array */ - public function listMethods($args) + public function listMethods(): array { // Returns a list of methods - uses array_reverse to ensure user defined // methods are listed before server defined methods @@ -305,24 +71,175 @@ EOD; public function multiCall($methodcalls) { // See http://www.xmlrpc.com/discuss/msgReader$1208 - $return = array(); + $return = []; foreach ($methodcalls as $call) { $method = $call['methodName']; $params = $call['params']; if ($method == 'system.multicall') { - $result = new IXR_Error(-32600, 'Recursive calls to system.multicall are forbidden'); + $result = new Error(-32600, 'Recursive calls to system.multicall are forbidden'); } else { $result = $this->call($method, $params); } - if (is_a($result, 'IXR_Error')) { - $return[] = array( - 'faultCode' => $result->code, + if (is_a($result, 'Error')) { + $return[] = [ + 'faultCode' => $result->code, 'faultString' => $result->message - ); + ]; } else { - $return[] = array($result); + $return[] = [$result]; } } return $return; } + + /** + * 呼叫内部方法 + * + * @param string $methodName 方法名 + * @param array $args 参数 + * @return mixed + */ + private function call(string $methodName, array $args) + { + if (!$this->hasMethod($methodName)) { + return new Error(-32601, 'server error. requested method ' . $methodName . ' does not exist.'); + } + $method = $this->callbacks[$methodName]; + + if (!is_callable($method)) { + return new Error( + -32601, + 'server error. requested class method "' . $methodName . '" does not exist.' + ); + } + + return call_user_func_array($method, $args); + } + + /** + * 抛出错误 + * + * @access private + * @param integer|Error $error 错误代码 + * @param string|null $message 错误消息 + * @return void + */ + private function error($error, ?string $message = null) + { + // Accepts either an error object or an error code and message + if (!$error instanceof Error) { + $error = new Error($error, $message); + } + + $this->output($error->getXml()); + } + + /** + * 输出xml + * + * @access private + * @param string $xml 输出xml + */ + private function output(string $xml) + { + $xml = '' . "\n" . $xml; + $length = strlen($xml); + header('Connection: close'); + header('Content-Length: ' . $length); + header('Content-Type: text/xml'); + header('Date: ' . date('r')); + echo $xml; + exit; + } + + /** + * 是否存在方法 + * + * @access private + * @param string $method 方法名 + * @return mixed + */ + private function hasMethod(string $method) + { + return in_array($method, array_keys($this->callbacks)); + } + + /** + * 设置默认参数 + * + * @access public + * @return void + */ + private function setCapabilities() + { + // Initialises capabilities array + $this->capabilities = [ + 'xmlrpc' => [ + 'specUrl' => 'http://www.xmlrpc.com/spec', + 'specVersion' => 1 + ], + 'faults_interop' => [ + 'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php', + 'specVersion' => 20010516 + ], + 'system.multicall' => [ + 'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208', + 'specVersion' => 1 + ], + ]; + } + + /** + * 设置默认方法 + * + * @access private + * @return void + */ + private function setCallbacks() + { + $this->callbacks['system.getCapabilities'] = [$this, 'getCapabilities']; + $this->callbacks['system.listMethods'] = [$this, 'listMethods']; + $this->callbacks['system.multicall'] = [$this, 'multiCall']; + } + + /** + * 服务入口 + */ + private function serve() + { + $message = new Message(file_get_contents('php://input') ?: ''); + + if (!$message->parse()) { + $this->error(-32700, 'parse error. not well formed'); + } elseif ($message->messageType != 'methodCall') { + $this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall'); + } + + $result = $this->call($message->methodName, $message->params); + // Is the result an error? + if ($result instanceof Error) { + $this->error($result); + } + + // Encode the result + $r = new Value($result); + $resultXml = $r->getXml(); + + // Create the XML + $xml = << + + + + $resultXml + + + + + +EOD; + + // Send it + $this->output($xml); + } } diff --git a/var/IXR/Value.php b/var/IXR/Value.php index 676ab0ee..e147493a 100644 --- a/var/IXR/Value.php +++ b/var/IXR/Value.php @@ -1,21 +1,24 @@ htmlspecialchars) - Site: http://scripts.incutio.com/xmlrpc/ - Manual: http://scripts.incutio.com/xmlrpc/manual.php - Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php -*/ + +namespace IXR; /** * IXR值 * * @package IXR */ -class IXR_Value { - var $data; - var $type; - function __construct ($data, $type = false) { +class Value +{ + private $data; + + private $type; + + /** + * @param mixed $data + * @param bool|string $type + */ + public function __construct($data, $type = false) + { $this->data = $data; if (!$type) { $type = $this->calculateType(); @@ -24,16 +27,62 @@ class IXR_Value { if ($type == 'struct') { /* Turn all the values in the array in to new IXR_Value objects */ foreach ($this->data as $key => $value) { - $this->data[$key] = new IXR_Value($value); + $this->data[$key] = new Value($value); } } if ($type == 'array') { for ($i = 0, $j = count($this->data); $i < $j; $i++) { - $this->data[$i] = new IXR_Value($this->data[$i]); + $this->data[$i] = new Value($this->data[$i]); } } } - function calculateType() { + + public function getXml(): string + { + /* Return XML for this value */ + switch ($this->type) { + case 'boolean': + return '' . (($this->data) ? '1' : '0') . ''; + break; + case 'int': + return '' . $this->data . ''; + break; + case 'double': + return '' . $this->data . ''; + break; + case 'string': + return '' . htmlspecialchars($this->data) . ''; + break; + case 'array': + $return = '' . "\n"; + foreach ($this->data as $item) { + $return .= ' ' . $item->getXml() . "\n"; + } + $return .= ''; + return $return; + break; + case 'struct': + $return = '' . "\n"; + foreach ($this->data as $name => $value) { + $return .= " $name"; + $return .= $value->getXml() . "\n"; + } + $return .= ''; + return $return; + break; + case 'date': + case 'base64': + return $this->data->getXml(); + break; + } + return false; + } + + /** + * @return string + */ + private function calculateType(): string + { if ($this->data === true || $this->data === false) { return 'boolean'; } @@ -52,7 +101,6 @@ class IXR_Value { } // If it is a normal PHP object convert it in to a struct if (is_object($this->data)) { - $this->data = get_object_vars($this->data); return 'struct'; } @@ -66,46 +114,9 @@ class IXR_Value { return 'array'; } } - function getXml() { - /* Return XML for this value */ - switch ($this->type) { - case 'boolean': - return ''.(($this->data) ? '1' : '0').''; - break; - case 'int': - return ''.$this->data.''; - break; - case 'double': - return ''.$this->data.''; - break; - case 'string': - return ''.htmlspecialchars($this->data).''; - break; - case 'array': - $return = ''."\n"; - foreach ($this->data as $item) { - $return .= ' '.$item->getXml()."\n"; - } - $return .= ''; - return $return; - break; - case 'struct': - $return = ''."\n"; - foreach ($this->data as $name => $value) { - $return .= " $name"; - $return .= $value->getXml()."\n"; - } - $return .= ''; - return $return; - break; - case 'date': - case 'base64': - return $this->data->getXml(); - break; - } - return false; - } - function isStruct($array) { + + private function isStruct($array): bool + { /* Nasty function to check if an array is a struct or not */ $expected = 0; foreach ($array as $key => $value) { diff --git a/var/Typecho/Cookie.php b/var/Typecho/Cookie.php index d1c18856..162f7df1 100644 --- a/var/Typecho/Cookie.php +++ b/var/Typecho/Cookie.php @@ -1,13 +1,6 @@ timeStamp = (NULL === $time ? self::time() : $time) + (self::$timezoneOffset - self::$serverTimezoneOffset); + $this->timeStamp = (null === $time ? self::time() : $time) + + (self::$timezoneOffset - self::$serverTimezoneOffset); } /** @@ -90,7 +93,7 @@ class Typecho_Date */ public function word(): string { - return Typecho_I18n::dateWord($this->timeStamp, self::time() + (self::$timezoneOffset - self::$serverTimezoneOffset)); + return I18n::dateWord($this->timeStamp, self::time() + (self::$timezoneOffset - self::$serverTimezoneOffset)); } /** diff --git a/var/Typecho/Feed.php b/var/Typecho/Feed.php index d91de5c2..ed0fcd54 100644 --- a/var/Typecho/Feed.php +++ b/var/Typecho/Feed.php @@ -1,43 +1,31 @@ - * @category typecho - * @package Feed - * @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org) - * @license GNU General Public License 2.0 - * @version $Id: Feed.php 219 2008-05-27 09:06:15Z magike.net $ - */ + +namespace Typecho; /** * Typecho_Feed * - * @author qining - * @category typecho * @package Feed - * @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org) - * @license GNU General Public License 2.0 */ -class Typecho_Feed +class Feed { /** 定义RSS 1.0类型 */ - const RSS1 = 'RSS 1.0'; + public const RSS1 = 'RSS 1.0'; /** 定义RSS 2.0类型 */ - const RSS2 = 'RSS 2.0'; + public const RSS2 = 'RSS 2.0'; /** 定义ATOM 1.0类型 */ - const ATOM1 = 'ATOM 1.0'; + public const ATOM1 = 'ATOM 1.0'; /** 定义RSS时间格式 */ - const DATE_RFC822 = 'r'; + public const DATE_RFC822 = 'r'; /** 定义ATOM时间格式 */ - const DATE_W3CDTF = 'c'; + public const DATE_W3CDTF = 'c'; /** 定义行结束符 */ - const EOL = "\n"; + public const EOL = "\n"; /** * feed状态 @@ -45,7 +33,7 @@ class Typecho_Feed * @access private * @var string */ - private $_type; + private $type; /** * 字符集编码 @@ -53,7 +41,7 @@ class Typecho_Feed * @access private * @var string */ - private $_charset; + private $charset; /** * 语言状态 @@ -61,7 +49,7 @@ class Typecho_Feed * @access private * @var string */ - private $_lang; + private $lang; /** * 聚合地址 @@ -69,7 +57,7 @@ class Typecho_Feed * @access private * @var string */ - private $_feedUrl; + private $feedUrl; /** * 基本地址 @@ -77,7 +65,7 @@ class Typecho_Feed * @access private * @var string */ - private $_baseUrl; + private $baseUrl; /** * 聚合标题 @@ -85,7 +73,7 @@ class Typecho_Feed * @access private * @var string */ - private $_title; + private $title; /** * 聚合副标题 @@ -93,7 +81,7 @@ class Typecho_Feed * @access private * @var string */ - private $_subTitle; + private $subTitle; /** * 版本信息 @@ -101,7 +89,7 @@ class Typecho_Feed * @access private * @var string */ - private $_version; + private $version; /** * 所有的items @@ -109,7 +97,7 @@ class Typecho_Feed * @access private * @var array */ - private $_items = []; + private $items = []; /** * 创建Feed对象 @@ -119,10 +107,10 @@ class Typecho_Feed */ public function __construct($version, $type = self::RSS2, $charset = 'UTF-8', $lang = 'en') { - $this->_version = $version; - $this->_type = $type; - $this->_charset = $charset; - $this->_lang = $lang; + $this->version = $version; + $this->type = $type; + $this->charset = $charset; + $this->lang = $lang; } /** @@ -136,7 +124,7 @@ class Typecho_Feed */ public function setTitle(string $title) { - $this->_title = $title; + $this->title = $title; } /** @@ -150,7 +138,7 @@ class Typecho_Feed */ public function setSubTitle(string $subTitle) { - $this->_subTitle = $subTitle; + $this->subTitle = $subTitle; } /** @@ -164,7 +152,7 @@ class Typecho_Feed */ public function setFeedUrl(string $feedUrl) { - $this->_feedUrl = $feedUrl; + $this->feedUrl = $feedUrl; } /** @@ -178,7 +166,7 @@ class Typecho_Feed */ public function setBaseUrl(string $baseUrl) { - $this->_baseUrl = $baseUrl; + $this->baseUrl = $baseUrl; } /** @@ -203,7 +191,7 @@ class Typecho_Feed */ public function addItem(array $item) { - $this->_items[] = $item; + $this->items[] = $item; } /** @@ -212,11 +200,11 @@ class Typecho_Feed * @access public * @return string */ - public function __toString() + public function __toString(): string { - $result = '_charset . '"?>' . self::EOL; + $result = 'charset . '"?>' . self::EOL; - if (self::RSS1 == $this->_type) { + if (self::RSS1 == $this->type) { $result .= '' . self::EOL; $links = []; $lastUpdate = 0; - foreach ($this->_items as $item) { + foreach ($this->items as $item) { $content .= '' . self::EOL; $content .= '' . htmlspecialchars($item['title']) . '' . self::EOL; $content .= '' . $item['link'] . '' . self::EOL; @@ -244,10 +232,10 @@ xmlns:dc="http://purl.org/dc/elements/1.1/">' . self::EOL; } } - $result .= ' -' . htmlspecialchars($this->_title) . ' -' . $this->_baseUrl . ' -' . htmlspecialchars($this->_subTitle) . ' + $result .= ' +' . htmlspecialchars($this->title) . ' +' . $this->baseUrl . ' +' . htmlspecialchars($this->subTitle) . ' ' . self::EOL; @@ -260,8 +248,7 @@ xmlns:dc="http://purl.org/dc/elements/1.1/">' . self::EOL; ' . self::EOL; $result .= $content . ''; - - } else if (self::RSS2 == $this->_type) { + } elseif (self::RSS2 == $this->type) { $result .= ' $content = ''; $lastUpdate = 0; - foreach ($this->_items as $item) { + foreach ($this->items as $item) { $content .= '' . self::EOL; $content .= '' . htmlspecialchars($item['title']) . '' . self::EOL; $content .= '' . $item['link'] . '' . self::EOL; $content .= '' . $item['link'] . '' . self::EOL; $content .= '' . $this->dateFormat($item['date']) . '' . self::EOL; - $content .= '' . htmlspecialchars($item['author']->screenName) . '' . self::EOL; + $content .= '' . htmlspecialchars($item['author']->screenName) + . '' . self::EOL; if (!empty($item['category']) && is_array($item['category'])) { foreach ($item['category'] as $category) { @@ -288,11 +276,12 @@ xmlns:wfw="http://wellformedweb.org/CommentAPI/"> } if (!empty($item['excerpt'])) { - $content .= '' . self::EOL; + $content .= '' . self::EOL; } if (!empty($item['content'])) { - $content .= 'lang . '">' . self::EOL; @@ -318,28 +307,27 @@ xmlns:wfw="http://wellformedweb.org/CommentAPI/"> } } - $result .= '' . htmlspecialchars($this->_title) . ' -' . $this->_baseUrl . ' - -' . $this->_lang . ' -' . htmlspecialchars($this->_subTitle) . ' + $result .= '' . htmlspecialchars($this->title) . ' +' . $this->baseUrl . ' + +' . $this->lang . ' +' . htmlspecialchars($this->subTitle) . ' ' . $this->dateFormat($lastUpdate) . ' ' . $this->dateFormat($lastUpdate) . '' . self::EOL; $result .= $content . ' '; - - } else if (self::ATOM1 == $this->_type) { + } elseif (self::ATOM1 == $this->type) { $result .= '' . self::EOL; $content = ''; $lastUpdate = 0; - foreach ($this->_items as $item) { + foreach ($this->items as $item) { $content .= '' . self::EOL; $content .= '<![CDATA[' . $item['title'] . ']]>' . self::EOL; $content .= '' . self::EOL; @@ -353,26 +341,31 @@ xml:base="' . $this->_baseUrl . '" if (!empty($item['category']) && is_array($item['category'])) { foreach ($item['category'] as $category) { - $content .= '' . self::EOL; + $content .= '' . self::EOL; } } if (!empty($item['excerpt'])) { - $content .= '' . self::EOL; + $content .= '' . self::EOL; } if (!empty($item['content'])) { - $content .= 'lang . '">' . self::EOL; } if (isset($item['comments']) && strlen($item['comments']) > 0) { - $content .= '' . self::EOL; + $content .= '' . self::EOL; if (!empty($item['commentsFeedUrl'])) { - $content .= '' . self::EOL; + $content .= '' . self::EOL; } } @@ -387,13 +380,13 @@ xml:base="' . $this->_baseUrl . '" } } - $result .= '' . htmlspecialchars($this->_title) . ' -' . htmlspecialchars($this->_subTitle) . ' + $result .= '' . htmlspecialchars($this->title) . ' +' . htmlspecialchars($this->subTitle) . ' ' . $this->dateFormat($lastUpdate) . ' -Typecho - -' . $this->_feedUrl . ' - +Typecho + +' . $this->feedUrl . ' + '; $result .= $content . ''; } @@ -412,10 +405,12 @@ xml:base="' . $this->_baseUrl . '" */ public function dateFormat(int $stamp): string { - if (self::RSS2 == $this->_type) { + if (self::RSS2 == $this->type) { return date(self::DATE_RFC822, $stamp); - } else if (self::RSS1 == $this->_type || self::ATOM1 == $this->_type) { + } elseif (self::RSS1 == $this->type || self::ATOM1 == $this->type) { return date(self::DATE_W3CDTF, $stamp); } + + return ''; } } diff --git a/var/Typecho/I18n.php b/var/Typecho/I18n.php index 24b62bed..83bf7276 100644 --- a/var/Typecho/I18n.php +++ b/var/Typecho/I18n.php @@ -1,26 +1,23 @@ translate($string) : $string; + return self::$loaded ? self::$loaded->translate($string) : $string; } /** @@ -53,8 +50,8 @@ class Typecho_I18n private static function init() { /** GetText支持 */ - if (false === self::$_loaded && self::$_lang && file_exists(self::$_lang)) { - self::$_loaded = new Typecho_I18n_GetTextMulti(self::$_lang); + if (!isset(self::$loaded) && self::$lang && file_exists(self::$lang)) { + self::$loaded = new GetTextMulti(self::$lang); } } @@ -70,7 +67,7 @@ class Typecho_I18n public static function ngettext(string $single, string $plural, int $number): string { self::init(); - return self::$_loaded ? self::$_loaded->ngettext($single, $plural, $number) : ($number > 1 ? $plural : $single); + return self::$loaded ? self::$loaded->ngettext($single, $plural, $number) : ($number > 1 ? $plural : $single); } /** @@ -78,8 +75,8 @@ class Typecho_I18n * * @access public * - * @param string $from 起始时间 - * @param string $now 终止时间 + * @param int $from 起始时间 + * @param int $now 终止时间 * * @return string */ @@ -109,9 +106,12 @@ class Typecho_I18n } /** 如果是昨天 */ - if ($between > 0 && $between < 172800 + if ( + $between > 0 + && $between < 172800 && (date('z', $from) + 1 == date('z', $now) // 在同一年的情况 - || date('z', $from) + 1 == date('L') + 365 + date('z', $now))) { // 跨年的情况 + || date('z', $from) + 1 == date('L') + 365 + date('z', $now)) + ) { // 跨年的情况 return _t('昨天 %s', date('H:i', $from)); } @@ -140,7 +140,7 @@ class Typecho_I18n */ public static function addLang(string $lang) { - self::$_loaded->addFile($lang); + self::$loaded->addFile($lang); } /** @@ -151,7 +151,7 @@ class Typecho_I18n */ public static function getLang(): ?string { - return self::$_lang; + return self::$lang; } /** @@ -165,6 +165,6 @@ class Typecho_I18n */ public static function setLang(string $lang) { - self::$_lang = $lang; + self::$lang = $lang; } } diff --git a/var/Typecho/I18n/GetText.php b/var/Typecho/I18n/GetText.php index e084abcd..2526a953 100644 --- a/var/Typecho/I18n/GetText.php +++ b/var/Typecho/I18n/GetText.php @@ -1,4 +1,7 @@ . Copyright (c) 2005 Nico Kaiser @@ -21,21 +24,6 @@ */ -/** - * Provides a simple gettext replacement that works independently from - * the system's gettext abilities. - * It can read MO files and use them for translating strings. - * The files are passed to gettext_reader as a Stream (see streams.php) - * - * This version has the ability to cache all strings and translations to - * speed up the string lookup. - * While the cache is enabled by default, it can be switched off with the - * second parameter in the constructor (e.g. whenusing very large MO files - * that you don't want to keep in memory) - */ - -//reload by 70 (typecho group) - /** * This file is part of PHP-gettext * @@ -43,22 +31,32 @@ * @category typecho * @package I18n */ -class Typecho_I18n_GetText +class GetText { //public: public $error = 0; // public variable that holds error code (0 if no error) //private: - private $BYTEORDER = 0; // 0: low endian, 1: big endian + private $BYTE_ORDER = 0; // 0: low endian, 1: big endian + private $STREAM = null; + private $short_circuit = false; + private $enable_cache = false; + private $originals = null; // offset of original table + private $translations = null; // offset of translation table - private $pluralheader = null; // cache header field for plural forms + + private $pluralHeader = null; // cache header field for plural forms + private $total = 0; // total string count + private $table_originals = null; // table for original strings (offsets) + private $table_translations = null; // table for translated strings (offsets) + private $cache_translations = null; // original -> translation mapping @@ -69,7 +67,7 @@ class Typecho_I18n_GetText * @param string $file file name * @param boolean enable_cache Enable or disable caching of strings (default on) */ - public function __construct($file, $enable_cache = true) + public function __construct(string $file, $enable_cache = true) { // If there isn't a StreamReader, turn on short circuit mode. if (!file_exists($file)) { @@ -84,21 +82,114 @@ class Typecho_I18n_GetText $unpacked = unpack('c', $this->read(4)); $magic = array_shift($unpacked); - if (- 34 == $magic) { - $this->BYTEORDER = 0; - } elseif (- 107 == $magic) { - $this->BYTEORDER = 1; + if (-34 == $magic) { + $this->BYTE_ORDER = 0; + } elseif (-107 == $magic) { + $this->BYTE_ORDER = 1; } else { $this->error = 1; // not MO file return false; } // FIXME: Do we care about revision? We should. - $revision = $this->readint(); + $revision = $this->readInt(); - $this->total = $this->readint(); - $this->originals = $this->readint(); - $this->translations = $this->readint(); + $this->total = $this->readInt(); + $this->originals = $this->readInt(); + $this->translations = $this->readInt(); + } + + /** + * Translates a string + * + * @access public + * @param string string to be translated + * @param integer|null $num found string number + * @return string translated string (or original, if not found) + */ + public function translate($string, ?int &$num): string + { + if ($this->short_circuit) { + return $string; + } + $this->loadTables(); + + if ($this->enable_cache) { + // Caching enabled, get translated string from cache + if (array_key_exists($string, $this->cache_translations)) { + return $this->cache_translations[$string]; + } else { + return $string; + } + } else { + // Caching not enabled, try to find string + $num = $this->findString($string); + if ($num == -1) { + return $string; + } else { + return $this->getTranslationString($num); + } + } + } + + /** + * Plural version of gettext + * + * @access public + * @param string single + * @param string plural + * @param string number + * @param integer|null $num found string number + * @return string plural form + */ + public function ngettext($single, $plural, $number, ?int &$num): string + { + $number = intval($number); + + if ($this->short_circuit) { + if ($number != 1) { + return $plural; + } else { + return $single; + } + } + + // find out the appropriate form + $select = $this->selectString($number); + + // this should contains all strings separated by NULLs + $key = $single . chr(0) . $plural; + + + if ($this->enable_cache) { + if (!array_key_exists($key, $this->cache_translations)) { + return ($number != 1) ? $plural : $single; + } else { + $result = $this->cache_translations[$key]; + $list = explode(chr(0), $result); + return $list[$select]; + } + } else { + $num = $this->findString($key); + if ($num == -1) { + return ($number != 1) ? $plural : $single; + } else { + $result = $this->getTranslationString($num); + $list = explode(chr(0), $result); + return $list[$select]; + } + } + } + + /** + * 关闭文件句柄 + * + * @access public + * @return void + */ + public function __destruct() + { + fclose($this->STREAM); } /** @@ -106,7 +197,7 @@ class Typecho_I18n_GetText * * @param mixed $count * @access private - * @return void + * @return false|string */ private function read($count) { @@ -116,7 +207,7 @@ class Typecho_I18n_GetText return fread($this->STREAM, $count); } - return null; + return false; } /** @@ -125,42 +216,12 @@ class Typecho_I18n_GetText * @access private * @return Integer from the Stream */ - private function readint() + private function readInt(): int { - $end = unpack($this->BYTEORDER == 0 ? 'V' : 'N', $this->read(4)); + $end = unpack($this->BYTE_ORDER == 0 ? 'V' : 'N', $this->read(4)); return array_shift($end); } - /** - * Translates a string - * - * @access public - * @param string string to be translated - * @param integer $num found string number - * @return string translated string (or original, if not found) - */ - public function translate($string, &$num) - { - if ($this->short_circuit) - return $string; - $this->load_tables(); - - if ($this->enable_cache) { - // Caching enabled, get translated string from cache - if (array_key_exists($string, $this->cache_translations)) - return $this->cache_translations[$string]; - else - return $string; - } else { - // Caching not enabled, try to find string - $num = $this->find_string($string); - if ($num == - 1) - return $string; - else - return $this->get_translation_string($num); - } - } - /** * Loads the translation tables from the MO file into the cache * If caching is enabled, also loads all strings into a cache @@ -168,23 +229,26 @@ class Typecho_I18n_GetText * * @access private */ - private function load_tables() + private function loadTables() { - if (is_array($this->cache_translations) && + if ( + is_array($this->cache_translations) && is_array($this->table_originals) && - is_array($this->table_translations)) + is_array($this->table_translations) + ) { return; + } /* get original and translations tables */ fseek($this->STREAM, $this->originals); - $this->table_originals = $this->readintarray($this->total * 2); + $this->table_originals = $this->readIntArray($this->total * 2); fseek($this->STREAM, $this->translations); - $this->table_translations = $this->readintarray($this->total * 2); + $this->table_translations = $this->readIntArray($this->total * 2); if ($this->enable_cache) { $this->cache_translations = ['' => null]; /* read all strings in the cache */ - for ($i = 0; $i < $this->total; $i ++) { + for ($i = 0; $i < $this->total; $i++) { if ($this->table_originals[$i * 2 + 1] > 0) { fseek($this->STREAM, $this->table_originals[$i * 2 + 2]); $original = fread($this->STREAM, $this->table_originals[$i * 2 + 1]); @@ -200,11 +264,11 @@ class Typecho_I18n_GetText * Reads an array of Integers from the Stream * * @param int count How many elements should be read - * @return Array of Integers + * @return array of Integers */ - private function readintarray($count) + private function readIntArray($count): array { - return unpack(($this->BYTEORDER == 0 ? 'V' : 'N') . $count, $this->read(4 * $count)); + return unpack(($this->BYTE_ORDER == 0 ? 'V' : 'N') . $count, $this->read(4 * $count)); } /** @@ -216,36 +280,37 @@ class Typecho_I18n_GetText * @param int end (internally used in recursive function) * @return int string number (offset in originals table) */ - private function find_string($string, $start = - 1, $end = - 1) + private function findString($string, $start = -1, $end = -1): int { - if (($start == - 1) or ($end == - 1)) { - // find_string is called with only one parameter, set start end end + if (($start == -1) or ($end == -1)) { + // findString is called with only one parameter, set start end end $start = 0; $end = $this->total; } if (abs($start - $end) <= 1) { // We're done, now we either found the string, or it doesn't exist - $txt = $this->get_original_string($start); - if ($string == $txt) + $txt = $this->getOriginalString($start); + if ($string == $txt) { return $start; - else - return - 1; + } else { + return -1; + } } elseif ($start > $end) { // start > end -> turn around and start over - return $this->find_string($string, $end, $start); + return $this->findString($string, $end, $start); } else { // Divide table in two parts $half = (int)(($start + $end) / 2); - $cmp = strcmp($string, $this->get_original_string($half)); - if ($cmp == 0) + $cmp = strcmp($string, $this->getOriginalString($half)); + if ($cmp == 0) { // string is exactly in the middle => return it return $half; - elseif ($cmp < 0) + } elseif ($cmp < 0) { // The string is in the upper half - return $this->find_string($string, $start, $half); - else - // The string is in the lower half - return $this->find_string($string, $half, $end); + return $this->findString($string, $start, $half); + } else { // The string is in the lower half + return $this->findString($string, $half, $end); + } } } @@ -256,12 +321,13 @@ class Typecho_I18n_GetText * @param int num Offset number of original string * @return string Requested string if found, otherwise '' */ - private function get_original_string($num) + private function getOriginalString($num): string { $length = $this->table_originals[$num * 2 + 1]; $offset = $this->table_originals[$num * 2 + 2]; - if (!$length) + if (!$length) { return ''; + } fseek($this->STREAM, $offset); $data = fread($this->STREAM, $length); return (string)$data; @@ -274,65 +340,18 @@ class Typecho_I18n_GetText * @param int num Offset number of original string * @return string Requested string if found, otherwise '' */ - private function get_translation_string($num) + private function getTranslationString($num): string { $length = $this->table_translations[$num * 2 + 1]; $offset = $this->table_translations[$num * 2 + 2]; - if (!$length) + if (!$length) { return ''; + } fseek($this->STREAM, $offset); $data = fread($this->STREAM, $length); return (string)$data; } - /** - * Plural version of gettext - * - * @access public - * @param string single - * @param string plural - * @param string number - * @param integer $num found string number - * @return translated plural form - */ - public function ngettext($single, $plural, $number, &$num) - { - $number = intval($number); - - if ($this->short_circuit) { - if ($number != 1) - return $plural; - else - return $single; - } - - // find out the appropriate form - $select = $this->select_string($number); - - // this should contains all strings separated by NULLs - $key = $single . chr(0) . $plural; - - - if ($this->enable_cache) { - if (!array_key_exists($key, $this->cache_translations)) { - return ($number != 1) ? $plural : $single; - } else { - $result = $this->cache_translations[$key]; - $list = explode(chr(0), $result); - return $list[$select]; - } - } else { - $num = $this->find_string($key); - if ($num == - 1) { - return ($number != 1) ? $plural : $single; - } else { - $result = $this->get_translation_string($num); - $list = explode(chr(0), $result); - return $list[$select]; - } - } - } - /** * Detects which plural form to take * @@ -340,9 +359,9 @@ class Typecho_I18n_GetText * @param n count * @return int array index of the right plural form */ - private function select_string($n) + private function selectString($n): int { - $string = $this->get_plural_forms(); + $string = $this->getPluralForms(); $string = str_replace('nplurals', "\$total", $string); $string = str_replace("n", $n, $string); $string = str_replace('plural', "\$plural", $string); @@ -351,7 +370,9 @@ class Typecho_I18n_GetText $plural = 0; eval("$string"); - if ($plural >= $total) $plural = $total - 1; + if ($plural >= $total) { + $plural = $total - 1; + } return $plural; } @@ -361,36 +382,26 @@ class Typecho_I18n_GetText * @access private * @return string plural form header */ - private function get_plural_forms() + private function getPluralForms(): string { // lets assume message number 0 is header // this is true, right? - $this->load_tables(); + $this->loadTables(); // cache header field for plural forms - if (!is_string($this->pluralheader)) { + if (!is_string($this->pluralHeader)) { if ($this->enable_cache) { $header = $this->cache_translations[""]; } else { - $header = $this->get_translation_string(0); + $header = $this->getTranslationString(0); } - if (preg_match("/plural\-forms: ([^\n]*)\n/i", $header, $regs)) + if (preg_match("/plural\-forms: ([^\n]*)\n/i", $header, $regs)) { $expr = $regs[1]; - else + } else { $expr = "nplurals=2; plural=n == 1 ? 0 : 1;"; - $this->pluralheader = $expr; + } + $this->pluralHeader = $expr; } - return $this->pluralheader; - } - - /** - * 关闭文件句柄 - * - * @access public - * @return void - */ - public function __destruct() - { - fclose($this->STREAM); + return $this->pluralHeader; } } diff --git a/var/Typecho/I18n/GetTextMulti.php b/var/Typecho/I18n/GetTextMulti.php index 0221044b..2a62515e 100644 --- a/var/Typecho/I18n/GetTextMulti.php +++ b/var/Typecho/I18n/GetTextMulti.php @@ -1,11 +1,6 @@ addFile($fileName); } @@ -44,9 +39,9 @@ class Typecho_I18n_GetTextMulti * @param string $fileName 语言文件名 * @return void */ - public function addFile($fileName) + public function addFile(string $fileName) { - $this->_handles[] = new Typecho_I18n_GetText($fileName, true); + $this->handlers[] = new GetText($fileName, true); } /** @@ -56,9 +51,9 @@ class Typecho_I18n_GetTextMulti * @param string string to be translated * @return string translated string (or original, if not found) */ - public function translate($string) + public function translate(string $string): string { - foreach ($this->_handles as $handle) { + foreach ($this->handlers as $handle) { $string = $handle->translate($string, $count); if (- 1 != $count) { break; @@ -75,14 +70,14 @@ class Typecho_I18n_GetTextMulti * @param string single * @param string plural * @param string number - * @return translated plural form + * @return string translated plural form */ - public function ngettext($single, $plural, $number) + public function ngettext($single, $plural, $number): string { $count = - 1; - foreach ($this->_handles as $handle) { - $string = $handle->ngettext($single, $plural, $number, $count); + foreach ($this->handlers as $handler) { + $string = $handler->ngettext($single, $plural, $number, $count); if (- 1 != $count) { break; } @@ -99,9 +94,9 @@ class Typecho_I18n_GetTextMulti */ public function __destruct() { - foreach ($this->_handles as $handle) { + foreach ($this->handlers as $handler) { /** 显示的释放内存 */ - unset($handle); + unset($handler); } } } diff --git a/var/Typecho/Router.php b/var/Typecho/Router.php index b8e23478..e1b56a79 100644 --- a/var/Typecho/Router.php +++ b/var/Typecho/Router.php @@ -41,13 +41,13 @@ class Router * * @access public * - * @param string $pathInfo 全路径 + * @param string|null $pathInfo 全路径 * @param mixed $parameter 输入参数 * * @return false|Widget * @throws \Exception */ - public static function match(string $pathInfo, $parameter = null) + public static function match(?string $pathInfo, $parameter = null) { foreach (self::$routingTable as $key => $route) { if (preg_match($route['regx'], $pathInfo, $matches)) {