Example #1
0
 /**
  * Constructor.
  *
  * @param Dropbox_AppInfo $appInfo
  *                                          See {@link getAppInfo()}
  * @param string          $clientIdentifier
  *                                          See {@link getClientIdentifier()}
  * @param null|string     $userLocale
  *                                          See {@link getUserLocale()}
  */
 public function __construct($appInfo, $clientIdentifier, $userLocale = null)
 {
     Dropbox_AppInfo::checkArg("appInfo", $appInfo);
     Dropbox_Client::checkClientIdentifierArg("clientIdentifier", $clientIdentifier);
     Dropbox_Checker::argStringNonEmptyOrNull("userLocale", $userLocale);
     $this->appInfo = $appInfo;
     $this->clientIdentifier = $clientIdentifier;
     $this->userLocale = $userLocale;
 }
Example #2
0
 /**
  * Returns cryptographically strong secure random bytes (as a PHP string).
  *
  * @param int $numBytes
  *                      The number of bytes of random data to return.
  *
  * @return string
  */
 public static function getRandomBytes($numBytes)
 {
     Dropbox_Checker::argIntPositive("numBytes", $numBytes);
     // openssl_random_pseudo_bytes had some issues prior to PHP 5.3.4
     if (function_exists('openssl_random_pseudo_bytes') && version_compare(PHP_VERSION, '5.3.4') >= 0) {
         $s = openssl_random_pseudo_bytes($numBytes, $isCryptoStrong);
         if ($isCryptoStrong) {
             return $s;
         }
     }
     if (function_exists('mcrypt_create_iv')) {
         return mcrypt_create_iv($numBytes);
     }
     // Hopefully the above two options cover all our users.  But if not, there are
     // other platform-specific options we could add.
     throw new Exception("no suitable random number source available");
 }
 /**
  * Use this to check that a function argument is of type <code>AppInfo</code>
  *
  * @internal
  */
 public static function checkArg($argName, $argValue)
 {
     if (!$argValue instanceof self) {
         Dropbox_Checker::throwError($argName, $argValue, __CLASS__);
     }
 }
 /**
  * Call this after the user has visited the authorize URL returned by {@link start()},
  * approved your app, was presented with an authorization code by Dropbox, and has copy/paste'd
  * that authorization code into your app.
  *
  * See <a href="https://www.dropbox.com/developers/core/docs#oa2-token">/oauth2/token</a>.
  *
  * @param string $code
  *                     The authorization code provided to the user by Dropbox.
  *
  * @return array
  *               A <code>list(string $accessToken, string $userId)</code>, where
  *               <code>$accessToken</code> can be used to construct a {@link Client} and
  *               <code>$userId</code> is the user ID of the user's Dropbox account.
  *
  * @throws Dropbox_Exception
  *                           Thrown if there's an error getting the access token from Dropbox.
  */
 public function finish($code)
 {
     Dropbox_Checker::argStringNonEmpty("code", $code);
     return $this->_finish($code, null);
 }
Example #5
0
 /**
  * Check that a function argument is either <code>null</code> or of type
  * <code>WriteMode</code>.
  *
  * @internal
  */
 public static function checkArgOrNull($argName, $argValue)
 {
     if ($argValue === null) {
         return;
     }
     if (!$argValue instanceof self) {
         Dropbox_Checker::throwError($argName, $argValue, __CLASS__);
     }
 }
Example #6
0
 /**
  * Return the last component of a path (the file or folder name).
  *
  * <code>
  * Path::getName("/Misc/Notes.txt") // "Notes.txt"
  * Path::getName("/Misc")           // "Misc"
  * Path::getName("/")               // null
  * </code>
  *
  * @param string $path
  *                     The full path you want to get the last component of.
  *
  * @return null|string
  *                     The last component of <code>$path</code> or <code>null</code> if the given
  *                     <code>$path</code> was <code>"/"<code>.
  */
 public static function getName($path)
 {
     Dropbox_Checker::argString("path", $path);
     if (substr_compare($path, "/", 0, 1) !== 0) {
         throw new InvalidArgumentException("'path' must start with \"/\"");
     }
     $l = strlen($path);
     if ($l === 1) {
         return null;
     }
     if ($path[$l - 1] === "/") {
         throw new InvalidArgumentException("'path' must not end with \"/\"");
     }
     $lastSlash = strrpos($path, "/");
     return substr($path, $lastSlash + 1);
 }
Example #7
0
 /**
  * Perform an OAuth-2-authorized POST request to the Dropbox API.  Will automatically
  * fill in "User-Agent" and "locale" as well.
  *
  * @param string     $host
  *                           Either the "API" or "API content" hostname from {@link getHost()}.
  * @param string     $path
  *                           The "path" part of the URL.  For example, "/commit_chunked_upload".
  * @param array|null $params
  *                           POST parameters.
  *
  * @return Dropbox_HttpResponse
  *
  * @throws Dropbox_Exception
  */
 public function doPost($host, $path, $params = null)
 {
     Dropbox_Checker::argString("host", $host);
     Dropbox_Checker::argString("path", $path);
     return Dropbox_RequestUtil::doPost($this->clientIdentifier, $this->accessToken, $this->userLocale, $host, $path, $params);
 }
Example #8
0
 /**
  * Call this after the user has visited the authorize URL ({@link start()}), approved your app,
  * and was redirected to your redirect URI.
  *
  * See <a href="https://www.dropbox.com/developers/core/docs#oa2-token">/oauth2/token</a>.
  *
  * @param array $queryParams
  *                           The query parameters on the GET request to your redirect URI.
  *
  * @return array
  *               A <code>list(string $accessToken, string $userId, string $urlState)</code>, where
  *               <code>$accessToken</code> can be used to construct a {@link Client}, <code>$userId</code>
  *               is the user ID of the user's Dropbox account, and <code>$urlState</code> is the
  *               value you originally passed in to {@link start()}.
  *
  * @throws Dropbox_Exception
  *                                              Thrown if there's an error getting the access token from Dropbox.
  * @throws Dropbox_WebAuthException_BadRequest
  * @throws Dropbox_WebAuthException_BadState
  * @throws Dropbox_WebAuthException_Csrf
  * @throws Dropbox_WebAuthException_NotApproved
  * @throws Dropbox_WebAuthException_Provider
  *
  *
  */
 public function finish($queryParams)
 {
     Dropbox_Checker::argArray("queryParams", $queryParams);
     $csrfTokenFromSession = $this->csrfTokenStore->get();
     Dropbox_Checker::argStringOrNull("this->csrfTokenStore->get()", $csrfTokenFromSession);
     // Check well-formedness of request.
     if (!isset($queryParams['state'])) {
         throw new Dropbox_WebAuthException_BadRequest("Missing query parameter 'state'.");
     }
     $state = $queryParams['state'];
     Dropbox_Checker::argString("queryParams['state']", $state);
     $error = null;
     $errorDescription = null;
     if (isset($queryParams['error'])) {
         $error = $queryParams['error'];
         Dropbox_Checker::argString("queryParams['error']", $error);
         if (isset($queryParams['error_description'])) {
             $errorDescription = $queryParams['error_description'];
             Dropbox_Checker::argString("queryParams['error_description']", $errorDescription);
         }
     }
     $code = null;
     if (isset($queryParams['code'])) {
         $code = $queryParams['code'];
         Dropbox_Checker::argString("queryParams['code']", $code);
     }
     if ($code !== null && $error !== null) {
         throw new Dropbox_WebAuthException_BadRequest("Query parameters 'code' and 'error' are both set;" . " only one must be set.");
     }
     if ($code === null && $error === null) {
         throw new Dropbox_WebAuthException_BadRequest("Neither query parameter 'code' or 'error' is set.");
     }
     // Check CSRF token
     if ($csrfTokenFromSession === null) {
         throw new Dropbox_WebAuthException_BadState();
     }
     $splitPos = strpos($state, "|");
     if ($splitPos === false) {
         $givenCsrfToken = $state;
         $urlState = null;
     } else {
         $givenCsrfToken = substr($state, 0, $splitPos);
         $urlState = substr($state, $splitPos + 1);
     }
     if (!Dropbox_Security::stringEquals($csrfTokenFromSession, $givenCsrfToken)) {
         throw new Dropbox_WebAuthException_Csrf("Expected " . Dropbox_Client::q($csrfTokenFromSession) . ", got " . Dropbox_Client::q($givenCsrfToken) . ".");
     }
     $this->csrfTokenStore->clear();
     // Check for error identifier
     if ($error !== null) {
         if ($error === 'access_denied') {
             // When the user clicks "Deny".
             if ($errorDescription === null) {
                 throw new Dropbox_WebAuthException_NotApproved("No additional description from Dropbox.");
             } else {
                 throw new Dropbox_WebAuthException_NotApproved("Additional description from Dropbox: {$errorDescription}");
             }
         } else {
             // All other errors.
             $fullMessage = $error;
             if ($errorDescription !== null) {
                 $fullMessage .= ": ";
                 $fullMessage .= $errorDescription;
             }
             throw new Dropbox_WebAuthException_Provider($fullMessage);
         }
     }
     // If everything went ok, make the network call to get an access token.
     list($accessToken, $userId) = $this->_finish($code, $this->redirectUri);
     return array($accessToken, $userId, $urlState);
 }
 /**
  * @param int $maxRetries
  *                        The number of times to retry it the action if it fails with one of the transient
  *                        API errors.  A value of 1 means we'll try the action once and if it fails, we
  *                        will retry once.
  *
  * @param callable $action
  *                         The the action you want to retry.
  *
  * @return mixed
  *               Whatever is returned by the $action callable.
  */
 public static function runWithRetry($maxRetries, Dropbox_Closure_ReRunnableActionInterface $action)
 {
     Dropbox_Checker::argNat("maxRetries", $maxRetries);
     $retryDelay = 1;
     $numRetries = 0;
     while (true) {
         try {
             return $action->run();
         } catch (Dropbox_Exception_NetworkIO $ex) {
             $savedEx = $ex;
         } catch (Dropbox_Exception_ServerError $ex) {
             $savedEx = $ex;
         } catch (Dropbox_Exception_RetryLater $ex) {
             $savedEx = $ex;
         }
         // We maxed out our retries.  Propagate the last exception we got.
         if ($numRetries >= $maxRetries) {
             throw $savedEx;
         }
         $numRetries++;
         sleep($retryDelay);
         $retryDelay *= 2;
         // Exponential back-off.
     }
     throw new RuntimeException("unreachable");
 }