Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. CurlDownloader.php

function CurlDownloader::initDownload

Parameters

mixed[] $options:

array{retryAuthFailure?: bool, redirects?: int<0, max>, retries?: int<0, max>, storeAuth?: 'prompt'|bool, ipResolve?: 4|6|null} $attributes:

non-empty-string $url:

Return value

int internal job id

2 calls to CurlDownloader::initDownload()
CurlDownloader::download in vendor/composer/composer/src/Composer/Util/Http/CurlDownloader.php
CurlDownloader::restartJob in vendor/composer/composer/src/Composer/Util/Http/CurlDownloader.php

File

vendor/composer/composer/src/Composer/Util/Http/CurlDownloader.php, line 143

Class

CurlDownloader
@internal @author Jordi Boggiano <j.boggiano@seld.be> @author Nicolas Grekas <p@tchwork.com> @phpstan-type Attributes array{retryAuthFailure: bool, redirects: int<0, max>, retries: int<0, max>, storeAuth:…

Namespace

Composer\Util\Http

Code

private function initDownload(callable $resolve, callable $reject, string $origin, string $url, array $options, ?string $copyTo = null, array $attributes = []) : int {
    $attributes = array_merge([
        'retryAuthFailure' => true,
        'redirects' => 0,
        'retries' => 0,
        'storeAuth' => false,
        'ipResolve' => null,
    ], $attributes);
    if ($attributes['ipResolve'] === null && Platform::getEnv('COMPOSER_IPRESOLVE') === '4') {
        $attributes['ipResolve'] = 4;
    }
    elseif ($attributes['ipResolve'] === null && Platform::getEnv('COMPOSER_IPRESOLVE') === '6') {
        $attributes['ipResolve'] = 6;
    }
    $originalOptions = $options;
    // check URL can be accessed (i.e. is not insecure), but allow insecure Packagist calls to $hashed providers as file integrity is verified with sha256
    if (!Preg::isMatch('{^http://(repo\\.)?packagist\\.org/p/}', $url) || false === strpos($url, '$') && false === strpos($url, '%24')) {
        $this->config
            ->prohibitUrlByConfig($url, $this->io, $options);
    }
    $curlHandle = curl_init();
    $headerHandle = fopen('php://temp/maxmemory:32768', 'w+b');
    if (false === $headerHandle) {
        throw new \RuntimeException('Failed to open a temp stream to store curl headers');
    }
    if ($copyTo !== null) {
        $bodyTarget = $copyTo . '~';
    }
    else {
        $bodyTarget = 'php://temp/maxmemory:524288';
    }
    $errorMessage = '';
    set_error_handler(static function (int $code, string $msg) use (&$errorMessage) : bool {
        if ($errorMessage) {
            $errorMessage .= "\n";
        }
        $errorMessage .= Preg::replace('{^fopen\\(.*?\\): }', '', $msg);
        return true;
    });
    $bodyHandle = fopen($bodyTarget, 'w+b');
    restore_error_handler();
    if (false === $bodyHandle) {
        throw new TransportException('The "' . $url . '" file could not be written to ' . ($copyTo ?? 'a temporary file') . ': ' . $errorMessage);
    }
    curl_setopt($curlHandle, CURLOPT_URL, $url);
    curl_setopt($curlHandle, CURLOPT_FOLLOWLOCATION, false);
    curl_setopt($curlHandle, CURLOPT_CONNECTTIMEOUT, 10);
    curl_setopt($curlHandle, CURLOPT_TIMEOUT, max((int) ini_get("default_socket_timeout"), 300));
    curl_setopt($curlHandle, CURLOPT_WRITEHEADER, $headerHandle);
    curl_setopt($curlHandle, CURLOPT_FILE, $bodyHandle);
    curl_setopt($curlHandle, CURLOPT_ENCODING, "");
    // let cURL set the Accept-Encoding header to what it supports
    curl_setopt($curlHandle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
    if ($attributes['ipResolve'] === 4) {
        curl_setopt($curlHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
    }
    elseif ($attributes['ipResolve'] === 6) {
        curl_setopt($curlHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
    }
    if (function_exists('curl_share_init')) {
        curl_setopt($curlHandle, CURLOPT_SHARE, $this->shareHandle);
    }
    if (!isset($options['http']['header'])) {
        $options['http']['header'] = [];
    }
    $options['http']['header'] = array_diff($options['http']['header'], [
        'Connection: close',
    ]);
    $options['http']['header'][] = 'Connection: keep-alive';
    $version = curl_version();
    $features = $version['features'];
    if (0 === strpos($url, 'https://') && \defined('CURL_VERSION_HTTP2') && \defined('CURL_HTTP_VERSION_2_0') && (CURL_VERSION_HTTP2 & $features) !== 0) {
        curl_setopt($curlHandle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
    }
    // curl 8.7.0 - 8.7.1 has a bug whereas automatic accept-encoding header results in an error when reading the response
    // https://github.com/composer/composer/issues/11913
    if (isset($version['version']) && in_array($version['version'], [
        '8.7.0',
        '8.7.1',
    ], true) && \defined('CURL_VERSION_LIBZ') && (CURL_VERSION_LIBZ & $features) !== 0) {
        curl_setopt($curlHandle, CURLOPT_ENCODING, "gzip");
    }
    $options['http']['header'] = $this->authHelper
        ->addAuthenticationHeader($options['http']['header'], $origin, $url);
    $options = StreamContextFactory::initOptions($url, $options, true);
    foreach (self::$options as $type => $curlOptions) {
        foreach ($curlOptions as $name => $curlOption) {
            if (isset($options[$type][$name])) {
                if ($type === 'ssl' && $name === 'verify_peer_name') {
                    curl_setopt($curlHandle, $curlOption, $options[$type][$name] === true ? 2 : $options[$type][$name]);
                }
                else {
                    curl_setopt($curlHandle, $curlOption, $options[$type][$name]);
                }
            }
        }
    }
    $proxy = ProxyManager::getInstance()->getProxyForRequest($url);
    curl_setopt_array($curlHandle, $proxy->getCurlOptions($options['ssl'] ?? []));
    $progress = array_diff_key(curl_getinfo($curlHandle), self::$timeInfo);
    $this->jobs[(int) $curlHandle] = [
        'url' => $url,
        'origin' => $origin,
        'attributes' => $attributes,
        'options' => $originalOptions,
        'progress' => $progress,
        'curlHandle' => $curlHandle,
        'filename' => $copyTo,
        'headerHandle' => $headerHandle,
        'bodyHandle' => $bodyHandle,
        'resolve' => $resolve,
        'reject' => $reject,
        'primaryIp' => '',
    ];
    $usingProxy = $proxy->getStatus(' using proxy (%s)');
    $ifModified = false !== stripos(implode(',', $options['http']['header']), 'if-modified-since:') ? ' if modified' : '';
    if ($attributes['redirects'] === 0 && $attributes['retries'] === 0) {
        $this->io
            ->writeError('Downloading ' . Url::sanitize($url) . $usingProxy . $ifModified, true, IOInterface::DEBUG);
    }
    $this->checkCurlResult(curl_multi_add_handle($this->multiHandle, $curlHandle));
    // TODO progress
    return (int) $curlHandle;
}

API Navigation

  • Drupal Core 11.1.x
  • Topics
  • Classes
  • Functions
  • Constants
  • Globals
  • Files
  • Namespaces
  • Deprecated
  • Services
RSS feed
Powered by Drupal