Skip to content
This repository has been archived by the owner on Nov 26, 2017. It is now read-only.

Commit

Permalink
Allowing JDatabaseDriver::quote to take an array of strings.
Browse files Browse the repository at this point in the history
If supplied with an array of strings, the quote method will return an
array of quoted strings.
Documentation for the escape and quote methods added.
Unit test updated.
  • Loading branch information
eddieajau committed Nov 26, 2012
1 parent 1885bb3 commit e94d647
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 7 deletions.
48 changes: 47 additions & 1 deletion docs/manual/en-US/chapters/packages/database.md
Expand Up @@ -5,14 +5,60 @@
The *Database* package is designed to manage the operations of data
management through the use of a generic database engine.

### Escaping strings

Strings must be escaped before using them in queries (never trust any variable input, even if it comes from a previous database query from your own data source). This can be done using the `escape` and the `quote` method.

The `escape` method will generally backslash unsafe characters (unually quote characters but it depends on the database engine). It also allows for optional escaping of additional characters (such as the underscore or percent when used in conjunction with a `LIKE` clause).

The `quote` method will escape a string and wrap it in quotes, however, the escaping can be turned off which is desirable in some situations. The `quote` method will also accept an array of strings (added in 12.3) and return an array quoted and escaped (unless turned off) string.

```php
function search($title)
{
// Get the database driver from the factory, or by some other suitable means.
$db = JFactory::getDbo();

// Search for an exact match of the title, correctly sanitising the untrusted input.
$sql1 = 'SELECT * FROM #__content WHERE title = ' . $db->quote($title);

// Special treatment for a LIKE clause.
$search = $db->quote($db->escape($title, true) . '%', false);
$sql2 = 'SELECT * FROM #__content WHERE title LIKE ' . $search;

//
if (is_array($title))
{
$sql3 = 'SELECT * FROM #__content WHERE title IN ('
. implode(',', $db->quote($title)) . ')';
}

// Do the database calls.
}
```

In the first case, the title variable is simply escaped and quoted. Any quote characters in the title string will be prepended with a backslash and the whole string will be wrapped in quotes.

In the second case, the example shows how to treat a search string that will be used in a `LIKE` clause. In this case, the title variable is manually escaped using `escape` with a second argument of `true`. This will force other special characters to be escaped (otherwise you could set youself up for serious performance problems if the user includes too many wildcards). Then, the result is passed to the `quote` method but escaping is turned off (because it has already been done manually).

In the third case, the title variable is an array so the whole array can be passed to the `quote` method (this saves using a closure and a )

Shorthand versions are available the these methods:
* `q` can be used instead of `quote`
* `e` can be used instead of `escape`

These shorthand versions are also available when using the `JDatabaseQuery` class.

### Iterating on results

The `JDatabaseIterator` class allows iteration over
database results

```php
$dbo = JFactory::getDbo();
$iterator = $dbo->setQuery($dbo->getQuery(true)->select('*')->from('#__content'))->getIterator();
$iterator = $dbo->setQuery(
$dbo->getQuery(true)->select('*')->from('#__content')
)->getIterator();
foreach ($iterator as $row)
{
// Deal with $row
Expand Down
25 changes: 21 additions & 4 deletions libraries/joomla/database/driver.php
Expand Up @@ -422,7 +422,7 @@ abstract public function disconnect();
public abstract function dropTable($table, $ifExists = true);

/**
* Method to escape a string for usage in an SQL statement.
* Escapes a string for usage in an SQL statement.
*
* @param string $text The string to be escaped.
* @param boolean $extra Optional parameter to provide extra escaping.
Expand Down Expand Up @@ -1263,18 +1263,35 @@ public function loadRowList($key = null)
public abstract function lockTable($tableName);

/**
* Method to quote and optionally escape a string to database requirements for insertion into the database.
* Quotes and optionally escapes a string to database requirements for use in database queries.
*
* @param string $text The string to quote.
* @param mixed $text A string or an array of strings to quote.
* @param boolean $escape True (default) to escape the string, false to leave it unchanged.
*
* @return string The quoted input string.
*
* @note Accepting an array of strings was added in 12.3.
* @since 11.1
*/
public function quote($text, $escape = true)
{
return '\'' . ($escape ? $this->escape($text) : $text) . '\'';
if (is_string($text))
{
return '\'' . ($escape ? $this->escape($text) : $text) . '\'';
}
elseif (is_array($text))
{
foreach ($text as $k => $v)
{
$text[$k] = $this->quote($v, $escape);
}

return $text;
}
else
{
throw new InvalidArgumentException(sprintf('%s cannot accept a %s', __METHOD__, gettype($text)));
}
}

/**
Expand Down
3 changes: 2 additions & 1 deletion libraries/joomla/database/query.php
Expand Up @@ -1241,8 +1241,9 @@ public function outerJoin($condition)
* Usage:
* $query->quote('fulltext');
* $query->q('fulltext');
* $query->q(array('option', 'fulltext'));
*
* @param string $text The string to quote.
* @param mixed $text A string or an array of strings to quote.
* @param boolean $escape True to escape the string, false to leave it unchanged.
*
* @return string The quoted input string.
Expand Down
23 changes: 22 additions & 1 deletion tests/suites/unit/joomla/database/JDatabaseTest.php
Expand Up @@ -22,7 +22,7 @@
class JDatabaseTest extends TestCaseDatabase
{
/**
* @var JDatabase
* @var JDatabase
* @since 11.4
*/
protected $db;
Expand Down Expand Up @@ -412,6 +412,7 @@ public function testStderr()
*
* @return void
*
* @covers JDatabaseDriver::quote
* @since 11.4
*/
public function testQuote()
Expand All @@ -427,6 +428,26 @@ public function testQuote()
$this->equalTo("'-test-'"),
'Tests the with escaping (default).'
);

$this->assertEquals(
array("'-test1-'", "'-test2-'"),
$this->db->quote(array('test1', 'test2')),
'Check that the array is quoted.'
);
}

/**
* Tests the JDatabase::quote method for a known exception.
*
* @return void
*
* @covers JDatabaseDriver::quote
* @expectedException InvalidArgumentException
* @since 12.3
*/
public function testQuote_exception()
{
$this->db->quote(new stdClass);
}

/**
Expand Down

0 comments on commit e94d647

Please sign in to comment.