diff --git a/scripts/make-archive.sh b/scripts/make-archive.sh index a19874e..b3b85c7 100755 --- a/scripts/make-archive.sh +++ b/scripts/make-archive.sh @@ -1,14 +1,31 @@ #!/bin/sh VERSION=$1 +APP="miniflux" cd /tmp -rm -rf /tmp/miniflux /tmp/miniflux-*.zip 2>/dev/null -git clone git@github.com:fguillot/miniflux.git -rm -rf miniflux/data/*.sqlite miniflux/.git miniflux/.gitignore miniflux/scripts miniflux/examples -find miniflux -name *.less -delete -sed -i.bak s/master/$VERSION/g miniflux/common.php && rm -f miniflux/*.bak -zip -r miniflux-$VERSION.zip miniflux -mv miniflux-*.zip ~/Devel/websites/miniflux -rm -rf /tmp/miniflux 2>/dev/null +rm -rf /tmp/$APP /tmp/$APP-*.zip 2>/dev/null +git clone --depth 1 git@github.com:fguillot/$APP.git + +rm -rf $APP/data/*.sqlite \ + $APP/.git \ + $APP/.gitignore \ + $APP/scripts \ + $APP/docs \ + $APP/README.* + +find $APP -name *.less -delete +find $APP -name *.scss -delete +find $APP -name *.rb -delete + +sed -i.bak s/master/$VERSION/g $APP/common.php && rm -f $APP/*.bak + +zip -r $APP-$VERSION.zip $APP +mv $APP-*.zip ~/Devel/websites/$APP + +cd ~/Devel/websites/$APP/ +unlink $APP-latest.zip +ln -s $APP-$VERSION.zip $APP-latest.zip + +rm -rf /tmp/$APP 2>/dev/null diff --git a/vendor/JsonRPC/Client.php b/vendor/JsonRPC/Client.php index 14fe507..65aed22 100644 --- a/vendor/JsonRPC/Client.php +++ b/vendor/JsonRPC/Client.php @@ -2,42 +2,119 @@ namespace JsonRPC; +use BadFunctionCallException; + +/** + * JsonRPC client class + * + * @package JsonRPC + * @author Frederic Guillot + * @license Unlicense http://unlicense.org/ + */ class Client { + /** + * URL of the server + * + * @access private + * @var string + */ private $url; + + /** + * HTTP client timeout + * + * @access private + * @var integer + */ private $timeout; - private $debug; + + /** + * Username for authentication + * + * @access private + * @var string + */ private $username; + + /** + * Password for authentication + * + * @access private + * @var string + */ private $password; + /** + * Enable debug output to the php error log + * + * @access public + * @var boolean + */ + public $debug = false; + + /** + * Default HTTP headers to send to the server + * + * @access private + * @var array + */ private $headers = array( 'Connection: close', 'Content-Type: application/json', 'Accept: application/json' ); - - public function __construct($url, $timeout = 5, $debug = false, $headers = array()) + /** + * Constructor + * + * @access public + * @param string $url Server URL + * @param integer $timeout Server URL + * @param array $headers Custom HTTP headers + */ + public function __construct($url, $timeout = 5, $headers = array()) { $this->url = $url; $this->timeout = $timeout; - $this->debug = $debug; $this->headers = array_merge($this->headers, $headers); } + /** + * Automatic mapping of procedures + * + * @access public + * @param string $method Procedure name + * @param array $params Procedure arguments + * @return mixed + */ public function __call($method, $params) { - return $this->execute($method, $params); } - + + /** + * Set authentication parameters + * + * @access public + * @param string $username Username + * @param string $password Password + */ public function authentication($username, $password) { $this->username = $username; $this->password = $password; } - + /** + * Execute + * + * @access public + * @throws BadFunctionCallException Exception thrown when a bad request is made (missing argument/procedure) + * @param string $procedure Procedure name + * @param array $params Procedure arguments + * @return mixed + */ public function execute($procedure, array $params = array()) { $id = mt_rand(); @@ -49,25 +126,24 @@ class Client ); if (! empty($params)) { - $payload['params'] = $params; } $result = $this->doRequest($payload); if (isset($result['id']) && $result['id'] == $id && array_key_exists('result', $result)) { - return $result['result']; } - else if ($this->debug && isset($result['error'])) { - print_r($result['error']); - } - - return null; + throw new BadFunctionCallException('Bad Request'); } - + /** + * Do the HTTP request + * + * @access public + * @param string $payload Data to send + */ public function doRequest($payload) { $ch = curl_init(); @@ -83,13 +159,17 @@ class Client curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload)); if ($this->username && $this->password) { - curl_setopt($ch, CURLOPT_USERPWD, $this->username.':'.$this->password); } $result = curl_exec($ch); $response = json_decode($result, true); + if ($this->debug) { + error_log('==> Request: '.PHP_EOL.json_encode($payload, JSON_PRETTY_PRINT)); + error_log('==> Response: '.PHP_EOL.json_encode($response, JSON_PRETTY_PRINT)); + } + curl_close($ch); return is_array($response) ? $response : array(); diff --git a/vendor/JsonRPC/Server.php b/vendor/JsonRPC/Server.php index 24b52bd..72d4e27 100644 --- a/vendor/JsonRPC/Server.php +++ b/vendor/JsonRPC/Server.php @@ -2,18 +2,54 @@ namespace JsonRPC; +use ReflectionFunction; +use Closure; + +/** + * JsonRPC server class + * + * @package JsonRPC + * @author Frederic Guillot + * @license Unlicense http://unlicense.org/ + */ class Server { + /** + * Data received from the client + * + * @access private + * @var string + */ private $payload; + + /** + * List of procedures + * + * @static + * @access private + * @var array + */ static private $procedures = array(); - + /** + * Constructor + * + * @access public + * @param string $payload Client data + */ public function __construct($payload = '') { $this->payload = $payload; } - + /** + * IP based client restrictions + * + * Return an HTTP error 403 if the client is not allowed + * + * @access public + * @param array $hosts List of hosts + */ public function allowHosts(array $hosts) { if (! in_array($_SERVER['REMOTE_ADDR'], $hosts)) { @@ -25,7 +61,14 @@ class Server } } - + /** + * HTTP Basic authentication + * + * Return an HTTP error 401 if the client is not allowed + * + * @access public + * @param array $users Map of username/password + */ public function authentication(array $users) { // OVH workaround @@ -45,32 +88,52 @@ class Server } } - - public function register($name, \Closure $callback) + /** + * Register a new procedure + * + * @access public + * @param string $name Procedure name + * @param closure $callback Callback + */ + public function register($name, Closure $callback) { self::$procedures[$name] = $callback; } - + /** + * Unregister a procedure + * + * @access public + * @param string $name Procedure name + */ public function unregister($name) { if (isset(self::$procedures[$name])) { - unset(self::$procedures[$name]); } } - + /** + * Unregister all procedures + * + * @access public + */ public function unregisterAll() { self::$procedures = array(); } - + /** + * Return the response to the client + * + * @access public + * @param array $data Data to send to the client + * @param array $payload Incoming data + * @return string + */ public function getResponse(array $data, array $payload = array()) { if (! array_key_exists('id', $payload)) { - return ''; } @@ -81,19 +144,29 @@ class Server $response = array_merge($response, $data); - header('Content-Type: application/json'); + @header('Content-Type: application/json'); return json_encode($response); } - - public function mapParameters(array $request_params, array $method_params, array &$params) + /** + * Map arguments to the procedure + * + * @access public + * @param array $request_params Incoming arguments + * @param array $method_params Procedure arguments + * @param array $params Arguments to pass to the callback + * @param integer $nb_required_params Number of required parameters + * @return bool + */ + public function mapParameters(array $request_params, array $method_params, array &$params, $nb_required_params) { + if (count($request_params) < $nb_required_params) { + return false; + } + // Positional parameters if (array_keys($request_params) === range(0, count($request_params) - 1)) { - - if (count($request_params) !== count($method_params)) return false; $params = $request_params; - return true; } @@ -103,11 +176,12 @@ class Server $name = $p->getName(); if (isset($request_params[$name])) { - $params[$name] = $request_params[$name]; - } else if ($p->isDefaultValueAvailable()) { - continue; - } else { + } + else if ($p->isDefaultValueAvailable()) { + $params[$name] = $p->getDefaultValue(); + } + else { return false; } } @@ -115,23 +189,102 @@ class Server return true; } - - public function execute() + /** + * Parse the payload and test if the parsed JSON is ok + * + * @access public + * @return boolean + */ + public function isValidJsonFormat() { - // Parse payload if (empty($this->payload)) { - $this->payload = file_get_contents('php://input'); } if (is_string($this->payload)) { - $this->payload = json_decode($this->payload, true); } - // Check JSON format - if (! is_array($this->payload)) { + return is_array($this->payload); + } + /** + * Test if all required JSON-RPC parameters are here + * + * @access public + * @return boolean + */ + public function isValidJsonRpcFormat() + { + if (! isset($this->payload['jsonrpc']) || + ! isset($this->payload['method']) || + ! is_string($this->payload['method']) || + $this->payload['jsonrpc'] !== '2.0' || + (isset($this->payload['params']) && ! is_array($this->payload['params']))) { + + return false; + } + + return true; + } + + /** + * Return true if we have a batch request + * + * @access public + * @return boolean + */ + private function isBatchRequest() + { + return array_keys($this->payload) === range(0, count($this->payload) - 1); + } + + /** + * Handle batch request + * + * @access private + * @return string + */ + private function handleBatchRequest() + { + $responses = array(); + + foreach ($this->payload as $payload) { + + if (! is_array($payload)) { + + $responses[] = $this->getResponse(array( + 'error' => array( + 'code' => -32600, + 'message' => 'Invalid Request' + )), + array('id' => null) + ); + } + else { + + $server = new Server($payload); + $response = $server->execute(); + + if ($response) { + $responses[] = $response; + } + } + } + + return empty($responses) ? '' : '['.implode(',', $responses).']'; + } + + /** + * Parse incoming requests + * + * @access public + * @return string + */ + public function execute() + { + // Invalid Json + if (! $this->isValidJsonFormat()) { return $this->getResponse(array( 'error' => array( 'code' => -32700, @@ -142,40 +295,12 @@ class Server } // Handle batch request - if (array_keys($this->payload) === range(0, count($this->payload) - 1)) { - - $responses = array(); - - foreach ($this->payload as $payload) { - - if (! is_array($payload)) { - - $responses[] = $this->getResponse(array( - 'error' => array( - 'code' => -32600, - 'message' => 'Invalid Request' - )), - array('id' => null) - ); - } - else { - - $server = new Server($payload); - $response = $server->execute(); - - if ($response) $responses[] = $response; - } - } - - return empty($responses) ? '' : '['.implode(',', $responses).']'; + if ($this->isBatchRequest()){ + return $this->handleBatchRequest(); } - // Check JSON-RPC format - if (! isset($this->payload['jsonrpc']) || - ! isset($this->payload['method']) || - ! is_string($this->payload['method']) || - $this->payload['jsonrpc'] !== '2.0' || - (isset($this->payload['params']) && ! is_array($this->payload['params']))) { + // Invalid JSON-RPC format + if (! $this->isValidJsonRpcFormat()) { return $this->getResponse(array( 'error' => array( @@ -198,16 +323,17 @@ class Server ); } + // Execute the procedure $callback = self::$procedures[$this->payload['method']]; $params = array(); - $reflection = new \ReflectionFunction($callback); + $reflection = new ReflectionFunction($callback); if (isset($this->payload['params'])) { $parameters = $reflection->getParameters(); - if (! $this->mapParameters($this->payload['params'], $parameters, $params)) { + if (! $this->mapParameters($this->payload['params'], $parameters, $params, $reflection->getNumberOfRequiredParameters())) { return $this->getResponse(array( 'error' => array(