<commit_before><?php

namespace Acquia\Hmac;

use Acquia\Hmac\Request\RequestInterface;

class RequestSigner implements RequestSignerInterface
{
    /**
     * @var \Acquia\Hmac\Digest\DigestInterface
     */
    protected $digest;

    /**
     * @var string
     */
    protected $provider = 'Acquia';

    /**
     * @var array
     */
    protected $timestampHeaders = array('Date');

    /**
     * @var array
     */
    protected $customHeaders = array();

    /**
     * @param \Acquia\Hmac\Digest\DigestInterface $digest
     */
    public function __construct(Digest\DigestInterface $digest = null)
    {
        $this->digest = $digest ?: new Digest\Version1();
    }

    /**
     * {@inheritDoc}
     *
     * @throws \Acquia\Hmac\Exception\MalformedRequest
     */
    public function getSignature(RequestInterface $request)
    {
        if (!$request->hasHeader('Authorization')) {
            throw new Exception\MalformedRequestException('Authorization header required');
        }

        $provider = preg_quote($this->provider, '@');
        $pattern = '@^' . $provider . ' ([a-zA-Z0-9]+):([a-zA-Z0-9+/]+={0,2})$@';

        if (!preg_match($pattern, $request->getHeader('Authorization'), $matches)) {
            throw new Exception\MalformedRequestException('Authorization header not valid');
        }

        $time = $this->getTimestamp($request);
        $timestamp = strtotime($time);
        if (!$timestamp) {
            throw new Exception\MalformedRequestException('Timestamp not valid');
        }

        return new Signature($matches[1], $matches[2], $timestamp);
    }

    /**
     * {@inheritDoc}
     *
     * @throws \InvalidArgumentException
     * @throws \Acquia\Hmac\Exception\InvalidRequestException
     */
    public function signRequest(RequestInterface $request, $secretKey)
    {
        return $this->digest->get($this, $request, $secretKey);
    }

    /**
     * {@inheritDoc}
     *
     * @throws \Acquia\Hmac\Exception\InvalidRequestException
     */
    public function getAuthorization(RequestInterface $request, $id, $secretKey)
    {
        $signature = $this->signRequest($request, $secretKey);
        return $this->provider . ' ' . $id . ':' . $signature;
    }

    /**
     * @param string $provider
     *
     * @return \Acquia\Hmac\RequestSigner
     */
    public function setProvider($provider)
    {
        $this->provider = $provider;
        return $this;
    }

    /**
     * {@inheritDoc}
     */
    public function getProvider()
    {
        return $this->provider;
    }

    /**
     * Appends a timestap header to the stack.
     *
     * @param string $header
     *
     * @return \Acquia\Hmac\RequestSigner
     */
    public function addTimestampHeader($header)
    {<commit_msg>Fixed #11: Removed character restriction on IDs.<commit_after><?php

namespace Acquia\Hmac;

use Acquia\Hmac\Request\RequestInterface;

class RequestSigner implements RequestSignerInterface
{
    /**
     * @var \Acquia\Hmac\Digest\DigestInterface
     */
    protected $digest;

    /**
     * @var string
     */
    protected $provider = 'Acquia';

    /**
     * @var array
     */
    protected $timestampHeaders = array('Date');

    /**
     * @var array
     */
    protected $customHeaders = array();

    /**
     * @param \Acquia\Hmac\Digest\DigestInterface $digest
     */
    public function __construct(Digest\DigestInterface $digest = null)
    {
        $this->digest = $digest ?: new Digest\Version1();
    }

    /**
     * {@inheritDoc}
     *
     * @throws \Acquia\Hmac\Exception\MalformedRequest
     */
    public function getSignature(RequestInterface $request)
    {
        if (!$request->hasHeader('Authorization')) {
            throw new Exception\MalformedRequestException('Authorization header required');
        }

        // Check the provider.
        $header = $request->getHeader('Authorization');
        if ($pos = strpos($header, $this->provider . ' ') === false) {
            throw new Exception\MalformedRequestException('Invalid provider in authorization header');
        }

        // Split ID and sgnature by an unescaped colon.
        $offset = strlen($this->provider) + 1;
        $credentials = substr($header, $offset);
        $matches = preg_split('@\\\\.(*SKIP)(*FAIL)|:@s', $credentials);
        if (!isset($matches[1])) {
            throw new Exception\MalformedRequestException('Unable to parse ID and signature from authorization header');
        }

        // Ensure the signature is a base64 encoded string.
        if (!preg_match('@^[a-zA-Z0-9+/]+={0,2}$@', $matches[1])) {
            throw new Exception\MalformedRequestException('Invalid signature in authorization header');
        }

        $time = $this->getTimestamp($request);
        $timestamp = strtotime($time);
        if (!$timestamp) {
            throw new Exception\MalformedRequestException('Timestamp not valid');
        }

        return new Signature(stripslashes($matches[0]), $matches[1], $timestamp);
    }

    /**
     * {@inheritDoc}
     *
     * @throws \InvalidArgumentException
     * @throws \Acquia\Hmac\Exception\InvalidRequestException
     */
    public function signRequest(RequestInterface $request, $secretKey)
    {
        return $this->digest->get($this, $request, $secretKey);
    }

    /**
     * {@inheritDoc}
     *
     * @throws \Acquia\Hmac\Exception\InvalidRequestException
     */
    public function getAuthorization(RequestInterface $request, $id, $secretKey)
    {
        $signature = $this->signRequest($request, $secretKey);
        return $this->provider . ' ' . str_replace(':', '\\:', $id) . ':' . $signature;
    }

    /**
     * @param string $provider
     *
     * @return \Acquia\Hmac\RequestSigner
     */
    public function setProvider($provider)
    {
        $this->provider = $provider;
        return $this;
    }

    /**
     * {@inheritDoc}
     */
    public function getProvider()
    {
        return $this->provider;
    }

    /**
     * Appends a timestap header to the stack.
     *
     * @param string $header
     *
     * @return \Acquia\Hmac\RequestSigner
     */
    public function addTimestampHeader($header)
    {
{'fraction_non_alphanumeric': 0.14177296948167287, 'fraction_numerical': 0.003713870498950428, 'mean_word_length': 2.355362946912243, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 26, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3788886', 'n_tokens_mistral': 1827, 'n_tokens_neox': 1780, 'n_words': 353}