security on insert batch? codeigniter - codeigniter

can anyone know how to preventing user input, on codeigniter if i use insert_batch? sorry bad english
code like this
$data[] = array(
'id_invoice' => $this->input->post('id_invoice'),
'id_product' => $key['id_product'],
'id_fabrics' => $key['id_fabric'],
'id_option' => $id_option,
'name' => $key['name'],
'number' => $key['number'],
'id_size' => $key['size'],
'comment' => $key['comment']);
and use insert batch like this
$this->orders->insert_order_mix($data);

So Simple You can remove abuse tags and data from user input
//Change This
$this->orders->insert_order_mix($data);
// to
$data = $this->security->xss_clean($data); // You have to clean Data with XSS Filtering
$this->orders->insert_order_mix($data);
This method Clean your all abuse data with [removed] keyword
if user can input any script then XSS filtering remove as per below
$name = '<script>Your Name</script>';
echo $name; // Output : <script>Your Name</script>
// But you use XSS then output is change as per below
$name = '<script>Your Name</script>';
$name = $this->security->xss_clean($name);
echo $name; // Output : [removed]Your Name[removed]
Or You can use very simple with edit your config file
// Change global_xss_filtering value FALSE to TRUE;
/*
|--------------------------------------------------------------------------
| Global XSS Filtering
|--------------------------------------------------------------------------
|
| Determines whether the XSS filter is always active when GET, POST or
| COOKIE data is encountered
|
*/
$config['global_xss_filtering'] = TRUE;

I think you are confused with the concept of Batch Insert. Please READ THIS to get a good understanding of Batch Insert. Now for your issue, it's very good to be concerned about security these days as said
Always filter input and escape output, Never trust data.
You can Use Codeigniter Security Class to secure your data.
E.g
$data=$this->security->xss_clean($this->input->post());
OR
$postData=$this->input->post();
$data=$this->security->xss_clean($postData);
Furthermore you can avoid Cross Site Request Forgery by using CSRF token in your Forms

Thanks for your answer, i am not sure about your answer because i am using ajax to get data, and data is on array format, and this is my code to process on controller
if (!$this->input->is_ajax_request()) {
exit('No direct script access allowed');
} else {
$input = $this->input->post('ar_dat');
$option = $this->input->post('list_option');
if ($option == null){
$id_option = '';
} else {
$id_option = implode(',',$option);
}
foreach ($input as $key) {
$data[] = array(
'id_invoice' => $this->input->post('id_invoice'),
'id_product' => $this->input->post('id_product'),
'id_fabrics' => $this->input->post('id_fabric'),
'id_option' => $id_option,
'name' => $key['name'],
'number' => $key['number'],
'id_size' => $key['size'],
'comment' => $key['comment']);
}
$this->orders->insert_order_uniform($data);
}

Related

change password when is set

i want to change password in my update method , when is $request->data['password'] is set and is not null
if is not set old password be replace
this is my code but i'm faced with error !
$user=Model::whereId($id)->update([
"updated_at" => Carbon::now(),
"department_id" => $department,
"username" => $request->data['username'],
'password'=>isset($request->data['password'])?bcrypt($request->data['password']):$user->password,
]);
You can use this solution
$data = [
"updated_at" => Carbon::now(),
"department_id" => $department,
"username" => $request->data['username'],
];
if (! empty($request->data['password'])) {
$data["password"] = bcrypt($request->data['password']);
}
$user = Model::whereId($id)->update($data);
isset checks if the password field exists in the request but if it exists there and is null then it will still pass through. Also your ternary is the other way around.
you can use empty for what you are trying to achieve like:
'password'=>!empty($request->data['password'])?bcrypt($request->data['password']):$user->password,
But if you want to use the ternary there then you must have retrieved your user model before that so your fallback actually has the value of the user password in the database. A similar approach is:
$user=Model::whereId($id)->first();
$user->updated_at = Carbon::now();
$user->department_id => $department;
$user->username = $request->data['username'];
if(!empty($request->data['password']){
$user->password=bcrypt($request->data['password']);
}
$user->save();
That way you don't need a fallback. Returning the user model with the latest changes you can use the fresh() function after you save()
return $user->fresh()
Use "dot" notation to access the arrays (like name="data['password']") :
$password = $request->input('data.password');
$model = Model::find($id);
$model->username = $request->input('data.username');
$model->department_id = $department;
if($password){
$model->password = Hash::make($password);
}
$model->save();
You may use the has method to determine if a value is present on the request. The has method returns true if the value is present on the request:
if ($request->has('data.password')) {
//
}
Or use whenHas. The whenHas method will execute the given closure if a value is present on the request:
$request->whenHas('data.password', function ($input) {
//
});

How to approach caching in ZF2

I am just starting to get my head into caching as a whole. I have a simple indexAction() that fetches all given Datasets. My approach is:
check for existing key 'controllername-index-index'
if existing: return the value of the key
if not existing, do the normal action and add the key
The value inside the key should be the ViewModel that will be generated and populated with my data.
Here's what i have done so far:
<?php
public function indexAction()
{
$sl = $this->getServiceLocator();
// $cache = $sl->get('cache');
// $key = 'kennzahlen-index-index';
//
// if ($cache->hasItem($key)) {
// return $cache->getItem($key);
// }
$viewModel = new ViewModel();
$viewModel->setTemplate('kennzahlen/index/index');
$entityService = $sl->get('kennzahlen_referenzwert_service');
$viewModel->setVariable('entities', $entityService->findAll());
// $cache->setItem($key, $viewModel);
return $viewModel;
}
The Caching parts are commented out for testing purposes, but basically this is all that i am doing. The Caching config/service looks like the following:
<?php
'cache' => function () {
return \Zend\Cache\StorageFactory::factory(array(
'adapter' => array(
'name' => 'filesystem',
'options' => array(
'cache_dir' => __DIR__ . '/../../data/cache',
'ttl' => 100
),
),
'plugins' => array(
array(
'name' => 'serializer',
'options' => array(
)
)
)
));
},
The serialization and caching works quite well, but i am surprised by the missing results. Going by what the ZendDevelopersToolbar tells me, the times WITHOUT caching range between 1.8s to 2.5s. Having the caching parts uncommented (enabled) doesn't really improve the loading time of my page at all.
So my question is: Is this approach completely wrong? Are there different, more speedy parts, that can be saved with some neat configuration tricks?
I Feel that a 2 second load time of a page is DEFINITELY too slow. 1s to me is the maximum given a huge amount of data, but certainly not anything more than that :S
All help/hints/suggestions will be greatly appreciated. Thanks in advance!
One option would be to cache the complete output of your page, for example based on the route match. You need to listen between routing and dispatching which route has been found as match and then act accordingly:
namespace MyModule;
use Zend\Mvc\MvcEvent;
class Module
{
public function onBootstrap(MvcEvent $e)
{
// A list of routes to be cached
$routes = array('foo/bar', 'foo/baz');
$app = $e->getApplication();
$em = $app->getEventManager();
$sm = $app->getServiceManager();
$em->attach(MvcEvent::EVENT_ROUTE, function($e) use ($sm) {
$route = $e->getRouteMatch()->getMatchedRouteName();
$cache = $sm->get('cache-service');
$key = 'route-cache-' . $route;
if ($cache->hasItem($key)) {
// Handle response
$content = $cache->getItem($key);
$response = $e->getResponse();
$response->setContent($content);
return $response;
}
}, -1000); // Low, then routing has happened
$em->attach(MvcEvent::EVENT_RENDER, function($e) use ($sm, $routes) {
$route = $e->getRouteMatch()->getMatchedRouteName();
if (!in_array($route, $routes)) {
return;
}
$response = $e->getResponse();
$content = $response->getContent();
$cache = $sm->get('cache-service');
$key = 'route-cache-' . $route;
$cache->setItem($key, $content);
}, -1000); // Late, then rendering has happened
}
}
The second listener checks at the render event. If that happens, the result of the response will be cached.
This system (perhaps not with 100% copy/paste, but the concept) works because if you return a Response during the route or dispatch event, the application will short circuit the application flow and stop further triggering listeners. It will then serve this response as it is.
Bear in mind it will be the complete page (including layout). If you don't want that (only the controller), move the logic to the controller. The first event (now route) will be dispatch of the controller. Listen to that early, so the normal execution of the action will be omitted. To cache the result, check the render event for the view layer to listen to.
/update: I wrote a small module to use this DRY in your app: SlmCache

CodeIgniter: unset all userdata, but not destroy the session

Is there a way to unset ALL userdata in a session without having to use session destroy? I'm trying to log my user out and need to unset all userdata one at a time. It's becoming tedious to keep track of all possible userdata set in session. I just want to unset everything that might have been set in userdata.
This is very simple!
$this->session->unset_userdata('some_name');
or
$array_items = array('username' => '', 'email' => '');
$this->session->unset_userdata($array_items);
I hope this helps!
Edit: It looks like you actually don't keep track of anything in your session (kind of strange?). You could call this function I wrote up:
function unset_only() {
$user_data = $this->session->all_userdata();
foreach ($user_data as $key => $value) {
if ($key != 'session_id' && $key != 'ip_address' && $key != 'user_agent' && $key != 'last_activity') {
$this->session->unset_userdata($key);
}
}
}
Of course, that assumes you use the default CI session setup though.
Copied from codeigniter forum:
All it does is kills the users cookie, but the userdata will
remain within the session class until the end of the current request.
The session will be reinitialised on the next request, and there will
be no userdata available. Basically, all it does is severs the link
between the user and the server session, but the data still remains
until the end of the request.
If it’s that much of an issue, you can do this:
$this->session->userdata = array();
I manage it please try it .
$this->load->library('session');
// write parameter your session data
$this->session->unset_userdata('sessiondata');
// if you want to session unset group then try it
$array_items = array('username' => '', 'email' => '');
$this->session->unset_userdata($array_items);
You can try this one.
In the latest version above code is not working.
$unset_array_items = array('token_id', 'last_id');
$this->session->unset_userdata($unset_array_items);

codeigniter datamapper relationship validation issues

I need to set up the validation rules to validate the related items on a specific object, ie: A user can have no more than 3 products related to it.
I believe DataMapper can check for this validation using _related_max_size rule, but I can't figure out how to use it on the $validation array in the model.
So far I've tried this in both my user and product models:
var $validation = array(
'product' => array(
'rules' => array('max_size' => 3)
)
);
Can somebody show me an example on how to set up this at the model, controller and finally the view?
Edit: What I mean is, a user has many products, and can create a certain amount of them, let's say 3 products, when that amount is reached, the user can no longer create products, and this validation rule should not permit the user to create more products.
This would be the DB Schema:
Users table
------------------
id | username |
------------------
Products table
------------------------
id | user_id | name |
------------------------
More info here: http://codeigniter.com/forums/viewthread/178045/P500/
Thanks!
EDIT:
Ok, I got it all working now… Except, I need to do the following:
var $validation = array(
'product' => array(
'label' => 'productos',
'rules' => array('required','max_size' => $products_limit)
)
);
The $products_limit comes from the “plan” the user has associated, and it’s stored in the session when the user logs in. When I try to run this I get:
Parse error: syntax error, unexpected T_VARIABLE in /var/www/stocker/application/models/user.php on line 11
Is there any way to make this setting dynamic?
In model
var $validation = array(
array(
'field' => 'username',
'label' => 'Username',
'rules' => array('required')
)
);
In controller. $this -> $object = new Your_model();
$object->validate();
if ($object->valid)
{ $object->save();
// Validation Passed
}
else
{ $data['error'] = $object->error;
// Validation Failed
}
In view.
echo $error->field_name
I never use Codeigniter before, but give me a chance to help you. So far I didn't found any built-in validation in Code-igniter (correct me if I'm wrong).
One workaround that I could think of is to Callback:Your own Validation Functions. Below is a snip. Pardon me if it didn't work as you want.
In Model: (create something like)
function product_limit($id)
{
$this->db->where('product_id',$id);
$query = $this->db->get('products');
if ($query->num_rows() > 3){
return true;
}
else{
return false;
}
}
In controller: (create something like)
function productkey_limit($id)
{
$this->product_model->product_exists($id);
}
public function index()
{
$this->form_validation->set_rules('username', 'Username', 'callback_product_limit');
}
For more information Please refer to the manual page which gives more complete. I am also new to CodeIgniter. But I hope this helps you, not complicate you.
First, set up a custom validation rule in libraries/MY_Form_validation.php
If the file doesn't exist, create it.
Contents of MY_Form_validation.php:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Form_validation extends CI_Form_validation
{
function __construct($config = array())
{
parent::__construct($config);
}
function valid_num_products()
{
//Perhaps it would be better to store a maxProducts column in your users table. That way, every user can have a different max products? (just a thought). For now, let's be static.
$maxProducts = 3;
//The $this object is not available in libraries, you must request an instance of CI then, $this will be known as $CI...Yes the ampersand is correct, you want it by reference because it's huge.
$CI =& get_instance();
//Assumptions: You have stored logged in user details in the global data array & You have installed DataMapper + Set up your Product and User models.
$p = new Product();
$count = $p->where('user_id', $CI->data['user']['id'])->count();
if($count>=$maxProducts) return false;
else return true;
}
}
Next, set up your rule in config/form_validation.php.
Contents of form_validation.php
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
$config = array
(
'addProduct' => array
(
array
(
'field' => 'name',
'label' => 'Product Name',
'rules' => 'required|valid_num_products'
)
)
);
Next, set up your error message in language/english/form_validation_lang.php. Add the following line:
$lang['valid_num_products'] = "Sorry, you have exceeded your maximum number of allowable products.";
Now in the Controller, you'll want something along the lines of:
class Products extends MY_In_Controller
{
function __construct()
{
parent::__construct();
$this->load->library('form_validation');
}
function add()
{
$p = $this->input->post();
//was there even a post to the server?
if($p){
//yes there was a post to the server. run form validation.
if($this->form_validation->run('addProduct')){
//it's safe to add. grab the user, create the product and save the relationship.
$u = new User($this->data['user']['id']);
$x = new Product();
$x->name = $p['name'];
$x->save($u);
}
else{
//there was an error. should print the error message we wrote above.
echo validation_errors();
}
}
}
}
Finally, you might wonder why I've inherited from MY_In_Controller. There is an excellent article written by Phil Sturgeon over on his blog entitled Keeping It Dry. In the post he explains how to write controllers that inherit from access-controlling Controllers. By using this paradigm, controllers that inherit from MY_In_Controller can be assumed to be logged in, and the $this->data['user']['id'] stuff is therefore assumed to be available. In fact, $this->data['user']['id'] is SET in MY_In_Controller. This helps you seperate your logic in such a way that you're not checking for logged in status in the constructors of your controllers, or (even worse) in the functions of them.

In Codeigniter, how to pass a third parameter to a callback (form validation)?

I am currently using the Form Validation class (on Codeigniter) and setting rules.
It works like this with two parameters (codeigniter.com/user_guide/libraries/form_validation.html):
$this->form_validation->set_rules('username', 'Username', 'callback_test[abc]');
But what about a third parameter? And a fourth...? Is it possible?
It is not official but works
Split the parameter by ','
$this->form_validation->set_rules('article_big_image','Gambar Besar','callback_check_picture[article_big_image,edit]');
function check_picture($image,$param){
$param = preg_split('/,/', $param);
$field = $param[0];
$action = $param[1];
echo $field.$action;
}
Not without extended the system form validation class. For information on how to achieve this take a look at this article.
Alternatively you can access the post variables within your callback function using:
$this->input->post('field_name');
which may or may not help you out.
You can use Array for more parameters for more fields as like i did below:
$error = array(
array(
'field' => 'check', // the field name will come here
'label' => 'Check',
'rules' => 'required|here you can put the callback Function'
)
);
$this->form_validation->set_rules('article_big_image','Gambar','callback_check_picture[article_big_image,edit]');
function check_picture($image,$param){
$param = explode(',', $param);
$field = isset($param[0])?$param[0]:'';
$action = isset($param[1])?$param[1]:'';
echo $field.$action;
}
You can pass to the rule
|callback_handle_is_unique_value_combinations[val1,val2]
than,
public function callback_handle_is_unique_value_combinations($str, $field)
{
$fields = explode(',', $field);
$val1 = $fields[0];
$val2 = $fields[1];
and then you made your cponarisons

Resources