コード例 #1
0
 /**
  * @param string $realServer
  * @return bool|mysqli
  * @throws DBConnectionError
  */
 protected function mysqlConnect($realServer)
 {
     global $wgDBmysql5;
     # Fail now
     # Otherwise we get a suppressed fatal error, which is very hard to track down
     if (!function_exists('mysqli_init')) {
         throw new DBConnectionError($this, "MySQLi functions missing," . " have you compiled PHP with the --with-mysqli option?\n");
     }
     // Other than mysql_connect, mysqli_real_connect expects an explicit port
     // and socket parameters. So we need to parse the port and socket out of
     // $realServer
     $port = null;
     $socket = null;
     $hostAndPort = IP::splitHostAndPort($realServer);
     if ($hostAndPort) {
         $realServer = $hostAndPort[0];
         if ($hostAndPort[1]) {
             $port = $hostAndPort[1];
         }
     } elseif (substr_count($realServer, ':') == 1) {
         // If we have a colon and something that's not a port number
         // inside the hostname, assume it's the socket location
         $hostAndSocket = explode(':', $realServer);
         $realServer = $hostAndSocket[0];
         $socket = $hostAndSocket[1];
     }
     $connFlags = 0;
     if ($this->mFlags & DBO_SSL) {
         $connFlags |= MYSQLI_CLIENT_SSL;
     }
     if ($this->mFlags & DBO_COMPRESS) {
         $connFlags |= MYSQLI_CLIENT_COMPRESS;
     }
     if ($this->mFlags & DBO_PERSISTENT) {
         $realServer = 'p:' . $realServer;
     }
     $mysqli = mysqli_init();
     if ($wgDBmysql5) {
         // Tell the server we're communicating with it in UTF-8.
         // This may engage various charset conversions.
         $mysqli->options(MYSQLI_SET_CHARSET_NAME, 'utf8');
     } else {
         $mysqli->options(MYSQLI_SET_CHARSET_NAME, 'binary');
     }
     $numAttempts = 2;
     for ($i = 0; $i < $numAttempts; $i++) {
         if ($i > 1) {
             usleep(1000);
         }
         if ($mysqli->real_connect($realServer, $this->mUser, $this->mPassword, $this->mDBname, $port, $socket, $connFlags)) {
             return $mysqli;
         }
     }
     return false;
 }
コード例 #2
0
ファイル: DatabaseMysqli.php プロジェクト: paladox/mediawiki
 /**
  * @param string $realServer
  * @return bool|mysqli
  * @throws DBConnectionError
  */
 protected function mysqlConnect($realServer)
 {
     # Avoid suppressed fatal error, which is very hard to track down
     if (!function_exists('mysqli_init')) {
         throw new DBConnectionError($this, "MySQLi functions missing," . " have you compiled PHP with the --with-mysqli option?\n");
     }
     // Other than mysql_connect, mysqli_real_connect expects an explicit port
     // and socket parameters. So we need to parse the port and socket out of
     // $realServer
     $port = null;
     $socket = null;
     $hostAndPort = IP::splitHostAndPort($realServer);
     if ($hostAndPort) {
         $realServer = $hostAndPort[0];
         if ($hostAndPort[1]) {
             $port = $hostAndPort[1];
         }
     } elseif (substr_count($realServer, ':') == 1) {
         // If we have a colon and something that's not a port number
         // inside the hostname, assume it's the socket location
         $hostAndSocket = explode(':', $realServer);
         $realServer = $hostAndSocket[0];
         $socket = $hostAndSocket[1];
     }
     $mysqli = mysqli_init();
     $connFlags = 0;
     if ($this->mFlags & self::DBO_SSL) {
         $connFlags |= MYSQLI_CLIENT_SSL;
         $mysqli->ssl_set($this->sslKeyPath, $this->sslCertPath, null, $this->sslCAPath, $this->sslCiphers);
     }
     if ($this->mFlags & self::DBO_COMPRESS) {
         $connFlags |= MYSQLI_CLIENT_COMPRESS;
     }
     if ($this->mFlags & self::DBO_PERSISTENT) {
         $realServer = 'p:' . $realServer;
     }
     if ($this->utf8Mode) {
         // Tell the server we're communicating with it in UTF-8.
         // This may engage various charset conversions.
         $mysqli->options(MYSQLI_SET_CHARSET_NAME, 'utf8');
     } else {
         $mysqli->options(MYSQLI_SET_CHARSET_NAME, 'binary');
     }
     $mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 3);
     if ($mysqli->real_connect($realServer, $this->mUser, $this->mPassword, $this->mDBname, $port, $socket, $connFlags)) {
         return $mysqli;
     }
     return false;
 }
コード例 #3
0
	protected function mysqlConnect( $realServer ) {
		# Fail now
		# Otherwise we get a suppressed fatal error, which is very hard to track down
		if ( !function_exists( 'mysqli_init' ) ) {
			throw new DBConnectionError( $this, "MySQLi functions missing,"
				. " have you compiled PHP with the --with-mysqli option?\n" );
		}

		// Other than mysql_connect, mysqli_real_connect expects an explicit port
		// parameter. So we need to parse the port out of $realServer
		$port = null;
		$hostAndPort = IP::splitHostAndPort( $realServer );
		if ( $hostAndPort ) {
			$realServer = $hostAndPort[0];
			if ( $hostAndPort[1] ) {
				$port = $hostAndPort[1];
			}
		}

		$connFlags = 0;
		if ( $this->mFlags & DBO_SSL ) {
			$connFlags |= MYSQLI_CLIENT_SSL;
		}
		if ( $this->mFlags & DBO_COMPRESS ) {
			$connFlags |= MYSQLI_CLIENT_COMPRESS;
		}
		if ( $this->mFlags & DBO_PERSISTENT ) {
			$realServer = 'p:' . $realServer;
		}

		$mysqli = mysqli_init();
		$numAttempts = 2;

		for ( $i = 0; $i < $numAttempts; $i++ ) {
			if ( $i > 1 ) {
				usleep( 1000 );
			}
			if ( $mysqli->real_connect( $realServer, $this->mUser,
				$this->mPassword, $this->mDBname, $port, null, $connFlags ) )
			{
				return $mysqli;
			}
		}

		return false;
	}
コード例 #4
0
ファイル: WebRequest.php プロジェクト: mangowi/mediawiki
 /**
  * Work out an appropriate URL prefix containing scheme and host, based on
  * information detected from $_SERVER
  *
  * @return string
  */
 public static function detectServer()
 {
     list($proto, $stdPort) = self::detectProtocolAndStdPort();
     $varNames = array('HTTP_HOST', 'SERVER_NAME', 'HOSTNAME', 'SERVER_ADDR');
     $host = 'localhost';
     $port = $stdPort;
     foreach ($varNames as $varName) {
         if (!isset($_SERVER[$varName])) {
             continue;
         }
         $parts = IP::splitHostAndPort($_SERVER[$varName]);
         if (!$parts) {
             // Invalid, do not use
             continue;
         }
         $host = $parts[0];
         if ($parts[1] === false) {
             if (isset($_SERVER['SERVER_PORT'])) {
                 $port = $_SERVER['SERVER_PORT'];
             }
             // else leave it as $stdPort
         } else {
             $port = $parts[1];
         }
         break;
     }
     return $proto . '://' . IP::combineHostAndPort($host, $port, $stdPort);
 }
コード例 #5
0
ファイル: IPTest.php プロジェクト: Tjorriemorrie/app
 /**
  * Test for IP::splitHostAndPort().
  * @dataProvider provideSplitHostAndPort
  */
 function testSplitHostAndPort($expected, $input, $description)
 {
     $this->assertEquals($expected, IP::splitHostAndPort($input), $description);
 }
コード例 #6
0
 /**
  * Get a connection to a redis server. Based on code in RedisBagOStuff.php.
  *
  * @param string $server A hostname/port combination or the absolute path of a UNIX socket.
  *                       If a hostname is specified but no port, port 6379 will be used.
  * @return RedisConnRef|bool Returns false on failure
  * @throws MWException
  */
 public function getConnection($server)
 {
     // Check the listing "dead" servers which have had a connection errors.
     // Servers are marked dead for a limited period of time, to
     // avoid excessive overhead from repeated connection timeouts.
     if (isset($this->downServers[$server])) {
         $now = time();
         if ($now > $this->downServers[$server]) {
             // Dead time expired
             unset($this->downServers[$server]);
         } else {
             // Server is dead
             $this->logger->debug('Server "{redis_server}" is marked down for another ' . ($this->downServers[$server] - $now) . 'seconds', array('redis_server' => $server));
             return false;
         }
     }
     // Check if a connection is already free for use
     if (isset($this->connections[$server])) {
         foreach ($this->connections[$server] as &$connection) {
             if ($connection['free']) {
                 $connection['free'] = false;
                 --$this->idlePoolSize;
                 return new RedisConnRef($this, $server, $connection['conn'], $this->logger);
             }
         }
     }
     if (substr($server, 0, 1) === '/') {
         // UNIX domain socket
         // These are required by the redis extension to start with a slash, but
         // we still need to set the port to a special value to make it work.
         $host = $server;
         $port = 0;
     } else {
         // TCP connection
         $hostPort = IP::splitHostAndPort($server);
         if (!$server || !$hostPort) {
             throw new MWException(__CLASS__ . ": invalid configured server \"{$server}\"");
         }
         list($host, $port) = $hostPort;
         if ($port === false) {
             $port = 6379;
         }
     }
     $conn = new Redis();
     try {
         if ($this->persistent) {
             $result = $conn->pconnect($host, $port, $this->connectTimeout);
         } else {
             $result = $conn->connect($host, $port, $this->connectTimeout);
         }
         if (!$result) {
             $this->logger->error('Could not connect to server "{redis_server}"', array('redis_server' => $server));
             // Mark server down for some time to avoid further timeouts
             $this->downServers[$server] = time() + self::SERVER_DOWN_TTL;
             return false;
         }
         if ($this->password !== null) {
             if (!$conn->auth($this->password)) {
                 $this->logger->error('Authentication error connecting to "{redis_server}"', array('redis_server' => $server));
             }
         }
     } catch (RedisException $e) {
         $this->downServers[$server] = time() + self::SERVER_DOWN_TTL;
         $this->logger->error('Redis exception connecting to "{redis_server}"', array('redis_server' => $server, 'exception' => $e));
         return false;
     }
     if ($conn) {
         $conn->setOption(Redis::OPT_READ_TIMEOUT, $this->readTimeout);
         $conn->setOption(Redis::OPT_SERIALIZER, $this->serializer);
         $this->connections[$server][] = array('conn' => $conn, 'free' => false);
         return new RedisConnRef($this, $server, $conn, $this->logger);
     } else {
         return false;
     }
 }
コード例 #7
0
ファイル: WebRequest.php プロジェクト: xfstudio/mediawiki
 /**
  * Work out an appropriate URL prefix containing scheme and host, based on
  * information detected from $_SERVER
  *
  * @return string
  */
 public static function detectServer()
 {
     global $wgAssumeProxiesUseDefaultProtocolPorts;
     $proto = self::detectProtocol();
     $stdPort = $proto === 'https' ? 443 : 80;
     $varNames = array('HTTP_HOST', 'SERVER_NAME', 'HOSTNAME', 'SERVER_ADDR');
     $host = 'localhost';
     $port = $stdPort;
     foreach ($varNames as $varName) {
         if (!isset($_SERVER[$varName])) {
             continue;
         }
         $parts = IP::splitHostAndPort($_SERVER[$varName]);
         if (!$parts) {
             // Invalid, do not use
             continue;
         }
         $host = $parts[0];
         if ($wgAssumeProxiesUseDefaultProtocolPorts && isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
             // Bug 70021: Assume that upstream proxy is running on the default
             // port based on the protocol. We have no reliable way to determine
             // the actual port in use upstream.
             $port = $stdPort;
         } elseif ($parts[1] === false) {
             if (isset($_SERVER['SERVER_PORT'])) {
                 $port = $_SERVER['SERVER_PORT'];
             }
             // else leave it as $stdPort
         } else {
             $port = $parts[1];
         }
         break;
     }
     return $proto . '://' . IP::combineHostAndPort($host, $port, $stdPort);
 }
コード例 #8
0
 /**
  * Get a connection to the server with the specified name. Connections
  * are cached, and failures are persistent to avoid multiple timeouts.
  *
  * @param $server
  * @throws MWException
  * @return Redis object, or false on failure
  */
 protected function getConnectionToServer($server)
 {
     if (isset($this->deadServers[$server])) {
         $now = time();
         if ($now > $this->deadServers[$server]) {
             // Dead time expired
             unset($this->deadServers[$server]);
         } else {
             // Server is dead
             $this->debug("server {$server} is marked down for another " . ($this->deadServers[$server] - $now) . " seconds, can't get connection");
             return false;
         }
     }
     if (isset($this->conns[$server])) {
         return $this->conns[$server];
     }
     if (substr($server, 0, 1) === '/') {
         // UNIX domain socket
         // These are required by the redis extension to start with a slash, but
         // we still need to set the port to a special value to make it work.
         $host = $server;
         $port = 0;
     } else {
         // TCP connection
         $hostPort = IP::splitHostAndPort($server);
         if (!$hostPort) {
             throw new MWException(__CLASS__ . ": invalid configured server \"{$server}\"");
         }
         list($host, $port) = $hostPort;
         if ($port === false) {
             $port = 6379;
         }
     }
     $conn = new Redis();
     try {
         if ($this->persistent) {
             $this->debug("opening persistent connection to {$host}:{$port}");
             $result = $conn->pconnect($host, $port, $this->connectTimeout);
         } else {
             $this->debug("opening non-persistent connection to {$host}:{$port}");
             $result = $conn->connect($host, $port, $this->connectTimeout);
         }
         if (!$result) {
             $this->logError("could not connect to server {$server}");
             // Mark server down for 30s to avoid further timeouts
             $this->deadServers[$server] = time() + 30;
             return false;
         }
         if ($this->password !== null) {
             if (!$conn->auth($this->password)) {
                 $this->logError("authentication error connecting to {$server}");
             }
         }
     } catch (RedisException $e) {
         $this->deadServers[$server] = time() + 30;
         wfDebugLog('redis', "Redis exception: " . $e->getMessage() . "\n");
         return false;
     }
     $conn->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP);
     $this->conns[$server] = $conn;
     return $conn;
 }
コード例 #9
0
 /**
  * Constructor
  *
  * Available parameters are:
  *   - servers:             The list of IP:port combinations holding the memcached servers.
  *   - persistent:          Whether to use a persistent connection
  *   - compress_threshold:  The minimum size an object must be before it is compressed
  *   - timeout:             The read timeout in microseconds
  *   - connect_timeout:     The connect timeout in seconds
  *   - retry_timeout:       Time in seconds to wait before retrying a failed connect attempt
  *   - server_failure_limit:  Limit for server connect failures before it is removed
  *   - serializer:          May be either "php" or "igbinary". Igbinary produces more compact
  *                          values, but serialization is much slower unless the php.ini option
  *                          igbinary.compact_strings is off.
  * @param array $params
  * @throws MWException
  */
 function __construct($params)
 {
     parent::__construct($params);
     $params = $this->applyDefaultParams($params);
     if ($params['persistent']) {
         // The pool ID must be unique to the server/option combination.
         // The Memcached object is essentially shared for each pool ID.
         // We can only reuse a pool ID if we keep the config consistent.
         $this->client = new Memcached(md5(serialize($params)));
         if (count($this->client->getServerList())) {
             $this->logger->debug(__METHOD__ . ": persistent Memcached object already loaded.");
             return;
             // already initialized; don't add duplicate servers
         }
     } else {
         $this->client = new Memcached();
     }
     if (!isset($params['serializer'])) {
         $params['serializer'] = 'php';
     }
     if (isset($params['retry_timeout'])) {
         $this->client->setOption(Memcached::OPT_RETRY_TIMEOUT, $params['retry_timeout']);
     }
     if (isset($params['server_failure_limit'])) {
         $this->client->setOption(Memcached::OPT_SERVER_FAILURE_LIMIT, $params['server_failure_limit']);
     }
     // The compression threshold is an undocumented php.ini option for some
     // reason. There's probably not much harm in setting it globally, for
     // compatibility with the settings for the PHP client.
     ini_set('memcached.compression_threshold', $params['compress_threshold']);
     // Set timeouts
     $this->client->setOption(Memcached::OPT_CONNECT_TIMEOUT, $params['connect_timeout'] * 1000);
     $this->client->setOption(Memcached::OPT_SEND_TIMEOUT, $params['timeout']);
     $this->client->setOption(Memcached::OPT_RECV_TIMEOUT, $params['timeout']);
     $this->client->setOption(Memcached::OPT_POLL_TIMEOUT, $params['timeout'] / 1000);
     // Set libketama mode since it's recommended by the documentation and
     // is as good as any. There's no way to configure libmemcached to use
     // hashes identical to the ones currently in use by the PHP client, and
     // even implementing one of the libmemcached hashes in pure PHP for
     // forwards compatibility would require MWMemcached::get_sock() to be
     // rewritten.
     $this->client->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true);
     // Set the serializer
     switch ($params['serializer']) {
         case 'php':
             $this->client->setOption(Memcached::OPT_SERIALIZER, Memcached::SERIALIZER_PHP);
             break;
         case 'igbinary':
             if (!Memcached::HAVE_IGBINARY) {
                 throw new MWException(__CLASS__ . ': the igbinary extension is not available ' . 'but igbinary serialization was requested.');
             }
             $this->client->setOption(Memcached::OPT_SERIALIZER, Memcached::SERIALIZER_IGBINARY);
             break;
         default:
             throw new MWException(__CLASS__ . ': invalid value for serializer parameter');
     }
     $servers = array();
     foreach ($params['servers'] as $host) {
         $servers[] = IP::splitHostAndPort($host);
         // (ip, port)
     }
     $this->client->addServers($servers);
 }
コード例 #10
0
	/**
	 *
	 */
	protected function streamThumbnail() {
		global $wgVipsThumbnailerHost, $wgVipsTestExpiry;

		$request = $this->getRequest();

		# Validate title and file existance
		$title = Title::makeTitleSafe( NS_FILE, $request->getText( 'thumb' ) );
		if ( is_null( $title ) ) {
			$this->streamError( 404, "VipsScaler: invalid title\n" );
			return;
		}
		$file = wfFindFile( $title );
		if ( !$file || !$file->exists() ) {
			$this->streamError( 404, "VipsScaler: file not found\n" );
			return;
		}

		# Check if vips can handle this file
		if ( VipsScaler::getVipsHandler( $file ) === false ) {
			$this->streamError( 500, "VipsScaler: VIPS cannot handle this file type\n" );
			return;
		}

		# Validate param string
		$handler = $file->getHandler();
		$params = array( 'width' => $request->getInt( 'width' ) );
		if ( !$handler->normaliseParams( $file, $params ) ) {
			$this->streamError( 500, "VipsScaler: invalid parameters\n" );
			return;
		}

		# Get the thumbnail
		if ( is_null( $wgVipsThumbnailerHost ) || $request->getBool( 'noproxy' ) ) {
			# No remote scaler, need to do it ourselves.
			# Emulate the BitmapHandlerTransform hook

			$dstPath = VipsCommand::makeTemp( $file->getExtension() );
			$dstUrl = '';
			wfDebug( __METHOD__ . ": Creating vips thumbnail at $dstPath\n" );

			$scalerParams = array(
				# The size to which the image will be resized
				'physicalWidth' => $params['physicalWidth'],
				'physicalHeight' => $params['physicalHeight'],
				'physicalDimensions' => "{$params['physicalWidth']}x{$params['physicalHeight']}",
				# The size of the image on the page
				'clientWidth' => $params['width'],
				'clientHeight' => $params['height'],
				# Comment as will be added to the EXIF of the thumbnail
				'comment' => isset( $params['descriptionUrl'] ) ?
					"File source: {$params['descriptionUrl']}" : '',
				# Properties of the original image
				'srcWidth' => $file->getWidth(),
				'srcHeight' => $file->getHeight(),
				'mimeType' => $file->getMimeType(),
				'srcPath' => $file->getPath(),
				'dstPath' => $dstPath,
				'dstUrl' => $dstUrl,
			);

			$options = array();
			if ( $request->getBool( 'bilinear' ) ) {
				$options['bilinear'] = true;
				wfDebug( __METHOD__ . ": using bilinear scaling\n" );
			}
			if ( $request->getVal( 'sharpen' ) && $request->getVal( 'sharpen' ) < 5 ) {
				# Limit sharpen sigma to 5, otherwise we have to write huge convolution matrices
				$options['sharpen'] = array( 'sigma' => floatval( $request->getVal( 'sharpen' ) ) );
				wfDebug( __METHOD__ . ": sharpening with radius {$options['sharpen']}\n" );
			}

			# Call the hook
			$mto = null;
			VipsScaler::doTransform( $handler, $file, $scalerParams, $options, $mto );
			if ( $mto && !$mto->isError() ) {
				wfDebug( __METHOD__ . ": streaming thumbnail...\n" );
				$this->getOutput()->disable();
				StreamFile::stream( $dstPath, array(
					"Cache-Control: public, max-age=$wgVipsTestExpiry, s-maxage=$wgVipsTestExpiry",
					'Expires: ' . gmdate( 'r ', time() + $wgVipsTestExpiry )
				) );
			} else {
				$this->streamError( 500, $mto->getHtmlMsg() );
			}

			# Cleanup the temporary file
			wfSuppressWarnings();
			unlink( $dstPath );
			wfRestoreWarnings();

		} else {
			# Request the thumbnail at a remote scaler
			$url = wfExpandUrl( $request->getRequestURL(), PROTO_INTERNAL );
			$url = wfAppendQuery( $url, array( 'noproxy' => '1' ) );
			wfDebug( __METHOD__ . ": Getting vips thumb from remote url $url\n" );

			$bits = IP::splitHostAndPort( $wgVipsThumbnailerHost );
			if ( !$bits ) {
				throw new MWException( __METHOD__.': $wgVipsThumbnailerHost is not set to a valid host' );
			}
			list( $host, $port ) = $bits;
			if ( $port === false ) {
				$port = 80;
			}
			$proxy = IP::combineHostAndPort( $host, $port );

			$options = array(
				'method' => 'GET',
				'proxy' => $proxy,
			);

			$req = MWHttpRequest::factory( $url, $options );
			$status = $req->execute();
			if ( $status->isOk() ) {
				# Disable output and stream the file
				$this->getOutput()->disable();
				wfResetOutputBuffers();
				header( 'Content-Type: ' . $file->getMimeType() );
				header( 'Content-Length: ' . strlen( $req->getContent() ) );
				header( "Cache-Control: public, max-age=$wgVipsTestExpiry, s-maxage=$wgVipsTestExpiry" );
				header( 'Expires: ' . gmdate( 'r ', time() + $wgVipsTestExpiry ) );
				print $req->getContent();
			} elseif ( $status->hasMessage( 'http-bad-status' ) ) {
				$this->streamError( 500, $req->getContent() );
				return;
			} else {
				global $wgOut;
				$this->streamError( 500, $wgOut->parse( $status->getWikiText() ) );
				return;
			}
		}
	}