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
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;
}
}
}
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 );
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
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
);
}
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