This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Freyo\Flysystem\QcloudCOSv3\Client; |
||
4 | |||
5 | class Cosapi |
||
6 | { |
||
7 | //计算sign签名的时间参数 |
||
8 | const EXPIRED_SECONDS = 180; |
||
9 | //512K |
||
10 | const SLICE_SIZE_512K = 524288; |
||
11 | //1M |
||
12 | const SLICE_SIZE_1M = 1048576; |
||
13 | //2M |
||
14 | const SLICE_SIZE_2M = 2097152; |
||
15 | //3M |
||
16 | const SLICE_SIZE_3M = 3145728; |
||
17 | //20M 大于20M的文件需要进行分片传输 |
||
18 | const MAX_UNSLICE_FILE_SIZE = 20971520; |
||
19 | //失败尝试次数 |
||
20 | const MAX_RETRY_TIMES = 3; |
||
21 | //返回的错误码 |
||
22 | const COSAPI_PARAMS_ERROR = -1; |
||
23 | const COSAPI_NETWORK_ERROR = -2; |
||
24 | |||
25 | //HTTP请求超时时间 |
||
26 | private static $timeout = 60; |
||
27 | |||
28 | /** |
||
29 | * 获取当前指定时区的 Unix 时间戳 |
||
30 | * |
||
31 | * @param string $timezone |
||
32 | * |
||
33 | * @return int |
||
34 | */ |
||
35 | 14 | public static function time($timezone = 'Asia/Shanghai') |
|
36 | { |
||
37 | 14 | return date_create('now', timezone_open($timezone))->getTimestamp(); |
|
38 | } |
||
39 | |||
40 | /* |
||
41 | * 设置HTTP请求超时时间 |
||
42 | * |
||
43 | * @param int $timeout 超时时长 |
||
44 | * |
||
45 | * @return bool |
||
46 | */ |
||
47 | public static function setTimeout($timeout = 60) |
||
48 | { |
||
49 | if (!is_int($timeout) || $timeout < 0) { |
||
50 | return false; |
||
51 | } |
||
52 | |||
53 | self::$timeout = $timeout; |
||
54 | |||
55 | return true; |
||
56 | } |
||
57 | |||
58 | /** |
||
59 | * 上传文件,自动判断文件大小,如果小于20M则使用普通文件上传,大于20M则使用分片上传. |
||
60 | * |
||
61 | * @param string $bucketName bucket名称 |
||
62 | * @param string $srcPath 本地文件路径 |
||
63 | * @param string $dstPath 上传的文件路径 |
||
64 | * @param string $bizAttr 文件属性 |
||
65 | * @param string $sliceSize 分片大小(512k,1m,2m,3m),默认:1m |
||
66 | * @param string $insertOnly 同名文件是否覆盖 |
||
67 | * |
||
68 | * @return array |
||
69 | */ |
||
70 | 2 | public static function upload($bucketName, $srcPath, $dstPath, |
|
71 | $bizAttr = null, $sliceSize = null, $insertOnly = null) |
||
72 | { |
||
73 | 2 | View Code Duplication | if (!file_exists($srcPath)) { |
0 ignored issues
–
show
|
|||
74 | return [ |
||
75 | 'code' => self::COSAPI_PARAMS_ERROR, |
||
76 | 'message' => 'file '.$srcPath.' not exists', |
||
77 | 'data' => [], ]; |
||
78 | } |
||
79 | |||
80 | 2 | $dstPath = '/'.ltrim($dstPath, '/'); |
|
81 | |||
82 | //文件大于20M则使用分片传输 |
||
83 | 2 | if (filesize($srcPath) < self::MAX_UNSLICE_FILE_SIZE) { |
|
84 | 2 | return self::uploadfile($bucketName, $srcPath, $dstPath, $bizAttr, $insertOnly); |
|
85 | } else { |
||
86 | $sliceSize = self::getSliceSize($sliceSize); |
||
87 | |||
88 | return self::upload_slice($bucketName, $srcPath, $dstPath, $bizAttr, $sliceSize, $insertOnly); |
||
89 | } |
||
90 | } |
||
91 | |||
92 | /** |
||
93 | * 创建目录. |
||
94 | * |
||
95 | * @param string $bucketName bucket名称 |
||
96 | * @param string $path 目录路径 |
||
97 | * @param string $bizAttr 目录属性 |
||
98 | * |
||
99 | * @return array |
||
100 | */ |
||
101 | 1 | public static function createFolder($bucketName, $path, $bizAttr = null) |
|
102 | { |
||
103 | 1 | $path = self::normalizerPath($path, true); |
|
104 | 1 | $path = self::cosUrlEncode($path); |
|
105 | 1 | $expired = self::time() + self::EXPIRED_SECONDS; |
|
106 | 1 | $url = self::generateResUrl($bucketName, $path); |
|
107 | 1 | $sign = Auth::appSign($expired, $bucketName); |
|
108 | |||
109 | $data = [ |
||
110 | 1 | 'op' => 'create', |
|
111 | 1 | 'biz_attr' => (isset($bizAttr) ? $bizAttr : ''), |
|
112 | 1 | ]; |
|
113 | |||
114 | 1 | $data = json_encode($data); |
|
115 | |||
116 | $req = [ |
||
117 | 1 | 'url' => $url, |
|
118 | 1 | 'method' => 'post', |
|
119 | 1 | 'timeout' => self::$timeout, |
|
120 | 1 | 'data' => $data, |
|
121 | 'header' => [ |
||
122 | 1 | 'Authorization:'.$sign, |
|
123 | 1 | 'Content-Type: application/json', |
|
124 | 1 | ], |
|
125 | 1 | ]; |
|
126 | |||
127 | 1 | return self::sendRequest($req); |
|
128 | } |
||
129 | |||
130 | /** |
||
131 | * 目录列表. |
||
132 | * |
||
133 | * @param string $bucketName bucket名称 |
||
134 | * @param string $path 目录路径,sdk会补齐末尾的 '/' |
||
135 | * @param int $num 拉取的总数 |
||
136 | * @param string $pattern eListBoth,ListDirOnly,eListFileOnly 默认both |
||
137 | * @param int $order 默认正序(=0), 填1为反序, |
||
138 | * @param string $context 透传字段,用于翻页,前端不需理解,需要往前/往后翻页则透传回来 |
||
139 | * |
||
140 | * @return array |
||
141 | */ |
||
142 | 1 | View Code Duplication | public static function listFolder( |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
143 | $bucketName, $path, $num = 20, |
||
144 | $pattern = 'eListBoth', $order = 0, |
||
145 | $context = null) |
||
146 | { |
||
147 | 1 | $path = self::normalizerPath($path, true); |
|
148 | |||
149 | 1 | return self::listBase($bucketName, $path, $num, |
|
150 | 1 | $pattern, $order, $context); |
|
151 | } |
||
152 | |||
153 | /** |
||
154 | * 目录列表(前缀搜索). |
||
155 | * |
||
156 | * @param string $bucketName bucket名称 |
||
157 | * @param string $prefix 列出含此前缀的所有文件 |
||
158 | * @param int $num 拉取的总数 |
||
159 | * @param string $pattern eListBoth(默认),ListDirOnly,eListFileOnly |
||
160 | * @param int $order 默认正序(=0), 填1为反序, |
||
161 | * @param string $context 透传字段,用于翻页,前端不需理解,需要往前/往后翻页则透传回来 |
||
162 | * |
||
163 | * @return array |
||
164 | */ |
||
165 | View Code Duplication | public static function prefixSearch( |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
166 | $bucketName, $prefix, $num = 20, |
||
167 | $pattern = 'eListBoth', $order = 0, |
||
168 | $context = null) |
||
169 | { |
||
170 | $path = self::normalizerPath($prefix); |
||
171 | |||
172 | return self::listBase($bucketName, $path, $num, |
||
173 | $pattern, $order, $context); |
||
174 | } |
||
175 | |||
176 | /** |
||
177 | * 目录更新. |
||
178 | * |
||
179 | * @param string $bucketName bucket名称 |
||
180 | * @param string $path 文件夹路径,SDK会补齐末尾的 '/' |
||
181 | * @param string $bizAttr 目录属性 |
||
182 | * |
||
183 | * @return array |
||
184 | */ |
||
185 | public static function updateFolder($bucketName, $path, $bizAttr = null) |
||
186 | { |
||
187 | $path = self::normalizerPath($path, true); |
||
188 | |||
189 | return self::updateBase($bucketName, $path, $bizAttr); |
||
190 | } |
||
191 | |||
192 | /** |
||
193 | * 查询目录信息. |
||
194 | * |
||
195 | * @param string $bucketName bucket名称 |
||
196 | * @param string $path 目录路径 |
||
197 | * |
||
198 | * @return array |
||
199 | */ |
||
200 | public static function statFolder($bucketName, $path) |
||
201 | { |
||
202 | $path = self::normalizerPath($path, true); |
||
203 | |||
204 | return self::statBase($bucketName, $path); |
||
205 | } |
||
206 | |||
207 | /** |
||
208 | * 删除目录. |
||
209 | * |
||
210 | * @param string $bucketName bucket名称 |
||
211 | * @param string $path 目录路径 |
||
212 | * 注意不能删除bucket下根目录/ |
||
213 | * |
||
214 | * @return array |
||
215 | */ |
||
216 | 1 | public static function delFolder($bucketName, $path) |
|
217 | { |
||
218 | 1 | $path = self::normalizerPath($path, true); |
|
219 | |||
220 | 1 | return self::delBase($bucketName, $path); |
|
221 | } |
||
222 | |||
223 | /** |
||
224 | * 更新文件. |
||
225 | * |
||
226 | * @param string $bucketName bucket名称 |
||
227 | * @param string $path 文件路径 |
||
228 | * @param null $bizAttr |
||
229 | * @param string $authority : eInvalid(继承Bucket的读写权限)/eWRPrivate(私有读写)/eWPrivateRPublic(公有读私有写) |
||
230 | * @param array $customer_headers_array 携带的用户自定义头域,包括 |
||
231 | * 'Cache-Control' => '*' |
||
232 | * 'Content-Type' => '*' |
||
233 | * 'Content-Disposition' => '*' |
||
234 | * 'Content-Language' => '*' |
||
235 | * 'x-cos-meta-自定义内容' => '*' |
||
236 | * |
||
237 | * @return array |
||
238 | */ |
||
239 | 1 | public static function update($bucketName, $path, |
|
240 | $bizAttr = null, $authority = null, $customer_headers_array = null) |
||
241 | { |
||
242 | 1 | $path = self::normalizerPath($path); |
|
243 | |||
244 | 1 | return self::updateBase($bucketName, $path, $bizAttr, $authority, $customer_headers_array); |
|
245 | } |
||
246 | |||
247 | /** |
||
248 | * 移动(重命名)文件. |
||
249 | * |
||
250 | * @param string $bucketName bucket名称 |
||
251 | * @param string $srcPath 源文件路径 |
||
252 | * @param string $dstPath 目的文件名(可以是单独文件名也可以是带目录的文件名) |
||
253 | * @param int $toOverWrite 是否覆盖(当目的文件名已经存在同名文件时是否覆盖) |
||
254 | * |
||
255 | * @return array |
||
256 | */ |
||
257 | 1 | public static function move($bucketName, $srcPath, $dstPath, $toOverWrite = 0) |
|
258 | { |
||
259 | 1 | $srcPath = self::normalizerPath($srcPath); |
|
260 | 1 | $dstPath = self::normalizerPath($dstPath); |
|
261 | |||
262 | 1 | $srcPath = self::cosUrlEncode($srcPath); |
|
263 | 1 | $url = self::generateResUrl($bucketName, $srcPath); |
|
264 | 1 | $sign = Auth::appSign_once($srcPath, $bucketName); |
|
265 | |||
266 | $data = [ |
||
267 | 1 | 'op' => 'move', |
|
268 | 1 | 'dest_fileid' => $dstPath, |
|
269 | 1 | 'to_over_write' => $toOverWrite, |
|
270 | 1 | ]; |
|
271 | |||
272 | 1 | $data = json_encode($data); |
|
273 | |||
274 | $req = [ |
||
275 | 1 | 'url' => $url, |
|
276 | 1 | 'method' => 'post', |
|
277 | 1 | 'timeout' => self::$timeout, |
|
278 | 1 | 'data' => $data, |
|
279 | 'header' => [ |
||
280 | 1 | 'Authorization: '.$sign, |
|
281 | 1 | 'Content-Type: application/json', |
|
282 | 1 | ], |
|
283 | 1 | ]; |
|
284 | |||
285 | 1 | return self::sendRequest($req); |
|
286 | } |
||
287 | |||
288 | /** |
||
289 | * 查询文件信息. |
||
290 | * |
||
291 | * @param string $bucketName bucket名称 |
||
292 | * @param string $path 文件路径 |
||
293 | * |
||
294 | * @return array |
||
295 | */ |
||
296 | 6 | public static function stat($bucketName, $path) |
|
297 | { |
||
298 | 6 | $path = self::normalizerPath($path); |
|
299 | |||
300 | 6 | return self::statBase($bucketName, $path); |
|
301 | } |
||
302 | |||
303 | /** |
||
304 | * 删除文件. |
||
305 | * |
||
306 | * @param string $bucketName |
||
307 | * @param string $path 文件路径 |
||
308 | * |
||
309 | * @return array |
||
310 | */ |
||
311 | 1 | public static function delFile($bucketName, $path) |
|
312 | { |
||
313 | 1 | $path = self::normalizerPath($path); |
|
314 | |||
315 | 1 | return self::delBase($bucketName, $path); |
|
316 | } |
||
317 | |||
318 | /** |
||
319 | * 内部方法, 上传文件. |
||
320 | * |
||
321 | * @param string $bucketName bucket名称 |
||
322 | * @param string $srcPath 本地文件路径 |
||
323 | * @param string $dstPath 上传的文件路径 |
||
324 | * @param string $bizAttr 文件属性 |
||
325 | * @param int $insertOnly 是否覆盖同名文件:0 覆盖,1:不覆盖 |
||
326 | * |
||
327 | * @return array |
||
328 | */ |
||
329 | 2 | private static function uploadfile($bucketName, $srcPath, $dstPath, $bizAttr = null, $insertOnly = null) |
|
330 | { |
||
331 | 2 | $srcPath = realpath($srcPath); |
|
332 | 2 | $dstPath = self::cosUrlEncode($dstPath); |
|
333 | |||
334 | 2 | View Code Duplication | if (filesize($srcPath) >= self::MAX_UNSLICE_FILE_SIZE) { |
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
335 | return [ |
||
336 | 'code' => self::COSAPI_PARAMS_ERROR, |
||
337 | 'message' => 'file '.$srcPath.' larger then 20M, please use upload_slice interface', |
||
338 | 'data' => [], ]; |
||
339 | } |
||
340 | |||
341 | 2 | $expired = self::time() + self::EXPIRED_SECONDS; |
|
342 | 2 | $url = self::generateResUrl($bucketName, $dstPath); |
|
343 | 2 | $sign = Auth::appSign($expired, $bucketName); |
|
344 | 2 | $sha1 = hash_file('sha1', $srcPath); |
|
345 | |||
346 | $data = [ |
||
347 | 2 | 'op' => 'upload', |
|
348 | 2 | 'sha' => $sha1, |
|
349 | 2 | 'biz_attr' => (isset($bizAttr) ? $bizAttr : ''), |
|
350 | 2 | ]; |
|
351 | |||
352 | 2 | if (function_exists('curl_file_create')) { |
|
353 | 2 | $data['filecontent'] = curl_file_create($srcPath); |
|
354 | 2 | } else { |
|
355 | $data['filecontent'] = '@'.$srcPath; |
||
356 | } |
||
357 | |||
358 | 2 | if (isset($insertOnly) && strlen($insertOnly) > 0) { |
|
359 | 2 | $data['insertOnly'] = (($insertOnly == 0 || $insertOnly == '0') ? 0 : 1); |
|
360 | 2 | } |
|
361 | |||
362 | $req = [ |
||
363 | 2 | 'url' => $url, |
|
364 | 2 | 'method' => 'post', |
|
365 | 2 | 'timeout' => self::$timeout, |
|
366 | 2 | 'data' => $data, |
|
367 | 'header' => [ |
||
368 | 2 | 'Authorization:'.$sign, |
|
369 | 2 | ], |
|
370 | 2 | ]; |
|
371 | |||
372 | 2 | return self::sendRequest($req); |
|
373 | } |
||
374 | |||
375 | /** |
||
376 | * 内部方法,上传文件. |
||
377 | * |
||
378 | * @param string $bucketName bucket名称 |
||
379 | * @param string $srcPath 本地文件路径 |
||
380 | * @param string $dstPath 上传的文件路径 |
||
381 | * @param string $bizAttr 文件属性 |
||
382 | * @param string $sliceSize 分片大小 |
||
383 | * @param int $insertOnly 是否覆盖同名文件:0 覆盖,1:不覆盖 |
||
384 | * |
||
385 | * @return array |
||
386 | */ |
||
387 | private static function upload_slice( |
||
388 | $bucketName, $srcPath, $dstPath, |
||
389 | $bizAttr = null, $sliceSize = null, $insertOnly = null) |
||
390 | { |
||
391 | $srcPath = realpath($srcPath); |
||
392 | $fileSize = filesize($srcPath); |
||
393 | $dstPath = self::cosUrlEncode($dstPath); |
||
394 | |||
395 | $expired = self::time() + self::EXPIRED_SECONDS; |
||
396 | $url = self::generateResUrl($bucketName, $dstPath); |
||
397 | $sign = Auth::appSign($expired, $bucketName); |
||
398 | $sha1 = hash_file('sha1', $srcPath); |
||
399 | |||
400 | $ret = self::upload_prepare( |
||
401 | $fileSize, $sha1, $sliceSize, |
||
402 | $sign, $url, $bizAttr, $insertOnly); |
||
403 | |||
404 | if ($ret['code'] != 0) { |
||
405 | return $ret; |
||
406 | } |
||
407 | |||
408 | if (isset($ret['data']) |
||
409 | && isset($ret['data']['url'])) { |
||
410 | //秒传命中,直接返回了url |
||
411 | return $ret; |
||
412 | } |
||
413 | |||
414 | $sliceSize = $ret['data']['slice_size']; |
||
415 | if ($sliceSize > self::SLICE_SIZE_3M || |
||
416 | $sliceSize <= 0) { |
||
417 | $ret['code'] = self::COSAPI_PARAMS_ERROR; |
||
418 | $ret['message'] = 'illegal slice size'; |
||
419 | |||
420 | return $ret; |
||
421 | } |
||
422 | |||
423 | $session = $ret['data']['session']; |
||
424 | $offset = $ret['data']['offset']; |
||
425 | |||
426 | $sliceCnt = ceil($fileSize / $sliceSize); |
||
427 | // expired seconds for one slice mutiply by slice count |
||
428 | // will be the expired seconds for whole file |
||
429 | $expired = self::time() + (self::EXPIRED_SECONDS * $sliceCnt); |
||
430 | $sign = Auth::appSign($expired, $bucketName); |
||
431 | |||
432 | $ret = self::upload_data( |
||
433 | $fileSize, $sha1, $sliceSize, |
||
434 | $sign, $url, $srcPath, |
||
435 | $offset, $session); |
||
436 | |||
437 | return $ret; |
||
438 | } |
||
439 | |||
440 | /** |
||
441 | * 第一个分片控制消息. |
||
442 | * |
||
443 | * @param string $fileSize 文件大小 |
||
444 | * @param string $sha1 文件sha值 |
||
445 | * @param string $sliceSize 分片大小 |
||
446 | * @param string $sign 签名 |
||
447 | * @param string $url URL |
||
448 | * @param string $bizAttr 文件属性 |
||
449 | * @param string $insertOnly 同名文件是否覆盖 |
||
450 | * |
||
451 | * @return array |
||
452 | */ |
||
453 | private static function upload_prepare( |
||
454 | $fileSize, $sha1, $sliceSize, |
||
455 | $sign, $url, $bizAttr = null, $insertOnly = null) |
||
456 | { |
||
457 | $data = [ |
||
458 | 'op' => 'upload_slice', |
||
459 | 'filesize' => $fileSize, |
||
460 | 'sha' => $sha1, |
||
461 | ]; |
||
462 | |||
463 | if (isset($bizAttr) && strlen($bizAttr)) { |
||
464 | $data['biz_attr'] = $bizAttr; |
||
465 | } |
||
466 | |||
467 | if (isset($insertOnly)) { |
||
468 | $data['insertOnly'] = (($insertOnly == 0) ? 0 : 1); |
||
469 | } |
||
470 | |||
471 | if ($sliceSize <= self::SLICE_SIZE_3M) { |
||
472 | $data['slice_size'] = $sliceSize; |
||
473 | } else { |
||
474 | $data['slice_size'] = self::SLICE_SIZE_3M; |
||
475 | } |
||
476 | |||
477 | $req = [ |
||
478 | 'url' => $url, |
||
479 | 'method' => 'post', |
||
480 | 'timeout' => self::$timeout, |
||
481 | 'data' => $data, |
||
482 | 'header' => [ |
||
483 | 'Authorization:'.$sign, |
||
484 | ], |
||
485 | ]; |
||
486 | |||
487 | $ret = self::sendRequest($req); |
||
488 | |||
489 | return $ret; |
||
490 | } |
||
491 | |||
492 | /** |
||
493 | * 分片上传. |
||
494 | * |
||
495 | * @param int $fileSize 文件大小 |
||
496 | * @param string $sha1 文件sha值 |
||
497 | * @param int $sliceSize 文件分片大小 |
||
498 | * @param string $sign 签名 |
||
499 | * @param string $url url |
||
500 | * @param string $srcPath 源文件路径 |
||
501 | * @param int $offset 文件偏移offset |
||
502 | * @param string $session session |
||
503 | * |
||
504 | * @return array |
||
505 | */ |
||
506 | private static function upload_data( |
||
507 | $fileSize, $sha1, $sliceSize, |
||
508 | $sign, $url, $srcPath, |
||
509 | $offset, $session) |
||
510 | { |
||
511 | while ($fileSize > $offset) { |
||
512 | $filecontent = file_get_contents( |
||
513 | $srcPath, false, null, |
||
514 | $offset, $sliceSize); |
||
515 | |||
516 | View Code Duplication | if ($filecontent === false) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
517 | return [ |
||
518 | 'code' => self::COSAPI_PARAMS_ERROR, |
||
519 | 'message' => 'read file '.$srcPath.' error', |
||
520 | 'data' => [], |
||
521 | ]; |
||
522 | } |
||
523 | |||
524 | $boundary = '---------------------------'.substr(md5(mt_rand()), 0, 10); |
||
525 | $data = self::generateSliceBody( |
||
526 | $filecontent, $offset, $sha1, |
||
527 | $session, basename($srcPath), $boundary); |
||
528 | |||
529 | $req = [ |
||
530 | 'url' => $url, |
||
531 | 'method' => 'post', |
||
532 | 'timeout' => self::$timeout, |
||
533 | 'data' => $data, |
||
534 | 'header' => [ |
||
535 | 'Authorization:'.$sign, |
||
536 | 'Content-Type: multipart/form-data; boundary='.$boundary, |
||
537 | ], |
||
538 | ]; |
||
539 | |||
540 | $retry_times = 0; |
||
541 | do { |
||
542 | $ret = self::sendRequest($req); |
||
543 | if ($ret['code'] == 0) { |
||
544 | break; |
||
545 | } |
||
546 | $retry_times++; |
||
547 | } while ($retry_times < self::MAX_RETRY_TIMES); |
||
548 | |||
549 | if ($ret['code'] != 0) { |
||
550 | return $ret; |
||
551 | } |
||
552 | |||
553 | if (!empty($ret['data']['session'])) { |
||
554 | $session = $ret['data']['session']; |
||
555 | } |
||
556 | |||
557 | $offset += $sliceSize; |
||
558 | } |
||
559 | |||
560 | return $ret; |
||
0 ignored issues
–
show
The variable
$ret does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
561 | } |
||
562 | |||
563 | /** |
||
564 | * 构造分片body体. |
||
565 | * |
||
566 | * @param string $fileContent 文件内容 |
||
567 | * @param string $offset 文件偏移 |
||
568 | * @param string $sha 文件sha值 |
||
569 | * @param string $session session |
||
570 | * @param string $fileName 文件名 |
||
571 | * @param string $boundary 分隔符 |
||
572 | * |
||
573 | * @return string |
||
574 | */ |
||
575 | private static function generateSliceBody( |
||
576 | $fileContent, $offset, $sha, |
||
0 ignored issues
–
show
|
|||
577 | $session, $fileName, $boundary) |
||
578 | { |
||
579 | $formdata = ''; |
||
580 | |||
581 | $formdata .= '--'.$boundary."\r\n"; |
||
582 | $formdata .= "content-disposition: form-data; name=\"op\"\r\n\r\nupload_slice\r\n"; |
||
583 | |||
584 | $formdata .= '--'.$boundary."\r\n"; |
||
585 | $formdata .= "content-disposition: form-data; name=\"offset\"\r\n\r\n".$offset."\r\n"; |
||
586 | |||
587 | $formdata .= '--'.$boundary."\r\n"; |
||
588 | $formdata .= "content-disposition: form-data; name=\"session\"\r\n\r\n".$session."\r\n"; |
||
589 | |||
590 | $formdata .= '--'.$boundary."\r\n"; |
||
591 | $formdata .= 'content-disposition: form-data; name="fileContent"; filename="'.$fileName."\"\r\n"; |
||
592 | $formdata .= "content-type: application/octet-stream\r\n\r\n"; |
||
593 | |||
594 | $data = $formdata.$fileContent."\r\n--".$boundary."--\r\n"; |
||
595 | |||
596 | return $data; |
||
597 | } |
||
598 | |||
599 | /** |
||
600 | * 内部公共函数. |
||
601 | * |
||
602 | * @param string $bucketName bucket名称 |
||
603 | * @param string $path 文件夹路径 |
||
604 | * @param int $num 拉取的总数 |
||
605 | * @param string $pattern eListBoth(默认),ListDirOnly,eListFileOnly |
||
606 | * @param int $order 默认正序(=0), 填1为反序, |
||
607 | * @param string $context 在翻页查询时候用到 |
||
608 | * |
||
609 | * @return array |
||
610 | */ |
||
611 | 1 | private static function listBase( |
|
612 | $bucketName, $path, $num = 20, |
||
613 | $pattern = 'eListBoth', $order = 0, $context = null) |
||
614 | { |
||
615 | 1 | $path = self::cosUrlEncode($path); |
|
616 | 1 | $expired = self::time() + self::EXPIRED_SECONDS; |
|
617 | 1 | $url = self::generateResUrl($bucketName, $path); |
|
618 | 1 | $sign = Auth::appSign($expired, $bucketName); |
|
619 | |||
620 | $data = [ |
||
621 | 1 | 'op' => 'list', |
|
622 | 1 | ]; |
|
623 | |||
624 | 1 | if (self::isPatternValid($pattern) == false) { |
|
0 ignored issues
–
show
|
|||
625 | return [ |
||
626 | 'code' => self::COSAPI_PARAMS_ERROR, |
||
627 | 'message' => 'parameter pattern invalid', |
||
628 | ]; |
||
629 | } |
||
630 | 1 | $data['pattern'] = $pattern; |
|
631 | |||
632 | 1 | if ($order != 0 && $order != 1) { |
|
633 | return [ |
||
634 | 'code' => self::COSAPI_PARAMS_ERROR, |
||
635 | 'message' => 'parameter order invalid', |
||
636 | ]; |
||
637 | } |
||
638 | 1 | $data['order'] = $order; |
|
639 | |||
640 | 1 | if ($num < 0 || $num > 199) { |
|
641 | return [ |
||
642 | 'code' => self::COSAPI_PARAMS_ERROR, |
||
643 | 'message' => 'parameter num invalid, num need less then 200', |
||
644 | ]; |
||
645 | } |
||
646 | 1 | $data['num'] = $num; |
|
647 | |||
648 | 1 | if (isset($context)) { |
|
649 | $data['context'] = $context; |
||
650 | } |
||
651 | |||
652 | 1 | $url = $url.'?'.http_build_query($data); |
|
653 | |||
654 | $req = [ |
||
655 | 1 | 'url' => $url, |
|
656 | 1 | 'method' => 'get', |
|
657 | 1 | 'timeout' => self::$timeout, |
|
658 | 'header' => [ |
||
659 | 1 | 'Authorization:'.$sign, |
|
660 | 1 | ], |
|
661 | 1 | ]; |
|
662 | |||
663 | 1 | return self::sendRequest($req); |
|
664 | } |
||
665 | |||
666 | /** |
||
667 | * 内部公共方法(更新文件和更新文件夹). |
||
668 | * |
||
669 | * @param string $bucketName bucket名称 |
||
670 | * @param string $path 路径 |
||
671 | * @param string $bizAttr 文件/目录属性 |
||
672 | * @param string $authority : eInvalid/eWRPrivate(私有)/eWPrivateRPublic(公有读写) |
||
673 | * @param array $custom_headers_array 携带的用户自定义头域,包括 |
||
674 | * 'Cache-Control' => '*' |
||
675 | * 'Content-Type' => '*' |
||
676 | * 'Content-Disposition' => '*' |
||
677 | * 'Content-Language' => '*' |
||
678 | * 'x-cos-meta-自定义内容' => '*' |
||
679 | * |
||
680 | * @return array|mixed |
||
681 | */ |
||
682 | 1 | private static function updateBase($bucketName, $path, |
|
683 | $bizAttr = null, $authority = null, $custom_headers_array = null) |
||
684 | { |
||
685 | 1 | $path = self::cosUrlEncode($path); |
|
686 | |||
687 | 1 | $url = self::generateResUrl($bucketName, $path); |
|
688 | 1 | $sign = Auth::appSign_once( |
|
689 | 1 | $path, $bucketName); |
|
690 | |||
691 | $data = [ |
||
692 | 1 | 'op' => 'update', |
|
693 | 1 | ]; |
|
694 | |||
695 | 1 | $flag = 0; |
|
696 | 1 | if (isset($bizAttr)) { |
|
697 | $data['biz_attr'] = $bizAttr; |
||
698 | $flag = $flag | 0x01; |
||
699 | } |
||
700 | |||
701 | 1 | if (isset($authority) && strlen($authority) > 0) { |
|
702 | 1 | if (self::isAuthorityValid($authority) == false) { |
|
0 ignored issues
–
show
|
|||
703 | return [ |
||
704 | 'code' => self::COSAPI_PARAMS_ERROR, |
||
705 | 'message' => 'parameter authority invalid', |
||
706 | ]; |
||
707 | } |
||
708 | |||
709 | 1 | $data['authority'] = $authority; |
|
710 | 1 | $flag = $flag | 0x80; |
|
711 | 1 | } |
|
712 | |||
713 | 1 | if (isset($custom_headers_array)) { |
|
714 | $data['custom_headers'] = []; |
||
715 | self::add_customer_header($data['custom_headers'], $custom_headers_array); |
||
716 | $flag = $flag | 0x40; |
||
717 | } |
||
718 | |||
719 | 1 | if ($flag != 0 && $flag != 1) { |
|
720 | 1 | $data['flag'] = $flag; |
|
721 | 1 | } |
|
722 | |||
723 | 1 | $data = json_encode($data); |
|
724 | |||
725 | $req = [ |
||
726 | 1 | 'url' => $url, |
|
727 | 1 | 'method' => 'post', |
|
728 | 1 | 'timeout' => self::$timeout, |
|
729 | 1 | 'data' => $data, |
|
730 | 'header' => [ |
||
731 | 1 | 'Authorization:'.$sign, |
|
732 | 1 | 'Content-Type: application/json', |
|
733 | 1 | ], |
|
734 | 1 | ]; |
|
735 | |||
736 | 1 | return self::sendRequest($req); |
|
737 | } |
||
738 | |||
739 | /** |
||
740 | * 内部方法. |
||
741 | * |
||
742 | * @param string $bucketName bucket名称 |
||
743 | * @param string $path 文件/目录路径 |
||
744 | * |
||
745 | * @return array |
||
746 | */ |
||
747 | 6 | private static function statBase($bucketName, $path) |
|
748 | { |
||
749 | 6 | $path = self::cosUrlEncode($path); |
|
750 | 6 | $expired = self::time() + self::EXPIRED_SECONDS; |
|
751 | 6 | $url = self::generateResUrl($bucketName, $path); |
|
752 | 6 | $sign = Auth::appSign($expired, $bucketName); |
|
753 | |||
754 | $data = [ |
||
755 | 6 | 'op' => 'stat', |
|
756 | 6 | ]; |
|
757 | |||
758 | 6 | $url = $url.'?'.http_build_query($data); |
|
759 | |||
760 | $req = [ |
||
761 | 6 | 'url' => $url, |
|
762 | 6 | 'method' => 'get', |
|
763 | 6 | 'timeout' => self::$timeout, |
|
764 | 'header' => [ |
||
765 | 6 | 'Authorization:'.$sign, |
|
766 | 6 | ], |
|
767 | 6 | ]; |
|
768 | |||
769 | 6 | return self::sendRequest($req); |
|
770 | } |
||
771 | |||
772 | /** |
||
773 | * 内部私有方法. |
||
774 | * |
||
775 | * @param string $bucketName bucket名称 |
||
776 | * @param string $path 文件/目录路径路径 |
||
777 | * |
||
778 | * @return array |
||
779 | */ |
||
780 | 2 | private static function delBase($bucketName, $path) |
|
781 | { |
||
782 | 2 | if ($path == '/') { |
|
783 | return [ |
||
784 | 'code' => self::COSAPI_PARAMS_ERROR, |
||
785 | 'message' => 'can not delete bucket using api! go to http://console.qcloud.com/cos to operate bucket', |
||
786 | ]; |
||
787 | } |
||
788 | |||
789 | 2 | $path = self::cosUrlEncode($path); |
|
790 | |||
791 | 2 | $url = self::generateResUrl($bucketName, $path); |
|
792 | 2 | $sign = Auth::appSign_once( |
|
793 | 2 | $path, $bucketName); |
|
794 | |||
795 | $data = [ |
||
796 | 2 | 'op' => 'delete', |
|
797 | 2 | ]; |
|
798 | |||
799 | 2 | $data = json_encode($data); |
|
800 | |||
801 | $req = [ |
||
802 | 2 | 'url' => $url, |
|
803 | 2 | 'method' => 'post', |
|
804 | 2 | 'timeout' => self::$timeout, |
|
805 | 2 | 'data' => $data, |
|
806 | 'header' => [ |
||
807 | 2 | 'Authorization:'.$sign, |
|
808 | 2 | 'Content-Type: application/json', |
|
809 | 2 | ], |
|
810 | 2 | ]; |
|
811 | |||
812 | 2 | return self::sendRequest($req); |
|
813 | } |
||
814 | |||
815 | /** |
||
816 | * 内部公共方法, 路径编码 |
||
817 | * |
||
818 | * @param string $path 待编码路径 |
||
819 | * |
||
820 | * @return mixed |
||
821 | */ |
||
822 | 14 | private static function cosUrlEncode($path) |
|
823 | { |
||
824 | 14 | return str_replace('%2F', '/', rawurlencode($path)); |
|
825 | } |
||
826 | |||
827 | /** |
||
828 | * 内部公共方法, 构造URL. |
||
829 | * |
||
830 | * @param string $bucketName |
||
831 | * @param string $dstPath |
||
832 | * |
||
833 | * @return string |
||
834 | */ |
||
835 | 14 | private static function generateResUrl($bucketName, $dstPath) |
|
836 | { |
||
837 | 14 | return Conf::API_COSAPI_END_POINT.Conf::getAppId().'/'.$bucketName.$dstPath; |
|
838 | } |
||
839 | |||
840 | /** |
||
841 | * 内部公共方法, 发送消息. |
||
842 | * |
||
843 | * @param array $req |
||
844 | * |
||
845 | * @return array |
||
846 | */ |
||
847 | 14 | private static function sendRequest($req) |
|
848 | { |
||
849 | 14 | $rsp = Http::send($req); |
|
850 | |||
851 | 14 | $ret = json_decode($rsp, true); |
|
852 | |||
853 | 14 | if ($ret) { |
|
854 | 14 | if (0 === $ret['code']) { |
|
855 | return $ret; |
||
856 | } else { |
||
857 | return [ |
||
858 | 14 | 'code' => $ret['code'], |
|
859 | 14 | 'message' => $ret['message'], |
|
860 | 14 | 'data' => [], |
|
861 | 14 | ]; |
|
862 | } |
||
863 | } else { |
||
864 | return [ |
||
865 | 'code' => self::COSAPI_NETWORK_ERROR, |
||
866 | 'message' => $rsp, |
||
867 | 'data' => [], |
||
868 | ]; |
||
869 | } |
||
870 | } |
||
871 | |||
872 | /** |
||
873 | * 设置分片大小. |
||
874 | * |
||
875 | * @param string $sliceSize |
||
876 | * |
||
877 | * @return int |
||
878 | */ |
||
879 | private static function getSliceSize($sliceSize) |
||
880 | { |
||
881 | $size = self::SLICE_SIZE_1M; |
||
882 | if (!isset($sliceSize)) { |
||
883 | return $size; |
||
884 | } |
||
885 | |||
886 | if ($sliceSize <= self::SLICE_SIZE_512K) { |
||
887 | $size = self::SLICE_SIZE_512K; |
||
888 | } elseif ($sliceSize <= self::SLICE_SIZE_1M) { |
||
889 | $size = self::SLICE_SIZE_1M; |
||
890 | } elseif ($sliceSize <= self::SLICE_SIZE_2M) { |
||
891 | $size = self::SLICE_SIZE_2M; |
||
892 | } else { |
||
893 | $size = self::SLICE_SIZE_3M; |
||
894 | } |
||
895 | |||
896 | return $size; |
||
897 | } |
||
898 | |||
899 | /** |
||
900 | * 内部方法, 规整文件路径. |
||
901 | * |
||
902 | * @param string $path 文件路径 |
||
903 | * @param bool $isfolder 是否为文件夹 |
||
904 | * |
||
905 | * @return string |
||
906 | */ |
||
907 | 12 | private static function normalizerPath($path, $isfolder = false) |
|
908 | { |
||
909 | 12 | if (preg_match('/^\//', $path) == 0) { |
|
910 | 12 | $path = '/'.$path; |
|
911 | 12 | } |
|
912 | |||
913 | 12 | if ($isfolder == true) { |
|
0 ignored issues
–
show
|
|||
914 | 3 | if (preg_match('/\/$/', $path) == 0) { |
|
915 | 3 | $path = $path.'/'; |
|
916 | 3 | } |
|
917 | 3 | } |
|
918 | |||
919 | 12 | return $path; |
|
920 | } |
||
921 | |||
922 | /** |
||
923 | * 判断authority值是否正确. |
||
924 | * |
||
925 | * @param string $authority |
||
926 | * |
||
927 | * @return bool |
||
928 | */ |
||
929 | 1 | private static function isAuthorityValid($authority) |
|
930 | { |
||
931 | if ($authority == 'eInvalid' |
||
932 | 1 | || $authority == 'eWRPrivate' |
|
933 | 1 | || $authority == 'eWPrivateRPublic') { |
|
934 | 1 | return true; |
|
935 | } |
||
936 | |||
937 | return false; |
||
938 | } |
||
939 | |||
940 | /** |
||
941 | * 判断pattern值是否正确. |
||
942 | * |
||
943 | * |
||
944 | * @param string $pattern |
||
945 | * |
||
946 | * @return bool |
||
947 | */ |
||
948 | 1 | private static function isPatternValid($pattern) |
|
949 | { |
||
950 | if ($pattern == 'eListBoth' |
||
951 | 1 | || $pattern == 'eListDirOnly' |
|
952 | 1 | || $pattern == 'eListFileOnly') { |
|
953 | 1 | return true; |
|
954 | } |
||
955 | |||
956 | return false; |
||
957 | } |
||
958 | |||
959 | /** |
||
960 | * 判断是否符合自定义属性. |
||
961 | * |
||
962 | * @param string $key |
||
963 | * |
||
964 | * @return bool |
||
965 | */ |
||
966 | private static function isCustomer_header($key) |
||
967 | { |
||
968 | if ($key == 'Cache-Control' |
||
969 | || $key == 'Content-Type' |
||
970 | || $key == 'Content-Disposition' |
||
971 | || $key == 'Content-Language' |
||
972 | || substr($key, 0, strlen('x-cos-meta-')) == 'x-cos-meta-') { |
||
973 | return true; |
||
974 | } |
||
975 | |||
976 | return false; |
||
977 | } |
||
978 | |||
979 | /** |
||
980 | * 增加自定义属性到data中. |
||
981 | * |
||
982 | * @param array $data |
||
983 | * @param array $customer_headers_array |
||
984 | */ |
||
985 | private static function add_customer_header(&$data, &$customer_headers_array) |
||
986 | { |
||
987 | if (count($customer_headers_array) < 1) { |
||
988 | return; |
||
989 | } |
||
990 | foreach ($customer_headers_array as $key=>$value) { |
||
991 | if (self::isCustomer_header($key)) { |
||
992 | $data[$key] = $value; |
||
993 | } |
||
994 | } |
||
995 | } |
||
996 | } |
||
997 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.