Add APC caching method, update automated.config.php and settings.php.example accordingly. Add find_password_hash_cost.php into misc/testing/Various/ folder.

This commit is contained in:
Darko
2015-06-15 08:55:13 +02:00
parent 35fa7f3ea9
commit e595d81308
4 changed files with 289 additions and 126 deletions
@@ -0,0 +1,29 @@
<?php
/**
* This code will benchmark your server to determine how high of a cost you can
* afford. You want to set the highest cost that you can without slowing down
* you server too much. 10 is a good baseline, and more is good if your servers
* are fast enough.
*
* Set this number in www/settings.php, the nZEDb_PASSWORD_HASH_COST setting.
*/
if (!isset($argv[1]) || !is_numeric($argv[1]) || $argv[1] < 0.05) {
exit(
'You can pass in a target time, which will be used to determine the cost.' . PHP_EOL .
'The target time is the amount of time it will take to hash a password.' . PHP_EOL .
'Hashing of passwords happens when a user registers an account or their hash needs to be updated because it is insecure.' . PHP_EOL .
'Values between 0.2 and 0.5 are recommended. The minimum is 0.05 for security reasons.' . PHP_EOL
);
}
$timeTarget = $argv[1];
$cost = 7;
do {
$cost++;
$start = microtime(true);
password_hash("test", PASSWORD_DEFAULT, ["cost" => $cost]);
$end = microtime(true);
} while (($end - $start) < $timeTarget);
echo "Appropriate Cost Found: " . $cost . PHP_EOL;
+195 -98
View File
@@ -17,6 +17,7 @@ class Cache
const TYPE_DISABLED = 0;
const TYPE_MEMCACHED = 1;
const TYPE_REDIS = 2;
const TYPE_APC = 3;
/**
* @var \Memcached|\Redis
@@ -35,18 +36,6 @@ class Cache
*/
private $socketFile;
/**
* Serializer type.
* @var bool|int
*/
private $serializerType;
/**
* Are we using redis or memcached?
* @var bool
*/
private $isRedis = true;
/**
* Does the user have igBinary support and wants to use it?
* @var bool
@@ -65,16 +54,43 @@ class Cache
*/
public function set($key, $data, $expiration)
{
if ($this->connected === true && $this->ping() === true) {
return $this->server->set(
$key,
($this->isRedis ? ($this->IgBinarySupport ? igbinary_serialize($data) : serialize($data)) : $data),
$expiration
);
if ($this->ping()) {
$this->serializeData($data);
switch (NN_CACHE_TYPE) {
case self::TYPE_REDIS:
case self::TYPE_MEMCACHED:
return $this->server->set($key, $data, $expiration);
case self::TYPE_APC:
return apc_add($key, $data, $expiration);
}
}
return false;
}
/**
* Serialize data, or not based on admin setting.
*
* @param string|array $data
*/
private function serializeData(&$data)
{
switch (NN_CACHE_SERIALIZER) {
case self::SERIALIZER_IGBINARY:
if ($this->IgBinarySupport) {
$data = igbinary_serialize($data);
} else {
$data = serialize($data);
}
break;
case self::SERIALIZER_PHP:
$data = serialize($data);
break;
case self::SERIALIZER_NONE:
default:
break;
}
}
/**
* Attempt to retrieve a value from the cache server, if not set it.
*
@@ -85,13 +101,47 @@ class Cache
*/
public function get($key)
{
if ($this->connected === true && $this->ping() === true) {
$data = $this->server->get($key);
return ($this->isRedis ? ($this->IgBinarySupport ? igbinary_unserialize($data) : unserialize($data)) : $data);
if ($this->ping()) {
$data = '';
switch (NN_CACHE_TYPE) {
case self::TYPE_REDIS:
case self::TYPE_MEMCACHED:
$data = $this->server->get($key);
break;
case self::TYPE_APC:
$data = apc_fetch($key);
break;
}
$this->unserializeData($data);
return $data;
}
return false;
}
/**
* Un-serialize data, or not based on admin setting.
*
* @param string $data
*/
private function unserializeData(&$data)
{
switch (NN_CACHE_SERIALIZER) {
case self::SERIALIZER_IGBINARY:
if ($this->IgBinarySupport) {
$data = igbinary_unserialize($data);
} else {
$data = unserialize($data);
}
break;
case self::SERIALIZER_PHP:
$data = unserialize($data);
break;
case self::SERIALIZER_NONE:
default:
break;
}
}
/**
* Delete data tied to a key on the cache server.
*
@@ -102,8 +152,14 @@ class Cache
*/
public function delete($key)
{
if ($this->connected === true && $this->ping() === true) {
return (bool)$this->server->delete($key);
if ($this->ping()) {
switch (NN_CACHE_TYPE) {
case self::TYPE_REDIS:
case self::TYPE_MEMCACHED:
return (bool)$this->server->delete($key);
case self::TYPE_APC:
return apc_delete($key);
}
}
return false;
}
@@ -113,11 +169,18 @@ class Cache
*/
public function flush()
{
if ($this->connected === true && $this->ping() === true) {
if ($this->isRedis === true) {
$this->server->flushAll();
} else {
$this->server->flush();
if ($this->ping()) {
switch (NN_CACHE_TYPE) {
case self::TYPE_REDIS:
$this->server->flushAll();
break;
case self::TYPE_MEMCACHED:
$this->server->flush();
break;
case self::TYPE_APC:
apc_clear_cache("user");
apc_clear_cache();
break;
}
}
}
@@ -138,16 +201,19 @@ class Cache
/**
* Get cache server statistics.
*
* @return array|string
* @return array
* @access public
*/
public function serverStatistics()
{
if ($this->connected === true && $this->ping() === true) {
if ($this->isRedis === true) {
return $this->server->info();
} else {
return $this->server->getStats();
if ($this->ping()) {
switch (NN_CACHE_TYPE) {
case self::TYPE_REDIS:
return $this->server->info();
case self::TYPE_MEMCACHED:
return $this->server->getStats();
case self::TYPE_APC:
return apc_cache_info();
}
}
return array();
@@ -175,9 +241,9 @@ class Cache
$this->socketFile = true;
}
$this->serializerType = false;
$serializer = false;
if (defined('NN_CACHE_SERIALIZER')) {
$this->serializerType = true;
$serializer = true;
}
switch (NN_CACHE_TYPE) {
@@ -187,11 +253,9 @@ class Cache
throw new CacheException('The redis extension is not loaded!');
}
$this->server = new \Redis();
$this->isRedis = true;
$this->connect();
if ($this->serializerType !== false) {
$this->serializerType = $this->verifySerializer();
$this->server->setOption(\Redis::OPT_SERIALIZER, $this->serializerType);
if ($serializer) {
$this->server->setOption(\Redis::OPT_SERIALIZER, $this->verifySerializer());
}
break;
@@ -200,18 +264,23 @@ class Cache
throw new CacheException('The memcached extension is not loaded!');
}
$this->server = new \Memcached();
$this->isRedis = false;
if ($this->serializerType !== false) {
$this->serializerType = $this->verifySerializer();
$this->server->setOption(\Memcached::OPT_SERIALIZER, $this->serializerType);
if ($serializer) {
$this->server->setOption(\Memcached::OPT_SERIALIZER, $this->verifySerializer());
}
$this->server->setOption(\Memcached::OPT_COMPRESSION, (defined('NN_CACHE_COMPRESSION') ? NN_CACHE_COMPRESSION : false));
$this->connect();
break;
case self::TYPE_APC:
if (!function_exists('apc_set')) {
throw new CacheException('The APC extension is not loaded!');
}
$this->connect();
break;
case self::TYPE_DISABLED:
default:
return;
break;
}
}
@@ -239,54 +308,74 @@ class Cache
private function connect()
{
$this->connected = false;
if ($this->isRedis === true) {
if ($this->socketFile === false) {
$servers = unserialize(NN_CACHE_HOSTS);
foreach ($servers as $server) {
if ($this->server->connect($server['host'], $server['port'], (float)NN_CACHE_TIMEOUT) === false) {
switch (NN_CACHE_TYPE) {
case self::TYPE_REDIS:
if ($this->socketFile === false) {
$servers = unserialize(NN_CACHE_HOSTS);
foreach ($servers as $server) {
if ($this->server->connect($server['host'], $server['port'], (float)NN_CACHE_TIMEOUT) === false) {
throw new CacheException('Error connecting to the Redis server!');
} else {
$this->connected = true;
}
}
} else {
if ($this->server->connect(NN_CACHE_SOCKET_FILE) === false) {
throw new CacheException('Error connecting to the Redis server!');
} else {
$this->connected = true;
}
}
} else {
if ($this->server->connect(NN_CACHE_SOCKET_FILE) === false) {
throw new CacheException('Error connecting to the Redis server!');
} else {
$this->connected = true;
}
}
} else {
if ($this->socketFile === false) {
if ($this->server->addServers(unserialize(NN_CACHE_HOSTS)) === false) {
break;
case self::TYPE_MEMCACHED:
$params = ($this->socketFile === false ? unserialize(NN_CACHE_HOSTS) : [[NN_CACHE_SOCKET_FILE, 'port' => 0]]);
if ($this->server->addServers($params) === false) {
throw new CacheException('Error connecting to the Memcached server!');
} else {
$this->connected = true;
}
} else {
if ($this->server->addServers(array(array(NN_CACHE_SOCKET_FILE, 'port' => 0))) === false) {
throw new CacheException('Error connecting to the Memcached server!');
} else {
$this->connected = true;
}
}
break;
case self::TYPE_APC:
$this->connected = true;
break;
}
}
/**
* Redis supports ping'ing the server, so use it.
* Check if we are still connected to the cache server, reconnect if not.
*
* @return bool
*/
private function ping()
{
if ($this->isRedis === true) {
try {
return (bool)$this->server->ping();
} catch (\RedisException $error) {
$this->connect();
return $this->connected;
}
if (!$this->connected) {
return false;
}
return true;
switch (NN_CACHE_TYPE) {
case self::TYPE_REDIS:
try {
return (bool)$this->server->ping();
} catch (\RedisException $error) {
// nothing to see here, move along
}
break;
case self::TYPE_MEMCACHED:
$versions = $this->server->getVersion();
if ($versions) {
foreach ($versions as $version) {
if ($version != "255.255.255") {
return true;
}
}
}
break;
case self::TYPE_APC:
return true;
default:
return false;
}
$this->connect();
return $this->connected;
}
/**
@@ -300,34 +389,42 @@ class Cache
{
switch (NN_CACHE_SERIALIZER) {
case self::SERIALIZER_IGBINARY:
if (extension_loaded('igbinary')) {
$this->IgBinarySupport = true;
if ($this->isRedis === true) {
return \Redis::SERIALIZER_IGBINARY;
} else {
if (\Memcached::HAVE_IGBINARY > 0) {
return \Memcached::SERIALIZER_IGBINARY;
} else {
throw new CacheException('Error: You have not compiled Memcached with igbinary support!');
}
}
} else {
if (!extension_loaded('igbinary')) {
throw new CacheException('Error: The igbinary extension is not loaded!');
}
case self::SERIALIZER_NONE:
if ($this->isRedis === true) {
return \Redis::SERIALIZER_NONE;
} else {
throw new CacheException('Error: Disabled serialization is not available on Memcached!');
switch (NN_CACHE_TYPE) {
case self::TYPE_REDIS:
// No way to check since phpredis has no constants or functions for this.
return \Redis::SERIALIZER_IGBINARY;
case self::TYPE_MEMCACHED:
if (\Memcached::HAVE_IGBINARY > 0) {
return \Memcached::SERIALIZER_IGBINARY;
}
throw new CacheException('Error: You have not compiled Memcached with igbinary support!');
case self::TYPE_APC: // No way to check, since apc.serializer can not be fetched using ini_get.
default:
return null;
}
case self::SERIALIZER_NONE:
// Only redis supports this.
if (NN_CACHE_TYPE != self::TYPE_REDIS) {
throw new CacheException('Error: Disabled serialization is only available on Redis!');
}
return \Redis::SERIALIZER_NONE;
case self::SERIALIZER_PHP:
default:
if ($this->isRedis === true) {
return \Redis::SERIALIZER_PHP;
} else {
return \Memcached::SERIALIZER_PHP;
switch (NN_CACHE_TYPE) {
case self::TYPE_REDIS:
return \Redis::SERIALIZER_PHP;
case self::TYPE_MEMCACHED:
return \Memcached::SERIALIZER_PHP;
default:
return null;
}
}
}
}
}
+1 -1
View File
@@ -77,7 +77,7 @@ $settings_file = __DIR__ . DS . 'settings.php';
if (is_file($settings_file)) {
require_once($settings_file);
if (php_sapi_name() == 'cli') {
$current_settings_file_version = 1; // Update this when updating settings.php.example
$current_settings_file_version = 3; // Update this when updating settings.php.example
if (!defined('NN_SETTINGS_FILE_VERSION') || NN_SETTINGS_FILE_VERSION != $current_settings_file_version) {
echo ("\033[0;31mNotice: Your $settings_file file is either out of date or you have not updated" .
" NN_SETTINGS_FILE_VERSION to $current_settings_file_version in that file.\033[0m" . PHP_EOL
+64 -27
View File
@@ -2,7 +2,8 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////// Copy this file to settings.php and edit the options. //////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**********************************************************************************************************************/
///////////////////////////////// Scroll down to the bottom for a change log. //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**********************************************************************************************************************/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -14,9 +15,9 @@
*
* @note Developers: When updating settings.php.example, up this version
* and $current_settings_file_version in automated.config.php
* @version 1
* @version 3
*/
define('NN_SETTINGS_FILE_VERSION', 1);
define('NN_SETTINGS_FILE_VERSION', 3);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////// Web Settings //////////////////////////////////////////////////////////
@@ -47,7 +48,6 @@ define('ITEMS_PER_COVER_PAGE', '20');
*/
define('NN_MAX_PAGER_RESULTS', '125000');
/**
* If the PRE API page (preinfo) is open to the public or only accessible by registered / api users.
*
@@ -81,10 +81,12 @@ define('NN_FLOOD_MAX_REQUESTS_PER_SECOND', 5);
/**
* The higher this number, the more secure the password algorithm for the website will be, at the cost
* of server resources.
* To find a good number for your server, run the misc/testing/Dev/find_password_hash_cost.php script.
* To find a good number for your server, run the misc/testing/Various/find_password_hash_cost.php script.
*
* @note It is not recommended to set this under 11.
* @default 11
*
* @version 2
*/
define('NN_PASSWORD_HASH_COST', 11);
@@ -158,10 +160,14 @@ define('NN_RENAME_MUSIC_MEDIAINFO', true);
* 0 - disabled ; No cache server(s) will be used.
* 1 - memcached ; Memcached server(s) will be used for caching.
* 2 - redis ; Redis server(s) will be used for caching.
* 3 - apc/apcu ; APC or APCu will be used for caching.
*
* @note We use the Redis extension by nicolasff.
* @see https://github.com/nicolasff/phpredis
* @note Memcahed: The Memcached PHP extension must be installed.
* @note Redis: We use the Redis PHP extension by nicolasff. https://github.com/nicolasff/phpredis
* @note APC: The APC or APCu PHP extension must be installed.
* @note APC: Ignore these settings: NN_CACHE_HOSTS / NN_CACHE_SOCKET_FILE / NN_CACHE_TIMEOUT
* @default 0
* @version 3
*/
define('NN_CACHE_TYPE', 0);
@@ -215,21 +221,25 @@ define('NN_CACHE_TIMEOUT', 10);
define('NN_CACHE_COMPRESSION', false);
/**
* 0 - Use the PHP serializer.
* 1 - [Requires igbinary] Use igbinary serializer which is faster and uses less memory, works on both Memcached and Redis.
* Serialization is a way of converting data in PHP into strings of text which can be stored on the cache server.
*
* 0 - Use the PHP serializer. Recommended for most people.
* 1 - [Requires igbinary] Use igbinary serializer which is faster and uses less memory, works
* on Memcached / Redis / APC, read the notes below.
* 2 - [Redis Only] Use no serializer.
*
* @note igbinary must be compiled and enabled in php.ini
* @note Memcached/Redis must be compiled with igbinary support as well to use igbinary.
* @note Read the igbinary page how to compile / enable.
* @see https://github.com/phadej/igbinary
* @see https://github.com/nicolasff/phpredis
* @default 0
* @version 3
*/
define('NN_CACHE_SERIALIZER', 0);
/**
* Amount of time in seconds to expire data from the cache server.
* The developers of NN decide what should be set as short/medium/long, depending on the type of data.
* The developers of nZEDb decide what should be set as short/medium/long, depending on the type of data.
*
* @defaults 300/600/900
*/
@@ -277,10 +287,10 @@ define('NN_LOGGING_MAX_LOGS', 20);
define('NN_LOGGING_MAX_SIZE', 30);
/**
* The folder to put the log files in. Put quotes, example : '/var/log/NN/'
* The default is in the NN root folder /resources/logs/
* The folder to put the log files in. Put quotes, example : '/var/log/newznab/'
* The default is in the nZEDb root folder /resources/logs/
*
* @example '/var/log/NN/'
* @example '/var/log/newznab/'
* @default NN_LOGS
*/
define('NN_LOGGING_LOG_FOLDER', NN_LOGS);
@@ -390,6 +400,30 @@ define('NN_QUERY_STRIP_WHITESPACE', false);
*/
define('NN_USE_SQL_TRANSACTIONS', true);
/**
* Allows the use of LOW_PRIORITY in certain DELETE queries.
* This prevents table locks by deleting only when no SELECT queries are active on the table.
* This works on MyISAM/ARIA, not INNODB.
*
* @note Does not cause any errors or warnings if enabled on INNODB.
* @link https://dev.mysql.com/doc/refman/5.7/en/delete.html
* @default false
* @version 1
*/
define('NN_SQL_DELETE_LOW_PRIORITY', false);
/**
* Allows the use QUICK in certain DELETE queries.
* This makes DELETE queries faster on MyISAM/ARIA tables by not merging index leaves.
* Only supported on MyISAM/ARIA
*
* @note Does not cause any errors or warnings if enabled on INNODB.
* @link https://dev.mysql.com/doc/refman/5.7/en/delete.html
* @default false
* @version 1
*/
define('NN_SQL_DELETE_QUICK', false);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////// PHPMailer Settings //////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -399,18 +433,9 @@ define('NN_USE_SQL_TRANSACTIONS', true);
*/
//define('PHPMAILER_ENABLED', true);
/**
* Should we use a SMTP server to send mail?
* If false, it will use your default settings from php.ini.
*
* @note If set to true, be sure to set the server settings below.
* @default false
*/
define('PHPMAILER_USE_SMTP', false);
/**
* Global "From" Address.
* This address will be set as the From: address on every email sent by newznab.
* This address will be set as the From: address on every email sent by nZEDb.
*
* @example 'noreply@example.com'
* @note Depending on server configurations, it may not respect this value.
@@ -430,7 +455,7 @@ define('PHPMAILER_FROM_NAME', '');
/**
* Global "Reply-to" Address.
* This address will be set as the Reply-to: address on every email sent by newznab.
* This address will be set as the Reply-to: address on every email sent by nZEDb.
*
* @example 'support@example.com'
* @note It's a good idea to set this to your support email account (if possible)
@@ -447,6 +472,14 @@ define('PHPMAILER_REPLYTO', '');
*/
define('PHPMAILER_BCC', '');
/**
* Should we use a SMTP server to send mail?
* If false, it will use your default settings from php.ini.
*
* @note If set to true, be sure to set the server settings below.
* @default false
*/
define('PHPMAILER_USE_SMTP', false);
/*********************************************************************************
@@ -511,8 +544,12 @@ define('PHPMAILER_SMTP_PASSWORD', '');
//////////////////////////////////////////////// Change log ////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2015-05-05 v1 Track settings.php.example changes.
2015-06-11 v3 Add support for APC or APCu extensions for caching data. Search for @version 3 for the changes.
2015-05-10 v2 Update path to find_password_hash_cost.php in comments. Search for @version 2 for the changes.
2015-05-03 v1 Track settings.php.example changes.
Add support for quick and low_priority on MySQL DELETE queries.
Search for @version 1 in this file to quickly find these additions.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/