mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
mlanthaler: Switched from file-based to database-based storage to prevent replay attacks.
(merged from branches/gsoc) git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@41812 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
4d7346825a
commit
66ccb6914a
@ -40,8 +40,12 @@ class OpenIDAuthenticator extends Authenticator {
|
|||||||
* @param Form $form Optional: If passed, better error messages can be
|
* @param Form $form Optional: If passed, better error messages can be
|
||||||
* produced by using
|
* produced by using
|
||||||
* {@link Form::sessionMessage()}
|
* {@link Form::sessionMessage()}
|
||||||
* @return bool|Member Returns FALSE if authentication fails, otherwise
|
* @return bool Returns FALSE if authentication fails, otherwise the
|
||||||
* the member object
|
* method will not return at all because the browser will be
|
||||||
|
* redirected to some other server.
|
||||||
|
*
|
||||||
|
* @todo Check if we can send the POST request for OpenID 2 directly
|
||||||
|
* (without rendering a form and using javascript)
|
||||||
*/
|
*/
|
||||||
public function authenticate(array $RAW_data, Form $form = null) {
|
public function authenticate(array $RAW_data, Form $form = null) {
|
||||||
$openid = $RAW_data['OpenIDURL'];
|
$openid = $RAW_data['OpenIDURL'];
|
||||||
@ -49,26 +53,12 @@ class OpenIDAuthenticator extends Authenticator {
|
|||||||
$trust_root = Director::absoluteBaseURL();
|
$trust_root = Director::absoluteBaseURL();
|
||||||
$return_to_url = $trust_root . 'OpenIDAuthenticator_Controller';
|
$return_to_url = $trust_root . 'OpenIDAuthenticator_Controller';
|
||||||
|
|
||||||
/**
|
$consumer = new Auth_OpenID_Consumer(new OpenIDStorage(),
|
||||||
* @todo Change the store to use the database!
|
new SessionWrapper());
|
||||||
*/
|
|
||||||
// FIXXXME
|
|
||||||
$store_path = TEMP_FOLDER;
|
|
||||||
|
|
||||||
if(!file_exists($store_path) && !mkdir($store_path)) {
|
|
||||||
print "Could not create the FileStore directory '$store_path'. ".
|
|
||||||
" Please check the effective permissions.";
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
$store = new Auth_OpenID_FileStore($store_path);
|
|
||||||
// END FIXXXME
|
|
||||||
$consumer = new Auth_OpenID_Consumer($store, new SessionWrapper());
|
|
||||||
|
|
||||||
|
|
||||||
// Begin the OpenID authentication process.
|
// No auth request means we can't begin OpenID
|
||||||
$auth_request = $consumer->begin($openid);
|
$auth_request = $consumer->begin($openid);
|
||||||
|
|
||||||
// No auth request means we can't begin OpenID.
|
|
||||||
if(!$auth_request) {
|
if(!$auth_request) {
|
||||||
if(!is_null($form)) {
|
if(!is_null($form)) {
|
||||||
$form->sessionMessage("That doesn't seem to be a valid OpenID " .
|
$form->sessionMessage("That doesn't seem to be a valid OpenID " .
|
||||||
@ -91,32 +81,23 @@ class OpenIDAuthenticator extends Authenticator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @todo Check if the POST request should be send directly (without rendering a form)
|
|
||||||
*/
|
|
||||||
// For OpenID 1, send a redirect. For OpenID 2, use a Javascript
|
|
||||||
// form to send a POST request to the server.
|
|
||||||
if($auth_request->shouldSendRedirect()) {
|
if($auth_request->shouldSendRedirect()) {
|
||||||
|
// For OpenID 1, send a redirect.
|
||||||
$redirect_url = $auth_request->redirectURL($trust_root, $return_to_url);
|
$redirect_url = $auth_request->redirectURL($trust_root, $return_to_url);
|
||||||
|
|
||||||
// If the redirect URL can't be built, display an error
|
|
||||||
// message.
|
|
||||||
if(Auth_OpenID::isFailure($redirect_url)) {
|
if(Auth_OpenID::isFailure($redirect_url)) {
|
||||||
displayError("Could not redirect to server: " . $redirect_url->message);
|
displayError("Could not redirect to server: " . $redirect_url->message);
|
||||||
} else {
|
} else {
|
||||||
Director::redirect($redirect_url);
|
Director::redirect($redirect_url);
|
||||||
// header("Location: ".$redirect_url);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Generate form markup and render it.
|
// For OpenID 2, use a javascript form to send a POST request to the
|
||||||
|
// server.
|
||||||
$form_id = 'openid_message';
|
$form_id = 'openid_message';
|
||||||
$form_html = $auth_request->formMarkup($trust_root, $return_to_url,
|
$form_html = $auth_request->formMarkup($trust_root, $return_to_url,
|
||||||
false, array('id' => $form_id));
|
false, array('id' => $form_id));
|
||||||
|
|
||||||
// Display an error if the form markup couldn't be generated;
|
|
||||||
// otherwise, render the HTML.
|
|
||||||
if(Auth_OpenID::isFailure($form_html)) {
|
if(Auth_OpenID::isFailure($form_html)) {
|
||||||
displayError("Could not redirect to server: " . $form_html->message);
|
displayError("Could not redirect to server: " . $form_html->message);
|
||||||
} else {
|
} else {
|
||||||
@ -126,12 +107,15 @@ class OpenIDAuthenticator extends Authenticator {
|
|||||||
"</title></head>",
|
"</title></head>",
|
||||||
"<body onload='document.getElementById(\"".$form_id."\").submit()'>",
|
"<body onload='document.getElementById(\"".$form_id."\").submit()'>",
|
||||||
$form_html,
|
$form_html,
|
||||||
"<p>Click "Continue" to login. You are only seeing this because you appear to have JavaScript disabled.</p>",
|
"<p>Click "Continue" to login. You are only seeing " .
|
||||||
|
"this because you appear to have JavaScript disabled.</p>",
|
||||||
"</body></html>");
|
"</body></html>");
|
||||||
|
|
||||||
print implode("\n", $page_contents);
|
print implode("\n", $page_contents);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stop the script execution! This method should return only on error
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,6 +157,8 @@ class OpenIDAuthenticator_Controller extends Controller {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Run the controller
|
* Run the controller
|
||||||
|
*
|
||||||
|
* @param array $requestParams Passed request parameters
|
||||||
*/
|
*/
|
||||||
function run($requestParams) {
|
function run($requestParams) {
|
||||||
parent::init();
|
parent::init();
|
||||||
@ -181,23 +167,8 @@ class OpenIDAuthenticator_Controller extends Controller {
|
|||||||
Profiler::mark("OpenIDAuthenticator_Controller");
|
Profiler::mark("OpenIDAuthenticator_Controller");
|
||||||
|
|
||||||
|
|
||||||
/**
|
$consumer = new Auth_OpenID_Consumer(new OpenIDStorage(),
|
||||||
* This is where the example will store its OpenID information.
|
new SessionWrapper());
|
||||||
* You should change this path if you want the example store to be
|
|
||||||
* created elsewhere. After you're done playing with the example
|
|
||||||
* script, you'll have to remove this directory manually.
|
|
||||||
*/
|
|
||||||
$store_path = TEMP_FOLDER;
|
|
||||||
|
|
||||||
if(!file_exists($store_path) && !mkdir($store_path)) {
|
|
||||||
print "Could not create the FileStore directory '$store_path'. ".
|
|
||||||
" Please check the effective permissions.";
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
$store = new Auth_OpenID_FileStore($store_path);
|
|
||||||
|
|
||||||
$consumer = new Auth_OpenID_Consumer($store, new SessionWrapper());
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Complete the authentication process using the server's response.
|
// Complete the authentication process using the server's response.
|
||||||
@ -277,8 +248,10 @@ class OpenIDAuthenticator_Controller extends Controller {
|
|||||||
* @param string $type Message type (e.g. "good" or "bad")
|
* @param string $type Message type (e.g. "good" or "bad")
|
||||||
*/
|
*/
|
||||||
function sessionMessage($message, $type) {
|
function sessionMessage($message, $type) {
|
||||||
Session::set("FormInfo.OpenIDLoginForm_LoginForm.formError.message", $message);
|
Session::set("FormInfo.OpenIDLoginForm_LoginForm.formError.message",
|
||||||
Session::set("'FormInfo.OpenIDLoginForm_LoginForm.formError.type", $type);
|
$message);
|
||||||
|
Session::set("'FormInfo.OpenIDLoginForm_LoginForm.formError.type",
|
||||||
|
$type);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
400
security/OpenIDStorage.php
Normal file
400
security/OpenIDStorage.php
Normal file
@ -0,0 +1,400 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenID storage class
|
||||||
|
*
|
||||||
|
* @author Markus Lanthaler <markus@silverstripe.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Require the {@link Auth_OpenID_MySQLStore MySQL storage class}
|
||||||
|
*/
|
||||||
|
require_once "Auth/OpenID/MySQLStore.php";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Require the
|
||||||
|
* {@link Auth_OpenID_DatabaseConnection database connection class}
|
||||||
|
*/
|
||||||
|
require_once "Auth/OpenID/DatabaseConnection.php";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenID storage class
|
||||||
|
*
|
||||||
|
* This is the interface for the store objects the OpenID library uses.
|
||||||
|
* It is a single class that provides all of the persistence mechanisms that
|
||||||
|
* the OpenID library needs, for both servers and consumers.
|
||||||
|
*
|
||||||
|
* @author Markus Lanthaler <markus@silverstripe.com>
|
||||||
|
*/
|
||||||
|
class OpenIDStorage extends Auth_OpenID_MySQLStore {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This static variable is used to decrease the number of table existence
|
||||||
|
* checks
|
||||||
|
*
|
||||||
|
* @todo Create the tables during installation, so we can reduce the
|
||||||
|
* number of needed SQL queries to a minimum and we don't need this
|
||||||
|
* variable anymore
|
||||||
|
*/
|
||||||
|
private static $S_checkedTableExistence = false;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* The constructor will check (once per script execution; with help of a
|
||||||
|
* static variable) if the needed tables exist, otherwise it will create
|
||||||
|
* them.
|
||||||
|
*
|
||||||
|
* @param string $associations_table This is an optional parameter to
|
||||||
|
* specify the name of the table used
|
||||||
|
* for storing associations.
|
||||||
|
* The default value is
|
||||||
|
* 'authentication_openid_associations'.
|
||||||
|
* @param string $nonces_table This is an optional parameter to specify
|
||||||
|
* the name of the table used for storing
|
||||||
|
* nonces.
|
||||||
|
* The default value is
|
||||||
|
* 'authentication_openid_nonces'.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @todo Should the max. nonce age be configurable?
|
||||||
|
* @todo Create the tables during installation, so we can reduce the
|
||||||
|
* number of needed SQL queries.
|
||||||
|
*/
|
||||||
|
function __construct($associations_table = null, $nonces_table = null)
|
||||||
|
{
|
||||||
|
if(is_null($associations_table))
|
||||||
|
$associations_table = 'authentication_openid_associations';
|
||||||
|
|
||||||
|
if(is_null($nonces_table))
|
||||||
|
$nonces_table = 'authentication_openid_nonces';
|
||||||
|
|
||||||
|
$connection = new OpenIDDatabaseConnection();
|
||||||
|
|
||||||
|
parent::__construct($connection, $associations_table, $nonces_table);
|
||||||
|
|
||||||
|
|
||||||
|
if(self::$S_checkedTableExistence == false) {
|
||||||
|
$table_list = (!isset(DB::getConn()->tableList))
|
||||||
|
? $table_list = DB::tableList()
|
||||||
|
: DB::getConn()->tableList;
|
||||||
|
|
||||||
|
$this->connection->autoCommit(true);
|
||||||
|
|
||||||
|
if(!isset($table_list[strtolower($this->associations_table_name)]))
|
||||||
|
$this->create_assoc_table();
|
||||||
|
|
||||||
|
if(!isset($table_list[strtolower($this->nonces_table_name)]))
|
||||||
|
$this->create_nonce_table();
|
||||||
|
|
||||||
|
$this->connection->autoCommit(false);
|
||||||
|
DB::tableList();
|
||||||
|
|
||||||
|
self::$S_checkedTableExistence = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called by the constructor to set values in $this->sql,
|
||||||
|
* which is an array keyed on sql name.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
function setSQL()
|
||||||
|
{
|
||||||
|
parent::setSQL();
|
||||||
|
|
||||||
|
$this->sql['nonce_table'] =
|
||||||
|
"CREATE TABLE %s (\n".
|
||||||
|
" server_url VARCHAR(2047),\n".
|
||||||
|
" timestamp INTEGER,\n".
|
||||||
|
" salt CHAR(40),\n".
|
||||||
|
" UNIQUE (server_url(255), timestamp, salt)\n".
|
||||||
|
")";
|
||||||
|
|
||||||
|
$this->sql['assoc_table'] =
|
||||||
|
"CREATE TABLE %s (\n".
|
||||||
|
" server_url BLOB,\n".
|
||||||
|
" handle VARCHAR(255),\n".
|
||||||
|
" secret BLOB,\n".
|
||||||
|
" issued INTEGER,\n".
|
||||||
|
" lifetime INTEGER,\n".
|
||||||
|
" assoc_type VARCHAR(64),\n".
|
||||||
|
" PRIMARY KEY (server_url(255), handle)\n".
|
||||||
|
")";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constitutes the passed value a database error?
|
||||||
|
*
|
||||||
|
* @return Returns TRUE if $value constitutes a database error; returns
|
||||||
|
* FALSE otherwise.
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
function isError($value)
|
||||||
|
{
|
||||||
|
return ($value === false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the nonce table
|
||||||
|
*
|
||||||
|
* @return bool Returns TRUE on success, FALSE on failure.
|
||||||
|
*/
|
||||||
|
function create_nonce_table()
|
||||||
|
{
|
||||||
|
return $this->resultToBool(
|
||||||
|
$this->connection->query($this->sql['nonce_table']));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the associations table
|
||||||
|
*
|
||||||
|
* @return bool Returns TRUE on success, FALSE on failure.
|
||||||
|
*/
|
||||||
|
function create_assoc_table()
|
||||||
|
{
|
||||||
|
return $this->resultToBool(
|
||||||
|
$this->connection->query($this->sql['assoc_table']));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper that emulates PEAR connection functionality which is needed for
|
||||||
|
* the {@link OpenIDStorage} class.
|
||||||
|
*
|
||||||
|
* @author Markus Lanthaler <markus@silverstripe.com>
|
||||||
|
*
|
||||||
|
* @todo If the new database abstraction adds support for transactions and
|
||||||
|
* prepared statements (placeholders) use that code without emulating
|
||||||
|
* it here.
|
||||||
|
*/
|
||||||
|
class OpenIDDatabaseConnection extends Auth_OpenID_DatabaseConnection {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run an SQL query with the specified parameters, if any.
|
||||||
|
*
|
||||||
|
* @param string $sql An SQL string with placeholders. A '?' is used for
|
||||||
|
* values to put into quotes, and a '!' for values that
|
||||||
|
* should not be quoted.
|
||||||
|
* @param array $params An array of parameters to insert into the SQL
|
||||||
|
* string using this connection's escaping mechanism.
|
||||||
|
* @return mixed $result The result of calling this connection's internal
|
||||||
|
* query function.
|
||||||
|
* The type of result depends on the underlying
|
||||||
|
* database engine. This method is usually used when
|
||||||
|
* the result of a query is not important, like a
|
||||||
|
* DDL query.
|
||||||
|
*/
|
||||||
|
public function query($sql, $params = array())
|
||||||
|
{
|
||||||
|
if(($sql = $this->generateQuery($sql, $params)) === false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return DB::query($sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run an SQL query and return the first column of the first row
|
||||||
|
* of the result set, if any.
|
||||||
|
*
|
||||||
|
* @param string $sql An SQL string with placeholders. A '?' is used for
|
||||||
|
* values to put into quotes, and a '!' for values that
|
||||||
|
* should not be quoted.
|
||||||
|
* @param array $params An array of parameters to insert into the SQL
|
||||||
|
* string using this connection's escaping mechanism.
|
||||||
|
* @return mixed $result The value of the first column of the first row of
|
||||||
|
* the result set.
|
||||||
|
* FALSE if no such result was found.
|
||||||
|
*/
|
||||||
|
public function getOne($sql, $params = array())
|
||||||
|
{
|
||||||
|
if(($sql = $this->generateQuery($sql, $params)) === false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(($result = DB::query($sql)) === false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return $result->value();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run an SQL query and return the first row of the result set, if
|
||||||
|
* any.
|
||||||
|
*
|
||||||
|
* @param string $sql An SQL string with placeholders. A '?' is used for
|
||||||
|
* values to put into quotes, and a '!' for values that
|
||||||
|
* should not be quoted.
|
||||||
|
* @param array $params An array of parameters to insert into the SQL
|
||||||
|
* string using this connection's escaping mechanism.
|
||||||
|
* @return array $result The first row of the result set, if any, keyed on
|
||||||
|
* column name.
|
||||||
|
* FALSE if no such result was found.
|
||||||
|
*/
|
||||||
|
public function getRow($sql, $params = array())
|
||||||
|
{
|
||||||
|
if(($sql = $this->generateQuery($sql, $params)) === false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(($result = DB::query($sql)) === false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return $result->record();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run an SQL query with the specified parameters, if any.
|
||||||
|
*
|
||||||
|
* @param string $sql An SQL string with placeholders. A '?' is used for
|
||||||
|
* values to put into quotes, and a '!' for values that
|
||||||
|
* should not be quoted.
|
||||||
|
* @param array $params An array of parameters to insert into the SQL
|
||||||
|
* string using this connection's escaping mechanism.
|
||||||
|
* @return array $result An array of arrays representing the result of the
|
||||||
|
* query; each array is keyed on column name.
|
||||||
|
*/
|
||||||
|
public function getAll($sql, $params = array())
|
||||||
|
{
|
||||||
|
if(($sql = $this->generateQuery($sql, $params)) === false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(($result = DB::query($sql)) === false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for($result_array = array(); $result->valid(); $result->next()) {
|
||||||
|
array_push($result_array, $result->current());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets auto-commit mode on this database connection.
|
||||||
|
*
|
||||||
|
* @param bool $mode TRUE if auto-commit is to be used; FALSE if not.
|
||||||
|
*/
|
||||||
|
public function autoCommit($mode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a transaction on this connection, if supported.
|
||||||
|
*/
|
||||||
|
public function begin()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Commits a transaction on this connection, if supported.
|
||||||
|
*/
|
||||||
|
public function commit()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a rollback on this connection, if supported.
|
||||||
|
*/
|
||||||
|
public function rollback()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats input so it can be safely used in a query
|
||||||
|
*
|
||||||
|
* @param string $sql An SQL string with placeholders. A '?' is used for
|
||||||
|
* values to put into quotes, and a '!' for values that
|
||||||
|
* should not be quoted.
|
||||||
|
* @param array $params An array of parameters to insert into the SQL
|
||||||
|
* string using this connection's escaping mechanism.
|
||||||
|
* @return bool|string $result A valid SQL string with all parameters
|
||||||
|
* properly escaped or FALSE if an invalid SQL
|
||||||
|
* string or an invalid number of parameters
|
||||||
|
* was passed.
|
||||||
|
*/
|
||||||
|
private function generateQuery($sql, $params = array())
|
||||||
|
{
|
||||||
|
$tokens = preg_split('/((?<!\\\)[&?!])/', $sql, -1,
|
||||||
|
PREG_SPLIT_DELIM_CAPTURE);
|
||||||
|
$token = 0;
|
||||||
|
$types = array();
|
||||||
|
$newtokens = array();
|
||||||
|
|
||||||
|
foreach ($tokens as $val) {
|
||||||
|
switch ($val) {
|
||||||
|
case '?':
|
||||||
|
$types[$token++] = 'SCALAR';
|
||||||
|
break;
|
||||||
|
case '!':
|
||||||
|
$types[$token++] = 'MISC';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$newtokens[] = preg_replace('/\\\([&?!])/', "\\1", $val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(count($types) != count($params))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
|
||||||
|
$realquery = $newtokens[0];
|
||||||
|
$i = 0;
|
||||||
|
|
||||||
|
foreach($params as $value) {
|
||||||
|
if($types[$i] == 'SCALAR') {
|
||||||
|
$realquery .= $this->quote($value);
|
||||||
|
} else {
|
||||||
|
$realquery .= $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
$realquery .= $newtokens[++$i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $realquery;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats input so it can be safely used in a query
|
||||||
|
*
|
||||||
|
* @param mixed $in The data to be formatted
|
||||||
|
* @return mixed The formatted data. The format depends on the input's
|
||||||
|
* PHP type-
|
||||||
|
*/
|
||||||
|
private function quote($in)
|
||||||
|
{
|
||||||
|
if(is_int($in)) {
|
||||||
|
return $in;
|
||||||
|
} elseif(is_float($in)) {
|
||||||
|
return "'" . Convert::raw2sql(
|
||||||
|
str_replace(',', '.', strval(floatval($in)))) . "'";
|
||||||
|
} elseif(is_bool($in)) {
|
||||||
|
return ($in) ? '1' : '0';
|
||||||
|
} elseif(is_null($in)) {
|
||||||
|
return 'NULL';
|
||||||
|
} else {
|
||||||
|
return "'" . Convert::raw2sql($in) . "'";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
Loading…
Reference in New Issue
Block a user