These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | class UpYun |
||
0 ignored issues
–
show
|
|||
3 | { |
||
4 | const VERSION = '2.2.0'; |
||
5 | |||
6 | const ED_AUTO = 'v0.api.upyun.com'; |
||
7 | const ED_TELECOM = 'v1.api.upyun.com'; |
||
8 | const ED_CNC = 'v2.api.upyun.com'; |
||
9 | const ED_CTT = 'v3.api.upyun.com'; |
||
10 | |||
11 | const CONTENT_TYPE = 'Content-Type'; |
||
12 | const CONTENT_MD5 = 'Content-MD5'; |
||
13 | const CONTENT_SECRET = 'Content-Secret'; |
||
14 | |||
15 | // 缩略图 |
||
16 | const X_GMKERL_THUMBNAIL = 'x-gmkerl-thumbnail'; |
||
17 | const X_GMKERL_TYPE = 'x-gmkerl-type'; |
||
18 | const X_GMKERL_VALUE = 'x-gmkerl-value'; |
||
19 | const X_GMKERL_QUALITY = 'xgmkerl-quality'; |
||
20 | const X_GMKERL_UNSHARP = 'xgmkerl-unsharp'; |
||
21 | |||
22 | |||
23 | private $_bucketname; |
||
24 | private $_username; |
||
25 | private $_password; |
||
26 | private $_timeout = 30; |
||
27 | private $_file_secret = null; |
||
28 | private $_content_md5 = null; |
||
29 | |||
30 | protected $endpoint; |
||
31 | |||
32 | /** |
||
33 | * @var string: UPYUN 请求唯一id, 出现错误时, 可以将该id报告给 UPYUN,进行调试 |
||
34 | */ |
||
35 | private $x_request_id; |
||
36 | |||
37 | /** |
||
38 | * 初始化 UpYun 存储接口 |
||
39 | * @param $bucketname string 空间名称 |
||
40 | * @param $username string 操作员名称 |
||
41 | * @param $password string 密码 |
||
42 | * |
||
43 | * @param null $endpoint |
||
44 | * @param int $timeout |
||
45 | */ |
||
46 | public function __construct($bucketname, $username, $password, $endpoint = NULL, $timeout = 30) |
||
47 | { |
||
48 | $this->_bucketname = $bucketname; |
||
49 | $this->_username = $username; |
||
50 | $this->_password = md5($password); |
||
51 | $this->_timeout = $timeout; |
||
52 | |||
53 | $this->endpoint = is_null($endpoint) ? self::ED_AUTO : $endpoint; |
||
54 | } |
||
55 | |||
56 | /** |
||
57 | * 获取当前SDK版本号 |
||
58 | */ |
||
59 | public function version() |
||
60 | { |
||
61 | return self::VERSION; |
||
62 | } |
||
63 | |||
64 | /** |
||
65 | * 创建目录 |
||
66 | * @param $path string 路径 |
||
67 | * @param $auto_mkdir bool 是否自动创建父级目录,最多10层次 |
||
68 | * |
||
69 | * @return mixed |
||
70 | */ |
||
71 | public function makeDir($path, $auto_mkdir = true) |
||
72 | { |
||
73 | $headers = array('Folder' => 'true'); |
||
74 | if ($auto_mkdir) $headers['Mkdir'] = 'true'; |
||
75 | return $this->_do_request('PUT', $path, $headers); |
||
76 | } |
||
77 | |||
78 | /** |
||
79 | * 删除目录和文件 |
||
80 | * @param string $path 路径 |
||
81 | * |
||
82 | * @return boolean |
||
83 | */ |
||
84 | public function delete($path) |
||
85 | { |
||
86 | return $this->_do_request('DELETE', $path); |
||
87 | } |
||
88 | |||
89 | |||
90 | /** |
||
91 | * 上传文件 |
||
92 | * @param string $path 存储路径 |
||
93 | * @param mixed $file 需要上传的文件,可以是文件流或者文件内容 |
||
94 | * @param boolean $auto_mkdir 自动创建目录 |
||
95 | * @param array $opts 可选参数 |
||
96 | * @return mixed|null |
||
97 | */ |
||
98 | public function writeFile($path, $file, $auto_mkdir = true, $opts = NULL) |
||
99 | { |
||
100 | if (is_null($opts)) $opts = array(); |
||
101 | |||
102 | if (!is_null($this->_content_md5)) $opts[self::CONTENT_MD5] = $this->_content_md5; |
||
103 | if (!is_null($this->_file_secret)) $opts[self::CONTENT_SECRET] = $this->_file_secret; |
||
104 | |||
105 | if ($auto_mkdir === true) $opts['Mkdir'] = 'true'; |
||
106 | |||
107 | return $this->_do_request('PUT', $path, $opts, $file); |
||
108 | } |
||
109 | |||
110 | /** |
||
111 | * 下载文件 |
||
112 | * @param string $path 文件路径 |
||
113 | * @param mixed $file_handle |
||
114 | * |
||
115 | * @return mixed |
||
116 | */ |
||
117 | public function readFile($path, $file_handle = NULL) |
||
118 | { |
||
119 | return $this->_do_request('GET', $path, NULL, NULL, $file_handle); |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * 获取目录文件列表 |
||
124 | * |
||
125 | * @param string $path 查询路径 |
||
126 | * |
||
127 | * @return mixed |
||
128 | */ |
||
129 | public function getList($path = '/') |
||
130 | { |
||
131 | $rsp = $this->_do_request('GET', $path); |
||
132 | |||
133 | $list = array(); |
||
134 | if ($rsp) { |
||
135 | $rsp = explode("\n", $rsp); |
||
136 | foreach ($rsp as $item) { |
||
137 | @list($name, $type, $size, $time) = explode("\t", trim($item)); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
138 | if (!empty($time)) { |
||
139 | $type = ($type == 'N') ? 'file' : 'folder'; |
||
140 | } |
||
141 | |||
142 | $item = array( |
||
143 | 'name' => $name, |
||
144 | 'type' => $type, |
||
145 | 'size' => intval($size), |
||
146 | 'time' => intval($time), |
||
147 | ); |
||
148 | array_push($list, $item); |
||
149 | } |
||
150 | } |
||
151 | |||
152 | return $list; |
||
153 | } |
||
154 | |||
155 | /** |
||
156 | * 获取文件、目录信息 |
||
157 | * |
||
158 | * @param string $path 路径 |
||
159 | * |
||
160 | * @return mixed |
||
161 | */ |
||
162 | public function getFileInfo($path) |
||
163 | { |
||
164 | $rsp = $this->_do_request('HEAD', $path); |
||
165 | return $rsp; |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * 获取空间使用情况 |
||
170 | * @param string $bucket |
||
171 | * @return mixed |
||
172 | * @throws UpYunAuthorizationException |
||
173 | * @throws UpYunException |
||
174 | * @throws UpYunForbiddenException |
||
175 | * @throws UpYunNotAcceptableException |
||
176 | * @throws UpYunNotFoundException |
||
177 | * @throws UpYunServiceUnavailable |
||
178 | */ |
||
179 | public function getFolderUsage($bucket = '/') |
||
180 | { |
||
181 | return $this->_do_request('GET', "{$bucket}?usage"); |
||
182 | } |
||
183 | |||
184 | /** |
||
185 | * 获取空间存储使用量,单位 byte |
||
186 | */ |
||
187 | public function getBucketUsage() |
||
188 | { |
||
189 | return $this->getFolderUsage('/'); |
||
190 | } |
||
191 | |||
192 | public function getXRequestId() |
||
193 | { |
||
194 | return $this->x_request_id; |
||
195 | } |
||
196 | |||
197 | /** |
||
198 | * 设置文件访问密钥 |
||
199 | */ |
||
200 | public function setFileSecret($str) |
||
201 | { |
||
202 | $this->_file_secret = $str; |
||
203 | } |
||
204 | |||
205 | /** |
||
206 | * 这是文件 md5 校验值 |
||
207 | */ |
||
208 | public function setContentMd5($str) |
||
209 | { |
||
210 | $this->_content_md5 = $str; |
||
211 | } |
||
212 | |||
213 | /** |
||
214 | * 连接签名方法 |
||
215 | * @param $method string 请求方式 {GET, POST, PUT, DELETE} |
||
216 | * @return string 签名字符串 |
||
217 | */ |
||
218 | private function sign($method, $uri, $date, $length) |
||
219 | { |
||
220 | //$uri = urlencode($uri); |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
56% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
221 | $sign = "{$method}&{$uri}&{$date}&{$length}&{$this->_password}"; |
||
222 | return 'UpYun ' . $this->_username . ':' . md5($sign); |
||
223 | } |
||
224 | |||
225 | /** |
||
226 | * HTTP REQUEST 封装 |
||
227 | * @param string $method HTTP REQUEST方法,包括PUT、POST、GET、OPTIONS、DELETE |
||
228 | * @param string $path 除Bucketname之外的请求路径,包括get参数 |
||
229 | * @param array $headers 请求需要的特殊HTTP HEADERS |
||
230 | * @param array $body 需要POST发送的数据 |
||
231 | * @param null $file_handle |
||
232 | * @return mixed |
||
233 | * @throws UpYunAuthorizationException |
||
234 | * @throws UpYunException |
||
235 | * @throws UpYunForbiddenException |
||
236 | * @throws UpYunNotAcceptableException |
||
237 | * @throws UpYunNotFoundException |
||
238 | * @throws UpYunServiceUnavailable |
||
239 | */ |
||
240 | protected function _do_request($method, $path, $headers = NULL, $body = NULL, $file_handle = NULL) |
||
241 | { |
||
242 | $uri = "/{$this->_bucketname}{$path}"; |
||
243 | $ch = curl_init("http://{$this->endpoint}{$uri}"); |
||
244 | |||
245 | $_headers = array('Expect:'); |
||
246 | if (!is_null($headers) && is_array($headers)) { |
||
247 | foreach ($headers as $k => $v) { |
||
248 | array_push($_headers, "{$k}: {$v}"); |
||
249 | } |
||
250 | } |
||
251 | |||
252 | $length = 0; |
||
253 | $date = gmdate('D, d M Y H:i:s \G\M\T'); |
||
254 | |||
255 | if (!is_null($body)) { |
||
256 | if (is_resource($body)) { |
||
257 | fseek($body, 0, SEEK_END); |
||
258 | $length = ftell($body); |
||
259 | fseek($body, 0); |
||
260 | |||
261 | array_push($_headers, "Content-Length: {$length}"); |
||
262 | curl_setopt($ch, CURLOPT_INFILE, $body); |
||
263 | curl_setopt($ch, CURLOPT_INFILESIZE, $length); |
||
264 | } else { |
||
265 | $length = @strlen($body); |
||
266 | array_push($_headers, "Content-Length: {$length}"); |
||
267 | curl_setopt($ch, CURLOPT_POSTFIELDS, $body); |
||
268 | } |
||
269 | } else { |
||
270 | array_push($_headers, "Content-Length: {$length}"); |
||
271 | } |
||
272 | |||
273 | array_push($_headers, "Authorization: {$this->sign($method, $uri, $date, $length)}"); |
||
274 | array_push($_headers, "Date: {$date}"); |
||
275 | |||
276 | curl_setopt($ch, CURLOPT_HTTPHEADER, $_headers); |
||
277 | curl_setopt($ch, CURLOPT_TIMEOUT, $this->_timeout); |
||
278 | curl_setopt($ch, CURLOPT_HEADER, 1); |
||
279 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); |
||
280 | //curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
64% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
281 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0); |
||
282 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); |
||
283 | |||
284 | if ($method == 'PUT' || $method == 'POST') { |
||
285 | curl_setopt($ch, CURLOPT_POST, 1); |
||
286 | } else { |
||
287 | curl_setopt($ch, CURLOPT_POST, 0); |
||
288 | } |
||
289 | |||
290 | if ($method == 'GET' && is_resource($file_handle)) { |
||
291 | curl_setopt($ch, CURLOPT_HEADER, 0); |
||
292 | curl_setopt($ch, CURLOPT_FILE, $file_handle); |
||
293 | } |
||
294 | |||
295 | if ($method == 'HEAD') { |
||
296 | curl_setopt($ch, CURLOPT_NOBODY, true); |
||
297 | } |
||
298 | |||
299 | $response = curl_exec($ch); |
||
300 | $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); |
||
301 | |||
302 | if ($http_code == 0) throw new UpYunException('Connection Failed', $http_code); |
||
303 | |||
304 | curl_close($ch); |
||
305 | |||
306 | $header_string = ''; |
||
307 | $body = ''; |
||
308 | |||
309 | if ($method == 'GET' && is_resource($file_handle)) { |
||
310 | $header_string = ''; |
||
311 | $body = $response; |
||
312 | } else { |
||
313 | list($header_string, $body) = explode("\r\n\r\n", $response, 2); |
||
314 | } |
||
315 | $this->setXRequestId($header_string); |
||
316 | if ($http_code == 200) { |
||
317 | if ($method == 'GET' && is_null($file_handle)) { |
||
318 | return $body; |
||
319 | } else { |
||
320 | $data = $this->_getHeadersData($header_string); |
||
321 | return count($data) > 0 ? $data : true; |
||
322 | } |
||
323 | } else { |
||
324 | $message = $this->_getErrorMessage($header_string); |
||
325 | if (is_null($message) && $method == 'GET' && is_resource($file_handle)) { |
||
326 | $message = 'File Not Found'; |
||
327 | } |
||
328 | switch ($http_code) { |
||
329 | case 401: |
||
330 | throw new UpYunAuthorizationException($message); |
||
331 | break; |
||
0 ignored issues
–
show
break; does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
332 | case 403: |
||
333 | throw new UpYunForbiddenException($message); |
||
334 | break; |
||
0 ignored issues
–
show
break; does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
335 | case 404: |
||
336 | throw new UpYunNotFoundException($message); |
||
337 | break; |
||
0 ignored issues
–
show
break; does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
338 | case 406: |
||
339 | throw new UpYunNotAcceptableException($message); |
||
340 | break; |
||
0 ignored issues
–
show
break; does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
341 | case 503: |
||
342 | throw new UpYunServiceUnavailable($message); |
||
343 | break; |
||
0 ignored issues
–
show
break; does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
344 | default: |
||
345 | throw new UpYunException($message, $http_code); |
||
346 | } |
||
347 | } |
||
348 | } |
||
349 | |||
350 | /** |
||
351 | * 处理HTTP HEADERS中返回的自定义数据 |
||
352 | * |
||
353 | * @param string $text header字符串 |
||
354 | * |
||
355 | * @return array |
||
356 | */ |
||
357 | private function _getHeadersData($text) |
||
358 | { |
||
359 | $headers = explode("\r\n", $text); |
||
360 | $items = array(); |
||
361 | foreach ($headers as $header) { |
||
362 | $header = trim($header); |
||
363 | if (stripos($header, 'x-upyun') !== False) { |
||
364 | list($k, $v) = explode(':', $header); |
||
365 | $items[trim($k)] = in_array(substr($k, 8, 5), array('width', 'heigh', 'frame')) ? intval($v) : trim($v); |
||
366 | } |
||
367 | } |
||
368 | return $items; |
||
369 | } |
||
370 | |||
371 | /** |
||
372 | * 获取返回的错误信息 |
||
373 | * |
||
374 | * @param string $header_string |
||
375 | * |
||
376 | * @return mixed |
||
377 | */ |
||
378 | private function _getErrorMessage($header_string) |
||
379 | { |
||
380 | list($status, $stash) = explode("\r\n", $header_string, 2); |
||
0 ignored issues
–
show
The assignment to
$stash is unused. Consider omitting it like so list($first,,$third) .
This checks looks for assignemnts to variables using the Consider the following code example. <?php
function returnThreeValues() {
return array('a', 'b', 'c');
}
list($a, $b, $c) = returnThreeValues();
print $a . " - " . $c;
Only the variables Instead, the list call could have been. list($a,, $c) = returnThreeValues();
![]() |
|||
381 | list($v, $code, $message) = explode(" ", $status, 3); |
||
0 ignored issues
–
show
The assignment to
$v is unused. Consider omitting it like so list($first,,$third) .
This checks looks for assignemnts to variables using the Consider the following code example. <?php
function returnThreeValues() {
return array('a', 'b', 'c');
}
list($a, $b, $c) = returnThreeValues();
print $a . " - " . $c;
Only the variables Instead, the list call could have been. list($a,, $c) = returnThreeValues();
![]() The assignment to
$code is unused. Consider omitting it like so list($first,,$third) .
This checks looks for assignemnts to variables using the Consider the following code example. <?php
function returnThreeValues() {
return array('a', 'b', 'c');
}
list($a, $b, $c) = returnThreeValues();
print $a . " - " . $c;
Only the variables Instead, the list call could have been. list($a,, $c) = returnThreeValues();
![]() |
|||
382 | return $message . " X-Request-Id: " . $this->getXRequestId(); |
||
383 | } |
||
384 | |||
385 | private function setXRequestId($header_string) |
||
386 | { |
||
387 | preg_match('~^X-Request-Id: ([0-9a-zA-Z]{32})~ism', $header_string, $result); |
||
388 | $this->x_request_id = isset($result[1]) ? $result[1] : ''; |
||
389 | } |
||
390 | } |
||
391 | |||
392 | |||
393 | class UpYunException extends Exception |
||
0 ignored issues
–
show
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.
You can fix this by adding a namespace to your class: namespace YourVendor;
class YourClass { }
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries. ![]() |
|||
394 | { |
||
395 | public function __construct($message, $code, Exception $previous = null) |
||
396 | { |
||
397 | parent::__construct($message, $code); // For PHP 5.2.x |
||
398 | } |
||
399 | |||
400 | public function __toString() |
||
401 | { |
||
402 | return __CLASS__ . ": [{$this->code}]: {$this->message}\n"; |
||
403 | } |
||
404 | } |
||
405 | |||
406 | class UpYunAuthorizationException extends UpYunException |
||
0 ignored issues
–
show
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.
You can fix this by adding a namespace to your class: namespace YourVendor;
class YourClass { }
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries. ![]() |
|||
407 | { |
||
408 | public function __construct($message, $code = 0, Exception $previous = null) |
||
409 | { |
||
410 | parent::__construct($message, 401, $previous); |
||
411 | } |
||
412 | } |
||
413 | |||
414 | class UpYunForbiddenException extends UpYunException |
||
0 ignored issues
–
show
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.
You can fix this by adding a namespace to your class: namespace YourVendor;
class YourClass { }
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries. ![]() |
|||
415 | { |
||
416 | public function __construct($message, $code = 0, Exception $previous = null) |
||
417 | { |
||
418 | parent::__construct($message, 403, $previous); |
||
419 | } |
||
420 | } |
||
421 | |||
422 | class UpYunNotFoundException extends UpYunException |
||
0 ignored issues
–
show
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.
You can fix this by adding a namespace to your class: namespace YourVendor;
class YourClass { }
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries. ![]() |
|||
423 | { |
||
424 | public function __construct($message, $code = 0, Exception $previous = null) |
||
425 | { |
||
426 | parent::__construct($message, 404, $previous); |
||
427 | } |
||
428 | } |
||
429 | |||
430 | class UpYunNotAcceptableException extends UpYunException |
||
0 ignored issues
–
show
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.
You can fix this by adding a namespace to your class: namespace YourVendor;
class YourClass { }
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries. ![]() |
|||
431 | { |
||
432 | public function __construct($message, $code = 0, Exception $previous = null) |
||
433 | { |
||
434 | parent::__construct($message, 406, $previous); |
||
435 | } |
||
436 | } |
||
437 | |||
438 | class UpYunServiceUnavailable extends UpYunException |
||
0 ignored issues
–
show
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.
You can fix this by adding a namespace to your class: namespace YourVendor;
class YourClass { }
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries. ![]() |
|||
439 | { |
||
440 | public function __construct($message, $code = 0, Exception $previous = null) |
||
441 | { |
||
442 | parent::__construct($message, 503, $previous); |
||
443 | } |
||
444 | } |
||
445 |
You can fix this by adding a namespace to your class:
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.