Test Failed
Push — master ( 647c72...cd42b5 )
by
unknown
10:25
created
plugins/files/php/plugin.files.php 3 patches
Indentation   +93 added lines, -93 removed lines patch added patch discarded remove patch
@@ -25,100 +25,100 @@
 block discarded – undo
25 25
  */
26 26
 class Pluginfiles extends Plugin
27 27
 {
28
-	/**
29
-	 * Function initializes the Plugin and registers all hooks
30
-	 *
31
-	 * @return void
32
-	 */
33
-	function init()
34
-	{
35
-		$this->registerHook('server.core.settings.init.before');
36
-		$this->registerHook('server.index.load.custom');
37
-	}
28
+    /**
29
+     * Function initializes the Plugin and registers all hooks
30
+     *
31
+     * @return void
32
+     */
33
+    function init()
34
+    {
35
+        $this->registerHook('server.core.settings.init.before');
36
+        $this->registerHook('server.index.load.custom');
37
+    }
38 38
 
39
-	/**
40
-	 * Function is executed when a hook is triggered by the PluginManager
41
-	 *
42
-	 * @param string $eventID the id of the triggered hook
43
-	 * @param mixed $data object(s) related to the hook
44
-	 *
45
-	 * @return void
46
-	 */
47
-	function execute($eventID, &$data)
48
-	{
49
-		switch ($eventID) {
50
-			case 'server.core.settings.init.before' :
51
-				$this->injectPluginSettings($data);
52
-				break;
53
-			case 'server.index.load.custom':
54
-				switch($data['name']) {
55
-				case 'files_get_recipients':
56
-					RecipientHandler::doGetRecipients();
57
-					break;
58
-				case 'download_file':
59
-					DownloadHandler::doDownload();
60
-					break;
61
-				case 'upload_file':
62
-					UploadHandler::doUpload();
63
-					break;
64
-				case 'form':
65
-					if (isset($_GET['backend'])) {
66
-						$backend = urldecode($_GET["backend"]);
67
-					} else {
68
-						$backend = '';
69
-					}
70
-					$backendstore = Files\Backend\BackendStore::getInstance();
39
+    /**
40
+     * Function is executed when a hook is triggered by the PluginManager
41
+     *
42
+     * @param string $eventID the id of the triggered hook
43
+     * @param mixed $data object(s) related to the hook
44
+     *
45
+     * @return void
46
+     */
47
+    function execute($eventID, &$data)
48
+    {
49
+        switch ($eventID) {
50
+            case 'server.core.settings.init.before' :
51
+                $this->injectPluginSettings($data);
52
+                break;
53
+            case 'server.index.load.custom':
54
+                switch($data['name']) {
55
+                case 'files_get_recipients':
56
+                    RecipientHandler::doGetRecipients();
57
+                    break;
58
+                case 'download_file':
59
+                    DownloadHandler::doDownload();
60
+                    break;
61
+                case 'upload_file':
62
+                    UploadHandler::doUpload();
63
+                    break;
64
+                case 'form':
65
+                    if (isset($_GET['backend'])) {
66
+                        $backend = urldecode($_GET["backend"]);
67
+                    } else {
68
+                        $backend = '';
69
+                    }
70
+                    $backendstore = Files\Backend\BackendStore::getInstance();
71 71
 
72
-					if ($backendstore->backendExists($backend)) {
73
-						$backendInstance = $backendstore->getInstanceOfBackend($backend);
74
-						$formdata = $backendInstance->getFormConfig();
75
-						die($formdata);
76
-					} else {
77
-						die("Specified backend does not exist!");
78
-					}
79
-					break;
80
-			}
81
-			break;
82
-		}
83
-	}
72
+                    if ($backendstore->backendExists($backend)) {
73
+                        $backendInstance = $backendstore->getInstanceOfBackend($backend);
74
+                        $formdata = $backendInstance->getFormConfig();
75
+                        die($formdata);
76
+                    } else {
77
+                        die("Specified backend does not exist!");
78
+                    }
79
+                    break;
80
+            }
81
+            break;
82
+        }
83
+    }
84 84
 
85
-	/**
86
-	 * Called when the core Settings class is initialized and ready to accept sysadmin default
87
-	 * settings. Registers the sysadmin defaults for the FILES plugin.
88
-	 *
89
-	 * @param array $data Reference to the data of the triggered hook
90
-	 *
91
-	 * @return void
92
-	 */
93
-	function injectPluginSettings(&$data)
94
-	{
95
-		$data['settingsObj']->addSysAdminDefaults(Array(
96
-			'zarafa' => Array(
97
-				'v1' => Array(
98
-					'main' => Array(
99
-						'notifier' => Array(
100
-							'info' => Array(
101
-								'files' => Array(
102
-									'value' => "dropdown"        // static notifier
103
-								)
104
-							)
105
-						)
106
-					),
107
-					'contexts' => Array(
108
-						'files' => Array(
109
-							'ask_before_delete' => PLUGIN_FILES_ASK_BEFORE_DELETE,
110
-							'webapp_tmp' => TMP_PATH
111
-						)
112
-					),
113
-					'plugins' => Array(
114
-						'files' => Array(
115
-							'enable' => PLUGIN_FILES_USER_DEFAULT_ENABLE,
116
-							'onlyoffice_enabled' => PLUGIN_FILES_ONLYOFFICE_ENABLE,
117
-							'onlyoffice_filetypes' => PLUGIN_FILES_ONLYOFFICE_FILETYPES
118
-						)
119
-					)
120
-				)
121
-			)
122
-		));
123
-	}
85
+    /**
86
+     * Called when the core Settings class is initialized and ready to accept sysadmin default
87
+     * settings. Registers the sysadmin defaults for the FILES plugin.
88
+     *
89
+     * @param array $data Reference to the data of the triggered hook
90
+     *
91
+     * @return void
92
+     */
93
+    function injectPluginSettings(&$data)
94
+    {
95
+        $data['settingsObj']->addSysAdminDefaults(Array(
96
+            'zarafa' => Array(
97
+                'v1' => Array(
98
+                    'main' => Array(
99
+                        'notifier' => Array(
100
+                            'info' => Array(
101
+                                'files' => Array(
102
+                                    'value' => "dropdown"        // static notifier
103
+                                )
104
+                            )
105
+                        )
106
+                    ),
107
+                    'contexts' => Array(
108
+                        'files' => Array(
109
+                            'ask_before_delete' => PLUGIN_FILES_ASK_BEFORE_DELETE,
110
+                            'webapp_tmp' => TMP_PATH
111
+                        )
112
+                    ),
113
+                    'plugins' => Array(
114
+                        'files' => Array(
115
+                            'enable' => PLUGIN_FILES_USER_DEFAULT_ENABLE,
116
+                            'onlyoffice_enabled' => PLUGIN_FILES_ONLYOFFICE_ENABLE,
117
+                            'onlyoffice_filetypes' => PLUGIN_FILES_ONLYOFFICE_FILETYPES
118
+                        )
119
+                    )
120
+                )
121
+            )
122
+        ));
123
+    }
124 124
 }
Please login to merge, or discard this patch.
Switch Indentation   +24 added lines, -24 removed lines patch added patch discarded remove patch
@@ -52,31 +52,31 @@
 block discarded – undo
52 52
 				break;
53 53
 			case 'server.index.load.custom':
54 54
 				switch($data['name']) {
55
-				case 'files_get_recipients':
56
-					RecipientHandler::doGetRecipients();
57
-					break;
58
-				case 'download_file':
59
-					DownloadHandler::doDownload();
60
-					break;
61
-				case 'upload_file':
62
-					UploadHandler::doUpload();
63
-					break;
64
-				case 'form':
65
-					if (isset($_GET['backend'])) {
66
-						$backend = urldecode($_GET["backend"]);
67
-					} else {
68
-						$backend = '';
69
-					}
70
-					$backendstore = Files\Backend\BackendStore::getInstance();
55
+				    case 'files_get_recipients':
56
+					    RecipientHandler::doGetRecipients();
57
+					    break;
58
+				    case 'download_file':
59
+					    DownloadHandler::doDownload();
60
+					    break;
61
+				    case 'upload_file':
62
+					    UploadHandler::doUpload();
63
+					    break;
64
+				    case 'form':
65
+					    if (isset($_GET['backend'])) {
66
+						    $backend = urldecode($_GET["backend"]);
67
+					    } else {
68
+						    $backend = '';
69
+					    }
70
+					    $backendstore = Files\Backend\BackendStore::getInstance();
71 71
 
72
-					if ($backendstore->backendExists($backend)) {
73
-						$backendInstance = $backendstore->getInstanceOfBackend($backend);
74
-						$formdata = $backendInstance->getFormConfig();
75
-						die($formdata);
76
-					} else {
77
-						die("Specified backend does not exist!");
78
-					}
79
-					break;
72
+					    if ($backendstore->backendExists($backend)) {
73
+						    $backendInstance = $backendstore->getInstanceOfBackend($backend);
74
+						    $formdata = $backendInstance->getFormConfig();
75
+						    die($formdata);
76
+					    } else {
77
+						    die("Specified backend does not exist!");
78
+					    }
79
+					    break;
80 80
 			}
81 81
 			break;
82 82
 		}
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -51,7 +51,7 @@
 block discarded – undo
51 51
 				$this->injectPluginSettings($data);
52 52
 				break;
53 53
 			case 'server.index.load.custom':
54
-				switch($data['name']) {
54
+				switch ($data['name']) {
55 55
 				case 'files_get_recipients':
56 56
 					RecipientHandler::doGetRecipients();
57 57
 					break;
Please login to merge, or discard this patch.
plugins/files/php/cssloader.php 1 patch
Indentation   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -11,13 +11,13 @@  discard block
 block discarded – undo
11 11
 
12 12
 // in source mode load the non minifyed css
13 13
 if (isset($_GET['source'])) {
14
-	$content .= file_get_contents("../resources/css/files-main.css");
15
-	$content .= file_get_contents("../resources/css/icons.css");
16
-	$content .= file_get_contents("../resources/css/navbar.css");
17
-	$content .= file_get_contents("../resources/css/pdfjspanel.css");
18
-	$content .= file_get_contents("../resources/css/webodfpanel.css");
14
+    $content .= file_get_contents("../resources/css/files-main.css");
15
+    $content .= file_get_contents("../resources/css/icons.css");
16
+    $content .= file_get_contents("../resources/css/navbar.css");
17
+    $content .= file_get_contents("../resources/css/pdfjspanel.css");
18
+    $content .= file_get_contents("../resources/css/webodfpanel.css");
19 19
 } else {
20
-	$content .= file_get_contents("../resources/css/files" . $debug . ".css");
20
+    $content .= file_get_contents("../resources/css/files" . $debug . ".css");
21 21
 }
22 22
 
23 23
 // try to load all backend form config javascript files
@@ -26,17 +26,17 @@  discard block
 block discarded – undo
26 26
 
27 27
 // Populate the list of directories to check against
28 28
 if (($directoryHandle = opendir($BACKEND_PATH)) !== FALSE) {
29
-	while (($backend = readdir($directoryHandle)) !== false) {
30
-		// Make sure we're not dealing with a file or a link to the parent directory
31
-		if (is_dir($BACKEND_PATH . $backend) && ($backend == '.' || $backend == '..') !== true) {
32
-			if (is_file($BACKEND_PATH . $backend . $BACKEND_CSS_LOADER)) {
33
-				include($BACKEND_PATH . $backend . $BACKEND_CSS_LOADER);
34
-				$class = "\\Files\\Backend\\$backend\\BackendCSSLoader";
35
-				$cssloader = new $class();
36
-				$content .= $cssloader->get_combined_css($_GET['debug']);
37
-			}
38
-		}
39
-	}
29
+    while (($backend = readdir($directoryHandle)) !== false) {
30
+        // Make sure we're not dealing with a file or a link to the parent directory
31
+        if (is_dir($BACKEND_PATH . $backend) && ($backend == '.' || $backend == '..') !== true) {
32
+            if (is_file($BACKEND_PATH . $backend . $BACKEND_CSS_LOADER)) {
33
+                include($BACKEND_PATH . $backend . $BACKEND_CSS_LOADER);
34
+                $class = "\\Files\\Backend\\$backend\\BackendCSSLoader";
35
+                $cssloader = new $class();
36
+                $content .= $cssloader->get_combined_css($_GET['debug']);
37
+            }
38
+        }
39
+    }
40 40
 }
41 41
 
42 42
 echo $content;
Please login to merge, or discard this patch.
plugins/files/php/jsloader.php 1 patch
Indentation   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -19,17 +19,17 @@
 block discarded – undo
19 19
 
20 20
 // Populate the list of directories to check against
21 21
 if (($directoryHandle = opendir($BACKEND_PATH)) !== FALSE) {
22
-	while (($backend = readdir($directoryHandle)) !== false) {
23
-		// Make sure we're not dealing with a file or a link to the parent directory
24
-		if (is_dir($BACKEND_PATH . $backend) && ($backend == '.' || $backend == '..') !== true) {
25
-			if (is_file($BACKEND_PATH . $backend . $BACKEND_JS_LOADER)) {
26
-				include($BACKEND_PATH . $backend . $BACKEND_JS_LOADER);
27
-				$class = "\\Files\\Backend\\$backend\\BackendJSLoader";
28
-				$jsloader = new $class();
29
-				$content .= $jsloader->get_combined_js($_GET['debug']);
30
-			}
31
-		}
32
-	}
22
+    while (($backend = readdir($directoryHandle)) !== false) {
23
+        // Make sure we're not dealing with a file or a link to the parent directory
24
+        if (is_dir($BACKEND_PATH . $backend) && ($backend == '.' || $backend == '..') !== true) {
25
+            if (is_file($BACKEND_PATH . $backend . $BACKEND_JS_LOADER)) {
26
+                include($BACKEND_PATH . $backend . $BACKEND_JS_LOADER);
27
+                $class = "\\Files\\Backend\\$backend\\BackendJSLoader";
28
+                $jsloader = new $class();
29
+                $content .= $jsloader->get_combined_js($_GET['debug']);
30
+            }
31
+        }
32
+    }
33 33
 }
34 34
 
35 35
 echo $content;
Please login to merge, or discard this patch.
plugins/files/php/modules/class.fileslistmodule.php 2 patches
Indentation   +723 added lines, -723 removed lines patch added patch discarded remove patch
@@ -23,727 +23,727 @@
 block discarded – undo
23 23
  */
24 24
 class FilesListModule extends ListModule
25 25
 {
26
-	const LOG_CONTEXT = "FilesListModule"; // Context for the Logger
27
-
28
-	// Unauthorized errors of different backends.
29
-	const SMB_ERR_UNAUTHORIZED = 13;
30
-	const SMB_ERR_FORBIDDEN = 1;
31
-	const FTP_WD_OWNCLOUD_ERR_UNAUTHORIZED = 401;
32
-	const FTP_WD_OWNCLOUD_ERR_FORBIDDEN = 403;
33
-	const ALL_BACKEND_ERR_NOTFOUND = 404;
34
-
35
-	/**
36
-	 * @var \phpFastCache cache handler.
37
-	 */
38
-	public $cache;
39
-
40
-	/**
41
-	 * @var String User id of the currently logged in user. Used to generate unique cache id's.
42
-	 */
43
-	public $uid;
44
-
45
-	/**
46
-	 * @var {Object} The account store holding all available accounts
47
-	 */
48
-	public $accountStore;
49
-
50
-	/**
51
-	 * @var {Object} The backend store holding all available backends
52
-	 */
53
-	public $backendStore;
54
-
55
-	/**
56
-	 * @constructor
57
-	 *
58
-	 * @param $id
59
-	 * @param $data
60
-	 */
61
-	public function __construct($id, $data)
62
-	{
63
-		parent::__construct($id, $data);
64
-
65
-		// Initialize the account and backendstore
66
-		$this->accountStore = new \Files\Core\AccountStore();
67
-		$this->backendStore = \Files\Backend\BackendStore::getInstance();
68
-
69
-		// Setup the cache
70
-		$config = new RedisConfig();
71
-		$config->setHost(PLUGIN_FILES_REDIS_HOST);
72
-		$config->setPort(PLUGIN_FILES_REDIS_PORT);
73
-		$config->setPassword(PLUGIN_FILES_REDIS_AUTH);
74
-
75
-		$this->cache = CacheManager::getInstance('Redis', $config);
76
-
77
-		// For backward compatibility we will check if the Encryption store exists. If not,
78
-		// we will fall back to the old way of retrieving the password from the session.
79
-		if ( class_exists('EncryptionStore') ) {
80
-			// Get the username from the Encryption store
81
-			$encryptionStore = \EncryptionStore::getInstance();
82
-			$this->uid = $encryptionStore->get('username');
83
-		} else {
84
-			$this->uid = $_SESSION["username"];
85
-		}
86
-		// As of the V6, the following characters can not longer being a part of the key identifier: {}()/\@:
87
-		// If you try to do so, an \phpFastCache\Exceptions\phpFastCacheInvalidArgumentException will be raised.
88
-		// You must replace them with a safe delimiter such as .|-_
89
-		// @see https://github.com/PHPSocialNetwork/phpfastcache/blob/8.1.2/docs/migration/MigratingFromV5ToV6.md
90
-		$this->uid = str_replace(['{', '}', '(', ')', '/', '\\', '@'], '_', $this->uid);
91
-
92
-		Logger::debug(self::LOG_CONTEXT, "[constructor]: executing the module as uid: " . $this->uid);
93
-	}
94
-
95
-	/**
96
-	 * Function get the folder data from backend.
97
-	 *
98
-	 * @return array return folders array.
99
-	 */
100
-	function getHierarchyList($isReload = false)
101
-	{
102
-		$data = array();
103
-		$data["item"] = array();
104
-		$versions =  $GLOBALS['PluginManager']->getPluginsVersion();
105
-		$filesVersion = $versions['files'];
106
-
107
-		// Clear cache when version gets changed and update 'files' version in cache.
108
-		if ($isReload ||  version_compare($this->getVersionFromCache('files'), $filesVersion) !== 0) {
109
-			$this->clearCache();
110
-			$this->setVersionInCache('files', $filesVersion);
111
-		}
112
-
113
-		$accounts = $this->accountStore->getAllAccounts();
114
-		foreach ($accounts as $account) {
115
-			// we have to load all accounts and their folders
116
-			// skip accounts that are not valid
117
-			if ($account->getStatus() !== \Files\Core\Account::STATUS_OK) {
118
-				continue;
119
-			}
120
-
121
-			// build the real node id for this folder
122
-			$realNodeId = "#R#" . $account->getId() . "/";
123
-			$accountName = $account->getName();
124
-			$rootId = $this->createId($realNodeId);
125
-			$nodes = array(
126
-				"store_entryid" => $rootId,
127
-				"props" => array(
128
-					'entryid' => $rootId,
129
-					'subtree_id' => $rootId,
130
-					'display_name' => $accountName,
131
-					"object_type" => FILES_STORE,
132
-					"status" => $account->getStatus(),
133
-					"status_description" => $account->getStatusDescription(),
134
-					"backend" => $account->getBackend(),
135
-					"backend_config" => $account->getBackendConfig(),
136
-					'backend_features' => $account->getFeatures(),
137
-					'filename' => $accountName,
138
-					'account_sequence' => $account->getSequence(),
139
-					'cannot_change' => $account->getCannotChangeFlag()
140
-				)
141
-			);
142
-
143
-			$initializedBackend = $this->initializeBackend($account, true);
144
-
145
-			// Get sub folder of root folder.
146
-			$subFolders = $this->getSubFolders($realNodeId, $initializedBackend);
147
-
148
-			array_push($subFolders, array(
149
-				'id' => $realNodeId,
150
-				'folder_id' => $realNodeId,
151
-				'entryid' => $rootId,
152
-				'parent_entryid' => $rootId,
153
-				'store_entryid' => $rootId,
154
-				'props' => array(
155
-					'path' => $realNodeId,
156
-					'icon_index' => ICON_FOLDER,
157
-					// Fixme : remove text property. we have to use display_name property.
158
-					'text' => $accountName,
159
-					'has_subfolder'=> empty($subFolders) === false,
160
-					'object_type' => FILES_FOLDER,
161
-					'filename' => $accountName,
162
-					'display_name' => $accountName,
163
-				)
164
-			));
165
-
166
-			// TODO: dummy folder which used client side to show the account view when user
167
-			//  switch to home folder using navigation bar.
168
-			array_push($subFolders, array(
169
-				'id' => "#R#",
170
-				'folder_id' => "#R#",
171
-				'entryid' => "#R#",
172
-				'parent_entryid' => $rootId,
173
-				'store_entryid' => $rootId,
174
-				'props' => array(
175
-					'path' => $realNodeId,
176
-					'icon_index' => ICON_HOME_FOLDER,
177
-					'text' => "Files",
178
-					'has_subfolder'=> false,
179
-					'object_type' => FILES_FOLDER,
180
-					'filename' => "Files",
181
-					'display_name' => "Files",
182
-				)
183
-			));
184
-			$nodes["folders"] = array( "item" => $subFolders);
185
-			array_push($data["item"], $nodes);
186
-		}
187
-
188
-		return $data;
189
-	}
190
-
191
-	/**
192
-	 * Function used to get the sub folders of the given folder id.
193
-	 *
194
-	 * @param String $nodeId The folder id which used to get sub folders.
195
-	 * @param array $backend The backend which used to retrieve the folders
196
-	 * @param bool $recursive The recursive true which get the sub folder recursively.
197
-	 * @param array $nodes The nodes contains the array of nodes.
198
-	 * @return array return the array folders.
199
-	 */
200
-	function getSubFolders($nodeId, $backend, $recursive = false, $nodes = array())
201
-	{
202
-		// relative node ID. We need to trim off the #R# and account ID
203
-		$relNodeId = substr($nodeId, strpos($nodeId, '/'));
204
-		$nodeIdPrefix = substr($nodeId, 0, strpos($nodeId, '/'));
205
-
206
-		$accountID = $backend->getAccountID();
207
-
208
-		// remove the trailing slash for the cache key
209
-		$cachePath = rtrim($relNodeId, '/');
210
-		if ($cachePath === "") {
211
-			$cachePath = "/";
212
-		}
213
-
214
-		$backendDisplayName = $backend->backendDisplayName;
215
-		$backendVersion = $backend->backendVersion;
216
-		$cacheVersion  = $this->getVersionFromCache($backendDisplayName, $accountID);
217
-		$dir = $this->getCache($accountID, $cachePath);
218
-
219
-		// Get new data from backend when cache is empty or the version of backend got changed.
220
-		if (is_null($dir) || version_compare($backendVersion,$cacheVersion) !== 0) {
221
-			$this->setVersionInCache($backendDisplayName, $backendVersion, $accountID);
222
-			$dir = $backend->ls($relNodeId);
223
-		}
224
-
225
-		if ($dir) {
226
-			$updateCache = false;
227
-			foreach ($dir as $id => $node) {
228
-				$objectType = strcmp($node['resourcetype'], "collection") !== 0 ? FILES_FILE : FILES_FOLDER;
229
-
230
-				// Only get the Folder item.
231
-				if ($objectType !== FILES_FOLDER) {
232
-					continue;
233
-				}
234
-
235
-				// Check if foldernames have a trailing slash, if not, add one!
236
-				if (!StringUtil::endsWith($id, "/")) {
237
-					unset($dir[$id]);
238
-					$id .= "/";
239
-					$dir[$id] = $node;
240
-				}
241
-
242
-				$size = $node['getcontentlength'] === null ? -1 : intval($node['getcontentlength']);
243
-				// folder's dont have a size
244
-				$size = $objectType == FILES_FILE ? $size : -1;
245
-
246
-				$realID = $nodeIdPrefix . $id;
247
-				$filename = stringToUTF8Encode(basename($id));
248
-
249
-				if (!isset($node['entryid']) || !isset($node['parent_entryid']) || !isset($node['store_entryid'])) {
250
-					$parentNode = $this->getParentNode($cachePath, $accountID);
251
-
252
-					$entryid = $this->createId($realID);
253
-					$parentEntryid = $parentNode !== false && isset($parentNode['entryid']) ? $parentNode['entryid'] : $this->createId($nodeId);
254
-					$storeEntryid = $this->createId($nodeIdPrefix .'/');
255
-
256
-					$dir[$id]['entryid'] = $entryid;
257
-					$dir[$id]['parent_entryid'] = $parentEntryid;
258
-					$dir[$id]['store_entryid'] = $storeEntryid;
259
-
260
-					$updateCache = true;
261
-				} else {
262
-					$entryid = $node['entryid'];
263
-					$parentEntryid = $node['parent_entryid'];
264
-					$storeEntryid = $node['store_entryid'];
265
-				}
266
-
267
-				$nodeHasSubFolder = $this->hasSubFolder($id, $accountID, $backend);
268
-				// Skip displaying folder whose data is unaccesable.
269
-				// Also update the cache.
270
-				if (is_null($nodeHasSubFolder)) {
271
-					unset($dir[$id]);
272
-					$updateCache = true;
273
-				} else {
274
-					array_push($nodes, array(
275
-						'id' => $realID,
276
-						'folder_id' => $realID,
277
-						'entryid' => $entryid,
278
-						'parent_entryid' => $parentEntryid,
279
-						'store_entryid' => $storeEntryid,
280
-						'props' => array(
281
-							'path' => $nodeId,
282
-							'message_size' => $size,
283
-							'text' => $filename,
284
-							'object_type' => $objectType,
285
-							'icon_index' => ICON_FOLDER,
286
-							'filename' => $filename,
287
-							'display_name' => $filename,
288
-							'lastmodified' => strtotime($node['getlastmodified']) * 1000,
289
-							'has_subfolder' => $nodeHasSubFolder
290
-						)
291
-					));
292
-				}
293
-
294
-				// We need to call this function recursively when user rename the folder.
295
-				// we have to send all sub folder as server side notification so grommunio Web
296
-				// can update the sub folder as per it's parent folder is renamed.
297
-				if ($objectType === FILES_FOLDER && $recursive) {
298
-					$nodes = $this->getSubFolders($realID, $backend, true, $nodes);
299
-				}
300
-			}
301
-
302
-			if ($updateCache) {
303
-				$this->setCache($accountID, $cachePath, $dir);
304
-			}
305
-		}
306
-		return $nodes;
307
-	}
308
-
309
-	/**
310
-	 * Function which used to get the parent folder of selected folder.
311
-	 *
312
-	 * @param string $cachePath The cache path of selected folder.
313
-	 * @param string $accountID The account ID in which folder is belongs.
314
-	 *
315
-	 * @return array | bool return the parent folder data else false.
316
-	 */
317
-	function getParentNode($cachePath, $accountID)
318
-	{
319
-		$parentNode = dirname($cachePath, 1);
320
-
321
-		// remove the trailing slash for the cache key
322
-		$parentNode = rtrim($parentNode, '/');
323
-		if ($parentNode === "") {
324
-			$parentNode = "/";
325
-		}
326
-		$dir = $this->getCache($accountID, $parentNode);
327
-
328
-		if (!is_null($dir) && isset($dir[$cachePath . '/'])) {
329
-			return $dir[$cachePath . '/'];
330
-		}
331
-		return false;
332
-	}
333
-
334
-	/**
335
-	 * Function create the unique id.
336
-	 *
337
-	 * @param {string} $id The folder id
338
-	 * @return return generated a hash value
339
-	 */
340
-	function createId($id)
341
-	{
342
-		return hash("tiger192,3", $id);
343
-	}
344
-
345
-	/**
346
-	 * Function will check that given folder has sub folder or not.
347
-	 * This will retrurn null when there's an exception retrieving folder data.
348
-	 *
349
-	 * @param {String} $id The $id is id of selected folder.
350
-	 * @param $accountID
351
-	 * @param $backend
352
-	 * @return bool or null when unable to access folder data.
353
-	 */
354
-	function hasSubFolder($id, $accountID, $backend)
355
-	{
356
-		$cachePath = rtrim($id, '/');
357
-		if ($cachePath === "") {
358
-			$cachePath = "/";
359
-		}
360
-
361
-		$dir = $this->getCache($accountID, $cachePath);
362
-		if (is_null($dir)) {
363
-			try {
364
-				$dir = $backend->ls($id);
365
-				$this->setCache($accountID, $cachePath, $dir);
366
-			} catch (Exception $e) {
367
-				$errorCode = $e->getCode();
368
-
369
-				// If folder not found or folder doesn't have enough access then don't display that folder.
370
-				if ($errorCode === self::SMB_ERR_UNAUTHORIZED ||
371
-				$errorCode === self::SMB_ERR_FORBIDDEN ||
372
-				$errorCode === self::FTP_WD_OWNCLOUD_ERR_UNAUTHORIZED ||
373
-				$errorCode === self::FTP_WD_OWNCLOUD_ERR_FORBIDDEN||
374
-				$errorCode === self::ALL_BACKEND_ERR_NOTFOUND) {
375
-
376
-					if ($errorCode === self::ALL_BACKEND_ERR_NOTFOUND) {
377
-						Logger::error(self::LOG_CONTEXT, '[hasSubFolder]: folder '. $id .' not found');
378
-					} else {
379
-						Logger::error(self::LOG_CONTEXT, '[hasSubFolder]: Access denied for folder '. $id);
380
-					}
381
-					return null;
382
-				}
383
-				// rethrow exception if its not related to access permission.
384
-				throw $e;
385
-			}
386
-		}
387
-
388
-		if ($dir) {
389
-			foreach ($dir as $id => $node) {
390
-				if (strcmp($node['resourcetype'], "collection") === 0) {
391
-					// we have a folder
392
-					return true;
393
-				}
394
-			}
395
-		}
396
-		return false;
397
-	}
398
-
399
-	/**
400
-	 * @param $actionType
401
-	 * @param $actionData
402
-	 * @throws \Files\Backend\Exception
403
-	 */
404
-	function save($actionData)
405
-	{
406
-		$response = array();
407
-		$props = $actionData["props"];
408
-		$messageProps = array();
409
-		if (isset($actionData["entryid"]) && empty($actionData["entryid"])) {
410
-			$path = isset($props['path']) && !empty($props['path']) ? $props['path'] : "/";
411
-
412
-			$relDirname = substr($path, strpos($path, '/'));
413
-			$relDirname = $relDirname . $props["display_name"] .'/';
414
-			$account = $this->accountFromNode($path);
415
-
416
-			// initialize the backend
417
-			$initializedBackend = $this->initializeBackend($account, true);
418
-			$relDirname = stringToUTF8Encode($relDirname);
419
-			$result = $initializedBackend->mkcol($relDirname); // create it !
420
-
421
-			$filesPath = substr($path, strpos($path, '/'));
422
-			$dir = $initializedBackend->ls($filesPath);
423
-
424
-			$id = $path . $props["display_name"] . '/';
425
-
426
-			$actionId = $account->getId();
427
-
428
-			$entryid = $this->createId($id);
429
-			$parentEntryid = $actionData["parent_entryid"];
430
-			$storeEntryid = $this->createId('#R#' . $actionId . '/');
431
-
432
-			$cachePath = rtrim($relDirname, '/');
433
-			if ($cachePath === "") {
434
-				$cachePath = "/";
435
-			}
436
-
437
-			if (isset($dir[$relDirname]) && !empty($dir[$relDirname])) {
438
-				$newDir = $dir[$relDirname];
439
-				$newDir['entryid'] = $entryid;
440
-				$newDir['parent_entryid'] = $parentEntryid;
441
-				$newDir['store_entryid'] = $storeEntryid;
442
-
443
-				// Get old cached data.
444
-				$cachedDir = $this->getCache($actionId, dirname($cachePath, 1));
445
-
446
-				// Insert newly created folder info with entryid, parentEntryid and storeEntryid
447
-				// in already cached data.
448
-				$cachedDir[$relDirname] = $newDir;
449
-				$dir = $cachedDir;
450
-			}
451
-
452
-			// Delete old cache.
453
-			$this->deleteCache($actionId, dirname($relDirname));
454
-
455
-			// Set data in cache.
456
-			$this->setCache($actionId, dirname($relDirname), $dir);
457
-
458
-			if ($result) {
459
-				$folder = array(
460
-					'props' =>
461
-						array(
462
-							'path' => $path,
463
-							'filename' => $props["display_name"],
464
-							'display_name' => $props["display_name"],
465
-							'text' => $props["display_name"],
466
-							'object_type' => $props['object_type'],
467
-							'has_subfolder' => false,
468
-						),
469
-					'id' => rawurldecode($id),
470
-					'folder_id' => rawurldecode($id),
471
-					'entryid' => $entryid,
472
-					'parent_entryid' => $parentEntryid,
473
-					'store_entryid' => $storeEntryid
474
-				);
475
-				$response = $folder;
476
-			}
477
-		} else {
478
-			// Rename/update the folder/file name
479
-			$folderId = $actionData['message_action']["source_folder_id"];
480
-			// rename/update the folder or files name.
481
-			$parentEntryid = $actionData["parent_entryid"];
482
-
483
-			$isfolder = "";
484
-			if (substr($folderId, -1) == '/') {
485
-				$isfolder = "/"; // we have a folder...
486
-			}
487
-
488
-			$src = rtrim($folderId, '/');
489
-			$dstdir = dirname($src) == "/" ? "" : dirname($src);
490
-			$dst = $dstdir . "/" . rtrim($props['filename'], '/');
491
-
492
-			$relDst = substr($dst, strpos($dst, '/'));
493
-			$relSrc = substr($src, strpos($src, '/'));
494
-
495
-			$account = $this->accountFromNode($src);
496
-
497
-			// initialize the backend
498
-			$initializedBackend = $this->initializeBackend($account);
499
-
500
-			$result = $initializedBackend->move($relSrc, $relDst, false);
501
-
502
-			// get the cache data of parent directory.
503
-			$dir = $this->getCache($account->getId(), dirname($relSrc));
504
-			if (isset($dir[$relSrc . "/"]) && !empty($dir[$relSrc . "/"])) {
505
-				$srcDir = $dir[$relSrc . "/"];
506
-				unset($dir[$relSrc . "/"]);
507
-				$dir[$relDst . "/"] = $srcDir;
508
-
509
-				// Update only rename folder info in php cache.
510
-				$this->setCache($account->getId(), dirname($relSrc), $dir);
511
-
512
-				$this->updateCacheAfterRename($relSrc, $relDst, $account->getId());
513
-			} else {
514
-				// clear the cache
515
-				$this->deleteCache($account->getId(), dirname($relSrc));
516
-			}
517
-
518
-			if ($result) {
519
-				/* create the response object */
520
-				$folder = array();
521
-
522
-				// some requests might not contain a new filename... so dont update the store
523
-				if (isset($props['filename'])) {
524
-					$folder = array(
525
-						'props' =>
526
-							array(
527
-								'folder_id' => rawurldecode($dst . $isfolder),
528
-								'path' => rawurldecode($dstdir),
529
-								'filename' =>$props['filename'],
530
-								'display_name' =>$props['filename']
531
-							),
532
-						'entryid' => $actionData["entryid"],
533
-						'parent_entryid' => $parentEntryid,
534
-						'store_entryid' => $actionData["store_entryid"]
535
-					);
536
-				}
537
-				$response['item'] = $folder;
538
-				$messageProps = $folder;
539
-			}
540
-		}
541
-
542
-		$this->addActionData("update", $response);
543
-		$GLOBALS["bus"]->addData($this->getResponseData());
544
-		return $messageProps;
545
-	}
546
-
547
-	/**
548
-	 * Update the cache of renamed folder and it's sub folders.
549
-	 *
550
-	 * @param {String} $oldPath The $oldPath is path of folder before rename.
551
-	 * @param {String} $newPath The $newPath is path of folder after rename.
552
-	 * @param {String} $accountId The id of an account in which renamed folder is belongs.
553
-	 */
554
-	function updateCacheAfterRename($oldPath, $newPath, $accountId)
555
-	{
556
-		// remove the trailing slash for the cache key
557
-		$cachePath = rtrim($oldPath, '/');
558
-		if ($cachePath === "") {
559
-			$cachePath = "/";
560
-		}
561
-
562
-		$dir = $this->getCache($accountId, $cachePath);
563
-		if ($dir) {
564
-			foreach ($dir as $id => $node) {
565
-				$newId = str_replace(dirname($id), $newPath, $id);
566
-				unset($dir[$id]);
567
-				$dir[$newId] = $node;
568
-
569
-				$type = FILES_FILE;
570
-
571
-				if (strcmp($node['resourcetype'], "collection") == 0) { // we have a folder
572
-					$type = FILES_FOLDER;
573
-				}
574
-
575
-				if ($type === FILES_FOLDER) {
576
-					$this->updateCacheAfterRename($id,  rtrim($newId, '/'), $accountId);
577
-				}
578
-			}
579
-			$this->deleteCache($accountId, $cachePath);
580
-			$this->setCache($accountId, $newPath, $dir);
581
-		}
582
-	}
583
-
584
-	/**
585
-	 * Function used to notify the sub folder of selected/modified folder.
586
-	 *
587
-	 * @param {String} $folderID The $folderID of a folder which is modified.
588
-	 */
589
-	function notifySubFolders($folderID)
590
-	{
591
-		$account = $this->accountFromNode($folderID);
592
-		$initializedBackend = $this->initializeBackend($account, true);
593
-		$folderData = $this->getSubFolders($folderID, $initializedBackend, true);
594
-
595
-		if (!empty($folderData)) {
596
-			$GLOBALS["bus"]->notify(REQUEST_ENTRYID, OBJECT_SAVE, $folderData);
597
-		}
598
-	}
599
-
600
-	/**
601
-	 * Get the account id from a node id.
602
-	 * @param {String} $nodeID Id of the file or folder to operate on
603
-	 * @return {String} The account id extracted from $nodeId
604
-	 */
605
-	function accountIDFromNode($nodeID)
606
-	{
607
-		return substr($nodeID, 3, (strpos($nodeID, '/') - 3)); // parse account id from node id
608
-	}
609
-
610
-	/**
611
-	 * Get the account from a node id.
612
-	 * @param {String} $nodeId ID of the file or folder to operate on
613
-	 * @return {String} The account for $nodeId
614
-	 */
615
-	function accountFromNode($nodeID)
616
-	{
617
-		return $this->accountStore->getAccount($this->accountIDFromNode($nodeID));
618
-	}
619
-
620
-	/**
621
-	 * Create a key used to store data in the cache.
622
-	 * @param {String} $accountID Id of the account of the data to cache
623
-	 * @param {String} $path Path of the file or folder to create the cache element for
624
-	 * @return {String} The created key
625
-	 */
626
-	function makeCacheKey($accountID, $path)
627
-	{
628
-		return $this->uid . md5($accountID . $path);
629
-	}
630
-
631
-	/**
632
-	 * Get version data form the cache.
633
-	 *
634
-	 * @param {String} $displayName display name of the backend or file plugin
635
-	 * @param {String} $accountID Id of the account of the data to cache
636
-	 * @return {String} version data or null if nothing was found
637
-	 */
638
-	function getVersionFromCache($displayName, $accountID = '')
639
-	{
640
-		$key =  $this->uid . $accountID . $displayName;
641
-		return $this->cache->getItem($key)->get();
642
-	}
643
-
644
-	/**
645
-	 * Set version data in the cache only when version data has been changed.
646
-	 *
647
-	 * @param {String} $displayName display name of the backend or file plugin
648
-	 * @param {String} $version version info of backend or file plugin which needs to be cached
649
-	 * @param {String} $accountID Id of the account of the data to cache
650
-	 */
651
-	function setVersionInCache($displayName, $version, $accountID = '')
652
-	{
653
-		$olderVersionFromCache = $this->getVersionFromCache($displayName, $accountID);
654
-		// If version of files/backend is same then return.
655
-		if (version_compare($olderVersionFromCache,$version) === 0) {
656
-			return;
657
-		}
658
-
659
-		$key = $this->uid . $accountID . $displayName;
660
-		$this->cache->save($this->cache->getItem($key)->set($version));
661
-	}
662
-
663
-	/**
664
-	 * Initialize the backend for the given account.
665
-	 * @param {Object} $account The account object the backend should be initialized for
666
-	 * @param {Bool} $setID Should the accountID be set in the backend object, or not. Defaults to false.
667
-	 * @return {Object} The initialized backend
668
-	 */
669
-	function initializeBackend($account, $setID = false)
670
-	{
671
-		$backend = $this->backendStore->getInstanceOfBackend($account->getBackend());
672
-		$backend->init_backend($account->getBackendConfig());
673
-		if($setID) {
674
-			$backend->setAccountID($account->getId());
675
-		}
676
-		$backend->open();
677
-		return $backend;
678
-	}
679
-
680
-	/**
681
-	 * Save directory data in the cache.
682
-	 * @param {String} $accountID Id of the account of the data to cache
683
-	 * @param {String} $path Path of the file or folder to create the cache element for
684
-	 * @param {String} $data Data to be cached
685
-	 */
686
-	function setCache($accountID, $path, $data)
687
-	{
688
-		$key = $this->makeCacheKey($accountID, $path);
689
-		Logger::debug(self::LOG_CONTEXT, "Setting cache for node: " . $accountID . $path . " ## " . $key);
690
-		$this->cache->save($this->cache->getItem($key)->set($data));
691
-	}
692
-
693
-	/**
694
-	 * Get directotry data form the cache.
695
-	 * @param {String} $accountID Id of the account of the data to get
696
-	 * @param {String} $path Path of the file or folder to retrieve the cache element for
697
-	 * @return {String} The directory data or null if nothing was found
698
-	 */
699
-	function getCache($accountID, $path)
700
-	{
701
-		$key = $this->makeCacheKey($accountID, $path);
702
-		Logger::debug(self::LOG_CONTEXT, "Getting cache for node: " . $accountID . $path . " ## " . $key);
703
-		return $this->cache->getItem($key)->get();
704
-	}
705
-
706
-	/**
707
-	 * Remove data from the cache.
708
-	 * @param {String} $accountID Id of the account to delete the cache for
709
-	 * @param {String} $path Path of the file or folder to delete the cache element
710
-	 */
711
-	function deleteCache($accountID, $path)
712
-	{
713
-		$key = $this->makeCacheKey($accountID, $path);
714
-		Logger::debug(self::LOG_CONTEXT, "Removing cache for node: " . $accountID .  $path . " ## " . $key);
715
-		$this->cache->deleteItem($key);
716
-	}
717
-
718
-	/**
719
-	 * Function clear the cache.
720
-	 */
721
-	function clearCache()
722
-	{
723
-		$this->cache->clear();
724
-	}
725
-
726
-	/**
727
-	 * Function which returns MAPI Message Store Object. It
728
-	 * searches in the variable $action for a storeid.
729
-	 * @param array $action the XML data retrieved from the client
730
-	 * @return object MAPI Message Store Object, false if storeid is not found in the $action variable
731
-	 */
732
-	function getActionStore($action)
733
-	{
734
-		$store = false;
735
-
736
-		if(isset($action["store_entryid"]) && !empty($action["store_entryid"])) {
737
-			if(is_array($action["store_entryid"])) {
738
-				$store = array();
739
-				foreach($action["store_entryid"] as $store_id) {
740
-					array_push($store, $store_id);
741
-				}
742
-			} else {
743
-				$store = $action["store_entryid"];
744
-			}
745
-		}
746
-
747
-		return $store;
748
-	}
26
+    const LOG_CONTEXT = "FilesListModule"; // Context for the Logger
27
+
28
+    // Unauthorized errors of different backends.
29
+    const SMB_ERR_UNAUTHORIZED = 13;
30
+    const SMB_ERR_FORBIDDEN = 1;
31
+    const FTP_WD_OWNCLOUD_ERR_UNAUTHORIZED = 401;
32
+    const FTP_WD_OWNCLOUD_ERR_FORBIDDEN = 403;
33
+    const ALL_BACKEND_ERR_NOTFOUND = 404;
34
+
35
+    /**
36
+     * @var \phpFastCache cache handler.
37
+     */
38
+    public $cache;
39
+
40
+    /**
41
+     * @var String User id of the currently logged in user. Used to generate unique cache id's.
42
+     */
43
+    public $uid;
44
+
45
+    /**
46
+     * @var {Object} The account store holding all available accounts
47
+     */
48
+    public $accountStore;
49
+
50
+    /**
51
+     * @var {Object} The backend store holding all available backends
52
+     */
53
+    public $backendStore;
54
+
55
+    /**
56
+     * @constructor
57
+     *
58
+     * @param $id
59
+     * @param $data
60
+     */
61
+    public function __construct($id, $data)
62
+    {
63
+        parent::__construct($id, $data);
64
+
65
+        // Initialize the account and backendstore
66
+        $this->accountStore = new \Files\Core\AccountStore();
67
+        $this->backendStore = \Files\Backend\BackendStore::getInstance();
68
+
69
+        // Setup the cache
70
+        $config = new RedisConfig();
71
+        $config->setHost(PLUGIN_FILES_REDIS_HOST);
72
+        $config->setPort(PLUGIN_FILES_REDIS_PORT);
73
+        $config->setPassword(PLUGIN_FILES_REDIS_AUTH);
74
+
75
+        $this->cache = CacheManager::getInstance('Redis', $config);
76
+
77
+        // For backward compatibility we will check if the Encryption store exists. If not,
78
+        // we will fall back to the old way of retrieving the password from the session.
79
+        if ( class_exists('EncryptionStore') ) {
80
+            // Get the username from the Encryption store
81
+            $encryptionStore = \EncryptionStore::getInstance();
82
+            $this->uid = $encryptionStore->get('username');
83
+        } else {
84
+            $this->uid = $_SESSION["username"];
85
+        }
86
+        // As of the V6, the following characters can not longer being a part of the key identifier: {}()/\@:
87
+        // If you try to do so, an \phpFastCache\Exceptions\phpFastCacheInvalidArgumentException will be raised.
88
+        // You must replace them with a safe delimiter such as .|-_
89
+        // @see https://github.com/PHPSocialNetwork/phpfastcache/blob/8.1.2/docs/migration/MigratingFromV5ToV6.md
90
+        $this->uid = str_replace(['{', '}', '(', ')', '/', '\\', '@'], '_', $this->uid);
91
+
92
+        Logger::debug(self::LOG_CONTEXT, "[constructor]: executing the module as uid: " . $this->uid);
93
+    }
94
+
95
+    /**
96
+     * Function get the folder data from backend.
97
+     *
98
+     * @return array return folders array.
99
+     */
100
+    function getHierarchyList($isReload = false)
101
+    {
102
+        $data = array();
103
+        $data["item"] = array();
104
+        $versions =  $GLOBALS['PluginManager']->getPluginsVersion();
105
+        $filesVersion = $versions['files'];
106
+
107
+        // Clear cache when version gets changed and update 'files' version in cache.
108
+        if ($isReload ||  version_compare($this->getVersionFromCache('files'), $filesVersion) !== 0) {
109
+            $this->clearCache();
110
+            $this->setVersionInCache('files', $filesVersion);
111
+        }
112
+
113
+        $accounts = $this->accountStore->getAllAccounts();
114
+        foreach ($accounts as $account) {
115
+            // we have to load all accounts and their folders
116
+            // skip accounts that are not valid
117
+            if ($account->getStatus() !== \Files\Core\Account::STATUS_OK) {
118
+                continue;
119
+            }
120
+
121
+            // build the real node id for this folder
122
+            $realNodeId = "#R#" . $account->getId() . "/";
123
+            $accountName = $account->getName();
124
+            $rootId = $this->createId($realNodeId);
125
+            $nodes = array(
126
+                "store_entryid" => $rootId,
127
+                "props" => array(
128
+                    'entryid' => $rootId,
129
+                    'subtree_id' => $rootId,
130
+                    'display_name' => $accountName,
131
+                    "object_type" => FILES_STORE,
132
+                    "status" => $account->getStatus(),
133
+                    "status_description" => $account->getStatusDescription(),
134
+                    "backend" => $account->getBackend(),
135
+                    "backend_config" => $account->getBackendConfig(),
136
+                    'backend_features' => $account->getFeatures(),
137
+                    'filename' => $accountName,
138
+                    'account_sequence' => $account->getSequence(),
139
+                    'cannot_change' => $account->getCannotChangeFlag()
140
+                )
141
+            );
142
+
143
+            $initializedBackend = $this->initializeBackend($account, true);
144
+
145
+            // Get sub folder of root folder.
146
+            $subFolders = $this->getSubFolders($realNodeId, $initializedBackend);
147
+
148
+            array_push($subFolders, array(
149
+                'id' => $realNodeId,
150
+                'folder_id' => $realNodeId,
151
+                'entryid' => $rootId,
152
+                'parent_entryid' => $rootId,
153
+                'store_entryid' => $rootId,
154
+                'props' => array(
155
+                    'path' => $realNodeId,
156
+                    'icon_index' => ICON_FOLDER,
157
+                    // Fixme : remove text property. we have to use display_name property.
158
+                    'text' => $accountName,
159
+                    'has_subfolder'=> empty($subFolders) === false,
160
+                    'object_type' => FILES_FOLDER,
161
+                    'filename' => $accountName,
162
+                    'display_name' => $accountName,
163
+                )
164
+            ));
165
+
166
+            // TODO: dummy folder which used client side to show the account view when user
167
+            //  switch to home folder using navigation bar.
168
+            array_push($subFolders, array(
169
+                'id' => "#R#",
170
+                'folder_id' => "#R#",
171
+                'entryid' => "#R#",
172
+                'parent_entryid' => $rootId,
173
+                'store_entryid' => $rootId,
174
+                'props' => array(
175
+                    'path' => $realNodeId,
176
+                    'icon_index' => ICON_HOME_FOLDER,
177
+                    'text' => "Files",
178
+                    'has_subfolder'=> false,
179
+                    'object_type' => FILES_FOLDER,
180
+                    'filename' => "Files",
181
+                    'display_name' => "Files",
182
+                )
183
+            ));
184
+            $nodes["folders"] = array( "item" => $subFolders);
185
+            array_push($data["item"], $nodes);
186
+        }
187
+
188
+        return $data;
189
+    }
190
+
191
+    /**
192
+     * Function used to get the sub folders of the given folder id.
193
+     *
194
+     * @param String $nodeId The folder id which used to get sub folders.
195
+     * @param array $backend The backend which used to retrieve the folders
196
+     * @param bool $recursive The recursive true which get the sub folder recursively.
197
+     * @param array $nodes The nodes contains the array of nodes.
198
+     * @return array return the array folders.
199
+     */
200
+    function getSubFolders($nodeId, $backend, $recursive = false, $nodes = array())
201
+    {
202
+        // relative node ID. We need to trim off the #R# and account ID
203
+        $relNodeId = substr($nodeId, strpos($nodeId, '/'));
204
+        $nodeIdPrefix = substr($nodeId, 0, strpos($nodeId, '/'));
205
+
206
+        $accountID = $backend->getAccountID();
207
+
208
+        // remove the trailing slash for the cache key
209
+        $cachePath = rtrim($relNodeId, '/');
210
+        if ($cachePath === "") {
211
+            $cachePath = "/";
212
+        }
213
+
214
+        $backendDisplayName = $backend->backendDisplayName;
215
+        $backendVersion = $backend->backendVersion;
216
+        $cacheVersion  = $this->getVersionFromCache($backendDisplayName, $accountID);
217
+        $dir = $this->getCache($accountID, $cachePath);
218
+
219
+        // Get new data from backend when cache is empty or the version of backend got changed.
220
+        if (is_null($dir) || version_compare($backendVersion,$cacheVersion) !== 0) {
221
+            $this->setVersionInCache($backendDisplayName, $backendVersion, $accountID);
222
+            $dir = $backend->ls($relNodeId);
223
+        }
224
+
225
+        if ($dir) {
226
+            $updateCache = false;
227
+            foreach ($dir as $id => $node) {
228
+                $objectType = strcmp($node['resourcetype'], "collection") !== 0 ? FILES_FILE : FILES_FOLDER;
229
+
230
+                // Only get the Folder item.
231
+                if ($objectType !== FILES_FOLDER) {
232
+                    continue;
233
+                }
234
+
235
+                // Check if foldernames have a trailing slash, if not, add one!
236
+                if (!StringUtil::endsWith($id, "/")) {
237
+                    unset($dir[$id]);
238
+                    $id .= "/";
239
+                    $dir[$id] = $node;
240
+                }
241
+
242
+                $size = $node['getcontentlength'] === null ? -1 : intval($node['getcontentlength']);
243
+                // folder's dont have a size
244
+                $size = $objectType == FILES_FILE ? $size : -1;
245
+
246
+                $realID = $nodeIdPrefix . $id;
247
+                $filename = stringToUTF8Encode(basename($id));
248
+
249
+                if (!isset($node['entryid']) || !isset($node['parent_entryid']) || !isset($node['store_entryid'])) {
250
+                    $parentNode = $this->getParentNode($cachePath, $accountID);
251
+
252
+                    $entryid = $this->createId($realID);
253
+                    $parentEntryid = $parentNode !== false && isset($parentNode['entryid']) ? $parentNode['entryid'] : $this->createId($nodeId);
254
+                    $storeEntryid = $this->createId($nodeIdPrefix .'/');
255
+
256
+                    $dir[$id]['entryid'] = $entryid;
257
+                    $dir[$id]['parent_entryid'] = $parentEntryid;
258
+                    $dir[$id]['store_entryid'] = $storeEntryid;
259
+
260
+                    $updateCache = true;
261
+                } else {
262
+                    $entryid = $node['entryid'];
263
+                    $parentEntryid = $node['parent_entryid'];
264
+                    $storeEntryid = $node['store_entryid'];
265
+                }
266
+
267
+                $nodeHasSubFolder = $this->hasSubFolder($id, $accountID, $backend);
268
+                // Skip displaying folder whose data is unaccesable.
269
+                // Also update the cache.
270
+                if (is_null($nodeHasSubFolder)) {
271
+                    unset($dir[$id]);
272
+                    $updateCache = true;
273
+                } else {
274
+                    array_push($nodes, array(
275
+                        'id' => $realID,
276
+                        'folder_id' => $realID,
277
+                        'entryid' => $entryid,
278
+                        'parent_entryid' => $parentEntryid,
279
+                        'store_entryid' => $storeEntryid,
280
+                        'props' => array(
281
+                            'path' => $nodeId,
282
+                            'message_size' => $size,
283
+                            'text' => $filename,
284
+                            'object_type' => $objectType,
285
+                            'icon_index' => ICON_FOLDER,
286
+                            'filename' => $filename,
287
+                            'display_name' => $filename,
288
+                            'lastmodified' => strtotime($node['getlastmodified']) * 1000,
289
+                            'has_subfolder' => $nodeHasSubFolder
290
+                        )
291
+                    ));
292
+                }
293
+
294
+                // We need to call this function recursively when user rename the folder.
295
+                // we have to send all sub folder as server side notification so grommunio Web
296
+                // can update the sub folder as per it's parent folder is renamed.
297
+                if ($objectType === FILES_FOLDER && $recursive) {
298
+                    $nodes = $this->getSubFolders($realID, $backend, true, $nodes);
299
+                }
300
+            }
301
+
302
+            if ($updateCache) {
303
+                $this->setCache($accountID, $cachePath, $dir);
304
+            }
305
+        }
306
+        return $nodes;
307
+    }
308
+
309
+    /**
310
+     * Function which used to get the parent folder of selected folder.
311
+     *
312
+     * @param string $cachePath The cache path of selected folder.
313
+     * @param string $accountID The account ID in which folder is belongs.
314
+     *
315
+     * @return array | bool return the parent folder data else false.
316
+     */
317
+    function getParentNode($cachePath, $accountID)
318
+    {
319
+        $parentNode = dirname($cachePath, 1);
320
+
321
+        // remove the trailing slash for the cache key
322
+        $parentNode = rtrim($parentNode, '/');
323
+        if ($parentNode === "") {
324
+            $parentNode = "/";
325
+        }
326
+        $dir = $this->getCache($accountID, $parentNode);
327
+
328
+        if (!is_null($dir) && isset($dir[$cachePath . '/'])) {
329
+            return $dir[$cachePath . '/'];
330
+        }
331
+        return false;
332
+    }
333
+
334
+    /**
335
+     * Function create the unique id.
336
+     *
337
+     * @param {string} $id The folder id
338
+     * @return return generated a hash value
339
+     */
340
+    function createId($id)
341
+    {
342
+        return hash("tiger192,3", $id);
343
+    }
344
+
345
+    /**
346
+     * Function will check that given folder has sub folder or not.
347
+     * This will retrurn null when there's an exception retrieving folder data.
348
+     *
349
+     * @param {String} $id The $id is id of selected folder.
350
+     * @param $accountID
351
+     * @param $backend
352
+     * @return bool or null when unable to access folder data.
353
+     */
354
+    function hasSubFolder($id, $accountID, $backend)
355
+    {
356
+        $cachePath = rtrim($id, '/');
357
+        if ($cachePath === "") {
358
+            $cachePath = "/";
359
+        }
360
+
361
+        $dir = $this->getCache($accountID, $cachePath);
362
+        if (is_null($dir)) {
363
+            try {
364
+                $dir = $backend->ls($id);
365
+                $this->setCache($accountID, $cachePath, $dir);
366
+            } catch (Exception $e) {
367
+                $errorCode = $e->getCode();
368
+
369
+                // If folder not found or folder doesn't have enough access then don't display that folder.
370
+                if ($errorCode === self::SMB_ERR_UNAUTHORIZED ||
371
+                $errorCode === self::SMB_ERR_FORBIDDEN ||
372
+                $errorCode === self::FTP_WD_OWNCLOUD_ERR_UNAUTHORIZED ||
373
+                $errorCode === self::FTP_WD_OWNCLOUD_ERR_FORBIDDEN||
374
+                $errorCode === self::ALL_BACKEND_ERR_NOTFOUND) {
375
+
376
+                    if ($errorCode === self::ALL_BACKEND_ERR_NOTFOUND) {
377
+                        Logger::error(self::LOG_CONTEXT, '[hasSubFolder]: folder '. $id .' not found');
378
+                    } else {
379
+                        Logger::error(self::LOG_CONTEXT, '[hasSubFolder]: Access denied for folder '. $id);
380
+                    }
381
+                    return null;
382
+                }
383
+                // rethrow exception if its not related to access permission.
384
+                throw $e;
385
+            }
386
+        }
387
+
388
+        if ($dir) {
389
+            foreach ($dir as $id => $node) {
390
+                if (strcmp($node['resourcetype'], "collection") === 0) {
391
+                    // we have a folder
392
+                    return true;
393
+                }
394
+            }
395
+        }
396
+        return false;
397
+    }
398
+
399
+    /**
400
+     * @param $actionType
401
+     * @param $actionData
402
+     * @throws \Files\Backend\Exception
403
+     */
404
+    function save($actionData)
405
+    {
406
+        $response = array();
407
+        $props = $actionData["props"];
408
+        $messageProps = array();
409
+        if (isset($actionData["entryid"]) && empty($actionData["entryid"])) {
410
+            $path = isset($props['path']) && !empty($props['path']) ? $props['path'] : "/";
411
+
412
+            $relDirname = substr($path, strpos($path, '/'));
413
+            $relDirname = $relDirname . $props["display_name"] .'/';
414
+            $account = $this->accountFromNode($path);
415
+
416
+            // initialize the backend
417
+            $initializedBackend = $this->initializeBackend($account, true);
418
+            $relDirname = stringToUTF8Encode($relDirname);
419
+            $result = $initializedBackend->mkcol($relDirname); // create it !
420
+
421
+            $filesPath = substr($path, strpos($path, '/'));
422
+            $dir = $initializedBackend->ls($filesPath);
423
+
424
+            $id = $path . $props["display_name"] . '/';
425
+
426
+            $actionId = $account->getId();
427
+
428
+            $entryid = $this->createId($id);
429
+            $parentEntryid = $actionData["parent_entryid"];
430
+            $storeEntryid = $this->createId('#R#' . $actionId . '/');
431
+
432
+            $cachePath = rtrim($relDirname, '/');
433
+            if ($cachePath === "") {
434
+                $cachePath = "/";
435
+            }
436
+
437
+            if (isset($dir[$relDirname]) && !empty($dir[$relDirname])) {
438
+                $newDir = $dir[$relDirname];
439
+                $newDir['entryid'] = $entryid;
440
+                $newDir['parent_entryid'] = $parentEntryid;
441
+                $newDir['store_entryid'] = $storeEntryid;
442
+
443
+                // Get old cached data.
444
+                $cachedDir = $this->getCache($actionId, dirname($cachePath, 1));
445
+
446
+                // Insert newly created folder info with entryid, parentEntryid and storeEntryid
447
+                // in already cached data.
448
+                $cachedDir[$relDirname] = $newDir;
449
+                $dir = $cachedDir;
450
+            }
451
+
452
+            // Delete old cache.
453
+            $this->deleteCache($actionId, dirname($relDirname));
454
+
455
+            // Set data in cache.
456
+            $this->setCache($actionId, dirname($relDirname), $dir);
457
+
458
+            if ($result) {
459
+                $folder = array(
460
+                    'props' =>
461
+                        array(
462
+                            'path' => $path,
463
+                            'filename' => $props["display_name"],
464
+                            'display_name' => $props["display_name"],
465
+                            'text' => $props["display_name"],
466
+                            'object_type' => $props['object_type'],
467
+                            'has_subfolder' => false,
468
+                        ),
469
+                    'id' => rawurldecode($id),
470
+                    'folder_id' => rawurldecode($id),
471
+                    'entryid' => $entryid,
472
+                    'parent_entryid' => $parentEntryid,
473
+                    'store_entryid' => $storeEntryid
474
+                );
475
+                $response = $folder;
476
+            }
477
+        } else {
478
+            // Rename/update the folder/file name
479
+            $folderId = $actionData['message_action']["source_folder_id"];
480
+            // rename/update the folder or files name.
481
+            $parentEntryid = $actionData["parent_entryid"];
482
+
483
+            $isfolder = "";
484
+            if (substr($folderId, -1) == '/') {
485
+                $isfolder = "/"; // we have a folder...
486
+            }
487
+
488
+            $src = rtrim($folderId, '/');
489
+            $dstdir = dirname($src) == "/" ? "" : dirname($src);
490
+            $dst = $dstdir . "/" . rtrim($props['filename'], '/');
491
+
492
+            $relDst = substr($dst, strpos($dst, '/'));
493
+            $relSrc = substr($src, strpos($src, '/'));
494
+
495
+            $account = $this->accountFromNode($src);
496
+
497
+            // initialize the backend
498
+            $initializedBackend = $this->initializeBackend($account);
499
+
500
+            $result = $initializedBackend->move($relSrc, $relDst, false);
501
+
502
+            // get the cache data of parent directory.
503
+            $dir = $this->getCache($account->getId(), dirname($relSrc));
504
+            if (isset($dir[$relSrc . "/"]) && !empty($dir[$relSrc . "/"])) {
505
+                $srcDir = $dir[$relSrc . "/"];
506
+                unset($dir[$relSrc . "/"]);
507
+                $dir[$relDst . "/"] = $srcDir;
508
+
509
+                // Update only rename folder info in php cache.
510
+                $this->setCache($account->getId(), dirname($relSrc), $dir);
511
+
512
+                $this->updateCacheAfterRename($relSrc, $relDst, $account->getId());
513
+            } else {
514
+                // clear the cache
515
+                $this->deleteCache($account->getId(), dirname($relSrc));
516
+            }
517
+
518
+            if ($result) {
519
+                /* create the response object */
520
+                $folder = array();
521
+
522
+                // some requests might not contain a new filename... so dont update the store
523
+                if (isset($props['filename'])) {
524
+                    $folder = array(
525
+                        'props' =>
526
+                            array(
527
+                                'folder_id' => rawurldecode($dst . $isfolder),
528
+                                'path' => rawurldecode($dstdir),
529
+                                'filename' =>$props['filename'],
530
+                                'display_name' =>$props['filename']
531
+                            ),
532
+                        'entryid' => $actionData["entryid"],
533
+                        'parent_entryid' => $parentEntryid,
534
+                        'store_entryid' => $actionData["store_entryid"]
535
+                    );
536
+                }
537
+                $response['item'] = $folder;
538
+                $messageProps = $folder;
539
+            }
540
+        }
541
+
542
+        $this->addActionData("update", $response);
543
+        $GLOBALS["bus"]->addData($this->getResponseData());
544
+        return $messageProps;
545
+    }
546
+
547
+    /**
548
+     * Update the cache of renamed folder and it's sub folders.
549
+     *
550
+     * @param {String} $oldPath The $oldPath is path of folder before rename.
551
+     * @param {String} $newPath The $newPath is path of folder after rename.
552
+     * @param {String} $accountId The id of an account in which renamed folder is belongs.
553
+     */
554
+    function updateCacheAfterRename($oldPath, $newPath, $accountId)
555
+    {
556
+        // remove the trailing slash for the cache key
557
+        $cachePath = rtrim($oldPath, '/');
558
+        if ($cachePath === "") {
559
+            $cachePath = "/";
560
+        }
561
+
562
+        $dir = $this->getCache($accountId, $cachePath);
563
+        if ($dir) {
564
+            foreach ($dir as $id => $node) {
565
+                $newId = str_replace(dirname($id), $newPath, $id);
566
+                unset($dir[$id]);
567
+                $dir[$newId] = $node;
568
+
569
+                $type = FILES_FILE;
570
+
571
+                if (strcmp($node['resourcetype'], "collection") == 0) { // we have a folder
572
+                    $type = FILES_FOLDER;
573
+                }
574
+
575
+                if ($type === FILES_FOLDER) {
576
+                    $this->updateCacheAfterRename($id,  rtrim($newId, '/'), $accountId);
577
+                }
578
+            }
579
+            $this->deleteCache($accountId, $cachePath);
580
+            $this->setCache($accountId, $newPath, $dir);
581
+        }
582
+    }
583
+
584
+    /**
585
+     * Function used to notify the sub folder of selected/modified folder.
586
+     *
587
+     * @param {String} $folderID The $folderID of a folder which is modified.
588
+     */
589
+    function notifySubFolders($folderID)
590
+    {
591
+        $account = $this->accountFromNode($folderID);
592
+        $initializedBackend = $this->initializeBackend($account, true);
593
+        $folderData = $this->getSubFolders($folderID, $initializedBackend, true);
594
+
595
+        if (!empty($folderData)) {
596
+            $GLOBALS["bus"]->notify(REQUEST_ENTRYID, OBJECT_SAVE, $folderData);
597
+        }
598
+    }
599
+
600
+    /**
601
+     * Get the account id from a node id.
602
+     * @param {String} $nodeID Id of the file or folder to operate on
603
+     * @return {String} The account id extracted from $nodeId
604
+     */
605
+    function accountIDFromNode($nodeID)
606
+    {
607
+        return substr($nodeID, 3, (strpos($nodeID, '/') - 3)); // parse account id from node id
608
+    }
609
+
610
+    /**
611
+     * Get the account from a node id.
612
+     * @param {String} $nodeId ID of the file or folder to operate on
613
+     * @return {String} The account for $nodeId
614
+     */
615
+    function accountFromNode($nodeID)
616
+    {
617
+        return $this->accountStore->getAccount($this->accountIDFromNode($nodeID));
618
+    }
619
+
620
+    /**
621
+     * Create a key used to store data in the cache.
622
+     * @param {String} $accountID Id of the account of the data to cache
623
+     * @param {String} $path Path of the file or folder to create the cache element for
624
+     * @return {String} The created key
625
+     */
626
+    function makeCacheKey($accountID, $path)
627
+    {
628
+        return $this->uid . md5($accountID . $path);
629
+    }
630
+
631
+    /**
632
+     * Get version data form the cache.
633
+     *
634
+     * @param {String} $displayName display name of the backend or file plugin
635
+     * @param {String} $accountID Id of the account of the data to cache
636
+     * @return {String} version data or null if nothing was found
637
+     */
638
+    function getVersionFromCache($displayName, $accountID = '')
639
+    {
640
+        $key =  $this->uid . $accountID . $displayName;
641
+        return $this->cache->getItem($key)->get();
642
+    }
643
+
644
+    /**
645
+     * Set version data in the cache only when version data has been changed.
646
+     *
647
+     * @param {String} $displayName display name of the backend or file plugin
648
+     * @param {String} $version version info of backend or file plugin which needs to be cached
649
+     * @param {String} $accountID Id of the account of the data to cache
650
+     */
651
+    function setVersionInCache($displayName, $version, $accountID = '')
652
+    {
653
+        $olderVersionFromCache = $this->getVersionFromCache($displayName, $accountID);
654
+        // If version of files/backend is same then return.
655
+        if (version_compare($olderVersionFromCache,$version) === 0) {
656
+            return;
657
+        }
658
+
659
+        $key = $this->uid . $accountID . $displayName;
660
+        $this->cache->save($this->cache->getItem($key)->set($version));
661
+    }
662
+
663
+    /**
664
+     * Initialize the backend for the given account.
665
+     * @param {Object} $account The account object the backend should be initialized for
666
+     * @param {Bool} $setID Should the accountID be set in the backend object, or not. Defaults to false.
667
+     * @return {Object} The initialized backend
668
+     */
669
+    function initializeBackend($account, $setID = false)
670
+    {
671
+        $backend = $this->backendStore->getInstanceOfBackend($account->getBackend());
672
+        $backend->init_backend($account->getBackendConfig());
673
+        if($setID) {
674
+            $backend->setAccountID($account->getId());
675
+        }
676
+        $backend->open();
677
+        return $backend;
678
+    }
679
+
680
+    /**
681
+     * Save directory data in the cache.
682
+     * @param {String} $accountID Id of the account of the data to cache
683
+     * @param {String} $path Path of the file or folder to create the cache element for
684
+     * @param {String} $data Data to be cached
685
+     */
686
+    function setCache($accountID, $path, $data)
687
+    {
688
+        $key = $this->makeCacheKey($accountID, $path);
689
+        Logger::debug(self::LOG_CONTEXT, "Setting cache for node: " . $accountID . $path . " ## " . $key);
690
+        $this->cache->save($this->cache->getItem($key)->set($data));
691
+    }
692
+
693
+    /**
694
+     * Get directotry data form the cache.
695
+     * @param {String} $accountID Id of the account of the data to get
696
+     * @param {String} $path Path of the file or folder to retrieve the cache element for
697
+     * @return {String} The directory data or null if nothing was found
698
+     */
699
+    function getCache($accountID, $path)
700
+    {
701
+        $key = $this->makeCacheKey($accountID, $path);
702
+        Logger::debug(self::LOG_CONTEXT, "Getting cache for node: " . $accountID . $path . " ## " . $key);
703
+        return $this->cache->getItem($key)->get();
704
+    }
705
+
706
+    /**
707
+     * Remove data from the cache.
708
+     * @param {String} $accountID Id of the account to delete the cache for
709
+     * @param {String} $path Path of the file or folder to delete the cache element
710
+     */
711
+    function deleteCache($accountID, $path)
712
+    {
713
+        $key = $this->makeCacheKey($accountID, $path);
714
+        Logger::debug(self::LOG_CONTEXT, "Removing cache for node: " . $accountID .  $path . " ## " . $key);
715
+        $this->cache->deleteItem($key);
716
+    }
717
+
718
+    /**
719
+     * Function clear the cache.
720
+     */
721
+    function clearCache()
722
+    {
723
+        $this->cache->clear();
724
+    }
725
+
726
+    /**
727
+     * Function which returns MAPI Message Store Object. It
728
+     * searches in the variable $action for a storeid.
729
+     * @param array $action the XML data retrieved from the client
730
+     * @return object MAPI Message Store Object, false if storeid is not found in the $action variable
731
+     */
732
+    function getActionStore($action)
733
+    {
734
+        $store = false;
735
+
736
+        if(isset($action["store_entryid"]) && !empty($action["store_entryid"])) {
737
+            if(is_array($action["store_entryid"])) {
738
+                $store = array();
739
+                foreach($action["store_entryid"] as $store_id) {
740
+                    array_push($store, $store_id);
741
+                }
742
+            } else {
743
+                $store = $action["store_entryid"];
744
+            }
745
+        }
746
+
747
+        return $store;
748
+    }
749 749
 }
Please login to merge, or discard this patch.
Spacing   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -76,7 +76,7 @@  discard block
 block discarded – undo
76 76
 
77 77
 		// For backward compatibility we will check if the Encryption store exists. If not,
78 78
 		// we will fall back to the old way of retrieving the password from the session.
79
-		if ( class_exists('EncryptionStore') ) {
79
+		if (class_exists('EncryptionStore')) {
80 80
 			// Get the username from the Encryption store
81 81
 			$encryptionStore = \EncryptionStore::getInstance();
82 82
 			$this->uid = $encryptionStore->get('username');
@@ -101,11 +101,11 @@  discard block
 block discarded – undo
101 101
 	{
102 102
 		$data = array();
103 103
 		$data["item"] = array();
104
-		$versions =  $GLOBALS['PluginManager']->getPluginsVersion();
104
+		$versions = $GLOBALS['PluginManager']->getPluginsVersion();
105 105
 		$filesVersion = $versions['files'];
106 106
 
107 107
 		// Clear cache when version gets changed and update 'files' version in cache.
108
-		if ($isReload ||  version_compare($this->getVersionFromCache('files'), $filesVersion) !== 0) {
108
+		if ($isReload || version_compare($this->getVersionFromCache('files'), $filesVersion) !== 0) {
109 109
 			$this->clearCache();
110 110
 			$this->setVersionInCache('files', $filesVersion);
111 111
 		}
@@ -181,7 +181,7 @@  discard block
 block discarded – undo
181 181
 					'display_name' => "Files",
182 182
 				)
183 183
 			));
184
-			$nodes["folders"] = array( "item" => $subFolders);
184
+			$nodes["folders"] = array("item" => $subFolders);
185 185
 			array_push($data["item"], $nodes);
186 186
 		}
187 187
 
@@ -213,11 +213,11 @@  discard block
 block discarded – undo
213 213
 
214 214
 		$backendDisplayName = $backend->backendDisplayName;
215 215
 		$backendVersion = $backend->backendVersion;
216
-		$cacheVersion  = $this->getVersionFromCache($backendDisplayName, $accountID);
216
+		$cacheVersion = $this->getVersionFromCache($backendDisplayName, $accountID);
217 217
 		$dir = $this->getCache($accountID, $cachePath);
218 218
 
219 219
 		// Get new data from backend when cache is empty or the version of backend got changed.
220
-		if (is_null($dir) || version_compare($backendVersion,$cacheVersion) !== 0) {
220
+		if (is_null($dir) || version_compare($backendVersion, $cacheVersion) !== 0) {
221 221
 			$this->setVersionInCache($backendDisplayName, $backendVersion, $accountID);
222 222
 			$dir = $backend->ls($relNodeId);
223 223
 		}
@@ -251,7 +251,7 @@  discard block
 block discarded – undo
251 251
 
252 252
 					$entryid = $this->createId($realID);
253 253
 					$parentEntryid = $parentNode !== false && isset($parentNode['entryid']) ? $parentNode['entryid'] : $this->createId($nodeId);
254
-					$storeEntryid = $this->createId($nodeIdPrefix .'/');
254
+					$storeEntryid = $this->createId($nodeIdPrefix . '/');
255 255
 
256 256
 					$dir[$id]['entryid'] = $entryid;
257 257
 					$dir[$id]['parent_entryid'] = $parentEntryid;
@@ -370,13 +370,13 @@  discard block
 block discarded – undo
370 370
 				if ($errorCode === self::SMB_ERR_UNAUTHORIZED ||
371 371
 				$errorCode === self::SMB_ERR_FORBIDDEN ||
372 372
 				$errorCode === self::FTP_WD_OWNCLOUD_ERR_UNAUTHORIZED ||
373
-				$errorCode === self::FTP_WD_OWNCLOUD_ERR_FORBIDDEN||
373
+				$errorCode === self::FTP_WD_OWNCLOUD_ERR_FORBIDDEN ||
374 374
 				$errorCode === self::ALL_BACKEND_ERR_NOTFOUND) {
375 375
 
376 376
 					if ($errorCode === self::ALL_BACKEND_ERR_NOTFOUND) {
377
-						Logger::error(self::LOG_CONTEXT, '[hasSubFolder]: folder '. $id .' not found');
377
+						Logger::error(self::LOG_CONTEXT, '[hasSubFolder]: folder ' . $id . ' not found');
378 378
 					} else {
379
-						Logger::error(self::LOG_CONTEXT, '[hasSubFolder]: Access denied for folder '. $id);
379
+						Logger::error(self::LOG_CONTEXT, '[hasSubFolder]: Access denied for folder ' . $id);
380 380
 					}
381 381
 					return null;
382 382
 				}
@@ -410,7 +410,7 @@  discard block
 block discarded – undo
410 410
 			$path = isset($props['path']) && !empty($props['path']) ? $props['path'] : "/";
411 411
 
412 412
 			$relDirname = substr($path, strpos($path, '/'));
413
-			$relDirname = $relDirname . $props["display_name"] .'/';
413
+			$relDirname = $relDirname . $props["display_name"] . '/';
414 414
 			$account = $this->accountFromNode($path);
415 415
 
416 416
 			// initialize the backend
@@ -573,7 +573,7 @@  discard block
 block discarded – undo
573 573
 				}
574 574
 
575 575
 				if ($type === FILES_FOLDER) {
576
-					$this->updateCacheAfterRename($id,  rtrim($newId, '/'), $accountId);
576
+					$this->updateCacheAfterRename($id, rtrim($newId, '/'), $accountId);
577 577
 				}
578 578
 			}
579 579
 			$this->deleteCache($accountId, $cachePath);
@@ -637,7 +637,7 @@  discard block
 block discarded – undo
637 637
 	 */
638 638
 	function getVersionFromCache($displayName, $accountID = '')
639 639
 	{
640
-		$key =  $this->uid . $accountID . $displayName;
640
+		$key = $this->uid . $accountID . $displayName;
641 641
 		return $this->cache->getItem($key)->get();
642 642
 	}
643 643
 
@@ -652,7 +652,7 @@  discard block
 block discarded – undo
652 652
 	{
653 653
 		$olderVersionFromCache = $this->getVersionFromCache($displayName, $accountID);
654 654
 		// If version of files/backend is same then return.
655
-		if (version_compare($olderVersionFromCache,$version) === 0) {
655
+		if (version_compare($olderVersionFromCache, $version) === 0) {
656 656
 			return;
657 657
 		}
658 658
 
@@ -670,7 +670,7 @@  discard block
 block discarded – undo
670 670
 	{
671 671
 		$backend = $this->backendStore->getInstanceOfBackend($account->getBackend());
672 672
 		$backend->init_backend($account->getBackendConfig());
673
-		if($setID) {
673
+		if ($setID) {
674 674
 			$backend->setAccountID($account->getId());
675 675
 		}
676 676
 		$backend->open();
@@ -711,7 +711,7 @@  discard block
 block discarded – undo
711 711
 	function deleteCache($accountID, $path)
712 712
 	{
713 713
 		$key = $this->makeCacheKey($accountID, $path);
714
-		Logger::debug(self::LOG_CONTEXT, "Removing cache for node: " . $accountID .  $path . " ## " . $key);
714
+		Logger::debug(self::LOG_CONTEXT, "Removing cache for node: " . $accountID . $path . " ## " . $key);
715 715
 		$this->cache->deleteItem($key);
716 716
 	}
717 717
 
@@ -733,10 +733,10 @@  discard block
 block discarded – undo
733 733
 	{
734 734
 		$store = false;
735 735
 
736
-		if(isset($action["store_entryid"]) && !empty($action["store_entryid"])) {
737
-			if(is_array($action["store_entryid"])) {
736
+		if (isset($action["store_entryid"]) && !empty($action["store_entryid"])) {
737
+			if (is_array($action["store_entryid"])) {
738 738
 				$store = array();
739
-				foreach($action["store_entryid"] as $store_id) {
739
+				foreach ($action["store_entryid"] as $store_id) {
740 740
 					array_push($store, $store_id);
741 741
 				}
742 742
 			} else {
Please login to merge, or discard this patch.
plugins/files/php/modules/class.hierarchylistmodule.php 3 patches
Indentation   +203 added lines, -203 removed lines patch added patch discarded remove patch
@@ -9,207 +9,207 @@
 block discarded – undo
9 9
  */
10 10
 class HierarchyListModule extends FilesListModule
11 11
 {
12
-	/**
13
-	 * Creates the notifiers for this module,
14
-	 * and register them to the Bus.
15
-	 */
16
-	function createNotifiers()
17
-	{
18
-		$entryid = $this->getEntryID();
19
-		$GLOBALS["bus"]->registerNotifier('filesbrowsernotifier', $entryid);
20
-		$GLOBALS["bus"]->registerNotifier('fileshierarchynotifier', REQUEST_ENTRYID);
21
-	}
22
-
23
-	/**
24
-	 * @return bool|void
25
-	 */
26
-	function execute()
27
-	{
28
-		$result = false;
29
-		foreach ($this->data as $actionType => $actionData) {
30
-			if (isset($actionType)) {
31
-				try {
32
-					switch ($actionType) {
33
-						case "list":
34
-							$this->hierarchyList($actionData);
35
-							break;
36
-						case "updatelist":
37
-							$this->updateHierarchy($actionData);
38
-							break;
39
-						case "save":
40
-							$this->save($actionData);
41
-							break;
42
-						case "delete":
43
-							$result = $this->delete($actionData);
44
-							break;
45
-						default:
46
-							$this->handleUnknownActionType($actionType);
47
-					}
48
-				} catch (MAPIException $e) {
49
-					$this->sendFeedback(false, $this->errorDetailsFromException($e));
50
-				}
51
-				catch (AccountException $e) {
52
-					$this->sendFeedback(false, array(
53
-						'type' => ERROR_GENERAL,
54
-						'info' => array(
55
-							'title' => $e->getTitle(),
56
-							'original_message' => $e->getMessage(),
57
-							'display_message' => $e->getMessage()
58
-						)
59
-					));
60
-				} catch (BackendException $e) {
61
-					$this->sendFeedback(false, array(
62
-						'type' => ERROR_GENERAL,
63
-						'info' => array(
64
-							'title' => $e->getTitle(),
65
-							'original_message' => $e->getMessage(),
66
-							'display_message' => $e->getMessage(),
67
-							'code' => $e->getCode()
68
-						)
69
-					));
70
-				} catch (Exception $e) {
71
-					$this->sendFeedback(false, array(
72
-						'type' => ERROR_GENERAL,
73
-						'info' => array(
74
-							'title' => $e->getTitle(),
75
-							'original_message' => $e->getMessage(),
76
-							'display_message' => $e->getMessage(),
77
-							'code' => $e->getCode()
78
-						)
79
-					));
80
-				}
81
-			}
82
-		}
83
-
84
-		return $result;
85
-	}
86
-
87
-	/**
88
-	 * Generates the hierarchy list. All folders and sub folders are added to response data.
89
-	 */
90
-	function hierarchyList($action)
91
-	{
92
-		$isReload = isset($action['reload']) ? $action['reload'] : false;
93
-		$data = $this->getHierarchyList($isReload);
94
-		$this->addActionData("list", $data);
95
-		$GLOBALS["bus"]->addData($this->getResponseData());
96
-	}
97
-
98
-	/**
99
-	 * Function used to retrieve the child folders of given folder id.
100
-	 *
101
-	 * @param {Array} $action The action data which passed in request.
102
-	 */
103
-	function updateHierarchy($action)
104
-	{
105
-		$nodeId = $action["folder_id"];
106
-		$account = $this->accountFromNode($nodeId);
107
-		$backend = $this->initializeBackend($account,true);
108
-		$subFolders = $this->getSubFolders($nodeId, $backend);
109
-
110
-		$this->addActionData("updatelist", array("item"=>$subFolders));
111
-		$GLOBALS["bus"]->addData($this->getResponseData());
112
-	}
113
-
114
-	/**
115
-	 * @param $actionData
116
-	 * @return array|void
117
-	 * @throws \Files\Backend\Exception
118
-	 */
119
-	function save($actionData)
120
-	{
121
-		$messageProps = parent::save($actionData);
122
-		if(!empty($messageProps)) {
123
-			// Notify all subfolders for update folder.
124
-			$this->notifySubFolders($messageProps["props"]["folder_id"]);
125
-
126
-			// Need to add message class to update the files grid record through notification
127
-			$messageProps["props"]["message_class"] = "IPM.Files";
128
-			$GLOBALS["bus"]->notify($messageProps["parent_entryid"], OBJECT_SAVE, $messageProps);
129
-		}
130
-	}
131
-
132
-	/**
133
-	 * Deletes the selected files on the backend server
134
-	 *
135
-	 * @access private
136
-	 * @param string $actionType name of the current action
137
-	 * @param array $actionData all parameters contained in this request
138
-	 * @return bool
139
-	 * @throws BackendException if the backend request fails
140
-	 */
141
-	function delete($actionData)
142
-	{
143
-		// TODO: Do we need this if block code?
144
-		if (isset($actionData['records']) && is_array($actionData['records'])) {
145
-			foreach ($actionData['records'] as $record) {
146
-				$nodeId = $record['entryid'];
147
-				$relNodeId = substr($nodeId, strpos($nodeId, '/'));
148
-
149
-				$account = $this->accountFromNode($nodeId);
150
-
151
-				// initialize the backend
152
-				$initializedBackend = $this->initializeBackend($account);
153
-
154
-				$initializedBackend->delete($relNodeId);
155
-				//Logger::debug(self::LOG_CONTEXT, "deleted: " . $nodeId . ", worked: " . $result);
156
-
157
-				// clear the cache
158
-				$this->deleteCache($account->getId(), dirname($relNodeId));
159
-
160
-				$GLOBALS["bus"]->notify($record["parent_entryid"], OBJECT_DELETE, array(
161
-					"id"=> $nodeId,
162
-					"entryid"=> $nodeId,
163
-					"parent_entryid"=> $record["parent_entryid"],
164
-					"store_entryid"=> $record["store_entryid"]
165
-				));
166
-			}
167
-
168
-			$this->sendFeedback(true);
169
-		} else {
170
-			$nodeId = $actionData['folder_id'];
171
-			$relNodeId = substr($nodeId, strpos($nodeId, '/'));
172
-
173
-			$account = $this->accountFromNode($nodeId);
174
-			$accountId = $account->getId();
175
-
176
-			// initialize the backend
177
-			$initializedBackend = $this->initializeBackend($account);
178
-
179
-			try {
180
-				$initializedBackend->delete($relNodeId);
181
-			} catch (\Files\Backend\Exception $e) {
182
-				// TODO: this might fails because the file was already deleted.
183
-				// fire error message if any other error occurred.
184
-				//Logger::debug(self::LOG_CONTEXT, "deleted a directory that was no longer available");
185
-			}
186
-
187
-			// Get old cached data.
188
-			$cachedDir = $this->getCache($accountId, dirname($relNodeId));
189
-
190
-			if (isset($cachedDir[$relNodeId]) && !empty($cachedDir[$relNodeId])) {
191
-				// Delete the folder from cached data.
192
-				unset($cachedDir[$relNodeId]);
193
-			}
194
-
195
-			// clear the cache of parent directory.
196
-			$this->deleteCache($accountId, dirname($relNodeId));
197
-			// clear the cache of selected directory.
198
-			$this->deleteCache($accountId, rtrim($relNodeId, '/'));
199
-
200
-			// Set data in cache.
201
-			$this->setCache($accountId, dirname($relNodeId), $cachedDir);
202
-
203
-			$this->sendFeedback(true);
204
-			$GLOBALS["bus"]->notify($actionData["parent_entryid"], OBJECT_DELETE, array(
205
-				"id"=> $actionData["entryid"],
206
-				"folder_id"=> $nodeId,
207
-				"entryid"=> $actionData["entryid"],
208
-				"parent_entryid"=> $actionData["parent_entryid"],
209
-				"store_entryid"=> $actionData["store_entryid"]
210
-			));
211
-		}
212
-
213
-		return true;
214
-	}
12
+    /**
13
+     * Creates the notifiers for this module,
14
+     * and register them to the Bus.
15
+     */
16
+    function createNotifiers()
17
+    {
18
+        $entryid = $this->getEntryID();
19
+        $GLOBALS["bus"]->registerNotifier('filesbrowsernotifier', $entryid);
20
+        $GLOBALS["bus"]->registerNotifier('fileshierarchynotifier', REQUEST_ENTRYID);
21
+    }
22
+
23
+    /**
24
+     * @return bool|void
25
+     */
26
+    function execute()
27
+    {
28
+        $result = false;
29
+        foreach ($this->data as $actionType => $actionData) {
30
+            if (isset($actionType)) {
31
+                try {
32
+                    switch ($actionType) {
33
+                        case "list":
34
+                            $this->hierarchyList($actionData);
35
+                            break;
36
+                        case "updatelist":
37
+                            $this->updateHierarchy($actionData);
38
+                            break;
39
+                        case "save":
40
+                            $this->save($actionData);
41
+                            break;
42
+                        case "delete":
43
+                            $result = $this->delete($actionData);
44
+                            break;
45
+                        default:
46
+                            $this->handleUnknownActionType($actionType);
47
+                    }
48
+                } catch (MAPIException $e) {
49
+                    $this->sendFeedback(false, $this->errorDetailsFromException($e));
50
+                }
51
+                catch (AccountException $e) {
52
+                    $this->sendFeedback(false, array(
53
+                        'type' => ERROR_GENERAL,
54
+                        'info' => array(
55
+                            'title' => $e->getTitle(),
56
+                            'original_message' => $e->getMessage(),
57
+                            'display_message' => $e->getMessage()
58
+                        )
59
+                    ));
60
+                } catch (BackendException $e) {
61
+                    $this->sendFeedback(false, array(
62
+                        'type' => ERROR_GENERAL,
63
+                        'info' => array(
64
+                            'title' => $e->getTitle(),
65
+                            'original_message' => $e->getMessage(),
66
+                            'display_message' => $e->getMessage(),
67
+                            'code' => $e->getCode()
68
+                        )
69
+                    ));
70
+                } catch (Exception $e) {
71
+                    $this->sendFeedback(false, array(
72
+                        'type' => ERROR_GENERAL,
73
+                        'info' => array(
74
+                            'title' => $e->getTitle(),
75
+                            'original_message' => $e->getMessage(),
76
+                            'display_message' => $e->getMessage(),
77
+                            'code' => $e->getCode()
78
+                        )
79
+                    ));
80
+                }
81
+            }
82
+        }
83
+
84
+        return $result;
85
+    }
86
+
87
+    /**
88
+     * Generates the hierarchy list. All folders and sub folders are added to response data.
89
+     */
90
+    function hierarchyList($action)
91
+    {
92
+        $isReload = isset($action['reload']) ? $action['reload'] : false;
93
+        $data = $this->getHierarchyList($isReload);
94
+        $this->addActionData("list", $data);
95
+        $GLOBALS["bus"]->addData($this->getResponseData());
96
+    }
97
+
98
+    /**
99
+     * Function used to retrieve the child folders of given folder id.
100
+     *
101
+     * @param {Array} $action The action data which passed in request.
102
+     */
103
+    function updateHierarchy($action)
104
+    {
105
+        $nodeId = $action["folder_id"];
106
+        $account = $this->accountFromNode($nodeId);
107
+        $backend = $this->initializeBackend($account,true);
108
+        $subFolders = $this->getSubFolders($nodeId, $backend);
109
+
110
+        $this->addActionData("updatelist", array("item"=>$subFolders));
111
+        $GLOBALS["bus"]->addData($this->getResponseData());
112
+    }
113
+
114
+    /**
115
+     * @param $actionData
116
+     * @return array|void
117
+     * @throws \Files\Backend\Exception
118
+     */
119
+    function save($actionData)
120
+    {
121
+        $messageProps = parent::save($actionData);
122
+        if(!empty($messageProps)) {
123
+            // Notify all subfolders for update folder.
124
+            $this->notifySubFolders($messageProps["props"]["folder_id"]);
125
+
126
+            // Need to add message class to update the files grid record through notification
127
+            $messageProps["props"]["message_class"] = "IPM.Files";
128
+            $GLOBALS["bus"]->notify($messageProps["parent_entryid"], OBJECT_SAVE, $messageProps);
129
+        }
130
+    }
131
+
132
+    /**
133
+     * Deletes the selected files on the backend server
134
+     *
135
+     * @access private
136
+     * @param string $actionType name of the current action
137
+     * @param array $actionData all parameters contained in this request
138
+     * @return bool
139
+     * @throws BackendException if the backend request fails
140
+     */
141
+    function delete($actionData)
142
+    {
143
+        // TODO: Do we need this if block code?
144
+        if (isset($actionData['records']) && is_array($actionData['records'])) {
145
+            foreach ($actionData['records'] as $record) {
146
+                $nodeId = $record['entryid'];
147
+                $relNodeId = substr($nodeId, strpos($nodeId, '/'));
148
+
149
+                $account = $this->accountFromNode($nodeId);
150
+
151
+                // initialize the backend
152
+                $initializedBackend = $this->initializeBackend($account);
153
+
154
+                $initializedBackend->delete($relNodeId);
155
+                //Logger::debug(self::LOG_CONTEXT, "deleted: " . $nodeId . ", worked: " . $result);
156
+
157
+                // clear the cache
158
+                $this->deleteCache($account->getId(), dirname($relNodeId));
159
+
160
+                $GLOBALS["bus"]->notify($record["parent_entryid"], OBJECT_DELETE, array(
161
+                    "id"=> $nodeId,
162
+                    "entryid"=> $nodeId,
163
+                    "parent_entryid"=> $record["parent_entryid"],
164
+                    "store_entryid"=> $record["store_entryid"]
165
+                ));
166
+            }
167
+
168
+            $this->sendFeedback(true);
169
+        } else {
170
+            $nodeId = $actionData['folder_id'];
171
+            $relNodeId = substr($nodeId, strpos($nodeId, '/'));
172
+
173
+            $account = $this->accountFromNode($nodeId);
174
+            $accountId = $account->getId();
175
+
176
+            // initialize the backend
177
+            $initializedBackend = $this->initializeBackend($account);
178
+
179
+            try {
180
+                $initializedBackend->delete($relNodeId);
181
+            } catch (\Files\Backend\Exception $e) {
182
+                // TODO: this might fails because the file was already deleted.
183
+                // fire error message if any other error occurred.
184
+                //Logger::debug(self::LOG_CONTEXT, "deleted a directory that was no longer available");
185
+            }
186
+
187
+            // Get old cached data.
188
+            $cachedDir = $this->getCache($accountId, dirname($relNodeId));
189
+
190
+            if (isset($cachedDir[$relNodeId]) && !empty($cachedDir[$relNodeId])) {
191
+                // Delete the folder from cached data.
192
+                unset($cachedDir[$relNodeId]);
193
+            }
194
+
195
+            // clear the cache of parent directory.
196
+            $this->deleteCache($accountId, dirname($relNodeId));
197
+            // clear the cache of selected directory.
198
+            $this->deleteCache($accountId, rtrim($relNodeId, '/'));
199
+
200
+            // Set data in cache.
201
+            $this->setCache($accountId, dirname($relNodeId), $cachedDir);
202
+
203
+            $this->sendFeedback(true);
204
+            $GLOBALS["bus"]->notify($actionData["parent_entryid"], OBJECT_DELETE, array(
205
+                "id"=> $actionData["entryid"],
206
+                "folder_id"=> $nodeId,
207
+                "entryid"=> $actionData["entryid"],
208
+                "parent_entryid"=> $actionData["parent_entryid"],
209
+                "store_entryid"=> $actionData["store_entryid"]
210
+            ));
211
+        }
212
+
213
+        return true;
214
+    }
215 215
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -104,7 +104,7 @@  discard block
 block discarded – undo
104 104
 	{
105 105
 		$nodeId = $action["folder_id"];
106 106
 		$account = $this->accountFromNode($nodeId);
107
-		$backend = $this->initializeBackend($account,true);
107
+		$backend = $this->initializeBackend($account, true);
108 108
 		$subFolders = $this->getSubFolders($nodeId, $backend);
109 109
 
110 110
 		$this->addActionData("updatelist", array("item"=>$subFolders));
@@ -119,7 +119,7 @@  discard block
 block discarded – undo
119 119
 	function save($actionData)
120 120
 	{
121 121
 		$messageProps = parent::save($actionData);
122
-		if(!empty($messageProps)) {
122
+		if (!empty($messageProps)) {
123 123
 			// Notify all subfolders for update folder.
124 124
 			$this->notifySubFolders($messageProps["props"]["folder_id"]);
125 125
 
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -47,8 +47,7 @@
 block discarded – undo
47 47
 					}
48 48
 				} catch (MAPIException $e) {
49 49
 					$this->sendFeedback(false, $this->errorDetailsFromException($e));
50
-				}
51
-				catch (AccountException $e) {
50
+				} catch (AccountException $e) {
52 51
 					$this->sendFeedback(false, array(
53 52
 						'type' => ERROR_GENERAL,
54 53
 						'info' => array(
Please login to merge, or discard this patch.
plugins/files/php/class.filesaccountmodule.php 2 patches
Indentation   +450 added lines, -450 removed lines patch added patch discarded remove patch
@@ -17,454 +17,454 @@
 block discarded – undo
17 17
 
18 18
 class FilesAccountModule extends ListModule
19 19
 {
20
-	const LOG_CONTEXT = "FilesAccountModule"; // Context for the Logger
21
-
22
-	/**
23
-	 * @constructor
24
-	 *
25
-	 * @param $id
26
-	 * @param $data
27
-	 */
28
-	public function __construct($id, $data)
29
-	{
30
-		parent::__construct($id, $data);
31
-	}
32
-
33
-	/**
34
-	 * Executes all the actions in the $data variable.
35
-	 * Exception part is used for authentication errors also
36
-	 * @return boolean true on success or false on failure.
37
-	 */
38
-	public function execute()
39
-	{
40
-		$result = false;
41
-
42
-		foreach ($this->data as $actionType => $actionData) {
43
-			if (isset($actionType)) {
44
-				try {
45
-					switch ($actionType) {
46
-						case "save":
47
-							// check if we should create a new account or edit an existing one
48
-							if (isset($actionData["entryid"])) {
49
-								$result = $this->accountUpdate($actionData);
50
-							} else {
51
-								$result = $this->accountCreate($actionData);
52
-							}
53
-							break;
54
-						case "delete":
55
-							$result = $this->accountDelete($actionType, $actionData);
56
-							break;
57
-						case "list":
58
-							if(isset($actionData["list_backend"]) && $actionData["list_backend"]) {
59
-								$result = $this->backendInformation($actionType);
60
-							} else {
61
-								$result = $this->accountList($actionType, $actionData);
62
-							}
63
-							break;
64
-						case "getquota":
65
-							$result = $this->getQuotaInformation($actionType, $actionData);
66
-							break;
67
-						case "getversion":
68
-							$result = $this->getVersionInformation($actionType, $actionData);
69
-							break;
70
-						case "updatetoken":
71
-							$result = $this->updateOauthToken($actionType, $actionData);
72
-							break;
73
-						default:
74
-							$this->handleUnknownActionType($actionType);
75
-					}
76
-
77
-				} catch (MAPIException $e) {
78
-					$this->sendFeedback(false, $this->errorDetailsFromException($e));
79
-				} catch (AccountException $e) {
80
-					$this->sendFeedback(false, array(
81
-						'type' => ERROR_GENERAL,
82
-						'info' => array(
83
-							'title' => $e->getTitle(),
84
-							'original_message' => $e->getMessage(),
85
-							'display_message' => $e->getMessage()
86
-						)
87
-					));
88
-				} catch (BackendException $e) {
89
-					$this->sendFeedback(false, array(
90
-						'type' => ERROR_GENERAL,
91
-						'info' => array(
92
-							'title' => $e->getTitle(),
93
-							'original_message' => $e->getMessage(),
94
-							'display_message' => $e->getMessage()
95
-						)
96
-					));
97
-				}
98
-			}
99
-		}
100
-
101
-		return $result;
102
-	}
103
-
104
-	/**
105
-	 * @param {Array} $actionData
106
-	 */
107
-	public function accountCreate($actionData)
108
-	{
109
-		$response = array();
110
-		$requestProperties = $actionData["props"];
111
-
112
-		// create a new account in our backend
113
-		$accountStore = new \Files\Core\AccountStore();
114
-		$newAccount = $accountStore->createAccount($requestProperties["name"], $requestProperties["backend"], $requestProperties["backend_config"]);
115
-
116
-		// create the response account object
117
-		$account = array();
118
-		$account[$newAccount->getId()] = array(
119
-			'props' =>
120
-				array(
121
-					'id' => $newAccount->getId(),
122
-					'status' => $newAccount->getStatus(),
123
-					'status_description' => $newAccount->getStatusDescription(),
124
-					'name' => $newAccount->getName(),
125
-					'backend' => $newAccount->getBackend(),
126
-					'backend_config' => $newAccount->getBackendConfig(),
127
-					'backend_features' => $newAccount->getFeatures(),
128
-					'account_sequence' => $newAccount->getSequence()
129
-				),
130
-			'entryid' => $newAccount->getId(),
131
-			'store_entryid' => 'filesaccount',
132
-			'parent_entryid' => 'accountstoreroot'
133
-		);
134
-		$response['item'] = array_values($account);
135
-
136
-		$this->addActionData("update", $response);
137
-		$GLOBALS["bus"]->addData($this->getResponseData());
138
-
139
-		return true;
140
-	}
141
-
142
-	/**
143
-	 * remove an account from the store and the MAPI settings
144
-	 *
145
-	 * @param {String} $actionType
146
-	 * @param {Array} $actionData
147
-	 */
148
-	public function accountDelete($actionType, $actionData)
149
-	{
150
-		$response = array();
151
-
152
-		// check if account needs to clean things up before it gets deleted
153
-		try {
154
-			$accountStore = new \Files\Core\AccountStore();
155
-			$accountStore->getAccount($actionData['entryid'])->beforeDelete();
156
-		} catch (\Files\Backend\Exception $e) {
157
-			// ignore errors here
158
-		}
159
-
160
-		$response['status'] = $accountStore->deleteAccount($actionData['entryid']);
161
-
162
-		$this->addActionData($actionType, $response);
163
-		$GLOBALS["bus"]->addData($this->getResponseData());
164
-
165
-		return $response['status'];
166
-	}
167
-
168
-	/**
169
-	 * loads content of current folder - list of folders and files from the Files backend
170
-	 *
171
-	 * @param {String} $actionType
172
-	 * @param {Array} $actionData
173
-	 */
174
-	public function accountList($actionType, $actionData)
175
-	{
176
-		$response = array();
177
-
178
-		// get a list of all accounts
179
-		$accountStore = new \Files\Core\AccountStore();
180
-		$accounts = $accountStore->getAllAccounts();
181
-		$accountList = array();
182
-
183
-		if (is_array($accounts)) {
184
-			foreach ($accounts as $account) {
185
-				$account = $accountStore->updateAccount($account);
186
-				$accountList[$account->getId()] = array(
187
-					"props" => array(
188
-						"id" => $account->getId(),
189
-						"name" => $account->getName(),
190
-						"type" => "account", // to prevent warning while sorting
191
-						"status" => $account->getStatus(),
192
-						"status_description" => $account->getStatusDescription(),
193
-						"backend" => $account->getBackend(),
194
-						"backend_config" => $account->getBackendConfig(),
195
-						'backend_features' => $account->getFeatures(),
196
-						'account_sequence' => $account->getSequence(),
197
-						'cannot_change' => $account->getCannotChangeFlag()
198
-					),
199
-					'entryid' => $account->getId(),
200
-					'store_entryid' => 'filesaccount',
201
-					'parent_entryid' => 'accountstoreroot'
202
-				);
203
-			}
204
-		}
205
-
206
-		// sort the accounts
207
-		$sortKey = "account_sequence";
208
-		$sortDir = "ASC";
209
-
210
-		if (isset($data['sort'])) {
211
-			$sortKey = $data['sort'][0]['field'];
212
-			$sortDir = $data['sort'][0]['direction'];
213
-		}
214
-
215
-		Logger::debug(self::LOG_CONTEXT, "Sorting by " . $sortKey . " in direction: " . $sortDir);
216
-
217
-		$accountList = ArrayUtil::sort_props_by_key($accountList, $sortKey, $sortDir);
218
-
219
-		$response["item"] = array_values($accountList);
220
-		$response['page'] = array("start" => 0, "rowcount" => 50, "totalrowcount" => count($response["item"]));
221
-		$response['folder'] = array("content_count" => count($response["item"]), "content_unread" => 0);
222
-
223
-		$this->addActionData($actionType, $response);
224
-		$GLOBALS["bus"]->addData($this->getResponseData());
225
-
226
-		return true;
227
-	}
228
-
229
-	/**
230
-	 * update some values of an account
231
-	 *
232
-	 * @param {Array} $actionData
233
-	 */
234
-	public function accountUpdate($actionData)
235
-	{
236
-		$response = array();
237
-
238
-		// create a new account in our backend
239
-		$accountStore = new \Files\Core\AccountStore();
240
-		$currentAccount = $accountStore->getAccount($actionData['entryid']);
241
-
242
-		// apply changes to the account object
243
-		if (isset($actionData['props']['name'])) {
244
-			$currentAccount->setName(strip_tags($actionData['props']['name']));
245
-		}
246
-		if (isset($actionData['props']['backend'])) {
247
-			$currentAccount->setBackend(strip_tags($actionData['props']['backend']));
248
-		}
249
-		if (isset($actionData['props']['backend_config'])) { // we always get the whole backend config
250
-			$currentAccount->setBackendConfig($actionData['props']['backend_config']);
251
-		}
252
-		if (isset($actionData['props']['account_sequence'])) {
253
-			$currentAccount->setSequence($actionData['props']['account_sequence']);
254
-		}
255
-
256
-		// save changes
257
-		$accountStore->updateAccount($currentAccount);
258
-
259
-		// create the response object
260
-		$updatedAccount = array();
261
-		$updatedAccount[$currentAccount->getId()] = array(
262
-			"props" => array(
263
-				"id" => $currentAccount->getId(),
264
-				"name" => $currentAccount->getName(),
265
-				"status" => $currentAccount->getStatus(),
266
-				"status_description" => $currentAccount->getStatusDescription(),
267
-				"backend" => $currentAccount->getBackend(),
268
-				"backend_config" => $currentAccount->getBackendConfig(),
269
-				'backend_features' => $currentAccount->getFeatures(),
270
-				'account_sequence' => $currentAccount->getSequence()
271
-			),
272
-			'entryid' => $currentAccount->getId(),
273
-			'store_entryid' => 'filesaccount',
274
-			'parent_entryid' => 'accountstoreroot'
275
-		);
276
-
277
-		$response['item'] = array_values($updatedAccount);
278
-		$this->addActionData("update", $response);
279
-		$GLOBALS["bus"]->addData($this->getResponseData());
280
-
281
-		return true;
282
-	}
283
-
284
-	/**
285
-	 * Return all Information about the existing backends.
286
-	 *
287
-	 * @param {String} $actionType
288
-	 */
289
-	public function backendInformation($actionType)
290
-	{
291
-		// find all registered backends
292
-		$backendStore = \Files\Backend\BackendStore::getInstance();
293
-		$backendNames = $backendStore->getRegisteredBackendNames();
294
-
295
-		$data = array();
296
-		$items = array();
297
-		foreach ($backendNames as $backendName) {
298
-			$backendInstance = $backendStore->getInstanceOfBackend($backendName);
299
-			if ($backendInstance !== FALSE) {
300
-				array_push($items, array('props' => array(
301
-					"name" => $backendName,
302
-					"message_class" => "IPM.FilesBackend",
303
-					"displayName" => $backendInstance->getDisplayName()
304
-				)));
305
-			}
306
-		}
307
-
308
-		$data = array_merge($data, array('item' => $items));
309
-
310
-		$this->addActionData($actionType, $data);
311
-		$GLOBALS["bus"]->addData($this->getResponseData());
312
-		return true;
313
-	}
314
-
315
-	/**
316
-	 * Return all quota information from specified account.
317
-	 *
318
-	 * @param {String} $actionType
319
-	 * @param {String} $actionData
320
-	 */
321
-	public function getQuotaInformation($actionType, $actionData)
322
-	{
323
-		$response = array();
324
-
325
-		$accountId = $actionData["accountId"];
326
-		$rootPath = $actionData["folder"];
327
-
328
-		// load the accountstore
329
-		$accountStore = new \Files\Core\AccountStore();
330
-		$currentAccount = $accountStore->getAccount($accountId);
331
-
332
-		// check if ID was valid, if not respond with error.
333
-		if ($currentAccount === NULL || $currentAccount === FALSE) {
334
-			throw new AccountException(_("Unknown account ID"));
335
-		}
336
-
337
-		$backendStore = \Files\Backend\BackendStore::getInstance();
338
-		$backendInstance = $backendStore->getInstanceOfBackend($currentAccount->getBackend());
339
-
340
-		// check if backend really supports this feature
341
-		if (!$backendInstance->supports(\Files\Backend\BackendStore::FEATURE_QUOTA)) {
342
-			throw new AccountException(_('Feature "Quota Information" is not supported by this backend!'));
343
-		}
344
-
345
-		// init backend instance
346
-		$backendInstance->init_backend($currentAccount->getBackendConfig());
347
-
348
-		// get quota info
349
-		$backendInstance->open();
350
-		$qUsed = $backendInstance->getQuotaBytesUsed($rootPath);
351
-		$qAvailable = $backendInstance->getQuotaBytesAvailable($rootPath);
352
-
353
-		$response['status'] = true;
354
-		$response['quota'] = array(
355
-			array("state" => _('Used'), "amount" => $qUsed),
356
-			array("state" => _('Free'), "amount" => $qAvailable)
357
-		);
358
-
359
-		$this->addActionData($actionType, $response);
360
-		$GLOBALS["bus"]->addData($this->getResponseData());
361
-
362
-		return $response['status'];
363
-	}
364
-
365
-	/**
366
-	 * Return all quota information from specified account.
367
-	 *
368
-	 * @param {String} $actionType
369
-	 * @param {String} $actionData
370
-	 */
371
-	public function getVersionInformation($actionType, $actionData)
372
-	{
373
-		$response = array();
374
-
375
-		$accountId = $actionData["accountId"];
376
-
377
-		// load the accountstore
378
-		$accountStore = new \Files\Core\AccountStore();
379
-		$currentAccount = $accountStore->getAccount($accountId);
380
-
381
-		// check if ID was valid, if not respond with error.
382
-		if ($currentAccount === NULL || $currentAccount === FALSE) {
383
-			throw new AccountException(_("Unknown account ID"));
384
-		}
385
-
386
-		$backendStore = \Files\Backend\BackendStore::getInstance();
387
-		$backendInstance = $backendStore->getInstanceOfBackend($currentAccount->getBackend());
388
-
389
-		// check if backend really supports this feature
390
-		if (!$backendInstance->supports(\Files\Backend\BackendStore::FEATURE_VERSION)) {
391
-			throw new AccountException(_('Feature "Version Information" is not supported by this backend!'));
392
-		}
393
-
394
-		// init backend instance
395
-		$backendInstance->init_backend($currentAccount->getBackendConfig());
396
-
397
-		// get quota info
398
-		$backendInstance->open();
399
-		$serverVersion = $backendInstance->getServerVersion();
400
-		$backendVersion = $backendInstance->getBackendVersion();
401
-
402
-		$response['status'] = true;
403
-		$response['version'] = array(
404
-			"backend" => $backendVersion,
405
-			"server" => $serverVersion
406
-		);
407
-
408
-		$this->addActionData($actionType, $response);
409
-		$GLOBALS["bus"]->addData($this->getResponseData());
410
-
411
-		return $response['status'];
412
-	}
413
-
414
-	/**
415
-	 * Return all quota information from specified account.
416
-	 *
417
-	 * @param {String} $actionType
418
-	 * @param {String} $actionData
419
-	 */
420
-	public function updateOauthToken($actionType, $actionData)
421
-	{
422
-		$response = array();
423
-
424
-		$accountId = $actionData["accountId"];
425
-
426
-		// load the accountstore
427
-		$accountStore = new \Files\Core\AccountStore();
428
-		$currentAccount = $accountStore->getAccount($accountId);
429
-
430
-		// check if ID was valid, if not respond with error.
431
-		if ($currentAccount === NULL || $currentAccount === FALSE) {
432
-			throw new AccountException(_("Unknown account ID"));
433
-		}
434
-
435
-		$backendStore = \Files\Backend\BackendStore::getInstance();
436
-		$backendInstance = $backendStore->getInstanceOfBackend($currentAccount->getBackend());
437
-
438
-		// check if backend really supports this feature
439
-		if (!$backendInstance->supports(\Files\Backend\BackendStore::FEATURE_OAUTH)) {
440
-			throw new AccountException(_('Feature "OAUTH" is not supported by this backend!'));
441
-		}
442
-
443
-		// init backend instance
444
-		$backendInstance->init_backend($currentAccount->getBackendConfig());
445
-		$backendInstance->changeAccessToken($actionData["access_token"]);
446
-
447
-		$response['status'] = true;
448
-		$response['access_token'] = $actionData["access_token"];
449
-
450
-		$this->addActionData($actionType, $response);
451
-		$GLOBALS["bus"]->addData($this->getResponseData());
452
-
453
-		return $response['status'];
454
-	}
455
-
456
-	/**
457
-	 * Function will retrieve error details from exception object based on exception type.
458
-	 * it should also send type of exception with the data. so client can know which type
459
-	 * of exception is generated.
460
-	 *
461
-	 * @param Object $exception the exception object which is generated.
462
-	 *
463
-	 * @return Array error data
464
-	 * @overwrite
465
-	 */
466
-	function errorDetailsFromException($exception)
467
-	{
468
-		parent::errorDetailsFromException($exception);
469
-	}
20
+    const LOG_CONTEXT = "FilesAccountModule"; // Context for the Logger
21
+
22
+    /**
23
+     * @constructor
24
+     *
25
+     * @param $id
26
+     * @param $data
27
+     */
28
+    public function __construct($id, $data)
29
+    {
30
+        parent::__construct($id, $data);
31
+    }
32
+
33
+    /**
34
+     * Executes all the actions in the $data variable.
35
+     * Exception part is used for authentication errors also
36
+     * @return boolean true on success or false on failure.
37
+     */
38
+    public function execute()
39
+    {
40
+        $result = false;
41
+
42
+        foreach ($this->data as $actionType => $actionData) {
43
+            if (isset($actionType)) {
44
+                try {
45
+                    switch ($actionType) {
46
+                        case "save":
47
+                            // check if we should create a new account or edit an existing one
48
+                            if (isset($actionData["entryid"])) {
49
+                                $result = $this->accountUpdate($actionData);
50
+                            } else {
51
+                                $result = $this->accountCreate($actionData);
52
+                            }
53
+                            break;
54
+                        case "delete":
55
+                            $result = $this->accountDelete($actionType, $actionData);
56
+                            break;
57
+                        case "list":
58
+                            if(isset($actionData["list_backend"]) && $actionData["list_backend"]) {
59
+                                $result = $this->backendInformation($actionType);
60
+                            } else {
61
+                                $result = $this->accountList($actionType, $actionData);
62
+                            }
63
+                            break;
64
+                        case "getquota":
65
+                            $result = $this->getQuotaInformation($actionType, $actionData);
66
+                            break;
67
+                        case "getversion":
68
+                            $result = $this->getVersionInformation($actionType, $actionData);
69
+                            break;
70
+                        case "updatetoken":
71
+                            $result = $this->updateOauthToken($actionType, $actionData);
72
+                            break;
73
+                        default:
74
+                            $this->handleUnknownActionType($actionType);
75
+                    }
76
+
77
+                } catch (MAPIException $e) {
78
+                    $this->sendFeedback(false, $this->errorDetailsFromException($e));
79
+                } catch (AccountException $e) {
80
+                    $this->sendFeedback(false, array(
81
+                        'type' => ERROR_GENERAL,
82
+                        'info' => array(
83
+                            'title' => $e->getTitle(),
84
+                            'original_message' => $e->getMessage(),
85
+                            'display_message' => $e->getMessage()
86
+                        )
87
+                    ));
88
+                } catch (BackendException $e) {
89
+                    $this->sendFeedback(false, array(
90
+                        'type' => ERROR_GENERAL,
91
+                        'info' => array(
92
+                            'title' => $e->getTitle(),
93
+                            'original_message' => $e->getMessage(),
94
+                            'display_message' => $e->getMessage()
95
+                        )
96
+                    ));
97
+                }
98
+            }
99
+        }
100
+
101
+        return $result;
102
+    }
103
+
104
+    /**
105
+     * @param {Array} $actionData
106
+     */
107
+    public function accountCreate($actionData)
108
+    {
109
+        $response = array();
110
+        $requestProperties = $actionData["props"];
111
+
112
+        // create a new account in our backend
113
+        $accountStore = new \Files\Core\AccountStore();
114
+        $newAccount = $accountStore->createAccount($requestProperties["name"], $requestProperties["backend"], $requestProperties["backend_config"]);
115
+
116
+        // create the response account object
117
+        $account = array();
118
+        $account[$newAccount->getId()] = array(
119
+            'props' =>
120
+                array(
121
+                    'id' => $newAccount->getId(),
122
+                    'status' => $newAccount->getStatus(),
123
+                    'status_description' => $newAccount->getStatusDescription(),
124
+                    'name' => $newAccount->getName(),
125
+                    'backend' => $newAccount->getBackend(),
126
+                    'backend_config' => $newAccount->getBackendConfig(),
127
+                    'backend_features' => $newAccount->getFeatures(),
128
+                    'account_sequence' => $newAccount->getSequence()
129
+                ),
130
+            'entryid' => $newAccount->getId(),
131
+            'store_entryid' => 'filesaccount',
132
+            'parent_entryid' => 'accountstoreroot'
133
+        );
134
+        $response['item'] = array_values($account);
135
+
136
+        $this->addActionData("update", $response);
137
+        $GLOBALS["bus"]->addData($this->getResponseData());
138
+
139
+        return true;
140
+    }
141
+
142
+    /**
143
+     * remove an account from the store and the MAPI settings
144
+     *
145
+     * @param {String} $actionType
146
+     * @param {Array} $actionData
147
+     */
148
+    public function accountDelete($actionType, $actionData)
149
+    {
150
+        $response = array();
151
+
152
+        // check if account needs to clean things up before it gets deleted
153
+        try {
154
+            $accountStore = new \Files\Core\AccountStore();
155
+            $accountStore->getAccount($actionData['entryid'])->beforeDelete();
156
+        } catch (\Files\Backend\Exception $e) {
157
+            // ignore errors here
158
+        }
159
+
160
+        $response['status'] = $accountStore->deleteAccount($actionData['entryid']);
161
+
162
+        $this->addActionData($actionType, $response);
163
+        $GLOBALS["bus"]->addData($this->getResponseData());
164
+
165
+        return $response['status'];
166
+    }
167
+
168
+    /**
169
+     * loads content of current folder - list of folders and files from the Files backend
170
+     *
171
+     * @param {String} $actionType
172
+     * @param {Array} $actionData
173
+     */
174
+    public function accountList($actionType, $actionData)
175
+    {
176
+        $response = array();
177
+
178
+        // get a list of all accounts
179
+        $accountStore = new \Files\Core\AccountStore();
180
+        $accounts = $accountStore->getAllAccounts();
181
+        $accountList = array();
182
+
183
+        if (is_array($accounts)) {
184
+            foreach ($accounts as $account) {
185
+                $account = $accountStore->updateAccount($account);
186
+                $accountList[$account->getId()] = array(
187
+                    "props" => array(
188
+                        "id" => $account->getId(),
189
+                        "name" => $account->getName(),
190
+                        "type" => "account", // to prevent warning while sorting
191
+                        "status" => $account->getStatus(),
192
+                        "status_description" => $account->getStatusDescription(),
193
+                        "backend" => $account->getBackend(),
194
+                        "backend_config" => $account->getBackendConfig(),
195
+                        'backend_features' => $account->getFeatures(),
196
+                        'account_sequence' => $account->getSequence(),
197
+                        'cannot_change' => $account->getCannotChangeFlag()
198
+                    ),
199
+                    'entryid' => $account->getId(),
200
+                    'store_entryid' => 'filesaccount',
201
+                    'parent_entryid' => 'accountstoreroot'
202
+                );
203
+            }
204
+        }
205
+
206
+        // sort the accounts
207
+        $sortKey = "account_sequence";
208
+        $sortDir = "ASC";
209
+
210
+        if (isset($data['sort'])) {
211
+            $sortKey = $data['sort'][0]['field'];
212
+            $sortDir = $data['sort'][0]['direction'];
213
+        }
214
+
215
+        Logger::debug(self::LOG_CONTEXT, "Sorting by " . $sortKey . " in direction: " . $sortDir);
216
+
217
+        $accountList = ArrayUtil::sort_props_by_key($accountList, $sortKey, $sortDir);
218
+
219
+        $response["item"] = array_values($accountList);
220
+        $response['page'] = array("start" => 0, "rowcount" => 50, "totalrowcount" => count($response["item"]));
221
+        $response['folder'] = array("content_count" => count($response["item"]), "content_unread" => 0);
222
+
223
+        $this->addActionData($actionType, $response);
224
+        $GLOBALS["bus"]->addData($this->getResponseData());
225
+
226
+        return true;
227
+    }
228
+
229
+    /**
230
+     * update some values of an account
231
+     *
232
+     * @param {Array} $actionData
233
+     */
234
+    public function accountUpdate($actionData)
235
+    {
236
+        $response = array();
237
+
238
+        // create a new account in our backend
239
+        $accountStore = new \Files\Core\AccountStore();
240
+        $currentAccount = $accountStore->getAccount($actionData['entryid']);
241
+
242
+        // apply changes to the account object
243
+        if (isset($actionData['props']['name'])) {
244
+            $currentAccount->setName(strip_tags($actionData['props']['name']));
245
+        }
246
+        if (isset($actionData['props']['backend'])) {
247
+            $currentAccount->setBackend(strip_tags($actionData['props']['backend']));
248
+        }
249
+        if (isset($actionData['props']['backend_config'])) { // we always get the whole backend config
250
+            $currentAccount->setBackendConfig($actionData['props']['backend_config']);
251
+        }
252
+        if (isset($actionData['props']['account_sequence'])) {
253
+            $currentAccount->setSequence($actionData['props']['account_sequence']);
254
+        }
255
+
256
+        // save changes
257
+        $accountStore->updateAccount($currentAccount);
258
+
259
+        // create the response object
260
+        $updatedAccount = array();
261
+        $updatedAccount[$currentAccount->getId()] = array(
262
+            "props" => array(
263
+                "id" => $currentAccount->getId(),
264
+                "name" => $currentAccount->getName(),
265
+                "status" => $currentAccount->getStatus(),
266
+                "status_description" => $currentAccount->getStatusDescription(),
267
+                "backend" => $currentAccount->getBackend(),
268
+                "backend_config" => $currentAccount->getBackendConfig(),
269
+                'backend_features' => $currentAccount->getFeatures(),
270
+                'account_sequence' => $currentAccount->getSequence()
271
+            ),
272
+            'entryid' => $currentAccount->getId(),
273
+            'store_entryid' => 'filesaccount',
274
+            'parent_entryid' => 'accountstoreroot'
275
+        );
276
+
277
+        $response['item'] = array_values($updatedAccount);
278
+        $this->addActionData("update", $response);
279
+        $GLOBALS["bus"]->addData($this->getResponseData());
280
+
281
+        return true;
282
+    }
283
+
284
+    /**
285
+     * Return all Information about the existing backends.
286
+     *
287
+     * @param {String} $actionType
288
+     */
289
+    public function backendInformation($actionType)
290
+    {
291
+        // find all registered backends
292
+        $backendStore = \Files\Backend\BackendStore::getInstance();
293
+        $backendNames = $backendStore->getRegisteredBackendNames();
294
+
295
+        $data = array();
296
+        $items = array();
297
+        foreach ($backendNames as $backendName) {
298
+            $backendInstance = $backendStore->getInstanceOfBackend($backendName);
299
+            if ($backendInstance !== FALSE) {
300
+                array_push($items, array('props' => array(
301
+                    "name" => $backendName,
302
+                    "message_class" => "IPM.FilesBackend",
303
+                    "displayName" => $backendInstance->getDisplayName()
304
+                )));
305
+            }
306
+        }
307
+
308
+        $data = array_merge($data, array('item' => $items));
309
+
310
+        $this->addActionData($actionType, $data);
311
+        $GLOBALS["bus"]->addData($this->getResponseData());
312
+        return true;
313
+    }
314
+
315
+    /**
316
+     * Return all quota information from specified account.
317
+     *
318
+     * @param {String} $actionType
319
+     * @param {String} $actionData
320
+     */
321
+    public function getQuotaInformation($actionType, $actionData)
322
+    {
323
+        $response = array();
324
+
325
+        $accountId = $actionData["accountId"];
326
+        $rootPath = $actionData["folder"];
327
+
328
+        // load the accountstore
329
+        $accountStore = new \Files\Core\AccountStore();
330
+        $currentAccount = $accountStore->getAccount($accountId);
331
+
332
+        // check if ID was valid, if not respond with error.
333
+        if ($currentAccount === NULL || $currentAccount === FALSE) {
334
+            throw new AccountException(_("Unknown account ID"));
335
+        }
336
+
337
+        $backendStore = \Files\Backend\BackendStore::getInstance();
338
+        $backendInstance = $backendStore->getInstanceOfBackend($currentAccount->getBackend());
339
+
340
+        // check if backend really supports this feature
341
+        if (!$backendInstance->supports(\Files\Backend\BackendStore::FEATURE_QUOTA)) {
342
+            throw new AccountException(_('Feature "Quota Information" is not supported by this backend!'));
343
+        }
344
+
345
+        // init backend instance
346
+        $backendInstance->init_backend($currentAccount->getBackendConfig());
347
+
348
+        // get quota info
349
+        $backendInstance->open();
350
+        $qUsed = $backendInstance->getQuotaBytesUsed($rootPath);
351
+        $qAvailable = $backendInstance->getQuotaBytesAvailable($rootPath);
352
+
353
+        $response['status'] = true;
354
+        $response['quota'] = array(
355
+            array("state" => _('Used'), "amount" => $qUsed),
356
+            array("state" => _('Free'), "amount" => $qAvailable)
357
+        );
358
+
359
+        $this->addActionData($actionType, $response);
360
+        $GLOBALS["bus"]->addData($this->getResponseData());
361
+
362
+        return $response['status'];
363
+    }
364
+
365
+    /**
366
+     * Return all quota information from specified account.
367
+     *
368
+     * @param {String} $actionType
369
+     * @param {String} $actionData
370
+     */
371
+    public function getVersionInformation($actionType, $actionData)
372
+    {
373
+        $response = array();
374
+
375
+        $accountId = $actionData["accountId"];
376
+
377
+        // load the accountstore
378
+        $accountStore = new \Files\Core\AccountStore();
379
+        $currentAccount = $accountStore->getAccount($accountId);
380
+
381
+        // check if ID was valid, if not respond with error.
382
+        if ($currentAccount === NULL || $currentAccount === FALSE) {
383
+            throw new AccountException(_("Unknown account ID"));
384
+        }
385
+
386
+        $backendStore = \Files\Backend\BackendStore::getInstance();
387
+        $backendInstance = $backendStore->getInstanceOfBackend($currentAccount->getBackend());
388
+
389
+        // check if backend really supports this feature
390
+        if (!$backendInstance->supports(\Files\Backend\BackendStore::FEATURE_VERSION)) {
391
+            throw new AccountException(_('Feature "Version Information" is not supported by this backend!'));
392
+        }
393
+
394
+        // init backend instance
395
+        $backendInstance->init_backend($currentAccount->getBackendConfig());
396
+
397
+        // get quota info
398
+        $backendInstance->open();
399
+        $serverVersion = $backendInstance->getServerVersion();
400
+        $backendVersion = $backendInstance->getBackendVersion();
401
+
402
+        $response['status'] = true;
403
+        $response['version'] = array(
404
+            "backend" => $backendVersion,
405
+            "server" => $serverVersion
406
+        );
407
+
408
+        $this->addActionData($actionType, $response);
409
+        $GLOBALS["bus"]->addData($this->getResponseData());
410
+
411
+        return $response['status'];
412
+    }
413
+
414
+    /**
415
+     * Return all quota information from specified account.
416
+     *
417
+     * @param {String} $actionType
418
+     * @param {String} $actionData
419
+     */
420
+    public function updateOauthToken($actionType, $actionData)
421
+    {
422
+        $response = array();
423
+
424
+        $accountId = $actionData["accountId"];
425
+
426
+        // load the accountstore
427
+        $accountStore = new \Files\Core\AccountStore();
428
+        $currentAccount = $accountStore->getAccount($accountId);
429
+
430
+        // check if ID was valid, if not respond with error.
431
+        if ($currentAccount === NULL || $currentAccount === FALSE) {
432
+            throw new AccountException(_("Unknown account ID"));
433
+        }
434
+
435
+        $backendStore = \Files\Backend\BackendStore::getInstance();
436
+        $backendInstance = $backendStore->getInstanceOfBackend($currentAccount->getBackend());
437
+
438
+        // check if backend really supports this feature
439
+        if (!$backendInstance->supports(\Files\Backend\BackendStore::FEATURE_OAUTH)) {
440
+            throw new AccountException(_('Feature "OAUTH" is not supported by this backend!'));
441
+        }
442
+
443
+        // init backend instance
444
+        $backendInstance->init_backend($currentAccount->getBackendConfig());
445
+        $backendInstance->changeAccessToken($actionData["access_token"]);
446
+
447
+        $response['status'] = true;
448
+        $response['access_token'] = $actionData["access_token"];
449
+
450
+        $this->addActionData($actionType, $response);
451
+        $GLOBALS["bus"]->addData($this->getResponseData());
452
+
453
+        return $response['status'];
454
+    }
455
+
456
+    /**
457
+     * Function will retrieve error details from exception object based on exception type.
458
+     * it should also send type of exception with the data. so client can know which type
459
+     * of exception is generated.
460
+     *
461
+     * @param Object $exception the exception object which is generated.
462
+     *
463
+     * @return Array error data
464
+     * @overwrite
465
+     */
466
+    function errorDetailsFromException($exception)
467
+    {
468
+        parent::errorDetailsFromException($exception);
469
+    }
470 470
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -55,7 +55,7 @@
 block discarded – undo
55 55
 							$result = $this->accountDelete($actionType, $actionData);
56 56
 							break;
57 57
 						case "list":
58
-							if(isset($actionData["list_backend"]) && $actionData["list_backend"]) {
58
+							if (isset($actionData["list_backend"]) && $actionData["list_backend"]) {
59 59
 								$result = $this->backendInformation($actionType);
60 60
 							} else {
61 61
 								$result = $this->accountList($actionType, $actionData);
Please login to merge, or discard this patch.
plugins/files/php/class.filesbrowsermodule.php 2 patches
Indentation   +1293 added lines, -1293 removed lines patch added patch discarded remove patch
@@ -30,1305 +30,1305 @@
 block discarded – undo
30 30
  */
31 31
 class FilesBrowserModule extends FilesListModule
32 32
 {
33
-	const LOG_CONTEXT = "FilesBrowserModule"; // Context for the Logger
34
-
35
-	/**
36
-	 * Creates the notifiers for this module,
37
-	 * and register them to the Bus.
38
-	 */
39
-	function createNotifiers()
40
-	{
41
-		$GLOBALS["bus"]->registerNotifier('fileshierarchynotifier', REQUEST_ENTRYID);
42
-	}
43
-
44
-	/**
45
-	 * Executes all the actions in the $data variable.
46
-	 * Exception part is used for authentication errors also
47
-	 * @return boolean true on success or false on failure.
48
-	 */
49
-	public function execute()
50
-	{
51
-		$result = false;
52
-
53
-		foreach ($this->data as $actionType => $actionData) {
54
-			if (isset($actionType)) {
55
-				try {
56
-					switch ($actionType) {
57
-						case "checkifexists":
58
-							$records = $actionData["records"];
59
-							$destination = isset($actionData["destination"]) ? $actionData["destination"] : false;
60
-							$result = $this->checkIfExists($records, $destination);
61
-							$response = array();
62
-							$response['status'] = true;
63
-							$response['duplicate'] = $result;
64
-							$this->addActionData($actionType, $response);
65
-							$GLOBALS["bus"]->addData($this->getResponseData());
66
-							break;
67
-						case "downloadtotmp":
68
-							$result = $this->downloadSelectedFilesToTmp($actionType, $actionData);
69
-							break;
70
-						case "createdir":
71
-							$this->save($actionData);
72
-							$result = true;
73
-							break;
74
-						case "rename":
75
-							$result = $this->rename($actionType, $actionData);
76
-							break;
77
-						case "uploadtobackend":
78
-							$result = $this->uploadToBackend($actionType, $actionData);
79
-							break;
80
-						case "save":
81
-							if ((isset($actionData["props"]["sharedid"]) || isset($actionData["props"]["isshared"])) && (!isset($actionData["props"]["deleted"]) || !isset($actionData["props"]["message_size"]))) {
82
-								// JUST IGNORE THIS REQUEST - we don't need to interact with the backend if a share was changed
83
-								$response['status'] = true;
84
-								$folder = array();
85
-								$folder[$actionData['entryid']] = array(
86
-									'props' => $actionData["props"],
87
-									'entryid' => $actionData['entryid'],
88
-									'store_entryid' => 'files',
89
-									'parent_entryid' => $actionData['parent_entryid']
90
-								);
91
-
92
-								$response['item'] = array_values($folder);
93
-								$this->addActionData("update", $response);
94
-								$GLOBALS["bus"]->addData($this->getResponseData());
95
-
96
-								break;
97
-							}
98
-
99
-							/*
33
+    const LOG_CONTEXT = "FilesBrowserModule"; // Context for the Logger
34
+
35
+    /**
36
+     * Creates the notifiers for this module,
37
+     * and register them to the Bus.
38
+     */
39
+    function createNotifiers()
40
+    {
41
+        $GLOBALS["bus"]->registerNotifier('fileshierarchynotifier', REQUEST_ENTRYID);
42
+    }
43
+
44
+    /**
45
+     * Executes all the actions in the $data variable.
46
+     * Exception part is used for authentication errors also
47
+     * @return boolean true on success or false on failure.
48
+     */
49
+    public function execute()
50
+    {
51
+        $result = false;
52
+
53
+        foreach ($this->data as $actionType => $actionData) {
54
+            if (isset($actionType)) {
55
+                try {
56
+                    switch ($actionType) {
57
+                        case "checkifexists":
58
+                            $records = $actionData["records"];
59
+                            $destination = isset($actionData["destination"]) ? $actionData["destination"] : false;
60
+                            $result = $this->checkIfExists($records, $destination);
61
+                            $response = array();
62
+                            $response['status'] = true;
63
+                            $response['duplicate'] = $result;
64
+                            $this->addActionData($actionType, $response);
65
+                            $GLOBALS["bus"]->addData($this->getResponseData());
66
+                            break;
67
+                        case "downloadtotmp":
68
+                            $result = $this->downloadSelectedFilesToTmp($actionType, $actionData);
69
+                            break;
70
+                        case "createdir":
71
+                            $this->save($actionData);
72
+                            $result = true;
73
+                            break;
74
+                        case "rename":
75
+                            $result = $this->rename($actionType, $actionData);
76
+                            break;
77
+                        case "uploadtobackend":
78
+                            $result = $this->uploadToBackend($actionType, $actionData);
79
+                            break;
80
+                        case "save":
81
+                            if ((isset($actionData["props"]["sharedid"]) || isset($actionData["props"]["isshared"])) && (!isset($actionData["props"]["deleted"]) || !isset($actionData["props"]["message_size"]))) {
82
+                                // JUST IGNORE THIS REQUEST - we don't need to interact with the backend if a share was changed
83
+                                $response['status'] = true;
84
+                                $folder = array();
85
+                                $folder[$actionData['entryid']] = array(
86
+                                    'props' => $actionData["props"],
87
+                                    'entryid' => $actionData['entryid'],
88
+                                    'store_entryid' => 'files',
89
+                                    'parent_entryid' => $actionData['parent_entryid']
90
+                                );
91
+
92
+                                $response['item'] = array_values($folder);
93
+                                $this->addActionData("update", $response);
94
+                                $GLOBALS["bus"]->addData($this->getResponseData());
95
+
96
+                                break;
97
+                            }
98
+
99
+                            /*
100 100
 							 * The "message_action" object has been set, check the action_type field for
101 101
 							 * the exact action which must be taken.
102 102
 							 * Supported actions:
103 103
 							 *   - move: move record to new folder
104 104
 							 */
105
-							if (isset($actionData["message_action"]) && isset($actionData["message_action"]["action_type"])) {
106
-								switch ($actionData["message_action"]["action_type"]) {
107
-									case "move" :
108
-										$result = $this->move($actionType, $actionData);
109
-										break;
110
-									default:
111
-										// check if we should create something new or edit an existing file/folder
112
-										if (isset($actionData["entryid"])) {
113
-											$result = $this->rename($actionType, $actionData);
114
-										} else {
115
-											$result = $this->save($actionData);
116
-										}
117
-										break;
118
-								}
119
-							} else {
120
-								// check if we should create something new or edit an existing file/folder
121
-								if (isset($actionData["entryid"])) {
122
-									$result = $this->rename($actionType, $actionData);
123
-								} else {
124
-									$result = $this->save($actionData);
125
-								}
126
-							}
127
-							break;
128
-						case "delete":
129
-							$result = $this->delete($actionType, $actionData);
130
-							break;
131
-						case "list":
132
-							$result = $this->loadFiles($actionType, $actionData);
133
-							break;
134
-						case "loadsharingdetails":
135
-							$result = $this->getSharingInformation($actionType, $actionData);
136
-							break;
137
-						case "createnewshare":
138
-							$result = $this->createNewShare($actionType, $actionData);
139
-							break;
140
-						case "updateexistingshare":
141
-							$result = $this->updateExistingShare($actionType, $actionData);
142
-							break;
143
-						case "deleteexistingshare":
144
-							$result = $this->deleteExistingShare($actionType, $actionData);
145
-							break;
105
+                            if (isset($actionData["message_action"]) && isset($actionData["message_action"]["action_type"])) {
106
+                                switch ($actionData["message_action"]["action_type"]) {
107
+                                    case "move" :
108
+                                        $result = $this->move($actionType, $actionData);
109
+                                        break;
110
+                                    default:
111
+                                        // check if we should create something new or edit an existing file/folder
112
+                                        if (isset($actionData["entryid"])) {
113
+                                            $result = $this->rename($actionType, $actionData);
114
+                                        } else {
115
+                                            $result = $this->save($actionData);
116
+                                        }
117
+                                        break;
118
+                                }
119
+                            } else {
120
+                                // check if we should create something new or edit an existing file/folder
121
+                                if (isset($actionData["entryid"])) {
122
+                                    $result = $this->rename($actionType, $actionData);
123
+                                } else {
124
+                                    $result = $this->save($actionData);
125
+                                }
126
+                            }
127
+                            break;
128
+                        case "delete":
129
+                            $result = $this->delete($actionType, $actionData);
130
+                            break;
131
+                        case "list":
132
+                            $result = $this->loadFiles($actionType, $actionData);
133
+                            break;
134
+                        case "loadsharingdetails":
135
+                            $result = $this->getSharingInformation($actionType, $actionData);
136
+                            break;
137
+                        case "createnewshare":
138
+                            $result = $this->createNewShare($actionType, $actionData);
139
+                            break;
140
+                        case "updateexistingshare":
141
+                            $result = $this->updateExistingShare($actionType, $actionData);
142
+                            break;
143
+                        case "deleteexistingshare":
144
+                            $result = $this->deleteExistingShare($actionType, $actionData);
145
+                            break;
146 146
                         case "updatecache":
147 147
                             $result = $this->updateCache($actionType, $actionData);
148 148
                             break;
149
-						default:
150
-							$this->handleUnknownActionType($actionType);
151
-					}
152
-
153
-				} catch (MAPIException $e) {
154
-					$this->sendFeedback(false, $this->errorDetailsFromException($e));
155
-				} catch (AccountException $e) {
156
-					$this->sendFeedback(false, array(
157
-						'type' => ERROR_GENERAL,
158
-						'info' => array(
159
-							'title' => $e->getTitle(),
160
-							'original_message' => $e->getMessage(),
161
-							'display_message' => $e->getMessage()
162
-						)
163
-					));
164
-				} catch (BackendException $e) {
165
-					$this->sendFeedback(false, array(
166
-						'type' => ERROR_GENERAL,
167
-						'info' => array(
168
-							'title' => $e->getTitle(),
169
-							'original_message' => $e->getMessage(),
170
-							'display_message' => $e->getMessage(),
171
-							'code' => $e->getCode()
172
-						)
173
-					));
174
-				}
175
-			}
176
-		}
177
-
178
-		return $result;
179
-	}
180
-
181
-	/**
182
-	 * loads content of current folder - list of folders and files from Files
183
-	 *
184
-	 * @param string $actionType name of the current action
185
-	 * @param array $actionData all parameters contained in this request
186
-	 * @throws BackendException if the backend request fails
187
-	 *
188
-	 * @return bool
189
-	 */
190
-	public function loadFiles($actionType, $actionData)
191
-	{
192
-		$nodeId = $actionData['id'];
193
-		$onlyFiles = isset($actionData['only_files']) ? $actionData['only_files'] : false;
194
-		$response = array();
195
-		$nodes = array();
196
-
197
-		$accountID = $this->accountIDFromNode($nodeId);
198
-
199
-		// check if we are in the ROOT (#R#). If so, display some kind of device/account view.
200
-		if (empty($accountID) || !$this->accountStore->getAccount($accountID)) {
201
-			$accounts = $this->accountStore->getAllAccounts();
202
-			foreach ($accounts as $account) { // we have to load all accounts and their folders
203
-				// skip accounts that are not valid
204
-				if ($account->getStatus() != \Files\Core\Account::STATUS_OK) {
205
-					continue;
206
-				}
207
-				// build the real node id for this folder
208
-				$realNodeId = $nodeId . $account->getId() . "/";
209
-
210
-				$nodes[$realNodeId] = array('props' =>
211
-					array(
212
-						'id' => rawurldecode($realNodeId),
213
-						'folder_id' => rawurldecode($realNodeId),
214
-						'path' => $realNodeId,
215
-						'filename' => $account->getName(),
216
-						'message_size' => -1,
217
-						'lastmodified' => -1,
218
-						'message_class' => "IPM.Files",
219
-						'type' => 0
220
-					),
221
-					'entryid' => $this->createId($realNodeId),
222
-					'store_entryid' => $this->createId($realNodeId),
223
-					'parent_entryid' => $this->createId($realNodeId)
224
-				);
225
-			}
226
-		} else {
227
-			$account = $this->accountStore->getAccount($accountID);
228
-
229
-			// initialize the backend
230
-			$initializedBackend = $this->initializeBackend($account, true);
231
-
232
-			$starttime = microtime(true);
233
-			$nodes = $this->getFolderContent($nodeId, $initializedBackend, $onlyFiles);
234
-			Logger::debug(self::LOG_CONTEXT, "[loadfiles]: getFolderContent took: " . (microtime(true) - $starttime) . " seconds");
235
-
236
-			$nodes = $this->sortFolderContent($nodes, $actionData, false);
237
-		}
238
-
239
-		$response["item"] = array_values($nodes);
240
-
241
-		$response['page'] = array("start" => 0, "rowcount" => 50, "totalrowcount" => count($response["item"]));
242
-		$response['folder'] = array("content_count" => count($response["item"]), "content_unread" => 0);
243
-
244
-		$this->addActionData($actionType, $response);
245
-		$GLOBALS["bus"]->addData($this->getResponseData());
246
-
247
-		return true;
248
-	}
249
-
250
-	/**
251
-	 * Forms the structure needed for frontend
252
-	 * for the list of folders and files
253
-	 *
254
-	 * @param string $nodeId the name of the current root directory
255
-	 * @param Files\Backend\AbstractBackend $backendInstance
256
-	 * @param boolean $onlyFiles if true, get only files.
257
-	 *
258
-	 * @throws BackendException if the backend request fails
259
-	 * @return array of nodes for current path folder
260
-	 */
261
-	public function getFolderContent($nodeId, $backendInstance, $onlyFiles = false)
262
-	{
263
-		$nodes = array();
264
-
265
-		// relative node ID. We need to trim off the #R# and account ID
266
-		$relNodeId = substr($nodeId, strpos($nodeId, '/'));
267
-		$nodeIdPrefix = substr($nodeId, 0, strpos($nodeId, '/'));
268
-
269
-		$accountID = $backendInstance->getAccountID();
270
-
271
-		// remove the trailing slash for the cache key
272
-		$cachePath = rtrim($relNodeId, '/');
273
-		if ($cachePath === "") {
274
-			$cachePath = "/";
275
-		}
276
-
277
-		$dir = $this->getCache($accountID, $cachePath);
278
-		if (is_null($dir)) {
279
-			$dir = $backendInstance->ls($relNodeId);
280
-			$this->setCache($accountID, $cachePath, $dir);
281
-		}
282
-
283
-		// FIXME: There is something issue with getting sharing information from owncloud.
284
-		// check if backend supports sharing and load the information
285
-		if ($backendInstance->supports(\Files\Backend\BackendStore::FEATURE_SHARING)) {
286
-			Logger::debug(self::LOG_CONTEXT, "Checking for shared folders! ($relNodeId)");
287
-
288
-			$time_start = microtime(true);
289
-			/** @var \Files\Backend\iFeatureSharing $backendInstance */
290
-			$sharingInfo = $backendInstance->getShares($relNodeId);
291
-			$time_end = microtime(true);
292
-			$time = $time_end - $time_start;
293
-
294
-			Logger::debug(self::LOG_CONTEXT, "Checking for shared took $time s!");
295
-		}
296
-
297
-		if ($dir) {
298
-			$updateCache = false;
299
-			foreach ($dir as $id => $node) {
300
-				$type = FILES_FILE;
301
-
302
-				if (strcmp($node['resourcetype'], "collection") == 0) { // we have a folder
303
-					$type = FILES_FOLDER;
304
-				}
305
-
306
-				if ($type === FILES_FOLDER && $onlyFiles) {
307
-					continue;
308
-				}
309
-
310
-				// Check if foldernames have a trailing slash, if not, add one!
311
-				if ($type === FILES_FOLDER && !StringUtil::endsWith($id, "/")) {
312
-					$id .= "/";
313
-				}
314
-
315
-				$realID = $nodeIdPrefix . $id;
316
-
317
-				Logger::debug(self::LOG_CONTEXT, "parsing: " . $id . " in base: " . $nodeId);
318
-
319
-				$filename = stringToUTF8Encode(basename($id));
320
-
321
-				$size = $node['getcontentlength'] === null ? -1 : intval($node['getcontentlength']);
322
-				$size = $type == FILES_FOLDER ? -1 : $size; // folder's dont have a size
323
-
324
-				$fileid = $node['fileid'] === "-1" ? -1 : intval($node['fileid']);
325
-
326
-				$shared = false;
327
-				$sharedid = array();
328
-				if (isset($sharingInfo) && count($sharingInfo[$relNodeId]) > 0) {
329
-					foreach ($sharingInfo[$relNodeId] as $sid => $sdetails) {
330
-						if ($sdetails["path"] == rtrim($id, "/")) {
331
-							$shared = true;
332
-							$sharedid[] = $sid;
333
-						}
334
-					}
335
-				}
336
-
337
-				$nodeId = stringToUTF8Encode($id);
338
-				$dirName = dirname($nodeId, 1);
339
-				if ($dirName === '/') {
340
-					$path = stringToUTF8Encode($nodeIdPrefix . $dirName);
341
-				} else {
342
-					$path = stringToUTF8Encode($nodeIdPrefix . $dirName . '/');
343
-				}
344
-
345
-				if (!isset($node['entryid']) || !isset($node['parent_entryid']) || !isset($node['store_entryid'])) {
346
-					$entryid = $this->createId($realID);
347
-					$parentEntryid = $this->createId($path);
348
-					$storeEntryid = $this->createId($nodeIdPrefix .'/');
349
-
350
-					$dir[$id]['entryid'] = $entryid;
351
-					$dir[$id]['parent_entryid'] = $parentEntryid;
352
-					$dir[$id]['store_entryid'] = $storeEntryid;
353
-
354
-					$updateCache = true;
355
-				} else {
356
-					$entryid = $node['entryid'];
357
-					$parentEntryid = $node['parent_entryid'];
358
-					$storeEntryid = $node['store_entryid'];
359
-				}
360
-
361
-				$nodes[$nodeId] = array('props' =>
362
-					array(
363
-						'folder_id' => stringToUTF8Encode($realID),
364
-						'fileid' => $fileid,
365
-						'path' => $path,
366
-						'filename' => $filename,
367
-						'message_size' => $size,
368
-						'lastmodified' => strtotime($node['getlastmodified']) * 1000,
369
-						'message_class' => "IPM.Files",
370
-						'isshared' => $shared,
371
-						'sharedid' => $sharedid,
372
-						'object_type' => $type,
373
-						'type' => $type
374
-					),
375
-					'entryid' => $entryid,
376
-					'parent_entryid' => $parentEntryid,
377
-					'store_entryid' => $storeEntryid
378
-				);
379
-			}
380
-
381
-			// Update the cache.
382
-			if ($updateCache) {
383
-				$this->setCache($accountID, $cachePath, $dir);
384
-			}
385
-		} else {
386
-			Logger::debug(self::LOG_CONTEXT, "dir was empty");
387
-		}
388
-
389
-		return $nodes;
390
-	}
391
-
392
-	/**
393
-	 * This functions sorts an array of nodes.
394
-	 *
395
-	 * @param array $nodes array of nodes to sort
396
-	 * @param array $data all parameters contained in the request
397
-	 * @param boolean $navtree parse for navtree or browser
398
-	 *
399
-	 * @return array of sorted nodes
400
-	 */
401
-	public function sortFolderContent($nodes, $data, $navtree = false)
402
-	{
403
-		$sortednodes = array();
404
-
405
-		$sortkey = "filename";
406
-		$sortdir = "ASC";
407
-
408
-		if (isset($data['sort'])) {
409
-			$sortkey = $data['sort'][0]['field'];
410
-			$sortdir = $data['sort'][0]['direction'];
411
-		}
412
-
413
-		Logger::debug(self::LOG_CONTEXT, "sorting by " . $sortkey . " in direction: " . $sortdir);
414
-
415
-		if ($navtree) {
416
-			$sortednodes = ArrayUtil::sort_by_key($nodes, $sortkey, $sortdir);
417
-		} else {
418
-			$sortednodes = ArrayUtil::sort_props_by_key($nodes, $sortkey, $sortdir);
419
-		}
420
-
421
-		return $sortednodes;
422
-	}
423
-
424
-	/**
425
-	 * Deletes the selected files on the backend server
426
-	 *
427
-	 * @access private
428
-	 * @param string $actionType name of the current action
429
-	 * @param array $actionData all parameters contained in this request
430
-	 * @return bool
431
-	 * @throws BackendException if the backend request fails
432
-	 */
433
-	private function delete($actionType, $actionData)
434
-	{
435
-		// TODO: function is duplicate of class.hierarchylistmodule.php of delete function.
436
-		$result = false;
437
-		if (isset($actionData['records']) && is_array($actionData['records'])) {
438
-			foreach ($actionData['records'] as $record) {
439
-				$nodeId = $record['folder_id'];
440
-				$relNodeId = substr($nodeId, strpos($nodeId, '/'));
441
-
442
-				$account = $this->accountFromNode($nodeId);
443
-
444
-				// initialize the backend
445
-				$initializedBackend = $this->initializeBackend($account);
446
-
447
-				$result = $initializedBackend->delete($relNodeId);
448
-				Logger::debug(self::LOG_CONTEXT, "deleted: " . $nodeId . ", worked: " . $result);
449
-
450
-				// clear the cache
451
-				$this->deleteCache($account->getId(), dirname($relNodeId));
452
-				$GLOBALS["bus"]->notify(REQUEST_ENTRYID, OBJECT_DELETE, array(
453
-					"id"=> $nodeId,
454
-					"folder_id"=> $nodeId,
455
-					"entryid"=> $record['entryid'],
456
-					"parent_entryid"=> $record["parent_entryid"],
457
-					"store_entryid"=> $record["store_entryid"]
458
-				));
459
-			}
460
-
461
-			$response['status'] = true;
462
-			$this->addActionData($actionType, $response);
463
-			$GLOBALS["bus"]->addData($this->getResponseData());
464
-
465
-		} else {
466
-			$nodeId = $actionData['folder_id'];
467
-
468
-			$relNodeId = substr($nodeId, strpos($nodeId, '/'));
469
-			$response = array();
470
-
471
-			$account = $this->accountFromNode($nodeId);
472
-			$accountId = $account->getId();
473
-			// initialize the backend
474
-			$initializedBackend = $this->initializeBackend($account);
475
-
476
-			try {
477
-				$result = $initializedBackend->delete($relNodeId);
478
-			} catch (\Files\Backend\Exception $e) {
479
-				// TODO: this might fails because the file was already deleted.
480
-				// fire error message if any other error occurred.
481
-				Logger::debug(self::LOG_CONTEXT, "deleted a directory that was no longer available");
482
-			}
483
-			Logger::debug(self::LOG_CONTEXT, "deleted: " . $nodeId . ", worked: " . $result);
484
-
485
-			// Get old cached data.
486
-			$cachedDir = $this->getCache($accountId, dirname($relNodeId));
487
-			if (isset($cachedDir[$relNodeId]) && !empty($cachedDir[$relNodeId])) {
488
-				// Delete the folder from cached data.
489
-				unset($cachedDir[$relNodeId]);
490
-			}
491
-
492
-			// clear the cache of parent directory.
493
-			$this->deleteCache($accountId, dirname($relNodeId));
494
-			// clear the cache of selected directory.
495
-			$this->deleteCache($accountId, rtrim($relNodeId, '/'));
496
-
497
-			// Set data in cache.
498
-			$this->setCache($accountId, dirname($relNodeId), $cachedDir);
499
-
500
-			$response['status'] = $result ? true : false;
501
-			$this->addActionData($actionType, $response);
502
-			$GLOBALS["bus"]->addData($this->getResponseData());
503
-
504
-			$GLOBALS["bus"]->notify(REQUEST_ENTRYID, OBJECT_DELETE, array(
505
-				"entryid"=> $actionData["entryid"],
506
-				"parent_entryid"=> $actionData["parent_entryid"],
507
-				"store_entryid"=> $actionData["store_entryid"]
508
-			));
509
-		}
510
-
511
-		return true;
512
-	}
513
-
514
-	/**
515
-	 * Moves the selected files on the backend server
516
-	 *
517
-	 * @access private
518
-	 * @param string $actionType name of the current action
519
-	 * @param array $actionData all parameters contained in this request
520
-	 * @return bool if the backend request failed
521
-	 */
522
-	private function move($actionType, $actionData)
523
-	{
524
-		$dst = rtrim($actionData['message_action']["destination_folder_id"], '/');
525
-
526
-		$overwrite = isset($actionData['message_action']["overwrite"]) ? $actionData['message_action']["overwrite"] : true;
527
-		$isFolder = isset($actionData['message_action']["isFolder"]) ? $actionData['message_action']["isFolder"] : false;
528
-
529
-		$pathPostfix = "";
530
-		if (substr($actionData['folder_id'], -1) == '/') {
531
-			$pathPostfix = "/"; // we have a folder...
532
-		}
533
-
534
-		$source = rtrim($actionData['folder_id'], '/');
535
-		$fileName = basename($source);
536
-		$destination = $dst . '/' . basename($source);
537
-
538
-		// get dst and source account ids
539
-		// currently only moving within one account is supported
540
-		$srcAccountID = substr($actionData['folder_id'], 3, (strpos($actionData['folder_id'], '/') - 3)); // parse account id from node id
541
-		$dstAccountID = substr($actionData['message_action']["destination_folder_id"], 3, (strpos($actionData['message_action']["destination_folder_id"], '/') - 3)); // parse account id from node id
542
-
543
-		if ($srcAccountID !== $dstAccountID) {
544
-			$this->sendFeedback(false, array(
545
-				'type' => ERROR_GENERAL,
546
-				'info' => array(
547
-					'title' => _("Files Plugin"),
548
-					'original_message' => _("Moving between accounts is not implemented"),
549
-					'display_message' => _("Moving between accounts is not implemented")
550
-				)
551
-			));
552
-
553
-			return false;
554
-		} else {
555
-			$relDst = substr($destination, strpos($destination, '/'));
556
-			$relSrc = substr($source, strpos($source, '/'));
557
-
558
-			$account = $this->accountFromNode($source);
559
-
560
-			// initialize the backend
561
-			$initializedBackend = $this->initializeBackend($account);
562
-
563
-			$result = $initializedBackend->move($relSrc, $relDst, $overwrite);
564
-
565
-			$actionId = $account->getId();
566
-			// clear the cache
567
-			$this->deleteCache($actionId, dirname($relDst));
568
-
569
-			$cachedFolderName = $relSrc . $pathPostfix;
570
-			$this->deleteCache($actionId, $cachedFolderName);
571
-
572
-			$cached = $this->getCache($actionId, dirname($relSrc));
573
-			$this->deleteCache($actionId, dirname($relSrc));
574
-
575
-			if (isset($cached[$cachedFolderName]) && !empty($cached[$cachedFolderName])) {
576
-				unset($cached[$cachedFolderName]);
577
-				$this->setCache($actionId, dirname($relSrc), $cached);
578
-			}
579
-
580
-			$response['status'] = !$result ? false : true;
581
-
582
-
583
-			/* create the response object */
584
-			$folder = array(
585
-				'props' =>
586
-					array(
587
-						'folder_id' => ($destination . $pathPostfix),
588
-						'path' => $actionData['message_action']["destination_folder_id"],
589
-						'filename' => $fileName,
590
-						'display_name' => $fileName,
591
-						'object_type' => $isFolder ? FILES_FOLDER : FILES_FILE,
592
-						'deleted' => !$result ? false : true
593
-					),
594
-				'entryid' => $this->createId($destination . $pathPostfix),
595
-				'store_entryid' => $actionData['store_entryid'],
596
-				'parent_entryid' => $actionData['message_action']['parent_entryid']
597
-			);
598
-
599
-			$response['item'] = $folder;
600
-
601
-			$this->addActionData("update", $response);
602
-			$GLOBALS["bus"]->addData($this->getResponseData());
603
-
604
-			// Notify hierarchy only when folder was moved.
605
-			if ($isFolder) {
606
-				// Send notification to delete folder node in hierarchy.
607
-				$GLOBALS["bus"]->notify(REQUEST_ENTRYID, OBJECT_DELETE, array(
608
-					"entryid"=> $actionData["entryid"],
609
-					"parent_entryid"=> $actionData["parent_entryid"],
610
-					"store_entryid"=> $actionData["store_entryid"]
611
-				));
612
-
613
-				// Send notification to create new folder node in hierarchy.
614
-				$GLOBALS["bus"]->notify(REQUEST_ENTRYID, OBJECT_SAVE, $folder);
615
-			}
616
-		}
617
-
618
-		return true;
619
-	}
620
-
621
-	/**
622
-	 * Renames the selected file on the backend server
623
-	 *
624
-	 * @access private
625
-	 * @param string $actionType name of the current action
626
-	 * @param array $actionData all parameters contained in this request
627
-	 * @return bool
628
-	 * @throws BackendException if the backend request fails
629
-	 */
630
-	function rename($actionType, $actionData)
631
-	{
632
-		$messageProps = $this->save($actionData);
633
-		$notifySubFolders = isset($actionData['message_action']['isFolder']) ? $actionData['message_action']['isFolder'] : true;
634
-		if(!empty($messageProps)) {
635
-			$GLOBALS["bus"]->notify(REQUEST_ENTRYID, OBJECT_SAVE, $messageProps);
636
-			if ($notifySubFolders) {
637
-				$this->notifySubFolders($messageProps["props"]["folder_id"]);
638
-			}
639
-		}
640
-	}
641
-
642
-	/**
643
-	 * Check if given filename or folder already exists on server
644
-	 *
645
-	 * @access private
646
-	 * @param array $records which needs to be check for existence.
647
-	 * @param array $destination where the given records needs to be moved, uploaded, or renamed.
648
-	 * @throws BackendException if the backend request fails
649
-	 *
650
-	 * @return boolean True if duplicate found, false otherwise
651
-	 */
652
-	private function checkIfExists($records, $destination)
653
-	{
654
-		$duplicate = false;
655
-
656
-		if (isset($records) && is_array($records)) {
657
-			if (!isset($destination) || $destination == false) {
658
-				$destination = reset($records);
659
-				$destination = $destination["id"]; // we can only check files in the same folder, so one request will be enough
660
-				Logger::debug(self::LOG_CONTEXT, "Resetting destination to check.");
661
-			}
662
-			Logger::debug(self::LOG_CONTEXT, "Checking: " . $destination);
663
-			$account = $this->accountFromNode($destination);
664
-
665
-			// initialize the backend
666
-			$initializedBackend = $this->initializeBackend($account);
667
-
668
-			$relDirname = substr($destination, strpos($destination, '/'));
669
-			Logger::debug(self::LOG_CONTEXT, "Getting content for: " . $relDirname);
670
-			try {
671
-				$lsdata = $initializedBackend->ls($relDirname); // we can only check files in the same folder, so one request will be enough
672
-			} catch (Exception $e) {
673
-				// ignore - if file not found -> does not exist :)
674
-			}
675
-			if (isset($lsdata) && is_array($lsdata)) {
676
-				foreach ($records as $record) {
677
-					$relRecId = substr($record["id"], strpos($record["id"], '/'));
678
-					Logger::debug(self::LOG_CONTEXT, "Checking rec: " . $relRecId, "Core");
679
-					foreach ($lsdata as $argsid => $args) {
680
-						if (strcmp($args['resourcetype'], "collection") == 0 && $record["isFolder"] && strcmp(basename($argsid), basename($relRecId)) == 0) { // we have a folder
681
-							Logger::debug(self::LOG_CONTEXT, "Duplicate folder found: " . $argsid, "Core");
682
-							$duplicate = true;
683
-							break;
684
-						} else {
685
-							if (strcmp($args['resourcetype'], "collection") != 0 && !$record["isFolder"] && strcmp(basename($argsid), basename($relRecId)) == 0) {
686
-								Logger::debug(self::LOG_CONTEXT, "Duplicate file found: " . $argsid, "Core");
687
-								$duplicate = true;
688
-								break;
689
-							} else {
690
-								$duplicate = false;
691
-							}
692
-						}
693
-					}
694
-
695
-					if ($duplicate) {
696
-						Logger::debug(self::LOG_CONTEXT, "Duplicate entry: " . $relRecId, "Core");
697
-						break;
698
-					}
699
-				}
700
-			}
701
-		}
702
-
703
-		return $duplicate;
704
-	}
705
-
706
-	/**
707
-	 * Downloads file from the Files service and saves it in tmp
708
-	 * folder with unique name
709
-	 *
710
-	 * @access private
711
-	 * @param array $actionData
712
-	 * @throws BackendException if the backend request fails
713
-	 *
714
-	 * @return void
715
-	 */
716
-	private function downloadSelectedFilesToTmp($actionType, $actionData)
717
-	{
718
-		$ids = $actionData['ids'];
719
-		$dialogAttachmentId = $actionData['dialog_attachments'];
720
-		$response = array();
721
-
722
-		$attachment_state = new AttachmentState();
723
-		$attachment_state->open();
724
-
725
-		$account = $this->accountFromNode($ids[0]);
726
-
727
-		// initialize the backend
728
-		$initializedBackend = $this->initializeBackend($account);
729
-
730
-		foreach ($ids as $file) {
731
-			$filename = basename($file);
732
-			$tmpname = $attachment_state->getAttachmentTmpPath($filename);
733
-
734
-			// download file from the backend
735
-			$relRecId = substr($file, strpos($file, '/'));
736
-		    $http_status = $initializedBackend->get_file($relRecId, $tmpname);
737
-
738
-			$filesize = filesize($tmpname);
739
-
740
-			Logger::debug(self::LOG_CONTEXT, "Downloading: " . $filename . " to: " . $tmpname);
741
-
742
-			$attach_id = uniqid();
743
-			$response['items'][] = array(
744
-				'name' => $filename,
745
-				'size' => $filesize,
746
-				"attach_id" => $attach_id,
747
-				'tmpname' => PathUtil::getFilenameFromPath($tmpname)
748
-			);
749
-
750
-			$attachment_state->addAttachmentFile($dialogAttachmentId, PathUtil::getFilenameFromPath($tmpname), Array(
751
-				"name" => $filename,
752
-				"size" => $filesize,
753
-				"type" => PathUtil::get_mime($tmpname),
754
-				"attach_id" => $attach_id,
755
-				"sourcetype" => 'default'
756
-			));
757
-
758
-			Logger::debug(self::LOG_CONTEXT, "filesize: " . $filesize);
759
-		}
760
-
761
-		$attachment_state->close();
762
-		$response['status'] = true;
763
-		$this->addActionData($actionType, $response);
764
-		$GLOBALS["bus"]->addData($this->getResponseData());
765
-	}
766
-
767
-	/**
768
-	 * upload the tempfile to files
769
-	 *
770
-	 * @access private
771
-	 * @param array $actionData
772
-	 * @throws BackendException if the backend request fails
773
-	 *
774
-	 * @return void
775
-	 */
776
-	private function uploadToBackend($actionType, $actionData)
777
-	{
778
-		Logger::debug(self::LOG_CONTEXT, "preparing attachment");
779
-
780
-		$account = $this->accountFromNode($actionData["destdir"]);
781
-
782
-		// initialize the backend
783
-		$initializedBackend = $this->initializeBackend($account);
784
-
785
-		$result = true;
786
-
787
-		if ($actionData["type"] === "attachment") {
788
-			foreach ($actionData["items"] as $item) {
789
-				list($tmpname, $filename) = $this->prepareAttachmentForUpload($item);
790
-
791
-				$dirName = substr($actionData["destdir"], strpos($actionData["destdir"], '/'));
792
-				$filePath = $dirName . $filename;
793
-
794
-				Logger::debug(self::LOG_CONTEXT, "Uploading to: " . $filePath . " tmpfile: " . $tmpname);
795
-
796
-				$result = $result && $initializedBackend->put_file($filePath, $tmpname);
797
-				unlink($tmpname);
798
-
799
-				$this->updateDirCache($initializedBackend, $dirName, $filePath, $actionData);
800
-			}
801
-		} elseif ($actionData["type"] === "mail") {
802
-			foreach ($actionData["items"] as $item) {
803
-				list($tmpname, $filename) = $this->prepareEmailForUpload($item);
804
-
805
-				$dirName = substr($actionData["destdir"], strpos($actionData["destdir"], '/'));
806
-				$filePath = $dirName . $filename;
807
-
808
-				Logger::debug(self::LOG_CONTEXT, "Uploading to: " . $filePath . " tmpfile: " . $tmpname);
809
-
810
-				$result = $result && $initializedBackend->put_file($filePath, $tmpname);
811
-				unlink($tmpname);
812
-
813
-				$this->updateDirCache($initializedBackend, $dirName, $filePath, $actionData);
814
-			}
815
-		} else {
816
-			$this->sendFeedback(false, array(
817
-				'type' => ERROR_GENERAL,
818
-				'info' => array(
819
-					'title' => _("Files plugin"),
820
-					'original_message' => _("Unknown type - cannot save this file to the Files backend!"),
821
-					'display_message' => _("Unknown type - cannot save this file to the Files backend!")
822
-				)
823
-			));
824
-		}
825
-
826
-		$response = array();
827
-		$response['status'] = $result;
828
-		$this->addActionData($actionType, $response);
829
-		$GLOBALS["bus"]->addData($this->getResponseData());
830
-	}
831
-
832
-	/**
833
-	 * Update the cache of selected directory
834
-	 *
835
-	 * @param Files\Backend\AbstractBackend $backendInstance
836
-	 * @param string $dirName The directory name
837
-	 * @param $filePath The file path.
838
-	 * @param $actionData The action data.
839
-	 * @throws BackendException
840
-	 */
841
-	function updateDirCache($backendInstance, $dirName, $filePath, $actionData)
842
-	{
843
-		$cachePath = rtrim($dirName, '/');
844
-		if ($cachePath === "") {
845
-			$cachePath = "/";
846
-		}
847
-
848
-		$dir = $backendInstance->ls($cachePath);
849
-		$accountID = $this->accountIDFromNode($actionData["destdir"]);
850
-		$cacheDir = $this->getCache($accountID, $cachePath);
851
-		$cacheDir[$filePath] = $dir[$filePath];
852
-		$this->setCache($accountID, $cachePath, $cacheDir);
853
-	}
854
-
855
-	/**
856
-	 * This function will prepare an attachment for the upload to the backend.
857
-	 * It will store the attachment to the TMP folder and return its temporary
858
-	 * path and filename as array.
859
-	 *
860
-	 * @param $items
861
-	 * @return array (tmpname, filename) or false on error
862
-	 * @access private
863
-	 */
864
-	private function prepareAttachmentForUpload($item)
865
-	{
866
-		// Check which type isset
867
-		$openType = "attachment";
868
-
869
-		// Get store id
870
-		$storeid = false;
871
-		if (isset($item["store"])) {
872
-			$storeid = $item["store"];
873
-		}
874
-
875
-		// Get message entryid
876
-		$entryid = false;
877
-		if (isset($item["entryid"])) {
878
-			$entryid = $item["entryid"];
879
-		}
880
-
881
-		// Get number of attachment which should be opened.
882
-		$attachNum = false;
883
-		if (isset($item["attachNum"])) {
884
-			$attachNum = $item["attachNum"];
885
-		}
886
-
887
-		$tmpname = "";
888
-		$filename = "";
889
-
890
-		// Check if storeid and entryid isset
891
-		if ($storeid && $entryid) {
892
-			// Open the store
893
-			$store = $GLOBALS["mapisession"]->openMessageStore(hex2bin($storeid));
894
-
895
-			if ($store) {
896
-				// Open the message
897
-				$message = mapi_msgstore_openentry($store, hex2bin($entryid));
898
-
899
-				if ($message) {
900
-					$attachment = false;
901
-
902
-					// Check if attachNum isset
903
-					if ($attachNum) {
904
-						// Loop through the attachNums, message in message in message ...
905
-						for ($i = 0; $i < (count($attachNum) - 1); $i++) {
906
-							// Open the attachment
907
-							$tempattach = mapi_message_openattach($message, (int)$attachNum[$i]);
908
-							if ($tempattach) {
909
-								// Open the object in the attachment
910
-								$message = mapi_attach_openobj($tempattach);
911
-							}
912
-						}
913
-
914
-						// Open the attachment
915
-						$attachment = mapi_message_openattach($message, (int)$attachNum[(count($attachNum) - 1)]);
916
-					}
917
-
918
-					// Check if the attachment is opened
919
-					if ($attachment) {
920
-
921
-						// Get the props of the attachment
922
-						$props = mapi_attach_getprops($attachment, array(PR_ATTACH_LONG_FILENAME, PR_ATTACH_MIME_TAG, PR_DISPLAY_NAME, PR_ATTACH_METHOD));
923
-						// Content Type
924
-						$contentType = "application/octet-stream";
925
-						// Filename
926
-						$filename = "ERROR";
927
-
928
-						// Set filename
929
-						if (isset($props[PR_ATTACH_LONG_FILENAME])) {
930
-							$filename = PathUtil::sanitizeFilename($props[PR_ATTACH_LONG_FILENAME]);
931
-						} else {
932
-							if (isset($props[PR_ATTACH_FILENAME])) {
933
-								$filename = PathUtil::sanitizeFilename($props[PR_ATTACH_FILENAME]);
934
-							} else {
935
-								if (isset($props[PR_DISPLAY_NAME])) {
936
-									$filename = PathUtil::sanitizeFilename($props[PR_DISPLAY_NAME]);
937
-								}
938
-							}
939
-						}
940
-
941
-						// Set content type
942
-						if (isset($props[PR_ATTACH_MIME_TAG])) {
943
-							$contentType = $props[PR_ATTACH_MIME_TAG];
944
-						} else {
945
-							// Parse the extension of the filename to get the content type
946
-							if (strrpos($filename, ".") !== false) {
947
-								$extension = strtolower(substr($filename, strrpos($filename, ".")));
948
-								$contentType = "application/octet-stream";
949
-								if (is_readable("mimetypes.dat")) {
950
-									$fh = fopen("mimetypes.dat", "r");
951
-									$ext_found = false;
952
-									while (!feof($fh) && !$ext_found) {
953
-										$line = fgets($fh);
954
-										preg_match("/(\.[a-z0-9]+)[ \t]+([^ \t\n\r]*)/i", $line, $result);
955
-										if ($extension == $result[1]) {
956
-											$ext_found = true;
957
-											$contentType = $result[2];
958
-										}
959
-									}
960
-									fclose($fh);
961
-								}
962
-							}
963
-						}
964
-
965
-
966
-						$tmpname = tempnam(TMP_PATH, stripslashes($filename));
967
-
968
-						// Open a stream to get the attachment data
969
-						$stream = mapi_openproperty($attachment, PR_ATTACH_DATA_BIN, IID_IStream, 0, 0);
970
-						$stat = mapi_stream_stat($stream);
971
-						// File length =  $stat["cb"]
972
-
973
-						Logger::debug(self::LOG_CONTEXT, "filesize: " . $stat["cb"]);
974
-
975
-						$fhandle = fopen($tmpname, 'w');
976
-						$buffer = null;
977
-						for ($i = 0; $i < $stat["cb"]; $i += BLOCK_SIZE) {
978
-							// Write stream
979
-							$buffer = mapi_stream_read($stream, BLOCK_SIZE);
980
-							fwrite($fhandle, $buffer, strlen($buffer));
981
-						}
982
-						fclose($fhandle);
983
-
984
-						Logger::debug(self::LOG_CONTEXT, "temp attachment written to " . $tmpname);
985
-
986
-						return array($tmpname, $filename);
987
-					}
988
-				}
989
-			} else {
990
-				Logger::error(self::LOG_CONTEXT, "store could not be opened");
991
-			}
992
-		} else {
993
-			Logger::error(self::LOG_CONTEXT, "wrong call, store and entryid have to be set");
994
-		}
995
-
996
-		return false;
997
-	}
998
-
999
-	/**
1000
-	 * Store the email as eml to a temporary directory and return its temporary filename.
1001
-	 *
1002
-	 * @param {string} $actionType
1003
-	 * @param {array} $actionData
1004
-	 * @return array (tmpname, filename) or false on error
1005
-	 * @access private
1006
-	 */
1007
-	private function prepareEmailForUpload($item)
1008
-	{
1009
-		// Get store id
1010
-		$storeid = false;
1011
-		if (isset($item["store"])) {
1012
-			$storeid = $item["store"];
1013
-		}
1014
-
1015
-		// Get message entryid
1016
-		$entryid = false;
1017
-		if (isset($item["entryid"])) {
1018
-			$entryid = $item["entryid"];
1019
-		}
1020
-
1021
-		$tmpname = "";
1022
-		$filename = "";
1023
-
1024
-		$store = $GLOBALS['mapisession']->openMessageStore(hex2bin($storeid));
1025
-		$message = mapi_msgstore_openentry($store, hex2bin($entryid));
1026
-
1027
-		// Decode smime signed messages on this message
1028
-		parse_smime($store, $message);
1029
-
1030
-		if ($message && $store) {
1031
-			// get message properties.
1032
-			$messageProps = mapi_getprops($message, array(PR_SUBJECT, PR_EC_IMAP_EMAIL, PR_MESSAGE_CLASS));
1033
-
1034
-			$isSupportedMessage = (
1035
-				(stripos($messageProps[PR_MESSAGE_CLASS], 'IPM.Note') === 0)
1036
-				|| (stripos($messageProps[PR_MESSAGE_CLASS], 'Report.IPM.Note') === 0)
1037
-				|| (stripos($messageProps[PR_MESSAGE_CLASS], 'IPM.Schedule') === 0)
1038
-			);
1039
-
1040
-			if ($isSupportedMessage) {
1041
-				// If RFC822-formatted stream is already available in PR_EC_IMAP_EMAIL property
1042
-				// than directly use it, generate otherwise.
1043
-				if (isset($messageProps[PR_EC_IMAP_EMAIL]) || propIsError(PR_EC_IMAP_EMAIL, $messageProps) == MAPI_E_NOT_ENOUGH_MEMORY) {
1044
-					// Stream the message to properly get the PR_EC_IMAP_EMAIL property
1045
-					$stream = mapi_openproperty($message, PR_EC_IMAP_EMAIL, IID_IStream, 0, 0);
1046
-				} else {
1047
-					// Get addressbook for current session
1048
-					$addrBook = $GLOBALS['mapisession']->getAddressbook();
1049
-
1050
-					// Read the message as RFC822-formatted e-mail stream.
1051
-					$stream = mapi_inetmapi_imtoinet($GLOBALS['mapisession']->getSession(), $addrBook, $message, array());
1052
-				}
1053
-
1054
-				if (!empty($messageProps[PR_SUBJECT])) {
1055
-					$filename = PathUtil::sanitizeFilename($messageProps[PR_SUBJECT]) . '.eml';
1056
-				} else {
1057
-					$filename = _('Untitled') . '.eml';
1058
-				}
1059
-
1060
-				$tmpname = tempnam(TMP_PATH, "email2filez");
1061
-
1062
-				// Set the file length
1063
-				$stat = mapi_stream_stat($stream);
1064
-
1065
-				$fhandle = fopen($tmpname, 'w');
1066
-				$buffer = null;
1067
-				for ($i = 0; $i < $stat["cb"]; $i += BLOCK_SIZE) {
1068
-					// Write stream
1069
-					$buffer = mapi_stream_read($stream, BLOCK_SIZE);
1070
-					fwrite($fhandle, $buffer, strlen($buffer));
1071
-				}
1072
-				fclose($fhandle);
1073
-
1074
-				return array($tmpname, $filename);
1075
-			}
1076
-		}
1077
-
1078
-		return false;
1079
-	}
1080
-
1081
-	/**
1082
-	 * Get sharing information from the backend.
1083
-	 *
1084
-	 * @param $actionType
1085
-	 * @param $actionData
1086
-	 * @return bool
1087
-	 */
1088
-	private function getSharingInformation($actionType, $actionData)
1089
-	{
1090
-		$response = array();
1091
-		$records = $actionData["records"];
1092
-
1093
-		if (count($records) < 1) {
1094
-			$this->sendFeedback(false, array(
1095
-				'type' => ERROR_GENERAL,
1096
-				'info' => array(
1097
-					'title' => _("Files Plugin"),
1098
-					'original_message' => _("No record given!"),
1099
-					'display_message' => _("No record given!")
1100
-				)
1101
-			));
1102
-		}
1103
-
1104
-		$account = $this->accountFromNode($records[0]);
1105
-
1106
-		// initialize the backend
1107
-		$initializedBackend = $this->initializeBackend($account);
1108
-
1109
-		$relRecords = array();
1110
-		foreach ($records as $record) {
1111
-			$relRecords[] = substr($record, strpos($record, '/')); // remove account id
1112
-		}
1113
-
1114
-		try {
1115
-			$sInfo = $initializedBackend->sharingDetails($relRecords);
1116
-		} catch (Exception $e) {
1117
-			$response['status'] = false;
1118
-			$response['header'] = _('Fetching sharing information failed');
1119
-			$response['message'] = $e->getMessage();
1120
-			$this->addActionData("error", $response);
1121
-			$GLOBALS["bus"]->addData($this->getResponseData());
1122
-
1123
-			return false;
1124
-		}
1125
-
1126
-		$sharingInfo = array();
1127
-		foreach ($sInfo as $path => $details) {
1128
-			$realPath = "#R#" . $account->getId() . $path;
1129
-			$sharingInfo[$realPath] = $details; // add account id again
1130
-		}
1131
-
1132
-		$response['status'] = true;
1133
-		$response['shares'] = $sharingInfo;
1134
-		$this->addActionData($actionType, $response);
1135
-		$GLOBALS["bus"]->addData($this->getResponseData());
1136
-
1137
-		return true;
1138
-	}
1139
-
1140
-	/**
1141
-	 * Create a new share.
1142
-	 *
1143
-	 * @param $actionType
1144
-	 * @param $actionData
1145
-	 * @return bool
1146
-	 */
1147
-	private function createNewShare($actionType, $actionData)
1148
-	{
1149
-		$records = $actionData["records"];
1150
-		$shareOptions = $actionData["options"];
1151
-
1152
-		if (count($records) < 1) {
1153
-			$this->sendFeedback(false, array(
1154
-				'type' => ERROR_GENERAL,
1155
-				'info' => array(
1156
-					'title' => _("Files Plugin"),
1157
-					'original_message' => _("No record given!"),
1158
-					'display_message' => _("No record given!")
1159
-				)
1160
-			));
1161
-		}
1162
-
1163
-		$account = $this->accountFromNode($records[0]);
1164
-
1165
-		// initialize the backend
1166
-		$initializedBackend = $this->initializeBackend($account);
1167
-
1168
-		$sharingRecords = array();
1169
-		foreach ($records as $record) {
1170
-			$path = substr($record, strpos($record, '/')); // remove account id
1171
-			$sharingRecords[$path] = $shareOptions; // add options
1172
-		}
1173
-
1174
-		try {
1175
-			$sInfo = $initializedBackend->share($sharingRecords);
1176
-		} catch (Exception $e) {
1177
-			$response['status'] = false;
1178
-			$response['header'] = _('Sharing failed');
1179
-			$response['message'] = $e->getMessage();
1180
-			$this->addActionData("error", $response);
1181
-			$GLOBALS["bus"]->addData($this->getResponseData());
1182
-
1183
-			return false;
1184
-		}
1185
-
1186
-		$sharingInfo = array();
1187
-		foreach ($sInfo as $path => $details) {
1188
-			$realPath = "#R#" . $account->getId() . $path;
1189
-			$sharingInfo[$realPath] = $details; // add account id again
1190
-		}
1191
-
1192
-		$response = array();
1193
-		$response['status'] = true;
1194
-		$response['shares'] = $sharingInfo;
1195
-		$this->addActionData($actionType, $response);
1196
-		$GLOBALS["bus"]->addData($this->getResponseData());
1197
-
1198
-		return true;
1199
-	}
1200
-
1201
-	/**
1202
-	 * Update a existing share.
1203
-	 * @param $actionType
1204
-	 * @param $actionData
1205
-	 * @return bool
1206
-	 */
1207
-	private function updateExistingShare($actionType, $actionData)
1208
-	{
1209
-		$records = $actionData["records"];
1210
-		$accountID = $actionData["accountid"];
1211
-		$shareOptions = $actionData["options"];
1212
-
1213
-		if (count($records) < 1) {
1214
-			$this->sendFeedback(false, array(
1215
-				'type' => ERROR_GENERAL,
1216
-				'info' => array(
1217
-					'title' => _("Files Plugin"),
1218
-					'original_message' => _("No record given!"),
1219
-					'display_message' => _("No record given!")
1220
-				)
1221
-			));
1222
-		}
1223
-
1224
-		$account = $this->accountStore->getAccount($accountID);
1225
-
1226
-		// initialize the backend
1227
-		$initializedBackend = $this->initializeBackend($account);
1228
-
1229
-		$sharingRecords = array();
1230
-		foreach ($records as $record) {
1231
-			$sharingRecords[$record] = $shareOptions; // add options
1232
-		}
1233
-
1234
-		try {
1235
-			$sInfo = $initializedBackend->share($sharingRecords, true);
1236
-		} catch (Exception $e) {
1237
-			$response['status'] = false;
1238
-			$response['header'] = _('Updating share failed');
1239
-			$response['message'] = $e->getMessage();
1240
-			$this->addActionData("error", $response);
1241
-			$GLOBALS["bus"]->addData($this->getResponseData());
1242
-
1243
-			return false;
1244
-		}
1245
-
1246
-		$response = array();
1247
-		$response['status'] = true;
1248
-		$response['shares'] = $sInfo;
1249
-		$this->addActionData($actionType, $response);
1250
-		$GLOBALS["bus"]->addData($this->getResponseData());
1251
-
1252
-		return true;
1253
-	}
1254
-
1255
-	/**
1256
-	 * Delete one or more shares.
1257
-	 * @param $actionType
1258
-	 * @param $actionData
1259
-	 * @return bool
1260
-	 */
1261
-	private function deleteExistingShare($actionType, $actionData)
1262
-	{
1263
-		$records = $actionData["records"];
1264
-		$accountID = $actionData["accountid"];
1265
-
1266
-		if (count($records) < 1) {
1267
-			$this->sendFeedback(false, array(
1268
-				'type' => ERROR_GENERAL,
1269
-				'info' => array(
1270
-					'title' => _("Files Plugin"),
1271
-					'original_message' => _("No record given!"),
1272
-					'display_message' => _("No record given!")
1273
-				)
1274
-			));
1275
-		}
1276
-
1277
-		$account = $this->accountStore->getAccount($accountID);
1278
-
1279
-		// initialize the backend
1280
-		$initializedBackend = $this->initializeBackend($account);
1281
-
1282
-		try {
1283
-			$sInfo = $initializedBackend->unshare($records);
1284
-		} catch (Exception $e) {
1285
-			$response['status'] = false;
1286
-			$response['header'] = _('Deleting share failed');
1287
-			$response['message'] = $e->getMessage();
1288
-			$this->addActionData("error", $response);
1289
-			$GLOBALS["bus"]->addData($this->getResponseData());
1290
-
1291
-			return false;
1292
-		}
1293
-
1294
-		$response = array();
1295
-		$response['status'] = true;
1296
-		$this->addActionData($actionType, $response);
1297
-		$GLOBALS["bus"]->addData($this->getResponseData());
1298
-
1299
-		return true;
1300
-	}
1301
-
1302
-	/**
1303
-	 * Function will use to update the cache
1304
-	 *
1305
-	 * @param string $actionType name of the current action
1306
-	 * @param array $actionData all parameters contained in this request
1307
-	 *
1308
-	 * @return boolean true on success or false on failure.
1309
-	 */
1310
-	function updateCache($actionType, $actionData)
1311
-	{
1312
-		$nodeId = $actionData['id'];
1313
-		$accountID = $this->accountIDFromNode($nodeId);
1314
-		$account = $this->accountStore->getAccount($accountID);
1315
-		// initialize the backend
1316
-		$initializedBackend = $this->initializeBackend($account, true);
1317
-		$relNodeId = substr($nodeId, strpos($nodeId, '/'));
1318
-
1319
-		// remove the trailing slash for the cache key
1320
-		$cachePath = rtrim($relNodeId, '/');
1321
-		if ($cachePath === "") {
1322
-			$cachePath = "/";
1323
-		}
1324
-		$dir = $initializedBackend->ls($relNodeId);
1325
-		$this->setCache($accountID, $cachePath, $dir);
1326
-
1327
-		$response = array();
1328
-		$response['status'] = true;
1329
-		$this->addActionData($actionType, $response);
1330
-		$GLOBALS["bus"]->addData($this->getResponseData());
1331
-
1332
-		return true;
1333
-	}
149
+                        default:
150
+                            $this->handleUnknownActionType($actionType);
151
+                    }
152
+
153
+                } catch (MAPIException $e) {
154
+                    $this->sendFeedback(false, $this->errorDetailsFromException($e));
155
+                } catch (AccountException $e) {
156
+                    $this->sendFeedback(false, array(
157
+                        'type' => ERROR_GENERAL,
158
+                        'info' => array(
159
+                            'title' => $e->getTitle(),
160
+                            'original_message' => $e->getMessage(),
161
+                            'display_message' => $e->getMessage()
162
+                        )
163
+                    ));
164
+                } catch (BackendException $e) {
165
+                    $this->sendFeedback(false, array(
166
+                        'type' => ERROR_GENERAL,
167
+                        'info' => array(
168
+                            'title' => $e->getTitle(),
169
+                            'original_message' => $e->getMessage(),
170
+                            'display_message' => $e->getMessage(),
171
+                            'code' => $e->getCode()
172
+                        )
173
+                    ));
174
+                }
175
+            }
176
+        }
177
+
178
+        return $result;
179
+    }
180
+
181
+    /**
182
+     * loads content of current folder - list of folders and files from Files
183
+     *
184
+     * @param string $actionType name of the current action
185
+     * @param array $actionData all parameters contained in this request
186
+     * @throws BackendException if the backend request fails
187
+     *
188
+     * @return bool
189
+     */
190
+    public function loadFiles($actionType, $actionData)
191
+    {
192
+        $nodeId = $actionData['id'];
193
+        $onlyFiles = isset($actionData['only_files']) ? $actionData['only_files'] : false;
194
+        $response = array();
195
+        $nodes = array();
196
+
197
+        $accountID = $this->accountIDFromNode($nodeId);
198
+
199
+        // check if we are in the ROOT (#R#). If so, display some kind of device/account view.
200
+        if (empty($accountID) || !$this->accountStore->getAccount($accountID)) {
201
+            $accounts = $this->accountStore->getAllAccounts();
202
+            foreach ($accounts as $account) { // we have to load all accounts and their folders
203
+                // skip accounts that are not valid
204
+                if ($account->getStatus() != \Files\Core\Account::STATUS_OK) {
205
+                    continue;
206
+                }
207
+                // build the real node id for this folder
208
+                $realNodeId = $nodeId . $account->getId() . "/";
209
+
210
+                $nodes[$realNodeId] = array('props' =>
211
+                    array(
212
+                        'id' => rawurldecode($realNodeId),
213
+                        'folder_id' => rawurldecode($realNodeId),
214
+                        'path' => $realNodeId,
215
+                        'filename' => $account->getName(),
216
+                        'message_size' => -1,
217
+                        'lastmodified' => -1,
218
+                        'message_class' => "IPM.Files",
219
+                        'type' => 0
220
+                    ),
221
+                    'entryid' => $this->createId($realNodeId),
222
+                    'store_entryid' => $this->createId($realNodeId),
223
+                    'parent_entryid' => $this->createId($realNodeId)
224
+                );
225
+            }
226
+        } else {
227
+            $account = $this->accountStore->getAccount($accountID);
228
+
229
+            // initialize the backend
230
+            $initializedBackend = $this->initializeBackend($account, true);
231
+
232
+            $starttime = microtime(true);
233
+            $nodes = $this->getFolderContent($nodeId, $initializedBackend, $onlyFiles);
234
+            Logger::debug(self::LOG_CONTEXT, "[loadfiles]: getFolderContent took: " . (microtime(true) - $starttime) . " seconds");
235
+
236
+            $nodes = $this->sortFolderContent($nodes, $actionData, false);
237
+        }
238
+
239
+        $response["item"] = array_values($nodes);
240
+
241
+        $response['page'] = array("start" => 0, "rowcount" => 50, "totalrowcount" => count($response["item"]));
242
+        $response['folder'] = array("content_count" => count($response["item"]), "content_unread" => 0);
243
+
244
+        $this->addActionData($actionType, $response);
245
+        $GLOBALS["bus"]->addData($this->getResponseData());
246
+
247
+        return true;
248
+    }
249
+
250
+    /**
251
+     * Forms the structure needed for frontend
252
+     * for the list of folders and files
253
+     *
254
+     * @param string $nodeId the name of the current root directory
255
+     * @param Files\Backend\AbstractBackend $backendInstance
256
+     * @param boolean $onlyFiles if true, get only files.
257
+     *
258
+     * @throws BackendException if the backend request fails
259
+     * @return array of nodes for current path folder
260
+     */
261
+    public function getFolderContent($nodeId, $backendInstance, $onlyFiles = false)
262
+    {
263
+        $nodes = array();
264
+
265
+        // relative node ID. We need to trim off the #R# and account ID
266
+        $relNodeId = substr($nodeId, strpos($nodeId, '/'));
267
+        $nodeIdPrefix = substr($nodeId, 0, strpos($nodeId, '/'));
268
+
269
+        $accountID = $backendInstance->getAccountID();
270
+
271
+        // remove the trailing slash for the cache key
272
+        $cachePath = rtrim($relNodeId, '/');
273
+        if ($cachePath === "") {
274
+            $cachePath = "/";
275
+        }
276
+
277
+        $dir = $this->getCache($accountID, $cachePath);
278
+        if (is_null($dir)) {
279
+            $dir = $backendInstance->ls($relNodeId);
280
+            $this->setCache($accountID, $cachePath, $dir);
281
+        }
282
+
283
+        // FIXME: There is something issue with getting sharing information from owncloud.
284
+        // check if backend supports sharing and load the information
285
+        if ($backendInstance->supports(\Files\Backend\BackendStore::FEATURE_SHARING)) {
286
+            Logger::debug(self::LOG_CONTEXT, "Checking for shared folders! ($relNodeId)");
287
+
288
+            $time_start = microtime(true);
289
+            /** @var \Files\Backend\iFeatureSharing $backendInstance */
290
+            $sharingInfo = $backendInstance->getShares($relNodeId);
291
+            $time_end = microtime(true);
292
+            $time = $time_end - $time_start;
293
+
294
+            Logger::debug(self::LOG_CONTEXT, "Checking for shared took $time s!");
295
+        }
296
+
297
+        if ($dir) {
298
+            $updateCache = false;
299
+            foreach ($dir as $id => $node) {
300
+                $type = FILES_FILE;
301
+
302
+                if (strcmp($node['resourcetype'], "collection") == 0) { // we have a folder
303
+                    $type = FILES_FOLDER;
304
+                }
305
+
306
+                if ($type === FILES_FOLDER && $onlyFiles) {
307
+                    continue;
308
+                }
309
+
310
+                // Check if foldernames have a trailing slash, if not, add one!
311
+                if ($type === FILES_FOLDER && !StringUtil::endsWith($id, "/")) {
312
+                    $id .= "/";
313
+                }
314
+
315
+                $realID = $nodeIdPrefix . $id;
316
+
317
+                Logger::debug(self::LOG_CONTEXT, "parsing: " . $id . " in base: " . $nodeId);
318
+
319
+                $filename = stringToUTF8Encode(basename($id));
320
+
321
+                $size = $node['getcontentlength'] === null ? -1 : intval($node['getcontentlength']);
322
+                $size = $type == FILES_FOLDER ? -1 : $size; // folder's dont have a size
323
+
324
+                $fileid = $node['fileid'] === "-1" ? -1 : intval($node['fileid']);
325
+
326
+                $shared = false;
327
+                $sharedid = array();
328
+                if (isset($sharingInfo) && count($sharingInfo[$relNodeId]) > 0) {
329
+                    foreach ($sharingInfo[$relNodeId] as $sid => $sdetails) {
330
+                        if ($sdetails["path"] == rtrim($id, "/")) {
331
+                            $shared = true;
332
+                            $sharedid[] = $sid;
333
+                        }
334
+                    }
335
+                }
336
+
337
+                $nodeId = stringToUTF8Encode($id);
338
+                $dirName = dirname($nodeId, 1);
339
+                if ($dirName === '/') {
340
+                    $path = stringToUTF8Encode($nodeIdPrefix . $dirName);
341
+                } else {
342
+                    $path = stringToUTF8Encode($nodeIdPrefix . $dirName . '/');
343
+                }
344
+
345
+                if (!isset($node['entryid']) || !isset($node['parent_entryid']) || !isset($node['store_entryid'])) {
346
+                    $entryid = $this->createId($realID);
347
+                    $parentEntryid = $this->createId($path);
348
+                    $storeEntryid = $this->createId($nodeIdPrefix .'/');
349
+
350
+                    $dir[$id]['entryid'] = $entryid;
351
+                    $dir[$id]['parent_entryid'] = $parentEntryid;
352
+                    $dir[$id]['store_entryid'] = $storeEntryid;
353
+
354
+                    $updateCache = true;
355
+                } else {
356
+                    $entryid = $node['entryid'];
357
+                    $parentEntryid = $node['parent_entryid'];
358
+                    $storeEntryid = $node['store_entryid'];
359
+                }
360
+
361
+                $nodes[$nodeId] = array('props' =>
362
+                    array(
363
+                        'folder_id' => stringToUTF8Encode($realID),
364
+                        'fileid' => $fileid,
365
+                        'path' => $path,
366
+                        'filename' => $filename,
367
+                        'message_size' => $size,
368
+                        'lastmodified' => strtotime($node['getlastmodified']) * 1000,
369
+                        'message_class' => "IPM.Files",
370
+                        'isshared' => $shared,
371
+                        'sharedid' => $sharedid,
372
+                        'object_type' => $type,
373
+                        'type' => $type
374
+                    ),
375
+                    'entryid' => $entryid,
376
+                    'parent_entryid' => $parentEntryid,
377
+                    'store_entryid' => $storeEntryid
378
+                );
379
+            }
380
+
381
+            // Update the cache.
382
+            if ($updateCache) {
383
+                $this->setCache($accountID, $cachePath, $dir);
384
+            }
385
+        } else {
386
+            Logger::debug(self::LOG_CONTEXT, "dir was empty");
387
+        }
388
+
389
+        return $nodes;
390
+    }
391
+
392
+    /**
393
+     * This functions sorts an array of nodes.
394
+     *
395
+     * @param array $nodes array of nodes to sort
396
+     * @param array $data all parameters contained in the request
397
+     * @param boolean $navtree parse for navtree or browser
398
+     *
399
+     * @return array of sorted nodes
400
+     */
401
+    public function sortFolderContent($nodes, $data, $navtree = false)
402
+    {
403
+        $sortednodes = array();
404
+
405
+        $sortkey = "filename";
406
+        $sortdir = "ASC";
407
+
408
+        if (isset($data['sort'])) {
409
+            $sortkey = $data['sort'][0]['field'];
410
+            $sortdir = $data['sort'][0]['direction'];
411
+        }
412
+
413
+        Logger::debug(self::LOG_CONTEXT, "sorting by " . $sortkey . " in direction: " . $sortdir);
414
+
415
+        if ($navtree) {
416
+            $sortednodes = ArrayUtil::sort_by_key($nodes, $sortkey, $sortdir);
417
+        } else {
418
+            $sortednodes = ArrayUtil::sort_props_by_key($nodes, $sortkey, $sortdir);
419
+        }
420
+
421
+        return $sortednodes;
422
+    }
423
+
424
+    /**
425
+     * Deletes the selected files on the backend server
426
+     *
427
+     * @access private
428
+     * @param string $actionType name of the current action
429
+     * @param array $actionData all parameters contained in this request
430
+     * @return bool
431
+     * @throws BackendException if the backend request fails
432
+     */
433
+    private function delete($actionType, $actionData)
434
+    {
435
+        // TODO: function is duplicate of class.hierarchylistmodule.php of delete function.
436
+        $result = false;
437
+        if (isset($actionData['records']) && is_array($actionData['records'])) {
438
+            foreach ($actionData['records'] as $record) {
439
+                $nodeId = $record['folder_id'];
440
+                $relNodeId = substr($nodeId, strpos($nodeId, '/'));
441
+
442
+                $account = $this->accountFromNode($nodeId);
443
+
444
+                // initialize the backend
445
+                $initializedBackend = $this->initializeBackend($account);
446
+
447
+                $result = $initializedBackend->delete($relNodeId);
448
+                Logger::debug(self::LOG_CONTEXT, "deleted: " . $nodeId . ", worked: " . $result);
449
+
450
+                // clear the cache
451
+                $this->deleteCache($account->getId(), dirname($relNodeId));
452
+                $GLOBALS["bus"]->notify(REQUEST_ENTRYID, OBJECT_DELETE, array(
453
+                    "id"=> $nodeId,
454
+                    "folder_id"=> $nodeId,
455
+                    "entryid"=> $record['entryid'],
456
+                    "parent_entryid"=> $record["parent_entryid"],
457
+                    "store_entryid"=> $record["store_entryid"]
458
+                ));
459
+            }
460
+
461
+            $response['status'] = true;
462
+            $this->addActionData($actionType, $response);
463
+            $GLOBALS["bus"]->addData($this->getResponseData());
464
+
465
+        } else {
466
+            $nodeId = $actionData['folder_id'];
467
+
468
+            $relNodeId = substr($nodeId, strpos($nodeId, '/'));
469
+            $response = array();
470
+
471
+            $account = $this->accountFromNode($nodeId);
472
+            $accountId = $account->getId();
473
+            // initialize the backend
474
+            $initializedBackend = $this->initializeBackend($account);
475
+
476
+            try {
477
+                $result = $initializedBackend->delete($relNodeId);
478
+            } catch (\Files\Backend\Exception $e) {
479
+                // TODO: this might fails because the file was already deleted.
480
+                // fire error message if any other error occurred.
481
+                Logger::debug(self::LOG_CONTEXT, "deleted a directory that was no longer available");
482
+            }
483
+            Logger::debug(self::LOG_CONTEXT, "deleted: " . $nodeId . ", worked: " . $result);
484
+
485
+            // Get old cached data.
486
+            $cachedDir = $this->getCache($accountId, dirname($relNodeId));
487
+            if (isset($cachedDir[$relNodeId]) && !empty($cachedDir[$relNodeId])) {
488
+                // Delete the folder from cached data.
489
+                unset($cachedDir[$relNodeId]);
490
+            }
491
+
492
+            // clear the cache of parent directory.
493
+            $this->deleteCache($accountId, dirname($relNodeId));
494
+            // clear the cache of selected directory.
495
+            $this->deleteCache($accountId, rtrim($relNodeId, '/'));
496
+
497
+            // Set data in cache.
498
+            $this->setCache($accountId, dirname($relNodeId), $cachedDir);
499
+
500
+            $response['status'] = $result ? true : false;
501
+            $this->addActionData($actionType, $response);
502
+            $GLOBALS["bus"]->addData($this->getResponseData());
503
+
504
+            $GLOBALS["bus"]->notify(REQUEST_ENTRYID, OBJECT_DELETE, array(
505
+                "entryid"=> $actionData["entryid"],
506
+                "parent_entryid"=> $actionData["parent_entryid"],
507
+                "store_entryid"=> $actionData["store_entryid"]
508
+            ));
509
+        }
510
+
511
+        return true;
512
+    }
513
+
514
+    /**
515
+     * Moves the selected files on the backend server
516
+     *
517
+     * @access private
518
+     * @param string $actionType name of the current action
519
+     * @param array $actionData all parameters contained in this request
520
+     * @return bool if the backend request failed
521
+     */
522
+    private function move($actionType, $actionData)
523
+    {
524
+        $dst = rtrim($actionData['message_action']["destination_folder_id"], '/');
525
+
526
+        $overwrite = isset($actionData['message_action']["overwrite"]) ? $actionData['message_action']["overwrite"] : true;
527
+        $isFolder = isset($actionData['message_action']["isFolder"]) ? $actionData['message_action']["isFolder"] : false;
528
+
529
+        $pathPostfix = "";
530
+        if (substr($actionData['folder_id'], -1) == '/') {
531
+            $pathPostfix = "/"; // we have a folder...
532
+        }
533
+
534
+        $source = rtrim($actionData['folder_id'], '/');
535
+        $fileName = basename($source);
536
+        $destination = $dst . '/' . basename($source);
537
+
538
+        // get dst and source account ids
539
+        // currently only moving within one account is supported
540
+        $srcAccountID = substr($actionData['folder_id'], 3, (strpos($actionData['folder_id'], '/') - 3)); // parse account id from node id
541
+        $dstAccountID = substr($actionData['message_action']["destination_folder_id"], 3, (strpos($actionData['message_action']["destination_folder_id"], '/') - 3)); // parse account id from node id
542
+
543
+        if ($srcAccountID !== $dstAccountID) {
544
+            $this->sendFeedback(false, array(
545
+                'type' => ERROR_GENERAL,
546
+                'info' => array(
547
+                    'title' => _("Files Plugin"),
548
+                    'original_message' => _("Moving between accounts is not implemented"),
549
+                    'display_message' => _("Moving between accounts is not implemented")
550
+                )
551
+            ));
552
+
553
+            return false;
554
+        } else {
555
+            $relDst = substr($destination, strpos($destination, '/'));
556
+            $relSrc = substr($source, strpos($source, '/'));
557
+
558
+            $account = $this->accountFromNode($source);
559
+
560
+            // initialize the backend
561
+            $initializedBackend = $this->initializeBackend($account);
562
+
563
+            $result = $initializedBackend->move($relSrc, $relDst, $overwrite);
564
+
565
+            $actionId = $account->getId();
566
+            // clear the cache
567
+            $this->deleteCache($actionId, dirname($relDst));
568
+
569
+            $cachedFolderName = $relSrc . $pathPostfix;
570
+            $this->deleteCache($actionId, $cachedFolderName);
571
+
572
+            $cached = $this->getCache($actionId, dirname($relSrc));
573
+            $this->deleteCache($actionId, dirname($relSrc));
574
+
575
+            if (isset($cached[$cachedFolderName]) && !empty($cached[$cachedFolderName])) {
576
+                unset($cached[$cachedFolderName]);
577
+                $this->setCache($actionId, dirname($relSrc), $cached);
578
+            }
579
+
580
+            $response['status'] = !$result ? false : true;
581
+
582
+
583
+            /* create the response object */
584
+            $folder = array(
585
+                'props' =>
586
+                    array(
587
+                        'folder_id' => ($destination . $pathPostfix),
588
+                        'path' => $actionData['message_action']["destination_folder_id"],
589
+                        'filename' => $fileName,
590
+                        'display_name' => $fileName,
591
+                        'object_type' => $isFolder ? FILES_FOLDER : FILES_FILE,
592
+                        'deleted' => !$result ? false : true
593
+                    ),
594
+                'entryid' => $this->createId($destination . $pathPostfix),
595
+                'store_entryid' => $actionData['store_entryid'],
596
+                'parent_entryid' => $actionData['message_action']['parent_entryid']
597
+            );
598
+
599
+            $response['item'] = $folder;
600
+
601
+            $this->addActionData("update", $response);
602
+            $GLOBALS["bus"]->addData($this->getResponseData());
603
+
604
+            // Notify hierarchy only when folder was moved.
605
+            if ($isFolder) {
606
+                // Send notification to delete folder node in hierarchy.
607
+                $GLOBALS["bus"]->notify(REQUEST_ENTRYID, OBJECT_DELETE, array(
608
+                    "entryid"=> $actionData["entryid"],
609
+                    "parent_entryid"=> $actionData["parent_entryid"],
610
+                    "store_entryid"=> $actionData["store_entryid"]
611
+                ));
612
+
613
+                // Send notification to create new folder node in hierarchy.
614
+                $GLOBALS["bus"]->notify(REQUEST_ENTRYID, OBJECT_SAVE, $folder);
615
+            }
616
+        }
617
+
618
+        return true;
619
+    }
620
+
621
+    /**
622
+     * Renames the selected file on the backend server
623
+     *
624
+     * @access private
625
+     * @param string $actionType name of the current action
626
+     * @param array $actionData all parameters contained in this request
627
+     * @return bool
628
+     * @throws BackendException if the backend request fails
629
+     */
630
+    function rename($actionType, $actionData)
631
+    {
632
+        $messageProps = $this->save($actionData);
633
+        $notifySubFolders = isset($actionData['message_action']['isFolder']) ? $actionData['message_action']['isFolder'] : true;
634
+        if(!empty($messageProps)) {
635
+            $GLOBALS["bus"]->notify(REQUEST_ENTRYID, OBJECT_SAVE, $messageProps);
636
+            if ($notifySubFolders) {
637
+                $this->notifySubFolders($messageProps["props"]["folder_id"]);
638
+            }
639
+        }
640
+    }
641
+
642
+    /**
643
+     * Check if given filename or folder already exists on server
644
+     *
645
+     * @access private
646
+     * @param array $records which needs to be check for existence.
647
+     * @param array $destination where the given records needs to be moved, uploaded, or renamed.
648
+     * @throws BackendException if the backend request fails
649
+     *
650
+     * @return boolean True if duplicate found, false otherwise
651
+     */
652
+    private function checkIfExists($records, $destination)
653
+    {
654
+        $duplicate = false;
655
+
656
+        if (isset($records) && is_array($records)) {
657
+            if (!isset($destination) || $destination == false) {
658
+                $destination = reset($records);
659
+                $destination = $destination["id"]; // we can only check files in the same folder, so one request will be enough
660
+                Logger::debug(self::LOG_CONTEXT, "Resetting destination to check.");
661
+            }
662
+            Logger::debug(self::LOG_CONTEXT, "Checking: " . $destination);
663
+            $account = $this->accountFromNode($destination);
664
+
665
+            // initialize the backend
666
+            $initializedBackend = $this->initializeBackend($account);
667
+
668
+            $relDirname = substr($destination, strpos($destination, '/'));
669
+            Logger::debug(self::LOG_CONTEXT, "Getting content for: " . $relDirname);
670
+            try {
671
+                $lsdata = $initializedBackend->ls($relDirname); // we can only check files in the same folder, so one request will be enough
672
+            } catch (Exception $e) {
673
+                // ignore - if file not found -> does not exist :)
674
+            }
675
+            if (isset($lsdata) && is_array($lsdata)) {
676
+                foreach ($records as $record) {
677
+                    $relRecId = substr($record["id"], strpos($record["id"], '/'));
678
+                    Logger::debug(self::LOG_CONTEXT, "Checking rec: " . $relRecId, "Core");
679
+                    foreach ($lsdata as $argsid => $args) {
680
+                        if (strcmp($args['resourcetype'], "collection") == 0 && $record["isFolder"] && strcmp(basename($argsid), basename($relRecId)) == 0) { // we have a folder
681
+                            Logger::debug(self::LOG_CONTEXT, "Duplicate folder found: " . $argsid, "Core");
682
+                            $duplicate = true;
683
+                            break;
684
+                        } else {
685
+                            if (strcmp($args['resourcetype'], "collection") != 0 && !$record["isFolder"] && strcmp(basename($argsid), basename($relRecId)) == 0) {
686
+                                Logger::debug(self::LOG_CONTEXT, "Duplicate file found: " . $argsid, "Core");
687
+                                $duplicate = true;
688
+                                break;
689
+                            } else {
690
+                                $duplicate = false;
691
+                            }
692
+                        }
693
+                    }
694
+
695
+                    if ($duplicate) {
696
+                        Logger::debug(self::LOG_CONTEXT, "Duplicate entry: " . $relRecId, "Core");
697
+                        break;
698
+                    }
699
+                }
700
+            }
701
+        }
702
+
703
+        return $duplicate;
704
+    }
705
+
706
+    /**
707
+     * Downloads file from the Files service and saves it in tmp
708
+     * folder with unique name
709
+     *
710
+     * @access private
711
+     * @param array $actionData
712
+     * @throws BackendException if the backend request fails
713
+     *
714
+     * @return void
715
+     */
716
+    private function downloadSelectedFilesToTmp($actionType, $actionData)
717
+    {
718
+        $ids = $actionData['ids'];
719
+        $dialogAttachmentId = $actionData['dialog_attachments'];
720
+        $response = array();
721
+
722
+        $attachment_state = new AttachmentState();
723
+        $attachment_state->open();
724
+
725
+        $account = $this->accountFromNode($ids[0]);
726
+
727
+        // initialize the backend
728
+        $initializedBackend = $this->initializeBackend($account);
729
+
730
+        foreach ($ids as $file) {
731
+            $filename = basename($file);
732
+            $tmpname = $attachment_state->getAttachmentTmpPath($filename);
733
+
734
+            // download file from the backend
735
+            $relRecId = substr($file, strpos($file, '/'));
736
+            $http_status = $initializedBackend->get_file($relRecId, $tmpname);
737
+
738
+            $filesize = filesize($tmpname);
739
+
740
+            Logger::debug(self::LOG_CONTEXT, "Downloading: " . $filename . " to: " . $tmpname);
741
+
742
+            $attach_id = uniqid();
743
+            $response['items'][] = array(
744
+                'name' => $filename,
745
+                'size' => $filesize,
746
+                "attach_id" => $attach_id,
747
+                'tmpname' => PathUtil::getFilenameFromPath($tmpname)
748
+            );
749
+
750
+            $attachment_state->addAttachmentFile($dialogAttachmentId, PathUtil::getFilenameFromPath($tmpname), Array(
751
+                "name" => $filename,
752
+                "size" => $filesize,
753
+                "type" => PathUtil::get_mime($tmpname),
754
+                "attach_id" => $attach_id,
755
+                "sourcetype" => 'default'
756
+            ));
757
+
758
+            Logger::debug(self::LOG_CONTEXT, "filesize: " . $filesize);
759
+        }
760
+
761
+        $attachment_state->close();
762
+        $response['status'] = true;
763
+        $this->addActionData($actionType, $response);
764
+        $GLOBALS["bus"]->addData($this->getResponseData());
765
+    }
766
+
767
+    /**
768
+     * upload the tempfile to files
769
+     *
770
+     * @access private
771
+     * @param array $actionData
772
+     * @throws BackendException if the backend request fails
773
+     *
774
+     * @return void
775
+     */
776
+    private function uploadToBackend($actionType, $actionData)
777
+    {
778
+        Logger::debug(self::LOG_CONTEXT, "preparing attachment");
779
+
780
+        $account = $this->accountFromNode($actionData["destdir"]);
781
+
782
+        // initialize the backend
783
+        $initializedBackend = $this->initializeBackend($account);
784
+
785
+        $result = true;
786
+
787
+        if ($actionData["type"] === "attachment") {
788
+            foreach ($actionData["items"] as $item) {
789
+                list($tmpname, $filename) = $this->prepareAttachmentForUpload($item);
790
+
791
+                $dirName = substr($actionData["destdir"], strpos($actionData["destdir"], '/'));
792
+                $filePath = $dirName . $filename;
793
+
794
+                Logger::debug(self::LOG_CONTEXT, "Uploading to: " . $filePath . " tmpfile: " . $tmpname);
795
+
796
+                $result = $result && $initializedBackend->put_file($filePath, $tmpname);
797
+                unlink($tmpname);
798
+
799
+                $this->updateDirCache($initializedBackend, $dirName, $filePath, $actionData);
800
+            }
801
+        } elseif ($actionData["type"] === "mail") {
802
+            foreach ($actionData["items"] as $item) {
803
+                list($tmpname, $filename) = $this->prepareEmailForUpload($item);
804
+
805
+                $dirName = substr($actionData["destdir"], strpos($actionData["destdir"], '/'));
806
+                $filePath = $dirName . $filename;
807
+
808
+                Logger::debug(self::LOG_CONTEXT, "Uploading to: " . $filePath . " tmpfile: " . $tmpname);
809
+
810
+                $result = $result && $initializedBackend->put_file($filePath, $tmpname);
811
+                unlink($tmpname);
812
+
813
+                $this->updateDirCache($initializedBackend, $dirName, $filePath, $actionData);
814
+            }
815
+        } else {
816
+            $this->sendFeedback(false, array(
817
+                'type' => ERROR_GENERAL,
818
+                'info' => array(
819
+                    'title' => _("Files plugin"),
820
+                    'original_message' => _("Unknown type - cannot save this file to the Files backend!"),
821
+                    'display_message' => _("Unknown type - cannot save this file to the Files backend!")
822
+                )
823
+            ));
824
+        }
825
+
826
+        $response = array();
827
+        $response['status'] = $result;
828
+        $this->addActionData($actionType, $response);
829
+        $GLOBALS["bus"]->addData($this->getResponseData());
830
+    }
831
+
832
+    /**
833
+     * Update the cache of selected directory
834
+     *
835
+     * @param Files\Backend\AbstractBackend $backendInstance
836
+     * @param string $dirName The directory name
837
+     * @param $filePath The file path.
838
+     * @param $actionData The action data.
839
+     * @throws BackendException
840
+     */
841
+    function updateDirCache($backendInstance, $dirName, $filePath, $actionData)
842
+    {
843
+        $cachePath = rtrim($dirName, '/');
844
+        if ($cachePath === "") {
845
+            $cachePath = "/";
846
+        }
847
+
848
+        $dir = $backendInstance->ls($cachePath);
849
+        $accountID = $this->accountIDFromNode($actionData["destdir"]);
850
+        $cacheDir = $this->getCache($accountID, $cachePath);
851
+        $cacheDir[$filePath] = $dir[$filePath];
852
+        $this->setCache($accountID, $cachePath, $cacheDir);
853
+    }
854
+
855
+    /**
856
+     * This function will prepare an attachment for the upload to the backend.
857
+     * It will store the attachment to the TMP folder and return its temporary
858
+     * path and filename as array.
859
+     *
860
+     * @param $items
861
+     * @return array (tmpname, filename) or false on error
862
+     * @access private
863
+     */
864
+    private function prepareAttachmentForUpload($item)
865
+    {
866
+        // Check which type isset
867
+        $openType = "attachment";
868
+
869
+        // Get store id
870
+        $storeid = false;
871
+        if (isset($item["store"])) {
872
+            $storeid = $item["store"];
873
+        }
874
+
875
+        // Get message entryid
876
+        $entryid = false;
877
+        if (isset($item["entryid"])) {
878
+            $entryid = $item["entryid"];
879
+        }
880
+
881
+        // Get number of attachment which should be opened.
882
+        $attachNum = false;
883
+        if (isset($item["attachNum"])) {
884
+            $attachNum = $item["attachNum"];
885
+        }
886
+
887
+        $tmpname = "";
888
+        $filename = "";
889
+
890
+        // Check if storeid and entryid isset
891
+        if ($storeid && $entryid) {
892
+            // Open the store
893
+            $store = $GLOBALS["mapisession"]->openMessageStore(hex2bin($storeid));
894
+
895
+            if ($store) {
896
+                // Open the message
897
+                $message = mapi_msgstore_openentry($store, hex2bin($entryid));
898
+
899
+                if ($message) {
900
+                    $attachment = false;
901
+
902
+                    // Check if attachNum isset
903
+                    if ($attachNum) {
904
+                        // Loop through the attachNums, message in message in message ...
905
+                        for ($i = 0; $i < (count($attachNum) - 1); $i++) {
906
+                            // Open the attachment
907
+                            $tempattach = mapi_message_openattach($message, (int)$attachNum[$i]);
908
+                            if ($tempattach) {
909
+                                // Open the object in the attachment
910
+                                $message = mapi_attach_openobj($tempattach);
911
+                            }
912
+                        }
913
+
914
+                        // Open the attachment
915
+                        $attachment = mapi_message_openattach($message, (int)$attachNum[(count($attachNum) - 1)]);
916
+                    }
917
+
918
+                    // Check if the attachment is opened
919
+                    if ($attachment) {
920
+
921
+                        // Get the props of the attachment
922
+                        $props = mapi_attach_getprops($attachment, array(PR_ATTACH_LONG_FILENAME, PR_ATTACH_MIME_TAG, PR_DISPLAY_NAME, PR_ATTACH_METHOD));
923
+                        // Content Type
924
+                        $contentType = "application/octet-stream";
925
+                        // Filename
926
+                        $filename = "ERROR";
927
+
928
+                        // Set filename
929
+                        if (isset($props[PR_ATTACH_LONG_FILENAME])) {
930
+                            $filename = PathUtil::sanitizeFilename($props[PR_ATTACH_LONG_FILENAME]);
931
+                        } else {
932
+                            if (isset($props[PR_ATTACH_FILENAME])) {
933
+                                $filename = PathUtil::sanitizeFilename($props[PR_ATTACH_FILENAME]);
934
+                            } else {
935
+                                if (isset($props[PR_DISPLAY_NAME])) {
936
+                                    $filename = PathUtil::sanitizeFilename($props[PR_DISPLAY_NAME]);
937
+                                }
938
+                            }
939
+                        }
940
+
941
+                        // Set content type
942
+                        if (isset($props[PR_ATTACH_MIME_TAG])) {
943
+                            $contentType = $props[PR_ATTACH_MIME_TAG];
944
+                        } else {
945
+                            // Parse the extension of the filename to get the content type
946
+                            if (strrpos($filename, ".") !== false) {
947
+                                $extension = strtolower(substr($filename, strrpos($filename, ".")));
948
+                                $contentType = "application/octet-stream";
949
+                                if (is_readable("mimetypes.dat")) {
950
+                                    $fh = fopen("mimetypes.dat", "r");
951
+                                    $ext_found = false;
952
+                                    while (!feof($fh) && !$ext_found) {
953
+                                        $line = fgets($fh);
954
+                                        preg_match("/(\.[a-z0-9]+)[ \t]+([^ \t\n\r]*)/i", $line, $result);
955
+                                        if ($extension == $result[1]) {
956
+                                            $ext_found = true;
957
+                                            $contentType = $result[2];
958
+                                        }
959
+                                    }
960
+                                    fclose($fh);
961
+                                }
962
+                            }
963
+                        }
964
+
965
+
966
+                        $tmpname = tempnam(TMP_PATH, stripslashes($filename));
967
+
968
+                        // Open a stream to get the attachment data
969
+                        $stream = mapi_openproperty($attachment, PR_ATTACH_DATA_BIN, IID_IStream, 0, 0);
970
+                        $stat = mapi_stream_stat($stream);
971
+                        // File length =  $stat["cb"]
972
+
973
+                        Logger::debug(self::LOG_CONTEXT, "filesize: " . $stat["cb"]);
974
+
975
+                        $fhandle = fopen($tmpname, 'w');
976
+                        $buffer = null;
977
+                        for ($i = 0; $i < $stat["cb"]; $i += BLOCK_SIZE) {
978
+                            // Write stream
979
+                            $buffer = mapi_stream_read($stream, BLOCK_SIZE);
980
+                            fwrite($fhandle, $buffer, strlen($buffer));
981
+                        }
982
+                        fclose($fhandle);
983
+
984
+                        Logger::debug(self::LOG_CONTEXT, "temp attachment written to " . $tmpname);
985
+
986
+                        return array($tmpname, $filename);
987
+                    }
988
+                }
989
+            } else {
990
+                Logger::error(self::LOG_CONTEXT, "store could not be opened");
991
+            }
992
+        } else {
993
+            Logger::error(self::LOG_CONTEXT, "wrong call, store and entryid have to be set");
994
+        }
995
+
996
+        return false;
997
+    }
998
+
999
+    /**
1000
+     * Store the email as eml to a temporary directory and return its temporary filename.
1001
+     *
1002
+     * @param {string} $actionType
1003
+     * @param {array} $actionData
1004
+     * @return array (tmpname, filename) or false on error
1005
+     * @access private
1006
+     */
1007
+    private function prepareEmailForUpload($item)
1008
+    {
1009
+        // Get store id
1010
+        $storeid = false;
1011
+        if (isset($item["store"])) {
1012
+            $storeid = $item["store"];
1013
+        }
1014
+
1015
+        // Get message entryid
1016
+        $entryid = false;
1017
+        if (isset($item["entryid"])) {
1018
+            $entryid = $item["entryid"];
1019
+        }
1020
+
1021
+        $tmpname = "";
1022
+        $filename = "";
1023
+
1024
+        $store = $GLOBALS['mapisession']->openMessageStore(hex2bin($storeid));
1025
+        $message = mapi_msgstore_openentry($store, hex2bin($entryid));
1026
+
1027
+        // Decode smime signed messages on this message
1028
+        parse_smime($store, $message);
1029
+
1030
+        if ($message && $store) {
1031
+            // get message properties.
1032
+            $messageProps = mapi_getprops($message, array(PR_SUBJECT, PR_EC_IMAP_EMAIL, PR_MESSAGE_CLASS));
1033
+
1034
+            $isSupportedMessage = (
1035
+                (stripos($messageProps[PR_MESSAGE_CLASS], 'IPM.Note') === 0)
1036
+                || (stripos($messageProps[PR_MESSAGE_CLASS], 'Report.IPM.Note') === 0)
1037
+                || (stripos($messageProps[PR_MESSAGE_CLASS], 'IPM.Schedule') === 0)
1038
+            );
1039
+
1040
+            if ($isSupportedMessage) {
1041
+                // If RFC822-formatted stream is already available in PR_EC_IMAP_EMAIL property
1042
+                // than directly use it, generate otherwise.
1043
+                if (isset($messageProps[PR_EC_IMAP_EMAIL]) || propIsError(PR_EC_IMAP_EMAIL, $messageProps) == MAPI_E_NOT_ENOUGH_MEMORY) {
1044
+                    // Stream the message to properly get the PR_EC_IMAP_EMAIL property
1045
+                    $stream = mapi_openproperty($message, PR_EC_IMAP_EMAIL, IID_IStream, 0, 0);
1046
+                } else {
1047
+                    // Get addressbook for current session
1048
+                    $addrBook = $GLOBALS['mapisession']->getAddressbook();
1049
+
1050
+                    // Read the message as RFC822-formatted e-mail stream.
1051
+                    $stream = mapi_inetmapi_imtoinet($GLOBALS['mapisession']->getSession(), $addrBook, $message, array());
1052
+                }
1053
+
1054
+                if (!empty($messageProps[PR_SUBJECT])) {
1055
+                    $filename = PathUtil::sanitizeFilename($messageProps[PR_SUBJECT]) . '.eml';
1056
+                } else {
1057
+                    $filename = _('Untitled') . '.eml';
1058
+                }
1059
+
1060
+                $tmpname = tempnam(TMP_PATH, "email2filez");
1061
+
1062
+                // Set the file length
1063
+                $stat = mapi_stream_stat($stream);
1064
+
1065
+                $fhandle = fopen($tmpname, 'w');
1066
+                $buffer = null;
1067
+                for ($i = 0; $i < $stat["cb"]; $i += BLOCK_SIZE) {
1068
+                    // Write stream
1069
+                    $buffer = mapi_stream_read($stream, BLOCK_SIZE);
1070
+                    fwrite($fhandle, $buffer, strlen($buffer));
1071
+                }
1072
+                fclose($fhandle);
1073
+
1074
+                return array($tmpname, $filename);
1075
+            }
1076
+        }
1077
+
1078
+        return false;
1079
+    }
1080
+
1081
+    /**
1082
+     * Get sharing information from the backend.
1083
+     *
1084
+     * @param $actionType
1085
+     * @param $actionData
1086
+     * @return bool
1087
+     */
1088
+    private function getSharingInformation($actionType, $actionData)
1089
+    {
1090
+        $response = array();
1091
+        $records = $actionData["records"];
1092
+
1093
+        if (count($records) < 1) {
1094
+            $this->sendFeedback(false, array(
1095
+                'type' => ERROR_GENERAL,
1096
+                'info' => array(
1097
+                    'title' => _("Files Plugin"),
1098
+                    'original_message' => _("No record given!"),
1099
+                    'display_message' => _("No record given!")
1100
+                )
1101
+            ));
1102
+        }
1103
+
1104
+        $account = $this->accountFromNode($records[0]);
1105
+
1106
+        // initialize the backend
1107
+        $initializedBackend = $this->initializeBackend($account);
1108
+
1109
+        $relRecords = array();
1110
+        foreach ($records as $record) {
1111
+            $relRecords[] = substr($record, strpos($record, '/')); // remove account id
1112
+        }
1113
+
1114
+        try {
1115
+            $sInfo = $initializedBackend->sharingDetails($relRecords);
1116
+        } catch (Exception $e) {
1117
+            $response['status'] = false;
1118
+            $response['header'] = _('Fetching sharing information failed');
1119
+            $response['message'] = $e->getMessage();
1120
+            $this->addActionData("error", $response);
1121
+            $GLOBALS["bus"]->addData($this->getResponseData());
1122
+
1123
+            return false;
1124
+        }
1125
+
1126
+        $sharingInfo = array();
1127
+        foreach ($sInfo as $path => $details) {
1128
+            $realPath = "#R#" . $account->getId() . $path;
1129
+            $sharingInfo[$realPath] = $details; // add account id again
1130
+        }
1131
+
1132
+        $response['status'] = true;
1133
+        $response['shares'] = $sharingInfo;
1134
+        $this->addActionData($actionType, $response);
1135
+        $GLOBALS["bus"]->addData($this->getResponseData());
1136
+
1137
+        return true;
1138
+    }
1139
+
1140
+    /**
1141
+     * Create a new share.
1142
+     *
1143
+     * @param $actionType
1144
+     * @param $actionData
1145
+     * @return bool
1146
+     */
1147
+    private function createNewShare($actionType, $actionData)
1148
+    {
1149
+        $records = $actionData["records"];
1150
+        $shareOptions = $actionData["options"];
1151
+
1152
+        if (count($records) < 1) {
1153
+            $this->sendFeedback(false, array(
1154
+                'type' => ERROR_GENERAL,
1155
+                'info' => array(
1156
+                    'title' => _("Files Plugin"),
1157
+                    'original_message' => _("No record given!"),
1158
+                    'display_message' => _("No record given!")
1159
+                )
1160
+            ));
1161
+        }
1162
+
1163
+        $account = $this->accountFromNode($records[0]);
1164
+
1165
+        // initialize the backend
1166
+        $initializedBackend = $this->initializeBackend($account);
1167
+
1168
+        $sharingRecords = array();
1169
+        foreach ($records as $record) {
1170
+            $path = substr($record, strpos($record, '/')); // remove account id
1171
+            $sharingRecords[$path] = $shareOptions; // add options
1172
+        }
1173
+
1174
+        try {
1175
+            $sInfo = $initializedBackend->share($sharingRecords);
1176
+        } catch (Exception $e) {
1177
+            $response['status'] = false;
1178
+            $response['header'] = _('Sharing failed');
1179
+            $response['message'] = $e->getMessage();
1180
+            $this->addActionData("error", $response);
1181
+            $GLOBALS["bus"]->addData($this->getResponseData());
1182
+
1183
+            return false;
1184
+        }
1185
+
1186
+        $sharingInfo = array();
1187
+        foreach ($sInfo as $path => $details) {
1188
+            $realPath = "#R#" . $account->getId() . $path;
1189
+            $sharingInfo[$realPath] = $details; // add account id again
1190
+        }
1191
+
1192
+        $response = array();
1193
+        $response['status'] = true;
1194
+        $response['shares'] = $sharingInfo;
1195
+        $this->addActionData($actionType, $response);
1196
+        $GLOBALS["bus"]->addData($this->getResponseData());
1197
+
1198
+        return true;
1199
+    }
1200
+
1201
+    /**
1202
+     * Update a existing share.
1203
+     * @param $actionType
1204
+     * @param $actionData
1205
+     * @return bool
1206
+     */
1207
+    private function updateExistingShare($actionType, $actionData)
1208
+    {
1209
+        $records = $actionData["records"];
1210
+        $accountID = $actionData["accountid"];
1211
+        $shareOptions = $actionData["options"];
1212
+
1213
+        if (count($records) < 1) {
1214
+            $this->sendFeedback(false, array(
1215
+                'type' => ERROR_GENERAL,
1216
+                'info' => array(
1217
+                    'title' => _("Files Plugin"),
1218
+                    'original_message' => _("No record given!"),
1219
+                    'display_message' => _("No record given!")
1220
+                )
1221
+            ));
1222
+        }
1223
+
1224
+        $account = $this->accountStore->getAccount($accountID);
1225
+
1226
+        // initialize the backend
1227
+        $initializedBackend = $this->initializeBackend($account);
1228
+
1229
+        $sharingRecords = array();
1230
+        foreach ($records as $record) {
1231
+            $sharingRecords[$record] = $shareOptions; // add options
1232
+        }
1233
+
1234
+        try {
1235
+            $sInfo = $initializedBackend->share($sharingRecords, true);
1236
+        } catch (Exception $e) {
1237
+            $response['status'] = false;
1238
+            $response['header'] = _('Updating share failed');
1239
+            $response['message'] = $e->getMessage();
1240
+            $this->addActionData("error", $response);
1241
+            $GLOBALS["bus"]->addData($this->getResponseData());
1242
+
1243
+            return false;
1244
+        }
1245
+
1246
+        $response = array();
1247
+        $response['status'] = true;
1248
+        $response['shares'] = $sInfo;
1249
+        $this->addActionData($actionType, $response);
1250
+        $GLOBALS["bus"]->addData($this->getResponseData());
1251
+
1252
+        return true;
1253
+    }
1254
+
1255
+    /**
1256
+     * Delete one or more shares.
1257
+     * @param $actionType
1258
+     * @param $actionData
1259
+     * @return bool
1260
+     */
1261
+    private function deleteExistingShare($actionType, $actionData)
1262
+    {
1263
+        $records = $actionData["records"];
1264
+        $accountID = $actionData["accountid"];
1265
+
1266
+        if (count($records) < 1) {
1267
+            $this->sendFeedback(false, array(
1268
+                'type' => ERROR_GENERAL,
1269
+                'info' => array(
1270
+                    'title' => _("Files Plugin"),
1271
+                    'original_message' => _("No record given!"),
1272
+                    'display_message' => _("No record given!")
1273
+                )
1274
+            ));
1275
+        }
1276
+
1277
+        $account = $this->accountStore->getAccount($accountID);
1278
+
1279
+        // initialize the backend
1280
+        $initializedBackend = $this->initializeBackend($account);
1281
+
1282
+        try {
1283
+            $sInfo = $initializedBackend->unshare($records);
1284
+        } catch (Exception $e) {
1285
+            $response['status'] = false;
1286
+            $response['header'] = _('Deleting share failed');
1287
+            $response['message'] = $e->getMessage();
1288
+            $this->addActionData("error", $response);
1289
+            $GLOBALS["bus"]->addData($this->getResponseData());
1290
+
1291
+            return false;
1292
+        }
1293
+
1294
+        $response = array();
1295
+        $response['status'] = true;
1296
+        $this->addActionData($actionType, $response);
1297
+        $GLOBALS["bus"]->addData($this->getResponseData());
1298
+
1299
+        return true;
1300
+    }
1301
+
1302
+    /**
1303
+     * Function will use to update the cache
1304
+     *
1305
+     * @param string $actionType name of the current action
1306
+     * @param array $actionData all parameters contained in this request
1307
+     *
1308
+     * @return boolean true on success or false on failure.
1309
+     */
1310
+    function updateCache($actionType, $actionData)
1311
+    {
1312
+        $nodeId = $actionData['id'];
1313
+        $accountID = $this->accountIDFromNode($nodeId);
1314
+        $account = $this->accountStore->getAccount($accountID);
1315
+        // initialize the backend
1316
+        $initializedBackend = $this->initializeBackend($account, true);
1317
+        $relNodeId = substr($nodeId, strpos($nodeId, '/'));
1318
+
1319
+        // remove the trailing slash for the cache key
1320
+        $cachePath = rtrim($relNodeId, '/');
1321
+        if ($cachePath === "") {
1322
+            $cachePath = "/";
1323
+        }
1324
+        $dir = $initializedBackend->ls($relNodeId);
1325
+        $this->setCache($accountID, $cachePath, $dir);
1326
+
1327
+        $response = array();
1328
+        $response['status'] = true;
1329
+        $this->addActionData($actionType, $response);
1330
+        $GLOBALS["bus"]->addData($this->getResponseData());
1331
+
1332
+        return true;
1333
+    }
1334 1334
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -345,7 +345,7 @@  discard block
 block discarded – undo
345 345
 				if (!isset($node['entryid']) || !isset($node['parent_entryid']) || !isset($node['store_entryid'])) {
346 346
 					$entryid = $this->createId($realID);
347 347
 					$parentEntryid = $this->createId($path);
348
-					$storeEntryid = $this->createId($nodeIdPrefix .'/');
348
+					$storeEntryid = $this->createId($nodeIdPrefix . '/');
349 349
 
350 350
 					$dir[$id]['entryid'] = $entryid;
351 351
 					$dir[$id]['parent_entryid'] = $parentEntryid;
@@ -631,7 +631,7 @@  discard block
 block discarded – undo
631 631
 	{
632 632
 		$messageProps = $this->save($actionData);
633 633
 		$notifySubFolders = isset($actionData['message_action']['isFolder']) ? $actionData['message_action']['isFolder'] : true;
634
-		if(!empty($messageProps)) {
634
+		if (!empty($messageProps)) {
635 635
 			$GLOBALS["bus"]->notify(REQUEST_ENTRYID, OBJECT_SAVE, $messageProps);
636 636
 			if ($notifySubFolders) {
637 637
 				$this->notifySubFolders($messageProps["props"]["folder_id"]);
@@ -904,7 +904,7 @@  discard block
 block discarded – undo
904 904
 						// Loop through the attachNums, message in message in message ...
905 905
 						for ($i = 0; $i < (count($attachNum) - 1); $i++) {
906 906
 							// Open the attachment
907
-							$tempattach = mapi_message_openattach($message, (int)$attachNum[$i]);
907
+							$tempattach = mapi_message_openattach($message, (int) $attachNum[$i]);
908 908
 							if ($tempattach) {
909 909
 								// Open the object in the attachment
910 910
 								$message = mapi_attach_openobj($tempattach);
@@ -912,7 +912,7 @@  discard block
 block discarded – undo
912 912
 						}
913 913
 
914 914
 						// Open the attachment
915
-						$attachment = mapi_message_openattach($message, (int)$attachNum[(count($attachNum) - 1)]);
915
+						$attachment = mapi_message_openattach($message, (int) $attachNum[(count($attachNum) - 1)]);
916 916
 					}
917 917
 
918 918
 					// Check if the attachment is opened
Please login to merge, or discard this patch.
plugins/files/php/notifiers/class.fileshierarchynotifier.php 2 patches
Indentation   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -7,35 +7,35 @@
 block discarded – undo
7 7
  */
8 8
 class FilesHierarchyNotifier extends Notifier
9 9
 {
10
-	/**
11
-	 * @return Number the event which this module handles.
12
-	 */
13
-	public function getEvents()
14
-	{
15
-		return OBJECT_DELETE | OBJECT_SAVE;
16
-	}
10
+    /**
11
+     * @return Number the event which this module handles.
12
+     */
13
+    public function getEvents()
14
+    {
15
+        return OBJECT_DELETE | OBJECT_SAVE;
16
+    }
17 17
 
18
-	/**
19
-	 * If an event elsewhere has occurred, it enters in this method. This method
20
-	 * executes one ore more actions, depends on the event.
21
-	 * @param int $event Event.
22
-	 * @param string $entryid Entryid.
23
-	 * @param array $data array of data.
24
-	 */
25
-	public function update($event, $entryid, $props)
26
-	{
27
-		switch ($event) {
28
-			case OBJECT_DELETE:
29
-				$props["folderdelete"] = 1;
30
-				$this->addNotificationActionData("folders", array( "item" => array($props)));
31
-				$GLOBALS["bus"]->addData($this->createNotificationResponseData());
32
-				break;
33
-			case OBJECT_SAVE:
34
-				$this->addNotificationActionData("folders", array( "item" => $props));
35
-				$GLOBALS["bus"]->addData($this->createNotificationResponseData());
36
-				break;
37
-		}
38
-	}
18
+    /**
19
+     * If an event elsewhere has occurred, it enters in this method. This method
20
+     * executes one ore more actions, depends on the event.
21
+     * @param int $event Event.
22
+     * @param string $entryid Entryid.
23
+     * @param array $data array of data.
24
+     */
25
+    public function update($event, $entryid, $props)
26
+    {
27
+        switch ($event) {
28
+            case OBJECT_DELETE:
29
+                $props["folderdelete"] = 1;
30
+                $this->addNotificationActionData("folders", array( "item" => array($props)));
31
+                $GLOBALS["bus"]->addData($this->createNotificationResponseData());
32
+                break;
33
+            case OBJECT_SAVE:
34
+                $this->addNotificationActionData("folders", array( "item" => $props));
35
+                $GLOBALS["bus"]->addData($this->createNotificationResponseData());
36
+                break;
37
+        }
38
+    }
39 39
 }
40 40
 
41 41
 ?>
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -27,11 +27,11 @@
 block discarded – undo
27 27
 		switch ($event) {
28 28
 			case OBJECT_DELETE:
29 29
 				$props["folderdelete"] = 1;
30
-				$this->addNotificationActionData("folders", array( "item" => array($props)));
30
+				$this->addNotificationActionData("folders", array("item" => array($props)));
31 31
 				$GLOBALS["bus"]->addData($this->createNotificationResponseData());
32 32
 				break;
33 33
 			case OBJECT_SAVE:
34
-				$this->addNotificationActionData("folders", array( "item" => $props));
34
+				$this->addNotificationActionData("folders", array("item" => $props));
35 35
 				$GLOBALS["bus"]->addData($this->createNotificationResponseData());
36 36
 				break;
37 37
 		}
Please login to merge, or discard this patch.
plugins/files/php/notifiers/class.filesbrowsernotifier.php 2 patches
Indentation   +27 added lines, -27 removed lines patch added patch discarded remove patch
@@ -7,34 +7,34 @@
 block discarded – undo
7 7
  */
8 8
 class FilesBrowserNotifier extends Notifier
9 9
 {
10
-	/**
11
-	 * @return Number the event which this module handles.
12
-	 */
13
-	public function getEvents()
14
-	{
15
-		return OBJECT_DELETE | OBJECT_SAVE;
16
-	}
10
+    /**
11
+     * @return Number the event which this module handles.
12
+     */
13
+    public function getEvents()
14
+    {
15
+        return OBJECT_DELETE | OBJECT_SAVE;
16
+    }
17 17
 
18
-	/**
19
-	 * If an event elsewhere has occurred, it enters in this method. This method
20
-	 * executes one ore more actions, depends on the event.
21
-	 * @param int $event Event.
22
-	 * @param string $entryid Entryid.
23
-	 * @param array $data array of data.
24
-	 */
25
-	public function update($event, $entryid, $props)
26
-	{
27
-		switch ($event) {
28
-			case OBJECT_DELETE:
29
-				$this->addNotificationActionData("delete", array( "item" => array($props)));
30
-				$GLOBALS["bus"]->addData($this->createNotificationResponseData());
31
-				break;
32
-			case OBJECT_SAVE:
33
-				$this->addNotificationActionData("update", array( "item" => array($props)));
34
-				$GLOBALS["bus"]->addData($this->createNotificationResponseData());
35
-				break;
36
-		}
37
-	}
18
+    /**
19
+     * If an event elsewhere has occurred, it enters in this method. This method
20
+     * executes one ore more actions, depends on the event.
21
+     * @param int $event Event.
22
+     * @param string $entryid Entryid.
23
+     * @param array $data array of data.
24
+     */
25
+    public function update($event, $entryid, $props)
26
+    {
27
+        switch ($event) {
28
+            case OBJECT_DELETE:
29
+                $this->addNotificationActionData("delete", array( "item" => array($props)));
30
+                $GLOBALS["bus"]->addData($this->createNotificationResponseData());
31
+                break;
32
+            case OBJECT_SAVE:
33
+                $this->addNotificationActionData("update", array( "item" => array($props)));
34
+                $GLOBALS["bus"]->addData($this->createNotificationResponseData());
35
+                break;
36
+        }
37
+    }
38 38
 }
39 39
 
40 40
 ?>
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -26,11 +26,11 @@
 block discarded – undo
26 26
 	{
27 27
 		switch ($event) {
28 28
 			case OBJECT_DELETE:
29
-				$this->addNotificationActionData("delete", array( "item" => array($props)));
29
+				$this->addNotificationActionData("delete", array("item" => array($props)));
30 30
 				$GLOBALS["bus"]->addData($this->createNotificationResponseData());
31 31
 				break;
32 32
 			case OBJECT_SAVE:
33
-				$this->addNotificationActionData("update", array( "item" => array($props)));
33
+				$this->addNotificationActionData("update", array("item" => array($props)));
34 34
 				$GLOBALS["bus"]->addData($this->createNotificationResponseData());
35 35
 				break;
36 36
 		}
Please login to merge, or discard this patch.