CI active record, escapes & order_by datetime column - sql

I've noticed that when ordering by a datetime column in CI with active record, it's treating the column as a string, or int.
Example:
$this->db->limit(12);
$this->db->where('subscribed',1);
$this->db->join('profiles','profiles.user_id=users.id');
$this->db->where('active',1);
$this->db->select('users.thumbUpload,users.vanity_url');
$this->db->select('users.created_on as time');
$this->db->order_by('time');
$query = $this->db->get('users');
This is where users.created_on is a datetime field. Firstly, is it because active record is rendering time escaped, or is it something else? And if it is, can I prevent the escaping on order_by somehow?
Also, stackoverflow, please stop autocorrecting 'datetime' to 'date time'. It's annoying.
Cheers!

When you set second argument as false, function wont check and escape string. Try this
$this->db->select('users.created_on as time', FALSE);
Or for you query use
$this->db->order_by('users.created_on', 'DESC'); //or ASC
And for complex queries
$this->db->query("query");

According to the signature of the method in core files of CI (currently 2.2), it does not have any option to allow to choose whether or not to escape.
// The original prototype of the order_by()
public function order_by($orderby, $direction = '') {
// Definition
}
As you see there is not argument as $escape = true in the argument list. One way to do so is to hack this core file (I normally do not suggest it, since if you upgrade CI to a newer version later, then these changes will be lost, but if you do not intend to do so, it is OK to use it).
To do so, first change the prototype as:
public function order_by($orderby, $direction = '', $escape = true) {
// Definition
}
And then check the conditions in the following parts of definition:
// Line 842
if($escape){
$part = $this->_protect_identifiers(trim($part));
}else {
$part = trim($part);
}
// Line 856
if($escape){
$orderby = $this->_protect_identifiers($orderby);
}
When you call it, to prevent the escaping:
$this->db->order_by($ORDERBY_CLAUSE, null, false);

Related

SQLSTATE[22007]: Invalid datetime forma

I try to save some data that it brings me from my view, which is a table, but I don't know why it throws me that error with the insert.
result of insert
this is my view:
table of view
this is my controller:
$checked_array = $_POST['id_version'];
foreach ($request['id_version'] as $key => $value) {
if (in_array($request['id_version'][$key], $checked_array))
{
$soft_instal = new Software_instalacion;
$soft_instal->id_instalacion = $instalaciones->id;
$soft_instal->id_historial = $historial->id;
$soft_instal->id_usuario = $request->id_usuario;
$soft_instal->id_version = $_POST['id_version'][$key];
$soft_instal->obs_software = $_POST['obs_software'][$key];
$soft_instal->id_tipo_venta = $_POST['id_tipo_venta'][$key];
$soft_instal->save();
}
}
id_tipo_venta seems to be an empty string which is apparently not valid.
You can try debugging what you get in :
var_dump($_POST['id_tipo_venta'][$key]);
die;
Your database field expects to receive an integer. Therefore, using the intval() function can solve your problem.
Indeed, I think your code returns an alphanumeric string.
Therefore, the code below will return 0 in all cases if no version is returned (not set, string or simply null):
$soft_instal->id_tipo_venta = intval($_POST['id_tipo_venta'][$key]);
On the other hand, intval() will always convert to int, so a decimal will be converted, example :
intval("1.1") // returns 1
intval("v1.1") // returns 0
If this is not the desired behavior, maybe you should think about changing your database type.
EDIT :
Of course, you can also set the value as null if you prefer to 0. You must allow nullable values in your database.
id_tipo_venta can not be empty, try with some number or change type column to varchar in the database

Do strings need to be escaped inside parametrized queries?

I'm discovering Express by creating a simple CRUD without ORM.
Issue is, I'm not able to find any record through the Model.findBy() function
model User {
static async findBy(payload) {
try {
let attr = Object.keys(payload)[0]
let value = Object.values(payload)[0]
let user = await pool.query(
`SELECT * from users WHERE $1::text = $2::text LIMIT 1;`,
[attr, value]
);
return user.rows; // empty :-(
} catch (err) {
throw err
}
}
}
User.findBy({ email: 'foo#bar.baz' }).then(console.log);
User.findBy({ name: 'Foo' }).then(console.log);
I've no issue using psql if I surround $2::text by single quote ' like:
SELECT * FROM users WHERE email = 'foo#bar.baz' LIMIT 1;
Though that's not possible inside parametrized queries. I've tried stuff like '($2::text)' (and escaped variations), but that looks far from what the documentation recommends.
I must be missing something. Is the emptiness of user.rows related to the way I fetch attr & value ? Or maybe, is some kind of escape required when passing string parameters ?
"Answer":
As stated in the comment section, issue isn't related to string escape, but to dynamic column names.
Column names are not identifiers, and therefore cannot be dynamically set using a query parameter.
See: https://stackoverflow.com/a/50813577/11509906

If condition not working in Bean shell sampler

I am writing following script in Bean Shell sampler but it is not executed properly,
JMeter never enters in 'if' condition, what I m doing wrong?
*WRIDTEMP is a variable, WRId is a variable having value retrieved from a csv file.
if((vars.get("WRIDTEMP")==vars.get("WRId")) || vars.get("WRIDTEMP")==0)
{
String i = vars.get("C");
int counter = Integer.parseInt(i);
counter++;
vars.put("C", "" + counter);
if(counter<10 )
{
vars.put("Message",temp+authString);
}
}
You are comparing String using == , you must use .equals() method to compare them.
to compare to 0, you should do .equals("0")
I think I can confirm this issue.
I'm not sure if it's a bug or not, but what I have found is that when running this code:
String jira_version = vars.get("jiraVersion");
if (jira_version =="7") ) {
vars.put("closeIssueTitle_local","Done");
vars.put("isJIRA6_local","false");
vars.put("isJIRA7_local","true");
} else if ( jira_version.equals("6") ) {
vars.put("closeIssueTitle_local","Close Issue");
vars.put("isJIRA6_local","true");
vars.put("isJIRA7_local","false");
} else {
vars.put("closeIssueTitle_local","CLOSEISSUETITLE_BEANSHELL_FAILURE");
vars.put("isJIRA6_local","ERROR");
vars.put("isJIRA7_local","ERROR");
}
Where the value of jira_version is either literally 6 or 7, then the if condition always evaluates to it's last, no-match case.
when I change my evaluation condition to
if ( jira_version.equals("6") ) {
then it evaluates as expected.
Here's the rub for me. When I run this in the standalone beanshell environment, bsh-2.0b5.jar for example, it my code example works as expected. It's only within JMeter that I have to rely on .equals("X").
This does feel a bit like a bug.
This seems to be a bug with beanshell interpreter in jmeter. The regular beanshell shell does support string comparison using == . In fact, it is one of the features of beanshell.

Yii framework: Trying to get property of non-object

What I have:
public function beforeValidate() {
$offender = Accounts::model()->find(array('select'=>'id','condition'=>'username=:username','params'=>array(':username'=>$this->offender)));
$informer = Accounts::model()->find(array('select'=>'id','condition'=>'username=:username','params'=>array(':username'=>$this->informer)));
$this->offender = $offender->id;
$this->informer = $informer->id;
return parent::beforeValidate();
}
What I get:
PHP Notice, that says, that i'm trying to get property "id" of non-object $offender and $informer.
But those are 100% objects:
var_dump($offender):
object(Accounts)[46]
var_dump($informer):
object(Accounts)[46]
And it actually sets the right id, but shows that notice anyway. What is wrong?
SOLVED
Can't post it as official answer for six more hours, so i just leave it here:
Actually, the problem was in double beforeValidate() call.
AbuseController.php:
if(isset($_POST['AbuseReport']))
{
$model->attributes=$_POST['AbuseReport'];
if($model->validate())
{
$model->save();
}
}
First time it validates on $model->validate(), and replaces $this->offender and $this->informer with correct ID's. Second time it validates on $model->save();, but model returns null this time, because $this->offender is already ID, but it expects username.
The whole solution to this is to disable second validation: $model->save(false);.
use isset or is_object
if(isset($offender->id) || is_object($offender->id)){
$this->offender = $offender->id;
$this->informer = $informer->id;
}

PDO login script won't work

I changed this login script to PDO. Now it passes the username but get's stuck fetchAll line. I need help please. thanks
<?php
session_start();
include_once"includes/config.php";
if (isset($_POST['admin_login'])) {
$admin_user = trim($_POST['admin_user']);
$admin_pw = trim($_POST['admin_pw']);
if ($admin_user == NULL OR $admin_pw == NULL) {
$final_report.="Please complete all the fields below..";
} else {
$check_user_data = $db->prepare("SELECT * FROM `admin`
WHERE `admin_user`='$admin_user'");
$check_user_data->execute();
if ($check_user_data->fetchColumn() == 0) {
$final_report.="This admin username does not exist..";
} else {
$get_user_data = $check_user_data->fetchAll($check_user_data);
if ($get_user_data['admin_pw'] == $admin_pw) {
$start_idsess = $_SESSION['admin_user'] = "".$get_user_data['admin_user']."";
$start_passsess = $_SESSION['admin_pw'] = "".$get_user_data['admin_pw']."";
$final_report.="You are about to be logged in, please wait a few moments...";
header('Location: admin.php');
}
}
}
}
?>
Not checking return value prepare() or execute() for false. You need to check for SQL errors and handle them, stopping the code instead of continuing on blithely.
Not using query parameters in the prepared statement, still interpolating $_POST content into the query unsafely. You're missing the benefit of switching to PDO, and leaving yourself vulnerable to SQL injection attack.
You're storing passwords in plaintext, which is unsafe. See You're Probably Storing Passwords Incorrectly.
Do you really need to SELECT * if you only use the admin_pw column? Hint: no.
PDOStatement::fetchAll() returns an array of arrays, not just one array for a row. Read the examples in the documentation for fetchAll().