⚝
One Hat Cyber Team
⚝
Your IP:
216.73.216.72
Server IP:
41.128.143.86
Server:
Linux host.raqmix.cloud 6.8.0-1025-azure #30~22.04.1-Ubuntu SMP Wed Mar 12 15:28:20 UTC 2025 x86_64
Server Software:
Apache
PHP Version:
8.3.23
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
usr
/
share
/
psa-pear
/
pear
/
php
/
Horde
/
Edit File: Memcache.php
<?php /** * Copyright 2007-2016 Horde LLC (http://www.horde.org/) * * See the enclosed file COPYING for license information (LGPL). If you * did not receive this file, see http://www.horde.org/licenses/lgpl21. * * @author Jan Schneider <jan@horde.org> * @author Michael Slusarz <slusarz@horde.org> * @author Didi Rieder <adrieder@sbox.tugraz.at> * @category Horde * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 * @package Memcache */ /** * This class provides an API or Horde code to interact with a centrally * configured memcache installation. * * memcached website: http://www.danga.com/memcached/ * * @author Jan Schneider <jan@horde.org> * @author Michael Slusarz <slusarz@horde.org> * @author Didi Rieder <adrieder@sbox.tugraz.at> * @category Horde * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 * @package Memcache */ class Horde_Memcache implements Serializable { /** * The number of bits reserved by PHP's memcache layer for internal flag * use. */ const FLAGS_RESERVED = 16; /** * Locking timeout. */ const LOCK_TIMEOUT = 30; /** * Suffix added to key to create the lock entry. */ const LOCK_SUFFIX = '_l'; /** * The max storage size of the memcache server. This should be slightly * smaller than the actual value due to overhead. By default, the max * slab size of memcached (as of 1.1.2) is 1 MB. */ const MAX_SIZE = 1000000; /** * Serializable version. */ const VERSION = 1; /** * Locked keys. * * @var array */ protected $_locks = array(); /** * Logger instance. * * @var Horde_Log_Logger */ protected $_logger; /** * Memcache object. * * @var Memcache */ protected $_memcache; /** * A list of items known not to exist. * * @var array */ protected $_noexist = array(); /** * Memcache defaults. * * @var array */ protected $_params = array( 'compression' => false, 'hostspec' => array('localhost'), 'large_items' => true, 'persistent' => false, 'port' => array(11211), 'prefix' => 'horde' ); /** * The list of active servers. * * @var array */ protected $_servers = array(); /** * Constructor. * * @param array $params Configuration parameters: * - compression: (boolean) Compress data inside memcache? * DEFAULT: false * - c_threshold: (integer) The minimum value length before attempting * to compress. * DEFAULT: none * - hostspec: (array) The memcached host(s) to connect to. * DEFAULT: 'localhost' * - large_items: (boolean) Allow storing large data items (larger than * Horde_Memcache::MAX_SIZE)? Currently not supported with * memcached extension. * DEFAULT: true * - persistent: (boolean) Use persistent DB connections? * DEFAULT: false * - prefix: (string) The prefix to use for the memcache keys. * DEFAULT: 'horde' * - port: (array) The port(s) memcache is listening on. Leave empty * if using UNIX sockets. * DEFAULT: 11211 * - weight: (array) The weight(s) to use for each memcached host. * DEFAULT: none (equal weight to all servers) * * @throws Horde_Memcache_Exception */ public function __construct(array $params = array()) { $this->_params = array_merge($this->_params, $params); $this->_init(); } /** * Do initialization. * * @throws Horde_Memcache_Exception */ public function _init() { if (class_exists('Memcached')) { if (empty($this->_params['persistent'])) { $this->_memcache = new Memcached(); } else { $this->_memcache = new Memcached('horde_memcache'); } $this->_params['large_items'] = false; $this->_memcache->setOptions(array( Memcached::OPT_COMPRESSION => $this->_params['compression'], Memcached::OPT_DISTRIBUTION => Memcached::DISTRIBUTION_CONSISTENT, Memcached::OPT_HASH => Memcached::HASH_MD5, Memcached::OPT_LIBKETAMA_COMPATIBLE => true, Memcached::OPT_PREFIX_KEY => $this->_params['prefix'], )); } else { // Force consistent hashing ini_set('memcache.hash_strategy', 'consistent'); $this->_memcache = new Memcache(); } for ($i = 0, $n = count($this->_params['hostspec']); $i < $n; ++$i) { if ($this->_memcache instanceof Memcached) { $res = $this->_memcache->addServer( $this->_params['hostspec'][$i], empty($this->_params['port'][$i]) ? 0 : $this->_params['port'][$i], !empty($this->_params['weight'][$i]) ? $this->_params['weight'][$i] : 0 ); } else { $res = $this->_memcache->addServer( $this->_params['hostspec'][$i], empty($this->_params['port'][$i]) ? 0 : $this->_params['port'][$i], !empty($this->_params['persistent']), !empty($this->_params['weight'][$i]) ? $this->_params['weight'][$i] : 1, 1, 15, true, array($this, 'failover') ); } if ($res) { $this->_servers[] = $this->_params['hostspec'][$i] . (!empty($this->_params['port'][$i]) ? ':' . $this->_params['port'][$i] : ''); } } /* Check if any of the connections worked. */ if (empty($this->_servers)) { throw new Horde_Memcache_Exception('Could not connect to any defined memcache servers.'); } if ($this->_memcache instanceof Memcache && !empty($this->_params['c_threshold'])) { $this->_memcache->setCompressThreshold($this->_params['c_threshold']); } if (isset($this->_params['logger'])) { $this->_logger = $this->_params['logger']; $this->_logger->log('Connected to the following memcache servers:' . implode($this->_servers, ', '), 'DEBUG'); } } /** * Shutdown function. */ public function shutdown() { foreach (array_keys($this->_locks) as $key) { $this->unlock($key); } } /** * Delete a key. * * @see Memcache::delete() * * @param string $key The key. * @param integer $timeout Expiration time in seconds. * * @return boolean True on success. */ public function delete($key, $timeout = 0) { return isset($this->_noexist[$key]) ? false : $this->_memcache->delete($this->_key($key), $timeout); } /** * Get data associated with a key. * * @see Memcache::get() * * @param mixed $keys The key or an array of keys. * * @return mixed The string/array on success (return type is the type of * $keys), false on failure. */ public function get($keys) { $flags = null; $key_map = $missing_parts = $os = $out_array = array(); $ret_array = true; if (!is_array($keys)) { $keys = array($keys); $ret_array = false; } $search_keys = $keys; foreach ($search_keys as $v) { $key_map[$v] = $this->_key($v); } if ($this->_memcache instanceof Memcached) { $res = $this->_memcache->getMulti(array_values($key_map)); } else { $res = $this->_memcache->get(array_values($key_map), $flags); } if ($res === false) { return false; } /* Check to see if we have any oversize items we need to get. */ if (!empty($this->_params['large_items'])) { foreach ($key_map as $key => $val) { $part_count = isset($flags[$val]) ? ($flags[$val] >> self::FLAGS_RESERVED) - 1 : -1; switch ($part_count) { case -1: /* Ignore. */ unset($res[$val]); break; case 0: /* Not an oversize part. */ break; default: $os[$key] = $this->_getOSKeyArray($key, $part_count); foreach ($os[$key] as $val2) { $missing_parts[] = $key_map[$val2] = $this->_key($val2); } break; } } if (!empty($missing_parts)) { if (($res2 = $this->_memcache->get($missing_parts)) === false) { return false; } /* $res should now contain the same results as if we had * run a single get request with all keys above. */ $res = array_merge($res, $res2); } } foreach ($key_map as $k => $v) { if (!isset($res[$v])) { $this->_noexist[$k] = true; } } foreach ($keys as $k) { $out_array[$k] = false; if (isset($res[$key_map[$k]])) { $data = $res[$key_map[$k]]; if (isset($os[$k])) { foreach ($os[$k] as $v) { if (isset($res[$key_map[$v]])) { $data .= $res[$key_map[$v]]; } else { $this->delete($k); continue 2; } } } $out_array[$k] = @unserialize($data); } elseif (isset($os[$k]) && !isset($res[$key_map[$k]])) { $this->delete($k); } } return $ret_array ? $out_array : reset($out_array); } /** * Set the value of a key. * * @see Memcache::set() * * @param string $key The key. * @param string $var The data to store. * @param integer $timeout Expiration time in seconds. * * @return boolean True on success. */ public function set($key, $var, $expire = 0) { return $this->_set($key, @serialize($var), $expire); } /** * Set the value of a key. * * @param string $key The key. * @param string $var The data to store (serialized). * @param integer $timeout Expiration time in seconds. * @param integer $lent String length of $len. * * @return boolean True on success. */ protected function _set($key, $var, $expire = 0, $len = null) { if (is_null($len)) { $len = strlen($var); } if (empty($this->_params['large_items']) && ($len > self::MAX_SIZE)) { return false; } for ($i = 0; ($i * self::MAX_SIZE) < $len; ++$i) { $curr_key = $i ? ($key . '_s' . $i) : $key; $res = $this->_memcache instanceof Memcached ? $this->_memcache->set($curr_key, $var, $expire) : $this->_memcache->set( $this->_key($curr_key), substr($var, $i * self::MAX_SIZE, self::MAX_SIZE), $this->_getFlags($i ? 0 : ceil($len / self::MAX_SIZE)), $expire ); if ($res === false) { $this->delete($key); break; } unset($this->_noexist[$curr_key]); } return $res; } /** * Replace the value of a key. * * @see Memcache::replace() * * @param string $key The key. * @param string $var The data to store. * @param integer $timeout Expiration time in seconds. * * @return boolean True on success, false if key doesn't exist. */ public function replace($key, $var, $expire = 0) { $var = @serialize($var); $len = strlen($var); if ($len > self::MAX_SIZE) { if (!empty($this->_params['large_items']) && $this->_memcache->get($this->_key($key))) { return $this->_set($key, $var, $expire, $len); } return false; } return $this->_memcache instanceof Memcached ? $this->_memcache->replace($key, $var, $expire) : $this->_memcache->replace( $this->_key($key), $var, $this->_getFlags(1), $expire ); } /** * Obtain lock on a key. * * @param string $key The key to lock. */ public function lock($key) { $i = 0; while ($this->_lockAdd($key) === false) { usleep(min(pow(2, $i++) * 10000, 100000)); } /* Register a shutdown handler function here to catch cases where PHP * suffers a fatal error. Must be done via shutdown function, since * a destructor will not be called in this case. * Only trigger on error, since we must assume that the code that * locked will also handle unlocks (which may occur in the destruct * phase, e.g. session handling). * @todo: $this is not usable in closures until PHP 5.4+ */ if (empty($this->_locks)) { $self = $this; register_shutdown_function(function() use ($self) { $e = error_get_last(); if ($e['type'] & E_ERROR) { /* Try to do cleanup at very end of shutdown methods. */ register_shutdown_function(array($self, 'shutdown')); } }); } $this->_locks[$key] = true; } /** * Small wrapper around Memcache[d]#add(). * * @param string $key The key to lock. */ protected function _lockAdd($key) { if ($this->_memcache instanceof Memcached) { $this->_memcache->add( $this->_key($key . self::LOCK_SUFFIX), 1, self::LOCK_TIMEOUT ); } else { $this->_memcache->add( $this->_key($key . self::LOCK_SUFFIX), 1, 0, self::LOCK_TIMEOUT ); } } /** * Release lock on a key. * * @param string $key The key to lock. */ public function unlock($key) { $this->_memcache->delete($this->_key($key . self::LOCK_SUFFIX), 0); unset($this->_locks[$key]); } /** * Mark all entries on a memcache installation as expired. */ public function flush() { $this->_memcache->flush(); } /** * Get the statistics output from the current memcache pool. * * @return array The output from Memcache::getExtendedStats() using the * current configuration values. */ public function stats() { return $this->_memcache instanceof Memcached ? $this->_memcache->getStats() : $this->_memcache->getExtendedStats(); } /** * Failover method. * * @see Memcache::addServer() * * @param string $host Hostname. * @param integer $port Port. * * @throws Horde_Memcache_Exception */ public function failover($host, $port) { $pos = array_search($host . ':' . $port, $this->_servers); if ($pos !== false) { unset($this->_servers[$pos]); if (!count($this->_servers)) { throw new Horde_Memcache_Exception('Could not connect to any defined memcache servers.'); } } } /** * Obtains the md5 sum for a key. * * @param string $key The key. * * @return string The corresponding memcache key. */ protected function _key($key) { return $this->_memcache instanceof Memcached ? $key : hash('md5', $this->_params['prefix'] . $key); } /** * Returns the key listing of all key IDs for an oversized item. * * @return array The array of key IDs. */ protected function _getOSKeyArray($key, $length) { $ret = array(); for ($i = 0; $i < $length; ++$i) { $ret[] = $key . '_s' . ($i + 1); } return $ret; } /** * Get flags for memcache call. * * @param integer $count * * @return integer */ protected function _getFlags($count) { $flags = empty($this->_params['compression']) ? 0 : MEMCACHE_COMPRESSED; return ($flags | $count << self::FLAGS_RESERVED); } /* Serializable methods. */ /** * Serialize. * * @return string Serialized representation of this object. */ public function serialize() { return serialize(array( self::VERSION, $this->_params )); } /** * Unserialize. * * @param string $data Serialized data. * * @throws Exception * @throws Horde_Memcache_Exception */ public function unserialize($data) { $data = @unserialize($data); if (!is_array($data) || !isset($data[0]) || ($data[0] != self::VERSION)) { throw new Exception('Cache version change'); } $this->_params = $data[1]; $this->_init(); } }
Simpan