Test Failed
Push — master ( 7bf708...820e91 )
by
unknown
04:08
created

FilesWebDavClient   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 124
Duplicated Lines 0 %

Importance

Changes 2
Bugs 2 Features 0
Metric Value
eloc 59
c 2
b 2
f 0
dl 0
loc 124
rs 10
wmc 22
1
<?php
2
/**
3
 * File plugin webdav client.
4
 * Overrides the request function to add support for downloading really large files with less memory.
5
 */
6
7
namespace Files\Backend\Webdav\sabredav;
8
9
use Sabre\DAV\Client;
10
use Sabre\DAV\Exception;
11
use Sabre\DAV\Exception\BadRequest;
12
use Sabre\DAV\Exception\Conflict;
13
use Sabre\DAV\Exception\Forbidden;
14
use Sabre\DAV\Exception\InsufficientStorage;
15
use Sabre\DAV\Exception\MethodNotAllowed;
16
use Sabre\DAV\Exception\NotAuthenticated;
17
use Sabre\DAV\Exception\NotFound;
18
use Sabre\DAV\Exception\NotImplemented;
19
use Sabre\DAV\Exception\PaymentRequired;
20
use Sabre\DAV\Exception\PreconditionFailed;
21
use Sabre\DAV\Exception\RequestedRangeNotSatisfiable;
22
23
include __DIR__ . "/vendor/autoload.php";
24
25
class FilesWebDavClient extends Client {
26
	/**
27
	 * @var string
28
	 */
29
	public $userName;
30
31
	/**
32
	 * @var string
33
	 */
34
	public $password;
35
36
	public function __construct(array $settings) {
37
		if (isset($settings['userName'])) {
38
			$this->userName = $settings['userName'];
39
		}
40
		if (isset($settings['password'])) {
41
			$this->password = $settings['password'];
42
		}
43
		parent::__construct($settings);
44
	}
45
46
	/**
47
	 * Performs an actual HTTP request, and returns the result.
48
	 *
49
	 * If the specified url is relative, it will be expanded based on the base
50
	 * url.
51
	 *
52
	 * The returned array contains 3 keys:
53
	 *   * body - the response body
54
	 *   * httpCode - a HTTP code (200, 404, etc)
55
	 *   * headers - a list of response http headers. The header names have
56
	 *     been lowercased.
57
	 *
58
	 * @param string $url
59
	 * @param string $dstpath
60
	 * @param array  $headers
61
	 *
62
	 * @return array
63
	 */
64
	public function getFile($url, $dstpath, $headers = []) {
65
		if (empty($url)) {
66
			throw new Exception('Empty path');
67
		}
68
		$url = $this->getAbsoluteUrl($url);
69
		$file_handle = fopen($dstpath, "w");
70
71
		if (!$file_handle) {
72
			throw new Exception('[CURL] Error writing to temporary file! (' . $dstpath . ')');
73
		}
74
75
		// straight up curl instead of sabredav here, sabredav put's the entire get result in memory
76
		$curl = curl_init($url);
77
78
		if ($this->verifyPeer !== null) {
79
			curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->verifyPeer);
80
		}
81
		if ($this->trustedCertificates) {
82
			curl_setopt($curl, CURLOPT_CAINFO, $this->trustedCertificates);
83
		}
84
85
		curl_setopt($curl, CURLOPT_USERPWD, $this->userName . ":" . $this->password);
86
		curl_setopt($curl, CURLOPT_FILE, $file_handle);
87
		curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
88
		curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
89
		curl_setopt($curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
90
91
		curl_exec($curl);
92
93
		$statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
94
95
		curl_close($curl);
96
97
		$response = [
98
			'statusCode' => $statusCode,
99
		];
100
101
		if ($response['statusCode'] >= 400) {
102
			switch ($response['statusCode']) {
103
				case 400 :
104
					throw new BadRequest('Bad request');
105
106
				case 401 :
107
					throw new NotAuthenticated('Not authenticated');
108
109
				case 402 :
110
					throw new PaymentRequired('Payment required');
111
112
				case 403 :
113
					throw new Forbidden('Forbidden');
114
115
				case 404:
116
					throw new NotFound('Resource not found.');
117
118
				case 405 :
119
					throw new MethodNotAllowed('Method not allowed');
120
121
				case 409 :
122
					throw new Conflict('Conflict');
123
124
				case 412 :
125
					throw new PreconditionFailed('Precondition failed');
126
127
				case 416 :
128
					throw new RequestedRangeNotSatisfiable('Requested Range Not Satisfiable');
129
130
				case 500 :
131
					throw new Exception('Internal server error');
132
133
				case 501 :
134
					throw new NotImplemented('Not Implemented');
135
136
				case 507 :
137
					throw new InsufficientStorage('Insufficient storage');
138
139
				default:
140
					throw new Exception('HTTP error response. (errorcode ' . $response['statusCode'] . ')');
141
			}
142
		}
143
144
		return $response;
145
	}
146
147
	public function uploadChunkedFile($destination, $resource) {
148
		return $this->request("PUT", $destination, $resource);
149
	}
150
}
151