change all posted data in zend - zend-framework

I want to apply this function to all posted data in zend frame work to prevent XSS attacks.
static function safe_against_xss($argument) {
$HtmlEntities_Filter = new Zend_Filter_HtmlEntities ( array ('quotestyle' => NULL, 'charset' => 'UTF-8' ) );
$argument = $HtmlEntities_Filter->filter ( $argument );
return $argument;
}
I use this code in my controller
$requests = $request->getPost() ;
foreach ($requests as $key => $value)
{
$requests[$key]=Functions::safe_against_xss($value);
}
It's worked,but i want to apply this function to all posted data in all controllers. automatically.
Sincerely

I write this codes:
$this->setRequest(Functions::safe_request($this->getRequest()));
In init of controllers
Then in Functions:
static function safe_against_xss($argument) {
// $HtmlEntities_Filter = new Zend_Filter_HtmlEntities ( NULL, 'UTF-8'
// );
$HtmlEntities_Filter = new Zend_Filter_HtmlEntities ( array ('quotestyle' => NULL, 'charset' => 'UTF-8' ) );
if (is_array($argument))
{
foreach($argument as $key => $value) {
$argument[$key] = $HtmlEntities_Filter->filter ( $value );
}
}
else
{
$argument = $HtmlEntities_Filter->filter ( $argument );
}
return $argument;
}
static function safe_post_params($params)
{
$safePostParams = array();
foreach($params as $key => $value) {
$safePostParams[$key] = self::safe_against_xss($value);
}
return $safePostParams;
}
static function safe_request($params)
{
$params->setParams(Functions::safe_post_params($params->getParams()));
$params->setPost(Functions::safe_post_params($params->getPost()));
return $params;
}

Related

How to insert detail data from one form into two tables in database postgresql and use foreach in controller?

This code in my controller doesn't work and give me warning like this:
invalid argument foreach.
public function create_action()
{
$this->_rules();
if ($this->form_validation->run() == FALSE) {
$this->create();
} else {
$usulan = array(
'unit_id' => $this->input->post('unit_id',TRUE),
'layanan_id' =>$this->input->post('layanan_id', TRUE),
'surat_unit_no' => $this->input->post('surat_unit_no',TRUE),
'usulan_tgl' =>$this->input->post('usulan_tgl', TRUE),
);
$id = $this->m_usulan->insert($usulan);
$this->db->from('usulan_detail');
$this->db->where('usulan_detail.id', $id);
$this->db->join('usulan', 'usulan.usulan_id = usulan_detail.usulan_id', 'left');
$usulan_detail = $this->input->post('usulan_detail');
//prepare the data into a multidimensional array
$data = array();
foreach($usulan_detail as $row)
{
// if this is the first clip of a new sheet, make a new entry for it
if (!isset($data[$row['usulan_id']]))
{
$data[$row['usulan_id']] = $row;
$data[$row['usulan_id']]['usulan_detail'] = array(
'usulan_id' => $id,
'pegawai_nip' => $this->input->post('pegawai_nip[]',TRUE),
'usulan_id' => $this->input->get('usulan_id[]',TRUE),
'gol_lama_id' =>$this->input->post('gol_lama_id[]', TRUE),
'gol_baru_id' =>$this->input->post('gol_baru_id[]', TRUE)
);
}
$data[$row['usulan_id']]['usulan_detail'][] = $row;
}
}
}

Create deep hash mapping in perl

Below is my Code with the Hash
#!/usr/bin/perl
use warnings;
use JSON::PP; # Just 'use JSON;' on most systems
my %name = (
'sl' => {
'fsd' => {
'conf' => {
'ul' => '/sl/fsd/conf/ul',
'si' => '/sl/fsd/conf/si',
'ho1' => '/sl/fsd/conf/ho1'
}
}
},
're' => {
'fsd' => {
'cron' => {
'README' => '/re/fsd/cron/README'
},
'bin' => {
'db' => {
'smart.p_add_tag' => '/re/fsd/bin/db/smart.p_add_tag',
'smart.p_tag_partition' => '/re/fsd/bin/db/smart.p_tag_partition',
'smart.p_add_tag_type' => '/re/fsd/bin/db/smart.p_add_tag_type'
}
},
'doc' => {
'SMART' => '/re/fsd/doc/SMART',
'README' => '/re/fsd/doc/README'
},
'data' => {
'README' => '/re/fsd/data/README'
},
'conf' => {
'al1' => '/re/fsd/conf/al1',
'file' => '/re/fsd/conf/file',
'ho' => '/re/fsd/conf/ho',
'al3' => '/re/fsd/conf/al3',
'hst' => '/re/fsd/conf/hst',
'us' => '/re/fsd/conf/us',
'README' => '/re/fsd/conf/README',
'al2' => '/re/fsd/conf/al2'
}
}
}
);
(my $root) = keys %name;
my %nodes = ();
my %tree = ();
my #queue = ($root);
list_children(\%name, \#queue, \%nodes) while #queue;
my $tree = build_tree($root, \%nodes);
my $json = JSON::PP->new->pretty; # prettify for human consumption
print $json->encode($tree);
sub list_children {
my $adjac = shift;
my $queue = shift;
my $nodes = shift;
my $node = shift #$queue;
my #children = keys %{$adjac->{$node}};
#children = grep { ! exists $nodes->{$_}} #children;
$nodes->{$node} = \#children;
push #$queue, #children;
}
sub build_tree {
my $root = shift;
my $nodes = shift;
my #children;
for my $child (#{$nodes->{$root}}) {
push #children, build_tree($child, $nodes);
}
my %h = ('text' => $root,
'children' => \#children);
return \%h;
}
I'm trying to output JSONified hash, but it is only traversing upto two levels. whereas i need it to traverse all upto the last child node of each parent. Can someone please help to achieve this.
Below is current output
{
"text" : "sl",
"children" : [
{
"text" : "fsd",
"children" : []
}
]
}
Normally, transforming the hash, and then json-ing is not the most efficient idea, because you're going to make one traversal to transform the hash and JSON's going to make one to json-ify it, and JSON is a type of transform of a hash.
However, JSON is usually done with XS, which means that the second traversal is faster, at least. That and JSON behavior is standardized.
use 5.016;
use strict;
use warnings;
use Data::Dumper ();
use JSON;
my $hash
= {
'Foods' => {
'fruits' => {
'orange' => '1',
'apple' => '2',
},
'Vegetables' => {
'tomato' => '3',
'carrot' => '1',
'cabbage' => '2',
}
}
};
sub descend {
my ( $structure, $block ) = #_;
my $res;
while ( my ( $k, $v ) = each %$structure ) {
$block->( $structure, $k, $v );
if ( ref( $v ) eq 'HASH' ) {
$res = descend( $v, $block );
}
}
return $res;
}
my $new = {};
my $curr = $new;
descend( $hash => sub {
my ( $lvl, $k, $v ) = #_;
my $node = { text => $k };
$curr->{children} //= [];
push $curr->{children}, $node;
if ( ref( $v ) eq 'HASH' ) {
$curr = $node;
}
else {
$node->{children} = { text => $v };
}
});
# allow for the root-level special case, and retrieve the first child.
$new = $new->{children}[0];
say Data::Dumper->Dump( [ $new ], [ '$new' ] );
say JSON->new->encode( $new );

InputFilter "setRequired" not working for html5 multiple

I'm having hard time with a weird behaviour of fileinput.
This is my form:
namespace Frontend\Form;
use NW\Form\Form;
use Zend\InputFilter;
use Zend\Form\Element;
use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\ServiceManagerAwareInterface;
class EnrollStructure extends Form implements ServiceManagerAwareInterface
{
protected $sm;
public function __construct($name=null) {
parent::__construct("frmEnrollStructure");
$this->setAttribute("action", "/registrazione_struttura/submit")
->setAttribute('method', 'post')
->setAttribute("id", "iscrizione_struttura")
->setAttribute("class", "form fullpage");
$this->addInputFilter();
}
public function init()
{
$structureFs = $this->sm->get('Structure\Form\Fieldsets\Structure');
$structureFs->setUseAsBaseFieldset(true);
$structureFs->remove("id")
->remove("creationTime")
->remove("latLon");
$file = new Element\File("images");
$file->setAttribute('multiple', true);
$this->add($structureFs)->add($file);
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Iscriviti',
'id' => 'sbmtEnrollStructure',
'class' => 'submit_btn'
),
));
$this->setValidationGroup(
array(
'structure' =>
array(
'companyname',
'vatNumber',
'addressStreet',
'addressZip',
'addressCity',
'addressRegion',
'fax',
'publicPhone',
'publicEmail',
'website',
'status',
'ownerNotes',
'category',
'subcategory',
"facilities",
"agreeOnPolicy",
"agreeOnPrivacy",
"subscribeNewsletter",
"contact" => array("name", "surname", "email", "role", "phone"),
),
"images"
));
}
/**
* Set service manager
*
* #param ServiceManager $serviceManager
*/
public function setServiceManager(ServiceManager $serviceManager)
{
$this->sm = $serviceManager;
}
public function addInputFilter()
{
$inputFilter = new InputFilter\InputFilter();
// File Input
$fileInput = new InputFilter\FileInput('images');
$fileInput->setRequired(true);
$fileInput->getValidatorChain()
->attachByName('filesize', array('max' => "2MB"))
->attachByName('filemimetype', array('mimeType' => 'image/png,image/x-png,image/jpg,image/jpeg'))
->attachByName('fileimagesize', array('maxWidth' => 2048, 'maxHeight' => 2048));
$inputFilter->add($fileInput);
$this->setInputFilter($inputFilter);
}
}
Basically, I mainly use a fieldset which contains most of the data I request to the user, plus a File input field.
This is the Fieldset Structure: (most important parts..)
use Zend\Form\Element;
use Zend\Form\Fieldset;
use Zend\InputFilter\InputFilterProviderInterface;
use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\ServiceManagerAwareInterface;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
use Zend\Validator\Identical;
use Zend\Validator\NotEmpty;
use Zend\Validator\Regex;
use Zend\Validator\StringLength;
class Structure extends Fieldset implements InputFilterProviderInterface, ServiceManagerAwareInterface
{
protected $sm;
public function __construct()
{
parent::__construct('structure');
}
public function init()
{
$this->setHydrator(new DoctrineHydrator($this->_entityManager(),'Structure\Entity\Structure'));
$this->setObject($this->sm->getServiceLocator()->get("Structure_Structure"));
$id = new Element\Hidden("id");
$name = new Element\Text("companyname");
$name->setLabel("Ragione Sociale");
...........
}
public function getInputFilterSpecification()
{
return array
(
"id" => array(
"required" => false,
),
"companyname" => array(
"required" => true,
"validators" => array(
array('name' => "NotEmpty", 'options' => array("messages" => array( NotEmpty::IS_EMPTY => "Inserire la ragione sociale")))
),
),
.....
}
}
This is my controller:
public function submitAction()
{
try {
$this->layout("layout/json");
$form = $this->getForm('Frontend\Form\EnrollStructure');
//$form->addInputFilter();
$structure = $this->getServiceLocator()->get("Structure_Structure");
$viewModel = new ViewModel();
$request = $this->getRequest();
if ($request->isPost())
{
$post = array_merge_recursive
(
$request->getPost()->toArray(),
$request->getFiles()->toArray()
);
$form->setData($post);
if ($form->isValid())
{
$structure = $form->getObject();
$contact = $structure->getContact();
$this->getServiceLocator()->get('Structure_ContactService')->save($contact);
$files = $request->getFiles()->toArray();
if(isset($files['images']))
{
$count = 3;
foreach($files['images'] as $pos => $file)
{
$fpath = $this->getServiceLocator()->get('RdnUpload\Container')->upload($file);
if(!empty($fpath))
{
if(--$count ==0) break;
$asset = $this->getServiceLocator()->get("Application_AssetService")->fromDisk($fpath, $file['name']);
$this->getServiceLocator()->get("Application_AssetService")->save($asset);
$structure->addImage($asset);
}
}
}
$this->getServiceLocator()->get('Structure_StructureService')->save($structure);
$retCode = RetCode::success(array("iscrizione_struttura!" => array("form_submit_successfull")), true);
}
else
{
$messages = $form->getMessages();
if(empty($messages))
$retCode = RetCode::error(array("iscrizione_struttura" => array("need_at_least_one_file" => "missing file")), true);
else
$retCode = RetCode::error(array("iscrizione_struttura" => $messages), true);
}
$viewModel->setVariable("retcode", $retCode);
return $viewModel;
}
} catch(Exception $e)
{
throw $e;
}
}
The strange thing is that if i remove from the field "images" the "multiple" attribute everything works fine, causing the form not to validate and i get this message:
[images] => Array
(
[fileUploadFileErrorFileNotFound] => File was not found
)
While, if i set the attribute multiple, and the user does not upload a file i get no error, but the form gets invalidated (this is the reason for this "bad" code in my controller:)
$messages = $form->getMessages();
if(empty($messages))
$retCode = RetCode::error(array("iscrizione_struttura" => array("need_at_least_one_file" => "missing file")), true);
else
$retCode = RetCode::error(array("iscrizione_struttura" => $messages), true);
I found the problem was caused by the Jquery form plugin, without it it works fine. :( In case somebody needs, I think the correct action code can be found here (I haven't tryied it anyway)
https://github.com/cgmartin/ZF2FileUploadExamples/blob/master/src/ZF2FileUploadExamples/Controller/ProgressExamples.php

Redirect while error in form ZF2

I have a ZF2 form and validators.
I located at http://example.com/public/questions/edit/5730/2770,
where 5730 - $_GET['variant_id'], 2770 - $_GET['test_id'].
When I set input to empty value and submit form - I have an error, and ZF2 redirect me to http://example.com/public/questions/edit/5730 - without test_id (/2770).
How I can redirect me to a valid url? Thank all for answers.
Action:
public function editAction()
{
$language = 'EN';
$request = $this->getRequest();
$this->layout()->setVariable('messenger', 'Edit Questions');
$id = $this->params()->fromRoute('id');
$variantId = $this->params()->fromRoute('variant_id');
$sm = $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter');
$stCategories = new CategoriesTable($sm);
$conFunc = new FunctionsController();
$form = new Form\AddQuestionsForm();
$stCVariants = new ContestVariantsTable($sm);
$stQuestions = new QuestionsTable($sm);
$categoryList = $stCategories->getCategories($language);
$categories = $conFunc->_getSubs(null, $categoryList);
$config = $this->getServiceLocator()->get('config');
$folder = $config['settings']['url'] . $config['settings']['media_files'];
if (empty($id) && !$request->isPost()) {
$this->redirect()->toRoute('stickynotes', array('controller' => 'stickynotes', 'action' => 'contests'));
} elseif ($request->isPost()) {
$form->setInputFilter($stQuestions->getAddQuestionsFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$arrPost = (array) $request->getPost();
$arrFile = (array) $request->getFiles();
$postData = array_merge_recursive($arrPost, $arrFile);
$tryAddQuestion = $stQuestions->updateQuestions($postData);
if ($tryAddQuestion['query'] && $tryAddQuestion['exception'] === null) {
$isUpload = new \Zend\Validator\File\UploadFile();
if ($isUpload->isValid($postData['filebutton'])) {
$path_parts = pathinfo($postData['filebutton']['name']);
$extension = '.' . $path_parts['extension'];
$filename = $tryAddQuestion['lastId'];
$config = $this->getServiceLocator()->get('config');
$folder = $config['settings']['media_files'];
if ($postData['AddQuestionMedia'] == 'image') {
$validator = new \Zend\Validator\File\IsImage();
$validator2 = new \Zend\Validator\File\Extension(array('png', 'jpeg', 'jpg', 'gif'));
if ($validator->isValid($postData['filebutton'])
&& $validator2->isValid($postData['filebutton'])) {
$filter = new \Zend\Filter\File\Rename($folder . 'images/' . $filename . $extension);
$filter->filter($postData['filebutton']);
chmod($config['settings']['media_files'] . 'images/' . $filename . $extension, 0644);
$stQuestions->updateQuestionsFile($filename, $extension);
}
} elseif ($postData['AddQuestionMedia'] == 'video') {
$validator = new \Zend\Validator\File\Extension(array('mp4'));
if ($validator->isValid($postData['filebutton'])) {
$filter = new \Zend\Filter\File\Rename($folder . 'videos/' . $filename . '.mp4');
$filter->filter($postData['filebutton']);
chmod($config['settings']['media_files'] . 'videos/' . $filename . '.mp4', 0644);
$stQuestions->updateQuestionsFile($filename, $extension);
}
} elseif ($postData['AddQuestionMedia'] == 'audio') {
$validator = new \Zend\Validator\File\Extension(array('mp3'));
if ($validator->isValid($postData['filebutton'])) {
$filter = new \Zend\Filter\File\Rename($folder . 'sounds/' . $filename . '.mp3');
$filter->filter($postData['filebutton']);
chmod($config['settings']['media_files'] . 'sounds/' . $filename . '.mp3', 0644);
$stQuestions->updateQuestionsFile($filename, $extension);
}
} else {
$this->layout()->setVariable('messenger_error', 'Uploaded file have incorrect format');
}
}
$this->layout()->setVariable('messenger_info', 'Question has been updated!');
$this->redirect()->toRoute('questions', array('controller' => 'questions', 'action' => 'edit',
'id' => $id, 'variant_id' => $postData['question_id']));
} elseif(!empty($tryAddContest['exception'])) {
$this->layout()->setVariable('messenger_error', 'Failed with DB while update question. Please try again. ' . $tryAddQuestion['exception']);
} else {
$this->layout()->setVariable('messenger_error', 'Failed while update question. Please try again.');
}
if (!empty($postData['variant_id'])) {
$stCVariants->addEntity($postData['variant_id'], $tryAddQuestion['lastId']);
}
}
} else {
if (!empty($variantId)) {
$getContest = $stCVariants->getSingleContest($variantId);
$progressions = array();
$used_progressions = $stCVariants->getUsedProgressions($id);
for ($i=$getContest['progression_start']; $i<=$getContest['progression_stop']; $i++) {
if (!in_array($i, $used_progressions))
$progressions[] = $i;
}
$form->remove('AddQuestionProgression');
$form->getInputFilter()->remove('AddQuestionProgression');
$select = new \Zend\Form\Element\Select('AddQuestionProgression');
$select->setValueOptions($progressions)->setAttributes(array(
'id' => 'progression_id',
'class' => 'form-control',
'style' => 'width: 408px;',
));
$form->get('variant_id')->setValue($id);
$form->add($select);
}
$getQuestion = $stQuestions->getSingleQuestion($id);
switch ($getQuestion['media_type']) {
case 'image':
$folder .= 'images/' . $getQuestion['media_content'];
break;
case 'video':
$folder .= 'videos/' . $getQuestion['media_content'];
break;
case 'audio':
$folder .= 'sounds/' . $getQuestion['media_content'];
break;
}
$form->get('variant_id')->setValue($id);
$form->get('question_id')->setValue($variantId);
}
return array(
'form' => $form,
'categories' => $categories,
'url' => $folder,
'id' => $id
);
}

zend array[] element with validator

hello i have a form where the user can click on a button and dinamically add new elements(with Jquery)
<input name="sconto[]" type="text"><br>
<input name="sconto[]" type="text"><br>
<input name="sconto[]" type="text"><br>
...
I have a custom validator for float numbers in format with comma and dot separation like 20.50 and 20,50
The problem is i can't seem to find how to make zend apply it it to each element of the array.
So how should i declare this element and how to apply the validator? xD
this is my validator
protected $_messageTemplates = array(
self::NON_E_NUMERO => 'non sembra essere un numero'
);
public function isValid($value, $context = null)
{
$pos_virgola = strpos($value, ",");
if ($pos_virgola !== false)
$value = str_replace(",", ".", $value);
if (!is_numeric($value))
{
$this->_error(self::NON_E_NUMERO, $value);
return false;
}
else
return true;
}
}
the form i don't know how to do it, i use this but obviously it doesn't work
$sconto = $this->createElement('text','sconto')->setLabel('sconto');
//->setValidators(array(new Gestionale_Validator_Float()));
$this->addElement($sconto);
...
$sconto->setDecorators(array(//no ViewHelper
'Errors',
'Description',
array(array('data' => 'HtmlTag'), array('tag' => 'td', /*'class' => 'valore_campo', */'id'=>'sconto')),
array('TdLabel', array('placement' => 'prepend', 'class' => 'nome_campo'))
));
If Marcin comment is not what you want to do, then this is another way to create multi text element.
Create a custom decorator 'My_Form_Decorator_MultiText'. You will need to register your custom decorator class. Read Zend Framework doc for details http://framework.zend.com/manual/en/zend.form.decorators.html
class My_Form_Decorator_MultiText extends Zend_Form_Decorator_Abstract {
public function render($content) {
$element = $this->getElement();
if (!$element instanceof Zend_Form_Element_Text) {
return $content;
}
$view = $element->getView();
if (!$view instanceof Zend_View_Interface) {
return $content;
}
$values = $element->getValue();
$name = $element->getFullyQualifiedName();
$html = '';
if (is_array($values)) {
foreach ($values as $value) {
$html .= $view->formText($name, $value);
}
} else {
$html = $view->formText($name, $values);
}
switch ($this->getPlacement()) {
case self::PREPEND:
return $html . $this->getSeparator() . $content;
case self::APPEND:
default:
return $content . $this->getSeparator() . $html;
}
}
}
Now your validation class will validate each element value
class My_Validate_Test extends Zend_Validate_Abstract {
const NON_E_NUMERO = 'numero';
protected $_messageTemplates = array(
self::NON_E_NUMERO => 'non sembra essere un numero'
);
public function isValid($value, $context = null) {
if (!is_numeric($value)) {
$this->_error(self::NON_E_NUMERO, $value);
return false;
}
else
return true;
}
}
This is how you can use the new decorator
$element = new Zend_Form_Element_Text('sconto', array(
'validators' => array(
new My_Validate_Test(),
),
'decorators' => array(
'MultiText', // new decorator
'Label',
'Errors',
'Description',
array('HtmlTag', array('tag' => 'dl',))
),
'label' => 'sconto',
'isArray' => true // must be true
));
$this->addElement($element);
Hope this helps