/4.9/components/com_rest/rest.class.php
PHP | 336 lines | 188 code | 33 blank | 115 comment | 35 complexity | 6b2e3f2099d1182354de12d880107b24 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0, LGPL-2.0
- <?php
- /**
- * @package mosRest
- * @author Chad Auld and Ozgur Cem Sen (code@brilaps.com)
- * @copyright Brilaps, LLC (http://brilaps.com)
- * @link http://brilaps.com || http://wiki.brilaps.com
- * @license http://www.opensource.org/licenses/gpl-license.php GNU/GPL v.2.
- */
- class mosRest extends mosDBTable {
- /** @public int Primary key */
- public $id=null;
- /** @public string */
- public $developer_name=null;
- /** @public string */
- public $product_name=null;
- /** @public string */
- public $web_app_url=null;
- /** @public string */
- public $contact_email=null;
- /** @public string */
- public $phone_number=null;
- /** @public string */
- public $description=null;
- /** @public string */
- public $activation=null;
- /** @public string */
- public $block=null;
- /** @public string */
- public $registration_date=null;
- /** @public string */
- public $approval_date=null;
- /**
- * @param database A database connector object
- */
- function mosRest() {
- global $database;
- $this->mosDBTable( '#__rest', 'id', $database );
- }
- }
- class mosRestLog extends mosDBTable {
- /** @public int Primary key */
- public $id=null;
- /** @public string */
- public $request_key=null;
- /** @public string */
- public $request_type=null;
- /** @public string */
- public $request_uri=null;
- /** @public string */
- public $request_timestamp=null;
- /**
- * @param database A database connector object
- */
- function mosRestLog() {
- global $database;
- $this->mosDBTable( '#__rest_log', 'id', $database );
- }
- }
- /**
- * This class brings RESTful functionality to the MiaCMS. This is just a base class that handles many of the
- * key items needed to implement REST. It should be used as a building block to RESTify MiaCMS components. We
- * have also released a RESTified com_content (com_rest_content). You can use that as an example to extend additional
- * components. Each component will need to implement its own data retrival routines.
- */
- class mRest {
- static $apiVersion = '1.0';
- /**
- * Handles the actual REST response
- * @param htmlReturnStatusCode - html request status code (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)
- * @param returnFormat - response format requested be user (ie) JSON, XML, PHP
- * @param data - data to be sent back
- */
- function restResponse($htmlReturnStatusCode, $returnFormat, $data) {
- //Produce the final output
- header( $this->setHtmlStatusCode($htmlReturnStatusCode) );
- header( 'Content-Type: '.$this->setReturnContentType($returnFormat).'; charset=utf-8' );
- //Force the browser to use fresh data
- header( 'Expires: Mon, 26 Jul 1997 05:00:00 GMT' );
- header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
- header( 'Cache-Control: no-store, no-cache, must-revalidate' );
- header( 'Cache-Control: post-check=0, pre-check=0', false );
- header( 'Pragma: no-cache' );
- echo $data;
- exit;
- }
- /**
- * Handles encoding of the final REST response
- * @param data - data to be encoded
- * @param returnFormat - return format requested by the client (i.e.) json, xml, or php
- * @param callback - optional JavaScript callback function to wrap request with
- */
- function encodeRestResponse($data, $returnFormat, $callback='') {
- global $mosConfig_absolute_path;
- if ($this->validateReturnFormat($returnFormat)===false) {
- $returnFormat='json'; //force json
- }
- if ($returnFormat=='json') {
- /* Handles JSON encoding using the standard PEAR class (native in later version of PHP5, but we
- want to support all v5 installs) */
- if (file_exists($mosConfig_absolute_path.'/includes/PEAR/JSON/json.php')) {
- require($mosConfig_absolute_path.'/includes/PEAR/JSON/json.php');
- } else {
- require('json.php');
- }
- $json = new Services_JSON();
- $returnData = $json->encode($data);
- //Wrap in JS callback function if requested
- if (!empty($callback)) {
- $returnData = $callback.'( '.$returnData.' )';
- }
- } else if ($returnFormat=='php') {
- $returnData = serialize($data);
- } else if ($returnFormat=='xml') {
- //We expect a fully formed XML doc so nothing else is needed in theis case
- $returnData = $data;
- }
- return $returnData;
- }
- /**
- * Verifies that the appid passed with the request is valid for tracking purposes
- * @param appId - application id assigned to developer during registration
- * @param requestType - type of request being made (ex) content, search, rank, popular, etc
- * @param uri - the full url with query params to log with request (best obtained by using the full_url() function)
- */
- function verifyRestAPIKey($appId, $requestType, $uri) {
- global $database, $mosConfig_absolute_path;
- //Include REST settings
- $log_api_requests = '';
- require($mosConfig_absolute_path.'/administrator/components/com_rest/config.rest.php');
- //Log request for tracking purposes if enabled
- if ($log_api_requests=='1') {
- $this->logAPIRequest($appId, $requestType, $uri);
- }
- $appId = $database->getEscaped($appId);
- $database->setQuery("SELECT id FROM #__rest WHERE rest_key='{$appId}'"
- . "\n AND block=0");
- if (!$database->loadResult()) {
- return false;
- }
- }
- /**
- * Used to verify the requested JSON callback function name is valid
- *
- * The following characters are allowed: A-Z, a-z, 0-9, [], and _
- * Start with a simple ctype check since it's a lighter process and more common.
- * Fall back on character checking if the whole this isn't alphanumeric
- *
- * @param callback - the requested JSON callback function name
- */
- function verifyJSONCallbackName($callbackName) {
- if (ctype_alpha($callbackName)) {
- return true;
- } else {
- $chrCount=strlen($callbackName);
- $altChars=array('[',']','_');
- for ($i=0;$i<$chrCount;$i++) {
- if ((!ctype_alnum($callbackName[$i])) && (!in_array($callbackName[$i], $altChars))) {
- return false;
- }
- }
- }
- }
- /**
- * Log API request for REST usage tracking purposes (normally called on by verifyRestAPIKey)
- * @param appId - application id assigned to developer during registration
- * @param requestType - type of request being made (ex) content, search, rank, popular, etc
- * @param uri - the full url with query params to log with request (best obtained by using the full_url() function)
- */
- function logAPIRequest($appId, $requestType, $uri) {
- global $database;
- $row = new mosRestLog( $database );
- $row->id = 0;
- $row->rest_key = $database->getEscaped($appId);
- $row->request_type = $database->getEscaped($requestType);
- $row->request_uri = $database->getEscaped($uri);
- $row->request_timestamp = date("Y-m-d H:i:s");
- if (!$row->store()) {
- die('Unable to log request: '.$row->getError());
- }
- }
- /**
- * Builds the error document used in negative responses.
- * @param errorMessage - custom message to be wrapped in the error doc
- * @param returnFormat - error doc sent back in the user defined return format
- */
- function restError($errorMessage, $returnFormat='json') {
- if ($this->validateReturnFormat($returnFormat)===false) {
- $returnFormat='json'; //force json
- }
- if ($returnFormat=='json' || $returnFormat=='php') {
- $returnMessage = array('Error'=>array('Message'=>$errorMessage));
- } else if ($returnFormat=='xml') {
- //Send back XML
- $dom = new DOMDocument("1.0");
- //Create the root element
- $root = $dom->createElement("Error");
- $dom->appendChild($root);
- //Create child elements
- $message = $dom->createElement("Message");
- $root->appendChild($message);
- $message->appendChild($dom->createTextNode("$errorMessage"));
- //Save xml tree
- $returnMessage = $dom->saveXML();
- }
- $data = $this->encodeRestResponse($returnMessage, $returnFormat);
- return $data;
- }
- /**
- * Validate requested return format is one of the supported types
- * @param returnFormat - client requested output format
- */
- function validateReturnFormat($returnFormat) {
- $validReturnFormat = array('json', 'xml', 'php');
- if (!in_array($returnFormat, $validReturnFormat)) {
- return false;
- }
- }
- /**
- * Returns version number of the REST API. Needed so that developers can code to different versions of the API.
- * @param returnFormat - error doc sent back in the user defined return format
- */
- function getAPIVersion($returnFormat) {
- $version = self::$apiVersion;
- if ($this->validateReturnFormat($returnFormat)===false) {
- $returnFormat='json'; //force json
- }
- if ($returnFormat=='json' || $returnFormat=='php') {
- $returnMessage = array('API'=>array('Version'=>$version));
- } else if ($returnFormat=='xml') {
- //Send back XML
- $dom = new DOMDocument("1.0");
- //Create the root element
- $root = $dom->createElement("API");
- $dom->appendChild($root);
- //Create child elements
- $message = $dom->createElement("Version");
- $root->appendChild($message);
- $message->appendChild($dom->createTextNode("$version"));
- //Save xml tree
- $returnMessage = $dom->saveXML();
- }
- $data = $this->encodeRestResponse($returnMessage, $returnFormat);
- return $data;
- }
- /**
- * Used to aid in the building of the HTTP header to send back with the request response
- * @param htmlStatusCode - the code to sent back
- */
- function setHtmlStatusCode($htmlStatusCode) {
- $statusMessages = array(200=>'OK', 400=>'Bad Request', 401=>'Unauthorized');
- if (array_key_exists($htmlStatusCode, $statusMessages)) {
- $statusText = 'HTTP/1.1 '.$htmlStatusCode.' '.$statusMessages[$htmlStatusCode];
- return $statusText;
- } else {
- //Fix to allow compatibility with J!
- if (!function_exists( 'T_' )) { function T_($string) {return $string;} }
- die(T_('Invalid Html Response Code!'));
- }
- }
- /**
- * Set HTTP header content type to send back with the request response
- * @param returnFormat - user requested return format
- */
- function setReturnContentType($returnFormat) {
- //Determine return header content type
- switch ($returnFormat) {
- case 'json':
- case 'php':
- $ctype = 'text/html';
- break;
- case 'xml':
- $ctype = 'text/xml';
- break;
- default:
- $ctype = 'text/html';
- break;
- }
- return $ctype;
- }
- /**
- * Converts and object to an array
- * Code comes from PHP.net comments - http://us2.php.net/manual/en/function.get-object-vars.php#62470
- */
- function object_to_array($obj) {
- $_arr = is_object($obj) ? get_object_vars($obj) : $obj;
- foreach ($_arr as $key => $val) {
- $val = (is_array($val) || is_object($val)) ? $this->object_to_array($val) : $val;
- $arr[$key] = $val;
- }
- return $arr;
- }
- /**
- * Returns the full URL of the current page - including any query parameters.
- * Code comes from snipplr.com - http://snipplr.com/view/2734/get-full-url/
- */
- function full_url() {
- $s = empty($_SERVER["HTTPS"]) ? '' : ($_SERVER["HTTPS"] == "on") ? "s" : "";
- $protocol = substr(strtolower($_SERVER["SERVER_PROTOCOL"]), 0, strpos(strtolower($_SERVER["SERVER_PROTOCOL"]), "/")) . $s;
- $port = ($_SERVER["SERVER_PORT"] == "80") ? "" : (":".$_SERVER["SERVER_PORT"]);
- return $protocol . "://" . $_SERVER['SERVER_NAME'] . $port . $_SERVER['REQUEST_URI'];
- }
- }
- ?>