Here is the original code:
if (($handle = fopen($source_file, "r")) !== FALSE) {
$columns = fgetcsv($handle, $max_line_length, ",");
foreach ($columns as &$column) {
$column = str_replace(".","",$column);
}
while (($data = fgetcsv($handle, $max_line_length, ",")) !== FALSE) {
while(count($data) < count($columns)) {
array_push($data, NULL);
}
$c = count($data);
for($i = 0; $i < $c; $i++) {
$data[$i] = "'{$data[$i]}'";
}
$sql[] = '(' . implode(',', $data) . ", '" . $_POST['custgroup'] . "'," . $_POST['user_id'] . ')';
}
$query = "INSERT INTO $target_table (" . implode(',', $columns) .
',custgroup,user_id) VALUES ' . implode(',', $sql);
//mysql_query($query) or trigger_error(mysql_error());
echo $query;
fclose($handle);
}
But once I added mysql_real_escape_string:
$query = "INSERT INTO $target_table (" . implode(',',array_map('mysql_real_escape_string', $columns)) .
',custgroup,user_id) VALUES ' . implode(',',array_map('mysql_real_escape_string', $sql));
The query will become :
INSERT INTO UserAddedRecord (lastname,firstname,ceLL,fax,email,code,custgroup,user_id) VALUES (\'Last\',\'First\',\'01122331\',\'\',\'abc#hotmail.com\',\'12345\', \'\',17)
I checked my php.ini and get_magic_quotes_gpc(),magic quote is disabled.
magic_quotes_gpc = Off
magic_quotes_runtime = Off
magic_quotes_sybase = Off
What should be the problem?or I should just apply stripslashes()?But I assume it will be used only when magic quote is enabled.
You should to something along the lines of:
use mysql_real_escape_string on all string values
cast all the interters to (int)
after that apply the surrounding single quotes ( ' )
The point of mysql_real_escape_string is to escape the special chars within your test content so using stripslashes would take that away.
Another way to solve that is to look into preparedStatements where you don't need to to client side esacping.
Just remember that the whole point of doing this is to prevent SQL-Injection and act accordingly :)
Related
I am trying to create a cron job in php that deletes disabled users found in a csv file and logs the deleted users to a txt file. Everything works except only the last user in the csv file is deleted. Here is what I have so far:
class purgeInactive extends JApplicationCli
{
public function doExecute()
{
$file = '../tmp/purge_user.csv';
$contents = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$csvRows = array_map('str_getcsv', $contents);
$log = ('../log/purged_users.txt');
$today = date('F j, Y, g:ia');
$row = 1;
if (($handle = fopen("../tmp/purge_user.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
$row++;
for ($c=0; $c < $num; $c++) {
file_put_contents($log, PHP_EOL . 'Removed Disabled User(s): ' . $data[$c] . PHP_EOL . '-' . $today . PHP_EOL, FILE_APPEND);
$disUsers = implode(',', $data);
echo ', ' . $disUsers ; // to test $disUsers output
} // end for statement
} // end while statment
} // end if statement
fclose($handle);
$db = JFactory::getDbo();
$user = JFactory::getUser();
$query = $db->getQuery(true);
$userArray = var_export($disUsers,true);
echo PHP_EOL.'This is to test the output of $userArray'.$userArray;
$query
->select($db->quoteName(array('id')))
->from($db->quoteName('#__users'))
//->delete ($db->quoteName('#__users'))
//->where(array($db->quoteName('username') . ' IN(' . $userArray) . ')');
->where(array($db->quoteName('username') . ' = ' . $userArray));
//->where($deleteReq);
$db->setQuery($query);
//$result = $db->execute();
$result = $db->query();
}
}
JApplicationCli::getInstance('purgeInactive')->execute();
Any suggestions on how to run each user in the csv file individually? I am about brain dead on this as I have been working on it too long.
Note: I am running Joomla that uses ldap and I use echo for $userArray to check results.
I think instead of ...
->where(array($db->quoteName('username') . ' = ' . $userArray));
You just want
->where(array($db->quoteName('username') . ' IN(' . $userArray) . ')');
That's assuming you want to delete all the rows whose usernames are in $userArray.
If the values in $userArray aren't necessarily SQL-safe, you might also want to do this first:
$userArray = array_map('mysql_real_escape_string', $userArray);
Each row of your csv is iterating this line: $disUsers = implode(',', $data);
This means that all usernames in that row will be saved to $disUsers, then the next iteration will overwrite the old data with the new row's usernames -- this is why only the final row of data is making it down to your delete query.
$data[$c] is what should be pushed into a $disUsers array like this: $disUsers[] = $data[$c];
In your query, you'll need to quote-wrap each array value; this will do that job:
->where($db->qn('username') . ' IN (' . implode(',', array_map(function($username)use($db) {return $db->q($username);}, $disUsers)) . ')')
Here is a post of mine where I discuss writing Joomla queries with IN: https://joomla.stackexchange.com/a/22898/12352
I am trying to create a class to save time on cleaning up my variables before sending them to the database to prevent sql injections. The basic systems is working now but i cant seem to get a where/or statement implemented. Does anyone know how to add this?
<?php
class Database {
private $db = '';
private $database = '';
function __construct($settings) {
$this->db = new mysqli('127.0.0.1', $settings['mysql_user']['username'], $settings['mysql_user']['password']);
$this->database = $settings['mysql_user']['database'];
print_r('Database Loaded!<br/>');
}
public function query($method, $database, $rows, $params, $where = array(), $or = array()) {
$count = 0;
$amount = count($rows);
$final_rows = '';
$final_data = '';
$bind_names = array();
$bind_names[0] = '';
$param_types = array(
"int" => "i",
"string" => "s",
"double" => "d",
"blob" => "b"
);
switch($method) {
case 'INSERT':
foreach ($rows as $row) {
$count = $count + 1;
$final_rows .= '`' . $row . '`' . ($count != $amount ? ', ' : '');
$final_data .= '?' . ($count != $amount ? ', ' : '');
}
$stmt = $this->db->prepare('INSERT INTO `' . $this->database . '`.`' . $database . '` (' . $final_rows . ') VALUES (' . $final_data . ')');
for ($i = 0; $i < count($params); $i++)
{
$bind_name = 'bind'.$i;
$$bind_name = $params[$i][1];
$bind_names[0] .= $param_types[$params[$i][0]];
$bind_names[] = &$$bind_name;
}
call_user_func_array( array ($stmt, 'bind_param'), $bind_names);
return $stmt->execute();
break;
case 'UPDATE':
foreach ($rows as $row) {
$count = $count + 1;
$final_rows .= '`' . $row . '`' . ($count != $amount ? ', ' : '');
$final_data .= '?' . ($count != $amount ? ', ' : '');
}
$stmt = $this->db->prepare('UPDATE `' . $this->database . '`.`' . $database . '` SET ' . $final_rows . '');
for ($i = 0; $i < count($params); $i++)
{
$bind_name = 'bind'.$i;
$$bind_name = $params[$i][1];
$bind_names[0] .= $param_types[$params[$i][0]];
$bind_names[] = &$$bind_name;
}
call_user_func_array( array ($stmt, 'bind_param'), $bind_names);
return $stmt->execute();
break;
case 'REPLACE':
foreach ($rows as $row) {
$count = $count + 1;
$final_rows .= '`' . $row . '`' . ($count != $amount ? ', ' : '');
$final_data .= '?' . ($count != $amount ? ', ' : '');
}
$stmt = $this->db->prepare('REPLACE INTO `' . $this->database . '`.`' . $database . '` (' . $final_rows . ') VALUES (' . $final_data . ')');
for ($i = 0; $i < count($params); $i++)
{
$bind_name = 'bind'.$i;
$$bind_name = $params[$i][1];
$bind_names[0] .= $param_types[$params[$i][0]];
$bind_names[] = &$$bind_name;
}
call_user_func_array( array ($stmt, 'bind_param'), $bind_names);
return $stmt->execute();
break;
}
}
}
?>
Going to make a few assumptions, but first I'll recommend you use an ORM before whipping up your own solution. Here's a good list of PHP libraries (I've linked to the database sections, which includes some very well done stand-alone ORMs https://github.com/ziadoz/awesome-php#database)
That being said I'm going to assume the $where and $or arrays are both for the WHERE construct and the items in $where are combined via AND and the $or is combined via OR.
Because you didn't describe what kind of output you were looking for I'm also assuming your $where and $or are key/value pairs which translates to "key=value AND key=value AND (key=value OR key=value)".
DISCLAIMER: This example is kind of hacky, but is the shortest/simplest way to get the example across.
$whereQuery = '';
foreach ($where as $key => $value) {
$whereQuery .= "$key = $value AND";
}
if ($or !== array()) {
$whereQuery .= '(';
foreach ($or as $key => $value) {
$whereQuery .= "$key = $value OR";
}
}
if ($whereQuery !== '') {
if (($temp = strlen($whereQuery) - strlen('AND')) >= 0 && strpos($whereQuery, 'AND', $temp) !== false) {
$whereQuery = substr($whereQuery, -4);
} else {
$whereQuery = substr($whereQuery, -3) . ')';
}
$whereQuery = "WHERE $whereQuery";
}
You can then stick the $whereQuery at the end of an UPDATE or SELECT. Even if $where and $or are empty it'll still work.
You could move the loops into functions and make it recursive if the $value was another array so you could create more complex WHERE statements.
In the below query I am using the str_replace function to strip out '"' from some data I am parsing. I am getting this error. Any ideas on how I can fix this? Note that line 24 has the str_replace funtion
Fatal error: Only variables can be passed by reference in /public_html/Offices/update_db.php on line 24
Query:
$i = 0;
while (($data = fgetcsv($handle, 0, $separator)) !== FALSE) {
if ($i == $first_row_offset) {
$fields = [];
foreach ($data as $key => $item) {
$fields[$item] = $key;
}
} elseif ($i > $first_row_offset) {
$query = 'SELECT * FROM offices_empty_locations WHERE address="' . str_replace('"', '\"',$data[$fields['addres']], 0, 250)) . '" AND zip="' . $data[$fields['zip']] . '"';
$result = mysqli_query($mysqli, $query);
while ($tmp_data = mysqli_fetch_assoc($result)) {
if (isset($tmp_data['latitude']) && $tmp_data['latitude'] > 0) {
$query = 'UPDATE offices_main SET field_value="' . $data[$fields['lat']] . '" WHERE id=' . $tmp_data['latitude'] . ' AND field_value=""';
mysqli_query($mysqli, $query);
}
if (isset($tmp_data['longitude']) && $tmp_data['longitude'] > 0) {
$query = 'UPDATE offices_main SET field_value="' . $data[$fields['lon']] . '" WHERE id=' . $tmp_data['longitude'] . ' AND field_value=""';
mysqli_query($mysqli, $query);
}
}
}
$i++;
}
http://php.net/manual/en/function.str-replace.php
str_replace('"', '\"',$data[$fields['addres']], 0, 250))
error ┘ │ │
what? ┘ │
nooo ┘
I need to add data in my database and one way or the other the format must be like,
0 - 0 or 1 - 5
i have tryed =>
mysqli_real_escape_string();
but did not work.
i have also tryed changing the sign to / , * , +, exp.
PHP
$dataBase->_insertDataBase('tableNaam', $input);
function _insertDataBase($tabel,$input){
$velden='';
$waarden='';
$i=0;
foreach($input AS $key=>$value){
$i=$i+1;
if($i !== count($input)){
$a=', ';
}else{
$a='';
}
$velden.=$key.$a;
$waarden.=$value.$a;
unset($a);
}
$sql = "INSERT INTO `$tabel`($velden) VALUES ($waarden)";
$this->_conn()->query($sql);
}
The problem is your SQL statement is giving the equation 5-1 as a value, so the server is doing the math and inserting 4 just like you told it to. You need tell it that it's a literal string by surrounding the values with apostrophe's (i.e. '5-1').
Replace:
foreach ($input AS $key => $value) {
$i = $i + 1;
if ($i !== count($input)) {
$a = ', ';
} else {
$a = '';
}
$velden .= $key . $a;
$waarden .= $value . $a;
unset($a);
}
With:
$velden = array();
$waarden = array();
foreach ($input AS $key => $value) {
$velden[] = $key;
$waarden[] = $value;
}
$velden = implode(',', $velden);
$waarden = "'" . implode("','", $waarden) . "'";
Or possibly even:
$velden = array_keys($input);
$waarden = array_values($input);
$velden = implode(',', $velden);
$waarden = "'" . implode("','", $waarden) . "'";
this is the first time I'm using PDO and I'm trying to create a function to inserting data in a table just by passing 3 parameters.
This is the function:
public function insert($t, $v, $r)
{
if ($this->active)
{
if (($t != null) && ($r != null) && ($v != null) && (count($v) == count($r)))
{
$instruction = 'INSERT INTO `' . DBNAME . '`.`' . $t . '` (';
for ($i = 0; $i < count($r); $i++)
$_r[$i] = '`' . $r[$i] . '`';
$_r = implode(',', $_r);
$instruction .= $_r . ') VALUES (';
for ($i = 0; $i < count($r); $i++)
$r[$i] = ':' . $r[$i];
$r = implode(',', $r);
$instruction .= $r . ');';
$statement = $this->PDO->prepare($instruction);
for ($i = 0; $i < count($r); $i++)
$statement->bindParam($r[$i], $v[$i]);
$statement->execute();
echo $instruction;
return true;
} else
return false;
} else
return false;
}
I tried this:
$t = "users";
$v = array(201);
$r = array("id_user");
$data->insert($t, $v, $r);
But it doesn't work. That's what it returns:
Warning: PDOStatement::execute() [pdostatement.execute]: SQLSTATE[HY093]: Invalid parameter number: parameter was not defined in /Applications/XAMPP/xamppfiles/htdocs/friz/mysql_functions.php on line 68
INSERT INTO friz.users (id_user) VALUES (:id_user);
Can you help me?
P.S.: I used the search function, but I didn't find anything to solve my problem.
Your line
$r = implode(',', $r);
converts $r from an array to a string;
so it no longer contains an array of names when you try to bind; so $r[$i] will simply be the first character of the string $r which is a ':'
for ($i = 0; $i < count($r); $i++)
$_r1[$i] = '`' . $r[$i] . '`';
$_r1 = implode(',', $_r1);
$instruction .= $_r1 . ') VALUES (';
for ($i = 0; $i < count($r); $i++)
$_r2[$i] = ':' . $r[$i];
$_r2 = implode(',', $_r2);
$instruction .= $_r2 . ');';
will leave $r as an array