Parse Enterprise, Languages, Release Asset, and CI Job headers for plugins and themes.

@param array           $header
@param array|\WP_Theme $headers
@param array           $header_parts
@param array           $repo_parts

@return array $header
174762
protected function parse_extra_headers( $header, $headers, $header_parts, $repo_parts ) {
		$hosted_domains = [ 'github.com', 'bitbucket.org', 'gitlab.com' ];
		$theme          = null;

		$header['enterprise_uri'] = null;
		$header['enterprise_api'] = null;
		$header['languages']      = null;
		$header['ci_job']         = false;
		$header['release_asset']  = false;

		if ( ! empty( $header['host'] ) && ! in_array( $header['host'], $hosted_domains, true ) ) {
			$header['enterprise_uri'] = $header['base_uri'];
			$header['enterprise_api'] = trim( $header['enterprise_uri'], '/' );
			switch ( $header_parts[0] ) {
				case 'GitHub':
					$header['enterprise_api'] .= '/api/v3';
					break;
				case 'GitLab':
					$header['enterprise_api'] .= '/api/v4';
					break;
				case 'Bitbucket':
					$header['enterprise_api'] .= '/rest/api';
					break;
			}
		}

		if ( $headers instanceof \WP_Theme ) {
			$theme                    = $headers;
			$headers                  = [];
			$headers['Release Asset'] = '';
			$header['release_asset']  = 'true' === $theme->get( 'Release Asset' );
		}

		$self_hosted_parts = array_keys( self::$extra_repo_headers );
		foreach ( $self_hosted_parts as $part ) {
			if ( $theme instanceof \WP_Theme ) {
				$headers[ $repo_parts[ $part ] ] = $theme->get( $repo_parts[ $part ] );
			}
			if ( array_key_exists( $repo_parts[ $part ], $headers ) &&
				! empty( $headers[ $repo_parts[ $part ] ] )
			) {
				switch ( $part ) {
					case 'Languages':
						$header['languages'] = $headers[ $repo_parts[ $part ] ];
						break;
					case 'CIJob':
						$header['ci_job'] = $headers[ $repo_parts[ $part ] ];
						break;
				}
			}
		}
		$header['release_asset'] = ! $header['release_asset'] && isset( $headers['Release Asset'] ) ? 'true' === $headers['Release Asset'] : $header['release_asset'];

		return $header;
	}
917200
private function parseDirectives($header)
    {
        $directives = [];

        foreach (explode(';', $header) as $directive) {
            $parts = explode(' ', trim($directive));
            if (\count($parts) < 1) {
                continue;
            }
            $name = array_shift($parts);
            $directives[$name] = $parts;
        }

        return $directives;
    }
193377
public function remote_install( $headers, $install ) {
		$options['gitea_access_token'] = isset( static::$options['gitea_access_token'] ) ? static::$options['gitea_access_token'] : null;

		$base = $headers['base_uri'] . '/api/v1';

		$install['download_link'] = "{$base}/repos/{$install['github_updater_repo']}/archive/{$install['github_updater_branch']}.zip";

		/*
		 * Add/Save access token if present.
		 */
		if ( ! empty( $install['gitea_access_token'] ) ) {
			$install['options'][ $install['repo'] ]   = $install['gitea_access_token'];
			$install['options']['gitea_access_token'] = $install['gitea_access_token'];
		}

		$token = ! empty( $install['options']['gitea_access_token'] )
			? $install['options']['gitea_access_token']
			: $options['gitea_access_token'];

		if ( ! empty( $token ) ) {
			$install['download_link'] = add_query_arg( 'access_token', $token, $install['download_link'] );
		}

		if ( ! empty( static::$options['gitea_access_token'] ) ) {
			unset( $install['options']['gitea_access_token'] );
		}

		return $install;
	}
108120
public function getHeader($header, $first = true)
    {
        $normalizedHeader = str_replace('-', '_', strtolower($header));
        foreach ($this->headers as $key => $value) {
            if (str_replace('-', '_', strtolower($key)) === $normalizedHeader) {
                if ($first) {
                    return is_array($value) ? (count($value) ? $value[0] : '') : $value;
                }

                return is_array($value) ? $value : array($value);
            }
        }

        return $first ? null : array();
    }
302517
protected function set_part_filename(&$part, $headers = null)
    {
        if (!empty($part->d_parameters['filename'])) {
            $filename_mime = $part->d_parameters['filename'];
        }
        else if (!empty($part->d_parameters['filename*'])) {
            $filename_encoded = $part->d_parameters['filename*'];
        }
        else if (!empty($part->ctype_parameters['name*'])) {
            $filename_encoded = $part->ctype_parameters['name*'];
        }
        // RFC2231 value continuations
        // TODO: this should be rewrited to support RFC2231 4.1 combinations
        else if (!empty($part->d_parameters['filename*0'])) {
            $i = 0;
            while (isset($part->d_parameters['filename*'.$i])) {
                $filename_mime .= $part->d_parameters['filename*'.$i];
                $i++;
            }
            // some servers (eg. dovecot-1.x) have no support for parameter value continuations
            // we must fetch and parse headers "manually"
            if ($i<2) {
                if (!$headers) {
                    $headers = $this->conn->fetchPartHeader(
                        $this->folder, $this->msg_uid, true, $part->mime_id);
                }
                $filename_mime = '';
                $i = 0;
                while (preg_match('/filename\*'.$i.'\s*=\s*"*([^"\n;]+)[";]*/', $headers, $matches)) {
                    $filename_mime .= $matches[1];
                    $i++;
                }
            }
        }
        else if (!empty($part->d_parameters['filename*0*'])) {
            $i = 0;
            while (isset($part->d_parameters['filename*'.$i.'*'])) {
                $filename_encoded .= $part->d_parameters['filename*'.$i.'*'];
                $i++;
            }
            if ($i<2) {
                if (!$headers) {
                    $headers = $this->conn->fetchPartHeader(
                            $this->folder, $this->msg_uid, true, $part->mime_id);
                }
                $filename_encoded = '';
                $i = 0; $matches = array();
                while (preg_match('/filename\*'.$i.'\*\s*=\s*"*([^"\n;]+)[";]*/', $headers, $matches)) {
                    $filename_encoded .= $matches[1];
                    $i++;
                }
            }
        }
        else if (!empty($part->ctype_parameters['name*0'])) {
            $i = 0;
            while (isset($part->ctype_parameters['name*'.$i])) {
                $filename_mime .= $part->ctype_parameters['name*'.$i];
                $i++;
            }
            if ($i<2) {
                if (!$headers) {
                    $headers = $this->conn->fetchPartHeader(
                        $this->folder, $this->msg_uid, true, $part->mime_id);
                }
                $filename_mime = '';
                $i = 0; $matches = array();
                while (preg_match('/\s+name\*'.$i.'\s*=\s*"*([^"\n;]+)[";]*/', $headers, $matches)) {
                    $filename_mime .= $matches[1];
                    $i++;
                }
            }
        }
        else if (!empty($part->ctype_parameters['name*0*'])) {
            $i = 0;
            while (isset($part->ctype_parameters['name*'.$i.'*'])) {
                $filename_encoded .= $part->ctype_parameters['name*'.$i.'*'];
                $i++;
            }
            if ($i<2) {
                if (!$headers) {
                    $headers = $this->conn->fetchPartHeader(
                        $this->folder, $this->msg_uid, true, $part->mime_id);
                }
                $filename_encoded = '';
                $i = 0; $matches = array();
                while (preg_match('/\s+name\*'.$i.'\*\s*=\s*"*([^"\n;]+)[";]*/', $headers, $matches)) {
                    $filename_encoded .= $matches[1];
                    $i++;
                }
            }
        }
        // read 'name' after rfc2231 parameters as it may contains truncated filename (from Thunderbird)
        else if (!empty($part->ctype_parameters['name'])) {
            $filename_mime = $part->ctype_parameters['name'];
        }
        // Content-Disposition
        else if (!empty($part->headers['content-description'])) {
            $filename_mime = $part->headers['content-description'];
        }
        else {
            return;
        }

        // decode filename
        if (!empty($filename_mime)) {
            if (!empty($part->charset)) {
                $charset = $part->charset;
            }
            else if (!empty($this->struct_charset)) {
                $charset = $this->struct_charset;
            }
            else {
                $charset = rcube_charset::detect($filename_mime, $this->default_charset);
            }

            $part->filename = rcube_mime::decode_mime_string($filename_mime, $charset);
        }
        else if (!empty($filename_encoded)) {
            // decode filename according to RFC 2231, Section 4
            if (preg_match("/^([^']*)'[^']*'(.*)$/", $filename_encoded, $fmatches)) {
                $filename_charset = $fmatches[1];
                $filename_encoded = $fmatches[2];
            }

            $part->filename = rcube_charset::convert(urldecode($filename_encoded), $filename_charset);
        }
    }
451356
public function parseHeaders(array $headers)
    {
        $parsed = [];

        foreach ($headers as $key => $val)
        {
            $parsed[] = $key . ': ' . $val;
        }

        return $parsed;
    }
825014
function parseHeader(authHeader, callback){
        try {
            var parts=authHeader.split(/:/),
                username=parts[0],
                password=parts[1];

            callback(null, {username: username, password: password});
        }
        catch(ex){
            callback(ex);
        }
    }
271365
private static function parseRangeHeader($header)
    {
        if (preg_match('/bytes=(?P<first>\d+)-(?P<last>\d+)?/', $header, $matches)) {
            return [
                (int) $matches['first'],
                isset($matches['last']) ? (int) $matches['last'] : null,
            ];
        }

        return false;
    }
587687
private function addRawHeaderToPart($header, PartBuilder $partBuilder)
    {
        if ($header !== '' && strpos($header, ':') !== false) {
            $a = explode(':', $header, 2);
            $partBuilder->addHeader($a[0], trim($a[1]));
        }
    }
1178846
private function parseHeader($header) {
        if(!empty($header)) {
            $pos = strpos($header, ": ");

            if(false !== $pos) {
                $name = substr($header,0,$pos);
                $value = substr($header,$pos+2);

                $this->headers[$name] = $value;
            }
        }
    }
475491
private function parseHeader($header)
    {
        if (!\preg_match_all('/(?:[^,"]*+(?:"[^"]*+")?)+[^,"]*+/', $header, $matches)) {
            throw new InvalidArgumentException('Failed to parse accept header: "' . $header . '"');
        }

        return \array_values(\array_filter(\array_map('\trim', $matches[0])));
    }
1096846
public function nplurals_and_expression_from_header($header)
    {
        if (preg_match('/^\s*nplurals\s*=\s*(\d+)\s*;\s+plural\s*=\s*(.+)$/', $header, $matches)) {
            $nplurals = (int) $matches[1];
            $expression = trim($matches[2]);

            return array($nplurals, $expression);
        } else {
            return array(2, 'n != 1');
        }
    }
1001548
private function extractHeaderAddressPart($header, $part) {
        if (property_exists($header, $part)) {
            $this->$part = $this->parseAddresses($header->$part);
        }
    }
240860
public function setHeaders(array $headers, $merge = false)
    {
        if ($merge) {
            $headers = array_merge($this->headers, $headers);
        }

        $this->headers = $headers;
    }
550803
private function parseApiVersion ($responseHeaders)
    {
        // A header that's unique to the legacy API
        if (array_key_exists('X-SODA2-Legacy-Types', $responseHeaders) && $responseHeaders['X-SODA2-Legacy-Types'])
        {
            return 1;
        }

        // A header that's unique to the new API
        if (array_key_exists('X-SODA2-Truth-Last-Modified', $responseHeaders))
        {
            if (empty($this->metadata))
            {
                $this->getMetadata();
            }

            if ($this->metadata['newBackend'])
            {
                return 2.1;
            }

            return 2;
        }

        return 0;
    }
372994
private function failsHeaderFor(MessagePart $part, $type, $name, $header)
    {
        $headerValue = null;
        
        static $map = [
            'content-type' => 'getContentType',
            'content-disposition' => 'getContentDisposition',
            'content-transfer-encoding' => 'getContentTransferEncoding',
            'content-id' => 'getContentId'
        ];
        $lower = strtolower($name);
        if (isset($map[$lower])) {
            $headerValue = call_user_func([$part, $map[$lower]]);
        } elseif (!($part instanceof MimePart)) {
            return ($type === static::FILTER_INCLUDE);
        } else {
            $headerValue = $part->getHeaderValue($name);
        }
        
        return (($type === static::FILTER_EXCLUDE && strcasecmp($headerValue, $header) === 0)
            || ($type === static::FILTER_INCLUDE && strcasecmp($headerValue, $header) !== 0));
    }
136837
public function parseReturnHeaders($headers)
    {
        $head = [];
        foreach ($headers as $k => $v) {
            $t = explode(':', $v, 2);
            if (isset($t[1])) {
                $head[trim($t[0])] = trim($t[1]);
            } else {
                $head[] = $v;
                if (preg_match("#HTTP/[0-9\.]+\s+([0-9]+)#", $v, $out)) {
                    $head['reponse_code'] = intval($out[1]);
                }
            }
        }
        $this->debug->debug(__FUNCTION__, 'Response Header: ', $head);

        return $head;
    }