@@ -4,21 +4,21 @@ |
||
4 | 4 | |
5 | 5 | // TODO: implement logging levels |
6 | 6 | class Logger { |
7 | - public static function log($context, $msg) { |
|
8 | - if (PLUGIN_FILESBROWSER_LOGLEVEL === "DEBUG" || PLUGIN_FILESBROWSER_LOGLEVEL === "NORMAL") { |
|
9 | - error_log("[INFO][{$context}] " . print_r($msg, true)); |
|
10 | - } |
|
11 | - } |
|
7 | + public static function log($context, $msg) { |
|
8 | + if (PLUGIN_FILESBROWSER_LOGLEVEL === "DEBUG" || PLUGIN_FILESBROWSER_LOGLEVEL === "NORMAL") { |
|
9 | + error_log("[INFO][{$context}] " . print_r($msg, true)); |
|
10 | + } |
|
11 | + } |
|
12 | 12 | |
13 | - public static function error($context, $msg) { |
|
14 | - if (PLUGIN_FILESBROWSER_LOGLEVEL === "ERROR" || PLUGIN_FILESBROWSER_LOGLEVEL === "DEBUG" || PLUGIN_FILESBROWSER_LOGLEVEL === "NORMAL") { |
|
15 | - error_log("[ERROR][{$context}] " . print_r($msg, true)); |
|
16 | - } |
|
17 | - } |
|
13 | + public static function error($context, $msg) { |
|
14 | + if (PLUGIN_FILESBROWSER_LOGLEVEL === "ERROR" || PLUGIN_FILESBROWSER_LOGLEVEL === "DEBUG" || PLUGIN_FILESBROWSER_LOGLEVEL === "NORMAL") { |
|
15 | + error_log("[ERROR][{$context}] " . print_r($msg, true)); |
|
16 | + } |
|
17 | + } |
|
18 | 18 | |
19 | - public static function debug($context, $msg) { |
|
20 | - if (PLUGIN_FILESBROWSER_LOGLEVEL === "DEBUG") { |
|
21 | - error_log("[DBG][{$context}] " . print_r($msg, true)); |
|
22 | - } |
|
23 | - } |
|
19 | + public static function debug($context, $msg) { |
|
20 | + if (PLUGIN_FILESBROWSER_LOGLEVEL === "DEBUG") { |
|
21 | + error_log("[DBG][{$context}] " . print_r($msg, true)); |
|
22 | + } |
|
23 | + } |
|
24 | 24 | } |
@@ -9,166 +9,166 @@ |
||
9 | 9 | namespace Files\Core\Util; |
10 | 10 | |
11 | 11 | class PathUtil { |
12 | - /** |
|
13 | - * get_mime. |
|
14 | - * |
|
15 | - * Returns the mimetype for the specified file |
|
16 | - * |
|
17 | - * @static |
|
18 | - * |
|
19 | - * @param string $filename Filename to get the mime type from |
|
20 | - * @param int $mode 0 = full check, 1 = extension check only |
|
21 | - * |
|
22 | - * @return string the found mimetype or 'application/octet-stream' as fallback |
|
23 | - */ |
|
24 | - public static function get_mime($filename, $mode = 0) { |
|
25 | - // mode 0 = full check |
|
26 | - // mode 1 = extension check only |
|
27 | - |
|
28 | - $mime_types = [ |
|
29 | - 'txt' => 'text/plain', |
|
30 | - 'htm' => 'text/html', |
|
31 | - 'html' => 'text/html', |
|
32 | - 'php' => 'text/html', |
|
33 | - 'css' => 'text/css', |
|
34 | - 'js' => 'application/javascript', |
|
35 | - 'json' => 'application/json', |
|
36 | - 'xml' => 'application/xml', |
|
37 | - 'swf' => 'application/x-shockwave-flash', |
|
38 | - 'flv' => 'video/x-flv', |
|
39 | - |
|
40 | - // images |
|
41 | - 'png' => 'image/png', |
|
42 | - 'jpe' => 'image/jpeg', |
|
43 | - 'jpeg' => 'image/jpeg', |
|
44 | - 'jpg' => 'image/jpeg', |
|
45 | - 'gif' => 'image/gif', |
|
46 | - 'bmp' => 'image/bmp', |
|
47 | - 'ico' => 'image/vnd.microsoft.icon', |
|
48 | - 'tiff' => 'image/tiff', |
|
49 | - 'tif' => 'image/tiff', |
|
50 | - 'svg' => 'image/svg+xml', |
|
51 | - 'svgz' => 'image/svg+xml', |
|
52 | - |
|
53 | - // archives |
|
54 | - 'zip' => 'application/zip', |
|
55 | - 'rar' => 'application/x-rar-compressed', |
|
56 | - 'exe' => 'application/x-msdownload', |
|
57 | - 'msi' => 'application/x-msdownload', |
|
58 | - 'cab' => 'application/vnd.ms-cab-compressed', |
|
59 | - |
|
60 | - // audio/video |
|
61 | - 'mp3' => 'audio/mpeg', |
|
62 | - 'qt' => 'video/quicktime', |
|
63 | - 'mov' => 'video/quicktime', |
|
64 | - 'mp4' => 'video/mp4', |
|
65 | - 'webm' => 'video/webm', |
|
66 | - |
|
67 | - // adobe |
|
68 | - 'pdf' => 'application/pdf', |
|
69 | - 'psd' => 'image/vnd.adobe.photoshop', |
|
70 | - 'ai' => 'application/postscript', |
|
71 | - 'eps' => 'application/postscript', |
|
72 | - 'ps' => 'application/postscript', |
|
73 | - |
|
74 | - // ms office |
|
75 | - 'doc' => 'application/msword', |
|
76 | - 'rtf' => 'application/rtf', |
|
77 | - 'xls' => 'application/vnd.ms-excel', |
|
78 | - 'ppt' => 'application/vnd.ms-powerpoint', |
|
79 | - 'docx' => 'application/msword', |
|
80 | - 'xlsx' => 'application/vnd.ms-excel', |
|
81 | - 'pptx' => 'application/vnd.ms-powerpoint', |
|
82 | - |
|
83 | - // open office |
|
84 | - 'odt' => 'application/vnd.oasis.opendocument.text', |
|
85 | - 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', |
|
86 | - 'odp' => 'application/vnd.oasis.opendocument.presentation', |
|
87 | - ]; |
|
88 | - |
|
89 | - $exploded = explode('.', $filename); |
|
90 | - $last = array_pop($exploded); |
|
91 | - $ext = strtolower($last); |
|
92 | - |
|
93 | - if (function_exists('mime_content_type') && is_file($filename) && $mode == 0) { |
|
94 | - return mime_content_type($filename); |
|
95 | - } |
|
96 | - if (function_exists('finfo_open') && is_file($filename) && $mode == 0) { |
|
97 | - $finfo = finfo_open(FILEINFO_MIME); |
|
98 | - $mimetype = finfo_file($finfo, $filename); |
|
99 | - finfo_close($finfo); |
|
100 | - |
|
101 | - return $mimetype; |
|
102 | - } |
|
103 | - if (array_key_exists($ext, $mime_types)) { |
|
104 | - return $mime_types[$ext]; |
|
105 | - } |
|
106 | - |
|
107 | - return 'application/octet-stream'; |
|
108 | - } |
|
109 | - |
|
110 | - /** |
|
111 | - * Splits the filename from the given path. |
|
112 | - * |
|
113 | - * @static |
|
114 | - * |
|
115 | - * @param string $path a filesystem path, use / as path separator |
|
116 | - * |
|
117 | - * @return string the last part of the path, mostly this is the filename |
|
118 | - */ |
|
119 | - public static function getFilenameFromPath($path) { |
|
120 | - $pathParts = explode('/', $path); |
|
121 | - |
|
122 | - return end($pathParts); |
|
123 | - } |
|
124 | - |
|
125 | - /** |
|
126 | - * Splits the foldername/path from the given path. |
|
127 | - * |
|
128 | - * @static |
|
129 | - * |
|
130 | - * @param string $path |
|
131 | - * |
|
132 | - * @return string foldername |
|
133 | - */ |
|
134 | - public static function getFolderNameFromPath($path) { |
|
135 | - $tmp = explode("/", $path); |
|
136 | - array_pop($tmp); |
|
137 | - $folder = implode("/", $tmp); |
|
138 | - |
|
139 | - return $folder == "" ? "/" : $folder; |
|
140 | - } |
|
141 | - |
|
142 | - /** |
|
143 | - * creates a security file, which is checked before downloading a file. |
|
144 | - * |
|
145 | - * @static |
|
146 | - * |
|
147 | - * @param string secid A random id |
|
148 | - * @param mixed $basepath |
|
149 | - * @param mixed $secid |
|
150 | - */ |
|
151 | - public static function createSecIDFile($basepath, $secid) { |
|
152 | - $lockFile = $basepath . DIRECTORY_SEPARATOR . "secid." . $secid; |
|
153 | - $fh = fopen($lockFile, 'w') or exit("can't open secid file"); |
|
154 | - $stringData = date(DATE_RFC822); |
|
155 | - fwrite($fh, $stringData); |
|
156 | - fclose($fh); |
|
157 | - } |
|
158 | - |
|
159 | - /** |
|
160 | - * Sanitize a filename. |
|
161 | - * Currently removes all html tags |
|
162 | - * and replaces \, /, :, ", |, !, ?, <, > and *. |
|
163 | - * |
|
164 | - * @param string $string |
|
165 | - * |
|
166 | - * @return string |
|
167 | - */ |
|
168 | - public static function sanitizeFilename($string) { |
|
169 | - $cleanerString = preg_replace('/[:\|\"!\*\?\\\\\/]+/i', '', $string); |
|
170 | - $cleanerString = strip_tags($cleanerString); |
|
171 | - |
|
172 | - return preg_replace('/[><]+/i', '', $cleanerString); |
|
173 | - } |
|
12 | + /** |
|
13 | + * get_mime. |
|
14 | + * |
|
15 | + * Returns the mimetype for the specified file |
|
16 | + * |
|
17 | + * @static |
|
18 | + * |
|
19 | + * @param string $filename Filename to get the mime type from |
|
20 | + * @param int $mode 0 = full check, 1 = extension check only |
|
21 | + * |
|
22 | + * @return string the found mimetype or 'application/octet-stream' as fallback |
|
23 | + */ |
|
24 | + public static function get_mime($filename, $mode = 0) { |
|
25 | + // mode 0 = full check |
|
26 | + // mode 1 = extension check only |
|
27 | + |
|
28 | + $mime_types = [ |
|
29 | + 'txt' => 'text/plain', |
|
30 | + 'htm' => 'text/html', |
|
31 | + 'html' => 'text/html', |
|
32 | + 'php' => 'text/html', |
|
33 | + 'css' => 'text/css', |
|
34 | + 'js' => 'application/javascript', |
|
35 | + 'json' => 'application/json', |
|
36 | + 'xml' => 'application/xml', |
|
37 | + 'swf' => 'application/x-shockwave-flash', |
|
38 | + 'flv' => 'video/x-flv', |
|
39 | + |
|
40 | + // images |
|
41 | + 'png' => 'image/png', |
|
42 | + 'jpe' => 'image/jpeg', |
|
43 | + 'jpeg' => 'image/jpeg', |
|
44 | + 'jpg' => 'image/jpeg', |
|
45 | + 'gif' => 'image/gif', |
|
46 | + 'bmp' => 'image/bmp', |
|
47 | + 'ico' => 'image/vnd.microsoft.icon', |
|
48 | + 'tiff' => 'image/tiff', |
|
49 | + 'tif' => 'image/tiff', |
|
50 | + 'svg' => 'image/svg+xml', |
|
51 | + 'svgz' => 'image/svg+xml', |
|
52 | + |
|
53 | + // archives |
|
54 | + 'zip' => 'application/zip', |
|
55 | + 'rar' => 'application/x-rar-compressed', |
|
56 | + 'exe' => 'application/x-msdownload', |
|
57 | + 'msi' => 'application/x-msdownload', |
|
58 | + 'cab' => 'application/vnd.ms-cab-compressed', |
|
59 | + |
|
60 | + // audio/video |
|
61 | + 'mp3' => 'audio/mpeg', |
|
62 | + 'qt' => 'video/quicktime', |
|
63 | + 'mov' => 'video/quicktime', |
|
64 | + 'mp4' => 'video/mp4', |
|
65 | + 'webm' => 'video/webm', |
|
66 | + |
|
67 | + // adobe |
|
68 | + 'pdf' => 'application/pdf', |
|
69 | + 'psd' => 'image/vnd.adobe.photoshop', |
|
70 | + 'ai' => 'application/postscript', |
|
71 | + 'eps' => 'application/postscript', |
|
72 | + 'ps' => 'application/postscript', |
|
73 | + |
|
74 | + // ms office |
|
75 | + 'doc' => 'application/msword', |
|
76 | + 'rtf' => 'application/rtf', |
|
77 | + 'xls' => 'application/vnd.ms-excel', |
|
78 | + 'ppt' => 'application/vnd.ms-powerpoint', |
|
79 | + 'docx' => 'application/msword', |
|
80 | + 'xlsx' => 'application/vnd.ms-excel', |
|
81 | + 'pptx' => 'application/vnd.ms-powerpoint', |
|
82 | + |
|
83 | + // open office |
|
84 | + 'odt' => 'application/vnd.oasis.opendocument.text', |
|
85 | + 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', |
|
86 | + 'odp' => 'application/vnd.oasis.opendocument.presentation', |
|
87 | + ]; |
|
88 | + |
|
89 | + $exploded = explode('.', $filename); |
|
90 | + $last = array_pop($exploded); |
|
91 | + $ext = strtolower($last); |
|
92 | + |
|
93 | + if (function_exists('mime_content_type') && is_file($filename) && $mode == 0) { |
|
94 | + return mime_content_type($filename); |
|
95 | + } |
|
96 | + if (function_exists('finfo_open') && is_file($filename) && $mode == 0) { |
|
97 | + $finfo = finfo_open(FILEINFO_MIME); |
|
98 | + $mimetype = finfo_file($finfo, $filename); |
|
99 | + finfo_close($finfo); |
|
100 | + |
|
101 | + return $mimetype; |
|
102 | + } |
|
103 | + if (array_key_exists($ext, $mime_types)) { |
|
104 | + return $mime_types[$ext]; |
|
105 | + } |
|
106 | + |
|
107 | + return 'application/octet-stream'; |
|
108 | + } |
|
109 | + |
|
110 | + /** |
|
111 | + * Splits the filename from the given path. |
|
112 | + * |
|
113 | + * @static |
|
114 | + * |
|
115 | + * @param string $path a filesystem path, use / as path separator |
|
116 | + * |
|
117 | + * @return string the last part of the path, mostly this is the filename |
|
118 | + */ |
|
119 | + public static function getFilenameFromPath($path) { |
|
120 | + $pathParts = explode('/', $path); |
|
121 | + |
|
122 | + return end($pathParts); |
|
123 | + } |
|
124 | + |
|
125 | + /** |
|
126 | + * Splits the foldername/path from the given path. |
|
127 | + * |
|
128 | + * @static |
|
129 | + * |
|
130 | + * @param string $path |
|
131 | + * |
|
132 | + * @return string foldername |
|
133 | + */ |
|
134 | + public static function getFolderNameFromPath($path) { |
|
135 | + $tmp = explode("/", $path); |
|
136 | + array_pop($tmp); |
|
137 | + $folder = implode("/", $tmp); |
|
138 | + |
|
139 | + return $folder == "" ? "/" : $folder; |
|
140 | + } |
|
141 | + |
|
142 | + /** |
|
143 | + * creates a security file, which is checked before downloading a file. |
|
144 | + * |
|
145 | + * @static |
|
146 | + * |
|
147 | + * @param string secid A random id |
|
148 | + * @param mixed $basepath |
|
149 | + * @param mixed $secid |
|
150 | + */ |
|
151 | + public static function createSecIDFile($basepath, $secid) { |
|
152 | + $lockFile = $basepath . DIRECTORY_SEPARATOR . "secid." . $secid; |
|
153 | + $fh = fopen($lockFile, 'w') or exit("can't open secid file"); |
|
154 | + $stringData = date(DATE_RFC822); |
|
155 | + fwrite($fh, $stringData); |
|
156 | + fclose($fh); |
|
157 | + } |
|
158 | + |
|
159 | + /** |
|
160 | + * Sanitize a filename. |
|
161 | + * Currently removes all html tags |
|
162 | + * and replaces \, /, :, ", |, !, ?, <, > and *. |
|
163 | + * |
|
164 | + * @param string $string |
|
165 | + * |
|
166 | + * @return string |
|
167 | + */ |
|
168 | + public static function sanitizeFilename($string) { |
|
169 | + $cleanerString = preg_replace('/[:\|\"!\*\?\\\\\/]+/i', '', $string); |
|
170 | + $cleanerString = strip_tags($cleanerString); |
|
171 | + |
|
172 | + return preg_replace('/[><]+/i', '', $cleanerString); |
|
173 | + } |
|
174 | 174 | } |
@@ -11,5 +11,5 @@ |
||
11 | 11 | // if (!mb_detect_encoding($str, "UTF-8", true)) { |
12 | 12 | // $str = utf8_encode($str); |
13 | 13 | // } |
14 | - return $str; |
|
14 | + return $str; |
|
15 | 15 | } |
@@ -17,369 +17,369 @@ |
||
17 | 17 | use Files\Core\Util\Logger; |
18 | 18 | |
19 | 19 | class AccountStore { |
20 | - public const LOG_CONTEXT = "AccountStore"; // Context for the Logger |
|
21 | - public const ACCOUNT_STORAGE_PATH = "zarafa/v1/plugins/files/accounts"; |
|
22 | - public const ACCOUNT_VERSION = 1; |
|
23 | - |
|
24 | - /** |
|
25 | - * @var Account[] Account array |
|
26 | - */ |
|
27 | - private $accounts = []; |
|
28 | - |
|
29 | - public function __construct() { |
|
30 | - $this->initialiseAccounts(); |
|
31 | - } |
|
32 | - |
|
33 | - /** |
|
34 | - * @param $name |
|
35 | - * @param $backend |
|
36 | - * @param array $backendConfig Backend specific account settings |
|
37 | - * like username, password, serveraddress, ... |
|
38 | - * |
|
39 | - * @return Account |
|
40 | - */ |
|
41 | - public function createAccount($name, $backend, $backendConfig) { |
|
42 | - $newID = $this->createNewId($backendConfig); // create id out of the configuration |
|
43 | - |
|
44 | - // create instance of backend to get features |
|
45 | - $backendStore = BackendStore::getInstance(); |
|
46 | - $backendInstance = $backendStore->getInstanceOfBackend($backend); |
|
47 | - $features = $backendInstance->getAvailableFeatures(); |
|
48 | - |
|
49 | - // check backend_config for validity |
|
50 | - $status = $this->checkBackendConfig($backendInstance, $backendConfig); |
|
51 | - |
|
52 | - // get sequence number |
|
53 | - $sequence = $this->getNewSequenceNumber(); |
|
54 | - |
|
55 | - $newAccount = new Account($newID, strip_tags($name), $status[0], $status[1], strip_tags($backend), $backendConfig, $features, $sequence, false); |
|
56 | - |
|
57 | - // now store all the values to the user settings |
|
58 | - $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $newID . "/id", $newAccount->getId()); |
|
59 | - $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $newID . "/name", $newAccount->getName()); |
|
60 | - $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $newID . "/status", $newAccount->getStatus()); |
|
61 | - $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $newID . "/status_description", $newAccount->getStatusDescription()); |
|
62 | - $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $newID . "/backend", $newAccount->getBackend()); |
|
63 | - $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $newID . "/account_sequence", $newAccount->getSequence()); |
|
64 | - // User defined accounts are never administrative. So set cannot_change to false. |
|
65 | - $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $newID . "/cannot_change", false); |
|
66 | - $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $newID . "/backend_config/version", self::ACCOUNT_VERSION); |
|
67 | - // store all backend configurations |
|
68 | - foreach ($newAccount->getBackendConfig() as $key => $value) { |
|
69 | - if ($key !== "version") { |
|
70 | - $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $newID . "/backend_config/" . $key, $this->encryptBackendConfigProperty($value, self::ACCOUNT_VERSION)); |
|
71 | - } |
|
72 | - } |
|
73 | - |
|
74 | - // store all features |
|
75 | - foreach ($newAccount->getFeatures() as $feature) { |
|
76 | - $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $newID . "/backend_features/" . $feature, true); |
|
77 | - } |
|
78 | - |
|
79 | - $GLOBALS["settings"]->saveSettings(); // save to MAPI storage |
|
80 | - |
|
81 | - // add account to our local store after it was saved to the zarafa-settings |
|
82 | - $this->accounts[$newID] = $newAccount; |
|
83 | - |
|
84 | - return $newAccount; |
|
85 | - } |
|
86 | - |
|
87 | - /** |
|
88 | - * @param Account $account |
|
89 | - * |
|
90 | - * @return Account |
|
91 | - */ |
|
92 | - public function updateAccount($account) { |
|
93 | - $accId = $account->getId(); |
|
94 | - $isAdministrativeAccount = $account->getCannotChangeFlag(); |
|
95 | - |
|
96 | - // create instance of backend to get features |
|
97 | - $backendStore = BackendStore::getInstance(); |
|
98 | - $backendInstance = $backendStore->getInstanceOfBackend($account->getBackend()); |
|
99 | - $features = $backendInstance->getAvailableFeatures(); |
|
100 | - $account->setFeatures($features); |
|
101 | - |
|
102 | - // check backend_config for validity |
|
103 | - $status = $this->checkBackendConfig($backendInstance, $account->getBackendConfig()); |
|
104 | - $account->setStatus($status[0]); // update status |
|
105 | - $account->setStatusDescription($status[1]); // update status description |
|
106 | - |
|
107 | - // add account to local store |
|
108 | - $this->accounts[$accId] = $account; |
|
109 | - |
|
110 | - // save values to MAPI settings |
|
111 | - // now store all the values to the user settings |
|
112 | - // but if we have an administrative account only save the account sequence |
|
113 | - if (!$isAdministrativeAccount) { |
|
114 | - $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $accId . "/name", $account->getName()); |
|
115 | - $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $accId . "/status", $account->getStatus()); |
|
116 | - $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $accId . "/status_description", $account->getStatusDescription()); |
|
117 | - $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $accId . "/backend", $account->getBackend()); |
|
118 | - |
|
119 | - $acc = $account->getBackendConfig(); |
|
120 | - $version = 0; |
|
121 | - if (isset($acc["version"])) { |
|
122 | - $version = $acc["version"]; |
|
123 | - } |
|
124 | - |
|
125 | - // Unable to decrypt, don't update |
|
126 | - if ($version == 0 && !defined('FILES_PASSWORD_IV') && !defined('FILES_PASSWORD_KEY')) { |
|
127 | - Logger::error(self::LOG_CONTEXT, "Unable to update the account to as FILES_PASSWORD_IV/FILES_PASSWORD_KEY is not set"); |
|
128 | - } |
|
129 | - else { |
|
130 | - // store all backend configurations |
|
131 | - foreach ($account->getBackendConfig() as $key => $value) { |
|
132 | - if ($key !== "version") { |
|
133 | - $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $accId . "/backend_config/" . $key, $this->encryptBackendConfigProperty($value, self::ACCOUNT_VERSION)); |
|
134 | - } |
|
135 | - } |
|
136 | - |
|
137 | - $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $accId . "/backend_config/version", self::ACCOUNT_VERSION); |
|
138 | - } |
|
139 | - |
|
140 | - // store all features |
|
141 | - foreach ($account->getFeatures() as $feature) { |
|
142 | - $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $accId . "/backend_features/" . $feature, true); |
|
143 | - } |
|
144 | - } |
|
145 | - // when getSequence returns 0, there is no account_sequence setting yet. So create one. |
|
146 | - $account_sequence = ($account->getSequence() === 0 ? $this->getNewSequenceNumber() : $account->getSequence()); |
|
147 | - $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $accId . "/account_sequence", $account_sequence); |
|
148 | - |
|
149 | - $GLOBALS["settings"]->saveSettings(); // save to MAPI storage |
|
150 | - |
|
151 | - return $account; |
|
152 | - } |
|
153 | - |
|
154 | - /** |
|
155 | - * Delete account from local store and from the MAPI settings. |
|
156 | - * |
|
157 | - * @param $accountId |
|
158 | - * |
|
159 | - * @return bool |
|
160 | - */ |
|
161 | - public function deleteAccount($accountId) { |
|
162 | - $account = $this->getAccount($accountId); |
|
163 | - // Do not allow deleting administrative accounts, but fail silently. |
|
164 | - if (!$account->getCannotChangeFlag()) { |
|
165 | - $GLOBALS["settings"]->delete(self::ACCOUNT_STORAGE_PATH . "/" . $accountId); |
|
166 | - $GLOBALS["settings"]->saveSettings(); // save to MAPI storage |
|
167 | - } |
|
168 | - |
|
169 | - return true; |
|
170 | - } |
|
171 | - |
|
172 | - /** |
|
173 | - * Return the instance of the local account. |
|
174 | - * |
|
175 | - * @param $accountId |
|
176 | - * |
|
177 | - * @return Account |
|
178 | - */ |
|
179 | - public function getAccount($accountId) { |
|
180 | - return $this->accounts[$accountId]; |
|
181 | - } |
|
182 | - |
|
183 | - /** |
|
184 | - * @return Account[] all Accounts |
|
185 | - */ |
|
186 | - public function getAllAccounts() { |
|
187 | - return $this->accounts; |
|
188 | - } |
|
189 | - |
|
190 | - /** |
|
191 | - * Initialize the accountstore. Reads all accountinformation from the MAPI settings. |
|
192 | - */ |
|
193 | - private function initialiseAccounts() { |
|
194 | - // Parse accounts from the Settings |
|
195 | - $tmpAccs = $GLOBALS["settings"]->get(self::ACCOUNT_STORAGE_PATH); |
|
196 | - |
|
197 | - if (is_array($tmpAccs)) { |
|
198 | - $this->accounts = []; |
|
199 | - |
|
200 | - foreach ($tmpAccs as $acc) { |
|
201 | - // set backend_features if it is not set to prevent warning |
|
202 | - if (!isset($acc["backend_features"])) { |
|
203 | - $acc["backend_features"] = []; |
|
204 | - } |
|
205 | - // account_sequence was introduced later. So set and save it if missing. |
|
206 | - if (!isset($acc["account_sequence"])) { |
|
207 | - $acc["account_sequence"] = $this->getNewSequenceNumber(); |
|
208 | - Logger::debug(self::LOG_CONTEXT, "Account sequence missing. New seq: " . $acc["account_sequence"]); |
|
209 | - $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $acc["id"] . "/account_sequence", $acc["account_sequence"]); |
|
210 | - $GLOBALS["settings"]->saveSettings(); |
|
211 | - } |
|
212 | - // cannot_change flag was introduced later. So set it to false and save it if missing. |
|
213 | - if (!isset($acc["cannot_change"])) { |
|
214 | - $acc["cannot_change"] = false; |
|
215 | - Logger::debug(self::LOG_CONTEXT, "Cannot change flag missing. Setting to false."); |
|
216 | - $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $acc["id"] . "/cannot_change", false); |
|
217 | - $GLOBALS["settings"]->saveSettings(); |
|
218 | - } |
|
219 | - |
|
220 | - $backend_config = $acc["backend_config"]; |
|
221 | - $version = 0; |
|
222 | - |
|
223 | - if (isset($acc["backend_config"], $acc["backend_config"]["version"])) { |
|
224 | - $version = $acc["backend_config"]["version"]; |
|
225 | - } |
|
226 | - |
|
227 | - if (($version === 0 && defined('FILES_PASSWORD_IV') && defined('FILES_PASSWORD_KEY')) || $version === self::ACCOUNT_VERSION) { |
|
228 | - $backend_config = $this->decryptBackendConfig($acc["backend_config"], $version); |
|
229 | - // version is lost after decryption, add it again |
|
230 | - $backend_config["version"] = $version; |
|
231 | - } |
|
232 | - elseif ($version === 0) { |
|
233 | - Logger::error(self::LOG_CONTEXT, "FILES_PASSWORD_IV or FILES_PASSWORD_KEY not set, unable to decrypt backend configuration"); |
|
234 | - } |
|
235 | - else { |
|
236 | - Logger::error(self::LOG_CONTEXT, "Unsupported account version {$version}, unable to decrypt backend configuration"); |
|
237 | - } |
|
238 | - |
|
239 | - $this->accounts[$acc["id"]] = new Account( |
|
240 | - $acc["id"], |
|
241 | - $acc["name"], |
|
242 | - $acc["status"], |
|
243 | - $acc["status_description"], |
|
244 | - $acc["backend"], |
|
245 | - $backend_config, |
|
246 | - array_keys($acc["backend_features"]), |
|
247 | - $acc["account_sequence"], |
|
248 | - $acc["cannot_change"] |
|
249 | - ); |
|
250 | - } |
|
251 | - } |
|
252 | - Logger::debug(self::LOG_CONTEXT, "Found " . count($this->accounts) . " accounts."); |
|
253 | - } |
|
254 | - |
|
255 | - /** |
|
256 | - * @param AbstractBackend $backendInstance |
|
257 | - * @param array $backendConfig Backend specific account settings |
|
258 | - * like username, password, serveraddress, ... |
|
259 | - * |
|
260 | - * @return array |
|
261 | - */ |
|
262 | - private function checkBackendConfig($backendInstance, $backendConfig) { |
|
263 | - $status = Account::STATUS_NEW; |
|
264 | - $description = _('Account is ready to use.'); |
|
265 | - |
|
266 | - try { |
|
267 | - $backendInstance->init_backend($backendConfig); |
|
268 | - $backendInstance->open(); |
|
269 | - $backendInstance->ls("/"); |
|
270 | - $status = Account::STATUS_OK; |
|
271 | - } |
|
272 | - catch (BackendException $e) { |
|
273 | - $status = Account::STATUS_ERROR; |
|
274 | - $description = $e->getMessage(); |
|
275 | - |
|
276 | - Logger::error(self::LOG_CONTEXT, "Account check failed: " . $description); |
|
277 | - } |
|
278 | - |
|
279 | - return [$status, $description]; |
|
280 | - } |
|
281 | - |
|
282 | - /** |
|
283 | - * @param array $backendConfig Backend specific account settings |
|
284 | - * like username, password, serveraddress, ... |
|
285 | - * |
|
286 | - * @return an unique id |
|
287 | - */ |
|
288 | - private function createNewId($backendConfig) { |
|
289 | - // lets create a hash |
|
290 | - return md5(json_encode($backendConfig) . time()); // json_encode is faster than serialize |
|
291 | - } |
|
292 | - |
|
293 | - /** |
|
294 | - * Generate a new sequence number. It will always be the highest used sequence number +1. |
|
295 | - * |
|
296 | - * @return int |
|
297 | - */ |
|
298 | - private function getNewSequenceNumber() { |
|
299 | - $seq = 0; |
|
300 | - foreach ($this->accounts as $acc) { |
|
301 | - if ($acc->getSequence() > $seq) { |
|
302 | - $seq = $acc->getSequence(); |
|
303 | - } |
|
304 | - } |
|
305 | - |
|
306 | - return $seq + 1; |
|
307 | - } |
|
308 | - |
|
309 | - /** |
|
310 | - * Decrypt the backend configuration using the standard grommunio Web key. |
|
311 | - * |
|
312 | - * @param array $backendConfig Backend specific account settings |
|
313 | - * like username, password, serveraddress, ... |
|
314 | - * @param mixed $version |
|
315 | - * |
|
316 | - * @return array |
|
317 | - */ |
|
318 | - private function decryptBackendConfig($backendConfig, $version = 0) { |
|
319 | - $decBackendConfig = []; |
|
320 | - |
|
321 | - foreach ($backendConfig as $key => $value) { |
|
322 | - if ($key !== "version") { |
|
323 | - try { |
|
324 | - $decBackendConfig[$key] = $this->decryptBackendConfigProperty($value, $version); |
|
325 | - } |
|
326 | - catch (Exception $e) { |
|
327 | - Logger::error(self::LOG_CONTEXT, sprintf("Unable to decrypt backend configuration: '%s'", $e->getMessage())); |
|
328 | - } |
|
329 | - } |
|
330 | - } |
|
331 | - |
|
332 | - return $decBackendConfig; |
|
333 | - } |
|
334 | - |
|
335 | - /** |
|
336 | - * Encrypt the given string. |
|
337 | - * |
|
338 | - * @param $value |
|
339 | - * @param $version the storage version used to identify what encryption to use |
|
340 | - * |
|
341 | - * @return string |
|
342 | - */ |
|
343 | - private function encryptBackendConfigProperty($value, $version = 0) { |
|
344 | - if ($version == self::ACCOUNT_VERSION && !is_bool($value)) { |
|
345 | - $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); |
|
346 | - $key = $GLOBALS["operations"]->getFilesEncryptionKey(); |
|
347 | - $encrypted = sodium_crypto_secretbox($value, $nonce, $key); |
|
348 | - $value = bin2hex($nonce) . bin2hex($encrypted); |
|
349 | - } |
|
350 | - elseif ($version !== self::ACCOUNT_VERSION) { |
|
351 | - throw Exception("Unable to encrypt backend configuration unsupported version {$version}"); |
|
352 | - } |
|
353 | - |
|
354 | - return $value; |
|
355 | - } |
|
356 | - |
|
357 | - /** |
|
358 | - * Decrypt the given string. |
|
359 | - * |
|
360 | - * @param $value |
|
361 | - * @param $version the storage version used to identify what encryption to use |
|
362 | - * |
|
363 | - * @return string |
|
364 | - */ |
|
365 | - private function decryptBackendConfigProperty($value, $version = 0) { |
|
366 | - if (is_bool($value)) { |
|
367 | - return $value; |
|
368 | - } |
|
369 | - |
|
370 | - if ($version == self::ACCOUNT_VERSION) { |
|
371 | - $value = hex2bin($value); |
|
372 | - $nonce = substr($value, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); |
|
373 | - $encrypted = substr($value, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, strlen($value)); |
|
374 | - $key = $GLOBALS["operations"]->getFilesEncryptionKey(); |
|
375 | - $value = sodium_crypto_secretbox_open($encrypted, $nonce, $key); |
|
376 | - |
|
377 | - // Decryption failed, password might have changed |
|
378 | - if ($value === false) { |
|
379 | - throw new Exception("invalid password"); |
|
380 | - } |
|
381 | - } |
|
382 | - |
|
383 | - return $value; |
|
384 | - } |
|
20 | + public const LOG_CONTEXT = "AccountStore"; // Context for the Logger |
|
21 | + public const ACCOUNT_STORAGE_PATH = "zarafa/v1/plugins/files/accounts"; |
|
22 | + public const ACCOUNT_VERSION = 1; |
|
23 | + |
|
24 | + /** |
|
25 | + * @var Account[] Account array |
|
26 | + */ |
|
27 | + private $accounts = []; |
|
28 | + |
|
29 | + public function __construct() { |
|
30 | + $this->initialiseAccounts(); |
|
31 | + } |
|
32 | + |
|
33 | + /** |
|
34 | + * @param $name |
|
35 | + * @param $backend |
|
36 | + * @param array $backendConfig Backend specific account settings |
|
37 | + * like username, password, serveraddress, ... |
|
38 | + * |
|
39 | + * @return Account |
|
40 | + */ |
|
41 | + public function createAccount($name, $backend, $backendConfig) { |
|
42 | + $newID = $this->createNewId($backendConfig); // create id out of the configuration |
|
43 | + |
|
44 | + // create instance of backend to get features |
|
45 | + $backendStore = BackendStore::getInstance(); |
|
46 | + $backendInstance = $backendStore->getInstanceOfBackend($backend); |
|
47 | + $features = $backendInstance->getAvailableFeatures(); |
|
48 | + |
|
49 | + // check backend_config for validity |
|
50 | + $status = $this->checkBackendConfig($backendInstance, $backendConfig); |
|
51 | + |
|
52 | + // get sequence number |
|
53 | + $sequence = $this->getNewSequenceNumber(); |
|
54 | + |
|
55 | + $newAccount = new Account($newID, strip_tags($name), $status[0], $status[1], strip_tags($backend), $backendConfig, $features, $sequence, false); |
|
56 | + |
|
57 | + // now store all the values to the user settings |
|
58 | + $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $newID . "/id", $newAccount->getId()); |
|
59 | + $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $newID . "/name", $newAccount->getName()); |
|
60 | + $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $newID . "/status", $newAccount->getStatus()); |
|
61 | + $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $newID . "/status_description", $newAccount->getStatusDescription()); |
|
62 | + $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $newID . "/backend", $newAccount->getBackend()); |
|
63 | + $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $newID . "/account_sequence", $newAccount->getSequence()); |
|
64 | + // User defined accounts are never administrative. So set cannot_change to false. |
|
65 | + $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $newID . "/cannot_change", false); |
|
66 | + $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $newID . "/backend_config/version", self::ACCOUNT_VERSION); |
|
67 | + // store all backend configurations |
|
68 | + foreach ($newAccount->getBackendConfig() as $key => $value) { |
|
69 | + if ($key !== "version") { |
|
70 | + $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $newID . "/backend_config/" . $key, $this->encryptBackendConfigProperty($value, self::ACCOUNT_VERSION)); |
|
71 | + } |
|
72 | + } |
|
73 | + |
|
74 | + // store all features |
|
75 | + foreach ($newAccount->getFeatures() as $feature) { |
|
76 | + $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $newID . "/backend_features/" . $feature, true); |
|
77 | + } |
|
78 | + |
|
79 | + $GLOBALS["settings"]->saveSettings(); // save to MAPI storage |
|
80 | + |
|
81 | + // add account to our local store after it was saved to the zarafa-settings |
|
82 | + $this->accounts[$newID] = $newAccount; |
|
83 | + |
|
84 | + return $newAccount; |
|
85 | + } |
|
86 | + |
|
87 | + /** |
|
88 | + * @param Account $account |
|
89 | + * |
|
90 | + * @return Account |
|
91 | + */ |
|
92 | + public function updateAccount($account) { |
|
93 | + $accId = $account->getId(); |
|
94 | + $isAdministrativeAccount = $account->getCannotChangeFlag(); |
|
95 | + |
|
96 | + // create instance of backend to get features |
|
97 | + $backendStore = BackendStore::getInstance(); |
|
98 | + $backendInstance = $backendStore->getInstanceOfBackend($account->getBackend()); |
|
99 | + $features = $backendInstance->getAvailableFeatures(); |
|
100 | + $account->setFeatures($features); |
|
101 | + |
|
102 | + // check backend_config for validity |
|
103 | + $status = $this->checkBackendConfig($backendInstance, $account->getBackendConfig()); |
|
104 | + $account->setStatus($status[0]); // update status |
|
105 | + $account->setStatusDescription($status[1]); // update status description |
|
106 | + |
|
107 | + // add account to local store |
|
108 | + $this->accounts[$accId] = $account; |
|
109 | + |
|
110 | + // save values to MAPI settings |
|
111 | + // now store all the values to the user settings |
|
112 | + // but if we have an administrative account only save the account sequence |
|
113 | + if (!$isAdministrativeAccount) { |
|
114 | + $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $accId . "/name", $account->getName()); |
|
115 | + $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $accId . "/status", $account->getStatus()); |
|
116 | + $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $accId . "/status_description", $account->getStatusDescription()); |
|
117 | + $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $accId . "/backend", $account->getBackend()); |
|
118 | + |
|
119 | + $acc = $account->getBackendConfig(); |
|
120 | + $version = 0; |
|
121 | + if (isset($acc["version"])) { |
|
122 | + $version = $acc["version"]; |
|
123 | + } |
|
124 | + |
|
125 | + // Unable to decrypt, don't update |
|
126 | + if ($version == 0 && !defined('FILES_PASSWORD_IV') && !defined('FILES_PASSWORD_KEY')) { |
|
127 | + Logger::error(self::LOG_CONTEXT, "Unable to update the account to as FILES_PASSWORD_IV/FILES_PASSWORD_KEY is not set"); |
|
128 | + } |
|
129 | + else { |
|
130 | + // store all backend configurations |
|
131 | + foreach ($account->getBackendConfig() as $key => $value) { |
|
132 | + if ($key !== "version") { |
|
133 | + $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $accId . "/backend_config/" . $key, $this->encryptBackendConfigProperty($value, self::ACCOUNT_VERSION)); |
|
134 | + } |
|
135 | + } |
|
136 | + |
|
137 | + $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $accId . "/backend_config/version", self::ACCOUNT_VERSION); |
|
138 | + } |
|
139 | + |
|
140 | + // store all features |
|
141 | + foreach ($account->getFeatures() as $feature) { |
|
142 | + $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $accId . "/backend_features/" . $feature, true); |
|
143 | + } |
|
144 | + } |
|
145 | + // when getSequence returns 0, there is no account_sequence setting yet. So create one. |
|
146 | + $account_sequence = ($account->getSequence() === 0 ? $this->getNewSequenceNumber() : $account->getSequence()); |
|
147 | + $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $accId . "/account_sequence", $account_sequence); |
|
148 | + |
|
149 | + $GLOBALS["settings"]->saveSettings(); // save to MAPI storage |
|
150 | + |
|
151 | + return $account; |
|
152 | + } |
|
153 | + |
|
154 | + /** |
|
155 | + * Delete account from local store and from the MAPI settings. |
|
156 | + * |
|
157 | + * @param $accountId |
|
158 | + * |
|
159 | + * @return bool |
|
160 | + */ |
|
161 | + public function deleteAccount($accountId) { |
|
162 | + $account = $this->getAccount($accountId); |
|
163 | + // Do not allow deleting administrative accounts, but fail silently. |
|
164 | + if (!$account->getCannotChangeFlag()) { |
|
165 | + $GLOBALS["settings"]->delete(self::ACCOUNT_STORAGE_PATH . "/" . $accountId); |
|
166 | + $GLOBALS["settings"]->saveSettings(); // save to MAPI storage |
|
167 | + } |
|
168 | + |
|
169 | + return true; |
|
170 | + } |
|
171 | + |
|
172 | + /** |
|
173 | + * Return the instance of the local account. |
|
174 | + * |
|
175 | + * @param $accountId |
|
176 | + * |
|
177 | + * @return Account |
|
178 | + */ |
|
179 | + public function getAccount($accountId) { |
|
180 | + return $this->accounts[$accountId]; |
|
181 | + } |
|
182 | + |
|
183 | + /** |
|
184 | + * @return Account[] all Accounts |
|
185 | + */ |
|
186 | + public function getAllAccounts() { |
|
187 | + return $this->accounts; |
|
188 | + } |
|
189 | + |
|
190 | + /** |
|
191 | + * Initialize the accountstore. Reads all accountinformation from the MAPI settings. |
|
192 | + */ |
|
193 | + private function initialiseAccounts() { |
|
194 | + // Parse accounts from the Settings |
|
195 | + $tmpAccs = $GLOBALS["settings"]->get(self::ACCOUNT_STORAGE_PATH); |
|
196 | + |
|
197 | + if (is_array($tmpAccs)) { |
|
198 | + $this->accounts = []; |
|
199 | + |
|
200 | + foreach ($tmpAccs as $acc) { |
|
201 | + // set backend_features if it is not set to prevent warning |
|
202 | + if (!isset($acc["backend_features"])) { |
|
203 | + $acc["backend_features"] = []; |
|
204 | + } |
|
205 | + // account_sequence was introduced later. So set and save it if missing. |
|
206 | + if (!isset($acc["account_sequence"])) { |
|
207 | + $acc["account_sequence"] = $this->getNewSequenceNumber(); |
|
208 | + Logger::debug(self::LOG_CONTEXT, "Account sequence missing. New seq: " . $acc["account_sequence"]); |
|
209 | + $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $acc["id"] . "/account_sequence", $acc["account_sequence"]); |
|
210 | + $GLOBALS["settings"]->saveSettings(); |
|
211 | + } |
|
212 | + // cannot_change flag was introduced later. So set it to false and save it if missing. |
|
213 | + if (!isset($acc["cannot_change"])) { |
|
214 | + $acc["cannot_change"] = false; |
|
215 | + Logger::debug(self::LOG_CONTEXT, "Cannot change flag missing. Setting to false."); |
|
216 | + $GLOBALS["settings"]->set(self::ACCOUNT_STORAGE_PATH . "/" . $acc["id"] . "/cannot_change", false); |
|
217 | + $GLOBALS["settings"]->saveSettings(); |
|
218 | + } |
|
219 | + |
|
220 | + $backend_config = $acc["backend_config"]; |
|
221 | + $version = 0; |
|
222 | + |
|
223 | + if (isset($acc["backend_config"], $acc["backend_config"]["version"])) { |
|
224 | + $version = $acc["backend_config"]["version"]; |
|
225 | + } |
|
226 | + |
|
227 | + if (($version === 0 && defined('FILES_PASSWORD_IV') && defined('FILES_PASSWORD_KEY')) || $version === self::ACCOUNT_VERSION) { |
|
228 | + $backend_config = $this->decryptBackendConfig($acc["backend_config"], $version); |
|
229 | + // version is lost after decryption, add it again |
|
230 | + $backend_config["version"] = $version; |
|
231 | + } |
|
232 | + elseif ($version === 0) { |
|
233 | + Logger::error(self::LOG_CONTEXT, "FILES_PASSWORD_IV or FILES_PASSWORD_KEY not set, unable to decrypt backend configuration"); |
|
234 | + } |
|
235 | + else { |
|
236 | + Logger::error(self::LOG_CONTEXT, "Unsupported account version {$version}, unable to decrypt backend configuration"); |
|
237 | + } |
|
238 | + |
|
239 | + $this->accounts[$acc["id"]] = new Account( |
|
240 | + $acc["id"], |
|
241 | + $acc["name"], |
|
242 | + $acc["status"], |
|
243 | + $acc["status_description"], |
|
244 | + $acc["backend"], |
|
245 | + $backend_config, |
|
246 | + array_keys($acc["backend_features"]), |
|
247 | + $acc["account_sequence"], |
|
248 | + $acc["cannot_change"] |
|
249 | + ); |
|
250 | + } |
|
251 | + } |
|
252 | + Logger::debug(self::LOG_CONTEXT, "Found " . count($this->accounts) . " accounts."); |
|
253 | + } |
|
254 | + |
|
255 | + /** |
|
256 | + * @param AbstractBackend $backendInstance |
|
257 | + * @param array $backendConfig Backend specific account settings |
|
258 | + * like username, password, serveraddress, ... |
|
259 | + * |
|
260 | + * @return array |
|
261 | + */ |
|
262 | + private function checkBackendConfig($backendInstance, $backendConfig) { |
|
263 | + $status = Account::STATUS_NEW; |
|
264 | + $description = _('Account is ready to use.'); |
|
265 | + |
|
266 | + try { |
|
267 | + $backendInstance->init_backend($backendConfig); |
|
268 | + $backendInstance->open(); |
|
269 | + $backendInstance->ls("/"); |
|
270 | + $status = Account::STATUS_OK; |
|
271 | + } |
|
272 | + catch (BackendException $e) { |
|
273 | + $status = Account::STATUS_ERROR; |
|
274 | + $description = $e->getMessage(); |
|
275 | + |
|
276 | + Logger::error(self::LOG_CONTEXT, "Account check failed: " . $description); |
|
277 | + } |
|
278 | + |
|
279 | + return [$status, $description]; |
|
280 | + } |
|
281 | + |
|
282 | + /** |
|
283 | + * @param array $backendConfig Backend specific account settings |
|
284 | + * like username, password, serveraddress, ... |
|
285 | + * |
|
286 | + * @return an unique id |
|
287 | + */ |
|
288 | + private function createNewId($backendConfig) { |
|
289 | + // lets create a hash |
|
290 | + return md5(json_encode($backendConfig) . time()); // json_encode is faster than serialize |
|
291 | + } |
|
292 | + |
|
293 | + /** |
|
294 | + * Generate a new sequence number. It will always be the highest used sequence number +1. |
|
295 | + * |
|
296 | + * @return int |
|
297 | + */ |
|
298 | + private function getNewSequenceNumber() { |
|
299 | + $seq = 0; |
|
300 | + foreach ($this->accounts as $acc) { |
|
301 | + if ($acc->getSequence() > $seq) { |
|
302 | + $seq = $acc->getSequence(); |
|
303 | + } |
|
304 | + } |
|
305 | + |
|
306 | + return $seq + 1; |
|
307 | + } |
|
308 | + |
|
309 | + /** |
|
310 | + * Decrypt the backend configuration using the standard grommunio Web key. |
|
311 | + * |
|
312 | + * @param array $backendConfig Backend specific account settings |
|
313 | + * like username, password, serveraddress, ... |
|
314 | + * @param mixed $version |
|
315 | + * |
|
316 | + * @return array |
|
317 | + */ |
|
318 | + private function decryptBackendConfig($backendConfig, $version = 0) { |
|
319 | + $decBackendConfig = []; |
|
320 | + |
|
321 | + foreach ($backendConfig as $key => $value) { |
|
322 | + if ($key !== "version") { |
|
323 | + try { |
|
324 | + $decBackendConfig[$key] = $this->decryptBackendConfigProperty($value, $version); |
|
325 | + } |
|
326 | + catch (Exception $e) { |
|
327 | + Logger::error(self::LOG_CONTEXT, sprintf("Unable to decrypt backend configuration: '%s'", $e->getMessage())); |
|
328 | + } |
|
329 | + } |
|
330 | + } |
|
331 | + |
|
332 | + return $decBackendConfig; |
|
333 | + } |
|
334 | + |
|
335 | + /** |
|
336 | + * Encrypt the given string. |
|
337 | + * |
|
338 | + * @param $value |
|
339 | + * @param $version the storage version used to identify what encryption to use |
|
340 | + * |
|
341 | + * @return string |
|
342 | + */ |
|
343 | + private function encryptBackendConfigProperty($value, $version = 0) { |
|
344 | + if ($version == self::ACCOUNT_VERSION && !is_bool($value)) { |
|
345 | + $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); |
|
346 | + $key = $GLOBALS["operations"]->getFilesEncryptionKey(); |
|
347 | + $encrypted = sodium_crypto_secretbox($value, $nonce, $key); |
|
348 | + $value = bin2hex($nonce) . bin2hex($encrypted); |
|
349 | + } |
|
350 | + elseif ($version !== self::ACCOUNT_VERSION) { |
|
351 | + throw Exception("Unable to encrypt backend configuration unsupported version {$version}"); |
|
352 | + } |
|
353 | + |
|
354 | + return $value; |
|
355 | + } |
|
356 | + |
|
357 | + /** |
|
358 | + * Decrypt the given string. |
|
359 | + * |
|
360 | + * @param $value |
|
361 | + * @param $version the storage version used to identify what encryption to use |
|
362 | + * |
|
363 | + * @return string |
|
364 | + */ |
|
365 | + private function decryptBackendConfigProperty($value, $version = 0) { |
|
366 | + if (is_bool($value)) { |
|
367 | + return $value; |
|
368 | + } |
|
369 | + |
|
370 | + if ($version == self::ACCOUNT_VERSION) { |
|
371 | + $value = hex2bin($value); |
|
372 | + $nonce = substr($value, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); |
|
373 | + $encrypted = substr($value, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, strlen($value)); |
|
374 | + $key = $GLOBALS["operations"]->getFilesEncryptionKey(); |
|
375 | + $value = sodium_crypto_secretbox_open($encrypted, $nonce, $key); |
|
376 | + |
|
377 | + // Decryption failed, password might have changed |
|
378 | + if ($value === false) { |
|
379 | + throw new Exception("invalid password"); |
|
380 | + } |
|
381 | + } |
|
382 | + |
|
383 | + return $value; |
|
384 | + } |
|
385 | 385 | } |
@@ -125,8 +125,7 @@ discard block |
||
125 | 125 | // Unable to decrypt, don't update |
126 | 126 | if ($version == 0 && !defined('FILES_PASSWORD_IV') && !defined('FILES_PASSWORD_KEY')) { |
127 | 127 | Logger::error(self::LOG_CONTEXT, "Unable to update the account to as FILES_PASSWORD_IV/FILES_PASSWORD_KEY is not set"); |
128 | - } |
|
129 | - else { |
|
128 | + } else { |
|
130 | 129 | // store all backend configurations |
131 | 130 | foreach ($account->getBackendConfig() as $key => $value) { |
132 | 131 | if ($key !== "version") { |
@@ -228,11 +227,9 @@ discard block |
||
228 | 227 | $backend_config = $this->decryptBackendConfig($acc["backend_config"], $version); |
229 | 228 | // version is lost after decryption, add it again |
230 | 229 | $backend_config["version"] = $version; |
231 | - } |
|
232 | - elseif ($version === 0) { |
|
230 | + } elseif ($version === 0) { |
|
233 | 231 | Logger::error(self::LOG_CONTEXT, "FILES_PASSWORD_IV or FILES_PASSWORD_KEY not set, unable to decrypt backend configuration"); |
234 | - } |
|
235 | - else { |
|
232 | + } else { |
|
236 | 233 | Logger::error(self::LOG_CONTEXT, "Unsupported account version {$version}, unable to decrypt backend configuration"); |
237 | 234 | } |
238 | 235 | |
@@ -268,8 +265,7 @@ discard block |
||
268 | 265 | $backendInstance->open(); |
269 | 266 | $backendInstance->ls("/"); |
270 | 267 | $status = Account::STATUS_OK; |
271 | - } |
|
272 | - catch (BackendException $e) { |
|
268 | + } catch (BackendException $e) { |
|
273 | 269 | $status = Account::STATUS_ERROR; |
274 | 270 | $description = $e->getMessage(); |
275 | 271 | |
@@ -322,8 +318,7 @@ discard block |
||
322 | 318 | if ($key !== "version") { |
323 | 319 | try { |
324 | 320 | $decBackendConfig[$key] = $this->decryptBackendConfigProperty($value, $version); |
325 | - } |
|
326 | - catch (Exception $e) { |
|
321 | + } catch (Exception $e) { |
|
327 | 322 | Logger::error(self::LOG_CONTEXT, sprintf("Unable to decrypt backend configuration: '%s'", $e->getMessage())); |
328 | 323 | } |
329 | 324 | } |
@@ -346,8 +341,7 @@ discard block |
||
346 | 341 | $key = $GLOBALS["operations"]->getFilesEncryptionKey(); |
347 | 342 | $encrypted = sodium_crypto_secretbox($value, $nonce, $key); |
348 | 343 | $value = bin2hex($nonce) . bin2hex($encrypted); |
349 | - } |
|
350 | - elseif ($version !== self::ACCOUNT_VERSION) { |
|
344 | + } elseif ($version !== self::ACCOUNT_VERSION) { |
|
351 | 345 | throw Exception("Unable to encrypt backend configuration unsupported version {$version}"); |
352 | 346 | } |
353 | 347 |
@@ -17,171 +17,171 @@ |
||
17 | 17 | use Files\Core\Util\Logger; |
18 | 18 | |
19 | 19 | class UploadHandler { |
20 | - public const LOG_CONTEXT = "UploadHandler"; // Context for the Logger |
|
21 | - |
|
22 | - public static function doUpload() { |
|
23 | - // parse account id. |
|
24 | - if (isset($_POST["parentID"])) { // will be set if a standard upload is used. |
|
25 | - $dstID = $_POST["parentID"]; |
|
26 | - } |
|
27 | - else { |
|
28 | - if (isset($_SERVER['HTTP_X_FILE_DESTINATION'])) { // will be set if the upload is a ajax upload. |
|
29 | - $dstID = $_SERVER['HTTP_X_FILE_DESTINATION']; |
|
30 | - } |
|
31 | - else { |
|
32 | - Logger::error(self::LOG_CONTEXT, "upload failed: No destination given"); |
|
33 | - echo json_encode(['success' => false, 'response' => 'No destination given', 'message' => 'No destination given']); |
|
34 | - |
|
35 | - exit(); |
|
36 | - } |
|
37 | - } |
|
38 | - |
|
39 | - $accountID = substr($dstID, 3, (strpos($dstID, '/') - 3)); |
|
40 | - |
|
41 | - // relative node ID. We need to trim off the #R# and account ID |
|
42 | - $relNodeId = substr($dstID, strpos($dstID, '/')); |
|
43 | - |
|
44 | - // Initialize the account and backendstore |
|
45 | - $accountStore = new \Files\Core\AccountStore(); |
|
46 | - $backendStore = \Files\Backend\BackendStore::getInstance(); |
|
47 | - |
|
48 | - $account = $accountStore->getAccount($accountID); |
|
49 | - |
|
50 | - // initialize the backend |
|
51 | - $initializedBackend = $backendStore->getInstanceOfBackend($account->getBackend()); |
|
52 | - $initializedBackend->init_backend($account->getBackendConfig()); |
|
53 | - |
|
54 | - try { |
|
55 | - $initializedBackend->open(); |
|
56 | - } |
|
57 | - catch (\Files\Backend\Exception $e) { |
|
58 | - Logger::error(self::LOG_CONTEXT, "backend initialization failed: " . $e->getMessage()); |
|
59 | - echo json_encode(['success' => false, 'response' => $e->getCode(), 'message' => $e->getMessage()]); |
|
60 | - |
|
61 | - exit(); |
|
62 | - } |
|
63 | - |
|
64 | - // check if we are getting the file via the "new" method (ajax - XMLHttpRequest) or the standard way |
|
65 | - if (isset($_SERVER['HTTP_X_FILE_NAME'], $_SERVER['HTTP_X_FILE_SIZE'])) { // use the ajax method |
|
66 | - $targetPath = stringToUTF8Encode($relNodeId . $_SERVER['HTTP_X_FILE_NAME']); |
|
67 | - // check if backend supports streaming - this is the preferred way to upload files! |
|
68 | - if ($initializedBackend->supports(\Files\Backend\BackendStore::FEATURE_STREAMING)) { |
|
69 | - $fileReader = fopen('php://input', "r"); |
|
70 | - $targetPath = UploadHandler::checkFilesNameConflict($targetPath, $initializedBackend, $relNodeId); |
|
71 | - $fileWriter = $initializedBackend->getStreamwriter($targetPath); |
|
72 | - |
|
73 | - while (true) { |
|
74 | - set_time_limit(0); |
|
75 | - $buffer = fgets($fileReader, 4096); |
|
76 | - if (strlen($buffer) == 0) { |
|
77 | - fclose($fileReader); |
|
78 | - fclose($fileWriter); |
|
79 | - break; |
|
80 | - } |
|
81 | - |
|
82 | - fwrite($fileWriter, $buffer); |
|
83 | - } |
|
84 | - } |
|
85 | - else { // fallback to tmp files |
|
86 | - $targetPath = UploadHandler::checkFilesNameConflict($targetPath, $initializedBackend, $relNodeId); |
|
87 | - $targetPath = rawurldecode($targetPath); |
|
88 | - $temp_file = tempnam(TMP_PATH, "{$targetPath}"); |
|
89 | - $fileReader = fopen('php://input', "r"); |
|
90 | - $fileWriter = fopen($temp_file, "w"); |
|
91 | - |
|
92 | - // store post data to tmp file |
|
93 | - while (true) { |
|
94 | - set_time_limit(0); |
|
95 | - $buffer = fgets($fileReader, 4096); |
|
96 | - if (strlen($buffer) == 0) { |
|
97 | - fclose($fileReader); |
|
98 | - fclose($fileWriter); |
|
99 | - break; |
|
100 | - } |
|
101 | - |
|
102 | - fwrite($fileWriter, $buffer); |
|
103 | - } |
|
104 | - |
|
105 | - // upload tmp file to backend |
|
106 | - $initializedBackend->put_file($targetPath, $temp_file); |
|
107 | - // clean up tmp file |
|
108 | - unlink($temp_file); |
|
109 | - } |
|
110 | - echo json_encode(['success' => true, 'parent' => $dstID, 'item' => $targetPath]); |
|
111 | - |
|
112 | - exit(); |
|
113 | - } // upload the standard way with $_FILES |
|
114 | - $items = []; |
|
115 | - |
|
116 | - try { |
|
117 | - for ($i = 0; $i < count($_FILES['attachments']['name']); ++$i) { |
|
118 | - $targetPath = stringToUTF8Encode($relNodeId . $_FILES['attachments']['name'][$i]); |
|
119 | - |
|
120 | - // upload the file |
|
121 | - // check if backend supports streaming - this is the preferred way to upload files! |
|
122 | - if ($initializedBackend->supports(\Files\Backend\BackendStore::FEATURE_STREAMING)) { |
|
123 | - $fileReader = fopen($_FILES['attachments']['tmp_name'][$i], "r"); |
|
124 | - $fileWriter = $initializedBackend->getStreamwriter($targetPath); |
|
125 | - |
|
126 | - while (true) { |
|
127 | - set_time_limit(0); |
|
128 | - $buffer = fgets($fileReader, 4096); |
|
129 | - if (strlen($buffer) == 0) { |
|
130 | - fclose($fileReader); |
|
131 | - fclose($fileWriter); |
|
132 | - break; |
|
133 | - } |
|
134 | - |
|
135 | - fwrite($fileWriter, $buffer); |
|
136 | - } |
|
137 | - } |
|
138 | - else { // use the normal way - might have a high memory footprint |
|
139 | - $initializedBackend->put_file($targetPath, $_FILES['attachments']['tmp_name'][$i]); |
|
140 | - } |
|
141 | - |
|
142 | - $items[] = ['tmp_name' => $_FILES['attachments']['tmp_name'][$i], 'name' => $_FILES['attachments']['name'][$i]]; |
|
143 | - } |
|
144 | - echo json_encode(['success' => true, 'parent' => $dstID, 'items' => $items]); |
|
145 | - |
|
146 | - exit(); |
|
147 | - } |
|
148 | - catch (\Files\Backend\Exception $e) { |
|
149 | - Logger::error(self::LOG_CONTEXT, "upload failed: " . $e->getMessage()); |
|
150 | - echo json_encode(['success' => false, 'response' => $e->getCode(), 'message' => $e->getMessage()]); |
|
151 | - |
|
152 | - exit(); |
|
153 | - } |
|
154 | - } |
|
155 | - |
|
156 | - /** |
|
157 | - * Create a unique file name if file is already exist in backend and user |
|
158 | - * wants to keep both on server. |
|
159 | - * |
|
160 | - * @param string $targetPath targeted files path |
|
161 | - * @param object $initializedBackend Supported abstract backend object (i.e fpt,smb,owncloud etc.. ) |
|
162 | - * @param string $relNodeId relay node id |
|
163 | - * |
|
164 | - * @return string target file path |
|
165 | - */ |
|
166 | - public static function checkFilesNameConflict($targetPath, $initializedBackend, $relNodeId) { |
|
167 | - $keepBoth = isset($_REQUEST["keep_both"]) ? $_REQUEST["keep_both"] : false; |
|
168 | - // Check if file was already exist in directory and $keepBoth is true |
|
169 | - // then append the counter in files name. |
|
170 | - if (strtolower($keepBoth) === 'true') { |
|
171 | - $lsNodes = $initializedBackend->ls($relNodeId); |
|
172 | - $nodeExist = array_key_exists(rawurldecode($targetPath), $lsNodes); |
|
173 | - if ($nodeExist) { |
|
174 | - $i = 1; |
|
175 | - $targetPathInfo = pathinfo($targetPath); |
|
176 | - do { |
|
177 | - $targetPath = $targetPathInfo["dirname"] . "/" . $targetPathInfo["filename"] . " (" . $i . ")." . $targetPathInfo["extension"]; |
|
178 | - $targetPath = str_replace('//', '/', $targetPath); |
|
179 | - ++$i; |
|
180 | - } |
|
181 | - while (array_key_exists(rawurldecode($targetPath), $lsNodes)); |
|
182 | - } |
|
183 | - } |
|
184 | - |
|
185 | - return $targetPath; |
|
186 | - } |
|
20 | + public const LOG_CONTEXT = "UploadHandler"; // Context for the Logger |
|
21 | + |
|
22 | + public static function doUpload() { |
|
23 | + // parse account id. |
|
24 | + if (isset($_POST["parentID"])) { // will be set if a standard upload is used. |
|
25 | + $dstID = $_POST["parentID"]; |
|
26 | + } |
|
27 | + else { |
|
28 | + if (isset($_SERVER['HTTP_X_FILE_DESTINATION'])) { // will be set if the upload is a ajax upload. |
|
29 | + $dstID = $_SERVER['HTTP_X_FILE_DESTINATION']; |
|
30 | + } |
|
31 | + else { |
|
32 | + Logger::error(self::LOG_CONTEXT, "upload failed: No destination given"); |
|
33 | + echo json_encode(['success' => false, 'response' => 'No destination given', 'message' => 'No destination given']); |
|
34 | + |
|
35 | + exit(); |
|
36 | + } |
|
37 | + } |
|
38 | + |
|
39 | + $accountID = substr($dstID, 3, (strpos($dstID, '/') - 3)); |
|
40 | + |
|
41 | + // relative node ID. We need to trim off the #R# and account ID |
|
42 | + $relNodeId = substr($dstID, strpos($dstID, '/')); |
|
43 | + |
|
44 | + // Initialize the account and backendstore |
|
45 | + $accountStore = new \Files\Core\AccountStore(); |
|
46 | + $backendStore = \Files\Backend\BackendStore::getInstance(); |
|
47 | + |
|
48 | + $account = $accountStore->getAccount($accountID); |
|
49 | + |
|
50 | + // initialize the backend |
|
51 | + $initializedBackend = $backendStore->getInstanceOfBackend($account->getBackend()); |
|
52 | + $initializedBackend->init_backend($account->getBackendConfig()); |
|
53 | + |
|
54 | + try { |
|
55 | + $initializedBackend->open(); |
|
56 | + } |
|
57 | + catch (\Files\Backend\Exception $e) { |
|
58 | + Logger::error(self::LOG_CONTEXT, "backend initialization failed: " . $e->getMessage()); |
|
59 | + echo json_encode(['success' => false, 'response' => $e->getCode(), 'message' => $e->getMessage()]); |
|
60 | + |
|
61 | + exit(); |
|
62 | + } |
|
63 | + |
|
64 | + // check if we are getting the file via the "new" method (ajax - XMLHttpRequest) or the standard way |
|
65 | + if (isset($_SERVER['HTTP_X_FILE_NAME'], $_SERVER['HTTP_X_FILE_SIZE'])) { // use the ajax method |
|
66 | + $targetPath = stringToUTF8Encode($relNodeId . $_SERVER['HTTP_X_FILE_NAME']); |
|
67 | + // check if backend supports streaming - this is the preferred way to upload files! |
|
68 | + if ($initializedBackend->supports(\Files\Backend\BackendStore::FEATURE_STREAMING)) { |
|
69 | + $fileReader = fopen('php://input', "r"); |
|
70 | + $targetPath = UploadHandler::checkFilesNameConflict($targetPath, $initializedBackend, $relNodeId); |
|
71 | + $fileWriter = $initializedBackend->getStreamwriter($targetPath); |
|
72 | + |
|
73 | + while (true) { |
|
74 | + set_time_limit(0); |
|
75 | + $buffer = fgets($fileReader, 4096); |
|
76 | + if (strlen($buffer) == 0) { |
|
77 | + fclose($fileReader); |
|
78 | + fclose($fileWriter); |
|
79 | + break; |
|
80 | + } |
|
81 | + |
|
82 | + fwrite($fileWriter, $buffer); |
|
83 | + } |
|
84 | + } |
|
85 | + else { // fallback to tmp files |
|
86 | + $targetPath = UploadHandler::checkFilesNameConflict($targetPath, $initializedBackend, $relNodeId); |
|
87 | + $targetPath = rawurldecode($targetPath); |
|
88 | + $temp_file = tempnam(TMP_PATH, "{$targetPath}"); |
|
89 | + $fileReader = fopen('php://input', "r"); |
|
90 | + $fileWriter = fopen($temp_file, "w"); |
|
91 | + |
|
92 | + // store post data to tmp file |
|
93 | + while (true) { |
|
94 | + set_time_limit(0); |
|
95 | + $buffer = fgets($fileReader, 4096); |
|
96 | + if (strlen($buffer) == 0) { |
|
97 | + fclose($fileReader); |
|
98 | + fclose($fileWriter); |
|
99 | + break; |
|
100 | + } |
|
101 | + |
|
102 | + fwrite($fileWriter, $buffer); |
|
103 | + } |
|
104 | + |
|
105 | + // upload tmp file to backend |
|
106 | + $initializedBackend->put_file($targetPath, $temp_file); |
|
107 | + // clean up tmp file |
|
108 | + unlink($temp_file); |
|
109 | + } |
|
110 | + echo json_encode(['success' => true, 'parent' => $dstID, 'item' => $targetPath]); |
|
111 | + |
|
112 | + exit(); |
|
113 | + } // upload the standard way with $_FILES |
|
114 | + $items = []; |
|
115 | + |
|
116 | + try { |
|
117 | + for ($i = 0; $i < count($_FILES['attachments']['name']); ++$i) { |
|
118 | + $targetPath = stringToUTF8Encode($relNodeId . $_FILES['attachments']['name'][$i]); |
|
119 | + |
|
120 | + // upload the file |
|
121 | + // check if backend supports streaming - this is the preferred way to upload files! |
|
122 | + if ($initializedBackend->supports(\Files\Backend\BackendStore::FEATURE_STREAMING)) { |
|
123 | + $fileReader = fopen($_FILES['attachments']['tmp_name'][$i], "r"); |
|
124 | + $fileWriter = $initializedBackend->getStreamwriter($targetPath); |
|
125 | + |
|
126 | + while (true) { |
|
127 | + set_time_limit(0); |
|
128 | + $buffer = fgets($fileReader, 4096); |
|
129 | + if (strlen($buffer) == 0) { |
|
130 | + fclose($fileReader); |
|
131 | + fclose($fileWriter); |
|
132 | + break; |
|
133 | + } |
|
134 | + |
|
135 | + fwrite($fileWriter, $buffer); |
|
136 | + } |
|
137 | + } |
|
138 | + else { // use the normal way - might have a high memory footprint |
|
139 | + $initializedBackend->put_file($targetPath, $_FILES['attachments']['tmp_name'][$i]); |
|
140 | + } |
|
141 | + |
|
142 | + $items[] = ['tmp_name' => $_FILES['attachments']['tmp_name'][$i], 'name' => $_FILES['attachments']['name'][$i]]; |
|
143 | + } |
|
144 | + echo json_encode(['success' => true, 'parent' => $dstID, 'items' => $items]); |
|
145 | + |
|
146 | + exit(); |
|
147 | + } |
|
148 | + catch (\Files\Backend\Exception $e) { |
|
149 | + Logger::error(self::LOG_CONTEXT, "upload failed: " . $e->getMessage()); |
|
150 | + echo json_encode(['success' => false, 'response' => $e->getCode(), 'message' => $e->getMessage()]); |
|
151 | + |
|
152 | + exit(); |
|
153 | + } |
|
154 | + } |
|
155 | + |
|
156 | + /** |
|
157 | + * Create a unique file name if file is already exist in backend and user |
|
158 | + * wants to keep both on server. |
|
159 | + * |
|
160 | + * @param string $targetPath targeted files path |
|
161 | + * @param object $initializedBackend Supported abstract backend object (i.e fpt,smb,owncloud etc.. ) |
|
162 | + * @param string $relNodeId relay node id |
|
163 | + * |
|
164 | + * @return string target file path |
|
165 | + */ |
|
166 | + public static function checkFilesNameConflict($targetPath, $initializedBackend, $relNodeId) { |
|
167 | + $keepBoth = isset($_REQUEST["keep_both"]) ? $_REQUEST["keep_both"] : false; |
|
168 | + // Check if file was already exist in directory and $keepBoth is true |
|
169 | + // then append the counter in files name. |
|
170 | + if (strtolower($keepBoth) === 'true') { |
|
171 | + $lsNodes = $initializedBackend->ls($relNodeId); |
|
172 | + $nodeExist = array_key_exists(rawurldecode($targetPath), $lsNodes); |
|
173 | + if ($nodeExist) { |
|
174 | + $i = 1; |
|
175 | + $targetPathInfo = pathinfo($targetPath); |
|
176 | + do { |
|
177 | + $targetPath = $targetPathInfo["dirname"] . "/" . $targetPathInfo["filename"] . " (" . $i . ")." . $targetPathInfo["extension"]; |
|
178 | + $targetPath = str_replace('//', '/', $targetPath); |
|
179 | + ++$i; |
|
180 | + } |
|
181 | + while (array_key_exists(rawurldecode($targetPath), $lsNodes)); |
|
182 | + } |
|
183 | + } |
|
184 | + |
|
185 | + return $targetPath; |
|
186 | + } |
|
187 | 187 | } |
@@ -23,12 +23,10 @@ discard block |
||
23 | 23 | // parse account id. |
24 | 24 | if (isset($_POST["parentID"])) { // will be set if a standard upload is used. |
25 | 25 | $dstID = $_POST["parentID"]; |
26 | - } |
|
27 | - else { |
|
26 | + } else { |
|
28 | 27 | if (isset($_SERVER['HTTP_X_FILE_DESTINATION'])) { // will be set if the upload is a ajax upload. |
29 | 28 | $dstID = $_SERVER['HTTP_X_FILE_DESTINATION']; |
30 | - } |
|
31 | - else { |
|
29 | + } else { |
|
32 | 30 | Logger::error(self::LOG_CONTEXT, "upload failed: No destination given"); |
33 | 31 | echo json_encode(['success' => false, 'response' => 'No destination given', 'message' => 'No destination given']); |
34 | 32 | |
@@ -53,8 +51,7 @@ discard block |
||
53 | 51 | |
54 | 52 | try { |
55 | 53 | $initializedBackend->open(); |
56 | - } |
|
57 | - catch (\Files\Backend\Exception $e) { |
|
54 | + } catch (\Files\Backend\Exception $e) { |
|
58 | 55 | Logger::error(self::LOG_CONTEXT, "backend initialization failed: " . $e->getMessage()); |
59 | 56 | echo json_encode(['success' => false, 'response' => $e->getCode(), 'message' => $e->getMessage()]); |
60 | 57 | |
@@ -81,8 +78,7 @@ discard block |
||
81 | 78 | |
82 | 79 | fwrite($fileWriter, $buffer); |
83 | 80 | } |
84 | - } |
|
85 | - else { // fallback to tmp files |
|
81 | + } else { // fallback to tmp files |
|
86 | 82 | $targetPath = UploadHandler::checkFilesNameConflict($targetPath, $initializedBackend, $relNodeId); |
87 | 83 | $targetPath = rawurldecode($targetPath); |
88 | 84 | $temp_file = tempnam(TMP_PATH, "{$targetPath}"); |
@@ -134,8 +130,7 @@ discard block |
||
134 | 130 | |
135 | 131 | fwrite($fileWriter, $buffer); |
136 | 132 | } |
137 | - } |
|
138 | - else { // use the normal way - might have a high memory footprint |
|
133 | + } else { // use the normal way - might have a high memory footprint |
|
139 | 134 | $initializedBackend->put_file($targetPath, $_FILES['attachments']['tmp_name'][$i]); |
140 | 135 | } |
141 | 136 | |
@@ -144,8 +139,7 @@ discard block |
||
144 | 139 | echo json_encode(['success' => true, 'parent' => $dstID, 'items' => $items]); |
145 | 140 | |
146 | 141 | exit(); |
147 | - } |
|
148 | - catch (\Files\Backend\Exception $e) { |
|
142 | + } catch (\Files\Backend\Exception $e) { |
|
149 | 143 | Logger::error(self::LOG_CONTEXT, "upload failed: " . $e->getMessage()); |
150 | 144 | echo json_encode(['success' => false, 'response' => $e->getCode(), 'message' => $e->getMessage()]); |
151 | 145 |
@@ -17,156 +17,156 @@ |
||
17 | 17 | use Files\Core\Util\PathUtil; |
18 | 18 | |
19 | 19 | class DownloadHandler { |
20 | - public const LOG_CONTEXT = "DownloadHandler"; // Context for the Logger |
|
21 | - |
|
22 | - public static function doDownload() { |
|
23 | - // parse account id. |
|
24 | - // wo only need to parse one string because it is |
|
25 | - // only possible to download files from one backend at a time. |
|
26 | - if (isset($_GET["ids"])) { |
|
27 | - $tmpId = $_GET["ids"][0]; |
|
28 | - } |
|
29 | - else { |
|
30 | - $tmpId = $_GET["id"]; |
|
31 | - } |
|
32 | - $accountID = substr($tmpId, 3, (strpos($tmpId, '/') - 3)); |
|
33 | - |
|
34 | - // Initialize the account and backendstore |
|
35 | - $accountStore = new \Files\Core\AccountStore(); |
|
36 | - $backendStore = \Files\Backend\BackendStore::getInstance(); |
|
37 | - |
|
38 | - $account = $accountStore->getAccount($accountID); |
|
39 | - |
|
40 | - // initialize the backend |
|
41 | - $initializedBackend = $backendStore->getInstanceOfBackend($account->getBackend()); |
|
42 | - $initializedBackend->init_backend($account->getBackendConfig()); |
|
43 | - |
|
44 | - try { |
|
45 | - $initializedBackend->open(); |
|
46 | - } |
|
47 | - catch (\Files\Backend\Exception $e) { |
|
48 | - Logger::error(self::LOG_CONTEXT, "Could not open the backend: " . $e->getMessage()); |
|
49 | - |
|
50 | - if ((isset($_GET["inline"]) && $_GET["inline"] == "false") || (isset($_GET["contentDispositionType"]) && $_GET["contentDispositionType"] == "attachment")) { |
|
51 | - // Javascript error message |
|
52 | - echo "<script>alert('" . _('File backend not responding. Please try again later.') . "');</script>"; |
|
53 | - } |
|
54 | - else { |
|
55 | - // Text error message that is shown in the preview box |
|
56 | - echo _('File backend not responding. Please try again later.'); |
|
57 | - } |
|
58 | - |
|
59 | - exit(); |
|
60 | - } |
|
61 | - |
|
62 | - try { |
|
63 | - if (isset($_GET["ids"])) { |
|
64 | - $zip = new \ZipArchive(); |
|
65 | - $zipname = TMP_PATH . '/files_' . date("dmY_Hi") . '.zip'; |
|
66 | - Logger::debug(self::LOG_CONTEXT, "Download file tmp path: " . $zipname); |
|
67 | - $res = $zip->open($zipname, \ZipArchive::CREATE); |
|
68 | - if ($res !== true) { |
|
69 | - Logger::error(self::LOG_CONTEXT, "Zip creation failed: " . $res); |
|
70 | - echo "<script>alert('" . _('Zip file generation failed. Please inform the administrator.') . "');</script>"; |
|
71 | - |
|
72 | - exit(); |
|
73 | - } |
|
74 | - $i = 0; |
|
75 | - $tmpfiles = []; |
|
76 | - foreach ($_GET["ids"] as $id) { |
|
77 | - // relative node ID. We need to trim off the #R# and account ID |
|
78 | - $relNodeId = substr($id, strpos($id, '/')); |
|
79 | - |
|
80 | - $tmpfiles[$i] = tempnam(TMP_PATH, stripslashes(base64_encode($relNodeId))); |
|
81 | - $initializedBackend->get_file($relNodeId, $tmpfiles[$i]); |
|
82 | - |
|
83 | - $res = $zip->addFile($tmpfiles[$i], PathUtil::getFilenameFromPath($relNodeId)); |
|
84 | - ++$i; |
|
85 | - if ($res !== true) { |
|
86 | - Logger::error(self::LOG_CONTEXT, "Zip addFile failed: " . $res . " file: " . $tmpfiles[$i] . " id: " . $relNodeId); |
|
87 | - echo "<script>alert('" . _('Zip file generation failed. Please inform the administrator.') . "');</script>"; |
|
88 | - |
|
89 | - exit(); |
|
90 | - } |
|
91 | - } |
|
92 | - $zip->close(); |
|
93 | - |
|
94 | - // no caching |
|
95 | - header('Content-Disposition: attachment; filename="' . basename($zipname) . '"'); |
|
96 | - header("Expires: 0"); // set expiration time |
|
97 | - header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); |
|
98 | - header('Content-Length: ' . filesize($zipname)); |
|
99 | - header('Content-Type: application/zip'); |
|
100 | - readfile($zipname); |
|
101 | - unlink($zipname); |
|
102 | - foreach ($tmpfiles as $tmpfile) { |
|
103 | - unlink($tmpfile); |
|
104 | - } |
|
105 | - |
|
106 | - exit(); |
|
107 | - } |
|
108 | - // relative node ID. We need to trim off the #R# and account ID |
|
109 | - $relNodeId = substr($_GET["id"], strpos($_GET["id"], '/')); |
|
110 | - $stream = false; |
|
111 | - |
|
112 | - if (!$initializedBackend->supports(\Files\Backend\BackendStore::FEATURE_STREAMING)) { |
|
113 | - $tmpfile = tempnam(TMP_PATH, stripslashes(base64_encode($relNodeId))); |
|
114 | - $initializedBackend->get_file($relNodeId, $tmpfile); |
|
115 | - $filesize = filesize($tmpfile); |
|
116 | - } |
|
117 | - else { |
|
118 | - $gpi = $initializedBackend->gpi($relNodeId); |
|
119 | - $stream = true; |
|
120 | - $filesize = $gpi["getcontentlength"]; |
|
121 | - } |
|
122 | - |
|
123 | - $mime = PathUtil::get_mime($relNodeId); |
|
124 | - |
|
125 | - // set headers here |
|
126 | - if ((isset($_GET["inline"]) && $_GET["inline"] == "false") || (isset($_GET["contentDispositionType"]) && $_GET["contentDispositionType"] == "attachment")) { |
|
127 | - header('Content-Disposition: attachment; filename="' . PathUtil::getFilenameFromPath($relNodeId) . '"'); |
|
128 | - } |
|
129 | - |
|
130 | - // no caching |
|
131 | - header("Expires: 0"); // set expiration time |
|
132 | - header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); |
|
133 | - header('Content-Length: ' . $filesize); |
|
134 | - header('Content-Type: ' . $mime); |
|
135 | - flush(); |
|
136 | - |
|
137 | - if (!$stream) { |
|
138 | - // print the downloaded file |
|
139 | - readfile($tmpfile); |
|
140 | - ignore_user_abort(true); |
|
141 | - unlink($tmpfile); |
|
142 | - } |
|
143 | - else { |
|
144 | - // stream the file directly from the backend - much faster |
|
145 | - $fh = $initializedBackend->getStreamReader($relNodeId); |
|
146 | - while (!feof($fh)) { |
|
147 | - set_time_limit(0); |
|
148 | - echo fread($fh, 4096); |
|
149 | - ob_flush(); |
|
150 | - flush(); |
|
151 | - } |
|
152 | - fclose($fh); |
|
153 | - } |
|
154 | - |
|
155 | - exit(); |
|
156 | - } |
|
157 | - catch (\Files\Backend\Exception $e) { |
|
158 | - Logger::error(self::LOG_CONTEXT, "Downloading failed: " . $e->getMessage()); |
|
159 | - |
|
160 | - if (isset($_GET["inline"]) && $_GET["inline"] == "false") { |
|
161 | - // Javascript error message |
|
162 | - echo "<script>alert('" . _('This file is no longer available. Please reload the folder.') . "');</script>"; |
|
163 | - } |
|
164 | - else { |
|
165 | - // Text error message that is shown in the preview box |
|
166 | - echo _('This file is no longer available. Please reload the folder.'); |
|
167 | - } |
|
168 | - |
|
169 | - exit(); |
|
170 | - } |
|
171 | - } |
|
20 | + public const LOG_CONTEXT = "DownloadHandler"; // Context for the Logger |
|
21 | + |
|
22 | + public static function doDownload() { |
|
23 | + // parse account id. |
|
24 | + // wo only need to parse one string because it is |
|
25 | + // only possible to download files from one backend at a time. |
|
26 | + if (isset($_GET["ids"])) { |
|
27 | + $tmpId = $_GET["ids"][0]; |
|
28 | + } |
|
29 | + else { |
|
30 | + $tmpId = $_GET["id"]; |
|
31 | + } |
|
32 | + $accountID = substr($tmpId, 3, (strpos($tmpId, '/') - 3)); |
|
33 | + |
|
34 | + // Initialize the account and backendstore |
|
35 | + $accountStore = new \Files\Core\AccountStore(); |
|
36 | + $backendStore = \Files\Backend\BackendStore::getInstance(); |
|
37 | + |
|
38 | + $account = $accountStore->getAccount($accountID); |
|
39 | + |
|
40 | + // initialize the backend |
|
41 | + $initializedBackend = $backendStore->getInstanceOfBackend($account->getBackend()); |
|
42 | + $initializedBackend->init_backend($account->getBackendConfig()); |
|
43 | + |
|
44 | + try { |
|
45 | + $initializedBackend->open(); |
|
46 | + } |
|
47 | + catch (\Files\Backend\Exception $e) { |
|
48 | + Logger::error(self::LOG_CONTEXT, "Could not open the backend: " . $e->getMessage()); |
|
49 | + |
|
50 | + if ((isset($_GET["inline"]) && $_GET["inline"] == "false") || (isset($_GET["contentDispositionType"]) && $_GET["contentDispositionType"] == "attachment")) { |
|
51 | + // Javascript error message |
|
52 | + echo "<script>alert('" . _('File backend not responding. Please try again later.') . "');</script>"; |
|
53 | + } |
|
54 | + else { |
|
55 | + // Text error message that is shown in the preview box |
|
56 | + echo _('File backend not responding. Please try again later.'); |
|
57 | + } |
|
58 | + |
|
59 | + exit(); |
|
60 | + } |
|
61 | + |
|
62 | + try { |
|
63 | + if (isset($_GET["ids"])) { |
|
64 | + $zip = new \ZipArchive(); |
|
65 | + $zipname = TMP_PATH . '/files_' . date("dmY_Hi") . '.zip'; |
|
66 | + Logger::debug(self::LOG_CONTEXT, "Download file tmp path: " . $zipname); |
|
67 | + $res = $zip->open($zipname, \ZipArchive::CREATE); |
|
68 | + if ($res !== true) { |
|
69 | + Logger::error(self::LOG_CONTEXT, "Zip creation failed: " . $res); |
|
70 | + echo "<script>alert('" . _('Zip file generation failed. Please inform the administrator.') . "');</script>"; |
|
71 | + |
|
72 | + exit(); |
|
73 | + } |
|
74 | + $i = 0; |
|
75 | + $tmpfiles = []; |
|
76 | + foreach ($_GET["ids"] as $id) { |
|
77 | + // relative node ID. We need to trim off the #R# and account ID |
|
78 | + $relNodeId = substr($id, strpos($id, '/')); |
|
79 | + |
|
80 | + $tmpfiles[$i] = tempnam(TMP_PATH, stripslashes(base64_encode($relNodeId))); |
|
81 | + $initializedBackend->get_file($relNodeId, $tmpfiles[$i]); |
|
82 | + |
|
83 | + $res = $zip->addFile($tmpfiles[$i], PathUtil::getFilenameFromPath($relNodeId)); |
|
84 | + ++$i; |
|
85 | + if ($res !== true) { |
|
86 | + Logger::error(self::LOG_CONTEXT, "Zip addFile failed: " . $res . " file: " . $tmpfiles[$i] . " id: " . $relNodeId); |
|
87 | + echo "<script>alert('" . _('Zip file generation failed. Please inform the administrator.') . "');</script>"; |
|
88 | + |
|
89 | + exit(); |
|
90 | + } |
|
91 | + } |
|
92 | + $zip->close(); |
|
93 | + |
|
94 | + // no caching |
|
95 | + header('Content-Disposition: attachment; filename="' . basename($zipname) . '"'); |
|
96 | + header("Expires: 0"); // set expiration time |
|
97 | + header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); |
|
98 | + header('Content-Length: ' . filesize($zipname)); |
|
99 | + header('Content-Type: application/zip'); |
|
100 | + readfile($zipname); |
|
101 | + unlink($zipname); |
|
102 | + foreach ($tmpfiles as $tmpfile) { |
|
103 | + unlink($tmpfile); |
|
104 | + } |
|
105 | + |
|
106 | + exit(); |
|
107 | + } |
|
108 | + // relative node ID. We need to trim off the #R# and account ID |
|
109 | + $relNodeId = substr($_GET["id"], strpos($_GET["id"], '/')); |
|
110 | + $stream = false; |
|
111 | + |
|
112 | + if (!$initializedBackend->supports(\Files\Backend\BackendStore::FEATURE_STREAMING)) { |
|
113 | + $tmpfile = tempnam(TMP_PATH, stripslashes(base64_encode($relNodeId))); |
|
114 | + $initializedBackend->get_file($relNodeId, $tmpfile); |
|
115 | + $filesize = filesize($tmpfile); |
|
116 | + } |
|
117 | + else { |
|
118 | + $gpi = $initializedBackend->gpi($relNodeId); |
|
119 | + $stream = true; |
|
120 | + $filesize = $gpi["getcontentlength"]; |
|
121 | + } |
|
122 | + |
|
123 | + $mime = PathUtil::get_mime($relNodeId); |
|
124 | + |
|
125 | + // set headers here |
|
126 | + if ((isset($_GET["inline"]) && $_GET["inline"] == "false") || (isset($_GET["contentDispositionType"]) && $_GET["contentDispositionType"] == "attachment")) { |
|
127 | + header('Content-Disposition: attachment; filename="' . PathUtil::getFilenameFromPath($relNodeId) . '"'); |
|
128 | + } |
|
129 | + |
|
130 | + // no caching |
|
131 | + header("Expires: 0"); // set expiration time |
|
132 | + header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); |
|
133 | + header('Content-Length: ' . $filesize); |
|
134 | + header('Content-Type: ' . $mime); |
|
135 | + flush(); |
|
136 | + |
|
137 | + if (!$stream) { |
|
138 | + // print the downloaded file |
|
139 | + readfile($tmpfile); |
|
140 | + ignore_user_abort(true); |
|
141 | + unlink($tmpfile); |
|
142 | + } |
|
143 | + else { |
|
144 | + // stream the file directly from the backend - much faster |
|
145 | + $fh = $initializedBackend->getStreamReader($relNodeId); |
|
146 | + while (!feof($fh)) { |
|
147 | + set_time_limit(0); |
|
148 | + echo fread($fh, 4096); |
|
149 | + ob_flush(); |
|
150 | + flush(); |
|
151 | + } |
|
152 | + fclose($fh); |
|
153 | + } |
|
154 | + |
|
155 | + exit(); |
|
156 | + } |
|
157 | + catch (\Files\Backend\Exception $e) { |
|
158 | + Logger::error(self::LOG_CONTEXT, "Downloading failed: " . $e->getMessage()); |
|
159 | + |
|
160 | + if (isset($_GET["inline"]) && $_GET["inline"] == "false") { |
|
161 | + // Javascript error message |
|
162 | + echo "<script>alert('" . _('This file is no longer available. Please reload the folder.') . "');</script>"; |
|
163 | + } |
|
164 | + else { |
|
165 | + // Text error message that is shown in the preview box |
|
166 | + echo _('This file is no longer available. Please reload the folder.'); |
|
167 | + } |
|
168 | + |
|
169 | + exit(); |
|
170 | + } |
|
171 | + } |
|
172 | 172 | } |
@@ -25,8 +25,7 @@ discard block |
||
25 | 25 | // only possible to download files from one backend at a time. |
26 | 26 | if (isset($_GET["ids"])) { |
27 | 27 | $tmpId = $_GET["ids"][0]; |
28 | - } |
|
29 | - else { |
|
28 | + } else { |
|
30 | 29 | $tmpId = $_GET["id"]; |
31 | 30 | } |
32 | 31 | $accountID = substr($tmpId, 3, (strpos($tmpId, '/') - 3)); |
@@ -43,15 +42,13 @@ discard block |
||
43 | 42 | |
44 | 43 | try { |
45 | 44 | $initializedBackend->open(); |
46 | - } |
|
47 | - catch (\Files\Backend\Exception $e) { |
|
45 | + } catch (\Files\Backend\Exception $e) { |
|
48 | 46 | Logger::error(self::LOG_CONTEXT, "Could not open the backend: " . $e->getMessage()); |
49 | 47 | |
50 | 48 | if ((isset($_GET["inline"]) && $_GET["inline"] == "false") || (isset($_GET["contentDispositionType"]) && $_GET["contentDispositionType"] == "attachment")) { |
51 | 49 | // Javascript error message |
52 | 50 | echo "<script>alert('" . _('File backend not responding. Please try again later.') . "');</script>"; |
53 | - } |
|
54 | - else { |
|
51 | + } else { |
|
55 | 52 | // Text error message that is shown in the preview box |
56 | 53 | echo _('File backend not responding. Please try again later.'); |
57 | 54 | } |
@@ -113,8 +110,7 @@ discard block |
||
113 | 110 | $tmpfile = tempnam(TMP_PATH, stripslashes(base64_encode($relNodeId))); |
114 | 111 | $initializedBackend->get_file($relNodeId, $tmpfile); |
115 | 112 | $filesize = filesize($tmpfile); |
116 | - } |
|
117 | - else { |
|
113 | + } else { |
|
118 | 114 | $gpi = $initializedBackend->gpi($relNodeId); |
119 | 115 | $stream = true; |
120 | 116 | $filesize = $gpi["getcontentlength"]; |
@@ -139,8 +135,7 @@ discard block |
||
139 | 135 | readfile($tmpfile); |
140 | 136 | ignore_user_abort(true); |
141 | 137 | unlink($tmpfile); |
142 | - } |
|
143 | - else { |
|
138 | + } else { |
|
144 | 139 | // stream the file directly from the backend - much faster |
145 | 140 | $fh = $initializedBackend->getStreamReader($relNodeId); |
146 | 141 | while (!feof($fh)) { |
@@ -153,15 +148,13 @@ discard block |
||
153 | 148 | } |
154 | 149 | |
155 | 150 | exit(); |
156 | - } |
|
157 | - catch (\Files\Backend\Exception $e) { |
|
151 | + } catch (\Files\Backend\Exception $e) { |
|
158 | 152 | Logger::error(self::LOG_CONTEXT, "Downloading failed: " . $e->getMessage()); |
159 | 153 | |
160 | 154 | if (isset($_GET["inline"]) && $_GET["inline"] == "false") { |
161 | 155 | // Javascript error message |
162 | 156 | echo "<script>alert('" . _('This file is no longer available. Please reload the folder.') . "');</script>"; |
163 | - } |
|
164 | - else { |
|
157 | + } else { |
|
165 | 158 | // Text error message that is shown in the preview box |
166 | 159 | echo _('This file is no longer available. Please reload the folder.'); |
167 | 160 | } |
@@ -10,205 +10,205 @@ |
||
10 | 10 | use Files\Backend\BackendStore; |
11 | 11 | |
12 | 12 | class Account { |
13 | - private $id; |
|
14 | - private $name; // account name - for better usability |
|
15 | - private $status; |
|
16 | - private $statusDescription; |
|
17 | - private $backend; |
|
18 | - private $backendConfig; // This array will hold the backend configuration variables |
|
19 | - private $features; |
|
20 | - private $sequence; // for ordering |
|
21 | - private $cannot_change; // for locking accounts |
|
22 | - |
|
23 | - /** |
|
24 | - * Status variables. |
|
25 | - */ |
|
26 | - public const STATUS_NEW = "new"; |
|
27 | - public const STATUS_OK = "ok"; |
|
28 | - public const STATUS_ERROR = "err"; |
|
29 | - public const STATUS_UNKNOWN = "unk"; |
|
30 | - |
|
31 | - /** |
|
32 | - * @param $id |
|
33 | - * @param $name |
|
34 | - * @param $status |
|
35 | - * @param $statusDescription |
|
36 | - * @param $backend |
|
37 | - * @param $backendConfig |
|
38 | - * @param array $features |
|
39 | - * @param mixed $sequence |
|
40 | - * @param mixed $cannot_change |
|
41 | - */ |
|
42 | - public function __construct($id, $name, $status, $statusDescription, $backend, $backendConfig, $features = [], $sequence, $cannot_change) { |
|
43 | - $this->id = $id; |
|
44 | - $this->name = $name; |
|
45 | - $this->status = $status; |
|
46 | - $this->statusDescription = $statusDescription; |
|
47 | - $this->backend = $backend; |
|
48 | - $this->backendConfig = $backendConfig; |
|
49 | - $this->features = $features; |
|
50 | - $this->sequence = $sequence; |
|
51 | - $this->cannot_change = $cannot_change; |
|
52 | - } |
|
53 | - |
|
54 | - /** |
|
55 | - * @return mixed |
|
56 | - */ |
|
57 | - public function getBackend() { |
|
58 | - return $this->backend; |
|
59 | - } |
|
60 | - |
|
61 | - /** |
|
62 | - * @param mixed $backend |
|
63 | - */ |
|
64 | - public function setBackend($backend) { |
|
65 | - $this->backend = $backend; |
|
66 | - } |
|
67 | - |
|
68 | - /** |
|
69 | - * @return mixed |
|
70 | - */ |
|
71 | - public function getId() { |
|
72 | - return $this->id; |
|
73 | - } |
|
74 | - |
|
75 | - /** |
|
76 | - * @param mixed $id |
|
77 | - */ |
|
78 | - public function setId($id) { |
|
79 | - $this->id = $id; |
|
80 | - } |
|
81 | - |
|
82 | - /** |
|
83 | - * @return mixed |
|
84 | - */ |
|
85 | - public function getName() { |
|
86 | - return $this->name; |
|
87 | - } |
|
88 | - |
|
89 | - /** |
|
90 | - * @param mixed $name |
|
91 | - */ |
|
92 | - public function setName($name) { |
|
93 | - $this->name = $name; |
|
94 | - } |
|
95 | - |
|
96 | - /** |
|
97 | - * @return mixed |
|
98 | - */ |
|
99 | - public function getStatus() { |
|
100 | - return $this->status; |
|
101 | - } |
|
102 | - |
|
103 | - /** |
|
104 | - * @param mixed $status |
|
105 | - */ |
|
106 | - public function setStatus($status) { |
|
107 | - $this->status = $status; |
|
108 | - } |
|
109 | - |
|
110 | - /** |
|
111 | - * @return mixed |
|
112 | - */ |
|
113 | - public function getBackendConfig() { |
|
114 | - // always add the accountID to the backendConfig |
|
115 | - $this->backendConfig["current_account_id"] = $this->getId(); |
|
116 | - |
|
117 | - return $this->backendConfig; |
|
118 | - } |
|
119 | - |
|
120 | - /** |
|
121 | - * @param mixed $backendConfig |
|
122 | - */ |
|
123 | - public function setBackendConfig($backendConfig) { |
|
124 | - $this->backendConfig = $backendConfig; |
|
125 | - } |
|
126 | - |
|
127 | - /** |
|
128 | - * @return mixed |
|
129 | - */ |
|
130 | - public function getFeatures() { |
|
131 | - return $this->features; |
|
132 | - } |
|
133 | - |
|
134 | - /** |
|
135 | - * @param mixed $features |
|
136 | - */ |
|
137 | - public function setFeatures($features) { |
|
138 | - $this->features = $features; |
|
139 | - } |
|
140 | - |
|
141 | - /** |
|
142 | - * @return string |
|
143 | - */ |
|
144 | - public function getStatusDescription() { |
|
145 | - return $this->statusDescription; |
|
146 | - } |
|
147 | - |
|
148 | - /** |
|
149 | - * @param string $statusDescription |
|
150 | - */ |
|
151 | - public function setStatusDescription($statusDescription) { |
|
152 | - $this->statusDescription = $statusDescription; |
|
153 | - } |
|
154 | - |
|
155 | - /** |
|
156 | - * @param $property |
|
157 | - * |
|
158 | - * @return mixed |
|
159 | - */ |
|
160 | - public function getConfigValue($property) { |
|
161 | - if (is_array($this->backendConfig) && in_array($property, $this->backendConfig)) { |
|
162 | - return $this->backendConfig[$property]; |
|
163 | - } |
|
164 | - |
|
165 | - return false; |
|
166 | - } |
|
167 | - |
|
168 | - /** |
|
169 | - * @param $property |
|
170 | - * @param $value |
|
171 | - */ |
|
172 | - public function setConfigValue($property, $value) { |
|
173 | - if (!is_array($this->backendConfig)) { |
|
174 | - $this->backendConfig = []; |
|
175 | - } |
|
176 | - $this->backendConfig[$property] = $value; |
|
177 | - } |
|
178 | - |
|
179 | - /** |
|
180 | - * This function is executed before the account gets deleted. |
|
181 | - */ |
|
182 | - public function beforeDelete() { |
|
183 | - $backendstore = BackendStore::getInstance(); |
|
184 | - $backendinstance = $backendstore->getInstanceOfBackend($this->backend); |
|
185 | - $backendinstance->init_backend($this->backendConfig); |
|
186 | - $backendinstance->open(); |
|
187 | - $backendinstance->beforeDeleteAccount($this); |
|
188 | - } |
|
189 | - |
|
190 | - /** |
|
191 | - * @return int |
|
192 | - */ |
|
193 | - public function getSequence() { |
|
194 | - if (!$this->sequence) { |
|
195 | - $this->sequence = 0; |
|
196 | - } |
|
197 | - |
|
198 | - return $this->sequence; |
|
199 | - } |
|
200 | - |
|
201 | - /** |
|
202 | - * @param int $sequence |
|
203 | - */ |
|
204 | - public function setSequence($sequence) { |
|
205 | - $this->sequence = $sequence; |
|
206 | - } |
|
207 | - |
|
208 | - /** |
|
209 | - * @return bool |
|
210 | - */ |
|
211 | - public function getCannotChangeFlag() { |
|
212 | - return isset($this->cannot_change) ? $this->cannot_change : false; |
|
213 | - } |
|
13 | + private $id; |
|
14 | + private $name; // account name - for better usability |
|
15 | + private $status; |
|
16 | + private $statusDescription; |
|
17 | + private $backend; |
|
18 | + private $backendConfig; // This array will hold the backend configuration variables |
|
19 | + private $features; |
|
20 | + private $sequence; // for ordering |
|
21 | + private $cannot_change; // for locking accounts |
|
22 | + |
|
23 | + /** |
|
24 | + * Status variables. |
|
25 | + */ |
|
26 | + public const STATUS_NEW = "new"; |
|
27 | + public const STATUS_OK = "ok"; |
|
28 | + public const STATUS_ERROR = "err"; |
|
29 | + public const STATUS_UNKNOWN = "unk"; |
|
30 | + |
|
31 | + /** |
|
32 | + * @param $id |
|
33 | + * @param $name |
|
34 | + * @param $status |
|
35 | + * @param $statusDescription |
|
36 | + * @param $backend |
|
37 | + * @param $backendConfig |
|
38 | + * @param array $features |
|
39 | + * @param mixed $sequence |
|
40 | + * @param mixed $cannot_change |
|
41 | + */ |
|
42 | + public function __construct($id, $name, $status, $statusDescription, $backend, $backendConfig, $features = [], $sequence, $cannot_change) { |
|
43 | + $this->id = $id; |
|
44 | + $this->name = $name; |
|
45 | + $this->status = $status; |
|
46 | + $this->statusDescription = $statusDescription; |
|
47 | + $this->backend = $backend; |
|
48 | + $this->backendConfig = $backendConfig; |
|
49 | + $this->features = $features; |
|
50 | + $this->sequence = $sequence; |
|
51 | + $this->cannot_change = $cannot_change; |
|
52 | + } |
|
53 | + |
|
54 | + /** |
|
55 | + * @return mixed |
|
56 | + */ |
|
57 | + public function getBackend() { |
|
58 | + return $this->backend; |
|
59 | + } |
|
60 | + |
|
61 | + /** |
|
62 | + * @param mixed $backend |
|
63 | + */ |
|
64 | + public function setBackend($backend) { |
|
65 | + $this->backend = $backend; |
|
66 | + } |
|
67 | + |
|
68 | + /** |
|
69 | + * @return mixed |
|
70 | + */ |
|
71 | + public function getId() { |
|
72 | + return $this->id; |
|
73 | + } |
|
74 | + |
|
75 | + /** |
|
76 | + * @param mixed $id |
|
77 | + */ |
|
78 | + public function setId($id) { |
|
79 | + $this->id = $id; |
|
80 | + } |
|
81 | + |
|
82 | + /** |
|
83 | + * @return mixed |
|
84 | + */ |
|
85 | + public function getName() { |
|
86 | + return $this->name; |
|
87 | + } |
|
88 | + |
|
89 | + /** |
|
90 | + * @param mixed $name |
|
91 | + */ |
|
92 | + public function setName($name) { |
|
93 | + $this->name = $name; |
|
94 | + } |
|
95 | + |
|
96 | + /** |
|
97 | + * @return mixed |
|
98 | + */ |
|
99 | + public function getStatus() { |
|
100 | + return $this->status; |
|
101 | + } |
|
102 | + |
|
103 | + /** |
|
104 | + * @param mixed $status |
|
105 | + */ |
|
106 | + public function setStatus($status) { |
|
107 | + $this->status = $status; |
|
108 | + } |
|
109 | + |
|
110 | + /** |
|
111 | + * @return mixed |
|
112 | + */ |
|
113 | + public function getBackendConfig() { |
|
114 | + // always add the accountID to the backendConfig |
|
115 | + $this->backendConfig["current_account_id"] = $this->getId(); |
|
116 | + |
|
117 | + return $this->backendConfig; |
|
118 | + } |
|
119 | + |
|
120 | + /** |
|
121 | + * @param mixed $backendConfig |
|
122 | + */ |
|
123 | + public function setBackendConfig($backendConfig) { |
|
124 | + $this->backendConfig = $backendConfig; |
|
125 | + } |
|
126 | + |
|
127 | + /** |
|
128 | + * @return mixed |
|
129 | + */ |
|
130 | + public function getFeatures() { |
|
131 | + return $this->features; |
|
132 | + } |
|
133 | + |
|
134 | + /** |
|
135 | + * @param mixed $features |
|
136 | + */ |
|
137 | + public function setFeatures($features) { |
|
138 | + $this->features = $features; |
|
139 | + } |
|
140 | + |
|
141 | + /** |
|
142 | + * @return string |
|
143 | + */ |
|
144 | + public function getStatusDescription() { |
|
145 | + return $this->statusDescription; |
|
146 | + } |
|
147 | + |
|
148 | + /** |
|
149 | + * @param string $statusDescription |
|
150 | + */ |
|
151 | + public function setStatusDescription($statusDescription) { |
|
152 | + $this->statusDescription = $statusDescription; |
|
153 | + } |
|
154 | + |
|
155 | + /** |
|
156 | + * @param $property |
|
157 | + * |
|
158 | + * @return mixed |
|
159 | + */ |
|
160 | + public function getConfigValue($property) { |
|
161 | + if (is_array($this->backendConfig) && in_array($property, $this->backendConfig)) { |
|
162 | + return $this->backendConfig[$property]; |
|
163 | + } |
|
164 | + |
|
165 | + return false; |
|
166 | + } |
|
167 | + |
|
168 | + /** |
|
169 | + * @param $property |
|
170 | + * @param $value |
|
171 | + */ |
|
172 | + public function setConfigValue($property, $value) { |
|
173 | + if (!is_array($this->backendConfig)) { |
|
174 | + $this->backendConfig = []; |
|
175 | + } |
|
176 | + $this->backendConfig[$property] = $value; |
|
177 | + } |
|
178 | + |
|
179 | + /** |
|
180 | + * This function is executed before the account gets deleted. |
|
181 | + */ |
|
182 | + public function beforeDelete() { |
|
183 | + $backendstore = BackendStore::getInstance(); |
|
184 | + $backendinstance = $backendstore->getInstanceOfBackend($this->backend); |
|
185 | + $backendinstance->init_backend($this->backendConfig); |
|
186 | + $backendinstance->open(); |
|
187 | + $backendinstance->beforeDeleteAccount($this); |
|
188 | + } |
|
189 | + |
|
190 | + /** |
|
191 | + * @return int |
|
192 | + */ |
|
193 | + public function getSequence() { |
|
194 | + if (!$this->sequence) { |
|
195 | + $this->sequence = 0; |
|
196 | + } |
|
197 | + |
|
198 | + return $this->sequence; |
|
199 | + } |
|
200 | + |
|
201 | + /** |
|
202 | + * @param int $sequence |
|
203 | + */ |
|
204 | + public function setSequence($sequence) { |
|
205 | + $this->sequence = $sequence; |
|
206 | + } |
|
207 | + |
|
208 | + /** |
|
209 | + * @return bool |
|
210 | + */ |
|
211 | + public function getCannotChangeFlag() { |
|
212 | + return isset($this->cannot_change) ? $this->cannot_change : false; |
|
213 | + } |
|
214 | 214 | } |
@@ -10,41 +10,41 @@ |
||
10 | 10 | use Files\Core\Util\Logger; |
11 | 11 | |
12 | 12 | class RecipientHandler { |
13 | - public const LOG_CONTEXT = "RecipientHandler"; // Context for the Logger |
|
14 | - |
|
15 | - public static function doGetRecipients() { |
|
16 | - // parse account id. |
|
17 | - // wo only need to parse one string because it is |
|
18 | - // only possible to download files from one backend at a time. |
|
19 | - if (isset($_GET["ids"])) { |
|
20 | - $tmpId = $_GET["ids"][0]; |
|
21 | - } |
|
22 | - else { |
|
23 | - $tmpId = $_GET["id"]; |
|
24 | - } |
|
25 | - $accountID = substr($tmpId, 3, (strpos($tmpId, '/') - 3)); |
|
26 | - |
|
27 | - // Initialize the account and backendstore |
|
28 | - $accountStore = new \Files\Core\AccountStore(); |
|
29 | - $backendStore = \Files\Backend\BackendStore::getInstance(); |
|
30 | - |
|
31 | - $account = $accountStore->getAccount($accountID); |
|
32 | - |
|
33 | - // initialize the backend |
|
34 | - $initializedBackend = $backendStore->getInstanceOfBackend($account->getBackend()); |
|
35 | - $initializedBackend->init_backend($account->getBackendConfig()); |
|
36 | - |
|
37 | - try { |
|
38 | - $initializedBackend->open(); |
|
39 | - } |
|
40 | - catch (\Files\Backend\Exception $e) { |
|
41 | - Logger::error(self::LOG_CONTEXT, "Could not open the backend: " . $e->getMessage()); |
|
42 | - echo json_encode(['success' => false, 'response' => $e->getCode(), 'message' => $e->getMessage()]); |
|
43 | - |
|
44 | - exit(); |
|
45 | - } |
|
46 | - $responsedata = $initializedBackend->getRecipients($_GET["query"]); |
|
47 | - header('Content-Type: application/json'); |
|
48 | - echo json_encode($responsedata); |
|
49 | - } |
|
13 | + public const LOG_CONTEXT = "RecipientHandler"; // Context for the Logger |
|
14 | + |
|
15 | + public static function doGetRecipients() { |
|
16 | + // parse account id. |
|
17 | + // wo only need to parse one string because it is |
|
18 | + // only possible to download files from one backend at a time. |
|
19 | + if (isset($_GET["ids"])) { |
|
20 | + $tmpId = $_GET["ids"][0]; |
|
21 | + } |
|
22 | + else { |
|
23 | + $tmpId = $_GET["id"]; |
|
24 | + } |
|
25 | + $accountID = substr($tmpId, 3, (strpos($tmpId, '/') - 3)); |
|
26 | + |
|
27 | + // Initialize the account and backendstore |
|
28 | + $accountStore = new \Files\Core\AccountStore(); |
|
29 | + $backendStore = \Files\Backend\BackendStore::getInstance(); |
|
30 | + |
|
31 | + $account = $accountStore->getAccount($accountID); |
|
32 | + |
|
33 | + // initialize the backend |
|
34 | + $initializedBackend = $backendStore->getInstanceOfBackend($account->getBackend()); |
|
35 | + $initializedBackend->init_backend($account->getBackendConfig()); |
|
36 | + |
|
37 | + try { |
|
38 | + $initializedBackend->open(); |
|
39 | + } |
|
40 | + catch (\Files\Backend\Exception $e) { |
|
41 | + Logger::error(self::LOG_CONTEXT, "Could not open the backend: " . $e->getMessage()); |
|
42 | + echo json_encode(['success' => false, 'response' => $e->getCode(), 'message' => $e->getMessage()]); |
|
43 | + |
|
44 | + exit(); |
|
45 | + } |
|
46 | + $responsedata = $initializedBackend->getRecipients($_GET["query"]); |
|
47 | + header('Content-Type: application/json'); |
|
48 | + echo json_encode($responsedata); |
|
49 | + } |
|
50 | 50 | } |
@@ -18,8 +18,7 @@ discard block |
||
18 | 18 | // only possible to download files from one backend at a time. |
19 | 19 | if (isset($_GET["ids"])) { |
20 | 20 | $tmpId = $_GET["ids"][0]; |
21 | - } |
|
22 | - else { |
|
21 | + } else { |
|
23 | 22 | $tmpId = $_GET["id"]; |
24 | 23 | } |
25 | 24 | $accountID = substr($tmpId, 3, (strpos($tmpId, '/') - 3)); |
@@ -36,8 +35,7 @@ discard block |
||
36 | 35 | |
37 | 36 | try { |
38 | 37 | $initializedBackend->open(); |
39 | - } |
|
40 | - catch (\Files\Backend\Exception $e) { |
|
38 | + } catch (\Files\Backend\Exception $e) { |
|
41 | 39 | Logger::error(self::LOG_CONTEXT, "Could not open the backend: " . $e->getMessage()); |
42 | 40 | echo json_encode(['success' => false, 'response' => $e->getCode(), 'message' => $e->getMessage()]); |
43 | 41 |
@@ -15,455 +15,455 @@ |
||
15 | 15 | use Files\Core\Util\Logger; |
16 | 16 | |
17 | 17 | class FilesAccountModule extends ListModule { |
18 | - public const LOG_CONTEXT = "FilesAccountModule"; // Context for the Logger |
|
19 | - |
|
20 | - /** |
|
21 | - * @constructor |
|
22 | - * |
|
23 | - * @param $id |
|
24 | - * @param $data |
|
25 | - */ |
|
26 | - public function __construct($id, $data) { |
|
27 | - parent::__construct($id, $data); |
|
28 | - } |
|
29 | - |
|
30 | - /** |
|
31 | - * Executes all the actions in the $data variable. |
|
32 | - * Exception part is used for authentication errors also. |
|
33 | - * |
|
34 | - * @return bool true on success or false on failure |
|
35 | - */ |
|
36 | - public function execute() { |
|
37 | - $result = false; |
|
38 | - |
|
39 | - foreach ($this->data as $actionType => $actionData) { |
|
40 | - if (isset($actionType)) { |
|
41 | - try { |
|
42 | - switch ($actionType) { |
|
43 | - case "save": |
|
44 | - // check if we should create a new account or edit an existing one |
|
45 | - if (isset($actionData["entryid"])) { |
|
46 | - $result = $this->accountUpdate($actionData); |
|
47 | - } |
|
48 | - else { |
|
49 | - $result = $this->accountCreate($actionData); |
|
50 | - } |
|
51 | - break; |
|
52 | - |
|
53 | - case "delete": |
|
54 | - $result = $this->accountDelete($actionType, $actionData); |
|
55 | - break; |
|
56 | - |
|
57 | - case "list": |
|
58 | - if (isset($actionData["list_backend"]) && $actionData["list_backend"]) { |
|
59 | - $result = $this->backendInformation($actionType); |
|
60 | - } |
|
61 | - else { |
|
62 | - $result = $this->accountList($actionType, $actionData); |
|
63 | - } |
|
64 | - break; |
|
65 | - |
|
66 | - case "getquota": |
|
67 | - $result = $this->getQuotaInformation($actionType, $actionData); |
|
68 | - break; |
|
69 | - |
|
70 | - case "getversion": |
|
71 | - $result = $this->getVersionInformation($actionType, $actionData); |
|
72 | - break; |
|
73 | - |
|
74 | - case "updatetoken": |
|
75 | - $result = $this->updateOauthToken($actionType, $actionData); |
|
76 | - break; |
|
77 | - |
|
78 | - default: |
|
79 | - $this->handleUnknownActionType($actionType); |
|
80 | - } |
|
81 | - } |
|
82 | - catch (MAPIException $e) { |
|
83 | - $this->sendFeedback(false, $this->errorDetailsFromException($e)); |
|
84 | - } |
|
85 | - catch (AccountException $e) { |
|
86 | - $this->sendFeedback(false, [ |
|
87 | - 'type' => ERROR_GENERAL, |
|
88 | - 'info' => [ |
|
89 | - 'title' => $e->getTitle(), |
|
90 | - 'original_message' => $e->getMessage(), |
|
91 | - 'display_message' => $e->getMessage(), |
|
92 | - ], |
|
93 | - ]); |
|
94 | - } |
|
95 | - catch (BackendException $e) { |
|
96 | - $this->sendFeedback(false, [ |
|
97 | - 'type' => ERROR_GENERAL, |
|
98 | - 'info' => [ |
|
99 | - 'title' => $e->getTitle(), |
|
100 | - 'original_message' => $e->getMessage(), |
|
101 | - 'display_message' => $e->getMessage(), |
|
102 | - ], |
|
103 | - ]); |
|
104 | - } |
|
105 | - } |
|
106 | - } |
|
107 | - |
|
108 | - return $result; |
|
109 | - } |
|
110 | - |
|
111 | - /** |
|
112 | - * @param {Array} $actionData |
|
113 | - */ |
|
114 | - public function accountCreate($actionData) { |
|
115 | - $response = []; |
|
116 | - $requestProperties = $actionData["props"]; |
|
117 | - |
|
118 | - // create a new account in our backend |
|
119 | - $accountStore = new \Files\Core\AccountStore(); |
|
120 | - $newAccount = $accountStore->createAccount($requestProperties["name"], $requestProperties["backend"], $requestProperties["backend_config"]); |
|
121 | - |
|
122 | - // create the response account object |
|
123 | - $account = []; |
|
124 | - $account[$newAccount->getId()] = [ |
|
125 | - 'props' => [ |
|
126 | - 'id' => $newAccount->getId(), |
|
127 | - 'status' => $newAccount->getStatus(), |
|
128 | - 'status_description' => $newAccount->getStatusDescription(), |
|
129 | - 'name' => $newAccount->getName(), |
|
130 | - 'backend' => $newAccount->getBackend(), |
|
131 | - 'backend_config' => $newAccount->getBackendConfig(), |
|
132 | - 'backend_features' => $newAccount->getFeatures(), |
|
133 | - 'account_sequence' => $newAccount->getSequence(), |
|
134 | - ], |
|
135 | - 'entryid' => $newAccount->getId(), |
|
136 | - 'store_entryid' => 'filesaccount', |
|
137 | - 'parent_entryid' => 'accountstoreroot', |
|
138 | - ]; |
|
139 | - $response['item'] = array_values($account); |
|
140 | - |
|
141 | - $this->addActionData("update", $response); |
|
142 | - $GLOBALS["bus"]->addData($this->getResponseData()); |
|
143 | - |
|
144 | - return true; |
|
145 | - } |
|
146 | - |
|
147 | - /** |
|
148 | - * remove an account from the store and the MAPI settings. |
|
149 | - * |
|
150 | - * @param {String} $actionType |
|
151 | - * @param {Array} $actionData |
|
152 | - */ |
|
153 | - public function accountDelete($actionType, $actionData) { |
|
154 | - $response = []; |
|
155 | - |
|
156 | - // check if account needs to clean things up before it gets deleted |
|
157 | - try { |
|
158 | - $accountStore = new \Files\Core\AccountStore(); |
|
159 | - $accountStore->getAccount($actionData['entryid'])->beforeDelete(); |
|
160 | - } |
|
161 | - catch (\Files\Backend\Exception $e) { |
|
162 | - // ignore errors here |
|
163 | - } |
|
164 | - |
|
165 | - $response['status'] = $accountStore->deleteAccount($actionData['entryid']); |
|
166 | - |
|
167 | - $this->addActionData($actionType, $response); |
|
168 | - $GLOBALS["bus"]->addData($this->getResponseData()); |
|
169 | - |
|
170 | - return $response['status']; |
|
171 | - } |
|
172 | - |
|
173 | - /** |
|
174 | - * loads content of current folder - list of folders and files from the Files backend. |
|
175 | - * |
|
176 | - * @param {String} $actionType |
|
177 | - * @param {Array} $actionData |
|
178 | - */ |
|
179 | - public function accountList($actionType, $actionData) { |
|
180 | - $response = []; |
|
181 | - |
|
182 | - // get a list of all accounts |
|
183 | - $accountStore = new \Files\Core\AccountStore(); |
|
184 | - $accounts = $accountStore->getAllAccounts(); |
|
185 | - $accountList = []; |
|
186 | - |
|
187 | - if (is_array($accounts)) { |
|
188 | - foreach ($accounts as $account) { |
|
189 | - $account = $accountStore->updateAccount($account); |
|
190 | - $accountList[$account->getId()] = [ |
|
191 | - "props" => [ |
|
192 | - "id" => $account->getId(), |
|
193 | - "name" => $account->getName(), |
|
194 | - "type" => "account", // to prevent warning while sorting |
|
195 | - "status" => $account->getStatus(), |
|
196 | - "status_description" => $account->getStatusDescription(), |
|
197 | - "backend" => $account->getBackend(), |
|
198 | - "backend_config" => $account->getBackendConfig(), |
|
199 | - 'backend_features' => $account->getFeatures(), |
|
200 | - 'account_sequence' => $account->getSequence(), |
|
201 | - 'cannot_change' => $account->getCannotChangeFlag(), |
|
202 | - ], |
|
203 | - 'entryid' => $account->getId(), |
|
204 | - 'store_entryid' => 'filesaccount', |
|
205 | - 'parent_entryid' => 'accountstoreroot', |
|
206 | - ]; |
|
207 | - } |
|
208 | - } |
|
209 | - |
|
210 | - // sort the accounts |
|
211 | - $sortKey = "account_sequence"; |
|
212 | - $sortDir = "ASC"; |
|
213 | - |
|
214 | - if (isset($data['sort'])) { |
|
215 | - $sortKey = $data['sort'][0]['field']; |
|
216 | - $sortDir = $data['sort'][0]['direction']; |
|
217 | - } |
|
218 | - |
|
219 | - Logger::debug(self::LOG_CONTEXT, "Sorting by " . $sortKey . " in direction: " . $sortDir); |
|
220 | - |
|
221 | - $accountList = ArrayUtil::sort_props_by_key($accountList, $sortKey, $sortDir); |
|
222 | - |
|
223 | - $response["item"] = array_values($accountList); |
|
224 | - $response['page'] = ["start" => 0, "rowcount" => 50, "totalrowcount" => count($response["item"])]; |
|
225 | - $response['folder'] = ["content_count" => count($response["item"]), "content_unread" => 0]; |
|
226 | - |
|
227 | - $this->addActionData($actionType, $response); |
|
228 | - $GLOBALS["bus"]->addData($this->getResponseData()); |
|
229 | - |
|
230 | - return true; |
|
231 | - } |
|
232 | - |
|
233 | - /** |
|
234 | - * update some values of an account. |
|
235 | - * |
|
236 | - * @param {Array} $actionData |
|
237 | - */ |
|
238 | - public function accountUpdate($actionData) { |
|
239 | - $response = []; |
|
240 | - |
|
241 | - // create a new account in our backend |
|
242 | - $accountStore = new \Files\Core\AccountStore(); |
|
243 | - $currentAccount = $accountStore->getAccount($actionData['entryid']); |
|
244 | - |
|
245 | - // apply changes to the account object |
|
246 | - if (isset($actionData['props']['name'])) { |
|
247 | - $currentAccount->setName(strip_tags($actionData['props']['name'])); |
|
248 | - } |
|
249 | - if (isset($actionData['props']['backend'])) { |
|
250 | - $currentAccount->setBackend(strip_tags($actionData['props']['backend'])); |
|
251 | - } |
|
252 | - if (isset($actionData['props']['backend_config'])) { // we always get the whole backend config |
|
253 | - $currentAccount->setBackendConfig($actionData['props']['backend_config']); |
|
254 | - } |
|
255 | - if (isset($actionData['props']['account_sequence'])) { |
|
256 | - $currentAccount->setSequence($actionData['props']['account_sequence']); |
|
257 | - } |
|
258 | - |
|
259 | - // save changes |
|
260 | - $accountStore->updateAccount($currentAccount); |
|
261 | - |
|
262 | - // create the response object |
|
263 | - $updatedAccount = []; |
|
264 | - $updatedAccount[$currentAccount->getId()] = [ |
|
265 | - "props" => [ |
|
266 | - "id" => $currentAccount->getId(), |
|
267 | - "name" => $currentAccount->getName(), |
|
268 | - "status" => $currentAccount->getStatus(), |
|
269 | - "status_description" => $currentAccount->getStatusDescription(), |
|
270 | - "backend" => $currentAccount->getBackend(), |
|
271 | - "backend_config" => $currentAccount->getBackendConfig(), |
|
272 | - 'backend_features' => $currentAccount->getFeatures(), |
|
273 | - 'account_sequence' => $currentAccount->getSequence(), |
|
274 | - ], |
|
275 | - 'entryid' => $currentAccount->getId(), |
|
276 | - 'store_entryid' => 'filesaccount', |
|
277 | - 'parent_entryid' => 'accountstoreroot', |
|
278 | - ]; |
|
279 | - |
|
280 | - $response['item'] = array_values($updatedAccount); |
|
281 | - $this->addActionData("update", $response); |
|
282 | - $GLOBALS["bus"]->addData($this->getResponseData()); |
|
283 | - |
|
284 | - return true; |
|
285 | - } |
|
286 | - |
|
287 | - /** |
|
288 | - * Return all Information about the existing backends. |
|
289 | - * |
|
290 | - * @param {String} $actionType |
|
291 | - */ |
|
292 | - public function backendInformation($actionType) { |
|
293 | - // find all registered backends |
|
294 | - $backendStore = \Files\Backend\BackendStore::getInstance(); |
|
295 | - $backendNames = $backendStore->getRegisteredBackendNames(); |
|
296 | - |
|
297 | - $data = []; |
|
298 | - $items = []; |
|
299 | - foreach ($backendNames as $backendName) { |
|
300 | - $backendInstance = $backendStore->getInstanceOfBackend($backendName); |
|
301 | - if ($backendInstance !== false) { |
|
302 | - array_push($items, ['props' => [ |
|
303 | - "name" => $backendName, |
|
304 | - "message_class" => "IPM.FilesBackend", |
|
305 | - "displayName" => $backendInstance->getDisplayName(), |
|
306 | - ]]); |
|
307 | - } |
|
308 | - } |
|
309 | - |
|
310 | - $data = array_merge($data, ['item' => $items]); |
|
311 | - |
|
312 | - $this->addActionData($actionType, $data); |
|
313 | - $GLOBALS["bus"]->addData($this->getResponseData()); |
|
314 | - |
|
315 | - return true; |
|
316 | - } |
|
317 | - |
|
318 | - /** |
|
319 | - * Return all quota information from specified account. |
|
320 | - * |
|
321 | - * @param {String} $actionType |
|
322 | - * @param {String} $actionData |
|
323 | - */ |
|
324 | - public function getQuotaInformation($actionType, $actionData) { |
|
325 | - $response = []; |
|
326 | - |
|
327 | - $accountId = $actionData["accountId"]; |
|
328 | - $rootPath = $actionData["folder"]; |
|
329 | - |
|
330 | - // load the accountstore |
|
331 | - $accountStore = new \Files\Core\AccountStore(); |
|
332 | - $currentAccount = $accountStore->getAccount($accountId); |
|
333 | - |
|
334 | - // check if ID was valid, if not respond with error. |
|
335 | - if ($currentAccount === null || $currentAccount === false) { |
|
336 | - throw new AccountException(_("Unknown account ID")); |
|
337 | - } |
|
338 | - |
|
339 | - $backendStore = \Files\Backend\BackendStore::getInstance(); |
|
340 | - $backendInstance = $backendStore->getInstanceOfBackend($currentAccount->getBackend()); |
|
341 | - |
|
342 | - // check if backend really supports this feature |
|
343 | - if (!$backendInstance->supports(\Files\Backend\BackendStore::FEATURE_QUOTA)) { |
|
344 | - throw new AccountException(_('Feature "Quota Information" is not supported by this backend!')); |
|
345 | - } |
|
346 | - |
|
347 | - // init backend instance |
|
348 | - $backendInstance->init_backend($currentAccount->getBackendConfig()); |
|
349 | - |
|
350 | - // get quota info |
|
351 | - $backendInstance->open(); |
|
352 | - $qUsed = $backendInstance->getQuotaBytesUsed($rootPath); |
|
353 | - $qAvailable = $backendInstance->getQuotaBytesAvailable($rootPath); |
|
354 | - |
|
355 | - $response['status'] = true; |
|
356 | - $response['quota'] = [ |
|
357 | - ["state" => _('Used'), "amount" => $qUsed], |
|
358 | - ["state" => _('Free'), "amount" => $qAvailable], |
|
359 | - ]; |
|
360 | - |
|
361 | - $this->addActionData($actionType, $response); |
|
362 | - $GLOBALS["bus"]->addData($this->getResponseData()); |
|
363 | - |
|
364 | - return $response['status']; |
|
365 | - } |
|
366 | - |
|
367 | - /** |
|
368 | - * Return all quota information from specified account. |
|
369 | - * |
|
370 | - * @param {String} $actionType |
|
371 | - * @param {String} $actionData |
|
372 | - */ |
|
373 | - public function getVersionInformation($actionType, $actionData) { |
|
374 | - $response = []; |
|
375 | - |
|
376 | - $accountId = $actionData["accountId"]; |
|
377 | - |
|
378 | - // load the accountstore |
|
379 | - $accountStore = new \Files\Core\AccountStore(); |
|
380 | - $currentAccount = $accountStore->getAccount($accountId); |
|
381 | - |
|
382 | - // check if ID was valid, if not respond with error. |
|
383 | - if ($currentAccount === null || $currentAccount === false) { |
|
384 | - throw new AccountException(_("Unknown account ID")); |
|
385 | - } |
|
386 | - |
|
387 | - $backendStore = \Files\Backend\BackendStore::getInstance(); |
|
388 | - $backendInstance = $backendStore->getInstanceOfBackend($currentAccount->getBackend()); |
|
389 | - |
|
390 | - // check if backend really supports this feature |
|
391 | - if (!$backendInstance->supports(\Files\Backend\BackendStore::FEATURE_VERSION)) { |
|
392 | - throw new AccountException(_('Feature "Version Information" is not supported by this backend!')); |
|
393 | - } |
|
394 | - |
|
395 | - // init backend instance |
|
396 | - $backendInstance->init_backend($currentAccount->getBackendConfig()); |
|
397 | - |
|
398 | - // get quota info |
|
399 | - $backendInstance->open(); |
|
400 | - $serverVersion = $backendInstance->getServerVersion(); |
|
401 | - $backendVersion = $backendInstance->getBackendVersion(); |
|
402 | - |
|
403 | - $response['status'] = true; |
|
404 | - $response['version'] = [ |
|
405 | - "backend" => $backendVersion, |
|
406 | - "server" => $serverVersion, |
|
407 | - ]; |
|
408 | - |
|
409 | - $this->addActionData($actionType, $response); |
|
410 | - $GLOBALS["bus"]->addData($this->getResponseData()); |
|
411 | - |
|
412 | - return $response['status']; |
|
413 | - } |
|
414 | - |
|
415 | - /** |
|
416 | - * Return all quota information from specified account. |
|
417 | - * |
|
418 | - * @param {String} $actionType |
|
419 | - * @param {String} $actionData |
|
420 | - */ |
|
421 | - public function updateOauthToken($actionType, $actionData) { |
|
422 | - $response = []; |
|
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 | - public function errorDetailsFromException($exception) { |
|
467 | - parent::errorDetailsFromException($exception); |
|
468 | - } |
|
18 | + public const LOG_CONTEXT = "FilesAccountModule"; // Context for the Logger |
|
19 | + |
|
20 | + /** |
|
21 | + * @constructor |
|
22 | + * |
|
23 | + * @param $id |
|
24 | + * @param $data |
|
25 | + */ |
|
26 | + public function __construct($id, $data) { |
|
27 | + parent::__construct($id, $data); |
|
28 | + } |
|
29 | + |
|
30 | + /** |
|
31 | + * Executes all the actions in the $data variable. |
|
32 | + * Exception part is used for authentication errors also. |
|
33 | + * |
|
34 | + * @return bool true on success or false on failure |
|
35 | + */ |
|
36 | + public function execute() { |
|
37 | + $result = false; |
|
38 | + |
|
39 | + foreach ($this->data as $actionType => $actionData) { |
|
40 | + if (isset($actionType)) { |
|
41 | + try { |
|
42 | + switch ($actionType) { |
|
43 | + case "save": |
|
44 | + // check if we should create a new account or edit an existing one |
|
45 | + if (isset($actionData["entryid"])) { |
|
46 | + $result = $this->accountUpdate($actionData); |
|
47 | + } |
|
48 | + else { |
|
49 | + $result = $this->accountCreate($actionData); |
|
50 | + } |
|
51 | + break; |
|
52 | + |
|
53 | + case "delete": |
|
54 | + $result = $this->accountDelete($actionType, $actionData); |
|
55 | + break; |
|
56 | + |
|
57 | + case "list": |
|
58 | + if (isset($actionData["list_backend"]) && $actionData["list_backend"]) { |
|
59 | + $result = $this->backendInformation($actionType); |
|
60 | + } |
|
61 | + else { |
|
62 | + $result = $this->accountList($actionType, $actionData); |
|
63 | + } |
|
64 | + break; |
|
65 | + |
|
66 | + case "getquota": |
|
67 | + $result = $this->getQuotaInformation($actionType, $actionData); |
|
68 | + break; |
|
69 | + |
|
70 | + case "getversion": |
|
71 | + $result = $this->getVersionInformation($actionType, $actionData); |
|
72 | + break; |
|
73 | + |
|
74 | + case "updatetoken": |
|
75 | + $result = $this->updateOauthToken($actionType, $actionData); |
|
76 | + break; |
|
77 | + |
|
78 | + default: |
|
79 | + $this->handleUnknownActionType($actionType); |
|
80 | + } |
|
81 | + } |
|
82 | + catch (MAPIException $e) { |
|
83 | + $this->sendFeedback(false, $this->errorDetailsFromException($e)); |
|
84 | + } |
|
85 | + catch (AccountException $e) { |
|
86 | + $this->sendFeedback(false, [ |
|
87 | + 'type' => ERROR_GENERAL, |
|
88 | + 'info' => [ |
|
89 | + 'title' => $e->getTitle(), |
|
90 | + 'original_message' => $e->getMessage(), |
|
91 | + 'display_message' => $e->getMessage(), |
|
92 | + ], |
|
93 | + ]); |
|
94 | + } |
|
95 | + catch (BackendException $e) { |
|
96 | + $this->sendFeedback(false, [ |
|
97 | + 'type' => ERROR_GENERAL, |
|
98 | + 'info' => [ |
|
99 | + 'title' => $e->getTitle(), |
|
100 | + 'original_message' => $e->getMessage(), |
|
101 | + 'display_message' => $e->getMessage(), |
|
102 | + ], |
|
103 | + ]); |
|
104 | + } |
|
105 | + } |
|
106 | + } |
|
107 | + |
|
108 | + return $result; |
|
109 | + } |
|
110 | + |
|
111 | + /** |
|
112 | + * @param {Array} $actionData |
|
113 | + */ |
|
114 | + public function accountCreate($actionData) { |
|
115 | + $response = []; |
|
116 | + $requestProperties = $actionData["props"]; |
|
117 | + |
|
118 | + // create a new account in our backend |
|
119 | + $accountStore = new \Files\Core\AccountStore(); |
|
120 | + $newAccount = $accountStore->createAccount($requestProperties["name"], $requestProperties["backend"], $requestProperties["backend_config"]); |
|
121 | + |
|
122 | + // create the response account object |
|
123 | + $account = []; |
|
124 | + $account[$newAccount->getId()] = [ |
|
125 | + 'props' => [ |
|
126 | + 'id' => $newAccount->getId(), |
|
127 | + 'status' => $newAccount->getStatus(), |
|
128 | + 'status_description' => $newAccount->getStatusDescription(), |
|
129 | + 'name' => $newAccount->getName(), |
|
130 | + 'backend' => $newAccount->getBackend(), |
|
131 | + 'backend_config' => $newAccount->getBackendConfig(), |
|
132 | + 'backend_features' => $newAccount->getFeatures(), |
|
133 | + 'account_sequence' => $newAccount->getSequence(), |
|
134 | + ], |
|
135 | + 'entryid' => $newAccount->getId(), |
|
136 | + 'store_entryid' => 'filesaccount', |
|
137 | + 'parent_entryid' => 'accountstoreroot', |
|
138 | + ]; |
|
139 | + $response['item'] = array_values($account); |
|
140 | + |
|
141 | + $this->addActionData("update", $response); |
|
142 | + $GLOBALS["bus"]->addData($this->getResponseData()); |
|
143 | + |
|
144 | + return true; |
|
145 | + } |
|
146 | + |
|
147 | + /** |
|
148 | + * remove an account from the store and the MAPI settings. |
|
149 | + * |
|
150 | + * @param {String} $actionType |
|
151 | + * @param {Array} $actionData |
|
152 | + */ |
|
153 | + public function accountDelete($actionType, $actionData) { |
|
154 | + $response = []; |
|
155 | + |
|
156 | + // check if account needs to clean things up before it gets deleted |
|
157 | + try { |
|
158 | + $accountStore = new \Files\Core\AccountStore(); |
|
159 | + $accountStore->getAccount($actionData['entryid'])->beforeDelete(); |
|
160 | + } |
|
161 | + catch (\Files\Backend\Exception $e) { |
|
162 | + // ignore errors here |
|
163 | + } |
|
164 | + |
|
165 | + $response['status'] = $accountStore->deleteAccount($actionData['entryid']); |
|
166 | + |
|
167 | + $this->addActionData($actionType, $response); |
|
168 | + $GLOBALS["bus"]->addData($this->getResponseData()); |
|
169 | + |
|
170 | + return $response['status']; |
|
171 | + } |
|
172 | + |
|
173 | + /** |
|
174 | + * loads content of current folder - list of folders and files from the Files backend. |
|
175 | + * |
|
176 | + * @param {String} $actionType |
|
177 | + * @param {Array} $actionData |
|
178 | + */ |
|
179 | + public function accountList($actionType, $actionData) { |
|
180 | + $response = []; |
|
181 | + |
|
182 | + // get a list of all accounts |
|
183 | + $accountStore = new \Files\Core\AccountStore(); |
|
184 | + $accounts = $accountStore->getAllAccounts(); |
|
185 | + $accountList = []; |
|
186 | + |
|
187 | + if (is_array($accounts)) { |
|
188 | + foreach ($accounts as $account) { |
|
189 | + $account = $accountStore->updateAccount($account); |
|
190 | + $accountList[$account->getId()] = [ |
|
191 | + "props" => [ |
|
192 | + "id" => $account->getId(), |
|
193 | + "name" => $account->getName(), |
|
194 | + "type" => "account", // to prevent warning while sorting |
|
195 | + "status" => $account->getStatus(), |
|
196 | + "status_description" => $account->getStatusDescription(), |
|
197 | + "backend" => $account->getBackend(), |
|
198 | + "backend_config" => $account->getBackendConfig(), |
|
199 | + 'backend_features' => $account->getFeatures(), |
|
200 | + 'account_sequence' => $account->getSequence(), |
|
201 | + 'cannot_change' => $account->getCannotChangeFlag(), |
|
202 | + ], |
|
203 | + 'entryid' => $account->getId(), |
|
204 | + 'store_entryid' => 'filesaccount', |
|
205 | + 'parent_entryid' => 'accountstoreroot', |
|
206 | + ]; |
|
207 | + } |
|
208 | + } |
|
209 | + |
|
210 | + // sort the accounts |
|
211 | + $sortKey = "account_sequence"; |
|
212 | + $sortDir = "ASC"; |
|
213 | + |
|
214 | + if (isset($data['sort'])) { |
|
215 | + $sortKey = $data['sort'][0]['field']; |
|
216 | + $sortDir = $data['sort'][0]['direction']; |
|
217 | + } |
|
218 | + |
|
219 | + Logger::debug(self::LOG_CONTEXT, "Sorting by " . $sortKey . " in direction: " . $sortDir); |
|
220 | + |
|
221 | + $accountList = ArrayUtil::sort_props_by_key($accountList, $sortKey, $sortDir); |
|
222 | + |
|
223 | + $response["item"] = array_values($accountList); |
|
224 | + $response['page'] = ["start" => 0, "rowcount" => 50, "totalrowcount" => count($response["item"])]; |
|
225 | + $response['folder'] = ["content_count" => count($response["item"]), "content_unread" => 0]; |
|
226 | + |
|
227 | + $this->addActionData($actionType, $response); |
|
228 | + $GLOBALS["bus"]->addData($this->getResponseData()); |
|
229 | + |
|
230 | + return true; |
|
231 | + } |
|
232 | + |
|
233 | + /** |
|
234 | + * update some values of an account. |
|
235 | + * |
|
236 | + * @param {Array} $actionData |
|
237 | + */ |
|
238 | + public function accountUpdate($actionData) { |
|
239 | + $response = []; |
|
240 | + |
|
241 | + // create a new account in our backend |
|
242 | + $accountStore = new \Files\Core\AccountStore(); |
|
243 | + $currentAccount = $accountStore->getAccount($actionData['entryid']); |
|
244 | + |
|
245 | + // apply changes to the account object |
|
246 | + if (isset($actionData['props']['name'])) { |
|
247 | + $currentAccount->setName(strip_tags($actionData['props']['name'])); |
|
248 | + } |
|
249 | + if (isset($actionData['props']['backend'])) { |
|
250 | + $currentAccount->setBackend(strip_tags($actionData['props']['backend'])); |
|
251 | + } |
|
252 | + if (isset($actionData['props']['backend_config'])) { // we always get the whole backend config |
|
253 | + $currentAccount->setBackendConfig($actionData['props']['backend_config']); |
|
254 | + } |
|
255 | + if (isset($actionData['props']['account_sequence'])) { |
|
256 | + $currentAccount->setSequence($actionData['props']['account_sequence']); |
|
257 | + } |
|
258 | + |
|
259 | + // save changes |
|
260 | + $accountStore->updateAccount($currentAccount); |
|
261 | + |
|
262 | + // create the response object |
|
263 | + $updatedAccount = []; |
|
264 | + $updatedAccount[$currentAccount->getId()] = [ |
|
265 | + "props" => [ |
|
266 | + "id" => $currentAccount->getId(), |
|
267 | + "name" => $currentAccount->getName(), |
|
268 | + "status" => $currentAccount->getStatus(), |
|
269 | + "status_description" => $currentAccount->getStatusDescription(), |
|
270 | + "backend" => $currentAccount->getBackend(), |
|
271 | + "backend_config" => $currentAccount->getBackendConfig(), |
|
272 | + 'backend_features' => $currentAccount->getFeatures(), |
|
273 | + 'account_sequence' => $currentAccount->getSequence(), |
|
274 | + ], |
|
275 | + 'entryid' => $currentAccount->getId(), |
|
276 | + 'store_entryid' => 'filesaccount', |
|
277 | + 'parent_entryid' => 'accountstoreroot', |
|
278 | + ]; |
|
279 | + |
|
280 | + $response['item'] = array_values($updatedAccount); |
|
281 | + $this->addActionData("update", $response); |
|
282 | + $GLOBALS["bus"]->addData($this->getResponseData()); |
|
283 | + |
|
284 | + return true; |
|
285 | + } |
|
286 | + |
|
287 | + /** |
|
288 | + * Return all Information about the existing backends. |
|
289 | + * |
|
290 | + * @param {String} $actionType |
|
291 | + */ |
|
292 | + public function backendInformation($actionType) { |
|
293 | + // find all registered backends |
|
294 | + $backendStore = \Files\Backend\BackendStore::getInstance(); |
|
295 | + $backendNames = $backendStore->getRegisteredBackendNames(); |
|
296 | + |
|
297 | + $data = []; |
|
298 | + $items = []; |
|
299 | + foreach ($backendNames as $backendName) { |
|
300 | + $backendInstance = $backendStore->getInstanceOfBackend($backendName); |
|
301 | + if ($backendInstance !== false) { |
|
302 | + array_push($items, ['props' => [ |
|
303 | + "name" => $backendName, |
|
304 | + "message_class" => "IPM.FilesBackend", |
|
305 | + "displayName" => $backendInstance->getDisplayName(), |
|
306 | + ]]); |
|
307 | + } |
|
308 | + } |
|
309 | + |
|
310 | + $data = array_merge($data, ['item' => $items]); |
|
311 | + |
|
312 | + $this->addActionData($actionType, $data); |
|
313 | + $GLOBALS["bus"]->addData($this->getResponseData()); |
|
314 | + |
|
315 | + return true; |
|
316 | + } |
|
317 | + |
|
318 | + /** |
|
319 | + * Return all quota information from specified account. |
|
320 | + * |
|
321 | + * @param {String} $actionType |
|
322 | + * @param {String} $actionData |
|
323 | + */ |
|
324 | + public function getQuotaInformation($actionType, $actionData) { |
|
325 | + $response = []; |
|
326 | + |
|
327 | + $accountId = $actionData["accountId"]; |
|
328 | + $rootPath = $actionData["folder"]; |
|
329 | + |
|
330 | + // load the accountstore |
|
331 | + $accountStore = new \Files\Core\AccountStore(); |
|
332 | + $currentAccount = $accountStore->getAccount($accountId); |
|
333 | + |
|
334 | + // check if ID was valid, if not respond with error. |
|
335 | + if ($currentAccount === null || $currentAccount === false) { |
|
336 | + throw new AccountException(_("Unknown account ID")); |
|
337 | + } |
|
338 | + |
|
339 | + $backendStore = \Files\Backend\BackendStore::getInstance(); |
|
340 | + $backendInstance = $backendStore->getInstanceOfBackend($currentAccount->getBackend()); |
|
341 | + |
|
342 | + // check if backend really supports this feature |
|
343 | + if (!$backendInstance->supports(\Files\Backend\BackendStore::FEATURE_QUOTA)) { |
|
344 | + throw new AccountException(_('Feature "Quota Information" is not supported by this backend!')); |
|
345 | + } |
|
346 | + |
|
347 | + // init backend instance |
|
348 | + $backendInstance->init_backend($currentAccount->getBackendConfig()); |
|
349 | + |
|
350 | + // get quota info |
|
351 | + $backendInstance->open(); |
|
352 | + $qUsed = $backendInstance->getQuotaBytesUsed($rootPath); |
|
353 | + $qAvailable = $backendInstance->getQuotaBytesAvailable($rootPath); |
|
354 | + |
|
355 | + $response['status'] = true; |
|
356 | + $response['quota'] = [ |
|
357 | + ["state" => _('Used'), "amount" => $qUsed], |
|
358 | + ["state" => _('Free'), "amount" => $qAvailable], |
|
359 | + ]; |
|
360 | + |
|
361 | + $this->addActionData($actionType, $response); |
|
362 | + $GLOBALS["bus"]->addData($this->getResponseData()); |
|
363 | + |
|
364 | + return $response['status']; |
|
365 | + } |
|
366 | + |
|
367 | + /** |
|
368 | + * Return all quota information from specified account. |
|
369 | + * |
|
370 | + * @param {String} $actionType |
|
371 | + * @param {String} $actionData |
|
372 | + */ |
|
373 | + public function getVersionInformation($actionType, $actionData) { |
|
374 | + $response = []; |
|
375 | + |
|
376 | + $accountId = $actionData["accountId"]; |
|
377 | + |
|
378 | + // load the accountstore |
|
379 | + $accountStore = new \Files\Core\AccountStore(); |
|
380 | + $currentAccount = $accountStore->getAccount($accountId); |
|
381 | + |
|
382 | + // check if ID was valid, if not respond with error. |
|
383 | + if ($currentAccount === null || $currentAccount === false) { |
|
384 | + throw new AccountException(_("Unknown account ID")); |
|
385 | + } |
|
386 | + |
|
387 | + $backendStore = \Files\Backend\BackendStore::getInstance(); |
|
388 | + $backendInstance = $backendStore->getInstanceOfBackend($currentAccount->getBackend()); |
|
389 | + |
|
390 | + // check if backend really supports this feature |
|
391 | + if (!$backendInstance->supports(\Files\Backend\BackendStore::FEATURE_VERSION)) { |
|
392 | + throw new AccountException(_('Feature "Version Information" is not supported by this backend!')); |
|
393 | + } |
|
394 | + |
|
395 | + // init backend instance |
|
396 | + $backendInstance->init_backend($currentAccount->getBackendConfig()); |
|
397 | + |
|
398 | + // get quota info |
|
399 | + $backendInstance->open(); |
|
400 | + $serverVersion = $backendInstance->getServerVersion(); |
|
401 | + $backendVersion = $backendInstance->getBackendVersion(); |
|
402 | + |
|
403 | + $response['status'] = true; |
|
404 | + $response['version'] = [ |
|
405 | + "backend" => $backendVersion, |
|
406 | + "server" => $serverVersion, |
|
407 | + ]; |
|
408 | + |
|
409 | + $this->addActionData($actionType, $response); |
|
410 | + $GLOBALS["bus"]->addData($this->getResponseData()); |
|
411 | + |
|
412 | + return $response['status']; |
|
413 | + } |
|
414 | + |
|
415 | + /** |
|
416 | + * Return all quota information from specified account. |
|
417 | + * |
|
418 | + * @param {String} $actionType |
|
419 | + * @param {String} $actionData |
|
420 | + */ |
|
421 | + public function updateOauthToken($actionType, $actionData) { |
|
422 | + $response = []; |
|
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 | + public function errorDetailsFromException($exception) { |
|
467 | + parent::errorDetailsFromException($exception); |
|
468 | + } |
|
469 | 469 | } |
@@ -44,8 +44,7 @@ discard block |
||
44 | 44 | // check if we should create a new account or edit an existing one |
45 | 45 | if (isset($actionData["entryid"])) { |
46 | 46 | $result = $this->accountUpdate($actionData); |
47 | - } |
|
48 | - else { |
|
47 | + } else { |
|
49 | 48 | $result = $this->accountCreate($actionData); |
50 | 49 | } |
51 | 50 | break; |
@@ -57,8 +56,7 @@ discard block |
||
57 | 56 | case "list": |
58 | 57 | if (isset($actionData["list_backend"]) && $actionData["list_backend"]) { |
59 | 58 | $result = $this->backendInformation($actionType); |
60 | - } |
|
61 | - else { |
|
59 | + } else { |
|
62 | 60 | $result = $this->accountList($actionType, $actionData); |
63 | 61 | } |
64 | 62 | break; |
@@ -78,11 +76,9 @@ discard block |
||
78 | 76 | default: |
79 | 77 | $this->handleUnknownActionType($actionType); |
80 | 78 | } |
81 | - } |
|
82 | - catch (MAPIException $e) { |
|
79 | + } catch (MAPIException $e) { |
|
83 | 80 | $this->sendFeedback(false, $this->errorDetailsFromException($e)); |
84 | - } |
|
85 | - catch (AccountException $e) { |
|
81 | + } catch (AccountException $e) { |
|
86 | 82 | $this->sendFeedback(false, [ |
87 | 83 | 'type' => ERROR_GENERAL, |
88 | 84 | 'info' => [ |
@@ -91,8 +87,7 @@ discard block |
||
91 | 87 | 'display_message' => $e->getMessage(), |
92 | 88 | ], |
93 | 89 | ]); |
94 | - } |
|
95 | - catch (BackendException $e) { |
|
90 | + } catch (BackendException $e) { |
|
96 | 91 | $this->sendFeedback(false, [ |
97 | 92 | 'type' => ERROR_GENERAL, |
98 | 93 | 'info' => [ |
@@ -157,8 +152,7 @@ discard block |
||
157 | 152 | try { |
158 | 153 | $accountStore = new \Files\Core\AccountStore(); |
159 | 154 | $accountStore->getAccount($actionData['entryid'])->beforeDelete(); |
160 | - } |
|
161 | - catch (\Files\Backend\Exception $e) { |
|
155 | + } catch (\Files\Backend\Exception $e) { |
|
162 | 156 | // ignore errors here |
163 | 157 | } |
164 | 158 |