/**
  * @param DOMElement $element
  * @param mixed $data
  */
 protected function buildXml($element, $data)
 {
     if (is_object($data)) {
         $child = new DOMElement(StringHelper::basename(get_class($data)));
         $element->appendChild($child);
         if ($data instanceof Arrayable) {
             $this->buildXml($child, $data->toArray());
         } else {
             $array = [];
             foreach ($data as $name => $value) {
                 $array[$name] = $value;
             }
             $this->buildXml($child, $array);
         }
     } elseif (is_array($data)) {
         foreach ($data as $name => $value) {
             if (is_int($name) && is_object($value)) {
                 $this->buildXml($element, $value);
             } elseif (is_array($value) || is_object($value)) {
                 $child = new DOMElement(is_int($name) ? $this->itemTag : $name);
                 $element->appendChild($child);
                 $this->buildXml($child, $value);
             } else {
                 $child = new DOMElement(is_int($name) ? $this->itemTag : $name);
                 $element->appendChild($child);
                 $child->appendChild(new DOMText((string) $value));
             }
         }
     } else {
         $element->appendChild(new DOMText((string) $data));
     }
 }
Example #2
0
 /**
  * Builds a normalized cache key from a given key.
  *
  * If the given key is a string containing alphanumeric characters only and no more than 32 characters,
  * then the key will be returned back prefixed with [[keyPrefix]]. Otherwise, a normalized key
  * is generated by serializing the given key, applying MD5 hashing, and prefixing with [[keyPrefix]].
  *
  * @param mixed $key the key to be normalized
  * @return string the generated cache key
  */
 public function buildKey($key)
 {
     if (is_string($key)) {
         $key = ctype_alnum($key) && StringHelper::byteLength($key) <= 32 ? $key : md5($key);
     } else {
         $key = md5(json_encode($key));
     }
     return $this->keyPrefix . $key;
 }
Example #3
0
 /**
  * Declares the name of the database table associated with this AR class.
  * By default this method returns the class name as the table name by calling [[Inflector::camel2id()]]
  * with prefix [[Connection::tablePrefix]]. For example if [[Connection::tablePrefix]] is 'tbl_',
  * 'Customer' becomes 'tbl_customer', and 'OrderItem' becomes 'tbl_order_item'. You may override this method
  * if the table is not named after this convention.
  * @return string the table name
  */
 public static function tableName()
 {
     return '{{%' . Inflector::camel2id(StringHelper::basename(get_called_class()), '_') . '}}';
 }
Example #4
0
 /**
  * Performs string comparison using timing attack resistant approach.
  *
  * @see http://codereview.stackexchange.com/questions/13512
  * @param string $expected string to compare.
  * @param string $actual user-supplied string.
  * @return boolean whether strings are equal.
  */
 public function compareString($expected, $actual)
 {
     $expected .= "";
     $actual .= "";
     $expectedLength = StringHelper::byteLength($expected);
     $actualLength = StringHelper::byteLength($actual);
     $diff = $expectedLength - $actualLength;
     for ($i = 0; $i < $actualLength; $i++) {
         $diff |= ord($actual[$i]) ^ ord($expected[$i % $expectedLength]);
     }
     return $diff === 0;
 }
Example #5
0
 /**
  * Sends the specified content as a file to the browser.
  *
  * Note that this method only prepares the response for file sending. The file is not sent
  * until [[send()]] is called explicitly or implicitly. The latter is done after you return from a controller action.
  *
  * @param string $content the content to be sent. The existing [[content]] will be discarded.
  * @param string $attachmentName the file name shown to the user.
  * @param array $options additional options for sending the file. The following options are supported:
  *
  *  - `mimeType`: the MIME type of the content. Defaults to 'application/octet-stream'.
  *  - `inline`: boolean, whether the browser should open the file within the browser window. Defaults to false,
  *    meaning a download dialog will pop up.
  *
  * @return $this the response object itself
  * @throws HttpException if the requested range is not satisfiable
  */
 public function sendContentAsFile($content, $attachmentName, $options = [])
 {
     $headers = $this->getHeaders();
     $contentLength = StringHelper::byteLength($content);
     $range = $this->getHttpRange($contentLength);
     if ($range === false) {
         $headers->set('Content-Range', "bytes */{$contentLength}");
         throw new HttpException(416, 'Requested range not satisfiable');
     }
     list($begin, $end) = $range;
     if ($begin != 0 || $end != $contentLength - 1) {
         $this->setStatusCode(206);
         $headers->set('Content-Range', "bytes {$begin}-{$end}/{$contentLength}");
         $this->content = StringHelper::byteSubstr($content, $begin, $end - $begin + 1);
     } else {
         $this->setStatusCode(200);
         $this->content = $content;
     }
     $mimeType = isset($options['mimeType']) ? $options['mimeType'] : 'application/octet-stream';
     $this->setDownloadHeaders($attachmentName, $mimeType, !empty($options['inline']), $end - $begin + 1);
     $this->format = self::FORMAT_RAW;
     return $this;
 }
Example #6
0
 /**
  * Validates CSRF token
  *
  * @param string $token
  * @param string $trueToken
  * @return boolean
  */
 private function validateCsrfTokenInternal($token, $trueToken)
 {
     $token = base64_decode(str_replace('.', '+', $token));
     $n = StringHelper::byteLength($token);
     if ($n <= static::CSRF_MASK_LENGTH) {
         return false;
     }
     $mask = StringHelper::byteSubstr($token, 0, static::CSRF_MASK_LENGTH);
     $token = StringHelper::byteSubstr($token, static::CSRF_MASK_LENGTH, $n - static::CSRF_MASK_LENGTH);
     $token = $this->xorTokens($mask, $token);
     return $token === $trueToken;
 }