PluginProbe
InfiniteWP Client / trunk
InfiniteWP Client vtrunk
1.13.10 1.13.7 trunk 0.1.4 0.1.5 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.1.0 1.1.1 1.1.10 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.1.9 1.11.0 1.11.1 1.12.1 1.12.3 All 92 releases
iwp-client / lib / dropbox.php

dropbox.php in InfiniteWP Client trunk, at lib/dropbox.php

349 lines 16.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if ( ! defined('ABSPATH') )
4 die();
5 class IWP_Dropbox {
6 const API_URL = 'https://api.dropbox.com/';
7 const API_CONTENT_URL = 'https://api-content.dropbox.com/';
8 const API_WWW_URL = 'https://www.dropbox.com/';
9 const API_VERSION_URL = '1/';
10
11 private $root;
12 private $ProgressFunction = false;
13 private $oauth_app_key;
14 private $oauth_app_secret;
15 private $oauth_token;
16 private $oauth_token_secret;
17
18 public function __construct($oauth_app_key, $oauth_app_secret, $dropbox=false) {
19 $this->oauth_app_key = $oauth_app_key;
20 $this->oauth_app_secret = $oauth_app_secret;
21
22 if ($dropbox)
23 $this->root = 'dropbox';
24 else
25 $this->root = 'sandbox';
26 }
27
28 public function setOAuthTokens($token,$secret) {
29 $this->oauth_token = $token;
30 $this->oauth_token_secret = $secret;
31 }
32
33 public function setProgressFunction($function=null) {
34 if (function_exists($function))
35 $this->ProgressFunction = $function;
36 else
37 $this->ProgressFunction = false;
38 }
39
40 public function accountInfo(){
41 $url = self::API_URL.self::API_VERSION_URL.'account/info';
42 return $this->request($url);
43 }
44
45 public function upload($file, $path = '',$overwrite=true){
46 $file = str_replace("\\", "/",$file);
47 if (!is_readable($file) or !is_file($file))
48 throw new IWP_DropboxException("Error: File \"$file\" is not readable or doesn't exist.");
49 $filesize=iwp_mmb_get_file_size($file);
50 if ($filesize < (1024*1024*50)) { //chunk transfer on bigger uploads <50MB
51 $filehandle = fopen($file,'r');
52 $url = self::API_CONTENT_URL.self::API_VERSION_URL.'files_put/'.$this->root.'/'.trim($path, '/');
53 $output = $this->request($url, array('overwrite' => ($overwrite)? 'true' : 'false'), 'PUT', $filehandle, $filesize);
54 fclose($filehandle);
55 } else {//chunk transfer on bigger uploads >50MB
56 $output = $this->chunked_upload_single_call($file, $path,$overwrite);
57 }
58 return $output;
59 }
60
61 public function chunked_upload_single_call($file, $path = '',$overwrite=true){
62 $file = str_replace("\\", "/",$file);
63 if (!is_readable($file) or !is_file($file))
64 throw new IWP_DropboxException("Error: File \"$file\" is not readable or doesn't exist.");
65 $file_handle=fopen($file,'r');
66 $uploadid=null;
67 $offset=0;
68 $ProgressFunction=null;
69 while ($data=fread($file_handle, (1024*1024*30))) { //1024*1024*30 = 30MB
70 iwp_mmb_auto_print('dropbox_chucked_upload');
71 $chunkHandle = fopen('php://memory', 'rw');
72 fwrite($chunkHandle,$data);
73 rewind($chunkHandle);
74 //overwrite progress function
75 if (!empty($this->ProgressFunction) and function_exists($this->ProgressFunction)) {
76 $ProgressFunction=$this->ProgressFunction;
77 $this->ProgressFunction=false;
78 }
79 $url = self::API_CONTENT_URL.self::API_VERSION_URL.'chunked_upload';
80 $output = $this->request($url, array('upload_id' => $uploadid,'offset'=>$offset), 'PUT', $chunkHandle, strlen($data));
81 fclose($chunkHandle);
82 if ($ProgressFunction) {
83 call_user_func($ProgressFunction,0,0,0,$offset);
84 $this->ProgressFunction=$ProgressFunction;
85 }
86 //args for next chunk
87 $offset=$output['offset'];
88 $uploadid=$output['upload_id'];
89 fseek($file_handle,$offset);
90 }
91 fclose($file_handle);
92 $url = self::API_CONTENT_URL.self::API_VERSION_URL.'commit_chunked_upload/'.$this->root.'/'.trim($path, '/');
93 return $this->request($url, array('overwrite' => ($overwrite)? 'true' : 'false','upload_id'=>$uploadid), 'POST');
94 }
95
96 public function chunked_upload($file, $path = '',$overwrite=true,$uploadid = null,$offset = 0, $readSize = 0, $isCommit = false){//works for multi-call alone
97
98 $file = str_replace("\\", "/",$file);
99 if (!is_readable($file) or !is_file($file))
100 throw new IWP_DropboxException("Error: File \"$file\" is not readable or doesn't exist.");
101 $file_handle=fopen($file,'r');
102 fseek($file_handle,$offset);
103 /* $uploadid=null;
104 $offset=0; */
105 $ProgressFunction=null;
106
107
108 if($data=fread($file_handle, ($readSize))) { //1024*1024*30 = 30MB
109 //iwp_mmb_auto_print('dropbox_chucked_upload');
110 $chunkHandle = fopen('php://temp', 'rw');
111 fwrite($chunkHandle,$data);
112 rewind($chunkHandle);
113 //overwrite progress function
114 if (!empty($this->ProgressFunction) and function_exists($this->ProgressFunction)) {
115 $ProgressFunction=$this->ProgressFunction;
116 $this->ProgressFunction=false;
117 }
118
119 $url = self::API_CONTENT_URL.self::API_VERSION_URL.'chunked_upload';
120 $output = $this->request($url, array('upload_id' => $uploadid,'offset'=>$offset), 'PUT', $chunkHandle, strlen($data));
121 fclose($chunkHandle);
122
123 if ($ProgressFunction) {
124 call_user_func($ProgressFunction,0,0,0,$offset);
125 $this->ProgressFunction=$ProgressFunction;
126 }
127
128 //args for next chunk
129 $offset=$output['offset'];
130 $uploadid=$output['upload_id'];
131 //fseek($file_handle,$offset);
132 }
133 fclose($file_handle);
134 if($isCommit)
135 {
136 $url = self::API_CONTENT_URL.self::API_VERSION_URL.'commit_chunked_upload/'.$this->root.'/'.trim($path, '/');
137 $output = $this->request($url, array('overwrite' => ($overwrite)? 'true' : 'false','upload_id'=>$uploadid), 'POST');
138 }
139 return $output;
140 }
141
142 public function download($path, $file, $echo=false){
143 $url = self::API_CONTENT_URL.self::API_VERSION_URL.'files/'.$this->root.'/'.trim($path,'/');
144 if (!$echo){
145 $handle = fopen($file, 'w');
146 if($handle === false){
147 throw new IWP_DropboxException('Error while trying to open the file('.$file.') for writing');
148 }
149 $this->request($url,'','GET_DOWNLOAD_IN_FILE', $handle);
150 fclose($handle);
151 }
152 else
153 $this->request($url,'','GET','','',true);
154 }
155
156 public function metadata($path = '', $listContents = true, $fileLimit = 10000){
157 $url = self::API_URL.self::API_VERSION_URL.'metadata/'.$this->root.'/'.trim($path,'/');
158 return $this->request($url, array('list' => ($listContents)? 'true' : 'false', 'file_limit' => $fileLimit));
159 }
160
161 public function search($path = '', $query='' , $fileLimit = 1000){
162 if (strlen($query)>=3)
163 throw new IWP_DropboxException("Error: Query \"$query\" must three characters long.");
164 $url = self::API_URL.self::API_VERSION_URL.'search/'.$this->root.'/'.trim($path,'/');
165 return $this->request($url, array('query' => $query, 'file_limit' => $fileLimit));
166 }
167
168 public function shares($path = ''){
169 $url = self::API_URL.self::API_VERSION_URL.'shares/'.$this->root.'/'.trim($path,'/');
170 return $this->request($url);
171 }
172
173 public function media($path = ''){
174 $url = self::API_URL.self::API_VERSION_URL.'media/'.$this->root.'/'.trim($path,'/');
175 return $this->request($url);
176 }
177
178 public function fileopsDelete($path){
179 $url = self::API_URL.self::API_VERSION_URL.'fileops/delete';
180 return $this->request($url, array('path' => '/'.trim($path,'/'), 'root' => $this->root));
181 }
182
183 public function fileopsCreate_folder($path){
184 $url = self::API_URL.self::API_VERSION_URL.'fileops/create_folder';
185 return $this->request($url, array('path' => '/'.trim($path,'/'), 'root' => $this->root));
186 }
187
188 public function oAuthAuthorize($callback_url) {
189 $headers[] = 'Authorization: OAuth oauth_version="1.0", oauth_signature_method="PLAINTEXT", oauth_consumer_key="'.$this->oauth_app_key.'", oauth_signature="'.$this->oauth_app_secret.'&"';
190 $ch = curl_init();
191 curl_setopt($ch, CURLOPT_URL, self::API_URL . self::API_VERSION_URL . 'oauth/request_token' );
192 curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
193 curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
194 curl_setopt($ch, CURLOPT_SSLVERSION,1);
195 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
196 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
197 if (is_file(dirname(__FILE__).'/cacert.pem')){
198 curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__).'/cacert.pem');
199 }
200 curl_setopt($ch, CURLOPT_AUTOREFERER , true);
201 curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
202 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
203 $content = curl_exec($ch);
204 $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
205 if ($status>=200 and $status<300 and 0==curl_errno($ch) ) {
206 parse_str($content, $oauth_token);
207 } else {
208 $output = json_decode($content, true);
209 if(isset($output['error']) && is_string($output['error'])) $message = $output['error'];
210 elseif(isset($output['error']['hash']) && $output['error']['hash'] != '') $message = (string) $output['error']['hash'];
211 elseif (0!=curl_errno($ch)) $message = '('.curl_errno($ch).') '.curl_error($ch);
212 else $message = '('.$status.') Invalid response.';
213 throw new IWP_DropboxException($message);
214 }
215 curl_close($ch);
216 return array( 'authurl' => self::API_WWW_URL . self::API_VERSION_URL . 'oauth/authorize?oauth_token='.$oauth_token['oauth_token'].'&oauth_callback='.urlencode($callback_url),
217 'oauth_token' => $oauth_token['oauth_token'],
218 'oauth_token_secret'=> $oauth_token['oauth_token_secret'] );
219 }
220
221 public function oAuthAccessToken($oauth_token, $oauth_token_secret) {
222 $headers[] = 'Authorization: OAuth oauth_version="1.0", oauth_signature_method="PLAINTEXT", oauth_consumer_key="'.$this->oauth_app_key.'", oauth_token="'.$oauth_token.'", oauth_signature="'.$this->oauth_app_secret.'&'.$oauth_token_secret.'"';
223 $ch = curl_init();
224 curl_setopt($ch, CURLOPT_URL, self::API_URL . self::API_VERSION_URL . 'oauth/access_token' );
225 curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
226 curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
227 curl_setopt($ch, CURLOPT_SSLVERSION,1);
228 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
229 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
230 if (is_file(dirname(__FILE__).'/cacert.pem')){
231 curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__).'/cacert.pem');
232 }
233 curl_setopt($ch, CURLOPT_AUTOREFERER , true);
234 curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
235 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
236 $content = curl_exec($ch);
237 $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
238 if ($status>=200 and $status<300 and 0==curl_errno($ch)) {
239 parse_str($content, $oauth_token);
240 $this->setOAuthTokens($oauth_token['oauth_token'], $oauth_token['oauth_token_secret']);
241 return $oauth_token;
242 } else {
243 $output = json_decode($content, true);
244 if(isset($output['error']) && is_string($output['error'])) $message = $output['error'];
245 elseif(isset($output['error']['hash']) && $output['error']['hash'] != '') $message = (string) $output['error']['hash'];
246 elseif (0!=curl_errno($ch)) $message = '('.curl_errno($ch).') '.curl_error($ch);
247 else $message = '('.$status.') Invalid response.';
248 throw new IWP_DropboxException($message);
249 }
250 }
251
252 private function request($url, $args = null, $method = 'GET', $filehandle = null, $filesize=0, $echo=false){
253 $args = (is_array($args)) ? $args : array();
254 $url = $this->url_encode($url);
255
256 /* Header*/
257 $headers[]='Authorization: OAuth oauth_version="1.0", oauth_signature_method="PLAINTEXT", oauth_consumer_key="'.$this->oauth_app_key.'", oauth_token="'.$this->oauth_token.'", oauth_signature="'.$this->oauth_app_secret.'&'.$this->oauth_token_secret.'"';
258 $headers[]='Expect:';
259
260 /* Build cURL Request */
261 $ch = curl_init();
262 if ($method == 'POST') {
263 curl_setopt($ch, CURLOPT_POST, true);
264 curl_setopt($ch, CURLOPT_POSTFIELDS, $args);
265 curl_setopt($ch, CURLOPT_URL, $url);
266 } elseif ($method == 'PUT') {
267 curl_setopt($ch,CURLOPT_PUT,true);
268 curl_setopt($ch,CURLOPT_INFILE,$filehandle);
269 curl_setopt($ch,CURLOPT_INFILESIZE,$filesize);
270 $args = (is_array($args)) ? '?'.http_build_query($args, '', '&') : $args;
271 curl_setopt($ch, CURLOPT_URL, $url.$args);
272 } elseif ($method == 'GET_DOWNLOAD_IN_FILE') {
273 curl_setopt($ch, CURLOPT_FILE, $filehandle);
274 $args = (is_array($args)) ? '?'.http_build_query($args, '', '&') : $args;
275 curl_setopt($ch, CURLOPT_URL, $url.$args);
276 } else {
277 $args = (is_array($args)) ? '?'.http_build_query($args, '', '&') : $args;
278 curl_setopt($ch, CURLOPT_URL, $url.$args);
279 }
280
281 curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
282 curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
283 if($method != 'GET_DOWNLOAD_IN_FILE'){
284 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
285 }
286 curl_setopt($ch, CURLOPT_SSLVERSION,1);
287 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
288 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
289 if (is_file(dirname(__FILE__).'/cacert.pem')){
290 curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__).'/cacert.pem');
291 }
292 curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
293 curl_setopt($ch, CURLINFO_HEADER_OUT, true);
294 if (!empty($this->ProgressFunction) and function_exists($this->ProgressFunction) and defined('CURLOPT_PROGRESSFUNCTION') and $method == 'PUT') {
295 curl_setopt($ch, CURLOPT_NOPROGRESS, false);
296 curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, $this->ProgressFunction);
297 curl_setopt($ch, CURLOPT_BUFFERSIZE, 512);
298 }
299 if ($echo) {
300 echo curl_exec($ch);
301 $output='';
302 } else {
303 $content = curl_exec($ch);
304 $output = json_decode($content, true);
305 }
306 $status = curl_getinfo($ch);
307
308 if (isset($output['error']) or $status['http_code']>=300 or $status['http_code']<200 or curl_errno($ch)>0) {
309 if(isset($output['error']) && is_string($output['error'])) $message = '('.$status['http_code'].') '.$output['error'];
310 elseif(isset($output['error']['hash']) && $output['error']['hash'] != '') $message = (string) '('.$status['http_code'].') '.$output['error']['hash'];
311 elseif (0!=curl_errno($ch)) $message = '('.curl_errno($ch).') '.curl_error($ch);
312 elseif ($status['http_code']==304) $message = '(304) The folder contents have not changed (relies on hash parameter).';
313 elseif ($status['http_code']==400) $message = '(400) Bad input parameter: '.strip_tags($content);
314 elseif ($status['http_code']==401) $message = '(401) Bad or expired token. This can happen if the user or Dropbox revoked or expired an access token. To fix, you should re-authenticate the user.';
315 elseif ($status['http_code']==403) $message = '(403) Bad OAuth request (wrong consumer key, bad nonce, expired timestamp, ...). Unfortunately, reauthenticating the user won\'t help here.';
316 elseif ($status['http_code']==404) $message = '(404) The file was not found at the specified path, or was not found at the specified rev.';
317 elseif ($status['http_code']==405) $message = '(405) Request method not expected (generally should be GET,PUT or POST).';
318 elseif ($status['http_code']==406) $message = '(406) There are too many file entries to return.';
319 elseif ($status['http_code']==411) $message = '(411) Chunked encoding was attempted for this upload, but is not supported by Dropbox.';
320 elseif ($status['http_code']==415) $message = '(415) The image is invalid and cannot be thumbnailed.';
321 elseif ($status['http_code']==503) $message = '(503) Your app is making too many requests and is being rate limited. 503s can trigger on a per-app or per-user basis.';
322 elseif ($status['http_code']==507) $message = '(507) User is over Dropbox storage quota.';
323 else $message = '('.$status['http_code'].') Invalid response.';
324 throw new IWP_DropboxException($message);
325 } else {
326 curl_close($ch);
327 if (!is_array($output))
328 return $content;
329 else
330 return $output;
331 }
332 }
333
334 private function url_encode($string) {
335 $string = str_replace('?','%3F',$string);
336 $string = str_replace('=','%3D',$string);
337 $string = str_replace(' ','%20',$string);
338 $string = str_replace('(','%28',$string);
339 $string = str_replace(')','%29',$string);
340 $string = str_replace('&','%26',$string);
341 $string = str_replace('@','%40',$string);
342 return $string;
343 }
344
345 }
346
347 class IWP_DropboxException extends Exception {
348 }
349