Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
namespace Aws\S3;
3
 
4
use Aws\Arn\Exception\InvalidArnException;
5
use Aws\Arn\S3\AccessPointArn;
6
use Aws\Arn\ArnParser;
7
use GuzzleHttp\Psr7;
8
use Psr\Http\Message\UriInterface;
9
 
10
/**
11
 * Extracts a region, bucket, key, and and if a URI is in path-style
12
 */
13
class S3UriParser
14
{
15
    private $pattern = '/^(.+\\.)?s3[.-]([A-Za-z0-9-]+)\\./';
16
    private $streamWrapperScheme = 's3';
17
 
18
    private static $defaultResult = [
19
        'path_style' => true,
20
        'bucket'     => null,
21
        'key'        => null,
22
        'region'     => null
23
    ];
24
 
25
    /**
26
     * Parses a URL or S3 StreamWrapper Uri (s3://) into an associative array
27
     * of Amazon S3 data including:
28
     *
29
     * - bucket: The Amazon S3 bucket (null if none)
30
     * - key: The Amazon S3 key (null if none)
31
     * - path_style: Set to true if using path style, or false if not
32
     * - region: Set to a string if a non-class endpoint is used or null.
33
     *
34
     * @param string|UriInterface $uri
35
     *
36
     * @return array
37
     * @throws \InvalidArgumentException|InvalidArnException
38
     */
39
    public function parse($uri)
40
    {
41
        // Attempt to parse host component of uri as an ARN
42
        $components = $this->parseS3UrlComponents($uri);
43
        if (!empty($components)) {
44
            if (ArnParser::isArn($components['host'])) {
45
                $arn = new AccessPointArn($components['host']);
46
                return [
47
                    'bucket' => $components['host'],
48
                    'key' => $components['path'],
49
                    'path_style' => false,
50
                    'region' => $arn->getRegion()
51
                ];
52
            }
53
        }
54
 
55
        $url = Psr7\Utils::uriFor($uri);
56
 
57
        if ($url->getScheme() == $this->streamWrapperScheme) {
58
            return $this->parseStreamWrapper($url);
59
        }
60
 
61
        if (!$url->getHost()) {
62
            throw new \InvalidArgumentException('No hostname found in URI: '
63
                . $uri);
64
        }
65
 
66
        if (!preg_match($this->pattern, $url->getHost(), $matches)) {
67
            return $this->parseCustomEndpoint($url);
68
        }
69
 
70
        // Parse the URI based on the matched format (path / virtual)
71
        $result = empty($matches[1])
72
            ? $this->parsePathStyle($url)
73
            : $this->parseVirtualHosted($url, $matches);
74
 
75
        // Add the region if one was found and not the classic endpoint
76
        $result['region'] = $matches[2] == 'amazonaws' ? null : $matches[2];
77
 
78
        return $result;
79
    }
80
 
81
    private function parseS3UrlComponents($uri)
82
    {
83
        preg_match("/^([a-zA-Z0-9]*):\/\/([a-zA-Z0-9:-]*)\/(.*)/", $uri, $components);
84
        if (empty($components)) {
85
            return [];
86
        }
87
        return [
88
            'scheme' => $components[1],
89
            'host' => $components[2],
90
            'path' => $components[3],
91
        ];
92
    }
93
 
94
    private function parseStreamWrapper(UriInterface $url)
95
    {
96
        $result = self::$defaultResult;
97
        $result['path_style'] = false;
98
 
99
        $result['bucket'] = $url->getHost();
100
        if ($url->getPath()) {
101
            $key = ltrim($url->getPath(), '/ ');
102
            if (!empty($key)) {
103
                $result['key'] = $key;
104
            }
105
        }
106
 
107
        return $result;
108
    }
109
 
110
    private function parseCustomEndpoint(UriInterface $url)
111
    {
112
        $result = self::$defaultResult;
113
        $path = ltrim($url->getPath(), '/ ');
114
        $segments = explode('/', $path, 2);
115
 
116
        if (isset($segments[0])) {
117
            $result['bucket'] = $segments[0];
118
            if (isset($segments[1])) {
119
                $result['key'] = $segments[1];
120
            }
121
        }
122
 
123
        return $result;
124
    }
125
 
126
    private function parsePathStyle(UriInterface $url)
127
    {
128
        $result = self::$defaultResult;
129
 
130
        if ($url->getPath() != '/') {
131
            $path = ltrim($url->getPath(), '/');
132
            if ($path) {
133
                $pathPos = strpos($path, '/');
134
                if ($pathPos === false) {
135
                    // https://s3.amazonaws.com/bucket
136
                    $result['bucket'] = $path;
137
                } elseif ($pathPos == strlen($path) - 1) {
138
                    // https://s3.amazonaws.com/bucket/
139
                    $result['bucket'] = substr($path, 0, -1);
140
                } else {
141
                    // https://s3.amazonaws.com/bucket/key
142
                    $result['bucket'] = substr($path, 0, $pathPos);
143
                    $result['key'] = substr($path, $pathPos + 1) ?: null;
144
                }
145
            }
146
        }
147
 
148
        return $result;
149
    }
150
 
151
    private function parseVirtualHosted(UriInterface $url, array $matches)
152
    {
153
        $result = self::$defaultResult;
154
        $result['path_style'] = false;
155
        // Remove trailing "." from the prefix to get the bucket
156
        $result['bucket'] = substr($matches[1], 0, -1);
157
        $path = $url->getPath();
158
        // Check if a key was present, and if so, removing the leading "/"
159
        $result['key'] = !$path || $path == '/' ? null : substr($path, 1);
160
 
161
        return $result;
162
    }
163
}