I'm working on an application using ZF2. In my application, I have to insert many rows in a database (about 900).
I've got a table model for this, so I first try to do :
$table->insert(array('x' => $x, 'y' => $y));
in my loop. This technically work, but this is so slow that I can hardly insert half of the datas before php's timeout (and I can't change the timeout).
Then, I've decide to use a prepared statment. So I've prepared it outside of the loop, then execute it in my loop... it was even slower.
So, I decide to stop using ZF2 tools, as they seems to be too slow to be used in my case, and i've created my own request. I'm using mysql, so i can do a single request with all my values. But I can't find any method in any of the interface to escape my values...
Is there any way to do this ?
Thank you for your help and sorry for my poor english.
If you want to perform raw queries you can do so using the Database Adapter:
$sql = 'SELECT * FROM '
. $adapter->platform->quoteIdentifier('users')
. ' WHERE ' . $adapter->platform->quoteIdentifier('id') . ' = ' . $adapter->driver->formatParameterName('id');
/* #var $statement \Zend\Db\Adapter\Driver\StatementInterface */
$statement = $adapter->query($sql);
$parameters = array('id' => 99);
/* #var $results Zend\Db\ResultSet\ResultSet */
$results = $statement->execute($parameters);
$row = $results->current();
use transactions: http://dev.mysql.com/doc/refman/5.0/en/commit.html
Than will help you to decrease the execution time
Related
I want to update a topic with a post id in Wordpress and add it to the end of the post. However, I could not run the code below. Can you help?
wp_update_post(['ID' => $posts->ID,"post_content" => "concat_ws(' ',post_content, 'SECOND')"]);
Normally, this process is done over sql with concat. But I want to use it with php.
The version that works with sql;
update test_user set descrip = concat_ws(' ',descrip, 'SECOND') where Id=2
but I want to run it with php, not sql. How should the first code be?
You can use braces or concatenation operator .
echo "qwe{$a}rty"; // qwe12345rty, using braces
echo "qwe" . $a . "rty"; // qwe12345rty, concatenation used
Also, it much better to use WP_Post class than modify data in tables directly.
Your WP instance can use some db caching layer, or some hooks for posts updating. This functionality can be
potentially broken if you work with tables directly.
$post = get_post( 123 );
$post->post_content = $post->post_content . "Some other content";
wp_update_post( $post );
I am using prepared statements for a search functionality using PDO and I am using the like clause. Mysql is 5.5.32
function dblink(){
# hidden #
$conn = new PDO("mysql:host=localhost;dbname=$database",
$username, $password, array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ
));
return $conn;
}
$conn = dblink();
$query = "select * from tablename where attrib like ? ;";
$stmt = $conn->prepare($query);
$stmt->execute(array($_POST['field']."%"));
$results = $stmt->fetchAll(PDO::FETCH_OBJ);
This dumps all the table contents when user enters % for field in the html form. I thought prepared statement would handle it and there is % in execute so that it matches the substring entered.
How do I use the POST field as normal text only so that it doesn't cause such problem?
This dumps all the table contents when user enters % for field in the html form.
Yes. That's the exact purpose of LIKE operator.
No, it has nothing to do with prepared statement. The latter is used to format your data, not to interfere with query logic.
If you don't like the way your code works - change it. But at the moment it works exactly the way you coded, with no flaws.
Due to errors of my predecessors a (MySQL) database I would like to use contains a lot of HTML entities (e.g. € instead of €).
As the database should contain raw data (a database shouldn't have anything to do with HTML) I want to remove them from the DB and store it in proper UTF8, the collocation is already that.
What would be a good way to fix this? The only thing I can think of is to write a PHP script that gets all the data, runs it through html_entity_decode() and writes it back. It's doable since it's a one-time-operation and the DB is only about 100MB large, but it's still less than optimal.
Any ideas?
Since no-one could provide a satisfying SQL-only solution, I solved it with a script similar to this one.
Note that it only works if all the tables you use it on have a primary key, but this will usually be the case
<?php
// Specify which columns need to be de-entitiezed
$affected = array(
'table1' => array('column1', 'column2'),
'table2' => array('column1', 'column2'),
);
// Make database connection
$db = new PDO("mysql:dbname=yourdb;host=yourhost", "user", "pass");
foreach($affected as $table => $columns){
// Start a transaction for each table
$db->beginTransaction();
// Find the table primary key. PHP5.4 syntax!
$pk = $db->query("SHOW INDEX FROM " . $table . " WHERE Key_name = 'PRIMARY'")->fetch()[0];
foreach($columns as $column){
// Construct a prepared statement for this column
$ps = $db->prepare("UPDATE " . $table . " SET " . $column . " . = ? WHERE " . $pk . " = ?");
// Go through all rows
foreach( $db->query("SELECT " . $column . ", " . $pk . " FROM " . $table) as $row){
$row[0] = html_entity_decode($row[0]); // Actual processing
$ps->execute($row);
}
}
// Everything went well for this table, commit
$db->commit();
}
?>
I tnink u need to create a mysql procedure. (with SELECT loop and update replace) REPLACE(TextString, ''','"') ;
Depending on the database (Oracle, MySql, etc) and whether you can take it offline you might be able to export all the DDL and data as a large SQL script (containing INSERTs for all the tables). Then you could do a standard search/replace using sed:
sed -i 's/€/€/g' script.sql
then drop the database or truncate the tables and recreate it using the script.
Ultimately I think you are going to have to resort to PHP at some stage, converting a lot of these entites in SQL is going to invole a huge amount of desicion logic.
However, One approach I can think of if you must use SQL, is to create a user defined function, that esentially has a huge case statement in (Or lots of if/then's) :
http://dev.mysql.com/doc/refman/5.0/en/case-statement.html
Then you should simply be able to do something like:
SELECT col1,col2,col3,mtuserdecodefunction(column-with-entities-in) FROM mytable
Which should in theory return you a cleaned table.
I have this site with the following parameters:
http://www.example.com.com/pagination.php?page=4&order=comment_time&sc=desc
I use the values of each of the parameters as a value in a SQL query.
I am trying to test my application and ultimately hack my own application for learning purposes.
I'm trying to inject this statement:
http://www.example.com.com/pagination.php?page=4&order=comment_time&sc=desc' or 1=1 --
But It fails, and MySQL says this:
Warning: mysql_fetch_assoc() expects parameter 1 to be resource,
boolean given in /home/dir/public_html/pagination.php on line 132
Is my application completely free from SQL injection, or is it still possible?
EDIT: Is it possible for me to find a valid sql injection statement to input into one of the parameters of the URL?
The application secured from sql injection never produces invalid queries.
So obviously you still have some issues.
Well-written application for any input produces valid and expected output.
That's completely vulnerable, and the fact that you can cause a syntax error proves it.
There is no function to escape column names or order by directions. Those functions do not exist because it is bad style to expose the DB logic directly in the URL, because it makes the URLs dependent on changes to your database logic.
I'd suggest something like an array mapping the "order" parameter values to column names:
$order_cols = array(
'time' => 'comment_time',
'popular' => 'comment_score',
... and so on ...
);
if (!isset($order_cols[$_GET['order'])) {
$_GET['order'] = 'time';
}
$order = $order_cols[$_GET['order']];
Restrict "sc" manually:
if ($_GET['sc'] == 'asc' || $_GET['sc'] == 'desc') {
$order .= ' ' . $_GET['sc'];
} else {
$order .= ' desc';
}
Then you're guaranteed safe to append that to the query, and the URL is not tied to the DB implementation.
I'm not 100% certain, but I'd say it still seems vulnerable to me -- the fact that it's accepting the single-quote (') as a delimiter and then generating an error off the subsequent injected code says to me that it's passing things it shouldn't on to MySQL.
Any data that could possibly be taken from somewhere other than your application itself should go through mysql_real_escape_string() first. This way the whole ' or 1=1 part gets passed as a value to MySQL... unless you're passing "sc" straight through for the sort order, such as
$sql = "SELECT * FROM foo WHERE page='{$_REQUEST['page']}' ORDER BY data {$_REQUEST['sc']}";
... which you also shouldn't be doing. Try something along these lines:
$page = mysql_real_escape_string($_REQUEST['page']);
if ($_REQUEST['sc'] == "desc")
$sortorder = "DESC";
else
$sortorder = "ASC";
$sql = "SELECT * FROM foo WHERE page='{$page}' ORDER BY data {$sortorder}";
I still couldn't say it's TOTALLY injection-proof, but it's definitely more robust.
I am assuming that your generated query does something like
select <some number of fields>
from <some table>
where sc=desc
order by comment_time
Now, if I were to attack the order by statement instead of the WHERE, I might be able to get some results... Imagine I added the following
comment_time; select top 5 * from sysobjects
the query being returned to your front end would be the top 5 rows from sysobjects, rather than the query you try to generated (depending a lot on the front end)...
It really depends on how PHP validates those arguments. If MySQL is giving you a warning, it means that a hacker already passes through your first line of defence, which is your PHP script.
Use if(!preg_match('/^regex_pattern$/', $your_input)) to filter all your inputs before passing them to MySQL.
I have some extremely complex queries that I need to use to generate a report in my application. I'm using symfony as my framework and doctrine as my ORM.
My question is this:
What is the best way to pass in highly-complex sql queries directly to Doctrine without converting them to the Doctrine Query Language? I've been reading about the Raw_SQL extension but it appears that you still need to pass the query in sections (like from()). Is there anything for just dumping in a bunch of raw sql commands?
$q = Doctrine_Manager::getInstance()->getCurrentConnection();
$result = $q->execute(" -- RAW SQL HERE -- ");
See the Doctrine API documentation for different execution methods.
Yes. You can get a database handle from Doctrine using the following code:
$pdo = Doctrine_Manager::getInstance()->getCurrentConnection()->getDbh();
and then execute your SQL as follows:
$query = "SELECT * FROM table WHERE param1 = :param1 AND param2 = :param2";
$stmt = $pdo->prepare($query);
$params = array(
"param1" => "value1",
"param2" => "value2"
);
$stmt->execute($params);
$results = $stmt->fetchAll();
You can use bound variables as in the above example.
Note that Doctrine won't automatically hydrate your results nicely into record objects etc, so you'll need to deal with the results being returned as an array, consisting of one array per row returned (key-value as column-value).
I'm not sure what do you mean saying raw SQL, but you coud execute traditional SQL queries this way:
...
// $this->_displayPortabilityWarning();
$conn = Doctrine_Manager::connection();
$pdo = $conn->execute($sql);
$pdo->setFetchMode(Doctrine_Core::FETCH_ASSOC);
$result = $pdo->fetchAll();
...
The following method is not necsessary, but it shows a good practice.
protected function _displayPortabilityWarning($engine = 'pgsql')
{
$conn = Doctrine_Manager::connection();
$driver = $conn->getDriverName();
if (strtolower($engine) != strtolower($driver)) {
trigger_error('Here we have possible database portability issue. This code was tested on ' . $engine . ' but you are trying to run it on ' . $driver, E_USER_NOTICE);
}
}
You can also use Doctrine_RawSql(); to create raw SQL queries which will hydrate to doctrine objects.
It should be noted, that Doctrine2 uses PDO as a base, thus I would recommend using prepared statements over plain old execute.
Example:
$db = Doctrine_Manager::getInstance()->getCurrentConnection();
$query = $db->prepare("SELECT `someField` FROM `someTable` WHERE `field` = :value");
$query->execute(array('value' => 'someValue'));
Symfony insert raw sql using doctrine.
This in version Symfoney 1.3
$q = Doctrine_Manager::getInstance()->getCurrentConnection();
$result = $q->execute($query);