Advertisement
rfv123

Q49924789 - HTML Form 'conversation' Tracking

Apr 24th, 2018
268
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 5.73 KB | None | 0 0
  1. <?php
  2. /**
  3. * every 'data edit' form has one of these - without exeception.
  4. *
  5. * This ensures that the form I sent out came from me.
  6. *
  7. * It has:
  8. *    1) A unique @id
  9. *    2) A date time stamp and a lifetime
  10. *
  11. *  Can be automatically generated and checked.
  12. */
  13.  
  14. class FormState {
  15.  
  16.     const MAX_FORM_AGE = 600; // seconds
  17.  
  18.     const ENC_PASSWORD = '327136823981d9e57652bba2acfdb1f2';  
  19.     const ENC_IV       = 'f9928260b550dbb2eecb6e10fcf630ba';  
  20.  
  21.     protected $state = array();
  22.  
  23.     public function __construct($prevState = '')
  24.     {
  25.         if (!empty($prevState)) {
  26.             $this->reloadState($prevState); // will not be valid if fails
  27.             return;
  28.         }
  29.  
  30.         $this->setNewForm();
  31.     }
  32.  
  33.     /**
  34.      * Generate a new unique id and timestanp
  35.      *
  36.      * @param $name - optional name for the form
  37.      */
  38.     public function setNewForm($name = '')
  39.     {
  40.         $this->state = array();
  41.         $this->state['formid'] = sha1(uniqid(true)); // each form has a unique id
  42.         $this->state['when'] = time();
  43.  
  44.         if (!empty($name)) {
  45.             $this->setAttribute('name', $name);
  46.         }
  47.     }
  48.  
  49.     /**
  50.      * retrieve attribute value
  51.      *
  52.      * @param $name     attribute name to use
  53.      * @param $default  value to return if attribute does not exist
  54.      *
  55.      * @return string / number
  56.      */
  57.     public function getAttribute($name, $default = null)
  58.     {
  59.             if (isset($this->state[$name])) {
  60.                    return $this->state[$name];
  61.             } else {
  62.                    return $default;
  63.             }  
  64.     }
  65.  
  66.     /**
  67.      * store attribute value
  68.      *
  69.      * @param $name     attribute name to use
  70.      * @param $value    value to save
  71.      */
  72.     public function setAttribute($name, $value)
  73.     {
  74.             $this->state[$name] = $value;
  75.     }
  76.  
  77.     /**
  78.      * get the array
  79.      */
  80.     public function getAllAttributes()
  81.     {
  82.         return $this->state;
  83.     }
  84.  
  85.     /**
  86.      * the unique form id
  87.      *  
  88.      * @return hex string
  89.      */
  90.     public function getFormId()
  91.     {
  92.         return $this->getAttribute('formid');    
  93.     }
  94.  
  95.     /**
  96.      * Age of the form in seconds
  97.      * @return int seconds
  98.      */
  99.     public function getAge()
  100.     {
  101.         if ($this->isValid()) {
  102.             return time() - $this->state['when'];
  103.         }
  104.         return 0;
  105.     }
  106.  
  107.     /**
  108.      * check the age of the form
  109.      *
  110.      *@param $ageSeconds is age older than the supplied age
  111.      */
  112.     public function isOutOfDate($ageSeconds = self::MAX_FORM_AGE)
  113.     {
  114.         return $this->getAge() >= $ageSeconds;
  115.     }
  116.  
  117.     /**
  118.      * was a valid string passed when restoring it
  119.      * @return boolean
  120.      */
  121.     public function isValid()
  122.     {
  123.         return is_array($this->state) && !empty($this->state);
  124.     }
  125.  
  126.     /** -----------------------------------------------------------------------
  127.      * Encode as string - these are encrypted to ensure they are not tampered with  
  128.      */
  129.  
  130.     public function asString()
  131.     {        
  132.         $serialized = serialize($this->state);
  133.         $encrypted = $this->encrypt_decrypt('encrypt', $serialized);
  134.  
  135.         $result = base64_encode($encrypted);
  136.         return $result;
  137.     }
  138.  
  139.     /**
  140.      * Restore the saved attributes - it must be a valid string
  141.      *
  142.      * @Param $prevState
  143.      * @return array Attributes
  144.      */
  145.     public function fromString($prevState)
  146.     {
  147.         $encrypted = @base64_decode($prevState);
  148.         if ($encrypted === false) {
  149.            return false;
  150.         }
  151.  
  152.         $serialized = $this->encrypt_decrypt('decrypt', $encrypted);
  153.         if ($serialized === false) {
  154.            return false;
  155.         }
  156.  
  157.         $object = @unserialize($serialized);
  158.         if ($object === false) {
  159.            return false;
  160.         }
  161.  
  162.         if (!is_array($object)) {
  163.             throw new \Exception(__METHOD__ .' failed to return object: '. $object, 500);
  164.         }
  165.         return $object;
  166.     }
  167.  
  168.     public function __toString()
  169.     {
  170.         return $this->asString();
  171.     }
  172.  
  173.     /**
  174.      * Restore the previous state of the form
  175.      *    will not be valid if not a valid string
  176.      *
  177.      * @param  $prevState  an encoded serialized array
  178.      * @return bool isValid or not
  179.      */
  180.     public function reloadState($prevState)
  181.     {
  182.         $this->state = array();
  183.  
  184.         $state = $this->fromString($prevState);
  185.         if ($state !== false) {
  186.             $this->state = $state;
  187.         }
  188.  
  189.         return $this->isValid();
  190.     }
  191.  
  192.     /**
  193.      * simple method to encrypt or decrypt a plain text string
  194.      * initialization vector(IV) has to be the same when encrypting and decrypting
  195.      *
  196.      * @param string $action: can be 'encrypt' or 'decrypt'
  197.      * @param string $string: string to encrypt or decrypt
  198.      *
  199.      * @return string
  200.      */
  201.     public function encrypt_decrypt($action, $string)
  202.     {
  203.         $output = false;
  204.  
  205.         $encrypt_method = "AES-256-CBC";
  206.         $secret_key = self::ENC_PASSWORD;
  207.  
  208.  
  209.         // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
  210.         $secret_iv_len = openssl_cipher_iv_length($encrypt_method);
  211.         $secret_iv = substr(self::ENC_IV, 0, $secret_iv_len);
  212.  
  213.         if ( $action == 'encrypt' ) {
  214.             $output = openssl_encrypt($string, $encrypt_method, $secret_key, OPENSSL_RAW_DATA, $secret_iv);
  215.  
  216.         } else if( $action == 'decrypt' ) {
  217.             $output = openssl_decrypt($string, $encrypt_method, $secret_key, OPENSSL_RAW_DATA, $secret_iv);
  218.         }
  219.  
  220.         if ($output === false) {
  221.             // throw new \Exception($action .' failed: '. $string, 500);
  222.         }
  223.  
  224.         return $output;
  225.     }
  226. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement