use Kunnu\Dropbox\Dropbox;
use Kunnu\Dropbox\DropboxApp;
use Kunnu\Dropbox\DropboxFile;
use Kunnu\Dropbox\Exceptions\DropboxClientException;
use Kunnu\Dropbox\Models\FileMetadata;
use Kunnu\Dropbox\Models\FolderMetadata;
* Simple elFinder driver for Dropbox
* kunalvarma05/dropbox-php-sdk:0.1.5 or above.
class elFinderVolumeDropbox2 extends elFinderVolumeDriver
* Must be started from letter and contains [a-z0-9]
* Used as part of volume id.
protected $driverId = 'db';
* Dropbox service object.
protected $service = null;
private $FETCH_OPTIONS = [];
* Directory for tmp files
* If not set driver will try to use tmbDir as tmpDir.
public $netMountKey = '';
* Extend options with required fields.
public function __construct()
'aliasFormat' => '%s@Dropbox',
'acceptedName' => '#^[^\\\/]+$#',
'rootCssClass' => 'elfinder-navbar-root-dropbox',
'requested_visibility' => 'public',
'getThumbSize' => 'medium', // Available sizes: 'thumb', 'small', 'medium', 'large', 'huge'
$this->options = array_merge($this->options, $opts);
$this->options['mimeDetect'] = 'internal';
/*********************************************************************/
/*********************************************************************/
* Get Parent ID, Item ID, Parent Path as an array from path.
protected function _db_splitPath($path)
$path = trim($path, '/');
$pos = strrpos($path, '/');
$dirname = '/' . substr($path, 0, $pos);
$basename = substr($path, $pos + 1);
return [$dirname, $basename];
* Get dat(Dropbox metadata) from Dropbox.
* @return boolean|object Dropbox metadata
private function _db_getFile($path)
$file = $this->service->getMetadata($path, $this->FETCH_OPTIONS);
if ($file instanceof FolderMetadata || $file instanceof FileMetadata) {
} catch (DropboxClientException $e) {
* Parse line from Dropbox metadata output and return file stat (array).
* @param object $raw line from ftp_rawlist() output
protected function _db_parseRaw($raw)
$isFolder = $raw instanceof FolderMetadata;
} elseif (is_array($raw)) {
$isFolder = $raw['.tag'] === 'folder';
if (isset($data['path_lower'])) {
$stat['path'] = $data['path_lower'];
if (isset($data['name'])) {
$stat['name'] = $data['name'];
if (isset($data['id'])) {
$stat['iid'] = substr($data['id'], 3);
$stat['mime'] = 'directory';
$stat['size'] = isset($data['size']) ? (int)$data['size'] : 0;
if (isset($data['server_modified'])) {
$stat['ts'] = strtotime($data['server_modified']);
} elseif (isset($data['client_modified'])) {
$stat['ts'] = strtotime($data['client_modified']);
* Get thumbnail from Dropbox.
* @return string | boolean
protected function _db_getThumbnail($path)
return $this->service->getThumbnail($path, $this->options['getThumbSize'])->getContents();
} catch (DropboxClientException $e) {
* Join dir name and file name(display name) and retur full path.
* @param string $displayName
protected function _db_joinName($dir, $displayName)
return rtrim($dir, '/') . '/' . $displayName;
* Get OAuth2 access token form OAuth1 tokens.
* @param string $app_secret
* @param string $oauth1_token
* @param string $oauth1_secret
public static function getTokenFromOauth1($app_key, $app_secret, $oauth1_token, $oauth1_secret)
'oauth1_token' => $oauth1_token,
'oauth1_token_secret' => $oauth1_secret,
$auth = base64_encode($app_key . ':' . $app_secret);
$ch = curl_init('https://api.dropboxapi.com/2/auth/token/from_oauth1');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Authorization: Basic ' . $auth,
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$result = curl_exec($ch);
$res = $result ? json_decode($result, true) : [];
return isset($res['oauth2_token']) ? $res['oauth2_token'] : false;
/*********************************************************************/
/*********************************************************************/
* Call from elFinder::netmout() before volume->mount().
public function netmountPrepare($options)
if (empty($options['app_key']) && defined('ELFINDER_DROPBOX_APPKEY')) {
$options['app_key'] = ELFINDER_DROPBOX_APPKEY;
if (empty($options['app_secret']) && defined('ELFINDER_DROPBOX_APPSECRET')) {
$options['app_secret'] = ELFINDER_DROPBOX_APPSECRET;
if (!isset($options['pass'])) {
$app = new DropboxApp($options['app_key'], $options['app_secret']);
$dropbox = new Dropbox($app);
$authHelper = $dropbox->getAuthHelper();
if ($options['pass'] === 'reauth') {
$this->session->set('Dropbox2AuthParams', [])->set('Dropbox2Tokens', []);
} elseif ($options['pass'] === 'dropbox2') {
$options = array_merge($this->session->get('Dropbox2AuthParams', []), $options);
if (!isset($options['tokens'])) {
$options['tokens'] = $this->session->get('Dropbox2Tokens', []);
$this->session->remove('Dropbox2Tokens');
$aToken = $options['tokens'];
if (!is_array($aToken) || !isset($aToken['access_token'])) {
$dropbox->setAccessToken($aToken['access_token']);
$this->session->set('Dropbox2AuthParams', $options);
} catch (DropboxClientException $e) {
if ($options['user'] !== 'init') {
$this->session->set('Dropbox2AuthParams', $options);
return ['exit' => true, 'error' => elFinder::ERROR_REAUTH_REQUIRE];
if ((isset($options['user']) && $options['user'] === 'init') || (isset($_GET['host']) && $_GET['host'] == '1')) {
if (empty($options['url'])) {
$options['url'] = elFinder::getConnectorUrl();
if (!empty($options['id'])) {
$callback = $options['url']
. (strpos($options['url'], '?') !== false? '&' : '?') . 'cmd=netmount&protocol=dropbox2&host=' . ($options['id'] === 'elfinder'? '1' : $options['id']);
$itpCare = isset($options['code']);
$code = $itpCare? $options['code'] : (isset($_GET['code'])? $_GET['code'] : '');
$state = $itpCare? $options['state'] : (isset($_GET['state'])? $_GET['state'] : '');
if (!$aToken && empty($code)) {
$url = $authHelper->getAuthUrl($callback);
$html = '<input id="elf-volumedriver-dropbox2-host-btn" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" value="{msg:btnApprove}" type="button">';
jQuery("#' . $options['id'] . '").elfinder("instance").trigger("netmount", {protocol: "dropbox2", mode: "makebtn", url: "' . $url . '"});
if (empty($options['pass']) && $options['host'] !== '1') {
$options['pass'] = 'return';
$this->session->set('Dropbox2AuthParams', $options);
return ['exit' => true, 'body' => $html];
'node' => $options['id'],
'json' => '{"protocol": "dropbox2", "mode": "makebtn", "body" : "' . str_replace($html, '"', '\\"') . '", "error" : "' . elFinder::ERROR_ACCESS_DENIED . '"}',
return ['exit' => 'callback', 'out' => $out];
if (!empty($options['id'])) {
// see https://github.com/kunalvarma05/dropbox-php-sdk/issues/115
$authHelper->getPersistentDataStore()->set('state', filter_var($state, FILTER_SANITIZE_STRING));
$tokenObj = $authHelper->getAccessToken($code, $state, $callback);
'access_token' => $tokenObj->getToken(),
'uid' => $tokenObj->getUid(),
unset($options['code'], $options['state']);
$this->session->set('Dropbox2Tokens', $options['tokens'])->set('Dropbox2AuthParams', $options);
'node' => $options['id'],
'json' => '{"protocol": "dropbox2", "mode": "done", "reset": 1}',
$nodeid = ($_GET['host'] === '1')? 'elfinder' : $_GET['host'];
'json' => json_encode(array(
'protocol' => 'dropbox2',
return array('exit' => 'callback', 'out' => $out);
return array('exit' => true, 'body' => $out['json']);
$path = $options['path'];
$listFolderContents = $dropbox->listFolder($path);
$items = $listFolderContents->getItems();
foreach ($items as $item) {
$data = $item->getData();
if ($data['.tag'] === 'folder') {
$folders[$data['path_lower']] = $data['name'];
if ($options['pass'] === 'folders') {
return ['exit' => true, 'folders' => $folders];
$folders = ['/' => '/'] + $folders;
$folders = json_encode($folders);
$json = '{"protocol": "dropbox2", "mode": "done", "folders": ' . $folders . '}';
$options['pass'] = 'return';
jQuery("#' . $options['id'] . '").elfinder("instance").trigger("netmount", ' . $json . ');
$this->session->set('Dropbox2AuthParams', $options);
return ['exit' => true, 'body' => $html];
} catch (DropboxClientException $e) {
$this->session->remove('Dropbox2AuthParams')->remove('Dropbox2Tokens');
if (empty($options['pass'])) {
return ['exit' => true, 'body' => '{msg:' . elFinder::ERROR_ACCESS_DENIED . '}' . ' ' . $e->getMessage()];
return ['exit' => true, 'error' => [elFinder::ERROR_ACCESS_DENIED, $e->getMessage()]];
return ['exit' => true, 'error' => elFinder::ERROR_REAUTH_REQUIRE];
if ($options['path'] === 'root') {
if ($options['path'] !== '/') {
$file = $dropbox->getMetadata($options['path']);
$name = $file->getName();
$options['alias'] = sprintf($this->options['aliasFormat'], $name);
} catch (DropboxClientException $e) {
return ['exit' => true, 'error' => $e->getMessage()];
foreach (['host', 'user', 'pass', 'id', 'offline'] as $key) {
* process of on netunmount
* Drop `Dropbox` & rm thumbs.
public function netunmount($netVolumes, $key)
if ($tmbs = glob(rtrim($this->options['tmbPath'], '\\/') . DIRECTORY_SEPARATOR . $this->driverId . '_' . $this->options['tokens']['uid'] . '*.png')) {
foreach ($tmbs as $file) {
/*********************************************************************/
/*********************************************************************/
* Prepare Dropbox connection
* Connect to remote server and check if credentials are correct, if so, store the connection id in $this->service.
protected function init()
if (empty($this->options['app_key'])) {
if (defined('ELFINDER_DROPBOX_APPKEY') && ELFINDER_DROPBOX_APPKEY) {