: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* Get thumbnail from GoogleDrive.com.
* @return string | boolean
protected function _gd_getThumbnail($path)
list(, $itemId) = $this->_gd_splitPath($path);
$contents = $this->service->files->get($itemId, [
$contents = $contents->getBody()->detach();
* Publish permissions specified path item.
protected function _gd_publish($path)
if ($file = $this->_gd_getFile($path)) {
if ($this->_gd_isPublished($file)) {
if ($this->service->permissions->create($file->getId(), new \Google_Service_Drive_Permission($this->options['publishPermission']))) {
* unPublish permissions specified path.
protected function _gd_unPublish($path)
if ($file = $this->_gd_getFile($path)) {
if (!$this->_gd_isPublished($file)) {
$permissions = $file->getPermissions();
$pType = $this->options['publishPermission']['type'];
$pRole = $this->options['publishPermission']['role'];
foreach ($permissions as $permission) {
if ($permission->type === $pType && $permission->role === $pRole) {
$this->service->permissions->delete($file->getId(), $permission->getId());
* @param resource $handle
protected function _gd_readFileChunk($handle, $chunkSize)
// fread will never return more than 8192 bytes if the stream is read buffered and it does not represent a plain file
$chunk = fread($handle, 8192);
$byteCount += strlen($chunk);
if ($byteCount >= $chunkSize) {
/*********************************************************************/
/*********************************************************************/
* Call from elFinder::netmout() before volume->mount().
* @author Raja Sharma updating for GoogleDrive
public function netmountPrepare($options)
if (empty($options['client_id']) && defined('ELFINDER_GOOGLEDRIVE_CLIENTID')) {
$options['client_id'] = ELFINDER_GOOGLEDRIVE_CLIENTID;
if (empty($options['client_secret']) && defined('ELFINDER_GOOGLEDRIVE_CLIENTSECRET')) {
$options['client_secret'] = ELFINDER_GOOGLEDRIVE_CLIENTSECRET;
if (empty($options['googleApiClient']) && defined('ELFINDER_GOOGLEDRIVE_GOOGLEAPICLIENT')) {
$options['googleApiClient'] = ELFINDER_GOOGLEDRIVE_GOOGLEAPICLIENT;
include_once $options['googleApiClient'];
if (!isset($options['pass'])) {
$client = new \Google_Client();
$client->setClientId($options['client_id']);
$client->setClientSecret($options['client_secret']);
if ($options['pass'] === 'reauth') {
$this->session->set('GoogleDriveAuthParams', [])->set('GoogleDriveTokens', []);
} elseif ($options['pass'] === 'googledrive') {
$options = array_merge($this->session->get('GoogleDriveAuthParams', []), $options);
if (!isset($options['access_token'])) {
$options['access_token'] = $this->session->get('GoogleDriveTokens', []);
$this->session->remove('GoogleDriveTokens');
$aToken = $options['access_token'];
$rootObj = $service = null;
$client->setAccessToken($aToken);
if ($client->isAccessTokenExpired()) {
$aToken = array_merge($aToken, $client->fetchAccessTokenWithRefreshToken());
$client->setAccessToken($aToken);
$service = new \Google_Service_Drive($client);
$rootObj = $service->files->get('root');
$options['access_token'] = $aToken;
$this->session->set('GoogleDriveAuthParams', $options);
$options['access_token'] = [];
if ($options['user'] !== 'init') {
$this->session->set('GoogleDriveAuthParams', $options);
return ['exit' => true, 'error' => elFinder::ERROR_REAUTH_REQUIRE];
$itpCare = isset($options['code']);
$code = $itpCare? $options['code'] : (isset($_GET['code'])? $_GET['code'] : '');
if ($code || (isset($options['user']) && $options['user'] === 'init')) {
if (empty($options['url'])) {
$options['url'] = elFinder::getConnectorUrl();
if (isset($options['id'])) {
$callback = $options['url']
. (strpos($options['url'], '?') !== false? '&' : '?') . 'cmd=netmount&protocol=googledrive&host=' . ($options['id'] === 'elfinder'? '1' : $options['id']);
$client->setRedirectUri($callback);
if (!$aToken && empty($code)) {
$client->setScopes([Google_Service_Drive::DRIVE]);
if (!empty($options['offline'])) {
$client->setApprovalPrompt('force');
$client->setAccessType('offline');
$url = $client->createAuthUrl();
$html = '<input id="elf-volumedriver-googledrive-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: "googledrive", mode: "makebtn", url: "' . $url . '"});
if (empty($options['pass']) && $options['host'] !== '1') {
$options['pass'] = 'return';
$this->session->set('GoogleDriveAuthParams', $options);
return ['exit' => true, 'body' => $html];
'node' => $options['id'],
'json' => '{"protocol": "googledrive", "mode": "makebtn", "body" : "' . str_replace($html, '"', '\\"') . '", "error" : "' . elFinder::ERROR_ACCESS_DENIED . '"}',
return ['exit' => 'callback', 'out' => $out];
if (!empty($options['id'])) {
$aToken = $client->fetchAccessTokenWithAuthCode($code);
$options['access_token'] = $aToken;
$this->session->set('GoogleDriveTokens', $aToken)->set('GoogleDriveAuthParams', $options);
'node' => $options['id'],
'json' => '{"protocol": "googledrive", "mode": "done", "reset": 1}',
$nodeid = ($_GET['host'] === '1')? 'elfinder' : $_GET['host'];
'json' => json_encode(array(
'protocol' => 'googledrive',
return array('exit' => 'callback', 'out' => $out);
return array('exit' => true, 'body' => $out['json']);
$path = $options['path'];
foreach ($service->files->listFiles([
'q' => sprintf('trashed = false and "%s" in parents and mimeType = "application/vnd.google-apps.folder"', $path),
$folders[$f->getId()] = $f->getName();
if ($options['pass'] === 'folders') {
return ['exit' => true, 'folders' => $folders];
$folders = ['root' => $rootObj->getName()] + $folders;
$folders = json_encode($folders);
$expires = empty($aToken['refresh_token']) ? $aToken['created'] + $aToken['expires_in'] - 30 : 0;
$mnt2res = empty($aToken['refresh_token']) ? '' : ', "mnt2res": 1';
$json = '{"protocol": "googledrive", "mode": "done", "folders": ' . $folders . ', "expires": ' . $expires . $mnt2res . '}';
$options['pass'] = 'return';
jQuery("#' . $options['id'] . '").elfinder("instance").trigger("netmount", ' . $json . ');
$this->session->set('GoogleDriveAuthParams', $options);
return ['exit' => true, 'body' => $html];
$this->session->remove('GoogleDriveAuthParams')->remove('GoogleDriveTokens');
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'] === '/') {
$options['path'] = 'root';
$file = $service->files->get($options['path']);
$options['alias'] = sprintf($this->options['gdAlias'], $file->getName());
} catch (Google_Service_Exception $e) {
$err = json_decode($e->getMessage(), true);
if (isset($err['error']) && $err['error']['code'] == 404) {
return ['exit' => true, 'error' => [elFinder::ERROR_TRGDIR_NOT_FOUND, $options['path']]];
return ['exit' => true, 'error' => $e->getMessage()];
return ['exit' => true, 'error' => $e->getMessage()];
foreach (['host', 'user', 'pass', 'id', 'offline'] as $key) {
* process of on netunmount
* Drop `googledrive` & rm thumbs.
public function netunmount($netVolumes, $key)
if (!$this->options['useGoogleTmb']) {
if ($tmbs = glob(rtrim($this->options['tmbPath'], '\\/') . DIRECTORY_SEPARATOR . $this->netMountKey . '*.png')) {
foreach ($tmbs as $file) {
$this->session->remove($this->id . $this->netMountKey);
* Return fileinfo based on filename
* For item ID based path file system
* Please override if needed on each drivers.
* @param string $path file cache
protected function isNameExists($path)
list($parentId, $name) = $this->_gd_splitPath($path);
'q' => sprintf('trashed=false and "%s" in parents and name="%s"', $parentId, $name),
'fields' => self::FETCHFIELDS_LIST,
$srcFile = $this->_gd_query($opts);
return empty($srcFile) ? false : $this->_gd_parseRaw($srcFile[0]);
/*********************************************************************/
/*********************************************************************/
* Connect to remote server and check if credentials are correct, if so, store the connection id in $ftp_conn.
* @author Dmitry (dio) Levashov
* @author Cem (DiscoFever)
protected function init()
$serviceAccountConfig = '';
if (empty($this->options['serviceAccountConfigFile'])) {
if (empty($options['client_id'])) {
if (defined('ELFINDER_GOOGLEDRIVE_CLIENTID') && ELFINDER_GOOGLEDRIVE_CLIENTID) {
$this->options['client_id'] = ELFINDER_GOOGLEDRIVE_CLIENTID;
return $this->setError('Required option "client_id" is undefined.');
if (empty($options['client_secret'])) {
if (defined('ELFINDER_GOOGLEDRIVE_CLIENTSECRET') && ELFINDER_GOOGLEDRIVE_CLIENTSECRET) {
$this->options['client_secret'] = ELFINDER_GOOGLEDRIVE_CLIENTSECRET;
return $this->setError('Required option "client_secret" is undefined.');
if (!$this->options['access_token'] && !$this->options['refresh_token']) {
return $this->setError('Required option "access_token" or "refresh_token" is undefined.');
if (!is_readable($this->options['serviceAccountConfigFile'])) {
return $this->setError('Option "serviceAccountConfigFile" file is not readable.');
$serviceAccountConfig = $this->options['serviceAccountConfigFile'];
if (!$serviceAccountConfig) {
if ($this->options['refresh_token']) {
$aToken = $this->options['refresh_token'];
$this->options['access_token'] = '';
$tmp = elFinder::getStaticVar('commonTempPath');
$tmp = $this->getTempPath();
$aTokenFile = $tmp . DIRECTORY_SEPARATOR . md5($this->options['client_id'] . $this->options['refresh_token']) . '.gtoken';
if (is_file($aTokenFile)) {
$this->options['access_token'] = json_decode(file_get_contents($aTokenFile), true);
// make net mount key for network mount
if (is_array($this->options['access_token'])) {
$aToken = !empty($this->options['access_token']['refresh_token'])
? $this->options['access_token']['refresh_token']
: $this->options['access_token']['access_token'];
return $this->setError('Required option "access_token" is not Array or empty.');
if ($this->needOnline && !$this->service) {
if (($this->options['googleApiClient'] || defined('ELFINDER_GOOGLEDRIVE_GOOGLEAPICLIENT')) && !class_exists('Google_Client')) {
include_once $this->options['googleApiClient'] ? $this->options['googleApiClient'] : ELFINDER_GOOGLEDRIVE_GOOGLEAPICLIENT;
if (!class_exists('Google_Client')) {
return $this->setError('Class Google_Client not found.');
$this->client = new \Google_Client();
if (!$serviceAccountConfig) {
if ($this->options['access_token']) {
$client->setAccessToken($this->options['access_token']);
$access_token = $this->options['access_token'];
if ($client->isAccessTokenExpired()) {
$client->setClientId($this->options['client_id']);
$client->setClientSecret($this->options['client_secret']);
$access_token = $client->fetchAccessTokenWithRefreshToken($this->options['refresh_token'] ?: null);
$client->setAccessToken($access_token);
file_put_contents($aTokenFile, json_encode($access_token));
$access_token['refresh_token'] = $this->options['access_token']['refresh_token'];
if (!empty($this->options['netkey'])) {
elFinder::$instance->updateNetVolumeOption($this->options['netkey'], 'access_token', $access_token);
$this->options['access_token'] = $access_token;
$this->expires = empty($access_token['refresh_token']) ? $access_token['created'] + $access_token['expires_in'] - 30 : 0;
$client->setAuthConfigFile($serviceAccountConfig);
$client->setScopes([Google_Service_Drive::DRIVE]);
$aToken = $client->getClientId();
$this->service = new \Google_Service_Drive($client);
$this->netMountKey = md5($aToken . '-' . $this->options['path']);
} catch (InvalidArgumentException $e) {
$errors[] = $e->getMessage();
} catch (Google_Service_Exception $e) {
$errors[] = $e->getMessage();
if ($this->needOnline && !$this->service) {
$this->session->remove($this->id . $this->netMountKey);
if (is_file($aTokenFile)) {
$errors[] = 'Google Drive Service could not be loaded.';
return $this->setError($errors);