/** * 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; }
/** * Generates specified number of random bytes. * Note that output may not be ASCII. * * @see generateRandomString() if you need a string. * * @param integer $length the number of bytes to generate * @return string the generated random bytes * @throws InvalidConfigException if OpenSSL extension is required (e.g. on Windows) but not installed. * @throws Exception on failure. */ public function generateRandomKey($length = 32) { /* * Strategy * The most common platform is Linux, on which /dev/urandom is the best choice. Many other OSs * implement a device called /dev/urandom for Linux compat and it is good too. So if there is * a /dev/urandom then it is our first choice regardless of OS. * Nearly all other modern Unix-like systems (the BSDs, Unixes and OS X) have a /dev/random * that is a good choice. If we didn't get bytes from /dev/urandom then we try this next but * only if the system is not Linux. Do not try to read /dev/random on Linux. * Finally, OpenSSL can supply CSPR bytes. It is our last resort. On Windows this reads from * CryptGenRandom, which is the right thing to do. On other systems that don't have a Unix-like * /dev/urandom, it will deliver bytes from its own CSPRNG that is seeded from kernel sources * of randomness. Even though it is fast, we don't generally prefer OpenSSL over /dev/urandom * because an RNG in user space memory is undesirable. * For background, see http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/ */ $bytes = ''; // If we are on Linux or any OS that mimics the Linux /dev/urandom device, e.g. FreeBSD or OS X, // then read from /dev/urandom. if (@file_exists('/dev/urandom')) { $handle = fopen('/dev/urandom', 'r'); if ($handle !== false) { $bytes .= fread($handle, $length); fclose($handle); } } if (StringHelper::byteLength($bytes) >= $length) { return StringHelper::byteSubstr($bytes, 0, $length); } // If we are not on Linux and there is a /dev/random device then we have a BSD or Unix device // that won't block. It's not safe to read from /dev/random on Linux. if (PHP_OS !== 'Linux' && @file_exists('/dev/random')) { $handle = fopen('/dev/random', 'r'); if ($handle !== false) { $bytes .= fread($handle, $length); fclose($handle); } } if (StringHelper::byteLength($bytes) >= $length) { return StringHelper::byteSubstr($bytes, 0, $length); } if (!extension_loaded('openssl')) { throw new InvalidConfigException('The OpenSSL PHP extension is not installed.'); } $bytes .= openssl_random_pseudo_bytes($length, $cryptoStrong); if (StringHelper::byteLength($bytes) < $length || !$cryptoStrong) { throw new Exception('Unable to generate random bytes.'); } return StringHelper::byteSubstr($bytes, 0, $length); }
/** * 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; }