Changeset 868957
- Timestamp:
- 03/04/2014 02:55:15 AM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
wp-time-machine/trunk/includes/DropboxUploader.php
r661113 r868957 2 2 /** 3 3 * Dropbox Uploader 4 * 4 * 5 5 * Copyright (c) 2009 Jaka Jancar 6 * 6 * 7 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 8 * of this software and associated documentation files (the "Software"), to deal … … 11 11 * copies of the Software, and to permit persons to whom the Software is 12 12 * furnished to do so, subject to the following conditions: 13 * 13 * 14 14 * The above copyright notice and this permission notice shall be included in 15 15 * all copies or substantial portions of the Software. 16 * 16 * 17 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, … … 24 24 * 25 25 * @author Jaka Jancar [[email protected]] [http://jaka.kubje.org/] 26 * @version 1.1. 726 * @version 1.1.12 27 27 */ 28 28 class DropboxUploader { 29 /** 30 * Certificate Authority Certificate source types 31 */ 32 const CACERT_SOURCE_SYSTEM = 0; 33 const CACERT_SOURCE_FILE = 1; 34 const CACERT_SOURCE_DIR = 2; 35 /** 36 * Dropbox configuration 37 */ 38 const DROPBOX_UPLOAD_LIMIT_IN_BYTES = 314572800; 39 const HTTPS_DROPBOX_COM_HOME = 'https://www.dropbox.com/home'; 40 const HTTPS_DROPBOX_COM_LOGIN = 'https://www.dropbox.com/login'; 41 const HTTPS_DROPBOX_COM_UPLOAD = 'https://dl-web.dropbox.com/upload'; 42 /** 43 * DropboxUploader Error Flags and Codes 44 */ 45 const FLAG_DROPBOX_GENERIC = 0x10000000; 46 const FLAG_LOCAL_FILE_IO = 0x10010000; 47 const CODE_FILE_READ_ERROR = 0x10010101; 48 const CODE_TEMP_FILE_CREATE_ERROR = 0x10010102; 49 const CODE_TEMP_FILE_WRITE_ERROR = 0x10010103; 50 const FLAG_PARAMETER_INVALID = 0x10020000; 51 const CODE_PARAMETER_TYPE_ERROR = 0x10020101; 52 const CODE_FILESIZE_TOO_LARGE = 0x10020201; 53 const FLAG_REMOTE = 0x10040000; 54 const CODE_CURL_ERROR = 0x10040101; 55 const CODE_LOGIN_ERROR = 0x10040201; 56 const CODE_UPLOAD_ERROR = 0x10040401; 57 const CODE_SCRAPING_FORM = 0x10040801; 58 const CODE_SCRAPING_LOGIN = 0x10040802; 59 const CODE_CURL_EXTENSION_MISSING = 0x10080101; 29 60 protected $email; 30 61 protected $password; 31 62 protected $caCertSourceType = self::CACERT_SOURCE_SYSTEM; 32 const CACERT_SOURCE_SYSTEM = 0;33 const CACERT_SOURCE_FILE = 1;34 const CACERT_SOURCE_DIR = 2;35 63 protected $caCertSource; 36 protected $loggedIn = false;64 protected $loggedIn = FALSE; 37 65 protected $cookies = array(); 38 66 … … 41 69 * 42 70 * @param string $email 43 * @param string |null$password71 * @param string $password 44 72 * @throws Exception 45 73 */ … … 47 75 // Check requirements 48 76 if (!extension_loaded('curl')) 49 throw new Exception('DropboxUploader requires the cURL extension.'); 50 51 $this->email = $email; 77 throw new Exception('DropboxUploader requires the cURL extension.', self::CODE_CURL_EXTENSION_MISSING); 78 79 if (empty($email) || empty($password)) { 80 throw new Exception((empty($email) ? 'Email' : 'Password') . ' must not be empty.', self::CODE_PARAMETER_TYPE_ERROR); 81 } 82 83 $this->email = $email; 52 84 $this->password = $password; 53 85 } 54 55 public function setCaCertificateFile($file) 56 { 86 87 public function setCaCertificateDir($dir) { 88 $this->caCertSourceType = self::CACERT_SOURCE_DIR; 89 $this->caCertSource = $dir; 90 } 91 92 public function setCaCertificateFile($file) { 57 93 $this->caCertSourceType = self::CACERT_SOURCE_FILE; 58 $this->caCertSource = $file; 59 } 60 61 public function setCaCertificateDir($dir) 62 { 63 $this->caCertSourceType = self::CACERT_SOURCE_DIR; 64 $this->caCertSource = $dir; 65 } 66 67 public function upload($source, $remoteDir='/', $remoteName=null) { 94 $this->caCertSource = $file; 95 } 96 97 public function upload($source, $remoteDir = '/', $remoteName = NULL) { 68 98 if (!is_file($source) or !is_readable($source)) 69 throw new Exception("File '$source' does not exist or is not readable."); 99 throw new Exception("File '$source' does not exist or is not readable.", self::CODE_FILE_READ_ERROR); 100 101 $filesize = filesize($source); 102 if ($filesize < 0 or $filesize > self::DROPBOX_UPLOAD_LIMIT_IN_BYTES) { 103 throw new Exception("File '$source' too large ($filesize bytes).", self::CODE_FILESIZE_TOO_LARGE); 104 } 70 105 71 106 if (!is_string($remoteDir)) 72 throw new Exception("Remote directory must be a string, is " .gettype($remoteDir)." instead.");107 throw new Exception("Remote directory must be a string, is " . gettype($remoteDir) . " instead.", self::CODE_PARAMETER_TYPE_ERROR); 73 108 74 109 if (is_null($remoteName)) { 75 110 # intentionally left blank 76 111 } else if (!is_string($remoteName)) { 77 throw new Exception("Remote filename must be a string, is " .gettype($remoteDir)." instead.");112 throw new Exception("Remote filename must be a string, is " . gettype($remoteDir) . " instead.", self::CODE_PARAMETER_TYPE_ERROR); 78 113 } else { 79 $source .= ';filename=' .$remoteName;114 $source .= ';filename=' . $remoteName; 80 115 } 81 116 82 117 if (!$this->loggedIn) 83 118 $this->login(); 84 85 $data = $this->request('https://www.dropbox.com/home'); 86 $token = $this->extractToken($data, 'https://dl-web.dropbox.com/upload'); 87 88 89 $postData = array('plain'=>'yes', 'file'=>'@'.$source, 'dest'=>$remoteDir, 't'=>$token); 90 $data = $this->request('https://dl-web.dropbox.com/upload', true, $postData); 91 if (strpos($data, 'HTTP/1.1 302 FOUND') === false) 92 throw new Exception('Upload failed!'); 93 } 94 119 120 $data = $this->request(self::HTTPS_DROPBOX_COM_HOME); 121 $token = $this->extractToken($data, self::HTTPS_DROPBOX_COM_UPLOAD); 122 123 $postData = array( 124 'plain' => 'yes', 125 'file' => '@' . $source, 126 'dest' => $remoteDir, 127 't' => $token 128 ); 129 $data = $this->request(self::HTTPS_DROPBOX_COM_UPLOAD, $postData); 130 if (strpos($data, 'HTTP/1.1 302 FOUND') === FALSE) 131 throw new Exception('Upload failed!', self::CODE_UPLOAD_ERROR); 132 } 133 134 public function uploadString($string, $remoteName, $remoteDir = '/') { 135 $exception = NULL; 136 137 $file = tempnam(sys_get_temp_dir(), 'DBUploadString'); 138 if (!is_file($file)) 139 throw new Exception("Can not create temporary file.", self::CODE_TEMP_FILE_CREATE_ERROR); 140 141 $bytes = file_put_contents($file, $string); 142 if ($bytes === FALSE) { 143 unlink($file); 144 throw new Exception("Can not write to temporary file '$file'.", self::CODE_TEMP_FILE_WRITE_ERROR); 145 } 146 147 try { 148 $this->upload($file, $remoteDir, $remoteName); 149 } catch (Exception $exception) { 150 # intentionally left blank 151 } 152 153 unlink($file); 154 155 if ($exception) 156 throw $exception; 157 } 158 95 159 protected function login() { 96 $data = $this->request('https://www.dropbox.com/login');160 $data = $this->request(self::HTTPS_DROPBOX_COM_LOGIN); 97 161 $token = $this->extractTokenFromLoginForm($data); 98 162 99 $postData = array('login_email'=>$this->email, 'login_password'=>$this->password, 't'=>$token); 100 $data = $this->request('https://www.dropbox.com/login', true, $postData); 101 102 if (stripos($data, 'location: /home') === false) 103 throw new Exception('Login unsuccessful.'); 104 105 $this->loggedIn = true; 106 } 107 108 protected function request($url, $post=false, $postData=array()) { 163 $postData = array( 164 'login_email' => (string) $this->email, 165 'login_password' => (string) $this->password, 166 't' => $token 167 ); 168 $data = $this->request(self::HTTPS_DROPBOX_COM_LOGIN, http_build_query($postData)); 169 170 if (stripos($data, 'location: /home') === FALSE) 171 throw new Exception('Login unsuccessful.', self::CODE_LOGIN_ERROR); 172 173 $this->loggedIn = TRUE; 174 } 175 176 protected function request($url, $postData = NULL) { 109 177 $ch = curl_init(); 110 curl_setopt($ch, CURLOPT_URL, $url);178 curl_setopt($ch, CURLOPT_URL, (string) $url); 111 179 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); 112 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);180 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE); 113 181 switch ($this->caCertSourceType) { 114 182 case self::CACERT_SOURCE_FILE: 115 curl_setopt($ch, CURLOPT_CAINFO, $this->caCertSource);183 curl_setopt($ch, CURLOPT_CAINFO, (string) $this->caCertSource); 116 184 break; 117 185 case self::CACERT_SOURCE_DIR: 118 curl_setopt($ch, CURLOPT_CAPATH, $this->caCertSource);186 curl_setopt($ch, CURLOPT_CAPATH, (string) $this->caCertSource); 119 187 break; 120 188 } 121 curl_setopt($ch, CURLOPT_HEADER, 1);122 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);123 if ( $post) {124 curl_setopt($ch, CURLOPT_POST, $post);189 curl_setopt($ch, CURLOPT_HEADER, TRUE); 190 curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); 191 if (NULL !== $postData) { 192 curl_setopt($ch, CURLOPT_POST, TRUE); 125 193 curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); 126 194 } 127 195 128 196 // Send cookies 129 197 $rawCookies = array(); 130 foreach ($this->cookies as $k =>$v)198 foreach ($this->cookies as $k => $v) 131 199 $rawCookies[] = "$k=$v"; 132 200 $rawCookies = implode(';', $rawCookies); 133 201 curl_setopt($ch, CURLOPT_COOKIE, $rawCookies); 134 135 $data = curl_exec($ch); 136 137 if ($data === false) { 138 throw new Exception(sprintf('Curl error: (#%d) %s', curl_errno($ch), curl_error($ch))); 139 } 140 202 203 $data = curl_exec($ch); 204 $error = sprintf('Curl error: (#%d) %s', curl_errno($ch), curl_error($ch)); 205 curl_close($ch); 206 207 if ($data === FALSE) { 208 throw new Exception($error, self::CODE_CURL_ERROR); 209 } 210 141 211 // Store received cookies 142 212 preg_match_all('/Set-Cookie: ([^=]+)=(.*?);/i', $data, $matches, PREG_SET_ORDER); 143 213 foreach ($matches as $match) 144 214 $this->cookies[$match[1]] = $match[2]; 145 146 curl_close($ch); 147 215 148 216 return $data; 217 } 218 219 protected function extractToken($html, $formAction) { 220 $quot = preg_quote($formAction, '/'); 221 $pattern = '/<form [^>]*' . $quot . '[^>]*>.*?(?:<input [^>]*name="t" [^>]*value="(.*?)"[^>]*>).*?<\/form>/is'; 222 if (!preg_match($pattern, $html, $matches)) 223 throw new Exception("Cannot extract token! (form action is '$formAction')", self::CODE_SCRAPING_FORM); 224 return $matches[1]; 149 225 } 150 226 … … 152 228 // <input type="hidden" name="t" value="UJygzfv9DLLCS-is7cLwgG7z" /> 153 229 if (!preg_match('#<input type="hidden" name="t" value="([A-Za-z0-9_-]+)" />#', $html, $matches)) 154 throw new Exception('Cannot extract login CSRF token.' );230 throw new Exception('Cannot extract login CSRF token.', self::CODE_SCRAPING_LOGIN); 155 231 return $matches[1]; 156 232 } 157 233 158 protected function extractToken($html, $formAction) {159 if (!preg_match('/<form [^>]*'.preg_quote($formAction, '/').'[^>]*>.*?(<input [^>]*name="t" [^>]*value="(.*?)"[^>]*>).*?<\/form>/is', $html, $matches) || !isset($matches[2]))160 throw new Exception("Cannot extract token! (form action=$formAction)");161 return $matches[2];162 }163 164 234 }
Note: See TracChangeset
for help on using the changeset viewer.