* @param string $caller The method making this request, for profiling
* @param Profiler $profiler An instance of the profiler for profiling, or null
*/
- protected function __construct( $url, $options = array(), $caller = __METHOD__, $profiler = null ) {
+ protected function __construct(
+ $url, $options = array(), $caller = __METHOD__, $profiler = null
+ ) {
global $wgHTTPTimeout, $wgHTTPConnectTimeout;
$this->url = wfExpandUrl( $url, PROTO_HTTP );
public function getFinalUrl() {
$headers = $this->getResponseHeaders();
- //return full url (fix for incorrect but handled relative location)
+ // return full url (fix for incorrect but handled relative location)
if ( isset( $headers['location'] ) ) {
$locations = $headers['location'];
$domain = '';
if ( isset( $url['host'] ) ) {
$domain = $url['scheme'] . '://' . $url['host'];
- break; //found correct URI (with host)
+ break; // found correct URI (with host)
} else {
$foundRelativeURI = true;
}
* @return bool
*/
public function canFollowRedirects() {
- if ( strval( ini_get( 'open_basedir' ) ) !== '' || wfIniGetBool( 'safe_mode' ) ) {
- wfDebug( "Cannot follow redirects in safe mode\n" );
- return false;
- }
-
$curlVersionInfo = curl_version();
if ( $curlVersionInfo['version_number'] < 0x071304 ) {
wfDebug( "Cannot follow redirects with libcurl < 7.19.4 due to CVE-2009-0037\n" );
return false;
}
+ if ( version_compare( PHP_VERSION, '5.6.0', '<' ) ) {
+ if ( strval( ini_get( 'open_basedir' ) ) !== '' || wfIniGetBool( 'safe_mode' ) ) {
+ wfDebug( "Cannot follow redirects in safe mode\n" );
+ return false;
+ }
+ }
+
return true;
}
}
class PhpHttpRequest extends MWHttpRequest {
+ private $fopenErrors = array();
+
/**
* @param string $url
* @return string
}
/**
- * Returns an array with a 'capath' or 'cafile' key that is suitable to be merged into the 'ssl' sub-array of a
- * stream context options array. Uses the 'caInfo' option of the class if it is provided, otherwise uses the system
+ * Returns an array with a 'capath' or 'cafile' key
+ * that is suitable to be merged into the 'ssl' sub-array of
+ * a stream context options array.
+ * Uses the 'caInfo' option of the class if it is provided, otherwise uses the system
* default CA bundle if PHP supports that, or searches a few standard locations.
* @return array
* @throws DomainException
if ( $this->caInfo ) {
$certLocations = array( 'manual' => $this->caInfo );
} elseif ( version_compare( PHP_VERSION, '5.6.0', '<' ) ) {
+ // @codingStandardsIgnoreStart Generic.Files.LineLength
// Default locations, based on
// https://www.happyassassin.net/2015/01/12/a-note-about-ssltls-trusted-certificate-stores-and-platforms/
- // PHP 5.5 and older doesn't have any defaults, so we try to guess ourselves. PHP 5.6+ gets the CA location
- // from OpenSSL as long as it is not set manually, so we should leave capath/cafile empty there.
+ // PHP 5.5 and older doesn't have any defaults, so we try to guess ourselves.
+ // PHP 5.6+ gets the CA location from OpenSSL as long as it is not set manually,
+ // so we should leave capath/cafile empty there.
+ // @codingStandardsIgnoreEnd
$certLocations = array_filter( array(
getenv( 'SSL_CERT_DIR' ),
getenv( 'SSL_CERT_PATH' ),
) );
}
- foreach( $certLocations as $key => $cert ) {
+ foreach ( $certLocations as $key => $cert ) {
if ( is_dir( $cert ) ) {
$certOptions['capath'] = $cert;
break;
return $certOptions;
}
+ /**
+ * Custom error handler for dealing with fopen() errors.
+ * fopen() tends to fire multiple errors in succession, and the last one
+ * is completely useless (something like "fopen: failed to open stream")
+ * so normal methods of handling errors programmatically
+ * like get_last_error() don't work.
+ */
+ public function errorHandler( $errno, $errstr ) {
+ $n = count( $this->fopenErrors ) + 1;
+ $this->fopenErrors += array( "errno$n" => $errno, "errstr$n" => $errstr );
+ }
+
public function execute() {
parent::execute();
'ssl' => array(
'verify_peer' => $this->sslVerifyCert,
'SNI_enabled' => true,
+ 'ciphers' => 'HIGH:!SSLv2:!SSLv3:-ADH:-kDH:-kECDH:-DSS',
+ 'disable_compression' => true,
),
);
}
do {
$reqCount++;
- MediaWiki\suppressWarnings();
+ $this->fopenErrors = array();
+ set_error_handler( array( $this, 'errorHandler' ) );
$fh = fopen( $url, "r", false, $context );
- MediaWiki\restoreWarnings();
+ restore_error_handler();
if ( !$fh ) {
// HACK for instant commons.
$this->setStatus();
if ( $fh === false ) {
+ if ( $this->fopenErrors ) {
+ LoggerFactory::getInstance( 'http' )->warning( __CLASS__
+ . ': error opening connection: {errstr1}', $this->fopenErrors );
+ }
$this->status->fatal( 'http-request-error' );
return $this->status;
}