aurjson.class.php: Style fixes

* Fix braces, indentation and comment style.
* Remove some superfluous comments.
* Reword some comments.

Signed-off-by: Lukas Fleischer <archlinux@cryptocrack.de>
This commit is contained in:
Lukas Fleischer 2014-04-28 11:00:39 +02:00
parent e50f352643
commit 11a565936e

View file

@ -1,26 +1,24 @@
<?php <?php
/**
* AurJSON
*
* This file contains the AurRPC remote handling class
**/
include_once("aur.inc.php"); include_once("aur.inc.php");
/** /*
* This class defines a remote interface for fetching data * This class defines a remote interface for fetching data from the AUR using
* from the AUR using JSON formatted elements. * JSON formatted elements.
*
* @package rpc * @package rpc
* @subpackage classes * @subpackage classes
**/ */
class AurJSON { class AurJSON {
private $dbh = false; private $dbh = false;
private static $exposed_methods = array( private static $exposed_methods = array(
'search', 'info', 'multiinfo', 'msearch', 'suggest' 'search', 'info', 'multiinfo', 'msearch', 'suggest'
); );
private static $fields = array( private static $fields = array(
'Packages.ID', 'Packages.Name', 'PackageBases.Name AS PackageBase', 'Packages.ID', 'Packages.Name',
'Version', 'CategoryID', 'Description', 'URL', 'NumVotes', 'PackageBases.Name AS PackageBase', 'Version', 'CategoryID',
'OutOfDateTS AS OutOfDate', 'Users.UserName AS Maintainer', 'Description', 'URL', 'NumVotes', 'OutOfDateTS AS OutOfDate',
'Users.UserName AS Maintainer',
'SubmittedTS AS FirstSubmitted', 'ModifiedTS AS LastModified' 'SubmittedTS AS FirstSubmitted', 'ModifiedTS AS LastModified'
); );
private static $numeric_fields = array( private static $numeric_fields = array(
@ -28,49 +26,46 @@ class AurJSON {
'LastModified' 'LastModified'
); );
/** /*
* Handles post data, and routes the request. * Handles post data, and routes the request.
*
* @param string $post_data The post data to parse and handle. * @param string $post_data The post data to parse and handle.
*
* @return string The JSON formatted response data. * @return string The JSON formatted response data.
**/ */
public function handle($http_data) { public function handle($http_data) {
// unset global aur headers from aur.inc /*
// leave expires header to enforce validation * Unset global aur.inc.php Pragma header. We want to allow
// header_remove('Expires'); * caching of data in proxies, but require validation of data
// unset global aur.inc pragma header. We want to allow caching of data * (if-none-match) if possible.
// in proxies, but require validation of data (if-none-match) if */
// possible
header_remove('Pragma'); header_remove('Pragma');
// overwrite cache-control header set in aur.inc to allow caching, but /*
// require validation * Overwrite cache-control header set in aur.inc.php to allow
* caching, but require validation.
*/
header('Cache-Control: public, must-revalidate, max-age=0'); header('Cache-Control: public, must-revalidate, max-age=0');
header('Content-Type: application/json, charset=utf-8'); header('Content-Type: application/json, charset=utf-8');
// handle error states if (!isset($http_data['type']) || !isset($http_data['arg'])) {
if ( !isset($http_data['type']) || !isset($http_data['arg']) ) {
return $this->json_error('No request type/data specified.'); return $this->json_error('No request type/data specified.');
} }
if (!in_array($http_data['type'], self::$exposed_methods)) {
return $this->json_error('Incorrect request type specified.');
}
// do the routing
if ( in_array($http_data['type'], self::$exposed_methods) ) {
// set up db connection.
$this->dbh = DB::connect(); $this->dbh = DB::connect();
// ugh. this works. I hate you php. $json = call_user_func(array(&$this, $http_data['type']), $http_data['arg']);
$json = call_user_func(array(&$this, $http_data['type']),
$http_data['arg']);
// calculate etag as an md5 based on the json result
// this could be optimized by calculating the etag on the
// query result object before converting to json (step into
// the above function call) and adding the 'type' to the response,
// but having all this code here is cleaner and 'good enough'
$etag = md5($json); $etag = md5($json);
header("Etag: \"$etag\""); header("Etag: \"$etag\"");
// make sure to strip a few things off the if-none-match /*
// header. stripping whitespace may not be required, but * Make sure to strip a few things off the
// removing the quote on the incoming header is required * if-none-match header. Stripping whitespace may not
// to make the equality test * be required, but removing the quote on the incoming
* header is required to make the equality test.
*/
$if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? $if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ?
trim($_SERVER['HTTP_IF_NONE_MATCH'], "\t\n\r\" ") : false; trim($_SERVER['HTTP_IF_NONE_MATCH'], "\t\n\r\" ") : false;
if ($if_none_match && $if_none_match == $etag) { if ($if_none_match && $if_none_match == $etag) {
@ -78,42 +73,35 @@ class AurJSON {
return; return;
} }
// allow rpc callback for XDomainAjax if (isset($http_data['callback'])) {
if ( isset($http_data['callback']) ) {
// it is more correct to send text/javascript
// content-type for jsonp-callback
header('content-type: text/javascript'); header('content-type: text/javascript');
return $http_data['callback'] . "({$json})"; return $http_data['callback'] . "({$json})";
} } else {
else {
// set content type header to app/json
header('content-type: application/json'); header('content-type: application/json');
return $json; return $json;
} }
} }
else {
return $this->json_error('Incorrect request type specified.');
}
}
/** /*
* Returns a JSON formatted error string. * Returns a JSON formatted error string.
* *
* @param $msg The error string to return * @param $msg The error string to return
*
* @return mixed A json formatted error response. * @return mixed A json formatted error response.
**/ */
private function json_error($msg) { private function json_error($msg) {
// set content type header to app/json
header('content-type: application/json'); header('content-type: application/json');
return $this->json_results('error', 0, $msg); return $this->json_results('error', 0, $msg);
} }
/** /*
* Returns a JSON formatted result data. * Returns a JSON formatted result data.
*
* @param $type The response method type. * @param $type The response method type.
* @param $data The result data to return * @param $data The result data to return
*
* @return mixed A json formatted result response. * @return mixed A json formatted result response.
**/ */
private function json_results($type, $count, $data) { private function json_results($type, $count, $data) {
return json_encode(array( return json_encode(array(
'version' => 2, 'version' => 2,
@ -190,9 +178,11 @@ class AurJSON {
$pkgbase_name = $row['PackageBase']; $pkgbase_name = $row['PackageBase'];
$row['URLPath'] = URL_DIR . substr($pkgbase_name, 0, 2) . "/" . $pkgbase_name . "/" . $pkgbase_name . ".tar.gz"; $row['URLPath'] = URL_DIR . substr($pkgbase_name, 0, 2) . "/" . $pkgbase_name . "/" . $pkgbase_name . ".tar.gz";
/* Unfortunately, mysql_fetch_assoc() returns all fields as /*
* strings. We need to coerce numeric values into integers to * Unfortunately, mysql_fetch_assoc() returns
* provide proper data types in the JSON response. * all fields as strings. We need to coerce
* numeric values into integers to provide
* proper data types in the JSON response.
*/ */
foreach (self::$numeric_fields as $field) { foreach (self::$numeric_fields as $field) {
$row[$field] = intval($row[$field]); $row[$field] = intval($row[$field]);
@ -205,8 +195,7 @@ class AurJSON {
if ($type == 'info') { if ($type == 'info') {
$search_data = $row; $search_data = $row;
break; break;
} } else {
else {
array_push($search_data, $row); array_push($search_data, $row);
} }
} }
@ -216,20 +205,21 @@ class AurJSON {
} }
return $this->json_results($type, $resultcount, $search_data); return $this->json_results($type, $resultcount, $search_data);
} } else {
else {
return $this->json_results($type, 0, array()); return $this->json_results($type, 0, array());
} }
} }
/** /*
* Parse the args to the multiinfo function. We may have a string or an * Parse the args to the multiinfo function. We may have a string or an
* array, so do the appropriate thing. Within the elements, both * package * array, so do the appropriate thing. Within the elements, both * package
* IDs and package names are valid; sort them into the relevant arrays and * IDs and package names are valid; sort them into the relevant arrays and
* escape/quote the names. * escape/quote the names.
*
* @param $args the arg string or array to parse. * @param $args the arg string or array to parse.
*
* @return mixed An array containing 'ids' and 'names'. * @return mixed An array containing 'ids' and 'names'.
**/ */
private function parse_multiinfo_args($args) { private function parse_multiinfo_args($args) {
if (!is_array($args)) { if (!is_array($args)) {
$args = array($args); $args = array($args);
@ -251,51 +241,56 @@ class AurJSON {
return array('ids' => $id_args, 'names' => $name_args); return array('ids' => $id_args, 'names' => $name_args);
} }
/** /*
* Performs a fulltext mysql search of the package database. * Performs a fulltext mysql search of the package database.
*
* @param $keyword_string A string of keywords to search with. * @param $keyword_string A string of keywords to search with.
*
* @return mixed Returns an array of package matches. * @return mixed Returns an array of package matches.
**/ */
private function search($keyword_string) { private function search($keyword_string) {
global $MAX_RPC_RESULTS; global $MAX_RPC_RESULTS;
if (strlen($keyword_string) < 2) { if (strlen($keyword_string) < 2) {
return $this->json_error('Query arg too small'); return $this->json_error('Query arg too small');
} }
$keyword_string = $this->dbh->quote("%" . addcslashes($keyword_string, '%_') . "%"); $keyword_string = $this->dbh->quote("%" . addcslashes($keyword_string, '%_') . "%");
$where_condition = "(Packages.Name LIKE {$keyword_string} OR "; $where_condition = "(Packages.Name LIKE $keyword_string OR ";
$where_condition.= "Description LIKE {$keyword_string}) "; $where_condition .= "Description LIKE $keyword_string) ";
$where_condition.= "LIMIT {$MAX_RPC_RESULTS}"; $where_condition .= "LIMIT $MAX_RPC_RESULTS";
return $this->process_query('search', $where_condition); return $this->process_query('search', $where_condition);
} }
/** /*
* Returns the info on a specific package. * Returns the info on a specific package.
*
* @param $pqdata The ID or name of the package. Package Query Data. * @param $pqdata The ID or name of the package. Package Query Data.
*
* @return mixed Returns an array of value data containing the package data * @return mixed Returns an array of value data containing the package data
**/ */
private function info($pqdata) { private function info($pqdata) {
if ( is_numeric($pqdata) ) { if (is_numeric($pqdata)) {
// just using sprintf to coerce the pqd to an int $where_condition = "Packages.ID = $pqdata";
// should handle sql injection issues, since sprintf will } else {
// bork if not an int, or convert the string to a number 0 $where_condition = "Packages.Name = " . $this->dbh->quote($pqdata);
$where_condition = "Packages.ID={$pqdata}";
}
else {
$where_condition = sprintf("Packages.Name=%s", $this->dbh->quote($pqdata));
} }
return $this->process_query('info', $where_condition); return $this->process_query('info', $where_condition);
} }
/** /*
* Returns the info on multiple packages. * Returns the info on multiple packages.
*
* @param $pqdata A comma-separated list of IDs or names of the packages. * @param $pqdata A comma-separated list of IDs or names of the packages.
*
* @return mixed Returns an array of results containing the package data * @return mixed Returns an array of results containing the package data
**/ */
private function multiinfo($pqdata) { private function multiinfo($pqdata) {
global $MAX_RPC_RESULTS; global $MAX_RPC_RESULTS;
$args = $this->parse_multiinfo_args($pqdata); $args = $this->parse_multiinfo_args($pqdata);
$ids = $args['ids']; $ids = $args['ids'];
$names = $args['names']; $names = $args['names'];
@ -307,42 +302,49 @@ class AurJSON {
$where_condition = ""; $where_condition = "";
if ($ids) { if ($ids) {
$ids_value = implode(',', $args['ids']); $ids_value = implode(',', $args['ids']);
$where_condition .= "ID IN ({$ids_value}) "; $where_condition .= "ID IN ($ids_value) ";
} }
if ($ids && $names) { if ($ids && $names) {
$where_condition .= "OR "; $where_condition .= "OR ";
} }
if ($names) { if ($names) {
// individual names were quoted in parse_multiinfo_args() /*
* Individual names were quoted in
* parse_multiinfo_args().
*/
$names_value = implode(',', $args['names']); $names_value = implode(',', $args['names']);
$where_condition .= "Packages.Name IN ({$names_value}) "; $where_condition .= "Packages.Name IN ($names_value) ";
} }
$where_condition .= "LIMIT $MAX_RPC_RESULTS";
$where_condition .= "LIMIT {$MAX_RPC_RESULTS}";
return $this->process_query('multiinfo', $where_condition); return $this->process_query('multiinfo', $where_condition);
} }
/** /*
* Returns all the packages for a specific maintainer. * Returns all the packages for a specific maintainer.
*
* @param $maintainer The name of the maintainer. * @param $maintainer The name of the maintainer.
*
* @return mixed Returns an array of value data containing the package data * @return mixed Returns an array of value data containing the package data
**/ */
private function msearch($maintainer) { private function msearch($maintainer) {
global $MAX_RPC_RESULTS; global $MAX_RPC_RESULTS;
$maintainer = $this->dbh->quote($maintainer); $maintainer = $this->dbh->quote($maintainer);
$where_condition = "Users.Username = {$maintainer} "; $where_condition = "Users.Username = $maintainer ";
$where_condition .= "LIMIT {$MAX_RPC_RESULTS}"; $where_condition .= "LIMIT $MAX_RPC_RESULTS";
return $this->process_query('msearch', $where_condition); return $this->process_query('msearch', $where_condition);
} }
/** /*
* Get all package names that start with $search. * Get all package names that start with $search.
*
* @param string $search Search string. * @param string $search Search string.
*
* @return string The JSON formatted response data. * @return string The JSON formatted response data.
**/ */
private function suggest($search) { private function suggest($search) {
$query = 'SELECT Name FROM Packages WHERE Name LIKE ' . $query = 'SELECT Name FROM Packages WHERE Name LIKE ' .
$this->dbh->quote(addcslashes($search, '%_') . '%') . $this->dbh->quote(addcslashes($search, '%_') . '%') .