1 | <?php |
||
2 | |||
3 | /** |
||
4 | * This is the entry point for every request that should return HTML |
||
5 | * (one exception is that it also returns translated text for javascript). |
||
6 | */ |
||
7 | |||
8 | // Bootstrap the script |
||
9 | require_once 'server/includes/bootstrap.php'; |
||
10 | |||
11 | // Added in 3.4.0, remove check in 3.5.0 |
||
12 | if (!function_exists('gitversion')) { |
||
13 | /** |
||
14 | * Obtain the current Git working branch. |
||
15 | * |
||
16 | * @return string the current git working branch |
||
17 | */ |
||
18 | function gitversion() { |
||
19 | if (is_dir(BASE_PATH . DIRECTORY_SEPARATOR . '.git')) { |
||
20 | return trim(@shell_exec("git symbolic-ref --short HEAD || git rev-parse --short HEAD .")); |
||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
21 | } |
||
22 | |||
23 | return ''; |
||
24 | } |
||
25 | } |
||
26 | else { |
||
27 | error_log('Remove gitversion() function in debug.php it\'s deprecated'); |
||
28 | } |
||
29 | |||
30 | /* |
||
31 | * Get the favicon either from theme or use the default. |
||
32 | * |
||
33 | * @param string theme the users theme |
||
34 | * @return string favicon |
||
35 | */ |
||
36 | function getFavicon($theme) { |
||
37 | $favicon = Theming::getFavicon($theme); |
||
38 | |||
39 | if (!isset($favicon) || $favicon === false) { |
||
40 | $favicon = 'client/resources/images/favicon.ico?kv2.2.0'; |
||
41 | } |
||
42 | |||
43 | return $favicon; |
||
44 | } |
||
45 | |||
46 | // If the user wants to logout (and is not using single-signon) |
||
47 | // then destroy the session and redirect to this page, so the login page |
||
48 | // will be shown |
||
49 | |||
50 | if (isset($_GET['logout'])) { |
||
51 | if (isset($_SESSION['_keycloak_auth'])) { |
||
52 | $keycloak_auth = $_SESSION['_keycloak_auth']->logout(); |
||
53 | header("Location:" . $keycloak_auth . ""); |
||
54 | } |
||
55 | else { |
||
56 | // GET variable user will be set when the user was logged out because of session timeout |
||
57 | // or because he logged out in another window. |
||
58 | $username = sanitizeGetValue('user', '', USERNAME_REGEX); |
||
59 | $location = rtrim(dirname($_SERVER['PHP_SELF']), '/') . '/'; |
||
60 | header('Location: ' . $location . ($username ? '?user=' . rawurlencode($username) : ''), true, 303); |
||
61 | } |
||
62 | $webappSession->destroy(); |
||
63 | |||
64 | exit; |
||
65 | } |
||
66 | |||
67 | // Check if an action GET-parameter was sent with the request. |
||
68 | // This parameter is set when the webapp was opened by clicking on |
||
69 | // a mailto: link in the browser. |
||
70 | // If so, we will store it in the session, so we can use it later. |
||
71 | if (isset($_GET['action']) && !empty($_GET['action'])) { |
||
72 | storeURLDataToSession(); |
||
73 | } |
||
74 | |||
75 | // Check if the continue parameter was set. This will be set e.g. when someone |
||
76 | // uses the grommunio Web to login to another application with OpenID Connect. |
||
77 | if (isset($_GET['continue']) && !empty($_GET['continue']) && !isset($_GET['wacontinue'])) { |
||
78 | $_SESSION['continue'] = $_GET['continue']; |
||
79 | } |
||
80 | |||
81 | // Try to authenticate the user |
||
82 | WebAppAuthentication::authenticate(); |
||
83 | |||
84 | $webappTitle = defined('WEBAPP_TITLE') && WEBAPP_TITLE ? WEBAPP_TITLE : 'grommunio Web'; |
||
85 | if (isset($_COOKIE['webapp_title'])) { |
||
86 | $webappTitle .= " – " . $_COOKIE['webapp_title']; |
||
87 | } |
||
88 | |||
89 | // If we could not authenticate the user, we will show the login page |
||
90 | if (!WebAppAuthentication::isAuthenticated()) { |
||
91 | // Get language from the cookie, or from the language that is set by the admin |
||
92 | $Language = new Language(); |
||
93 | $lang = isset($_COOKIE['lang']) ? $_COOKIE['lang'] : LANG; |
||
94 | $lang = $Language->resolveLanguage($lang); |
||
95 | $Language->setLanguage($lang); |
||
96 | |||
97 | // If GET parameter 'load' is defined, we defer handling to the load.php script |
||
98 | if (isset($_GET['load']) && $_GET['load'] !== 'logon') { |
||
99 | include BASE_PATH . 'server/includes/load.php'; |
||
100 | |||
101 | exit; |
||
102 | } |
||
103 | |||
104 | // Set some template variables for the login page |
||
105 | $branch = DEBUG_LOADER === LOAD_SOURCE ? gitversion() : ''; |
||
106 | $version = 'grommunio Web ' . trim(file_get_contents('version')); |
||
107 | $user = sanitizeGetValue('user', '', USERNAME_REGEX); |
||
108 | |||
109 | $url = '?logon'; |
||
110 | |||
111 | if (isset($_GET["logout"]) && $_GET["logout"] == "auto") { |
||
112 | $error = _("You have been automatically logged out"); |
||
113 | } |
||
114 | else { |
||
115 | $error = WebAppAuthentication::getErrorMessage(); |
||
116 | if (empty($error) && useSecureCookies() && getRequestProtocol() == 'http') { |
||
117 | header("HTTP/1.0 400 Bad Request"); |
||
118 | include BASE_PATH . 'server/includes/templates/BadRequest.php'; |
||
119 | error_log("Rejected insecure request as configuration for 'SECURE_COOKIES' is true."); |
||
120 | |||
121 | exit; |
||
122 | } |
||
123 | } |
||
124 | |||
125 | // If a username was passed as GET parameter we will prefill the username input |
||
126 | // of the login form with it. |
||
127 | $user = isset($_GET['user']) ? htmlentities($_GET['user']) : ''; |
||
128 | |||
129 | // Lets add a header when login failed (DeskApp needs it to identify failed login attempts) |
||
130 | if (WebAppAuthentication::getErrorCode() !== NOERROR) { |
||
131 | header("X-grommunio-Hresult: " . get_mapi_error_name(WebAppAuthentication::getErrorCode())); |
||
132 | } |
||
133 | |||
134 | // Set a template variable for the favicon of the login, welcome, and webclient page |
||
135 | $theme = Theming::getActiveTheme(); |
||
136 | $favicon = getFavicon(Theming::getActiveTheme()); |
||
137 | include BASE_PATH . 'server/includes/templates/login.php'; |
||
138 | |||
139 | exit; |
||
140 | } |
||
141 | |||
142 | // The user is authenticated! Let's get ready to start the webapp. |
||
143 | // If the user just logged in or if url data was stored in the session, |
||
144 | // we will redirect to make sure that a browser refresh will not post |
||
145 | // the credentials again, and that the url data is taken away from the |
||
146 | // url in the address bar (so a browser refresh will not pass them again) |
||
147 | if (isset($_GET['code']) || (WebAppAuthentication::isUsingLoginForm() || isset($_GET['action']) && !empty($_GET['action']))) { |
||
148 | $location = rtrim(dirname($_SERVER['PHP_SELF']), '/') . '/'; |
||
149 | header('Location: ' . $location, true, 303); |
||
150 | |||
151 | exit; |
||
152 | } |
||
153 | |||
154 | // TODO: we could replace all references to $GLOBALS['mapisession'] |
||
155 | // with WebAppAuthentication::getMAPISession(), that way we would |
||
156 | // lose at least one GLOBAL (because globals suck) |
||
157 | $GLOBALS['mapisession'] = WebAppAuthentication::getMAPISession(); |
||
158 | |||
159 | // check if it's DB or LDAP for the password plugin |
||
160 | $result = @json_decode(@file_get_contents(ADMIN_API_STATUS_ENDPOINT, false), true); |
||
161 | if (isset($result['ldap']) && $result['ldap']) { |
||
162 | $GLOBALS['usersinldap'] = true; |
||
163 | } |
||
164 | |||
165 | // Instantiate Plugin Manager and init the plugins (btw: globals suck) |
||
166 | $GLOBALS['PluginManager'] = new PluginManager(ENABLE_PLUGINS); |
||
167 | $GLOBALS['PluginManager']->detectPlugins(DISABLED_PLUGINS_LIST); |
||
168 | |||
169 | // Initialize plugins and prevent any output which might be written as |
||
170 | // plugins might be uncleanly output white-space and other stuff. We must |
||
171 | // not allow this here as it can destroy the response data. |
||
172 | ob_start(); |
||
173 | $GLOBALS['PluginManager']->initPlugins(DEBUG_LOADER); |
||
174 | ob_end_clean(); |
||
175 | |||
176 | // Create globals settings object (btw: globals suck) |
||
177 | $GLOBALS["settings"] = new Settings(); |
||
178 | |||
179 | // Create global operations object |
||
180 | $GLOBALS["operations"] = new Operations(); |
||
181 | |||
182 | // If webapp feature is not enabled for the user, |
||
183 | // we will show the login page with appropriated error message. |
||
184 | if ($GLOBALS['mapisession']->isWebappDisableAsFeature()) { |
||
185 | header("X-grommunio-Hresult: " . get_mapi_error_name(MAPI_E_WEBAPP_FEATURE_DISABLED)); |
||
186 | |||
187 | $error = _("Sorry, access to grommunio Web is not available with this user account. Please contact your system administrator."); |
||
188 | // Set some template variables for the login page |
||
189 | $user = sanitizeGetValue('user', '', USERNAME_REGEX); |
||
190 | |||
191 | $url = '?logon'; |
||
192 | // Set a template variable for the favicon of the login, welcome, and webclient page |
||
193 | $theme = Theming::getActiveTheme(); |
||
194 | $favicon = getFavicon(Theming::getActiveTheme()); |
||
195 | $webappSession->destroy(); |
||
196 | // Include the login template |
||
197 | include BASE_PATH . 'server/includes/templates/login.php'; |
||
198 | |||
199 | exit; |
||
200 | } |
||
201 | |||
202 | $Language = new Language(); |
||
203 | |||
204 | // Set session settings (language & style) |
||
205 | foreach ($GLOBALS["settings"]->getSessionSettings($Language) as $key => $value) { |
||
206 | $_SESSION[$key] = $value; |
||
207 | } |
||
208 | |||
209 | // Get language from the request, or the session, or the user settings, or the config |
||
210 | if (isset($_REQUEST["language"]) && $Language->is_language($_REQUEST["language"])) { |
||
211 | $lang = $_REQUEST["language"]; |
||
212 | $GLOBALS["settings"]->set("zarafa/v1/main/language", $lang); |
||
213 | } |
||
214 | elseif (isset($_SESSION["lang"])) { |
||
215 | $lang = $_SESSION["lang"]; |
||
216 | $GLOBALS["settings"]->set("zarafa/v1/main/language", $lang); |
||
217 | } |
||
218 | else { |
||
219 | $lang = $GLOBALS["settings"]->get("zarafa/v1/main/language"); |
||
220 | if (empty($lang)) { |
||
221 | $lang = LANG; |
||
222 | $GLOBALS["settings"]->set("zarafa/v1/main/language", $lang); |
||
223 | } |
||
224 | } |
||
225 | |||
226 | $Language->setLanguage($lang); |
||
227 | setcookie('lang', $lang, [ |
||
228 | 'expires' => time() + 31536000, |
||
229 | 'path' => '/', |
||
230 | 'domain' => '', |
||
231 | 'secure' => true, |
||
232 | 'httponly' => true, |
||
233 | 'samesite' => 'Strict', |
||
234 | ]); |
||
235 | |||
236 | // add extra header |
||
237 | header("X-grommunio: " . trim(file_get_contents('version'))); |
||
238 | |||
239 | // Set a template variable for the favicon of the login, welcome, and webclient page |
||
240 | $theme = Theming::getActiveTheme(); |
||
241 | $favicon = getFavicon(Theming::getActiveTheme()); |
||
242 | $hideFavorites = $GLOBALS["settings"]->get("zarafa/v1/contexts/hierarchy/hide_favorites") ? 'hideFavorites' : ''; |
||
243 | $scrollFavorites = $GLOBALS["settings"]->get("zarafa/v1/contexts/hierarchy/scroll_favorites") ? 'scrollFavorites' : ''; |
||
244 | $unreadBorders = $GLOBALS["settings"]->get("zarafa/v1/main/unread_borders") === false ? '' : 'k-unreadborders'; |
||
245 | |||
246 | // If GET parameter 'load' is defined, we defer handling to the load.php script |
||
247 | if (isset($_GET['load'])) { |
||
248 | include BASE_PATH . 'server/includes/load.php'; |
||
249 | |||
250 | exit; |
||
251 | } |
||
252 | |||
253 | if (ENABLE_WELCOME_SCREEN && $GLOBALS["settings"]->get("zarafa/v1/main/show_welcome") !== false) { |
||
254 | // These hooks are defined twice (also when there is a "load" argument supplied) |
||
255 | $GLOBALS['PluginManager']->triggerHook("server.index.load.welcome.before"); |
||
256 | include BASE_PATH . 'server/includes/templates/welcome.php'; |
||
257 | $GLOBALS['PluginManager']->triggerHook("server.index.load.welcome.after"); |
||
258 | } |
||
259 | else { |
||
260 | // Set the show_welcome to false, so that when the admin is changing the |
||
261 | // ENABLE_WELCOME_SCREEN option to false after some time, the users who are already |
||
262 | // using grommunio Web are not bothered with the Welcome Screen. |
||
263 | $GLOBALS["settings"]->set("zarafa/v1/main/show_welcome", false); |
||
264 | |||
265 | // Clean up old state files in tmp/session/ |
||
266 | $state = new State("index"); |
||
267 | $state->clean(); |
||
268 | |||
269 | // Clean up old attachments in tmp/attachments/ |
||
270 | $state = new AttachmentState(); |
||
271 | $state->clean(); |
||
272 | |||
273 | // Fetch the hierarchy state cache for unread counters notifications for subfolders |
||
274 | $counterState = new State('counters_sessiondata'); |
||
275 | $counterState->open(); |
||
276 | $counterState->write("sessionData", updateHierarchyCounters()); |
||
277 | $counterState->close(); |
||
278 | |||
279 | // clean search folders |
||
280 | cleanSearchFolders(); |
||
281 | |||
282 | // These hooks are defined twice (also when there is a "load" argument supplied) |
||
283 | $GLOBALS['PluginManager']->triggerHook("server.index.load.main.before"); |
||
284 | |||
285 | // Include webclient |
||
286 | include BASE_PATH . 'server/includes/templates/webclient.php'; |
||
287 | $GLOBALS['PluginManager']->triggerHook("server.index.load.main.after"); |
||
288 | } |
||
289 |