Sanitize and Paginate - cakephp

I was just reading that in newer versions of Cake, the Sanitize class will be removed. I'm using CakePHP 2.3 in which it I believe is already deprecated. Normally I'd use prepared statements for the query I'm trying to write, but I don't believe that's possible while using the paginate Component. ultimately I will be paginating the results, but here's the options I have so far for the query:
$options = array(
'joins' => array(
array(
'table' => '(SELECT search_terms.name, product_search_terms.product_id AS product_id_1
FROM product_search_terms
JOIN search_terms ON search_terms.id = product_search_terms.search_term_id
)',
'alias' => 'SearchTerm',
'conditions' => array(
'SearchTerm.product_id_1 = Product.id',
'LOWER(SearchTerm.name) REGEXP "[[:<:]]' . $word . '[[:>:]]"', //Here's the line that is vulnerable
)
)
),
'fields' => array('Product.id', 'SearchTerm.name'),
);
The line 'LOWER(SearchTerm.name) REGEXP "[[:<:]]' . $word . '[[:>:]]"', is surely vulnerable to SQL injection. Can this be prevented without using Sanitize or prepared statements?

Related

Don't select an habtm field in a find

I am here trying to improve one of my select.
My model is as follows:
Network
--->hasMany Esx
--->hasAndBelongToMany Environment
A network might have 0 Esx and/or 0 environments
So here I want to select some network information and the Esx section, but not the environment information.
$this->Network->find('all',array(
'conditions'=>array(
'Network.plateform'=>IAAS,
'Network.active'=>true),
'fields'=>array(
'Network.id',
'Network.name')
));
So, I can't use fields to only select the vlan field
I can't lower recursive to remove environment because it would also remove Esx
I found on SO an other question that suggest to use $this->Network->schema() and remove the unwanted fields, but it doesn't return the hm and habtm structure.
In short, how can I transform the result of this query from this
0 => array(
'Network' => array(
'id' => '38',
'name' => 'HP_LOW'),
'Esx' => array(...),
'Environment' => array(...)
)...
To this
0 => array(
'Network' => array(
'id' => '38',
'name' => 'HP_LOW'),
'Esx' => array(...)
)...
The purpose is not to just unset the Environment field, but to not select it in order to improve database perfomance.
Thank you!
Ps: Im' workin with cakephp 2.6.2
use containable
see the manual here
in your Model you have to enable the Containable Behavior
class Networkextends AppModel {
public $actsAs = array('Containable');
}
then in the controller you can do
$this->Network->find('all',array(
'conditions'=>array(
'Network.plateform'=>IAAS,
'Network.active'=>true),
'fields'=>array(
'Network.id',
'Network.name'),
'contain'=>array(
'Esx')
));

CakePHP pagination not working for a customized query

I have a query in CakePHP which somehow joins other tables to get the result I wanted.
$options = array();
$options['fields'] = array('Order.*', 'OrderCustomer.*', 'Payment.*','OrderCoupon.*', 'OrderSalesrep.*', 'OrderPackage.*');
$options['order'] = "Order.added DESC";
$options['joins'] = array(
array(
'table'=>'ordercustomers',
'alias'=>'OrderCustomer',
'type'=>'inner',
'conditions'=>array('OrderCustomer.order_id=Order.id')
),
array(
'table'=>'payments',
'alias'=>'Payment',
'type'=>'inner',
'conditions'=>array('Payment.id=Order.payment_id')
),
array(
'table'=>'ordercoupons',
'alias'=>'OrderCoupon',
'type'=>'left',
'conditions'=>array('OrderCoupon.order_id=Order.id')
),
array(
'table'=>'ordersalesreps',
'alias'=>'OrderSalesrep',
'type'=>'left',
'conditions'=>array('OrderSalesrep.order_id=Order.id')
),
array(
'table'=>'orderpackages',
'alias'=>'OrderPackage',
'type'=>'left',
'conditions'=>array('OrderPackage.order_id=Order.id')
)
);
$orders = $this->Order->find('all', $options);
$pageSettings = array();
$pageSettings['limit'] = 20;
$pageSettings['order'] = array('Order.added'=>'desc');
$this->Paginator->settings = $pageSettings;
$this->set('orders', $this->Paginator->paginate());
And then I want to paginate it on my view. Somehow it doesn't work. However I did try having only these line $orders = $this->Order->find('all', $options);$this->set('orders', $this->Paginator->paginate()); and it works. Is the pagination only working for direct queries to the model or will it also work to queries like my query above which joins other tables. Thanks.
(Don't know your cakephp version, assuming 2.x)
You are confused. You do not find something and then paginate it. The paginator component does a whole query on it's own. So what you are doing is basically
here, cakephp, find me this complex query
got it, thanks a lot, now paginate me this completely unrelated query
hey, wait, that didn't work
So, don't use simple finds for queries intended to be paginated, and likewise, don't use Paginator for simple find queries intended for something else (not saying you are doing it now, just a friendly reminder).
For the problem at hand cakephp docs has examples. This one for example
$this->Paginator->settings = array(
'conditions' => array('Recipe.title LIKE' => 'a%'),
'limit' => 10
);
$data = $this->Paginator->paginate('Recipe');
$this->set(compact('data'));
So, changing it to your problem would be something like
//the same options array
//$pageSettings = array();
$options['limit'] = 20; //this is by default, I think, so you can omit it
$options['order'] = array('Order.added'=>'desc');
$this->Paginator->settings = $options;
$this->set('orders', $this->Paginator->paginate());
and you are done. If there are errors, you can handle them case by case (or ask them here if you don't find a solution online).
Here is the Paginator API if that helps you clear doubts about functions and parameters required.

Containable behavior issue with non-standard keys?

I'm working with a legacy database whose keys follow a convention, but not the cake convention, unfortunately, and I've bumped into something odd with the containable behavior -- it's pulling the wrong data. Here's my setup:
TechnologyIncentive belongsTo...
array(
'Incentive' => array(
'className' => 'Incentive',
'type' => 'inner',
'foreignKey' => false, # actually 'incentive_id', but we need to fool Cake
'conditions' => array( 'TechnologyIncentive.incentive_id = Incentive.incentive_id' ),
),
'Technology' => array(
'className' => 'Technology',
'type' => 'inner',
'foreignKey' => false, # actually 'incentive_tech_id', but we need to fool Cake
'conditions' => array( 'TechnologyIncentive.incentive_tech_id = Technology.incentive_tech_id' )
),
);
You can see that I've had to fool Cake into working with my non-standard keys by setting the foreignKey to false and defining the link in my where clause. So far so good.
Now, when I try to run a query from the TechnologyIncentive model:
$this->find( 'all', array(
'contain' => array( 'Incentive', 'Technology' ),
'fields' => array( 'Incentive.name', 'Technology.name', 'TechnologyIncentive.amount' ),
'conditions' => array( /** conditions... */ )
);
Everything works great. Stuff is nicely contained and I get exactly what I'd expect. Then I need to include a TechnologyGroup, which hasMany Technology and things breakdown for some reason.
Now my contain option looks like this:
'contain' => array( 'Incentive', 'Technology' => array( 'TechnologyGroup' ) )
And what I get back is an Incentive record contains an incentive record. That's not entirely surprising since I'm specifying a few fields in one place (the main fields option) and implicitly all fields in the contain option, but what's really weird to me is that they're different incentives. The "contained" incentive is just wrong.
Inspecting the SQL, it looks like the query was run with no effective where clause at all, so everything is being pulled and then artificially limited to a single record. Note the difference between $result['Incentive']['incentive_id'] and $result['Incentive']['Incentive']['incentive_id'].
Array
(
[Incentive] => Array
(
[incentive_id] => MD046
[name] => Incentive name
[category] =>
[Incentive] => Array
(
[incentive_id] => AK004
[code] => AK04F
[version] => 2
[category] => Incentive Category
)
)
)
Has anyone ever bumped into this? It's not a problem until I want to retrieve an extended record (TechnologyGroup). Any thoughts would be much appreciated.
It looks like this was directly attributed to the non-standard keys. The Containable behavior, more so, it seems, that other elements of Cake really wants the convention followed. Moreover, some of the key associations included a double underscore (__) in the field name and that caused other problems.
Kids, don't try this at home. Follow the conventions, even if it means manipulating a legacy database.

Can i give conditions in contain in cakephp 1.3

i m facing some problem in find function. im fetching value fro find function.i have model.contian another model .
Can i give conditions in contain in cakephp
is it possiblehi
$this->Post->find('all', array('contain' => array(
'Comment' => array(
'conditions' => array('Comment.author =' => "Daniel"),
'order' => 'Comment.created DESC'
)
)));
You should always try the documentation first :).
isnt conditions in the format $this->ModelName->find('all',array('conditions'=>array('Table.name'=>1))); working for you?
Yes you can give conditions in contain

Cakephp find problem

I want to query as below in cakePHP.so, How can I do query using 'find' function of cakePHP .
Help me.
SELECT DISTINCT(Property.City),'city' as Fieldname FROM `properties` as Property WHERE Property.City LIKE 'las%'
Try:
$this->Property->find(
'all',
array(
'fields' => array( 'DISTINCT ( Property.city )' ),
'conditions' => array( 'Property.city LIKE' => 'las%' )
)
I threw this up from memory, but it should be close. I'm also sure that DISTINCT queries are at least mentioned in the documentation. Probably in the "complex finds" section.
Hope that helps some.

Resources