mirror of
https://github.com/Yetangitu/ampache
synced 2025-10-06 03:49:56 +02:00
Fix Soundcloud and Dropbox catalog modules since SSE
Update php-dropbox to latest version (fix SSLv3 issue)
This commit is contained in:
parent
0da311f916
commit
1711cd14ff
27 changed files with 2278 additions and 579 deletions
|
@ -30,7 +30,22 @@ if (!Access::check('interface','100')) {
|
|||
|
||||
UI::show_header();
|
||||
|
||||
$sse_catalogs = urlencode(serialize($_REQUEST['catalogs']));
|
||||
$catalogs = $_REQUEST['catalogs'];
|
||||
// If only one catalog, check it is ready.
|
||||
if (is_array($catalogs) && count($catalogs) == 1 && $_REQUEST['action'] !== 'delete_catalog' && $_REQUEST['action'] !== 'show_delete_catalog') {
|
||||
// If not ready, display the data to make it ready / stop the action.
|
||||
$catalog = Catalog::create_from_id($catalogs[0]);
|
||||
if (!$catalog->isReady()) {
|
||||
if (!isset($_REQUEST['perform_ready'])) {
|
||||
$catalog->show_ready_process();
|
||||
UI::show_footer();
|
||||
exit;
|
||||
} else {
|
||||
$catalog->perform_ready();
|
||||
}
|
||||
}
|
||||
}
|
||||
$sse_catalogs = urlencode(serialize($catalogs));
|
||||
|
||||
/* Big switch statement to handle various actions */
|
||||
switch ($_REQUEST['action']) {
|
||||
|
@ -74,14 +89,14 @@ switch ($_REQUEST['action']) {
|
|||
}
|
||||
|
||||
/* Delete the sucker, we don't need to check perms as thats done above */
|
||||
foreach ($_REQUEST['catalogs'] as $catalog_id) {
|
||||
foreach ($catalogs as $catalog_id) {
|
||||
Catalog::delete($catalog_id);
|
||||
}
|
||||
$next_url = AmpConfig::get('web_path') . '/admin/catalog.php';
|
||||
show_confirmation(T_('Catalog Deleted'), T_('The Catalog and all associated records have been deleted'),$next_url);
|
||||
break;
|
||||
case 'show_delete_catalog':
|
||||
$next_url = AmpConfig::get('web_path') . '/admin/catalog.php?action=delete_catalog&catalogs[]=' . implode(',', $_REQUEST['catalogs']);
|
||||
$next_url = AmpConfig::get('web_path') . '/admin/catalog.php?action=delete_catalog&catalogs[]=' . implode(',', $catalogs);
|
||||
show_confirmation(T_('Catalog Delete'), T_('Confirm Deletion Request'),$next_url,1,'delete_catalog');
|
||||
break;
|
||||
case 'enable_disabled':
|
||||
|
|
|
@ -157,6 +157,31 @@ abstract class Catalog extends database_object
|
|||
*/
|
||||
abstract public function prepare_media($media);
|
||||
|
||||
/**
|
||||
* Check if the catalog is ready to perform actions (configuration completed, ...)
|
||||
* @return boolean
|
||||
*/
|
||||
public function isReady()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a message to make the catalog ready.
|
||||
*/
|
||||
public function show_ready_process()
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the last step process to make the catalog ready.
|
||||
*/
|
||||
public function perform_ready()
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
/**
|
||||
* uninstall
|
||||
* This removes the remote catalog
|
||||
|
|
|
@ -114,17 +114,23 @@ abstract class Catalog extends \Catalog
|
|||
*/
|
||||
public function add_to_catalog($options = null)
|
||||
{
|
||||
require AmpConfig::get('prefix') . '/templates/show_adds_catalog.inc.php';
|
||||
flush();
|
||||
if (!defined('SSE_OUTPUT')) {
|
||||
require AmpConfig::get('prefix') . '/templates/show_adds_catalog.inc.php';
|
||||
flush();
|
||||
}
|
||||
set_time_limit(0);
|
||||
UI::show_box_top(T_('Running Beets Update') . '. . .');
|
||||
if (!defined('SSE_OUTPUT')) {
|
||||
UI::show_box_top(T_('Running Beets Update') . '. . .');
|
||||
}
|
||||
$parser = $this->getParser();
|
||||
$parser->setHandler($this, 'addSong');
|
||||
$parser->start($parser->getTimedCommand($this->listCommand, 'added', $this->last_add));
|
||||
$this->updateUi('add', $this->addedSongs, null, true);
|
||||
$this->update_last_add();
|
||||
|
||||
UI::show_box_bottom();
|
||||
if (!defined('SSE_OUTPUT')) {
|
||||
UI::show_box_bottom();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -116,7 +116,7 @@ final class AppInfo
|
|||
}
|
||||
|
||||
$str = file_get_contents($path);
|
||||
$jsonArr = json_decode($str, TRUE);
|
||||
$jsonArr = json_decode($str, true);
|
||||
|
||||
if (is_null($jsonArr)) {
|
||||
throw new AppInfoLoadException("JSON parse error: \"$path\"");
|
||||
|
@ -131,7 +131,7 @@ final class AppInfo
|
|||
* Parses a JSON object to build an AppInfo object. If you would like to load this from a file,
|
||||
* use the loadFromJsonFile() method.
|
||||
*
|
||||
* @param array $jsonArr Output from json_decode($str, TRUE)
|
||||
* @param array $jsonArr Output from json_decode($str, true)
|
||||
*
|
||||
* @return AppInfo
|
||||
*
|
||||
|
|
|
@ -6,7 +6,10 @@ namespace Dropbox;
|
|||
*/
|
||||
class ArrayEntryStore implements ValueStore
|
||||
{
|
||||
/** @var array */
|
||||
private $array;
|
||||
|
||||
/** @var mixed */
|
||||
private $key;
|
||||
|
||||
/**
|
||||
|
@ -15,7 +18,7 @@ class ArrayEntryStore implements ValueStore
|
|||
* @param array $array
|
||||
* The array that we'll be accessing.
|
||||
*
|
||||
* @param object $key
|
||||
* @param mixed $key
|
||||
* The key for the array element we'll be accessing.
|
||||
*/
|
||||
function __construct(&$array, $key)
|
||||
|
|
75
modules/Dropbox/AuthBase.php
Normal file
75
modules/Dropbox/AuthBase.php
Normal file
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
namespace Dropbox;
|
||||
|
||||
/**
|
||||
* Base class for API authorization-related classes.
|
||||
*/
|
||||
class AuthBase
|
||||
{
|
||||
/**
|
||||
* Whatever AppInfo was passed into the constructor.
|
||||
*
|
||||
* @return AppInfo
|
||||
*/
|
||||
function getAppInfo() { return $this->appInfo; }
|
||||
|
||||
/** @var AppInfo */
|
||||
protected $appInfo;
|
||||
|
||||
/**
|
||||
* An identifier for the API client, typically of the form "Name/Version".
|
||||
* This is used to set the HTTP <code>User-Agent</code> header when making API requests.
|
||||
* Example: <code>"PhotoEditServer/1.3"</code>
|
||||
*
|
||||
* If you're the author a higher-level library on top of the basic SDK, and the
|
||||
* "Photo Edit" app's server code is using your library to access Dropbox, you should append
|
||||
* your library's name and version to form the full identifier. For example,
|
||||
* if your library is called "File Picker", you might set this field to:
|
||||
* <code>"PhotoEditServer/1.3 FilePicker/0.1-beta"</code>
|
||||
*
|
||||
* The exact format of the <code>User-Agent</code> header is described in
|
||||
* <a href="http://tools.ietf.org/html/rfc2616#section-3.8">section 3.8 of the HTTP specification</a>.
|
||||
*
|
||||
* Note that underlying HTTP client may append other things to the <code>User-Agent</code>, such as
|
||||
* the name of the library being used to actually make the HTTP request (such as cURL).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getClientIdentifier() { return $this->clientIdentifier; }
|
||||
|
||||
/** @var string */
|
||||
protected $clientIdentifier;
|
||||
|
||||
/**
|
||||
* The locale of the user of your application. Some API calls return localized
|
||||
* data and error messages; this "user locale" setting determines which locale
|
||||
* the server should use to localize those strings.
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
function getUserLocale() { return $this->userLocale; }
|
||||
|
||||
/** @var string */
|
||||
protected $userLocale;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param AppInfo $appInfo
|
||||
* See {@link getAppInfo()}
|
||||
* @param string $clientIdentifier
|
||||
* See {@link getClientIdentifier()}
|
||||
* @param null|string $userLocale
|
||||
* See {@link getUserLocale()}
|
||||
*/
|
||||
function __construct($appInfo, $clientIdentifier, $userLocale = null)
|
||||
{
|
||||
AppInfo::checkArg("appInfo", $appInfo);
|
||||
Client::checkClientIdentifierArg("clientIdentifier", $clientIdentifier);
|
||||
Checker::argStringNonEmptyOrNull("userLocale", $userLocale);
|
||||
|
||||
$this->appInfo = $appInfo;
|
||||
$this->clientIdentifier = $clientIdentifier;
|
||||
$this->userLocale = $userLocale;
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ final class AuthInfo
|
|||
}
|
||||
|
||||
$str = file_get_contents($path);
|
||||
$jsonArr = json_decode($str, TRUE);
|
||||
$jsonArr = json_decode($str, true);
|
||||
|
||||
if (is_null($jsonArr)) {
|
||||
throw new AuthInfoLoadException("JSON parse error: \"$path\"");
|
||||
|
@ -41,7 +41,7 @@ final class AuthInfo
|
|||
* please use the @see loadFromJsonFile method.
|
||||
*
|
||||
* @param array $jsonArr
|
||||
* A parsed JSON object, typcally the result of json_decode(..., TRUE).
|
||||
* A parsed JSON object, typcally the result of json_decode(..., true).
|
||||
* @return array
|
||||
* A <code>list(string $accessToken, Host $host)</code>.
|
||||
*
|
||||
|
|
|
@ -56,6 +56,13 @@ class Client
|
|||
/** @var null|string */
|
||||
private $userLocale;
|
||||
|
||||
/**
|
||||
* The {@link Host} object that determines the hostnames we make requests to.
|
||||
*
|
||||
* @return Host
|
||||
*/
|
||||
function getHost() { return $this->host; }
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
|
@ -68,8 +75,8 @@ class Client
|
|||
*/
|
||||
function __construct($accessToken, $clientIdentifier, $userLocale = null)
|
||||
{
|
||||
Checker::argStringNonEmpty("accessToken", $accessToken);
|
||||
Checker::argStringNonEmpty("clientIdentifier", $clientIdentifier);
|
||||
self::checkAccessTokenArg("accessToken", $accessToken);
|
||||
self::checkClientIdentifierArg("clientIdentifier", $clientIdentifier);
|
||||
Checker::argStringNonEmptyOrNull("userLocale", $userLocale);
|
||||
|
||||
$this->accessToken = $accessToken;
|
||||
|
@ -99,16 +106,40 @@ class Client
|
|||
private $apiHost;
|
||||
/** @var string */
|
||||
private $contentHost;
|
||||
/** @var string */
|
||||
private $root;
|
||||
|
||||
private function appendFilePath($base, $path)
|
||||
/**
|
||||
* Given a <code>$base</code> path for an API endpoint (for example, "/files"), append
|
||||
* a Dropbox API file path to the end of that URL. Special characters in the file will
|
||||
* be encoded properly.
|
||||
*
|
||||
* This is for endpoints like "/files" takes the path on the URL and not as a separate
|
||||
* query or POST parameter.
|
||||
*
|
||||
* @param string $base
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function appendFilePath($base, $path)
|
||||
{
|
||||
return $base . "/auto/" . rawurlencode(substr($path, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a basic account and quota information.
|
||||
* Make an API call to disable the access token that you constructed this <code>Client</code>
|
||||
* with. After calling this, API calls made with this <code>Client</code> will fail.
|
||||
*
|
||||
* See <a href="https://www.dropbox.com/developers/core/docs#disable-token">/disable_access_token</a>.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
function disableAccessToken()
|
||||
{
|
||||
$response = $this->doPost($this->apiHost, "1/disable_access_token");
|
||||
if ($response->statusCode !== 200) throw RequestUtil::unexpectedStatus($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an API call to get basic account and quota information.
|
||||
*
|
||||
* <code>
|
||||
* $client = ...
|
||||
|
@ -117,7 +148,7 @@ class Client
|
|||
* </code>
|
||||
*
|
||||
* @return array
|
||||
* See <a href="https://www.dropbox.com/developers/core/api#account-info">/account/info</a>.
|
||||
* See <a href="https://www.dropbox.com/developers/core/docs#account-info">/account/info</a>.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
|
@ -134,8 +165,9 @@ class Client
|
|||
*
|
||||
* <code>
|
||||
* $client = ...;
|
||||
* $metadata = $client->getFile("/Photos/Frog.jpeg",
|
||||
* fopen("./Frog.jpeg", "wb"));
|
||||
* $fd = fopen("./Frog.jpeg", "wb");
|
||||
* $metadata = $client->getFile("/Photos/Frog.jpeg", $fd);
|
||||
* fclose($fd);
|
||||
* print_r($metadata);
|
||||
* </code>
|
||||
*
|
||||
|
@ -149,29 +181,25 @@ class Client
|
|||
* If you want the latest revision of the file at the given path, pass in <code>null</code>.
|
||||
* If you want a specific version of a file, pass in value of the file metadata's "rev" field.
|
||||
*
|
||||
* @param int $maxisze
|
||||
* Limit the file size to download. 0 to download the complete file.
|
||||
*
|
||||
* @return null|array
|
||||
* The <a href="https://www.dropbox.com/developers/core/api#metadata-details">metadata
|
||||
* The <a href="https://www.dropbox.com/developers/core/docs#metadata-details">metadata
|
||||
* object</a> for the file at the given $path and $rev, or <code>null</code> if the file
|
||||
* doesn't exist,
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
function getFile($path, $outStream, $rev = null, $maxsize = 0)
|
||||
function getFile($path, $outStream, $rev = null)
|
||||
{
|
||||
Path::checkArgNonRoot("path", $path);
|
||||
Checker::argResource("outStream", $outStream);
|
||||
Checker::argStringNonEmptyOrNull("rev", $rev);
|
||||
|
||||
$url = RequestUtil::buildUrl(
|
||||
$this->userLocale,
|
||||
$url = $this->buildUrlForGetOrPut(
|
||||
$this->contentHost,
|
||||
$this->appendFilePath("1/files", $path),
|
||||
array("rev" => $rev));
|
||||
|
||||
$curl = $this->mkCurl($url, $maxsize);
|
||||
$curl = $this->mkCurl($url);
|
||||
$metadataCatcher = new DropboxMetadataHeaderCatcher($curl->handle);
|
||||
$streamRelay = new CurlStreamRelay($curl->handle, $outStream);
|
||||
|
||||
|
@ -238,7 +266,7 @@ class Client
|
|||
* than 8 MB.
|
||||
*
|
||||
* @return mixed
|
||||
* The <a href="https://www.dropbox.com/developers/core/api#metadata-details>metadata
|
||||
* The <a href="https://www.dropbox.com/developers/core/docs#metadata-details>metadata
|
||||
* object</a> for the newly-added file.
|
||||
*
|
||||
* @throws Exception
|
||||
|
@ -290,7 +318,7 @@ class Client
|
|||
* The data to use for the contents of the file.
|
||||
*
|
||||
* @return mixed
|
||||
* The <a href="https://www.dropbox.com/developers/core/api#metadata-details>metadata
|
||||
* The <a href="https://www.dropbox.com/developers/core/docs#metadata-details>metadata
|
||||
* object</a> for the newly-added file.
|
||||
*
|
||||
* @throws Exception
|
||||
|
@ -333,7 +361,7 @@ class Client
|
|||
* <code>null</code> and the library will use a reasonable default.
|
||||
*
|
||||
* @return mixed
|
||||
* The <a href="https://www.dropbox.com/developers/core/api#metadata-details>metadata
|
||||
* The <a href="https://www.dropbox.com/developers/core/docs#metadata-details>metadata
|
||||
* object</a> for the newly-added file.
|
||||
*
|
||||
* @throws Exception
|
||||
|
@ -370,7 +398,7 @@ class Client
|
|||
* @param int $chunkSize
|
||||
*
|
||||
* @return array
|
||||
* The <a href="https://www.dropbox.com/developers/core/api#metadata-details>metadata
|
||||
* The <a href="https://www.dropbox.com/developers/core/docs#metadata-details>metadata
|
||||
* object</a> for the newly-added file.
|
||||
*/
|
||||
private function _uploadFileChunked($path, $writeMode, $inStream, $numBytes, $chunkSize)
|
||||
|
@ -422,14 +450,14 @@ class Client
|
|||
// An earlier byte offset means the server has lost data we sent earlier.
|
||||
if ($serverByteOffset < $byteOffset) throw new Exception_BadResponse(
|
||||
"Server is at an ealier byte offset: us=$byteOffset, server=$serverByteOffset");
|
||||
// The normal case is that the server is a bit further along than us because of a
|
||||
// partially-uploaded chunk.
|
||||
$diff = $serverByteOffset - $byteOffset;
|
||||
// If the server is past where we think it could possibly be, something went wrong.
|
||||
if ($diff > $len) throw new Exception_BadResponse(
|
||||
"Server is more than a chunk ahead: us=$byteOffset, server=$serverByteOffset");
|
||||
|
||||
// Finish the rest of this chunk.
|
||||
// The normal case is that the server is a bit further along than us because of a
|
||||
// partially-uploaded chunk. Finish it off.
|
||||
$byteOffset += $diff;
|
||||
if ($diff === $len) break; // If the server is at the end, we're done.
|
||||
$data = substr($data, $diff);
|
||||
}
|
||||
}
|
||||
|
@ -451,7 +479,8 @@ class Client
|
|||
* bytes have been read or we've reached EOF.
|
||||
*
|
||||
* @param resource $inStream
|
||||
* @param int $limit
|
||||
* @param int $numBytes
|
||||
* @throws StreamReadException
|
||||
* @return string
|
||||
*/
|
||||
private static function readFully($inStream, $numBytes)
|
||||
|
@ -481,8 +510,7 @@ class Client
|
|||
WriteMode::checkArg("writeMode", $writeMode);
|
||||
Checker::argCallable("curlConfigClosure", $curlConfigClosure);
|
||||
|
||||
$url = RequestUtil::buildUrl(
|
||||
$this->userLocale,
|
||||
$url = $this->buildUrlForGetOrPut(
|
||||
$this->contentHost,
|
||||
$this->appendFilePath("1/files_put", $path),
|
||||
$writeMode->getExtraParams());
|
||||
|
@ -629,6 +657,8 @@ class Client
|
|||
/**
|
||||
* Creates a file on Dropbox using the accumulated contents of the given chunked upload session.
|
||||
*
|
||||
* See <a href="https://www.dropbox.com/developers/core/docs#commit-chunked-upload">/commit_chunked_upload</a>.
|
||||
*
|
||||
* @param string $uploadId
|
||||
* The unique identifier for the chunked upload session. This is obtained via
|
||||
* {@link chunkedUploadStart}.
|
||||
|
@ -643,7 +673,7 @@ class Client
|
|||
* If <code>null</code>, it means the Dropbox server wasn't aware of the
|
||||
* <code>$uploadId</code> you gave it.
|
||||
* Otherwise, you get back the
|
||||
* <a href="https://www.dropbox.com/developers/core/api#metadata-details">metadata object</a>
|
||||
* <a href="https://www.dropbox.com/developers/core/docs#metadata-details">metadata object</a>
|
||||
* for the newly-created file.
|
||||
*
|
||||
* @throws Exception
|
||||
|
@ -672,10 +702,11 @@ class Client
|
|||
* @param string $data
|
||||
* @return HttpResponse
|
||||
*/
|
||||
private function _chunkedUpload($params, $data)
|
||||
protected function _chunkedUpload($params, $data)
|
||||
// Marked 'protected' so I can override it in testing.
|
||||
{
|
||||
$url = RequestUtil::buildUrl(
|
||||
$this->userLocale, $this->contentHost, "1/chunked_upload", $params);
|
||||
$url = $this->buildUrlForGetOrPut(
|
||||
$this->contentHost, "1/chunked_upload", $params);
|
||||
|
||||
$curl = $this->mkCurl($url);
|
||||
|
||||
|
@ -702,7 +733,7 @@ class Client
|
|||
*
|
||||
* @return array|null
|
||||
* If there is a file or folder at the given path, you'll get back the
|
||||
* <a href="https://www.dropbox.com/developers/core/api#metadata-details">metadata object</a>
|
||||
* <a href="https://www.dropbox.com/developers/core/docs#metadata-details">metadata object</a>
|
||||
* for that file or folder. If not, you'll get back <code>null</code>.
|
||||
*
|
||||
* @throws Exception
|
||||
|
@ -729,7 +760,7 @@ class Client
|
|||
*
|
||||
* @return array|null
|
||||
* If there is a file or folder at the given path, you'll get back the
|
||||
* <a href="https://www.dropbox.com/developers/core/api#metadata-details">metadata object</a>
|
||||
* <a href="https://www.dropbox.com/developers/core/docs#metadata-details">metadata object</a>
|
||||
* for that file or folder, along with all immediate children if it's a folder. If not,
|
||||
* you'll get back <code>null</code>.
|
||||
*
|
||||
|
@ -796,7 +827,7 @@ class Client
|
|||
* A <code>list(boolean $changed, array $metadata)</code>. If the metadata hasn't changed,
|
||||
* you'll get <code>list(false, null)</code>. If the metadata of the folder or any of its
|
||||
* children has changed, you'll get <code>list(true, $newMetadata)</code>. $metadata is a
|
||||
* <a href="https://www.dropbox.com/developers/core/api#metadata-details">metadata object</a>.
|
||||
* <a href="https://www.dropbox.com/developers/core/docs#metadata-details">metadata object</a>.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
|
@ -830,8 +861,14 @@ class Client
|
|||
* If this is the first time you're calling this, pass in <code>null</code>. Otherwise,
|
||||
* pass in whatever cursor was returned by the previous call.
|
||||
*
|
||||
* @param string|null $pathPrefix
|
||||
* If <code>null</code>, you'll get results for the entire folder (either the user's
|
||||
* entire Dropbox or your App Folder). If you set <code>$path_prefix</code> to
|
||||
* "/Photos/Vacation", you'll only get results for that path and any files and folders
|
||||
* under it.
|
||||
*
|
||||
* @return array
|
||||
* A <a href="https://www.dropbox.com/developers/core/api#delta">delta page</a>, which
|
||||
* A <a href="https://www.dropbox.com/developers/core/docs#delta">delta page</a>, which
|
||||
* contains a list of changes to apply along with a new "cursor" that should be passed into
|
||||
* future <code>getDelta</code> calls. If the "reset" field is <code>true</code>, you
|
||||
* should clear your local state before applying the changes. If the "has_more" field is
|
||||
|
@ -840,11 +877,14 @@ class Client
|
|||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
function getDelta($cursor = null)
|
||||
function getDelta($cursor = null, $pathPrefix = null)
|
||||
{
|
||||
Checker::argStringNonEmptyOrNull("cursor", $cursor);
|
||||
Path::checkArgOrNull("pathPrefix", $pathPrefix);
|
||||
|
||||
$response = $this->doPost($this->apiHost, "1/delta", array("cursor" => $cursor));
|
||||
$response = $this->doPost($this->apiHost, "1/delta", array(
|
||||
"cursor" => $cursor,
|
||||
"path_prefix" => $pathPrefix));
|
||||
|
||||
if ($response->statusCode !== 200) throw RequestUtil::unexpectedStatus($response);
|
||||
|
||||
|
@ -854,7 +894,7 @@ class Client
|
|||
/**
|
||||
* Gets the metadata for all the file revisions (up to a limit) for a given path.
|
||||
*
|
||||
* See <a href="https://www.dropbox.com/developers/core/api#revisions">/revisions</a>.
|
||||
* See <a href="https://www.dropbox.com/developers/core/docs#revisions">/revisions</a>.
|
||||
*
|
||||
* @param string path
|
||||
* The Dropbox path that you want file revision metadata for (UTF-8).
|
||||
|
@ -863,7 +903,7 @@ class Client
|
|||
* The maximum number of revisions to return.
|
||||
*
|
||||
* @return array|null
|
||||
* A list of <a href="https://www.dropbox.com/developers/core/api#metadata-details>metadata
|
||||
* A list of <a href="https://www.dropbox.com/developers/core/docs#metadata-details>metadata
|
||||
* objects</a>, one for each file revision. The later revisions appear first in the list.
|
||||
* If <code>null</code>, then there were too many revisions at that path.
|
||||
*
|
||||
|
@ -889,7 +929,7 @@ class Client
|
|||
* Takes a copy of the file at the given revision and saves it over the current copy. This
|
||||
* will create a new revision, but the file contents will match the revision you specified.
|
||||
*
|
||||
* See <a href="https://www.dropbox.com/developers/core/api#restore">/restore</a>.
|
||||
* See <a href="https://www.dropbox.com/developers/core/docs#restore">/restore</a>.
|
||||
*
|
||||
* @param string $path
|
||||
* The Dropbox path of the file to restore (UTF-8).
|
||||
|
@ -898,7 +938,7 @@ class Client
|
|||
* The revision to restore the contents to.
|
||||
*
|
||||
* @return mixed
|
||||
* The <a href="https://www.dropbox.com/developers/core/api#metadata-details">metadata
|
||||
* The <a href="https://www.dropbox.com/developers/core/docs#metadata-details">metadata
|
||||
* object</a>
|
||||
*
|
||||
* @throws Exception
|
||||
|
@ -922,6 +962,8 @@ class Client
|
|||
/**
|
||||
* Returns metadata for all files and folders whose filename matches the query string.
|
||||
*
|
||||
* See <a href="https://www.dropbox.com/developers/core/docs#search">/search</a>.
|
||||
*
|
||||
* @param string $basePath
|
||||
* The path to limit the search to (UTF-8). Pass in "/" to search everything.
|
||||
*
|
||||
|
@ -936,7 +978,7 @@ class Client
|
|||
* Whether to include deleted files in the results.
|
||||
*
|
||||
* @return mixed
|
||||
* A list of <a href="https://www.dropbox.com/developers/core/api#metadata-details>metadata
|
||||
* A list of <a href="https://www.dropbox.com/developers/core/docs#metadata-details>metadata
|
||||
* objects</a> of files that match the search query.
|
||||
*
|
||||
* @throws Exception
|
||||
|
@ -967,7 +1009,7 @@ class Client
|
|||
* used without authentication. The preview page may contain a thumbnail or some other
|
||||
* preview of the file, along with a download link to download the actual file.
|
||||
*
|
||||
* See <a href="https://www.dropbox.com/developers/core/api#shares">/shares</a>.
|
||||
* See <a href="https://www.dropbox.com/developers/core/docs#shares">/shares</a>.
|
||||
*
|
||||
* @param string $path
|
||||
* The Dropbox path to the file or folder you want to create a shareable link to (UTF-8).
|
||||
|
@ -999,13 +1041,15 @@ class Client
|
|||
* Creates and returns a direct link to a file. This link can be used without authentication.
|
||||
* This link will expire in a few hours.
|
||||
*
|
||||
* See <a href="https://www.dropbox.com/developers/core/docs#media">/media</a>.
|
||||
*
|
||||
* @param string $path
|
||||
* The Dropbox path to a file or folder (UTF-8).
|
||||
*
|
||||
* @return array
|
||||
* A <code>list(string $url, \DateTime $expires) where <code>$url</code> is a direct link to
|
||||
* the requested file and <code>$expires</code> is a standard PHP <code>\DateTime</code>
|
||||
* representing when <code>$url</code> will stop working.
|
||||
* A <code>list(string $url, \DateTime $expires)</code> where <code>$url</code> is a direct
|
||||
* link to the requested file and <code>$expires</code> is a standard PHP
|
||||
* <code>\DateTime</code> representing when <code>$url</code> will stop working.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
|
@ -1035,6 +1079,8 @@ class Client
|
|||
* another account and call <code>copyFromCopyRef</code> using the copy ref. (You need to use
|
||||
* the same app key both times.)
|
||||
*
|
||||
* See <a href="https://www.dropbox.com/developers/core/docs#copy_ref">/copy_ref</a>.
|
||||
*
|
||||
* @param string path
|
||||
* The Dropbox path of the file or folder you want to create a copy ref for (UTF-8).
|
||||
*
|
||||
|
@ -1061,6 +1107,8 @@ class Client
|
|||
/**
|
||||
* Gets a thumbnail image representation of the file at the given path.
|
||||
*
|
||||
* See <a href="https://www.dropbox.com/developers/core/docs#thumbnails">/thumbnails</a>.
|
||||
*
|
||||
* @param string $path
|
||||
* The path to the file you want a thumbnail for (UTF-8).
|
||||
*
|
||||
|
@ -1080,7 +1128,7 @@ class Client
|
|||
* @return array|null
|
||||
* If the file exists, you'll get <code>list(array $metadata, string $data)</code> where
|
||||
* <code>$metadata</code> is the file's
|
||||
* <a href="https://www.dropbox.com/developers/core/api#metadata-details">metadata object</a>
|
||||
* <a href="https://www.dropbox.com/developers/core/docs#metadata-details">metadata object</a>
|
||||
* and $data is the raw data for the thumbnail image. If the file doesn't exist, you'll
|
||||
* get <code>null</code>.
|
||||
*
|
||||
|
@ -1098,8 +1146,7 @@ class Client
|
|||
throw new \InvalidArgumentException("Invalid 'size': ".self::q($format));
|
||||
}
|
||||
|
||||
$url = RequestUtil::buildUrl(
|
||||
$this->userLocale,
|
||||
$url = $this->buildUrlForGetOrPut(
|
||||
$this->contentHost,
|
||||
$this->appendFilePath("1/thumbnails", $path),
|
||||
array("size" => $size, "format" => $format));
|
||||
|
@ -1120,6 +1167,8 @@ class Client
|
|||
/**
|
||||
* Copies a file or folder to a new location
|
||||
*
|
||||
* See <a href="https://www.dropbox.com/developers/core/docs#fileops-copy">/fileops/copy</a>.
|
||||
*
|
||||
* @param string $fromPath
|
||||
* The Dropbox path of the file or folder you want to copy (UTF-8).
|
||||
*
|
||||
|
@ -1127,7 +1176,7 @@ class Client
|
|||
* The destination Dropbox path (UTF-8).
|
||||
*
|
||||
* @return mixed
|
||||
* The <a href="https://www.dropbox.com/developers/core/api#metadata-details">metadata
|
||||
* The <a href="https://www.dropbox.com/developers/core/docs#metadata-details">metadata
|
||||
* object</a> for the new file or folder.
|
||||
*
|
||||
* @throws Exception
|
||||
|
@ -1155,6 +1204,8 @@ class Client
|
|||
* Creates a file or folder based on an existing copy ref (possibly from a different Dropbox
|
||||
* account).
|
||||
*
|
||||
* See <a href="https://www.dropbox.com/developers/core/docs#fileops-copy">/fileops/copy</a>.
|
||||
*
|
||||
* @param string $copyRef
|
||||
* A copy ref obtained via the {@link createCopyRef()} call.
|
||||
*
|
||||
|
@ -1162,7 +1213,7 @@ class Client
|
|||
* The Dropbox path you want to copy the file or folder to (UTF-8).
|
||||
*
|
||||
* @return mixed
|
||||
* The <a href="https://www.dropbox.com/developers/core/api#metadata-details">metadata
|
||||
* The <a href="https://www.dropbox.com/developers/core/docs#metadata-details">metadata
|
||||
* object</a> for the new file or folder.
|
||||
*
|
||||
* @throws Exception
|
||||
|
@ -1190,12 +1241,14 @@ class Client
|
|||
/**
|
||||
* Creates a folder.
|
||||
*
|
||||
* See <a href="https://www.dropbox.com/developers/core/docs#fileops-create-folder">/fileops/create_folder</a>.
|
||||
*
|
||||
* @param string $path
|
||||
* The Dropbox path at which to create the folder (UTF-8).
|
||||
*
|
||||
* @return array|null
|
||||
* If successful, you'll get back the
|
||||
* <a href="https://www.dropbox.com/developers/core/api#metadata-details">metadata object</a>
|
||||
* <a href="https://www.dropbox.com/developers/core/docs#metadata-details">metadata object</a>
|
||||
* for the newly-created folder. If not successful, you'll get <code>null</code>.
|
||||
*
|
||||
* @throws Exception
|
||||
|
@ -1221,13 +1274,13 @@ class Client
|
|||
/**
|
||||
* Deletes a file or folder
|
||||
*
|
||||
* See <a href="https://www.dropbox.com/developers/core/api#fileops-delete">/fileops/delete</a>.
|
||||
* See <a href="https://www.dropbox.com/developers/core/docs#fileops-delete">/fileops/delete</a>.
|
||||
*
|
||||
* @param string $path
|
||||
* The Dropbox path of the file or folder to delete (UTF-8).
|
||||
*
|
||||
* @return mixed
|
||||
* The <a href="https://www.dropbox.com/developers/core/api#metadata-details">metadata
|
||||
* The <a href="https://www.dropbox.com/developers/core/docs#metadata-details">metadata
|
||||
* object</a> for the deleted file or folder.
|
||||
*
|
||||
* @throws Exception
|
||||
|
@ -1252,7 +1305,7 @@ class Client
|
|||
/**
|
||||
* Moves a file or folder to a new location.
|
||||
*
|
||||
* See <a href="https://www.dropbox.com/developers/core/api#fileops-move">/fileops/move</a>.
|
||||
* See <a href="https://www.dropbox.com/developers/core/docs#fileops-move">/fileops/move</a>.
|
||||
*
|
||||
* @param string $fromPath
|
||||
* The source Dropbox path (UTF-8).
|
||||
|
@ -1261,7 +1314,7 @@ class Client
|
|||
* The destination Dropbox path (UTF-8).
|
||||
*
|
||||
* @return mixed
|
||||
* The <a href="https://www.dropbox.com/developers/core/api#metadata-details">metadata
|
||||
* The <a href="https://www.dropbox.com/developers/core/docs#metadata-details">metadata
|
||||
* object</a> for the destination file or folder.
|
||||
*
|
||||
* @throws Exception
|
||||
|
@ -1286,14 +1339,39 @@ class Client
|
|||
}
|
||||
|
||||
/**
|
||||
* Build a URL for making a GET or PUT request. Will add the "locale"
|
||||
* parameter.
|
||||
*
|
||||
* @param string $host
|
||||
* Either the "API" or "API content" hostname from {@link getHost()}.
|
||||
* @param string $path
|
||||
* The "path" part of the URL. For example, "/account/info".
|
||||
* @param array|null $params
|
||||
* URL parameters. For POST requests, do not put the parameters here.
|
||||
* Include them in the request body instead.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function buildUrlForGetOrPut($host, $path, $params = null)
|
||||
{
|
||||
return RequestUtil::buildUrlForGetOrPut($this->userLocale, $host, $path, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an OAuth-2-authorized GET 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, "/account/info".
|
||||
* @param array|null $params
|
||||
* GET parameters.
|
||||
* @return HttpResponse
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
private function doGet($host, $path, $params = null)
|
||||
function doGet($host, $path, $params = null)
|
||||
{
|
||||
Checker::argString("host", $host);
|
||||
Checker::argString("path", $path);
|
||||
|
@ -1302,14 +1380,20 @@ class Client
|
|||
}
|
||||
|
||||
/**
|
||||
* 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 HttpResponse
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
private function doPost($host, $path, $params = null)
|
||||
function doPost($host, $path, $params = null)
|
||||
{
|
||||
Checker::argString("host", $host);
|
||||
Checker::argString("path", $path);
|
||||
|
@ -1318,12 +1402,17 @@ class Client
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a {@link Curl} object that is pre-configured with {@link getClientIdentifier()},
|
||||
* and the proper OAuth 2 "Authorization" header.
|
||||
*
|
||||
* @param string $url
|
||||
* Generate this URL using {@link buildUrl()}.
|
||||
*
|
||||
* @return Curl
|
||||
*/
|
||||
private function mkCurl($url, $maxsize=0)
|
||||
function mkCurl($url)
|
||||
{
|
||||
return RequestUtil::mkCurl($this->clientIdentifier, $url, $this->accessToken, $maxsize);
|
||||
return RequestUtil::mkCurlWithOAuth($this->clientIdentifier, $url, $this->accessToken);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1360,7 +1449,52 @@ class Client
|
|||
static function getField($j, $fieldName)
|
||||
{
|
||||
if (!array_key_exists($fieldName, $j)) throw new Exception_BadResponse(
|
||||
"missing field \"$fieldName\": $body");
|
||||
"missing field \"$fieldName\" in ".self::q($j));
|
||||
return $j[$fieldName];
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an OAuth 2 access token, returns <code>null</code> if it is well-formed (though
|
||||
* not necessarily valid). Otherwise, returns a string describing what's wrong with it.
|
||||
*
|
||||
* @param string $s
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static function getAccessTokenError($s)
|
||||
{
|
||||
if ($s === null) return "can't be null";
|
||||
if (strlen($s) === 0) return "can't be empty";
|
||||
if (preg_match('@[^-=_~/A-Za-z0-9\.\+]@', $s) === 1) return "contains invalid character";
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
static function checkAccessTokenArg($argName, $accessToken)
|
||||
{
|
||||
$error = self::getAccessTokenError($accessToken);
|
||||
if ($error !== null) throw new \InvalidArgumentException("'$argName' invalid: $error");
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
static function getClientIdentifierError($s)
|
||||
{
|
||||
if ($s === null) return "can't be null";
|
||||
if (strlen($s) === 0) return "can't be empty";
|
||||
if (preg_match('@[\x00-\x1f\x7f]@', $s) === 1) return "contains control character";
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
static function checkClientIdentifierArg($argName, $accessToken)
|
||||
{
|
||||
$error = self::getClientIdentifierError($accessToken);
|
||||
if ($error !== null) throw new \InvalidArgumentException("'$argName' invalid: $error");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,18 +11,14 @@ final class Curl
|
|||
/** @var resource */
|
||||
public $handle;
|
||||
|
||||
public $maxsize;
|
||||
|
||||
/** @var string[] */
|
||||
private $headers = array();
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
*/
|
||||
function __construct($url, $maxsize = 0)
|
||||
function __construct($url)
|
||||
{
|
||||
$this->maxsize = $maxsize;
|
||||
|
||||
// Make sure there aren't any spaces in the URL (i.e. the caller forgot to URL-encode).
|
||||
if (strpos($url, ' ') !== false) {
|
||||
throw new \InvalidArgumentException("Found space in \$url; it should be encoded");
|
||||
|
@ -30,28 +26,35 @@ final class Curl
|
|||
|
||||
$this->handle = curl_init($url);
|
||||
|
||||
// Force SSL and use our own certificate list.
|
||||
$this->set(CURLOPT_SSL_VERIFYPEER, true);
|
||||
$this->set(CURLOPT_SSL_VERIFYHOST, 2);
|
||||
$this->set(CURLOPT_SSLVERSION, 3); // Force SSL v3.
|
||||
$this->set(CURLOPT_CAINFO, __DIR__."/trusted-certs.crt");
|
||||
// NOTE: Though we turn on all the correct SSL settings, many PHP installations
|
||||
// don't respect these settings. Run "examples/test-ssl.php" to run some basic
|
||||
// SSL tests to see how well your PHP implementation behaves.
|
||||
|
||||
if ($this->maxsize > 0) {
|
||||
// Check if we get excepted minimum length
|
||||
$this->set(CURLOPT_BUFFERSIZE, 1024);
|
||||
$this->set(CURLOPT_NOPROGRESS, false);
|
||||
$this->set(CURLOPT_PROGRESSFUNCTION, array($this, 'progressChunk'));
|
||||
// Use our own certificate list.
|
||||
$this->set(CURLOPT_SSL_VERIFYPEER, true); // Enforce certificate validation
|
||||
$this->set(CURLOPT_SSL_VERIFYHOST, 2); // Enforce hostname validation
|
||||
|
||||
// Force the use of TLS (SSL v2 and v3 are not secure).
|
||||
// TODO: Use "CURL_SSLVERSION_TLSv1" instead of "1" once we can rely on PHP 5.5+.
|
||||
$this->set(CURLOPT_SSLVERSION, 1);
|
||||
|
||||
// Limit the set of ciphersuites used.
|
||||
global $sslCiphersuiteList;
|
||||
if ($sslCiphersuiteList !== null) {
|
||||
$this->set(CURLOPT_SSL_CIPHER_LIST, $sslCiphersuiteList);
|
||||
}
|
||||
|
||||
// Certificate file.
|
||||
$this->set(CURLOPT_CAINFO, __DIR__.'/certs/trusted-certs.crt');
|
||||
// Certificate folder. If not specified, some PHP installations will use
|
||||
// the system default, even when CURLOPT_CAINFO is specified.
|
||||
$this->set(CURLOPT_CAPATH, __DIR__.'/certs/');
|
||||
|
||||
// Limit vulnerability surface area. Supported in cURL 7.19.4+
|
||||
if (defined('CURLOPT_PROTOCOLS')) $this->set(CURLOPT_PROTOCOLS, CURLPROTO_HTTPS);
|
||||
if (defined('CURLOPT_REDIR_PROTOCOLS')) $this->set(CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTPS);
|
||||
}
|
||||
|
||||
function progressChunk($downloadSize, $downloaded, $uploadSize, $uploaded) {
|
||||
return ($this->maxsize > 0 && $downloaded >= $this->maxsize);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $header
|
||||
*/
|
||||
|
@ -66,9 +69,7 @@ final class Curl
|
|||
|
||||
$body = curl_exec($this->handle);
|
||||
if ($body === false) {
|
||||
if ($this->maxsize == 0 || curl_errno($this->handle) != CURLE_ABORTED_BY_CALLBACK) {
|
||||
throw new Exception_NetworkIO("Error executing HTTP request: " . curl_error($this->handle));
|
||||
}
|
||||
throw new Exception_NetworkIO("Error executing HTTP request: " . curl_error($this->handle));
|
||||
}
|
||||
|
||||
$statusCode = curl_getinfo($this->handle, CURLINFO_HTTP_CODE);
|
||||
|
@ -90,3 +91,35 @@ final class Curl
|
|||
curl_close($this->handle);
|
||||
}
|
||||
}
|
||||
|
||||
// Different cURL SSL backends use different names for ciphersuites.
|
||||
$curlVersion = \curl_version();
|
||||
$curlSslBackend = $curlVersion['ssl_version'];
|
||||
if (\substr_compare($curlSslBackend, "NSS/", 0, strlen("NSS/")) === 0) {
|
||||
// Can't figure out how to reliably set ciphersuites for NSS.
|
||||
$sslCiphersuiteList = null;
|
||||
}
|
||||
else {
|
||||
// Use the OpenSSL names for all other backends. We may have to
|
||||
// refine this if users report errors.
|
||||
$sslCiphersuiteList =
|
||||
'ECDHE-RSA-AES256-GCM-SHA384:'.
|
||||
'ECDHE-RSA-AES128-GCM-SHA256:'.
|
||||
'ECDHE-RSA-AES256-SHA384:'.
|
||||
'ECDHE-RSA-AES128-SHA256:'.
|
||||
'ECDHE-RSA-AES256-SHA:'.
|
||||
'ECDHE-RSA-AES128-SHA:'.
|
||||
'ECDHE-RSA-RC4-SHA:'.
|
||||
'DHE-RSA-AES256-GCM-SHA384:'.
|
||||
'DHE-RSA-AES128-GCM-SHA256:'.
|
||||
'DHE-RSA-AES256-SHA256:'.
|
||||
'DHE-RSA-AES128-SHA256:'.
|
||||
'DHE-RSA-AES256-SHA:'.
|
||||
'DHE-RSA-AES128-SHA:'.
|
||||
'AES256-GCM-SHA384:'.
|
||||
'AES128-GCM-SHA256:'.
|
||||
'AES256-SHA256:'.
|
||||
'AES128-SHA256:'.
|
||||
'AES256-SHA:'.
|
||||
'AES128-SHA';
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@ class CurlStreamRelay
|
|||
$this->errorData[] = $data;
|
||||
} else {
|
||||
fwrite($this->outStream, $data);
|
||||
ob_flush();
|
||||
}
|
||||
|
||||
return strlen($data);
|
||||
|
@ -44,4 +43,3 @@ class CurlStreamRelay
|
|||
return implode($this->errorData);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
61
modules/Dropbox/OAuth1AccessToken.php
Normal file
61
modules/Dropbox/OAuth1AccessToken.php
Normal file
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
namespace Dropbox;
|
||||
|
||||
/**
|
||||
* Use with {@link OAuth1Upgrader} to convert old OAuth 1 access tokens
|
||||
* to OAuth 2 access tokens. This SDK doesn't support using OAuth 1
|
||||
* access tokens for regular API calls.
|
||||
*/
|
||||
class OAuth1AccessToken
|
||||
{
|
||||
/**
|
||||
* The OAuth 1 access token key.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getKey() { return $this->key; }
|
||||
|
||||
/** @var string */
|
||||
private $key;
|
||||
|
||||
/**
|
||||
* The OAuth 1 access token secret.
|
||||
*
|
||||
* Make sure that this is kept a secret. Someone with your app secret can impesonate your
|
||||
* application. People sometimes ask for help on the Dropbox API forums and
|
||||
* copy/paste code that includes their app secret. Do not do that.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getSecret() { return $this->secret; }
|
||||
|
||||
/** @var secret */
|
||||
private $secret;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $key
|
||||
* {@link getKey()}
|
||||
* @param string $secret
|
||||
* {@link getSecret()}
|
||||
*/
|
||||
function __construct($key, $secret)
|
||||
{
|
||||
AppInfo::checkKeyArg($key);
|
||||
AppInfo::checkSecretArg($secret);
|
||||
|
||||
$this->key = $key;
|
||||
$this->secret = $secret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this to check that a function argument is of type <code>AppInfo</code>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
static function checkArg($argName, $argValue)
|
||||
{
|
||||
if (!($argValue instanceof self)) Checker::throwError($argName, $argValue, __CLASS__);
|
||||
}
|
||||
}
|
104
modules/Dropbox/OAuth1Upgrader.php
Normal file
104
modules/Dropbox/OAuth1Upgrader.php
Normal file
|
@ -0,0 +1,104 @@
|
|||
<?php
|
||||
namespace Dropbox;
|
||||
|
||||
/**
|
||||
* Lets you convert OAuth 1 access tokens to OAuth 2 access tokens. First call {@link
|
||||
* OAuth1AccessTokenUpgrader::createOAuth2AccessToken()} to get an OAuth 2 access token.
|
||||
* If that succeeds, call {@link OAuth1AccessTokenUpgrader::disableOAuth1AccessToken()}
|
||||
* to disable the OAuth 1 access token.
|
||||
*
|
||||
* <code>
|
||||
* use \Dropbox as dbx;
|
||||
* $appInfo = dbx\AppInfo::loadFromJsonFile(...);
|
||||
* $clientIdentifier = "my-app/1.0";
|
||||
* $oauth1AccessToken = dbx\OAuth1AccessToken(...);
|
||||
*
|
||||
* $upgrader = new dbx\OAuth1AccessTokenUpgrader($appInfo, $clientIdentifier, ...);
|
||||
* $oauth2AccessToken = $upgrader->getOAuth2AccessToken($oauth1AccessToken);
|
||||
* $upgrader->disableOAuth1AccessToken($oauth1AccessToken);
|
||||
* </code>
|
||||
*/
|
||||
class OAuth1Upgrader extends AuthBase
|
||||
{
|
||||
/**
|
||||
* Given an existing active OAuth 1 access token, make a Dropbox API call to get a new OAuth 2
|
||||
* access token that represents the same user and app.
|
||||
*
|
||||
* See <a href="https://www.dropbox.com/developers/core/docs#oa1-from-oa1">/oauth2/token_from_oauth1</a>.
|
||||
*
|
||||
* @param OAuth1AccessToken $oauth1AccessToken
|
||||
*
|
||||
* @return string
|
||||
* The OAuth 2 access token.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
function createOAuth2AccessToken($oauth1AccessToken)
|
||||
{
|
||||
OAuth1AccessToken::checkArg("oauth1AccessToken", $oauth1AccessToken);
|
||||
|
||||
$response = self::doPost($oauth1AccessToken, "1/oauth2/token_from_oauth1");
|
||||
|
||||
if ($response->statusCode !== 200) throw RequestUtil::unexpectedStatus($response);
|
||||
|
||||
$parts = RequestUtil::parseResponseJson($response->body);
|
||||
|
||||
if (!array_key_exists('token_type', $parts) || !is_string($parts['token_type'])) {
|
||||
throw new Exception_BadResponse("Missing \"token_type\" field.");
|
||||
}
|
||||
$tokenType = $parts['token_type'];
|
||||
if (!array_key_exists('access_token', $parts) || !is_string($parts['access_token'])) {
|
||||
throw new Exception_BadResponse("Missing \"access_token\" field.");
|
||||
}
|
||||
$accessToken = $parts['access_token'];
|
||||
|
||||
if ($tokenType !== "Bearer" && $tokenType !== "bearer") {
|
||||
throw new Exception_BadResponse("Unknown \"token_type\"; expecting \"Bearer\", got "
|
||||
.Client::q($tokenType));
|
||||
}
|
||||
|
||||
return $accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a Dropbox API call to disable the given OAuth 1 access token.
|
||||
*
|
||||
* See <a href="https://www.dropbox.com/developers/core/docs#disable-token">/disable_access_token</a>.
|
||||
*
|
||||
* @param OAuth1AccessToken $oauth1AccessToken
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
function disableOAuth1AccessToken($oauth1AccessToken)
|
||||
{
|
||||
OAuth1AccessToken::checkArg("oauth1AccessToken", $oauth1AccessToken);
|
||||
|
||||
$response = self::doPost($oauth1AccessToken, "1/disable_access_token");
|
||||
|
||||
if ($response->statusCode !== 200) throw RequestUtil::unexpectedStatus($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OAuth1AccessToken $oauth1AccessToken
|
||||
* @param string $path
|
||||
*
|
||||
* @return HttpResponse
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
private function doPost($oauth1AccessToken, $path)
|
||||
{
|
||||
// Construct the OAuth 1 header.
|
||||
$signature = rawurlencode($this->appInfo->getSecret()) . "&" . rawurlencode($oauth1AccessToken->getSecret());
|
||||
$authHeaderValue = "OAuth oauth_signature_method=\"PLAINTEXT\""
|
||||
. ", oauth_consumer_key=\"" . rawurlencode($this->appInfo->getKey()) . "\""
|
||||
. ", oauth_token=\"" . rawurlencode($oauth1AccessToken->getKey()) . "\""
|
||||
. ", oauth_signature=\"" . $signature . "\"";
|
||||
|
||||
return RequestUtil::doPostWithSpecificAuth(
|
||||
$this->clientIdentifier, $authHeaderValue, $this->userLocale,
|
||||
$this->appInfo->getHost()->getApi(),
|
||||
$path,
|
||||
null);
|
||||
}
|
||||
}
|
|
@ -141,6 +141,19 @@ final class Path
|
|||
if ($error !== null) throw new \InvalidArgumentException("'$argName'': bad path: $error: ".var_export($value, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @param string $argName
|
||||
* @param mixed $value
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
static function checkArgOrNull($argName, $value)
|
||||
{
|
||||
if ($value === null) return;
|
||||
self::checkArg($argName, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
|
|
|
@ -9,10 +9,17 @@ if (!function_exists('json_decode')) {
|
|||
throw new \Exception("The Dropbox SDK requires the JSON PHP extension, but it looks like you don't have it (couldn't find function \"json_decode\"). Library: \"" . __FILE__ . "\".");
|
||||
}
|
||||
|
||||
// If mbstring.func_overload is set, it changes the behavior of the standard string functions in
|
||||
// ways that makes this library break.
|
||||
$mbstring_func_overload = ini_get("mbstring.func_overload");
|
||||
if ($mbstring_func_overload & 2 == 2) {
|
||||
throw new \Exception("The Dropbox SDK doesn't work when mbstring.func_overload is set to overload the standard string functions (value = ".var_export($mbstring_func_overload, true)."). Library: \"" . __FILE__ . "\".");
|
||||
}
|
||||
|
||||
if (strlen((string) PHP_INT_MAX) < 19) {
|
||||
// Looks like we're running on a 32-bit build of PHP. This could cause problems because some of the numbers
|
||||
// we use (file sizes, quota, etc) can be larger than 32-bit ints can handle.
|
||||
//throw new \Exception("The Dropbox SDK uses 64-bit integers, but it looks like we're running on a version of PHP that doesn't support 64-bit integers (PHP_INT_MAX=" . ((string) PHP_INT_MAX) . "). Library: \"" . __FILE__ . "\"");
|
||||
throw new \Exception("The Dropbox SDK uses 64-bit integers, but it looks like we're running on a version of PHP that doesn't support 64-bit integers (PHP_INT_MAX=" . ((string) PHP_INT_MAX) . "). Library: \"" . __FILE__ . "\"");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -27,7 +34,7 @@ final class RequestUtil
|
|||
* @param array $params
|
||||
* @return string
|
||||
*/
|
||||
static function buildUrl($userLocale, $host, $path, $params = null)
|
||||
static function buildUrlForGetOrPut($userLocale, $host, $path, $params = null)
|
||||
{
|
||||
$url = self::buildUri($host, $path);
|
||||
$url .= "?locale=" . rawurlencode($userLocale);
|
||||
|
@ -69,9 +76,9 @@ final class RequestUtil
|
|||
* @param string $url
|
||||
* @return Curl
|
||||
*/
|
||||
static function mkCurlWithoutAuth($clientIdentifier, $url, $maxsize=0)
|
||||
static function mkCurl($clientIdentifier, $url)
|
||||
{
|
||||
$curl = new Curl($url, $maxsize);
|
||||
$curl = new Curl($url);
|
||||
|
||||
$curl->set(CURLOPT_CONNECTTIMEOUT, 10);
|
||||
|
||||
|
@ -86,17 +93,28 @@ final class RequestUtil
|
|||
return $curl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $clientIdentifier
|
||||
* @param string $url
|
||||
* @param string $authHeaderValue
|
||||
* @return Curl
|
||||
*/
|
||||
static function mkCurlWithAuth($clientIdentifier, $url, $authHeaderValue)
|
||||
{
|
||||
$curl = self::mkCurl($clientIdentifier, $url);
|
||||
$curl->addHeader("Authorization: $authHeaderValue");
|
||||
return $curl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $clientIdentifier
|
||||
* @param string $url
|
||||
* @param string $accessToken
|
||||
* @return Curl
|
||||
*/
|
||||
static function mkCurl($clientIdentifier, $url, $accessToken, $maxsize=0)
|
||||
static function mkCurlWithOAuth($clientIdentifier, $url, $accessToken)
|
||||
{
|
||||
$curl = self::mkCurlWithoutAuth($clientIdentifier, $url, $maxsize);
|
||||
$curl->addHeader("Authorization: Bearer $accessToken");
|
||||
return $curl;
|
||||
return self::mkCurlWithAuth($clientIdentifier, $url, "Bearer $accessToken");
|
||||
}
|
||||
|
||||
static function buildPostBody($params)
|
||||
|
@ -123,6 +141,7 @@ final class RequestUtil
|
|||
}
|
||||
|
||||
/**
|
||||
* @param string $clientIdentifier
|
||||
* @param string $accessToken
|
||||
* @param string $userLocale
|
||||
* @param string $host
|
||||
|
@ -142,7 +161,7 @@ final class RequestUtil
|
|||
if ($params === null) $params = array();
|
||||
$params['locale'] = $userLocale;
|
||||
|
||||
$curl = self::mkCurl($clientIdentifier, $url, $accessToken);
|
||||
$curl = self::mkCurlWithOAuth($clientIdentifier, $url, $accessToken);
|
||||
$curl->set(CURLOPT_POST, true);
|
||||
$curl->set(CURLOPT_POSTFIELDS, self::buildPostBody($params));
|
||||
|
||||
|
@ -151,6 +170,36 @@ final class RequestUtil
|
|||
}
|
||||
|
||||
/**
|
||||
* @param string $clientIdentifier
|
||||
* @param string $authHeaderValue
|
||||
* @param string $userLocale
|
||||
* @param string $host
|
||||
* @param string $path
|
||||
* @param array|null $params
|
||||
*
|
||||
* @return HttpResponse
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
static function doPostWithSpecificAuth($clientIdentifier, $authHeaderValue, $userLocale, $host, $path, $params = null)
|
||||
{
|
||||
Checker::argStringNonEmpty("authHeaderValue", $authHeaderValue);
|
||||
|
||||
$url = self::buildUri($host, $path);
|
||||
|
||||
if ($params === null) $params = array();
|
||||
$params['locale'] = $userLocale;
|
||||
|
||||
$curl = self::mkCurlWithAuth($clientIdentifier, $url, $authHeaderValue);
|
||||
$curl->set(CURLOPT_POST, true);
|
||||
$curl->set(CURLOPT_POSTFIELDS, self::buildPostBody($params));
|
||||
|
||||
$curl->set(CURLOPT_RETURNTRANSFER, true);
|
||||
return $curl->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $clientIdentifier
|
||||
* @param string $accessToken
|
||||
* @param string $userLocale
|
||||
* @param string $host
|
||||
|
@ -165,9 +214,9 @@ final class RequestUtil
|
|||
{
|
||||
Checker::argStringNonEmpty("accessToken", $accessToken);
|
||||
|
||||
$url = self::buildUrl($userLocale, $host, $path, $params);
|
||||
$url = self::buildUrlForGetOrPut($userLocale, $host, $path, $params);
|
||||
|
||||
$curl = self::mkCurl($clientIdentifier, $url, $accessToken);
|
||||
$curl = self::mkCurlWithOAuth($clientIdentifier, $url, $accessToken);
|
||||
$curl->set(CURLOPT_HTTPGET, true);
|
||||
$curl->set(CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
|
@ -181,7 +230,7 @@ final class RequestUtil
|
|||
*/
|
||||
static function parseResponseJson($responseBody)
|
||||
{
|
||||
$obj = json_decode($responseBody, TRUE, 10);
|
||||
$obj = json_decode($responseBody, true, 10);
|
||||
if ($obj === null) {
|
||||
throw new Exception_BadResponse("Got bad JSON from server: $responseBody");
|
||||
}
|
||||
|
@ -203,7 +252,7 @@ final class RequestUtil
|
|||
if ($sc === 500 || $sc === 502) return new Exception_ServerError($message);
|
||||
if ($sc === 503) return new Exception_RetryLater($message);
|
||||
|
||||
return new Exception_BadResponse("Unexpected $message");
|
||||
return new Exception_BadResponseCode("Unexpected $message", $sc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
132
modules/Dropbox/SSLTester.php
Normal file
132
modules/Dropbox/SSLTester.php
Normal file
|
@ -0,0 +1,132 @@
|
|||
<?php
|
||||
|
||||
namespace Dropbox;
|
||||
|
||||
/**
|
||||
* Call the <code>test()</code> method.
|
||||
*/
|
||||
class SSLTester
|
||||
{
|
||||
/**
|
||||
* Peforms a few basic tests of your PHP installation's SSL implementation to see
|
||||
* if it insecure in an obvious way. Results are written with "echo" and the output
|
||||
* is HTML-safe.
|
||||
*
|
||||
* @return bool
|
||||
* Returns <code>true</code> if all the tests passed.
|
||||
*/
|
||||
static function test()
|
||||
{
|
||||
$hostOs = php_uname('s').' '.php_uname('r');
|
||||
$phpVersion = phpversion();
|
||||
$curlVersionInfo = \curl_version();
|
||||
$curlVersion = $curlVersionInfo['version'];
|
||||
$curlSslBackend = $curlVersionInfo['ssl_version'];
|
||||
|
||||
echo "-----------------------------------------------------------------------------\n";
|
||||
echo "Testing your PHP installation's SSL implementation for a few obvious problems...\n";
|
||||
echo "-----------------------------------------------------------------------------\n";
|
||||
echo "- Host OS: $hostOs\n";
|
||||
echo "- PHP version: $phpVersion\n";
|
||||
echo "- cURL version: $curlVersion\n";
|
||||
echo "- cURL SSL backend: $curlSslBackend\n";
|
||||
|
||||
echo "Basic SSL tests\n";
|
||||
$basicFailures = self::testMulti(array(
|
||||
array("www.dropbox.com", 'testAllowed'),
|
||||
array("www.digicert.com", 'testAllowed'),
|
||||
array("www.v.dropbox.com", 'testHostnameMismatch'),
|
||||
array("testssl-expire.disig.sk", 'testUntrustedCert'),
|
||||
));
|
||||
|
||||
echo "Pinned certificate tests\n";
|
||||
$pinnedCertFailures = self::testMulti(array(
|
||||
array("www.verisign.com", 'testUntrustedCert'),
|
||||
array("www.globalsign.fr", 'testUntrustedCert'),
|
||||
));
|
||||
|
||||
if ($basicFailures) {
|
||||
echo "-----------------------------------------------------------------------------\n";
|
||||
echo "WARNING: Your PHP installation's SSL support is COMPLETELY INSECURE.\n";
|
||||
echo "Your app's communication with the Dropbox API servers can be viewed and\n";
|
||||
echo "manipulated by others. Try upgrading your version of PHP.\n";
|
||||
echo "-----------------------------------------------------------------------------\n";
|
||||
return false;
|
||||
}
|
||||
else if ($pinnedCertFailures) {
|
||||
echo "-----------------------------------------------------------------------------\n";
|
||||
echo "WARNING: Your PHP installation's cURL module doesn't support SSL certificate\n";
|
||||
echo "pinning, which is an important security feature of the Dropbox SDK.\n";
|
||||
echo "\n";
|
||||
echo "This SDK uses CURLOPT_CAINFO and CURLOPT_CAPATH to tell PHP cURL to only trust\n";
|
||||
echo "our custom certificate list. But your PHP installation's cURL module seems to\n";
|
||||
echo "trust certificates that aren't on that list.\n";
|
||||
echo "\n";
|
||||
echo "More information on SSL certificate pinning:\n";
|
||||
echo "https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#What_Is_Pinning.3F\n";
|
||||
echo "-----------------------------------------------------------------------------\n";
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static function testMulti($tests)
|
||||
{
|
||||
$anyFailed = false;
|
||||
foreach ($tests as $test) {
|
||||
list($host, $testType) = $test;
|
||||
|
||||
echo " - ".str_pad("$testType ($host) ", 50, ".");
|
||||
$url = "https://$host/";
|
||||
$passed = self::$testType($url);
|
||||
if ($passed) {
|
||||
echo " ok\n";
|
||||
} else {
|
||||
echo " FAILED\n";
|
||||
$anyFailed = true;
|
||||
}
|
||||
}
|
||||
return $anyFailed;
|
||||
}
|
||||
|
||||
private static function testPinnedCert()
|
||||
{
|
||||
}
|
||||
|
||||
private static function testAllowed($url)
|
||||
{
|
||||
$curl = RequestUtil::mkCurl("test-ssl", $url);
|
||||
$curl->set(CURLOPT_RETURNTRANSFER, true);
|
||||
$curl->exec();
|
||||
return true;
|
||||
}
|
||||
|
||||
private static function testUntrustedCert($url)
|
||||
{
|
||||
return self::testDisallowed($url, 'Error executing HTTP request: SSL certificate problem, verify that the CA cert is OK');
|
||||
}
|
||||
|
||||
private static function testHostnameMismatch($url)
|
||||
{
|
||||
return self::testDisallowed($url, 'Error executing HTTP request: SSL certificate problem: Invalid certificate chain');
|
||||
}
|
||||
|
||||
private static function testDisallowed($url, $expectedExceptionMessage)
|
||||
{
|
||||
$curl = RequestUtil::mkCurl("test-ssl", $url);
|
||||
$curl->set(CURLOPT_RETURNTRANSFER, true);
|
||||
try {
|
||||
$curl->exec();
|
||||
}
|
||||
catch (Exception_NetworkIO $ex) {
|
||||
if (strpos($ex->getMessage(), $expectedExceptionMessage) == 0) {
|
||||
return true;
|
||||
} else {
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -22,14 +22,16 @@ class Security
|
|||
{
|
||||
// Be strict with arguments. PHP's liberal types could get us pwned.
|
||||
if (func_num_args() !== 2) {
|
||||
throw \InvalidArgumentException("Expecting 2 args, got ".func_num_args().".");
|
||||
throw new \InvalidArgumentException("Expecting 2 args, got ".func_num_args().".");
|
||||
}
|
||||
Checker::argString("a", $a);
|
||||
Checker::argString("b", $b);
|
||||
|
||||
if (strlen($a) !== strlen($b)) return false;
|
||||
$len = strlen($a);
|
||||
if (strlen($b) !== $len) return false;
|
||||
|
||||
$result = 0;
|
||||
for ($i = 0; $i < strlen($a); $i++) {
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$result |= ord($a[$i]) ^ ord($b[$i]);
|
||||
}
|
||||
return $result === 0;
|
||||
|
@ -60,6 +62,6 @@ class Security
|
|||
|
||||
// Hopefully the above two options cover all our users. But if not, there are
|
||||
// other platform-specific options we could add.
|
||||
assert(False, "no suitable random number source available");
|
||||
throw new \Exception("no suitable random number source available");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,6 +130,8 @@ class WebAuth extends WebAuthBase
|
|||
* the constructor. This CSRF token will be checked on {@link finish()} to prevent
|
||||
* request forgery.
|
||||
*
|
||||
* See <a href="https://www.dropbox.com/developers/core/docs#oa2-authorize">/oauth2/authorize</a>.
|
||||
*
|
||||
* @param string|null $urlState
|
||||
* Any data you would like to keep in the URL through the authorization process.
|
||||
* This exact state will be returned to you by {@link finish()}.
|
||||
|
@ -159,15 +161,12 @@ class WebAuth extends WebAuthBase
|
|||
return strtr(base64_encode($string), '+/', '-_');
|
||||
}
|
||||
|
||||
private static function decodeCsrfToken($string)
|
||||
{
|
||||
return base64_decode(strtr($string, '-_', '+/'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
|
@ -201,10 +200,10 @@ class WebAuth extends WebAuthBase
|
|||
Checker::argString("queryParams['state']", $state);
|
||||
|
||||
$error = null;
|
||||
$errorDescription = null;
|
||||
if (isset($queryParams['error'])) {
|
||||
$error = $queryParams['error'];
|
||||
Checker::argString("queryParams['error']", $error);
|
||||
$errorDescription = null;
|
||||
if (isset($queryParams['error_description'])) {
|
||||
$errorDescription = $queryParams['error_description'];
|
||||
Checker::argString("queryParams['error_description']", $errorDescription);
|
||||
|
@ -230,8 +229,6 @@ class WebAuth extends WebAuthBase
|
|||
if ($csrfTokenFromSession === null) {
|
||||
throw new WebAuthException_BadState();
|
||||
}
|
||||
// Sanity check to make sure something hasn't gone terribly wrong.
|
||||
assert(strlen($csrfTokenFromSession) > 20);
|
||||
|
||||
$splitPos = strpos($state, "|");
|
||||
if ($splitPos === false) {
|
||||
|
|
|
@ -4,78 +4,11 @@ namespace Dropbox;
|
|||
/**
|
||||
* The base class for the two auth options.
|
||||
*/
|
||||
class WebAuthBase
|
||||
class WebAuthBase extends AuthBase
|
||||
{
|
||||
/**
|
||||
* Whatever AppInfo was passed into the constructor.
|
||||
*
|
||||
* @return AppInfo
|
||||
*/
|
||||
function getAppInfo() { return $this->appInfo; }
|
||||
|
||||
/** @var AppInfo */
|
||||
private $appInfo;
|
||||
|
||||
/**
|
||||
* An identifier for the API client, typically of the form "Name/Version".
|
||||
* This is used to set the HTTP <code>User-Agent</code> header when making API requests.
|
||||
* Example: <code>"PhotoEditServer/1.3"</code>
|
||||
*
|
||||
* If you're the author a higher-level library on top of the basic SDK, and the
|
||||
* "Photo Edit" app's server code is using your library to access Dropbox, you should append
|
||||
* your library's name and version to form the full identifier. For example,
|
||||
* if your library is called "File Picker", you might set this field to:
|
||||
* <code>"PhotoEditServer/1.3 FilePicker/0.1-beta"</code>
|
||||
*
|
||||
* The exact format of the <code>User-Agent</code> header is described in
|
||||
* <a href="http://tools.ietf.org/html/rfc2616#section-3.8">section 3.8 of the HTTP specification</a>.
|
||||
*
|
||||
* Note that underlying HTTP client may append other things to the <code>User-Agent</code>, such as
|
||||
* the name of the library being used to actually make the HTTP request (such as cURL).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getClientIdentifier() { return $this->clientIdentifier; }
|
||||
|
||||
/** @var string */
|
||||
private $clientIdentifier;
|
||||
|
||||
/**
|
||||
* The locale of the user of your application. Some API calls return localized
|
||||
* data and error messages; this "user locale" setting determines which locale
|
||||
* the server should use to localize those strings.
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
function getUserLocale() { return $this->userLocale; }
|
||||
|
||||
/** @var string */
|
||||
private $userLocale;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param AppInfo $appInfo
|
||||
* See {@link getAppInfo()}
|
||||
* @param string $clientIdentifier
|
||||
* See {@link getClientIdentifier()}
|
||||
* @param null|string $userLocale
|
||||
* See {@link getUserLocale()}
|
||||
*/
|
||||
function __construct($appInfo, $clientIdentifier, $userLocale = null)
|
||||
{
|
||||
AppInfo::checkArg("appInfo", $appInfo);
|
||||
Checker::argStringNonEmpty("clientIdentifier", $clientIdentifier);
|
||||
Checker::argStringNonEmptyOrNull("userLocale", $userLocale);
|
||||
|
||||
$this->appInfo = $appInfo;
|
||||
$this->clientIdentifier = $clientIdentifier;
|
||||
$this->userLocale = $userLocale;
|
||||
}
|
||||
|
||||
protected function _getAuthorizeUrl($redirectUri, $state)
|
||||
{
|
||||
return RequestUtil::buildUrl(
|
||||
return RequestUtil::buildUrlForGetOrPut(
|
||||
$this->userLocale,
|
||||
$this->appInfo->getHost()->getWeb(),
|
||||
"1/oauth2/authorize",
|
||||
|
@ -89,39 +22,33 @@ class WebAuthBase
|
|||
|
||||
protected function _finish($code, $originalRedirectUri)
|
||||
{
|
||||
$url = RequestUtil::buildUri($this->appInfo->getHost()->getApi(), "1/oauth2/token");
|
||||
$params = array(
|
||||
"grant_type" => "authorization_code",
|
||||
"code" => $code,
|
||||
"redirect_uri" => $originalRedirectUri,
|
||||
"locale" => $this->userLocale,
|
||||
);
|
||||
// This endpoint requires "Basic" auth.
|
||||
$clientCredentials = $this->appInfo->getKey().":".$this->appInfo->getSecret();
|
||||
$authHeaderValue = "Basic ".base64_encode($clientCredentials);
|
||||
|
||||
$curl = RequestUtil::mkCurlWithoutAuth($this->clientIdentifier, $url);
|
||||
|
||||
// Add Basic auth header.
|
||||
$basic_auth = $this->appInfo->getKey() . ":" . $this->appInfo->getSecret();
|
||||
$curl->addHeader("Authorization: Basic ".base64_encode($basic_auth));
|
||||
|
||||
$curl->set(CURLOPT_POST, true);
|
||||
$curl->set(CURLOPT_POSTFIELDS, RequestUtil::buildPostBody($params));
|
||||
|
||||
$curl->set(CURLOPT_RETURNTRANSFER, true);
|
||||
$response = $curl->exec();
|
||||
$response = RequestUtil::doPostWithSpecificAuth(
|
||||
$this->clientIdentifier, $authHeaderValue, $this->userLocale,
|
||||
$this->appInfo->getHost()->getApi(),
|
||||
"1/oauth2/token",
|
||||
array(
|
||||
"grant_type" => "authorization_code",
|
||||
"code" => $code,
|
||||
"redirect_uri" => $originalRedirectUri,
|
||||
));
|
||||
|
||||
if ($response->statusCode !== 200) throw RequestUtil::unexpectedStatus($response);
|
||||
|
||||
$parts = RequestUtil::parseResponseJson($response->body);
|
||||
|
||||
if (!array_key_exists('token_type', $parts) or !is_string($parts['token_type'])) {
|
||||
if (!array_key_exists('token_type', $parts) || !is_string($parts['token_type'])) {
|
||||
throw new Exception_BadResponse("Missing \"token_type\" field.");
|
||||
}
|
||||
$tokenType = $parts['token_type'];
|
||||
if (!array_key_exists('access_token', $parts) or !is_string($parts['access_token'])) {
|
||||
if (!array_key_exists('access_token', $parts) || !is_string($parts['access_token'])) {
|
||||
throw new Exception_BadResponse("Missing \"access_token\" field.");
|
||||
}
|
||||
$accessToken = $parts['access_token'];
|
||||
if (!array_key_exists('uid', $parts) or !is_string($parts['uid'])) {
|
||||
if (!array_key_exists('uid', $parts) || !is_string($parts['uid'])) {
|
||||
throw new Exception_BadResponse("Missing \"uid\" string field.");
|
||||
}
|
||||
$userId = $parts['uid'];
|
||||
|
|
|
@ -10,8 +10,6 @@ namespace Dropbox;
|
|||
class WebAuthException_BadState extends \Exception
|
||||
{
|
||||
/**
|
||||
* @param string $message
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
function __construct()
|
||||
|
|
|
@ -23,7 +23,8 @@ namespace Dropbox;
|
|||
* print("1. Go to: $authorizeUrl\n");
|
||||
* print("2. Click "Allow" (you might have to log in first).\n");
|
||||
* print("3. Copy the authorization code.\n");
|
||||
* $code = \trim(\readline("4. Enter the authorization code here: "));
|
||||
* print("Enter the authorization code here: ");
|
||||
* $code = \trim(\fgets(STDIN));
|
||||
*
|
||||
* try {
|
||||
* list($accessToken, $userId) = $webAuth->finish($code);
|
||||
|
@ -43,8 +44,10 @@ class WebAuthNoRedirect extends WebAuthBase
|
|||
* copy/paste that code into your application so your app can pass it to
|
||||
* {@link finish}.
|
||||
*
|
||||
* See <a href="https://www.dropbox.com/developers/core/docs#oa2-authorize">/oauth2/authorize</a>.
|
||||
*
|
||||
* @return string
|
||||
* An authorization URL. Redirect the user's browser to this URL. After the user decides
|
||||
* An authorization URL. Direct the user's browser to this URL. After the user decides
|
||||
* whether to authorize your app or not, Dropbox will show the user an authorization code,
|
||||
* which the user will need to give to your application (e.g. via copy/paste).
|
||||
*/
|
||||
|
@ -58,6 +61,8 @@ class WebAuthNoRedirect extends WebAuthBase
|
|||
* 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.
|
||||
*
|
||||
|
@ -75,4 +80,3 @@ class WebAuthNoRedirect extends WebAuthBase
|
|||
return $this->_finish($code, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
1396
modules/Dropbox/certs/trusted-certs.crt
Normal file
1396
modules/Dropbox/certs/trusted-certs.crt
Normal file
File diff suppressed because it is too large
Load diff
13
modules/Dropbox/strict.php
Normal file
13
modules/Dropbox/strict.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
// Throw exceptions on all PHP errors/warnings/notices.
|
||||
// We'd like to do this in all situations (and not just when running tests), but
|
||||
// this is a global setting and other code might not be ready for it.
|
||||
/** @internal */
|
||||
function error_to_exception($errno, $errstr, $errfile, $errline, $context)
|
||||
{
|
||||
// If the error is being suppressed with '@', don't throw an exception.
|
||||
if (error_reporting() === 0) return;
|
||||
|
||||
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
|
||||
}
|
||||
set_error_handler('error_to_exception');
|
|
@ -1,341 +0,0 @@
|
|||
# Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Server CA/emailAddress=server-certs@thawte.com <server-certs@thawte.com>
|
||||
# Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Server CA/emailAddress= server-certs@thawte.com
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx
|
||||
FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD
|
||||
VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv
|
||||
biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm
|
||||
MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx
|
||||
MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT
|
||||
DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3
|
||||
dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl
|
||||
cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3
|
||||
DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD
|
||||
gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91
|
||||
yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX
|
||||
L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj
|
||||
EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG
|
||||
7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e
|
||||
QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ
|
||||
qdq5snUb9kLy78fyGPmJvKP/iiMucEc=
|
||||
-----END CERTIFICATE-----
|
||||
# Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Premium Server CA/emailAddress=premium-server@thawte.com <premium-server@thawte.com>
|
||||
# Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Premium Server CA/emailAddress=premium-server@thawte.com <premium-server@thawte.com>
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx
|
||||
FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD
|
||||
VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv
|
||||
biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy
|
||||
dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t
|
||||
MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB
|
||||
MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG
|
||||
A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp
|
||||
b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl
|
||||
cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv
|
||||
bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE
|
||||
VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ
|
||||
ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR
|
||||
uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG
|
||||
9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI
|
||||
hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM
|
||||
pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg==
|
||||
-----END CERTIFICATE-----
|
||||
# Subject: C=US, O=VeriSign, Inc., OU=Class 1 Public Primary Certification Authority
|
||||
# Issuer: C=US, O=VeriSign, Inc., OU=Class 1 Public Primary Certification Authority
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICPDCCAaUCEDJQM89Q0VbzXIGtZVxPyCUwDQYJKoZIhvcNAQECBQAwXzELMAkG
|
||||
A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
|
||||
cyAxIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
|
||||
MDEyOTAwMDAwMFoXDTIwMDEwNzIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
|
||||
BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAxIFB1YmxpYyBQcmlt
|
||||
YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
|
||||
ADCBiQKBgQDlGb9to1ZhLZlIcfZn3rmN67eehoAKkQ76OCWvRoiC5XOooJskXQ0f
|
||||
zGVuDLDQVoQYh5oGmxChc9+0WDlrbsH2FdWoqD+qEgaNMax/sDTXjzRniAnNFBHi
|
||||
TkVWaR94AoDa3EeRKbs2yWNcxeDXLYd7obcysHswuiovMaruo2fa2wIDAQABMA0G
|
||||
CSqGSIb3DQEBAgUAA4GBAEtEZmBoZOSYG/OwcuaViXzde7OVwB0u2NgZ0C00PcZQ
|
||||
mhCGjKo/O6gE/DdSlcPZydvN8oYGxLEb8IKIMEKOF1AcZHq4PplJdJf8rAJD+5YM
|
||||
VgQlDHx8h50kp9jwMim1pN9dokzFFjKoQvZFprY2ueC/ZTaTwtLXa9zeWdaiNfhF
|
||||
-----END CERTIFICATE-----
|
||||
# Subject: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority
|
||||
# Issuer: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
|
||||
A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
|
||||
cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
|
||||
MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
|
||||
BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
|
||||
YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
|
||||
ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
|
||||
BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
|
||||
I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
|
||||
CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do
|
||||
lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc
|
||||
AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k
|
||||
-----END CERTIFICATE-----
|
||||
# Subject: C=US, O=RSA Data Security, Inc., OU=Secure Server Certification Authority
|
||||
# Issuer: C=US, O=RSA Data Security, Inc., OU=Secure Server Certification Authority
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICNDCCAaECEAKtZn5ORf5eV288mBle3cAwDQYJKoZIhvcNAQECBQAwXzELMAkG
|
||||
A1UEBhMCVVMxIDAeBgNVBAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYD
|
||||
VQQLEyVTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk0
|
||||
MTEwOTAwMDAwMFoXDTEwMDEwNzIzNTk1OVowXzELMAkGA1UEBhMCVVMxIDAeBgNV
|
||||
BAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2Vy
|
||||
dmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGbMA0GCSqGSIb3DQEBAQUAA4GJ
|
||||
ADCBhQJ+AJLOesGugz5aqomDV6wlAXYMra6OLDfO6zV4ZFQD5YRAUcm/jwjiioII
|
||||
0haGN1XpsSECrXZogZoFokvJSyVmIlZsiAeP94FZbYQHZXATcXY+m3dM41CJVphI
|
||||
uR2nKRoTLkoRWZweFdVJVCxzOmmCsZc5nG1wZ0jl3S3WyB57AgMBAAEwDQYJKoZI
|
||||
hvcNAQECBQADfgBl3X7hsuyw4jrg7HFGmhkRuNPHoLQDQCYCPgmc4RKz0Vr2N6W3
|
||||
YQO2WxZpO8ZECAyIUwxrl0nHPjXcbLm7qt9cuzovk2C2qUtN8iD3zV9/ZHuO3ABc
|
||||
1/p3yjkWWW8O6tO1g39NTUJWdrTJXwT4OPjr0l91X817/OWOgHz8UA==
|
||||
-----END CERTIFICATE-----
|
||||
# Subject: C=US, O=Equifax Secure Inc., CN=Equifax Secure Global eBusiness CA-1
|
||||
# Issuer: C=US, O=Equifax Secure Inc., CN=Equifax Secure Global eBusiness CA-1
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc
|
||||
MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT
|
||||
ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw
|
||||
MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj
|
||||
dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l
|
||||
c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC
|
||||
UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc
|
||||
58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/
|
||||
o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH
|
||||
MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr
|
||||
aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA
|
||||
A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA
|
||||
Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv
|
||||
8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV
|
||||
-----END CERTIFICATE-----
|
||||
# Subject: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Hardware
|
||||
# Issuer: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Hardware
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB
|
||||
lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
|
||||
Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
|
||||
dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt
|
||||
SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG
|
||||
A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe
|
||||
MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v
|
||||
d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh
|
||||
cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn
|
||||
0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ
|
||||
M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a
|
||||
MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd
|
||||
oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI
|
||||
DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy
|
||||
oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD
|
||||
VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0
|
||||
dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy
|
||||
bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF
|
||||
BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM
|
||||
//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli
|
||||
CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE
|
||||
CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t
|
||||
3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS
|
||||
KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA==
|
||||
-----END CERTIFICATE-----
|
||||
# Subject: C=US, O=Network Solutions L.L.C., CN=Network Solutions Certificate Authority
|
||||
# Issuer: C=US, O=Network Solutions L.L.C., CN=Network Solutions Certificate Authority
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi
|
||||
MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
|
||||
MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp
|
||||
dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV
|
||||
UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO
|
||||
ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG
|
||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz
|
||||
c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP
|
||||
OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl
|
||||
mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF
|
||||
BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4
|
||||
qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw
|
||||
gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB
|
||||
BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu
|
||||
bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp
|
||||
dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8
|
||||
6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/
|
||||
h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH
|
||||
/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
|
||||
wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN
|
||||
pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
|
||||
-----END CERTIFICATE-----
|
||||
# Subject: C=US, O=The Go Daddy Group, Inc., OU=Go Daddy Class 2 Certification Authority
|
||||
# Issuer: C=US, O=The Go Daddy Group, Inc., OU=Go Daddy Class 2 Certification Authority
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
|
||||
MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
|
||||
YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
|
||||
MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
|
||||
ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
|
||||
MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
|
||||
ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
|
||||
PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
|
||||
wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
|
||||
EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
|
||||
avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
|
||||
YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
|
||||
sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
|
||||
/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
|
||||
IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
|
||||
YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
|
||||
ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
|
||||
OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
|
||||
TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
|
||||
HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
|
||||
dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
|
||||
ReYNnyicsbkqWletNw+vHX/bvZ8=
|
||||
-----END CERTIFICATE-----
|
||||
# Subject: C=US, ST=Arizona, L=Scottsdale, O=GoDaddy.com, Inc., OU=http://certificates.godaddy.com/repository<http://certificates.godaddy.com/repository>, CN=Go Daddy Secure Certification Authority/serialNumber=07969287
|
||||
# Issuer: C=US, O=The Go Daddy Group, Inc., OU=Go Daddy Class 2 Certification Authority
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMx
|
||||
ITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
|
||||
RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMTYw
|
||||
MTU0MzdaFw0yNjExMTYwMTU0MzdaMIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMH
|
||||
QXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5j
|
||||
b20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j
|
||||
b20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmlj
|
||||
YXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4NzCCASIwDQYJKoZIhvcN
|
||||
AQEBBQADggEPADCCAQoCggEBAMQt1RWMnCZM7DI161+4WQFapmGBWTtwY6vj3D3H
|
||||
KrjJM9N55DrtPDAjhI6zMBS2sofDPZVUBJ7fmd0LJR4h3mUpfjWoqVTr9vcyOdQm
|
||||
VZWt7/v+WIbXnvQAjYwqDL1CBM6nPwT27oDyqu9SoWlm2r4arV3aLGbqGmu75RpR
|
||||
SgAvSMeYddi5Kcju+GZtCpyz8/x4fKL4o/K1w/O5epHBp+YlLpyo7RJlbmr2EkRT
|
||||
cDCVw5wrWCs9CHRK8r5RsL+H0EwnWGu1NcWdrxcx+AuP7q2BNgWJCJjPOq8lh8BJ
|
||||
6qf9Z/dFjpfMFDniNoW1fho3/Rb2cRGadDAW/hOUoz+EDU8CAwEAAaOCATIwggEu
|
||||
MB0GA1UdDgQWBBT9rGEyk2xF1uLuhV+auud2mWjM5zAfBgNVHSMEGDAWgBTSxLDS
|
||||
kdRMEXGzYcs9of7dqGrU4zASBgNVHRMBAf8ECDAGAQH/AgEAMDMGCCsGAQUFBwEB
|
||||
BCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZ29kYWRkeS5jb20wRgYDVR0f
|
||||
BD8wPTA7oDmgN4Y1aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBv
|
||||
c2l0b3J5L2dkcm9vdC5jcmwwSwYDVR0gBEQwQjBABgRVHSAAMDgwNgYIKwYBBQUH
|
||||
AgEWKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTAO
|
||||
BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBANKGwOy9+aG2Z+5mC6IG
|
||||
OgRQjhVyrEp0lVPLN8tESe8HkGsz2ZbwlFalEzAFPIUyIXvJxwqoJKSQ3kbTJSMU
|
||||
A2fCENZvD117esyfxVgqwcSeIaha86ykRvOe5GPLL5CkKSkB2XIsKd83ASe8T+5o
|
||||
0yGPwLPk9Qnt0hCqU7S+8MxZC9Y7lhyVJEnfzuz9p0iRFEUOOjZv2kWzRaJBydTX
|
||||
RE4+uXR21aITVSzGh6O1mawGhId/dQb8vxRMDsxuxN89txJx9OjxUUAiKEngHUuH
|
||||
qDTMBqLdElrRhjZkAzVvb3du6/KFUJheqwNTrZEjYx8WnM25sgVjOuH0aBsXBTWV
|
||||
U+4=
|
||||
-----END CERTIFICATE-----
|
||||
# Subject: C=US, ST=Arizona, L=Scottsdale, O=GoDaddy.com, Inc., CN=Go Daddy Root Certificate Authority - G2
|
||||
# Issuer: C=US, ST=Arizona, L=Scottsdale, O=GoDaddy.com, Inc., CN=Go Daddy Root Certificate Authority - G2
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
|
||||
EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
|
||||
EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
|
||||
ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz
|
||||
NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
|
||||
EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE
|
||||
AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw
|
||||
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD
|
||||
E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH
|
||||
/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy
|
||||
DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh
|
||||
GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR
|
||||
tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA
|
||||
AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
|
||||
FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX
|
||||
WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu
|
||||
9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr
|
||||
gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo
|
||||
2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
|
||||
LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI
|
||||
4uJEvlz36hz1
|
||||
-----END CERTIFICATE-----
|
||||
# Subject: C=US, O=GeoTrust Inc., CN=GeoTrust Global CA
|
||||
# Issuer: C=US, O=GeoTrust Inc., CN=GeoTrust Global CA
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
|
||||
MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
|
||||
YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG
|
||||
EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg
|
||||
R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9
|
||||
9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq
|
||||
fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv
|
||||
iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU
|
||||
1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+
|
||||
bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW
|
||||
MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA
|
||||
ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l
|
||||
uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn
|
||||
Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS
|
||||
tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF
|
||||
PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un
|
||||
hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV
|
||||
5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
|
||||
-----END CERTIFICATE-----
|
||||
# Subject: C=US, O=GeoTrust Inc., CN=GeoTrust Primary Certification Authority
|
||||
# Issuer: C=US, O=GeoTrust Inc., CN=GeoTrust Primary Certification Authority
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY
|
||||
MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo
|
||||
R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx
|
||||
MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
|
||||
Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp
|
||||
ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
|
||||
AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9
|
||||
AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA
|
||||
ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0
|
||||
7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W
|
||||
kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI
|
||||
mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G
|
||||
A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ
|
||||
KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1
|
||||
6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl
|
||||
4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K
|
||||
oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj
|
||||
UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU
|
||||
AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
|
||||
-----END CERTIFICATE-----
|
||||
# Subject: C=US, O=The Go Daddy Group, Inc., OU=Go Daddy Class 2 Certification Authority
|
||||
# Issuer: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 2 Policy Validation Authority, CN=http://www.valicert.com//emailAddress=info@valicert.com<http://www.valicert.com//emailAddress=info@valicert.com>
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE+zCCBGSgAwIBAgICAQ0wDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1Zh
|
||||
bGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIElu
|
||||
Yy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24g
|
||||
QXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAe
|
||||
BgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTA0MDYyOTE3MDYyMFoX
|
||||
DTI0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBE
|
||||
YWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3MgMiBDZXJ0
|
||||
aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgC
|
||||
ggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
|
||||
2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+q
|
||||
N1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiO
|
||||
r18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lN
|
||||
f4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+YihfukEH
|
||||
U1jPEX44dMX4/7VpkI+EdOqXG68CAQOjggHhMIIB3TAdBgNVHQ4EFgQU0sSw0pHU
|
||||
TBFxs2HLPaH+3ahq1OMwgdIGA1UdIwSByjCBx6GBwaSBvjCBuzEkMCIGA1UEBxMb
|
||||
VmFsaUNlcnQgVmFsaWRhdGlvbiBOZXR3b3JrMRcwFQYDVQQKEw5WYWxpQ2VydCwg
|
||||
SW5jLjE1MDMGA1UECxMsVmFsaUNlcnQgQ2xhc3MgMiBQb2xpY3kgVmFsaWRhdGlv
|
||||
biBBdXRob3JpdHkxITAfBgNVBAMTGGh0dHA6Ly93d3cudmFsaWNlcnQuY29tLzEg
|
||||
MB4GCSqGSIb3DQEJARYRaW5mb0B2YWxpY2VydC5jb22CAQEwDwYDVR0TAQH/BAUw
|
||||
AwEB/zAzBggrBgEFBQcBAQQnMCUwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmdv
|
||||
ZGFkZHkuY29tMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jZXJ0aWZpY2F0ZXMu
|
||||
Z29kYWRkeS5jb20vcmVwb3NpdG9yeS9yb290LmNybDBLBgNVHSAERDBCMEAGBFUd
|
||||
IAAwODA2BggrBgEFBQcCARYqaHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNv
|
||||
bS9yZXBvc2l0b3J5MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOBgQC1
|
||||
QPmnHfbq/qQaQlpE9xXUhUaJwL6e4+PrxeNYiY+Sn1eocSxI0YGyeR+sBjUZsE4O
|
||||
WBsUs5iB0QQeyAfJg594RAoYC5jcdnplDQ1tgMQLARzLrUc+cb53S8wGd9D0Vmsf
|
||||
SxOaFIqII6hR8INMqzW/Rn453HWkrugp++85j09VZw==
|
||||
-----END CERTIFICATE-----
|
||||
# Subject: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 2 Policy Validation Authority, CN=http://www.valicert.com//emailAddress=info@valicert.com<http://www.valicert.com//emailAddress=info@valicert.com>
|
||||
# Issuer: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 2 Policy Validation Authority, CN=http://www.valicert.com//emailAddress=info@valicert.com<http://www.valicert.com//emailAddress=info@valicert.com>
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
|
||||
IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
|
||||
BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
|
||||
aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
|
||||
9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy
|
||||
NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
|
||||
azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
|
||||
YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
|
||||
Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
|
||||
cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY
|
||||
dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9
|
||||
WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS
|
||||
v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v
|
||||
UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu
|
||||
IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC
|
||||
W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
|
|
@ -143,4 +143,11 @@ class Catalog_beets extends Beets\Catalog
|
|||
return $this->beetsdb;
|
||||
}
|
||||
|
||||
public function format()
|
||||
{
|
||||
parent::format();
|
||||
$this->f_info = $this->beetsdb;
|
||||
$this->f_full_info = $this->f_info;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -128,6 +128,22 @@ class Catalog_dropbox extends Catalog
|
|||
|
||||
}
|
||||
|
||||
public function isReady()
|
||||
{
|
||||
return (!empty($this->authtoken));
|
||||
}
|
||||
|
||||
public function show_ready_process()
|
||||
{
|
||||
$this->showAuthToken();
|
||||
}
|
||||
|
||||
public function perform_ready()
|
||||
{
|
||||
$this->authcode = $_REQUEST['authcode'];
|
||||
$this->completeAuthToken();
|
||||
}
|
||||
|
||||
public $apikey;
|
||||
public $secret;
|
||||
public $path;
|
||||
|
@ -205,10 +221,11 @@ class Catalog_dropbox extends Catalog
|
|||
$authurl = $webAuth->start();
|
||||
echo "<br />Go to <strong><a href='" . $authurl . "' target='_blank'>" . $authurl . "</a></strong> to generate the authorization code, then enter it bellow.<br />";
|
||||
echo "<form action='" . get_current_path() . "' method='post' enctype='multipart/form-data'>";
|
||||
if ($_POST['action']) {
|
||||
echo "<input type='hidden' name='action' value='add_to_catalog' />";
|
||||
if ($_REQUEST['action']) {
|
||||
echo "<input type='hidden' name='action' value='" . scrub_in($_REQUEST['action']) . "' />";
|
||||
echo "<input type='hidden' name='catalogs[]' value='". $this->id ."' />";
|
||||
}
|
||||
echo "<input type='hidden' name='perform_ready' value='true' />";
|
||||
echo "<input type='text' name='authcode' />";
|
||||
echo "<input type='submit' value='Ok' />";
|
||||
echo "</form>";
|
||||
|
|
|
@ -117,6 +117,22 @@ class Catalog_soundcloud extends Catalog
|
|||
|
||||
}
|
||||
|
||||
public function isReady()
|
||||
{
|
||||
return (!empty($this->authtoken));
|
||||
}
|
||||
|
||||
public function show_ready_process()
|
||||
{
|
||||
$this->showAuthToken();
|
||||
}
|
||||
|
||||
public function perform_ready()
|
||||
{
|
||||
$this->authcode = $_REQUEST['authcode'];
|
||||
$this->completeAuthToken();
|
||||
}
|
||||
|
||||
public $userid;
|
||||
public $secret;
|
||||
public $authtoken;
|
||||
|
@ -183,10 +199,11 @@ class Catalog_soundcloud extends Catalog
|
|||
$authurl = $api->getAuthorizeUrl(array('scope' => 'non-expiring'));
|
||||
echo "<br />Go to <strong><a href='" . $authurl . "' target='_blank'>" . $authurl . "</a></strong> to generate the authorization code, then enter it bellow.<br />";
|
||||
echo "<form action='" . get_current_path() . "' method='post' enctype='multipart/form-data'>";
|
||||
if ($_POST['action']) {
|
||||
echo "<input type='hidden' name='action' value='add_to_catalog' />";
|
||||
if ($_REQUEST['action']) {
|
||||
echo "<input type='hidden' name='action' value='" . scrub_in($_REQUEST['action']) . "' />";
|
||||
echo "<input type='hidden' name='catalogs[]' value='". $this->id ."' />";
|
||||
}
|
||||
echo "<input type='hidden' name='perform_ready' value='true' />";
|
||||
echo "<input type='text' name='authcode' />";
|
||||
echo "<input type='submit' value='Ok' />";
|
||||
echo "</form>";
|
||||
|
|
|
@ -58,7 +58,9 @@ switch ($worker) {
|
|||
if ($_REQUEST['catalogs']) {
|
||||
foreach ($_REQUEST['catalogs'] as $catalog_id) {
|
||||
$catalog = Catalog::create_from_id($catalog_id);
|
||||
$catalog->add_to_catalog($_POST);
|
||||
if ($catalog !== null) {
|
||||
$catalog->add_to_catalog($_POST);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -68,7 +70,9 @@ switch ($worker) {
|
|||
if (isset($_REQUEST['catalogs'])) {
|
||||
foreach ($_REQUEST['catalogs'] as $catalog_id) {
|
||||
$catalog = Catalog::create_from_id($catalog_id);
|
||||
$catalog->verify_catalog();
|
||||
if ($catalog !== null) {
|
||||
$catalog->verify_catalog();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -80,9 +84,11 @@ switch ($worker) {
|
|||
/* This runs the clean/verify/add in that order */
|
||||
foreach ($_REQUEST['catalogs'] as $catalog_id) {
|
||||
$catalog = Catalog::create_from_id($catalog_id);
|
||||
$catalog->clean_catalog();
|
||||
$catalog->verify_catalog();
|
||||
$catalog->add_to_catalog();
|
||||
if ($catalog !== null) {
|
||||
$catalog->clean_catalog();
|
||||
$catalog->verify_catalog();
|
||||
$catalog->add_to_catalog();
|
||||
}
|
||||
}
|
||||
Dba::optimize_tables();
|
||||
break;
|
||||
|
@ -93,7 +99,9 @@ switch ($worker) {
|
|||
if (isset($_REQUEST['catalogs'])) {
|
||||
foreach ($_REQUEST['catalogs'] as $catalog_id) {
|
||||
$catalog = Catalog::create_from_id($catalog_id);
|
||||
$catalog->clean_catalog();
|
||||
if ($catalog !== null) {
|
||||
$catalog->clean_catalog();
|
||||
}
|
||||
} // end foreach catalogs
|
||||
Dba::optimize_tables();
|
||||
}
|
||||
|
@ -104,7 +112,9 @@ switch ($worker) {
|
|||
if ($_REQUEST['add_path'] != '/' AND strlen($_REQUEST['add_path'])) {
|
||||
if ($catalog_id = Catalog_local::get_from_path($_REQUEST['add_path'])) {
|
||||
$catalog = Catalog::create_from_id($catalog_id);
|
||||
$catalog->add_to_catalog(array('subdirectory'=>$_REQUEST['add_path']));
|
||||
if ($catalog !== null) {
|
||||
$catalog->add_to_catalog(array('subdirectory'=>$_REQUEST['add_path']));
|
||||
}
|
||||
}
|
||||
} // end if add
|
||||
|
||||
|
@ -123,11 +133,13 @@ switch ($worker) {
|
|||
case 'add_catalog':
|
||||
$catalog_id = intval($_REQUEST['catalog_id']);
|
||||
$catalog = Catalog::create_from_id($catalog_id);
|
||||
// Run our initial add
|
||||
$catalog->add_to_catalog($options);
|
||||
if ($catalog !== null) {
|
||||
// Run our initial add
|
||||
$catalog->add_to_catalog($options);
|
||||
|
||||
if (!defined('SSE_OUTPUT')) {
|
||||
Error::display('catalog_add');
|
||||
if (!defined('SSE_OUTPUT')) {
|
||||
Error::display('catalog_add');
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'gather_media_art':
|
||||
|
@ -136,9 +148,11 @@ switch ($worker) {
|
|||
// Iterate throught the catalogs and gather as needed
|
||||
foreach ($catalogs as $catalog_id) {
|
||||
$catalog = Catalog::create_from_id($catalog_id);
|
||||
require AmpConfig::get('prefix') . '/templates/show_gather_art.inc.php';
|
||||
flush();
|
||||
$catalog->gather_art();
|
||||
if ($catalog !== null) {
|
||||
require AmpConfig::get('prefix') . '/templates/show_gather_art.inc.php';
|
||||
flush();
|
||||
$catalog->gather_art();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue