Basic API and Authentication extensions.

这个提交包含在:
Andy Smith 2011-08-17 02:21:23 +01:00
父节点 205fd1bab5
当前提交 8a793391ad
共有 12 个文件被更改,包括 1312 次插入0 次删除

查看文件

@ -0,0 +1,141 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class API extends CI_Controller {
// Do absolutely nothing
function index()
{
//load the model and get results
$this->load->model('logbook_model');
$data['data'] = array();
// load the view
//$this->load->view('layout/header');
$this->load->view('api/index', $data);
//$this->load->view('layout/footer');
}
// FUNCTION: search()
// Handle search requests
/*
Okay, so here's how it works in a nutshell...
*******************************************************************
Because this is effectively just a filter between the query string
and a MySQL statement, if done wrong we're just asking for pain.
DO NOT alter any of the filtering statements without fully
understanding what you're doing. CodeIgniter provides some
protection against unwanted characters in the query string, but
this should in no way be relied upon for safety.
*******************************************************************
Example query:-
.../search/query[Call~M0*(and)(Locator~I*(or)Locator~J*)]/limit[10]/fields[distinct(Call),Locator]/order[Call(asc)]
There's four parts to this query, separated with forward slashes. It's effectively a heavily-sanitised
MySQL query, hence the hideous search and replace code blocks below.
FIELDS
------
Straightforward - input is sanitised and passed on - in the example, this ends up as "DISTINCT (Call),Locator",
which is then the first argument to 'SELECT'
QUERY
-----
This forms the 'WHERE' clause.
* '(and)' and '(or)' are expanded out to ' AND ' and ' OR '
* Parentheses are preserved
* '~' is expanded out to ' LIKE '
* '*' is translated to '%'
* Values are encapsulated in quote marks
So in the example, this translates to "WHERE Call LIKE 'M0%' AND (Locator LIKE 'I%' OR Locator LIKE 'J%')"
ORDER
-----
Sanitised, so our example ends up as "ORDER BY Call ASC".
LIMIT
-----
Straightforward - what's between the square brackets is passed as an argument to 'LIMIT'
Finally, once this has been done, each field name is translated to the MySQL column name.
*/
function search()
{
// Load the API and Logbook models
$this->load->model('api_model');
$this->load->model('logbook_model');
// Retrieve the arguments from the query string
$arguments = $this->_retrieve();
// Call the parser within the API model to build the query
$query = $this->api_model->parse($arguments);
// Execute the query, and retrieve the results
$s = $this->logbook_model->api_search_query($query);
$results = $s['results'];
// Cycle through the results, and translate between MySQL column names
// and more friendly, descriptive names
$a = 0;
if($results->num_rows != 0)
{
foreach ($results->result() as $row) {
$record = (array)$row;
$r[$a]['rid'] = $a;
while (list($key, $val) = each($record)) {
$r[$a][$this->api_model->name($key)] = $val;
}
$a++;
}
// Add the result record to the main results array
$data['data']['search_Result']['results'] = $r;
}
else
{
// We've got no results, so make this empty for completeness
$data['data']['search_Result']['results'] = "";
}
// Add some debugging information to the XML output
$data['data']['queryInfo']['call'] = "search";
$data['data']['queryInfo']['dbQuery'] = $s['query'];
$data['data']['queryInfo']['numResults'] = $a;
$data['data']['queryInfo']['executionTime'] = $s['time'];
// Load the XML output view
$this->load->view('api/index', $data);
}
// FUNCTION: _retrieve()
// Pull the search query arguments from the query string
private function _retrieve()
{
// This whole function could probably have been done in one line... if this was Perl.
$arguments = array();
// Retrieve each arguments
$query = preg_grep("/^query\[(.*)\]$/", $this->uri->segments);
$limit = preg_grep("/^limit\[(.*)\]$/", $this->uri->segments);
$order = preg_grep("/^order\[(.*)\]$/", $this->uri->segments);
$fields = preg_grep("/^fields\[(.*)\]$/", $this->uri->segments);
// Strip each argument
$arguments['query'] = substr(array_pop($query), 6);
$arguments['query'] = substr($arguments['query'], 0, strlen($arguments['query']) - 1);
$arguments['limit'] = substr(array_pop($limit), 6);
$arguments['limit'] = substr($arguments['limit'], 0, strlen($arguments['limit']) - 1);
$arguments['order'] = substr(array_pop($order), 6);
$arguments['order'] = substr($arguments['order'], 0, strlen($arguments['order']) - 1);
$arguments['fields'] = substr(array_pop($fields), 7);
$arguments['fields'] = substr($arguments['fields'], 0, strlen($arguments['fields']) - 1);
// Return the arguments
return $arguments;
}
}

查看文件

@ -0,0 +1,95 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Auth extends CI_Controller {
/* Displays all notes in a list */
public function index()
{
$this->load->model('auth_model');
echo "<pre>";
echo "Querying for user...\n";
$u = $this->auth_model->get("m0vkga");
print_r($u);
echo "Test hashing\n";
echo $this->auth_model->test();
}
/*
$this->load->model('note');
$data['notes'] = $this->note->list_all();
$this->load->view('layout/header');
$this->load->view('notes/main', $data);
$this->load->view('layout/footer');
}
function add() {
$this->load->model('note');
$this->load->library('form_validation');
$this->form_validation->set_rules('title', 'Note Title', 'required');
$this->form_validation->set_rules('content', 'Content', 'required');
if ($this->form_validation->run() == FALSE)
{
$this->load->view('layout/header');
$this->load->view('notes/add');
$this->load->view('layout/footer');
}
else
{
$this->note->add();
redirect('notes');
}
}
function view($id) {
$this->load->model('note');
$data['note'] = $this->note->view($id);
// Display
$this->load->view('layout/header');
$this->load->view('notes/view',$data);
$this->load->view('layout/footer');
}
function edit($id) {
$this->load->model('note');
$data['id'] = $id;
$data['note'] = $this->note->view($id);
$this->load->library('form_validation');
$this->form_validation->set_rules('title', 'Note Title', 'required');
$this->form_validation->set_rules('content', 'Content', 'required');
if ($this->form_validation->run() == FALSE)
{
$this->load->view('layout/header');
$this->load->view('notes/edit', $data);
$this->load->view('layout/footer');
}
else
{
$this->note->edit();
redirect('notes');
}
}
function delete($id) {
$this->load->model('note');
$this->note->delete($id);
redirect('notes');
}
*/
}

查看文件

@ -0,0 +1,319 @@
<?php
class API_Model extends CI_Model {
function __construct()
{
// Call the Model constructor
parent::__construct();
}
// FUNCTION: string name(string $column)
// Converts a MySQL column name to a more friendly name
function name($col)
{
if($this->_columnName[$col])
{
return $this->_columnName[$col]['Name'];
}
else
{
return 0;
}
}
// FUNCTION: string description(string $column)
// Returns the description for a MySQL column name
function description($col)
{
if($this->_columnName[$col])
{
if($this->_columnName[$col]['Description'] != "")
{
return $this->_columnName[$col]['Description'];
}
else
{
return "No description available";
}
}
else
{
return 0;
}
}
// FUNCTION: string name(string $name)
// Converts a friendly name to a MySQL column name
function column($name)
{
while ($column = current($this->_columnName))
{
if($this->_columnName[key($this->_columnName)]['Name'] == $name)
{
return key($this->_columnName);
}
next($this->_columnName);
}
return 0;
}
// FUNCTION: string parse(array $arguments)
// Converts an array of arguments into a MySQL query string
// See documentation for search() under the API controller for more details
function parse($arguments)
{
// Initialise our string
$q = "SELECT ";
// Cycle through the fields, converting friendly names to MySQL column names
if($arguments['fields'] != "") {
$field = "";
$fields = explode(",", $arguments['fields']);
foreach ($fields as $f) {
if($field != "") {
$field .= ",";
}
// Add field to the query, with '++' placeholders for later translation
$field .= "++$f++";
}
// Handle any DISTINCT arguments
$field = str_replace("++distinct&#40;", "DISTINCT(++", $field);
$field = str_replace("&#41;++", "++)", $field);
// Add the MySQL column name to the query
$q .= $field." ";
} else {
// If no fields are specified, display all fields
$q .= "* ";
}
// Append the table we're pulling data from
$q .= "FROM ".$this->config->item('table_name');
// Parse the 'query' string, which is converted into a standard MySQL 'WHERE'
// clause.
// $s and $r can be refactored into single array definitions, but during
// development it's easier to list them in this way for quick reference.
if($arguments['query'] != "")
{
$q .= " WHERE ";
$s = null;
$r = null;
// (and), becomes ' AND '
$s[0] = '/&#40;and&#41;/';
// (or), becomes ' OR '
$s[1] = '/&#40;or&#41;/';
// <, >, [ and ] all translated from their urlencoded forms
$s[2] = '/%3C/';
$s[3] = '/%3E/';
$s[4] = '/%5B/';
$s[5] = '/%5D/';
// FieldName=, which becomes '++FieldName++ = '
$s[6] = '/([a-zA-Z0-9\-\_\*\(\)\=\~]+)=/';
// =Value, which becomes '= 'Value''
$s[7] = '/=([a-zA-Z0-9\-\_\*\(\)\=\~]+)/';
// now(), which becomes 'UNIX_TIMESTAMP(NOW())'
$s[8] = '/now()/';
// (, and ), which are translated to their non-HTML entity forms,
// and with added padding
$s[9] = '/&#40;/';
$s[10] = '/&#41;/';
// FieldName~, becomes '++FieldName++ LIKE~'
$s[11] = '/([a-zA-Z0-9\-\_\*\(\)\=\~]+)~/';
// ~Value, becomes ' 'Value''
$s[12] = '/~([a-zA-Z0-9\-\_\*\(\)\=\~]+)/';
// *, which becomes '%'
$s[13] = '/\*/';
$r[0] = ' AND ';
$r[1] = ' OR ';
$r[2] = ' < ';
$r[3] = ' > ';
$r[4] = '[';
$r[5] = ']';
$r[6] = '++$1++ =';
$r[7] = '= \'$1\'';
$r[8] = 'UNIX_TIMESTAMP(NOW())';
$r[9] = '( ';
$r[10] = ' )';
$r[11] = '++$1++ LIKE~';
$r[12] = ' \'$1\'';
$r[13] = '%';
// Bulk replace everything
$q .= preg_replace($s, $r, $arguments['query']);
}
// Parse any order arguments
if($arguments['order'] != "")
{
$q .= " ORDER BY ";
$s = null;
$r = null;
$s[0] = '/&#40;/';
$s[1] = '/&#41;/';
$s[2] = '/([a-zA-Z0-9\-\_]+)([,\(]{1}|$)/';
$s[3] = '/\(asc\)/';
$s[4] = '/\(desc\)/';
$s[5] = '/,$/';
$r[0] = '(';
$r[1] = ')';
$r[2] = '++$1++ $2';
$r[3] = ' ASC ';
$r[4] = ' DESC ';
$r[5] = '';
$q .= preg_replace($s, $r, $arguments['order']);
}
// Do search/replace on field names, to convert from friendly names
// to MySQL column names
while (list($key, $val) = each($this->_columnName)) {
$q = str_replace("++".$val['Name']."++", $key, $q);
}
// Parse any limit arguments
if($arguments['limit'] != "")
{
// Add the limit arguments, removing any characters other than numbers and commas
$q .= " LIMIT " . preg_replace(array("/[^0-9\,]/","/,$/"), "", $arguments['limit']);
}
else
{
// If no limit argument is given, default to the first 20 results
$q .= " LIMIT 0,20";
}
return $q;
}
// ARRAY: $_columnName
// An array matching MySQL column names to friendly names, descriptions and types
private $_columnName = array(
'COL_PRIMARY_KEY' => array('Name' => 'ID', 'Description' => 'Unique QSO ID', 'Type' => 'I'),
'COL_ADDRESS' => array('Name' => 'Address', 'Description' => 'Operator\'s address', 'Type' => 'S'),
'COL_AGE' => array('Name' => 'Age', 'Description' => 'Operator\'s age', 'Type' => 'I'),
'COL_A_INDEX' => array('Name' => 'AIndex', 'Description' => 'Solar A Index', 'Type' => 'I'),
'COL_ANT_AZ' => array('Name' => 'AntennaAzimuth', 'Description' => 'Antenna azimuth', 'Type' => 'I'),
'COL_ANT_EL' => array('Name' => 'AntennaElevation', 'Description' => 'Antenna elevation', 'Type' => 'I'),
'COL_ANT_PATH' => array('Name' => 'AntennaPath', 'Description' => 'Antenna path', 'Type' => ''),
'COL_ARRL_SECT' => array('Name' => 'ARRLSection', 'Description' => 'ARRL Section', 'Type' => ''),
'COL_BAND' => array('Name' => 'Band', 'Description' => 'Band', 'Type' => ''),
'COL_BAND_RX' => array('Name' => 'BandRX', 'Description' => '', 'Type' => ''),
'COL_BIOGRAPHY' => array('Name' => 'Biography', 'Description' => '', 'Type' => ''),
'COL_CALL' => array('Name' => 'Call', 'Description' => '', 'Type' => ''),
'COL_CHECK' => array('Name' => 'UNK_CHECK', 'Description' => '', 'Type' => ''),
'COL_CLASS' => array('Name' => 'Class', 'Description' => '', 'Type' => ''),
'COL_CNTY' => array('Name' => 'County', 'Description' => '', 'Type' => ''),
'COL_COMMENT' => array('Name' => 'Comment', 'Description' => '', 'Type' => ''),
'COL_CONT' => array('Name' => 'Continent', 'Description' => '', 'Type' => ''),
'COL_CONTACTED_OP' => array('Name' => 'UNK_CONTACTED_OP', 'Description' => '', 'Type' => ''),
'COL_CONTEST_ID' => array('Name' => 'ContestID', 'Description' => '', 'Type' => ''),
'COL_COUNTRY' => array('Name' => 'Country', 'Description' => '', 'Type' => ''),
'COL_CQZ' => array('Name' => 'CQZone', 'Description' => '', 'Type' => ''),
'COL_DISTANCE' => array('Name' => 'Distance', 'Description' => '', 'Type' => ''),
'COL_DXCC' => array('Name' => 'DXCC', 'Description' => '', 'Type' => ''),
'COL_EMAIL' => array('Name' => 'EMail', 'Description' => '', 'Type' => ''),
'COL_EQ_CALL' => array('Name' => 'UNK_EQ_CALL', 'Description' => '', 'Type' => ''),
'COL_EQSL_QSLRDATE' => array('Name' => 'EQSLRecievedDate', 'Description' => '', 'Type' => ''),
'COL_EQSL_QSLSDATE' => array('Name' => 'EQSLSentDate', 'Description' => '', 'Type' => ''),
'COL_EQSL_QSL_RCVD' => array('Name' => 'EQSLRecieved', 'Description' => '', 'Type' => ''),
'COL_EQSL_QSL_SENT' => array('Name' => 'EQSLSent', 'Description' => '', 'Type' => ''),
'COL_EQSL_STATUS' => array('Name' => 'EQSLStatus', 'Description' => '', 'Type' => ''),
'COL_FORCE_INIT' => array('Name' => 'UNK_FORCE_INIT', 'Description' => '', 'Type' => ''),
'COL_FREQ' => array('Name' => 'Frequency', 'Description' => '', 'Type' => ''),
'COL_FREQ_RX' => array('Name' => 'FrequencyRX', 'Description' => '', 'Type' => ''),
'COL_GRIDSQUARE' => array('Name' => 'Locator', 'Description' => '', 'Type' => ''),
'COL_HEADING' => array('Name' => 'Heading', 'Description' => '', 'Type' => ''),
'COL_IOTA' => array('Name' => 'IOTA', 'Description' => '', 'Type' => ''),
'COL_ITUZ' => array('Name' => 'ITUZone', 'Description' => '', 'Type' => ''),
'COL_K_INDEX' => array('Name' => 'KIndex', 'Description' => '', 'Type' => ''),
'COL_LAT' => array('Name' => 'Latitude', 'Description' => '', 'Type' => ''),
'COL_LON' => array('Name' => 'Longitude', 'Description' => '', 'Type' => ''),
'COL_LOTW_QSLRDATE' => array('Name' => 'LOTWRecievedDate', 'Description' => '', 'Type' => ''),
'COL_LOTW_QSLSDATE' => array('Name' => 'LOTWSentDate', 'Description' => '', 'Type' => ''),
'COL_LOTW_QSL_RCVD' => array('Name' => 'LOTWRecieved', 'Description' => '', 'Type' => ''),
'COL_LOTW_QSL_SENT' => array('Name' => 'LOTWSent', 'Description' => '', 'Type' => ''),
'COL_LOTW_STATUS' => array('Name' => 'LOTWStatus', 'Description' => '', 'Type' => ''),
'COL_MAX_BURSTS' => array('Name' => 'MaxBursts', 'Description' => '', 'Type' => ''),
'COL_MODE' => array('Name' => 'Mode', 'Description' => '', 'Type' => ''),
'COL_MS_SHOWER' => array('Name' => 'MSShower', 'Description' => '', 'Type' => ''),
'COL_MY_CITY' => array('Name' => 'MyCity', 'Description' => '', 'Type' => ''),
'COL_MY_CNTY' => array('Name' => 'MyCounty', 'Description' => '', 'Type' => ''),
'COL_MY_COUNTRY' => array('Name' => 'MyCountry', 'Description' => '', 'Type' => ''),
'COL_MY_CQ_ZONE' => array('Name' => 'MyCQZone', 'Description' => '', 'Type' => ''),
'COL_MY_GRIDSQUARE' => array('Name' => 'MyLocator', 'Description' => '', 'Type' => ''),
'COL_MY_IOTA' => array('Name' => 'MyIOTA', 'Description' => '', 'Type' => ''),
'COL_MY_ITU_ZONE' => array('Name' => 'MyITUZone', 'Description' => '', 'Type' => ''),
'COL_MY_LAT' => array('Name' => 'MyLatitude', 'Description' => '', 'Type' => ''),
'COL_MY_LON' => array('Name' => 'MyLongitude', 'Description' => '', 'Type' => ''),
'COL_MY_NAME' => array('Name' => 'MyName', 'Description' => '', 'Type' => ''),
'COL_MY_POSTAL_CODE' => array('Name' => 'MyPostalCode', 'Description' => '', 'Type' => ''),
'COL_MY_RIG' => array('Name' => 'MyRig', 'Description' => '', 'Type' => ''),
'COL_MY_SIG' => array('Name' => 'MySig', 'Description' => '', 'Type' => ''),
'COL_MY_SIG_INFO' => array('Name' => 'MySigInfo', 'Description' => '', 'Type' => ''),
'COL_MY_STATE' => array('Name' => 'MyState', 'Description' => '', 'Type' => ''),
'COL_MY_STREET' => array('Name' => 'MyStreet', 'Description' => '', 'Type' => ''),
'COL_NAME' => array('Name' => 'Name', 'Description' => '', 'Type' => ''),
'COL_NOTES' => array('Name' => 'Notes', 'Description' => '', 'Type' => ''),
'COL_NR_BURSTS' => array('Name' => 'NumBursts', 'Description' => '', 'Type' => ''),
'COL_NR_PINGS' => array('Name' => 'NumPings', 'Description' => '', 'Type' => ''),
'COL_OPERATOR' => array('Name' => 'Operator', 'Description' => '', 'Type' => ''),
'COL_OWNER_CALLSIGN' => array('Name' => 'OwnerCallsign', 'Description' => '', 'Type' => ''),
'COL_PFX' => array('Name' => 'Prefix', 'Description' => '', 'Type' => ''),
'COL_PRECEDENCE' => array('Name' => 'Precedence', 'Description' => '', 'Type' => ''),
'COL_PROP_MODE' => array('Name' => 'PropMode', 'Description' => '', 'Type' => ''),
'COL_PUBLIC_KEY' => array('Name' => 'PublicKey', 'Description' => '', 'Type' => ''),
'COL_QSLMSG' => array('Name' => 'QSLMessage', 'Description' => '', 'Type' => ''),
'COL_QSLRDATE' => array('Name' => 'QSLRecievedDate', 'Description' => '', 'Type' => ''),
'COL_QSLSDATE' => array('Name' => 'QSLSentDate', 'Description' => '', 'Type' => ''),
'COL_QSL_RCVD' => array('Name' => 'QSLRecieved', 'Description' => '', 'Type' => ''),
'COL_QSL_RCVD_VIA' => array('Name' => 'QSLRecievedVia', 'Description' => '', 'Type' => ''),
'COL_QSL_SENT' => array('Name' => 'QSLSent', 'Description' => '', 'Type' => ''),
'COL_QSL_SENT_VIA' => array('Name' => 'QSLSentVia', 'Description' => '', 'Type' => ''),
'COL_QSL_VIA' => array('Name' => 'QSLVia', 'Description' => '', 'Type' => ''),
'COL_QSO_COMPLETE' => array('Name' => 'QSOComplete', 'Description' => '', 'Type' => ''),
'COL_QSO_RANDOM' => array('Name' => 'QSORandom', 'Description' => '', 'Type' => ''),
'COL_QTH' => array('Name' => 'QTH', 'Description' => '', 'Type' => ''),
'COL_RIG' => array('Name' => 'Rig', 'Description' => '', 'Type' => ''),
'COL_RST_RCVD' => array('Name' => 'ReportRecieved', 'Description' => '', 'Type' => ''),
'COL_RST_SENT' => array('Name' => 'ReportSent', 'Description' => '', 'Type' => ''),
'COL_RX_PWR' => array('Name' => 'RXPower', 'Description' => '', 'Type' => ''),
'COL_SAT_MODE' => array('Name' => 'SatMode', 'Description' => '', 'Type' => ''),
'COL_SAT_NAME' => array('Name' => 'SatName', 'Description' => '', 'Type' => ''),
'COL_SFI' => array('Name' => 'SFI', 'Description' => '', 'Type' => ''),
'COL_SIG' => array('Name' => 'Sig', 'Description' => '', 'Type' => ''),
'COL_SIG_INFO' => array('Name' => 'SigInfo', 'Description' => '', 'Type' => ''),
'COL_SRX' => array('Name' => 'UNK_SRX', 'Description' => '', 'Type' => ''),
'COL_STX' => array('Name' => 'UNK_STX', 'Description' => '', 'Type' => ''),
'COL_SRX_STRING' => array('Name' => 'UNK_SRX_STRING', 'Description' => '', 'Type' => ''),
'COL_STX_STRING' => array('Name' => 'UNK_STX_STRING', 'Description' => '', 'Type' => ''),
'COL_STATE' => array('Name' => 'State', 'Description' => '', 'Type' => ''),
'COL_STATION_CALLSIGN' => array('Name' => 'StationCall', 'Description' => '', 'Type' => ''),
'COL_SWL' => array('Name' => 'SWL', 'Description' => '', 'Type' => ''),
'COL_TEN_TEN' => array('Name' => 'TenTen', 'Description' => '', 'Type' => ''),
'COL_TIME_OFF' => array('Name' => 'TimeOff', 'Description' => '', 'Type' => ''),
'COL_TIME_ON' => array('Name' => 'TimeOn', 'Description' => '', 'Type' => ''),
'COL_TX_PWR' => array('Name' => 'TXPower', 'Description' => '', 'Type' => ''),
'COL_WEB' => array('Name' => 'Website', 'Description' => '', 'Type' => ''),
'COL_USER_DEFINED_0' => array('Name' => 'UNK_USER_DEFINED_0', 'Description' => '', 'Type' => ''),
'COL_USER_DEFINED_1' => array('Name' => 'UNK_USER_DEFINED_1', 'Description' => '', 'Type' => ''),
'COL_USER_DEFINED_2' => array('Name' => 'UNK_USER_DEFINED_2', 'Description' => '', 'Type' => ''),
'COL_USER_DEFINED_3' => array('Name' => 'UNK_USER_DEFINED_3', 'Description' => '', 'Type' => ''),
'COL_USER_DEFINED_4' => array('Name' => 'UNK_USER_DEFINED_4', 'Description' => '', 'Type' => ''),
'COL_USER_DEFINED_5' => array('Name' => 'UNK_USER_DEFINED_5', 'Description' => '', 'Type' => ''),
'COL_USER_DEFINED_6' => array('Name' => 'UNK_USER_DEFINED_6', 'Description' => '', 'Type' => ''),
'COL_USER_DEFINED_7' => array('Name' => 'UNK_USER_DEFINED_7', 'Description' => '', 'Type' => ''),
'COL_USER_DEFINED_8' => array('Name' => 'UNK_USER_DEFINED_8', 'Description' => '', 'Type' => ''),
'COL_USER_DEFINED_9' => array('Name' => 'UNK_USER_DEFINED_9', 'Description' => '', 'Type' => ''),
'COL_CREDIT_GRANTED' => array('Name' => 'UNK_CREDIT_GRANTED', 'Description' => '', 'Type' => ''),
'COL_CREDIT_SUBMITTED' => array('Name' => 'UNK_CREDIT_SUBMITTED', 'Description' => '', 'Type' => ''),
);
}
?>

查看文件

@ -0,0 +1,95 @@
<?php
// Uses 'phpass' from http://www.openwall.com/phpass/ to implement password hashing
require_once('application/third_party/PasswordHash.php');
class Auth_Model extends CI_Model {
function __construct()
{
// Call the Model constructor
parent::__construct();
}
// Test function, can be removed once class is complete
function test() {
$hash = $this->_hash("password");
echo "Password hashed is '".$hash."\n";
echo "Does 'password' match '$hash'? result is ".$this->_auth("password", $hash)."\n";
}
// Retrieve a user
function get($username) {
$this->db->where('user_name', $username);
$r = $this->db->get($this->config->item('auth_table'));
if($r->num_rows == 1) {
return $r->result();
} else {
return 0;
}
}
function exists($username) {
if($this->get($username)->num_rows == 0) {
return 0;
} else {
return 1;
}
}
function add($username, $password, $email, $type) {
if(!$this->exists($username)) {
$data = array(
'user_name' => $username,
'user_password' => $this->_hash($password),
'user_email' => $email,
'user_type' => $type
);
$this->db->insert($this->config->item('auth_table'));
return 1;
} else {
return 0;
}
}
function authenticate($username, $password) {
$u = $this->get($username);
if($this->_hash($password, $u['user_password'])) {
return 1;
} else {
return 0;
}
}
function set($username, $data) {
$this->db->where('user_name', $username);
$this->db->update($this->config->item('auth_table', $data));
return 1;
}
private function _auth($password, $hash) {
$h = new PasswordHash(8, FALSE);
if($h->CheckPassword($password, $hash)) {
return 1;
} else {
return 0;
}
}
private function _hash($password) {
$h = new PasswordHash(8, FALSE);
$hash = $h->HashPassword($password);
unset($h);
if(strlen($hash) < 20) {
return 0;
} else {
return $hash;
}
}
}
?>

253
application/third_party/PasswordHash.php vendored 普通文件
查看文件

@ -0,0 +1,253 @@
<?php
#
# Portable PHP password hashing framework.
#
# Version 0.3 / genuine.
#
# Written by Solar Designer <solar at openwall.com> in 2004-2006 and placed in
# the public domain. Revised in subsequent years, still public domain.
#
# There's absolutely no warranty.
#
# The homepage URL for this framework is:
#
# http://www.openwall.com/phpass/
#
# Please be sure to update the Version line if you edit this file in any way.
# It is suggested that you leave the main version number intact, but indicate
# your project name (after the slash) and add your own revision information.
#
# Please do not change the "private" password hashing method implemented in
# here, thereby making your hashes incompatible. However, if you must, please
# change the hash type identifier (the "$P$") to something different.
#
# Obviously, since this code is in the public domain, the above are not
# requirements (there can be none), but merely suggestions.
#
class PasswordHash {
var $itoa64;
var $iteration_count_log2;
var $portable_hashes;
var $random_state;
function PasswordHash($iteration_count_log2, $portable_hashes)
{
$this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31)
$iteration_count_log2 = 8;
$this->iteration_count_log2 = $iteration_count_log2;
$this->portable_hashes = $portable_hashes;
$this->random_state = microtime();
if (function_exists('getmypid'))
$this->random_state .= getmypid();
}
function get_random_bytes($count)
{
$output = '';
if (is_readable('/dev/urandom') &&
($fh = @fopen('/dev/urandom', 'rb'))) {
$output = fread($fh, $count);
fclose($fh);
}
if (strlen($output) < $count) {
$output = '';
for ($i = 0; $i < $count; $i += 16) {
$this->random_state =
md5(microtime() . $this->random_state);
$output .=
pack('H*', md5($this->random_state));
}
$output = substr($output, 0, $count);
}
return $output;
}
function encode64($input, $count)
{
$output = '';
$i = 0;
do {
$value = ord($input[$i++]);
$output .= $this->itoa64[$value & 0x3f];
if ($i < $count)
$value |= ord($input[$i]) << 8;
$output .= $this->itoa64[($value >> 6) & 0x3f];
if ($i++ >= $count)
break;
if ($i < $count)
$value |= ord($input[$i]) << 16;
$output .= $this->itoa64[($value >> 12) & 0x3f];
if ($i++ >= $count)
break;
$output .= $this->itoa64[($value >> 18) & 0x3f];
} while ($i < $count);
return $output;
}
function gensalt_private($input)
{
$output = '$P$';
$output .= $this->itoa64[min($this->iteration_count_log2 +
((PHP_VERSION >= '5') ? 5 : 3), 30)];
$output .= $this->encode64($input, 6);
return $output;
}
function crypt_private($password, $setting)
{
$output = '*0';
if (substr($setting, 0, 2) == $output)
$output = '*1';
$id = substr($setting, 0, 3);
# We use "$P$", phpBB3 uses "$H$" for the same thing
if ($id != '$P$' && $id != '$H$')
return $output;
$count_log2 = strpos($this->itoa64, $setting[3]);
if ($count_log2 < 7 || $count_log2 > 30)
return $output;
$count = 1 << $count_log2;
$salt = substr($setting, 4, 8);
if (strlen($salt) != 8)
return $output;
# We're kind of forced to use MD5 here since it's the only
# cryptographic primitive available in all versions of PHP
# currently in use. To implement our own low-level crypto
# in PHP would result in much worse performance and
# consequently in lower iteration counts and hashes that are
# quicker to crack (by non-PHP code).
if (PHP_VERSION >= '5') {
$hash = md5($salt . $password, TRUE);
do {
$hash = md5($hash . $password, TRUE);
} while (--$count);
} else {
$hash = pack('H*', md5($salt . $password));
do {
$hash = pack('H*', md5($hash . $password));
} while (--$count);
}
$output = substr($setting, 0, 12);
$output .= $this->encode64($hash, 16);
return $output;
}
function gensalt_extended($input)
{
$count_log2 = min($this->iteration_count_log2 + 8, 24);
# This should be odd to not reveal weak DES keys, and the
# maximum valid value is (2**24 - 1) which is odd anyway.
$count = (1 << $count_log2) - 1;
$output = '_';
$output .= $this->itoa64[$count & 0x3f];
$output .= $this->itoa64[($count >> 6) & 0x3f];
$output .= $this->itoa64[($count >> 12) & 0x3f];
$output .= $this->itoa64[($count >> 18) & 0x3f];
$output .= $this->encode64($input, 3);
return $output;
}
function gensalt_blowfish($input)
{
# This one needs to use a different order of characters and a
# different encoding scheme from the one in encode64() above.
# We care because the last character in our encoded string will
# only represent 2 bits. While two known implementations of
# bcrypt will happily accept and correct a salt string which
# has the 4 unused bits set to non-zero, we do not want to take
# chances and we also do not want to waste an additional byte
# of entropy.
$itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$output = '$2a$';
$output .= chr(ord('0') + $this->iteration_count_log2 / 10);
$output .= chr(ord('0') + $this->iteration_count_log2 % 10);
$output .= '$';
$i = 0;
do {
$c1 = ord($input[$i++]);
$output .= $itoa64[$c1 >> 2];
$c1 = ($c1 & 0x03) << 4;
if ($i >= 16) {
$output .= $itoa64[$c1];
break;
}
$c2 = ord($input[$i++]);
$c1 |= $c2 >> 4;
$output .= $itoa64[$c1];
$c1 = ($c2 & 0x0f) << 2;
$c2 = ord($input[$i++]);
$c1 |= $c2 >> 6;
$output .= $itoa64[$c1];
$output .= $itoa64[$c2 & 0x3f];
} while (1);
return $output;
}
function HashPassword($password)
{
$random = '';
if (CRYPT_BLOWFISH == 1 && !$this->portable_hashes) {
$random = $this->get_random_bytes(16);
$hash =
crypt($password, $this->gensalt_blowfish($random));
if (strlen($hash) == 60)
return $hash;
}
if (CRYPT_EXT_DES == 1 && !$this->portable_hashes) {
if (strlen($random) < 3)
$random = $this->get_random_bytes(3);
$hash =
crypt($password, $this->gensalt_extended($random));
if (strlen($hash) == 20)
return $hash;
}
if (strlen($random) < 6)
$random = $this->get_random_bytes(6);
$hash =
$this->crypt_private($password,
$this->gensalt_private($random));
if (strlen($hash) == 34)
return $hash;
# Returning '*' on error is safe here, but would _not_ be safe
# in a crypt(3)-like function used _both_ for generating new
# hashes and for validating passwords against existing hashes.
return '*';
}
function CheckPassword($password, $stored_hash)
{
$hash = $this->crypt_private($password, $stored_hash);
if ($hash[0] == '*')
$hash = crypt($password, $stored_hash);
return $hash == $stored_hash;
}
}
?>

查看文件

@ -0,0 +1,117 @@
<?php
// Set the content-type for browsers
header("Content-type: text/xml");
// Create the DOMDocument for the XML output
$xmlDoc = new DOMDocument("1.0");
// Add reference to the XSLT
$xsl = $xmlDoc->createProcessingInstruction("xml-stylesheet", "type=\"text/xsl\" href=\"/css/api.xsl\"");
$xmlDoc->appendChild($xsl);
// Get the method called, and build the root node
$call = $data['queryInfo']['call'];
$rootNode = $xmlDoc->createElement("HRDWebLogbook-API");
$parentNode = $xmlDoc->appendChild($rootNode);
// Get the results output
$output = $data[$call."_Result"];
// Add the queryInfo node
$node = $xmlDoc->createElement("queryInfo");
$queryElement = $parentNode->appendChild($node);
$queryElement->setAttribute("timeStamp", date("r", time()));
$queryElement->setAttribute("calledMethod", $data['queryInfo']['call']);
//$queryElement->setAttribute("queryArgs", $queryArgsString);
$queryElement->setAttribute("resultsCount", count($data['queryInfo']['numResults']));
if(ENVIRONMENT == "development") {
$debugInfo = $xmlDoc->createElement("debugInfo");
$debugElement = $queryElement->appendChild($debugInfo);
$debugElement->setAttribute("dbQuery", $data['queryInfo']['dbQuery']);
$debugElement->setAttribute("clientVersion", $_SERVER['HTTP_USER_AGENT']);
$debugElement->setAttribute("requestURI", $_SERVER['REQUEST_URI']);
$debugElement->setAttribute("benchMark", $this->benchmark->marker['total_execution_time_start'].", ".$this->benchmark->marker['loading_time:_base_classes_start'].", ".$this->benchmark->marker['loading_time:_base_classes_end'].", ".$this->benchmark->marker['controller_execution_time_( api / search )_start']);
}
$queryElement->setAttribute("executionTime", $data['queryInfo']['executionTime']);
$queryElement->setAttribute("logbookURL", $this->config->item('base_url'));
// Add the main results node
$node = $xmlDoc->createElement("elements");
$elementsNode = $parentNode->appendChild($node);
// Cycle through the results and add to the results node
if($output['results'])
{
foreach($output['results'] as $e) {
$node = $xmlDoc->createElement("element");
$element = $elementsNode->appendChild($node);
foreach($e as $attr) {
#while($attr = current($e)) {
if(is_array($attr))
{
foreach($attr as $subattr)
{
$node = $xmlDoc->createElement(key($e));
foreach($subattr as $subsubattr)
{
$node->setAttribute(key($subattr), $subsubattr);
next($subattr);
}
$element->appendChild($node);
}
}
else
{
$element->setAttribute(key($e), $attr);
}
next($e);
}
}
}
// Output formatted XML
echo formatXmlString($xmlDoc->saveXML());
// This function tidies up the outputted XML
function formatXmlString($xml) {
// add marker linefeeds to aid the pretty-tokeniser (adds a linefeed between all tag-end boundaries)
$xml = preg_replace('/(>)(<)(\/*)/', "$1\n$2$3", $xml);
// now indent the tags
$token = strtok($xml, "\n");
$result = ''; // holds formatted version as it is built
$pad = 0; // initial indent
$matches = array(); // returns from preg_matches()
// scan each line and adjust indent based on opening/closing tags
while ($token !== false) :
// test for the various tag states
// 1. open and closing tags on same line - no change
if (preg_match('/.+<\/\w[^>]*>$/', $token, $matches)) :
$indent=0;
// 2. closing tag - outdent now
elseif (preg_match('/^<\/\w/', $token, $matches)) :
$pad--;
// 3. opening tag - don't pad this one, only subsequent tags
elseif (preg_match('/^<\w[^>]*[^\/]>.*$/', $token, $matches)) :
$indent=1;
// 4. no indentation needed
else :
$indent = 0;
endif;
// pad the line with the required number of leading spaces
$line = str_pad($token, strlen($token)+$pad, ' ', STR_PAD_LEFT);
$result .= $line . "\n"; // add to the cumulative result, with linefeed
$token = strtok("\n"); // get the next token
$pad += $indent; // update the pad size for subsequent lines
endwhile;
return $result;
}
?>

查看文件

@ -0,0 +1,70 @@
<h2>Add Note</h2>
<div class="wrap_content">
<?php echo validation_errors(); ?>
<form method="post" action="<?php echo site_url('notes/add'); ?>" name="notes_add" id="notes_add">
<table>
<tr>
<td><label for="title">Title</label></td>
<td><input type="text" name="title" value="" /></td>
</tr>
<tr>
<td><label for="category">Category</label></td>
<td><select name="category">
<option value="General" selected="selected">General</option>
<option value="Antennas">Antennas</option>
<option value="Satellites">Satellites</option>
</select></td>
</tr>
<tr>
<td></td>
<td><textarea name="content" id="markItUp" rows="10" cols="10"></textarea></td>
</tr>
</table>
<div><input type="submit" value="Submit" /></div>
</form>
</div>
<script type="text/javascript">
<!--
$(document).ready(function() {
// Add markItUp! to your textarea in one line
// $('textarea').markItUp( { Settings }, { OptionalExtraSettings } );
$('#markItUp').markItUp(mySettings);
// You can add content from anywhere in your page
// $.markItUp( { Settings } );
$('.add').click(function() {
$.markItUp( { openWith:'<opening tag>',
closeWith:'<\/closing tag>',
placeHolder:"New content"
}
);
return false;
});
// And you can add/remove markItUp! whenever you want
// $(textarea).markItUpRemove();
$('.toggle').click(function() {
if ($("#markItUp.markItUpEditor").length === 1) {
$("#markItUp").markItUpRemove();
$("span", this).text("get markItUp! back");
} else {
$('#markItUp').markItUp(mySettings);
$("span", this).text("remove markItUp!");
}
return false;
});
});
-->
</script>
<script type="text/javascript" src="<?php echo base_url(); ?>markitup/jquery.markitup.js"></script>
<!-- markItUp! toolbar settings -->
<script type="text/javascript" src="<?php echo base_url(); ?>markitup/sets/html/set.js"></script>
<!-- markItUp! skin -->
<link rel="stylesheet" type="text/css" href="<?php echo base_url(); ?>markitup/skins/markitup/style.css" />
<!-- markItUp! toolbar skin -->
<link rel="stylesheet" type="text/css" href="<?php echo base_url(); ?>markitup/sets/html/style.css" />

查看文件

@ -0,0 +1,72 @@
<?php foreach ($note->result() as $row) { ?>
<h2>Edit Note - <?php echo $row->title; ?></h2>
<div class="wrap_content">
<?php echo validation_errors(); ?>
<form method="post" action="<?php echo site_url('notes/edit'); ?>/<?php echo $id; ?>" name="notes_add" id="notes_add">
<table>
<tr>
<td><label for="title">Title</label></td>
<td><input type="text" name="title" value="<?php echo $row->title; ?>" /></td>
</tr>
<tr>
<td><label for="category">Category</label></td>
<td><select name="category">
<option value="General" selected="selected">General</option>
<option value="Antennas">Antennas</option>
<option value="Satellites">Satellites</option>
</select></td>
</tr>
<tr>
<td><input type="hidden" name="id" value="<?php echo $id; ?>" /></td>
<td><textarea name="content" id="markItUp" rows="10" cols="10"><?php echo $row->note; ?></textarea></td>
</tr>
</table>
<div><input type="submit" value="Submit" /></div>
</form>
</div>
<?php } ?>
<script type="text/javascript">
<!--
$(document).ready(function() {
// Add markItUp! to your textarea in one line
// $('textarea').markItUp( { Settings }, { OptionalExtraSettings } );
$('#markItUp').markItUp(mySettings);
// You can add content from anywhere in your page
// $.markItUp( { Settings } );
$('.add').click(function() {
$.markItUp( { openWith:'<opening tag>',
closeWith:'<\/closing tag>',
placeHolder:"New content"
}
);
return false;
});
// And you can add/remove markItUp! whenever you want
// $(textarea).markItUpRemove();
$('.toggle').click(function() {
if ($("#markItUp.markItUpEditor").length === 1) {
$("#markItUp").markItUpRemove();
$("span", this).text("get markItUp! back");
} else {
$('#markItUp').markItUp(mySettings);
$("span", this).text("remove markItUp!");
}
return false;
});
});
-->
</script>
<script type="text/javascript" src="<?php echo base_url(); ?>markitup/jquery.markitup.js"></script>
<!-- markItUp! toolbar settings -->
<script type="text/javascript" src="<?php echo base_url(); ?>markitup/sets/html/set.js"></script>
<!-- markItUp! skin -->
<link rel="stylesheet" type="text/css" href="<?php echo base_url(); ?>markitup/skins/markitup/style.css" />
<!-- markItUp! toolbar skin -->
<link rel="stylesheet" type="text/css" href="<?php echo base_url(); ?>markitup/sets/html/style.css" />

查看文件

@ -0,0 +1,24 @@
<h2>Note</h2>
<div class="wrap_content note">
<?php
if ($notes->num_rows() > 0)
{
echo "<ul class=\"notes_list\">";
foreach ($notes->result() as $row)
{
echo "<li>";
echo "<a href=\"".site_url()."/notes/view/".$row->id."\">".$row->title."</a>";
echo "</li>";
}
echo "</ul>";
} else {
echo "<p>You have no notes, why not create one!</p>";
}
?>
<p><a href="<?php echo site_url('notes/add'); ?>" title="Add Note">Create a Note</a></p>
</div>

查看文件

@ -0,0 +1,8 @@
<?php foreach ($note->result() as $row) { ?>
<h2>Note - <?php echo $row->title; ?></h2>
<div class="wrap_content note">
<?php echo nl2br($row->note); ?>
<p>Options: <a href="<?php echo site_url('notes/edit'); ?>/<?php echo $row->id; ?>"><img src="<?php echo base_url(); ?>images/application_edit.png" width="16" height="16" alt="Edit" /></a> <a href="<?php echo site_url('notes/delete'); ?>/<?php echo $row->id; ?>"><img src="<?php echo base_url(); ?>images/delete.png" width="16" height="16" alt="Delete" /></a></p>
</div>
<?php } ?>

52
css/api.css 普通文件
查看文件

@ -0,0 +1,52 @@
body {
background: #eee;
font-family: Verdana, sans-serif;
font-size: 8px;
}
#results table {
border: 0px solid #000;
border-collapse: collapse;
}
#results th {
padding: 4px;
border: 1px solid #000;
background-color: #6AA57B;
font-size: 11px;
}
#results td {
padding: 4px;
border: 1px solid #000;
font-size: 11px;
}
#results tr.row0 {
background-color: #A3BDF5;
}
#results tr.row1 {
background-color: #9ADF9A;
}
img {
border: 0px;
}
#footer {
font-size: 8px;
}
#debug {
border: 1px dotted #fff;
background-color: #c00;
color: #fff;
font-size: 8px;
}
#debug td {
padding: 4px;
color: #fff;
font-size: 10px;
}
.blank {
background-color: transparent;
}
.sub {
background-color: #cfc;
}
.subattr {
background-color: #cfc;
}

66
css/api.xsl 普通文件
查看文件

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head>
<title><xsl:value-of select="//queryInfo/@calledMethod"/></title>
<link rel="stylesheet" href="/css/api.css" type="text/css" />
</head>
<body>
<h1>Output of '<xsl:value-of select="//queryInfo/@calledMethod"/>'</h1>
<table id="results">
<tr>
<xsl:for-each select="//elements/element[1]/@*">
<th><b><xsl:value-of select="name()"/></b></th>
</xsl:for-each>
</tr>
<xsl:for-each select="//elements/element">
<tr class="row{position() mod 2}">
<xsl:for-each select="@*">
<td><xsl:value-of select="."/></td>
</xsl:for-each>
</tr>
<xsl:for-each select="*">
<tr>
<td class="blank"></td>
<td class="sub"><xsl:value-of select="name()"/></td>
<td class="blank" colspan="20">
<table>
<tr>
<xsl:for-each select="@*">
<td class="subattr">
<xsl:value-of select="name()"/> = <xsl:value-of select="."/>
</td>
</xsl:for-each>
</tr>
</table>
</td>
</tr>
</xsl:for-each>
</xsl:for-each>
</table>
<p/>
<xsl:if test="//debugInfo">
<div id="debug">
<table>
<tr>
<td><b>requestURI</b></td><td><xsl:value-of select="//debugInfo/@requestURI" /></td>
</tr>
<tr>
<td><b>dbQuery</b></td><td><xsl:value-of select="//debugInfo/@dbQuery" /></td>
</tr>
<tr>
<td><b>clientVersion</b></td><td><xsl:value-of select="//debugInfo/@clientVersion" /></td>
</tr>
</table>
</div>
<p/>
</xsl:if>
<div id="footer">
Retrieved from the <xsl:element name="a"><xsl:attribute name="href"><xsl:value-of select="//queryInfo/logbookURL"/>/index.php/api</xsl:attribute>HRD Web Frontend</xsl:element> API at <b><xsl:value-of select="//queryInfo/@timeStamp"/></b>. Query took <b><xsl:value-of select="//queryInfo/@executionTime"/></b> seconds.<br/>This is formatted XML using XSLT.
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>