<?php
namespace Jackbooted\Forms;
use \Jackbooted\Html\Tag;
use \Jackbooted\Html\WebPage;
use \Jackbooted\Security\Cryptography;
use \Jackbooted\Security\CSRFGuard;
use \Jackbooted\Security\TamperGuard;
/**
* @copyright Confidential and copyright (c) 2016 Jackbooted Software. All rights reserved.
*
* Written by Brett Dutton of Jackbooted Software
* brett at brettdutton dot com
*
* This software is written and distributed under the GNU General Public
* License which means that its source code is freely-distributed and
* available to the general public.
*/
/**
* Response - Created Hidden variables and URLs for the Response Vars
*/
class Response extends PipeLine {
const UNIQUE_CSRF = 'unique guard';
private static $crossSiteGuard = null;
private static $ignoreCrossSiteGuard = false;
private $intermediateUrlArray;
private $intermediateHiddenArray;
private $exemptKeys = [];
/**
* @param $initPattern
* @return Response
*/
public static function factory ( $initPattern=null ) {
return new Response ( $initPattern );
}
/**
* @param $initPattern
* @return void
*/
public function __construct( $initPattern=null ) {
parent::__construct();
// If there is a pattern passed thru then copy from request
if ( $initPattern != null ) $this->copyVarsFromRequest ( $initPattern );
$this->copyVarsFromRequest ( WebPage::SAVE_URL );
// Ensure that the known fields
foreach ( TamperGuard::$knownFields as $key ) {
$this->copyVarsFromRequest ( $key );
$this->addExempt ( $key );
}
}
/**
* @param $key
* @return void
*/
public function addExempt ( $key ) {
$this->exemptKeys[$key] = true;
return $this;
}
/**
* @param $key
* @param $val
* @param bool $encrypt
* @return Response
*/
public function set ( $key, $val ) {
$this->formVars[$key] = $val;
return $this;
}
/**
* @param $val
* @return Response
*/
public function action ( $val ) {
$this->formVars[WebPage::ACTION] = $val;
return $this;
}
/**
* @param $key
* @return Response
*/
public function del ( $key ) {
unset ( $this->formVars[$key] );
return $this;
}
/**
* @param string $matches
* @return Response
*/
public function copyVarsFromRequest ( $matches='/.*/') {
if ( ! preg_match ( '/^\\/.*\\/$/', $matches ) ) $matches = '/^' . $matches . '$/';
foreach ( Request::get () as $key => $val) {
if ( preg_match ( $matches, $key) ) $this->set ( $key, $val );
}
return $this;
}
private function addCSRFGuard () {
if ( self::$ignoreCrossSiteGuard ) return;
if ( self::$crossSiteGuard == null ) {
self::$crossSiteGuard = CSRFGuard::key();
}
$this->set ( CSRFGuard::KEY, self::$crossSiteGuard );
}
private function delCSRFGuard () {
$this->del ( CSRFGuard::KEY );
}
/**
* @return string
*/
public function toHidden ( $guard=true ) {
if ( $guard ) $this->addCSRFGuard ();
TamperGuard::add ( $this );
$html = '';
$this->convertFormVarsToAssocArray ();
foreach ( $this->intermediateHiddenArray as $key => $val ) {
$cypherText = $this->encryptValue ( $key, $val );
$html .= Tag::hidden ( $key, $cypherText );
}
TamperGuard::del ( $this );
if ( $guard ) $this->delCSRFGuard ();
return $html;
}
private function convertFormVarsToAssocArray () {
$this->intermediateHiddenArray = [];
foreach ( $this->formVars as $key => $val ) {
$this->arrayWalkerToConvertToAssoc ( $key, $val );
}
}
private function arrayWalkerToConvertToAssoc ( $key, &$value, $prefix='' ) {
$subKey = ( $prefix == '' ) ? $key : '[' . $key . ']';
$compoundKey = $prefix . $subKey;
if ( is_array ( $value ) ) {
foreach ( $value as $key => $val ) {
$this->arrayWalkerToConvertToAssoc ( $key, $val, $compoundKey );
}
}
else {
$this->intermediateHiddenArray[$compoundKey] = $value;
}
}
/**
* @return string
*/
public function toUrl ( $guard=false ) {
if ( $guard === true ) $this->addCSRFGuard ();
else if ( $guard == self::UNIQUE_CSRF ) {
$tempGuard = self::$crossSiteGuard;
self::$crossSiteGuard = null;
$this->addCSRFGuard ();
self::$crossSiteGuard = $tempGuard;
}
TamperGuard::add ( $this );
$this->convertFormVarsToFlatArray ();
TamperGuard::del ( $this );
if ( $guard ) $this->delCSRFGuard ();
return join ( '&', $this->intermediateUrlArray );
}
public function __toString () {
return $this->toUrl ();
}
private function convertFormVarsToFlatArray () {
$this->intermediateUrlArray = [];
foreach ( $this->formVars as $key => $val ) {
$this->arrayWalkerToConvertToFlat ( $key, $val );
}
}
private function arrayWalkerToConvertToFlat ( $key, &$value, $prefix='' ) {
$subKey = ( $prefix == '' ) ? $key : '[' . $key . ']';
$compoundKey = $prefix . $subKey;
if ( is_array ( $value ) ) {
foreach ( $value as $key => $val ) {
$this->arrayWalkerToConvertToFlat ( $key, $val, $compoundKey );
}
}
else {
$cypherText = $this->encryptValue ( $compoundKey, $value );
$this->intermediateUrlArray[] = $compoundKey . '=' . urlencode ( $cypherText );
}
}
private function encryptValue ( $key, $value ) {
if ( isset ( $this->exemptKeys[$key] ) ) {
return $value;
}
else {
return Cryptography::en ( $value );
}
}
}
|