Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
// This file is part of Moodle - http://moodle.org/
4
//
5
// Moodle is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
9
//
10
// Moodle is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
14
//
15
// You should have received a copy of the GNU General Public License
16
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
17
 
18
/**
19
 * This plugin is used to access s3 files
20
 *
21
 * @since Moodle 2.0
22
 * @package    repository_s3
23
 * @copyright  2010 Dongsheng Cai {@link http://dongsheng.org}
24
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25
 */
26
require_once($CFG->dirroot . '/repository/lib.php');
27
require_once($CFG->dirroot . '/repository/s3/S3.php');
28
 
29
// This constant is not defined in php 5.4. Set it to avoid errors.
30
if (!defined('CURL_SSLVERSION_TLSv1')) {
31
    define('CURL_SSLVERSION_TLSv1', 1);
32
}
33
 
34
/**
35
 * This is a repository class used to browse Amazon S3 content.
36
 *
37
 * @since Moodle 2.0
38
 * @package    repository_s3
39
 * @copyright  2009 Dongsheng Cai {@link http://dongsheng.org}
40
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41
 */
42
class repository_s3 extends repository {
43
 
44
    /** @var string access key. */
45
    protected $access_key;
46
    /** @var string secret key. */
47
    protected $secret_key;
48
    /** @var string endpoint URL. */
49
    protected $endpoint;
50
    /** @var S3 S3 class. */
51
    protected $s;
52
 
53
    /**
54
     * Constructor
55
     * @param int $repositoryid
56
     * @param object $context
57
     * @param array $options
58
     */
59
    public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()) {
60
        global $CFG;
61
        parent::__construct($repositoryid, $context, $options);
62
        $this->access_key = get_config('s3', 'access_key');
63
        $this->secret_key = get_config('s3', 'secret_key');
64
        $this->endpoint = get_config('s3', 'endpoint');
65
        if ($this->endpoint === false) { // If no endpoint has been set, use the default.
66
            $this->endpoint = 's3.amazonaws.com';
67
        }
68
        $this->s = new S3($this->access_key, $this->secret_key, false, $this->endpoint);
69
        $this->s->setExceptions(true);
70
 
71
        // Port of curl::__construct().
72
        if (!empty($CFG->proxyhost)) {
73
            if (empty($CFG->proxyport)) {
74
                $proxyhost = $CFG->proxyhost;
75
            } else {
76
                $proxyhost = $CFG->proxyhost . ':' . $CFG->proxyport;
77
            }
78
            $proxytype = CURLPROXY_HTTP;
79
            $proxyuser = null;
80
            $proxypass = null;
81
            if (!empty($CFG->proxyuser) and !empty($CFG->proxypassword)) {
82
                $proxyuser = $CFG->proxyuser;
83
                $proxypass = $CFG->proxypassword;
84
            }
85
            if (!empty($CFG->proxytype) && $CFG->proxytype == 'SOCKS5') {
86
                $proxytype = CURLPROXY_SOCKS5;
87
            }
88
            $this->s->setProxy($proxyhost, $proxyuser, $proxypass, $proxytype);
89
        }
90
    }
91
 
92
    /**
93
     * Extracts the Bucket and URI from the path
94
     *
95
     * @param string $path path in this format 'bucket/path/to/folder/and/file'
96
     * @return array including bucket and uri
97
     */
98
    protected function explode_path($path) {
99
        $parts = explode('/', $path, 2);
100
        if (isset($parts[1]) && $parts[1] !== '') {
101
            list($bucket, $uri) = $parts;
102
        } else {
103
            $bucket = $parts[0];
104
            $uri = '';
105
        }
106
        return array($bucket, $uri);
107
    }
108
 
109
    /**
110
     * Get S3 file list
111
     *
112
     * @param string $path
113
     * @return array The file list and options
114
     */
115
    public function get_listing($path = '', $page = '') {
116
        global $CFG, $OUTPUT;
117
        if (empty($this->access_key)) {
118
            throw new moodle_exception('needaccesskey', 'repository_s3');
119
        }
120
 
121
        $list = array();
122
        $list['list'] = array();
123
        $list['path'] = array(
124
            array('name' => get_string('pluginname', 'repository_s3'), 'path' => '')
125
        );
126
 
127
        // the management interface url
128
        $list['manage'] = false;
129
        // dynamically loading
130
        $list['dynload'] = true;
131
        // the current path of this list.
132
        // set to true, the login link will be removed
133
        $list['nologin'] = true;
134
        // set to true, the search button will be removed
135
        $list['nosearch'] = true;
136
 
137
        $tree = array();
138
 
139
        if (empty($path)) {
140
            try {
141
                $buckets = $this->s->listBuckets();
142
            } catch (S3Exception $e) {
143
                throw new moodle_exception(
144
                    'errorwhilecommunicatingwith',
145
                    'repository',
146
                    '',
147
                    $this->get_name(),
148
                    $e->getMessage()
149
                );
150
            }
151
            foreach ($buckets as $bucket) {
152
                $folder = array(
153
                    'title' => $bucket,
154
                    'children' => array(),
155
                    'thumbnail' => $OUTPUT->image_url(file_folder_icon())->out(false),
156
                    'path' => $bucket
157
                    );
158
                $tree[] = $folder;
159
            }
160
        } else {
161
            $files = array();
162
            $folders = array();
163
            list($bucket, $uri) = $this->explode_path($path);
164
 
165
            try {
166
                $contents = $this->s->getBucket($bucket, $uri, null, null, '/', true);
167
            } catch (S3Exception $e) {
168
                throw new moodle_exception(
169
                    'errorwhilecommunicatingwith',
170
                    'repository',
171
                    '',
172
                    $this->get_name(),
173
                    $e->getMessage()
174
                );
175
            }
176
            foreach ($contents as $object) {
177
 
178
                // If object has a prefix, it is a 'CommonPrefix', which we consider a folder
179
                if (isset($object['prefix'])) {
180
                    $title = rtrim($object['prefix'], '/');
181
                } else {
182
                    $title = $object['name'];
183
                }
184
 
185
                // Removes the prefix (folder path) from the title
186
                if (strlen($uri) > 0) {
187
                    $title = substr($title, strlen($uri));
188
                    // Check if title is empty and not zero
189
                    if (empty($title) && !is_numeric($title)) {
190
                        // Amazon returns the prefix itself, we skip it
191
                        continue;
192
                    }
193
                }
194
 
195
                // This is a so-called CommonPrefix, we consider it as a folder
196
                if (isset($object['prefix'])) {
197
                    $folders[] = array(
198
                        'title' => $title,
199
                        'children' => array(),
200
                        'thumbnail' => $OUTPUT->image_url(file_folder_icon())->out(false),
201
                        'path' => $bucket . '/' . $object['prefix'],
202
                    );
203
                } else {
204
                    $files[] = array(
205
                        'title' => $title,
206
                        'size' => $object['size'],
207
                        'datemodified' => $object['time'],
208
                        'source' => $bucket . '/' . $object['name'],
209
                        'thumbnail' => $OUTPUT->image_url(file_extension_icon($title))->out(false)
210
                    );
211
                }
212
            }
213
            $tree = array_merge($folders, $files);
214
        }
215
 
216
        $trail = '';
217
        if (!empty($path)) {
218
            $parts = explode('/', $path);
219
            if (count($parts) > 1) {
220
                foreach ($parts as $part) {
221
                    if (!empty($part)) {
222
                        $trail .= $part . '/';
223
                        $list['path'][] = array('name' => $part, 'path' => $trail);
224
                    }
225
                }
226
            } else {
227
                $list['path'][] = array('name' => $path, 'path' => $path);
228
            }
229
        }
230
 
231
        $list['list'] = $tree;
232
 
233
        return $list;
234
    }
235
 
236
    /**
237
     * Download S3 files to moodle
238
     *
239
     * @param string $filepath
240
     * @param string $file The file path in moodle
241
     * @return array The local stored path
242
     */
243
    public function get_file($filepath, $file = '') {
244
        list($bucket, $uri) = $this->explode_path($filepath);
245
        $path = $this->prepare_file($file);
246
        try {
247
            $this->s->getObject($bucket, $uri, $path);
248
        } catch (S3Exception $e) {
249
            throw new moodle_exception(
250
                'errorwhilecommunicatingwith',
251
                'repository',
252
                '',
253
                $this->get_name(),
254
                $e->getMessage()
255
            );
256
        }
257
        return array('path' => $path);
258
    }
259
 
260
    /**
261
     * Return the source information
262
     *
263
     * @param stdClass $filepath
264
     * @return string
265
     */
266
    public function get_file_source_info($filepath) {
267
        return 'Amazon S3: ' . $filepath;
268
    }
269
 
270
    /**
271
     * S3 doesn't require login
272
     *
273
     * @return bool
274
     */
275
    public function check_login() {
276
        return true;
277
    }
278
 
279
    /**
280
     * S3 doesn't provide search
281
     *
282
     * @return bool
283
     */
284
    public function global_search() {
285
        return false;
286
    }
287
 
288
    public static function get_type_option_names() {
289
        return array('access_key', 'secret_key', 'endpoint', 'pluginname');
290
    }
291
 
292
    public static function type_config_form($mform, $classname = 'repository') {
293
        parent::type_config_form($mform);
294
        $strrequired = get_string('required');
295
        $endpointselect = array( // List of possible Amazon S3 Endpoints.
296
            "s3.amazonaws.com" => "s3.amazonaws.com",
297
            "s3-external-1.amazonaws.com" => "s3-external-1.amazonaws.com",
298
            "s3-us-west-2.amazonaws.com" => "s3-us-west-2.amazonaws.com",
299
            "s3-us-west-1.amazonaws.com" => "s3-us-west-1.amazonaws.com",
300
            "s3-eu-west-1.amazonaws.com" => "s3-eu-west-1.amazonaws.com",
301
            "s3.eu-central-1.amazonaws.com" => "s3.eu-central-1.amazonaws.com",
302
            "s3-eu-central-1.amazonaws.com" => "s3-eu-central-1.amazonaws.com",
303
            "s3-ap-southeast-1.amazonaws.com" => "s3-ap-southeast-1.amazonaws.com",
304
            "s3-ap-southeast-2.amazonaws.com" => "s3-ap-southeast-2.amazonaws.com",
305
            "s3-ap-northeast-1.amazonaws.com" => "s3-ap-northeast-1.amazonaws.com",
306
            "s3-sa-east-1.amazonaws.com" => "s3-sa-east-1.amazonaws.com"
307
        );
308
        $mform->addElement('text', 'access_key', get_string('access_key', 'repository_s3'));
309
        $mform->setType('access_key', PARAM_RAW_TRIMMED);
310
        $mform->addElement('text', 'secret_key', get_string('secret_key', 'repository_s3'));
311
        $mform->setType('secret_key', PARAM_RAW_TRIMMED);
312
        $mform->addElement('select', 'endpoint', get_string('endpoint', 'repository_s3'), $endpointselect);
313
        $mform->setDefault('endpoint', 's3.amazonaws.com'); // Default to US Endpoint.
314
        $mform->addRule('access_key', $strrequired, 'required', null, 'client');
315
        $mform->addRule('secret_key', $strrequired, 'required', null, 'client');
316
    }
317
 
318
    /**
319
     * S3 plugins doesn't support return links of files
320
     *
321
     * @return int
322
     */
323
    public function supported_returntypes() {
324
        return FILE_INTERNAL;
325
    }
326
 
327
    /**
328
     * Is this repository accessing private data?
329
     *
330
     * @return bool
331
     */
332
    public function contains_private_data() {
333
        return false;
334
    }
335
}