/** * @param resource $resource Stream resource. * @param bool $autoClose True to close the resource on destruct, false to leave it open. */ public function __construct($resource, bool $autoClose = true) { parent::__construct($resource, $autoClose); stream_set_write_buffer($resource, 0); stream_set_chunk_size($resource, self::CHUNK_SIZE); $this->writeQueue = new \SplQueue(); $this->onCancelled = function (Throwable $exception) { $this->free($exception); }; }
/** * @param resource $resource Stream resource. * @param bool $autoClose True to close the resource on destruct, false to leave it open. */ public function __construct($resource, bool $autoClose = true) { parent::__construct($resource, $autoClose); stream_set_read_buffer($resource, 0); stream_set_chunk_size($resource, self::CHUNK_SIZE); $this->queue = new \SplQueue(); $this->poll = $this->createPoll($resource, $this->queue); $this->onCancelled = function () { $this->poll->cancel(); $this->queue->shift(); }; }
/** * Returns the pointer to the random source. * @return resource The pointer to the random source. */ private function getPointer() { if (!isset($this->pointer)) { $this->pointer = fopen($this->source, 'r'); // File read buffering is not supported on HHVM if (!defined('HHVM_VERSION')) { stream_set_chunk_size($this->pointer, 32); stream_set_read_buffer($this->pointer, 32); } } return $this->pointer; }
function __construct($host, $port, $timeout_ms = 2000) { $timeout_f = (double) $timeout_ms / 1000; $this->sock = @stream_socket_client("{$host}:{$port}", $errno, $errstr, $timeout_f); if (!$this->sock) { throw new SSDBException("{$errno}: {$errstr}"); } $timeout_sec = intval($timeout_ms / 1000); $timeout_usec = ($timeout_ms - $timeout_sec * 1000) * 1000; @stream_set_timeout($this->sock, $timeout_sec, $timeout_usec); if (function_exists('stream_set_chunk_size')) { @stream_set_chunk_size($this->sock, 1024 * 1024); } }
function __construct($stream, $eol = false) { $this->eol = $eol ?: null; $this->ceol = strlen($eol ?: PHP_EOL); if (!$eol) { ini_set('auto_detect_line_endings', true); } if (is_resource($stream)) { $this->stream = $stream; } else { $this->stream = fopen($stream, 'rb+'); } stream_set_chunk_size($this->stream, $this->blocksize); }
public function __construct($host, $port, $connection_timeout, $read_write_timeout = null, $context = null, $blocking = false) { $errstr = $errno = null; $this->sock = null; if ($context) { $remote = sprintf('tls://%s:%s', $host, $port); $this->sock = @stream_socket_client($remote, $errno, $errstr, $connection_timeout, STREAM_CLIENT_CONNECT, $context); } else { $remote = sprintf('tcp://%s:%s', $host, $port); $this->sock = @stream_socket_client($remote, $errno, $errstr, $connection_timeout, STREAM_CLIENT_CONNECT); } if (!$this->sock) { throw new RuntimeException("Error Connecting to server({$errno}): {$errstr} "); } if (null !== $read_write_timeout) { if (!stream_set_timeout($this->sock, $read_write_timeout)) { throw new \Exception("Timeout (stream_set_timeout) could not be set"); } } /** * Manually set blocking & write buffer settings and make sure they are successfuly set * Use non-blocking as we dont want to stuck waiting for socket data while fread() w/o timeout */ if (!stream_set_blocking($this->sock, $blocking)) { throw new \Exception("Blocking could not be set"); } $rbuff = stream_set_read_buffer($this->sock, 0); if (!(0 === $rbuff)) { throw new \Exception("Read buffer could not be set"); } /** * ! this is not reliably returns success (0) * ! but default buffer is pretty high (few Kb), so will not affect sending single small pushes * * Output using fwrite() is normally buffered at 8K. * This means that if there are two processes wanting to write to the same output stream (a file), * each is paused after 8K of data to allow the other to write. * * Ensures that all writes with fwrite() are completed * before other processes are allowed to write to that output stream */ stream_set_write_buffer($this->sock, 0); /** * Set small chunk size (default=4096/8192) * Setting this to small values (100bytes) still does NOT help detecting feof() */ stream_set_chunk_size($this->sock, 1024); }
/** * @group feof * @group filesystemfunc */ function testFeofReadWithoutStreamChunking() { $fullFile = "{$this->basePath}/test"; $this->put('/test', 'abcd'); $h = fopen($fullFile, "r"); // See stream_chunk_ensure_quirk stream_set_chunk_size($h, 1); $this->assertFalse(feof($h)); fread($h, 2); $this->assertFalse(feof($h)); fread($h, 2); $this->assertFalse(feof($h)); fread($h, 1); $this->assertTrue(feof($h)); fseek($h, 2); $this->assertFalse(feof($h)); }
public function init() { parent::init(); $timeout_f = (double) $this->timeout_ms / 1000; $this->sock = @stream_socket_client("{$this->host}:{$this->port}", $errno, $errstr, $timeout_f); if (!$this->sock) { throw new Exception("{$errno}: {$errstr}"); } $timeout_sec = intval($this->timeout_ms / 1000); $timeout_usec = ($this->timeout_ms - $timeout_sec * 1000) * 1000; @stream_set_timeout($this->sock, $timeout_sec, $timeout_usec); if (function_exists('stream_set_chunk_size')) { @stream_set_chunk_size($this->sock, 1024 * 1024); } if (true === $this->easy) { $this->easy(); } }
/** * A little bit messy but mainy to give useful errors. It's probably going to be the most common thing people hit. * * AbstractRegister constructor. * @param BoardInterface $board * @throws InternalFailureException */ public function __construct(BoardInterface $board) { //If there's a direct mapping file, try to use it. //Kept this generic in case we eventually get a /dev/spimem, /dev/pwmmem etc $dm_file = static::getDirectMemoryFile(); if ($dm_file !== null && file_exists($dm_file)) { $this->mmap = @mmap_open($dm_file, self::MMAP_BLOCK_SIZE, static::getOffset()); if ($this->mmap === false) { $reg_reflect = new \ReflectionClass($this); throw new InternalFailureException(sprintf('Couldn\'t map %s register. You must either run as root, or be a member of the %s group.', $reg_reflect->getShortName(), posix_getgrgid(filegroup($dm_file))['name'])); } } else { $this->mmap = @mmap_open('/dev/mem', self::MMAP_BLOCK_SIZE, $board->getPeripheralBaseAddress() + static::getOffset()); if ($this->mmap === false) { $reg_reflect = new \ReflectionClass($this); throw new InternalFailureException(sprintf('Couldn\'t map %s register. Are you running as root?', $reg_reflect->getShortName())); } } //Only read 4 bytes at a time, not PHP's 8k default stream_set_chunk_size($this->mmap, 4); //Should there be a 'register backup' in here that gets replayed on destruct? }
/** * @param resource $socket * @param bool $autoClose True to close the resource on destruct, false to leave it open. */ public function __construct($socket, bool $autoClose = true) { parent::__construct($socket, $autoClose); stream_set_read_buffer($socket, 0); stream_set_write_buffer($socket, 0); stream_set_chunk_size($socket, self::MAX_PACKET_SIZE); $this->readQueue = new \SplQueue(); $this->writeQueue = new \SplQueue(); $this->poll = $this->createPoll($socket, $this->readQueue); $this->await = $this->createAwait($socket, $this->writeQueue); $this->onReceiveCancelled = function () { $this->poll->cancel(); $this->readQueue->shift(); }; $this->onSendCancelled = function (\Exception $exception) { $this->free($exception); }; try { list($this->address, $this->port) = Socket\getName($socket, false); } catch (FailureException $exception) { $this->close(); } }
/** * Get random bytes * * @param int $length Output length * @return string */ public function get_random_bytes($length) { if (empty($length) or !ctype_digit((string) $length)) { return FALSE; } // Unfortunately, none of the following PRNGs is guaranteed to exist ... if (defined('MCRYPT_DEV_URANDOM') && ($output = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM)) !== FALSE) { return $output; } if (is_readable('/dev/urandom') && ($fp = fopen('/dev/urandom', 'rb')) !== FALSE) { // Try not to waste entropy ... is_php('5.4') && stream_set_chunk_size($fp, $length); $output = fread($fp, $length); fclose($fp); if ($output !== FALSE) { return $output; } } if (function_exists('openssl_random_pseudo_bytes')) { return openssl_random_pseudo_bytes($length); } return FALSE; }
/** * Generates specified number of random bytes. * Note that output may not be ASCII. * @see generateRandomString() if you need a string. * * @param int $length the number of bytes to generate * @return string the generated random bytes * @throws InvalidParamException if wrong length is specified * @throws Exception on failure. */ public function generateRandomKey($length = 32) { if (!is_int($length)) { throw new InvalidParamException('First parameter ($length) must be an integer'); } if ($length < 1) { throw new InvalidParamException('First parameter ($length) must be greater than 0'); } // always use random_bytes() if it is available if (function_exists('random_bytes')) { return random_bytes($length); } // The recent LibreSSL RNGs are faster and likely better than /dev/urandom. // Parse OPENSSL_VERSION_TEXT because OPENSSL_VERSION_NUMBER is no use for LibreSSL. // https://bugs.php.net/bug.php?id=71143 if ($this->_useLibreSSL === null) { $this->_useLibreSSL = defined('OPENSSL_VERSION_TEXT') && preg_match('{^LibreSSL (\\d\\d?)\\.(\\d\\d?)\\.(\\d\\d?)$}', OPENSSL_VERSION_TEXT, $matches) && 10000 * $matches[1] + 100 * $matches[2] + $matches[3] >= 20105; } // Since 5.4.0, openssl_random_pseudo_bytes() reads from CryptGenRandom on Windows instead // of using OpenSSL library. LibreSSL is OK everywhere but don't use OpenSSL on non-Windows. if ($this->_useLibreSSL || DIRECTORY_SEPARATOR !== '/' && substr_compare(PHP_OS, 'win', 0, 3, true) === 0 && function_exists('openssl_random_pseudo_bytes')) { $key = openssl_random_pseudo_bytes($length, $cryptoStrong); if ($cryptoStrong === false) { throw new Exception('openssl_random_pseudo_bytes() set $crypto_strong false. Your PHP setup is insecure.'); } if ($key !== false && StringHelper::byteLength($key) === $length) { return $key; } } // mcrypt_create_iv() does not use libmcrypt. Since PHP 5.3.7 it directly reads // CryptGenRandom on Windows. Elsewhere it directly reads /dev/urandom. if (function_exists('mcrypt_create_iv')) { $key = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM); if (StringHelper::byteLength($key) === $length) { return $key; } } // If not on Windows, try to open a random device. if ($this->_randomFile === null && DIRECTORY_SEPARATOR === '/') { // urandom is a symlink to random on FreeBSD. $device = PHP_OS === 'FreeBSD' ? '/dev/random' : '/dev/urandom'; // Check random device for special character device protection mode. Use lstat() // instead of stat() in case an attacker arranges a symlink to a fake device. $lstat = @lstat($device); if ($lstat !== false && ($lstat['mode'] & 0170000) === 020000) { $this->_randomFile = fopen($device, 'rb') ?: null; if (is_resource($this->_randomFile)) { // Reduce PHP stream buffer from default 8192 bytes to optimize data // transfer from the random device for smaller values of $length. // This also helps to keep future randoms out of user memory space. $bufferSize = 8; if (function_exists('stream_set_read_buffer')) { stream_set_read_buffer($this->_randomFile, $bufferSize); } // stream_set_read_buffer() isn't implemented on HHVM if (function_exists('stream_set_chunk_size')) { stream_set_chunk_size($this->_randomFile, $bufferSize); } } } } if (is_resource($this->_randomFile)) { $buffer = ''; $stillNeed = $length; while ($stillNeed > 0) { $someBytes = fread($this->_randomFile, $stillNeed); if ($someBytes === false) { break; } $buffer .= $someBytes; $stillNeed -= StringHelper::byteLength($someBytes); if ($stillNeed === 0) { // Leaving file pointer open in order to make next generation faster by reusing it. return $buffer; } } fclose($this->_randomFile); $this->_randomFile = null; } throw new Exception('Unable to generate a random key'); }
/** * Unless open_basedir is enabled, use /dev/urandom for * random numbers in accordance with best practices * * Why we use /dev/urandom and not /dev/random * @ref http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers * * @param int $bytes * * @throws Exception * * @return string */ function random_bytes($bytes) { static $fp = null; /** * This block should only be run once */ if (empty($fp)) { /** * We use /dev/urandom if it is a char device. * We never fall back to /dev/random */ $fp = fopen('/dev/urandom', 'rb'); if (!empty($fp)) { $st = fstat($fp); if (($st['mode'] & 0170000) !== 020000) { fclose($fp); $fp = false; } } if (!empty($fp)) { /** * stream_set_read_buffer() does not exist in HHVM * * If we don't set the stream's read buffer to 0, PHP will * internally buffer 8192 bytes, which can waste entropy * * stream_set_read_buffer returns 0 on success */ if (function_exists('stream_set_read_buffer')) { stream_set_read_buffer($fp, RANDOM_COMPAT_READ_BUFFER); } if (function_exists('stream_set_chunk_size')) { stream_set_chunk_size($fp, RANDOM_COMPAT_READ_BUFFER); } } } try { $bytes = RandomCompat_intval($bytes); } catch (TypeError $ex) { throw new TypeError('random_bytes(): $bytes must be an integer'); } if ($bytes < 1) { throw new Error('Length must be greater than 0'); } /** * This if() block only runs if we managed to open a file handle * * It does not belong in an else {} block, because the above * if (empty($fp)) line is logic that should only be run once per * page load. */ if (!empty($fp)) { $remaining = $bytes; $buf = ''; /** * We use fread() in a loop to protect against partial reads */ do { $read = fread($fp, $remaining); if ($read === false) { /** * We cannot safely read from the file. Exit the * do-while loop and trigger the exception condition */ $buf = false; break; } /** * Decrease the number of bytes returned from remaining */ $remaining -= RandomCompat_strlen($read); $buf .= $read; } while ($remaining > 0); /** * Is our result valid? */ if ($buf !== false) { if (RandomCompat_strlen($buf) === $bytes) { /** * Return our random entropy buffer here: */ return $buf; } } } /** * If we reach here, PHP has failed us. */ throw new Exception('Error reading from source device'); }
/** * Opens an internal GPG subprocess for the current operation * * Opens a GPG subprocess, then connects the subprocess to some pipes. Sets * the private class property {@link Crypt_GPG_Engine::$_process} to * the new subprocess. * * @return void * * @throws Crypt_GPG_OpenSubprocessException if the subprocess could not be * opened. * * @see Crypt_GPG_Engine::setOperation() * @see Crypt_GPG_Engine::_closeSubprocess() * @see Crypt_GPG_Engine::$_process */ private function _openSubprocess() { $version = $this->getVersion(); // log versions, but not when looking for the version number if ($version !== '1.0.0') { $this->_debug('USING GPG ' . $version . ' with PHP ' . PHP_VERSION); } // Binary operations will not work on Windows with PHP < 5.2.6. This is // in case stream_select() ever works on Windows. $rb = version_compare(PHP_VERSION, '5.2.6') < 0 ? 'r' : 'rb'; $wb = version_compare(PHP_VERSION, '5.2.6') < 0 ? 'w' : 'wb'; $env = $_ENV; // Newer versions of GnuPG return localized results. Crypt_GPG only // works with English, so set the locale to 'C' for the subprocess. $env['LC_ALL'] = 'C'; // If using GnuPG 2.x < 2.1.13 start the gpg-agent if (version_compare($version, '2.0.0', 'ge') && version_compare($version, '2.1.13', 'lt')) { if (!$this->_agent) { throw new Crypt_GPG_OpenSubprocessException('Unable to open gpg-agent subprocess (gpg-agent not found). ' . 'Please specify location of the gpg-agent binary ' . 'using the \'agent\' driver option.'); } $agentArguments = array('--daemon', '--options /dev/null', '--csh', '--keep-display', '--no-grab', '--ignore-cache-for-signing', '--pinentry-touch-file /dev/null', '--disable-scdaemon', '--no-use-standard-socket', '--pinentry-program ' . escapeshellarg($this->_getPinEntry())); if ($this->_homedir) { $agentArguments[] = '--homedir ' . escapeshellarg($this->_homedir); } if ($version21 = version_compare($version, '2.1.0', 'ge')) { // This is needed to get socket file location in stderr output // Note: This does not help when the agent already is running $agentArguments[] = '--verbose'; } $agentCommandLine = $this->_agent . ' ' . implode(' ', $agentArguments); $agentDescriptorSpec = array(self::FD_INPUT => array('pipe', $rb), self::FD_OUTPUT => array('pipe', $wb), self::FD_ERROR => array('pipe', $wb)); $this->_debug('OPENING GPG-AGENT SUBPROCESS WITH THE FOLLOWING COMMAND:'); $this->_debug($agentCommandLine); $this->_agentProcess = proc_open($agentCommandLine, $agentDescriptorSpec, $this->_agentPipes, null, $env, array('binary_pipes' => true)); if (!is_resource($this->_agentProcess)) { throw new Crypt_GPG_OpenSubprocessException('Unable to open gpg-agent subprocess.', 0, $agentCommandLine); } // Get GPG_AGENT_INFO and set environment variable for gpg process. // This is a blocking read, but is only 1 line. $agentInfo = fread($this->_agentPipes[self::FD_OUTPUT], self::CHUNK_SIZE); // For GnuPG 2.1 we need to read both stderr and stdout if ($version21) { $agentInfo .= "\n" . fread($this->_agentPipes[self::FD_ERROR], self::CHUNK_SIZE); } if ($agentInfo) { foreach (explode("\n", $agentInfo) as $line) { if ($version21) { if (preg_match('/listening on socket \'([^\']+)/', $line, $m)) { $this->_agentInfo = $m[1]; } else { if (preg_match('/gpg-agent\\[([0-9]+)\\].* started/', $line, $m)) { $this->_agentInfo .= ':' . $m[1] . ':1'; } } } else { if (preg_match('/GPG_AGENT_INFO=([^;]+)/', $line, $m)) { $this->_agentInfo = $m[1]; break; } } } } $this->_debug('GPG-AGENT-INFO: ' . $this->_agentInfo); $env['GPG_AGENT_INFO'] = $this->_agentInfo; // gpg-agent daemon is started, we can close the launching process $this->_closeAgentLaunchProcess(); // Terminate processes if something went wrong register_shutdown_function(array($this, '__destruct')); } // "Register" GPGConf existence for _closeIdleAgents() if (version_compare($version, '2.1.0', 'ge')) { if ($this->_gpgconf === null) { $this->_gpgconf = $this->_getGPGConf(); } } else { $this->_gpgconf = false; } $commandLine = $this->_binary; $defaultArguments = array('--status-fd ' . escapeshellarg(self::FD_STATUS), '--command-fd ' . escapeshellarg(self::FD_COMMAND), '--no-secmem-warning', '--no-tty', '--no-default-keyring', '--no-options'); if (version_compare($version, '1.0.7', 'ge')) { if (version_compare($version, '2.0.0', 'lt')) { $defaultArguments[] = '--no-use-agent'; } $defaultArguments[] = '--no-permission-warning'; } if (version_compare($version, '1.4.2', 'ge')) { $defaultArguments[] = '--exit-on-status-write-error'; } if (version_compare($version, '1.3.2', 'ge')) { $defaultArguments[] = '--trust-model always'; } else { $defaultArguments[] = '--always-trust'; } // Since 2.1.13 we can use "loopback mode" instead of gpg-agent if (version_compare($version, '2.1.13', 'ge')) { $defaultArguments[] = '--pinentry-mode loopback'; } $arguments = array_merge($defaultArguments, $this->_arguments); if ($this->_homedir) { $arguments[] = '--homedir ' . escapeshellarg($this->_homedir); // the random seed file makes subsequent actions faster so only // disable it if we have to. if (!is_writeable($this->_homedir)) { $arguments[] = '--no-random-seed-file'; } } if ($this->_publicKeyring) { $arguments[] = '--keyring ' . escapeshellarg($this->_publicKeyring); } if ($this->_privateKeyring) { $arguments[] = '--secret-keyring ' . escapeshellarg($this->_privateKeyring); } if ($this->_trustDb) { $arguments[] = '--trustdb-name ' . escapeshellarg($this->_trustDb); } $commandLine .= ' ' . implode(' ', $arguments) . ' ' . $this->_operation; $descriptorSpec = array(self::FD_INPUT => array('pipe', $rb), self::FD_OUTPUT => array('pipe', $wb), self::FD_ERROR => array('pipe', $wb), self::FD_STATUS => array('pipe', $wb), self::FD_COMMAND => array('pipe', $rb), self::FD_MESSAGE => array('pipe', $rb)); $this->_debug('OPENING GPG SUBPROCESS WITH THE FOLLOWING COMMAND:'); $this->_debug($commandLine); $this->_process = proc_open($commandLine, $descriptorSpec, $this->_pipes, null, $env, array('binary_pipes' => true)); if (!is_resource($this->_process)) { throw new Crypt_GPG_OpenSubprocessException('Unable to open GPG subprocess.', 0, $commandLine); } // Set streams as non-blocking. See Bug #18618. foreach ($this->_pipes as $pipe) { stream_set_blocking($pipe, 0); stream_set_write_buffer($pipe, self::CHUNK_SIZE); stream_set_chunk_size($pipe, self::CHUNK_SIZE); stream_set_read_buffer($pipe, self::CHUNK_SIZE); } $this->_openPipes = $this->_pipes; }
/** * Get random bytes * * @ref https://github.com/paragonie/random_compat/ * * @param int $length Output length * * @return string|false false on error */ public static function get_random_bytes($length) { if (!$length || !ctype_digit((string) $length)) { return false; } else { $length = (int) $length; } if (function_exists('random_bytes') && self::is_php('7.0')) { /** * PHP 7 -> http://php.net/manual/de/function.random-bytes.php */ try { $return = random_bytes($length); } catch (\Exception $e) { $return = false; } return $return; } else { /** * PHP 5.2.0 - 5.6.x way to implement random_bytes() * * // WARNING: Unfortunately, none of the following PRNGs is guaranteed to exist ... * * In order of preference: * 1. PHP-Module: "mcrypt" via mcrypt_create_iv() * 2. Linux / BSD: "/dev/urandom" via fread() * 3. Windows: \COM('CAPICOM.Utilities.1')->GetRandom() * 4. PHP+OpenSSL: openssl_random_pseudo_bytes() */ /** * 1. PHP-Module */ if (extension_loaded('mcrypt') && defined(MCRYPT_DEV_URANDOM) === true) { $output = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM); if ($output !== false && UTF8::strlen($output, '8bit') === $length) { return $output; } } /** * 2. Linux / BSD */ if (!ini_get('open_basedir') && is_readable('/dev/urandom')) { $fp = fopen('/dev/urandom', 'rb'); if (!empty($fp)) { $st = fstat($fp); // In C, this would be: (stat_mode & S_IFMT) !== S_IFCHR if (($st['mode'] & 0170000) !== 020000) { fclose($fp); $fp = false; } unset($st); } } if (isset($fp) && $fp !== false) { /** * stream_set_read_buffer() / stream_set_chunk_size does not exist in HHVM * * If we don't set the stream's read buffer to 0, PHP will * internally buffer 8192 bytes, which can waste entropy * * stream_set_read_buffer returns 0 on success */ if (function_exists('stream_set_chunk_size')) { stream_set_chunk_size($fp, $length); } if (function_exists('stream_set_read_buffer')) { stream_set_read_buffer($fp, $length); } $remaining = $length; $buf = ''; do { $read = fread($fp, $remaining); // We cannot safely read from the file, so exit the do-while loop. if ($read === false) { $buf = false; break; } // Decrease the number of bytes returned from remaining. $remaining -= UTF8::strlen($read, '8bit'); $buf .= $read; } while ($remaining > 0); fclose($fp); if ($buf !== false) { if (UTF8::strlen($buf, '8bit') === $length) { return $buf; } } } /* * 3. Windows * * PHP can be used to access COM objects on Windows platforms * * --- * * PROBLEM: you see this error-message: * com_exception thrown with message * "Failed to create COM object `CAPICOM.Utilities.1': Ungültige Syntax * * SOLUTION: register the dll: * regsvr32 c:\windows\capicom.dll * * --- * * @ref http://php.net/manual/en/ref.com.php */ if (extension_loaded('com_dotnet') && class_exists('COM') === true) { // init $buf = ''; /** @noinspection PhpUndefinedClassInspection */ $util = new \COM('CAPICOM.Utilities.1'); /** * Let's not let it loop forever. If we run N times and fail to * get N bytes of random data, then CAPICOM has failed us. */ $execCount = 0; do { /** @noinspection PhpUndefinedMethodInspection */ $buf .= base64_decode($util->GetRandom($length, 0)); if (UTF8::strlen($buf, '8bit') >= $length) { return UTF8::substr($buf, 0, $length); } ++$execCount; } while ($execCount < $length); } /** * 4. PHP + OpenSSL * * fallback to "openssl_random_pseudo_bytes()" */ if (function_exists('openssl_random_pseudo_bytes')) { $output = openssl_random_pseudo_bytes($length, $strong); if ($output !== false && $strong === true) { if (UTF8::strlen($output, '8bit') === $length) { return $output; } } } return false; } }
public function fopen($path, $mode) { $fh = fopen($this->constructUrl($path), $mode); if ($fh) { // override the default 8k php stream chunk // size for non-file streams. stream_set_chunk_size($fh, 1024 * 1024 * 10); } return $fh; }
/** * Change stream options. * * @codeCoverageIgnore * * @param int $option One of STREAM_OPTION_BLOCKING, STREAM_OPTION_READ_TIMEOUT, STREAM_OPTION_WRITE_BUFFER. * @param int $arg1 Depending on option. * @param int $arg2 Depending on option. * * @return boolean Returns TRUE on success or FALSE on failure. If option is not implemented, * FALSE should be returned. */ public function stream_set_option($option, $arg1, $arg2) { switch ($option) { case STREAM_OPTION_BLOCKING: return stream_set_blocking($this->resource, $arg1); case STREAM_OPTION_READ_TIMEOUT: return stream_set_timeout($this->resource, $arg1, $arg2); case STREAM_OPTION_WRITE_BUFFER: return stream_set_write_buffer($this->resource, $arg1); case STREAM_OPTION_READ_BUFFER: return stream_set_read_buffer($this->resource, $arg1); case STREAM_OPTION_CHUNK_SIZE: return stream_set_chunk_size($this->resource, $arg1); } }
/** * password_hash() * * @link http://php.net/password_hash * @param string $password * @param int $algo * @param array $options * @return mixed */ function password_hash($password, $algo, array $options = array()) { static $func_override; isset($func_override) or $func_override = extension_loaded('mbstring') && ini_get('mbstring.func_override'); if ($algo !== 1) { trigger_error('password_hash(): Unknown hashing algorithm: ' . (int) $algo, E_USER_WARNING); return NULL; } if (isset($options['cost']) && ($options['cost'] < 4 or $options['cost'] > 31)) { trigger_error('password_hash(): Invalid bcrypt cost parameter specified: ' . (int) $options['cost'], E_USER_WARNING); return NULL; } if (isset($options['salt']) && ($saltlen = $func_override ? mb_strlen($options['salt'], '8bit') : strlen($options['salt'])) < 22) { trigger_error('password_hash(): Provided salt is too short: ' . $saltlen . ' expecting 22', E_USER_WARNING); return NULL; } elseif (!isset($options['salt'])) { if (defined('MCRYPT_DEV_URANDOM')) { $options['salt'] = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM); } elseif (function_exists('openssl_random_pseudo_bytes')) { $options['salt'] = openssl_random_pseudo_bytes(16); } elseif (DIRECTORY_SEPARATOR === '/' && (is_readable($dev = '/dev/arandom') or is_readable($dev = '/dev/urandom'))) { if (($fp = fopen($dev, 'rb')) === FALSE) { log_message('error', 'compat/password: Unable to open ' . $dev . ' for reading.'); return FALSE; } // Try not to waste entropy ... is_php('5.4') && stream_set_chunk_size($fp, 16); $options['salt'] = ''; for ($read = 0; $read < 16; $read = $func_override ? mb_strlen($options['salt'], '8bit') : strlen($options['salt'])) { if (($read = fread($fp, 16 - $read)) === FALSE) { log_message('error', 'compat/password: Error while reading from ' . $dev . '.'); return FALSE; } $options['salt'] .= $read; } fclose($fp); } else { log_message('error', 'compat/password: No CSPRNG available.'); return FALSE; } $options['salt'] = str_replace('+', '.', rtrim(base64_encode($options['salt']), '=')); } elseif (!preg_match('#^[a-zA-Z0-9./]+$#D', $options['salt'])) { $options['salt'] = str_replace('+', '.', rtrim(base64_encode($options['salt']), '=')); } isset($options['cost']) or $options['cost'] = 10; return strlen($password = crypt($password, sprintf('$2y$%02d$%s', $options['cost'], $options['salt']))) === 60 ? $password : FALSE; }
/** * getRandomBytes() * * Reads the specified amount of data from the system's PRNG. * * @param int $length Desired output length * @return string A pseudo-random stream of bytes */ public static function getRandomBytes($length, $rawOutput = false) { if (!is_int($length) or $length < 1) { throw new \InvalidArgumentException('Length must be an integer larger than 0.'); } // @codeCoverageIgnoreStart if (\function_exists('openssl_random_pseudo_bytes')) { $cryptoStrong = null; if (($output = \openssl_random_pseudo_bytes($length, $cryptoStrong)) !== false && $cryptoStrong) { return $rawOutput ? $output : \bin2hex($output); } } if (\defined('MCRYPT_DEV_URANDOM')) { if (($output = \mcrypt_create_iv($length, MCRYPT_DEV_URANDOM)) !== false) { return $rawOutput ? $output : \bin2hex($output); } } if (\is_readable('/dev/urandom') && ($fp = \fopen('/dev/urandom', 'rb')) !== false) { \stream_set_chunk_size($fp, $length); $output = \fread($fp, $length); \fclose($fp); if ($output !== false) { return $rawOutput ? $output : \bin2hex($output); } } throw new \RuntimeException('No reliable PRNG source is available on the system.'); // @codeCoverageIgnoreEnd }
} if ($cli->getParam('in')) { $in = $cli->getParam('in'); } else { die("You must specify an input file\n"); } if ($cli->getParam('out')) { $out = $cli->getParam('out'); } else { die("You must specify an output file\n"); } $timeStart = microtime(true); if (file_exists($in)) { $flvIn = fopen($in, "rb"); if (function_exists("stream_set_chunk_size")) { stream_set_chunk_size($flvIn, 8 * 1024 * 1024); } $flvTag = fread($flvIn, $flvHeaderLen); if (strncmp($flvTag, "FLV", 3) != 0) { die("Input file is not a valid FLV file\n"); } $fileLen = filesize($in); $filePos = $flvHeaderLen; $fileSize = $fileLen / (1024 * 1024); $pFilePos = 0; } else { die("Input file doesn't exist\n"); } $flvOut = fopen($out, "w+b"); if (!$flvOut) { die("Failed to create output file\n");
/** * Alias for stream_set_chunk_size * @param integer $chunkSize * @return integer */ public function setChunkSize($chunkSize) { if ($this->isOpen()) { stream_set_chunk_size($this->pointer, $chunkSize); } return $chunkSize; }
/** * Sets the size of a stream's buffer. * * @param int $size The desired size of the buffer, in bytes. * @param int $direction The buffer of which direction to set. Valid * values are the DIRECTION_* constants. * * @return bool TRUE on success, FALSE on failure. */ public function setBuffer($size, $direction = self::DIRECTION_ALL) { $result = parent::setBuffer($size, $direction); if (self::DIRECTION_SEND === $direction && function_exists('stream_set_chunk_size') && !$result) { return false !== @stream_set_chunk_size($this->stream, $size); } return $result; }
<?php $fd = fopen(__DIR__ . '/stream_set_chunk_size.php.sample', 'rb'); var_dump(stream_set_chunk_size($fd, 8192)); var_dump(stream_set_chunk_size($fd, 256)); var_dump(stream_set_chunk_size($fd, 0)); fclose($fd);
/** * Get random bytes * * @param int $length Output length * @return string */ public function get_random_bytes($length) { if (empty($length) or !ctype_digit((string) $length)) { return FALSE; } if (function_exists('random_bytes')) { try { // The cast is required to avoid TypeError return random_bytes((int) $length); } catch (Exception $e) { // If random_bytes() can't do the job, we can't either ... // There's no point in using fallbacks. log_message('error', $e->getMessage()); return FALSE; } } // Unfortunately, none of the following PRNGs is guaranteed to exist ... if (defined('MCRYPT_DEV_URANDOM') && ($output = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM)) !== FALSE) { return $output; } if (is_readable('/dev/urandom') && ($fp = fopen('/dev/urandom', 'rb')) !== FALSE) { // Try not to waste entropy ... stream_set_chunk_size($fp, $length); $output = fread($fp, $length); fclose($fp); if ($output !== FALSE) { return $output; } } if (function_exists('openssl_random_pseudo_bytes')) { return openssl_random_pseudo_bytes($length); } return FALSE; }
/** * StreamWrapper::stream_fread is usually called with a minimum buffer size of 8192 * regardless of what value is passed to fread(). It will then keep reading until * the value passed to fread() is satisfied or EOF is reached. * * This can be overridden by calling stream_set_chunk_size($size), which has a * bizarre and undocumented quirk: * * // Pass $len from fread($h, $len) to StreamWrapper::stream_read($len) * stream_set_chunk_size($h, 1); * * // Pass stream chunk size to StreamWrapper::stream_read($len) * stream_set_chunk_size($h, 2); * * This function just tests that my assumptions about this behaviour remain correct. */ function stream_chunk_ensure_quirk() { stream_wrapper_register('streamchunkquirk', 'Defile\\Test\\BufferTestingStream'); $h = fopen('streamchunkquirk://yep', 'r'); fread($h, 1); fclose($h); if (\Defile\Test\BufferTestingStream::$bufferSize != 8192) { throw new \UnexpectedValueException(); } $h = fopen('streamchunkquirk://yep', 'r'); stream_set_chunk_size($h, 1); fread($h, 999); fclose($h); if (\Defile\Test\BufferTestingStream::$bufferSize != 999) { throw new \UnexpectedValueException(); } $h = fopen('streamchunkquirk://yep', 'r'); stream_set_chunk_size($h, 2); fread($h, 999); fclose($h); if (\Defile\Test\BufferTestingStream::$bufferSize != 2) { throw new \UnexpectedValueException(\Defile\Test\BufferTestingStream::$bufferSize); } stream_wrapper_unregister('streamchunkquirk'); }
{ echo "option: ", $option, ", ", $arg1, ", ", $arg2, "\n"; return false; } } var_dump(stream_wrapper_register('test', 'test_wrapper')); $f = fopen("test://foo", "r"); /* when the chunk size is 1, the read buffer is skipped, but the * the writes are made in chunks of size 1 (business as usual) * This should probably be revisited */ echo "should return previous chunk size (8192)\n"; var_dump(stream_set_chunk_size($f, 1)); echo "should be read without buffer (\$count == 10000)\n"; var_dump(strlen(fread($f, 10000))); echo "should elicit 3 writes of size 1 and return 3\n"; var_dump(fwrite($f, str_repeat('b', 3))); echo "should return previous chunk size (1)\n"; var_dump(stream_set_chunk_size($f, 100)); echo "should elicit one read of size 100 (chunk size)\n"; var_dump(strlen(fread($f, 250))); echo "should elicit one read of size 100 (chunk size)\n"; var_dump(strlen(fread($f, 50))); echo "should elicit no read because there is sufficient cached data\n"; var_dump(strlen(fread($f, 50))); echo "should elicit 2 writes of size 100 and one of size 50\n"; var_dump(strlen(fwrite($f, str_repeat('b', 250)))); echo "\nerror conditions\n"; var_dump(stream_set_chunk_size($f, 0)); var_dump(stream_set_chunk_size($f, -1)); var_dump(stream_set_chunk_size($f, array()));
/** * Set the stream chunk size * * @param resource $fp * @param int $chunkSize * * @return int */ public function setChunkSize($fp, int $chunkSize) : int { return stream_set_chunk_size($fp, $chunkSize); }