1: | <?php |
2: | |
3: | |
4: | |
5: | |
6: | |
7: | |
8: | namespace Aurora\Modules\CoreWebclient; |
9: | |
10: | use Aurora\Api; |
11: | use Aurora\System\Application; |
12: | use Aurora\System\Module\Decorator; |
13: | use Aurora\System\Router; |
14: | |
15: | |
16: | |
17: | |
18: | |
19: | |
20: | |
21: | |
22: | |
23: | |
24: | |
25: | |
26: | class Module extends \Aurora\System\Module\AbstractWebclientModule |
27: | { |
28: | |
29: | |
30: | |
31: | public static function getInstance() |
32: | { |
33: | return parent::getInstance(); |
34: | } |
35: | |
36: | |
37: | |
38: | |
39: | public static function Decorator() |
40: | { |
41: | return parent::Decorator(); |
42: | } |
43: | |
44: | |
45: | |
46: | |
47: | public function getModuleSettings() |
48: | { |
49: | return $this->oModuleSettings; |
50: | } |
51: | |
52: | |
53: | |
54: | |
55: | |
56: | |
57: | |
58: | public function init() |
59: | { |
60: | \Aurora\System\Router::getInstance()->registerArray( |
61: | self::GetName(), |
62: | [ |
63: | 'default' => [$this, 'EntryDefault'], |
64: | 'error' => [$this, 'EntryDefault'], |
65: | 'debugmode' => [$this, 'EntryDefault'], |
66: | 'xdebug_session_start' => [$this, 'EntryDefault'], |
67: | 'install' => [$this, 'EntryCompatibility'] |
68: | ] |
69: | ); |
70: | |
71: | $this->subscribeEvent('Core::UpdateSettings::after', array($this, 'onAfterUpdateSettings')); |
72: | $this->subscribeEvent('System::RunEntry::after', array($this, 'onAfterRunEntry')); |
73: | |
74: | $this->denyMethodsCallByWebApi([ |
75: | 'SetHtmlOutputHeaders', |
76: | ]); |
77: | } |
78: | |
79: | |
80: | |
81: | |
82: | |
83: | |
84: | private function getLanguageList($aSystemList) |
85: | { |
86: | $aResultList = []; |
87: | $aLanguageNames = $this->oModuleSettings->LanguageNames; |
88: | foreach ($aSystemList as $sLanguage) { |
89: | if (isset($aLanguageNames[$sLanguage])) { |
90: | $aResultList[] = [ |
91: | 'name' => json_decode('"' . $aLanguageNames[$sLanguage] . '"'), |
92: | 'value' => $sLanguage |
93: | ]; |
94: | } else { |
95: | $aResultList[] = [ |
96: | 'name' => $sLanguage, |
97: | 'value' => $sLanguage |
98: | ]; |
99: | } |
100: | } |
101: | return $aResultList; |
102: | } |
103: | |
104: | |
105: | |
106: | |
107: | |
108: | |
109: | |
110: | public function GetSettings() |
111: | { |
112: | \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::Anonymous); |
113: | |
114: | $oUser = \Aurora\System\Api::getAuthenticatedUser(); |
115: | $oIntegrator = \Aurora\Modules\Core\Module::getInstance()->getIntegratorManager(); |
116: | |
117: | return array( |
118: | 'AllowChangeSettings' => $this->oModuleSettings->AllowChangeSettings, |
119: | 'AllowClientDebug' => $this->oModuleSettings->AllowClientDebug, |
120: | 'AllowDesktopNotifications' => $oUser && null !== $oUser->getExtendedProp(self::GetName() . '::AllowDesktopNotifications') ? $oUser->getExtendedProp(self::GetName() . '::AllowDesktopNotifications') : $this->oModuleSettings->AllowDesktopNotifications, |
121: | 'AllowMobile' => $this->oModuleSettings->AllowMobile, |
122: | 'AllowPrefetch' => $this->oModuleSettings->AllowPrefetch, |
123: | 'AttachmentSizeLimit' => $this->oModuleSettings->AttachmentSizeLimit, |
124: | 'AutoRefreshIntervalMinutes' => $oUser && null !== $oUser->getExtendedProp(self::GetName() . '::AutoRefreshIntervalMinutes') ? $oUser->getExtendedProp(self::GetName() . '::AutoRefreshIntervalMinutes') : $this->oModuleSettings->AutoRefreshIntervalMinutes, |
125: | 'CustomLogoutUrl' => $this->oModuleSettings->CustomLogoutUrl, |
126: | 'DefaultAnonymScreenHash' => $this->oModuleSettings->DefaultAnonymScreenHash, |
127: | 'DefaultUserScreenHash' => $this->oModuleSettings->DefaultUserScreenHash, |
128: | 'GoogleAnalyticsAccount' => $this->oModuleSettings->GoogleAnalyticsAccount, |
129: | 'HeaderModulesOrder' => $this->oModuleSettings->HeaderModulesOrder, |
130: | 'IsDemo' => $this->oModuleSettings->IsDemo, |
131: | 'IsMobile' => $oIntegrator->isMobile(), |
132: | 'LanguageListWithNames' => $this->getLanguageList($oIntegrator->getLanguageList()), |
133: | 'MultipleFilesUploadLimit' => $this->oModuleSettings->MultipleFilesUploadLimit, |
134: | 'ShowQuotaBar' => $this->oModuleSettings->ShowQuotaBar, |
135: | 'ShowQuotaBarTextAsTooltip' => $this->oModuleSettings->ShowQuotaBarTextAsTooltip, |
136: | 'QuotaWarningPerc' => $this->oModuleSettings->QuotaWarningPerc, |
137: | 'Theme' => $oUser && null !== $oUser->getExtendedProp(self::GetName() . '::Theme') ? $oUser->getExtendedProp(self::GetName() . '::Theme') : $this->oModuleSettings->Theme, |
138: | 'ThemeList' => $this->oModuleSettings->ThemeList, |
139: | 'HideLogout' => $this->oModuleSettings->HideLogout, |
140: | 'BaseUrl' => Application::getBaseUrl(), |
141: | ); |
142: | } |
143: | |
144: | |
145: | |
146: | |
147: | |
148: | |
149: | public function onAfterUpdateSettings($Args, &$Result) |
150: | { |
151: | \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::NormalUser); |
152: | |
153: | $oUser = \Aurora\System\Api::getAuthenticatedUser(); |
154: | if ($oUser && $oUser->isNormalOrTenant()) { |
155: | if (isset($Args['AllowDesktopNotifications'])) { |
156: | $oUser->setExtendedProp(self::GetName() . '::AllowDesktopNotifications', $Args['AllowDesktopNotifications']); |
157: | } |
158: | if (isset($Args['AutoRefreshIntervalMinutes'])) { |
159: | $oUser->setExtendedProp(self::GetName() . '::AutoRefreshIntervalMinutes', $Args['AutoRefreshIntervalMinutes']); |
160: | } |
161: | if (isset($Args['Theme'])) { |
162: | $oUser->setExtendedProp(self::GetName() . '::Theme', $Args['Theme']); |
163: | } |
164: | |
165: | $oCoreDecorator = \Aurora\Modules\Core\Module::Decorator(); |
166: | $oCoreDecorator->UpdateUserObject($oUser); |
167: | } |
168: | |
169: | if ($oUser && $oUser->Role === \Aurora\System\Enums\UserRole::SuperAdmin) { |
170: | if (isset($Args['Theme'])) { |
171: | $this->setConfig('Theme', $Args['Theme']); |
172: | } |
173: | $Result = $this->saveModuleConfig(); |
174: | } |
175: | } |
176: | |
177: | public function GetTemplates() |
178: | { |
179: | \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::Anonymous); |
180: | |
181: | $oIntegrator = \Aurora\Modules\Core\Module::getInstance()->getIntegratorManager(); |
182: | return $oIntegrator->compileTemplates(); |
183: | } |
184: | |
185: | public function GetTranslation() |
186: | { |
187: | \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::Anonymous); |
188: | |
189: | $oIntegrator = \Aurora\Modules\Core\Module::getInstance()->getIntegratorManager(); |
190: | list($sLanguage, $sTheme) = $oIntegrator->getThemeAndLanguage(); |
191: | |
192: | return $oIntegrator->getLanguage($sLanguage); |
193: | } |
194: | |
195: | |
196: | |
197: | |
198: | public function SetHtmlOutputHeaders() |
199: | { |
200: | @\header('Content-Type: text/html; charset=utf-8', true); |
201: | $sContentSecurityPolicy = $this->oModuleSettings->ContentSecurityPolicy; |
202: | if (!empty($sContentSecurityPolicy)) { |
203: | $aArgs = []; |
204: | $aAddDefault = []; |
205: | $this->broadcastEvent( |
206: | 'AddToContentSecurityPolicyDefault', |
207: | $aArgs, |
208: | $aAddDefault |
209: | ); |
210: | if (!empty($aAddDefault)) { |
211: | $aPieces = explode(';', $sContentSecurityPolicy); |
212: | foreach ($aPieces as $iIndex => $sPiece) { |
213: | $sPrepared = strtolower(trim($sPiece)); |
214: | if (strpos($sPrepared, 'default-src') === 0) { |
215: | $aPieces[$iIndex] = implode(' ', array_merge([$sPiece], $aAddDefault)); |
216: | } |
217: | } |
218: | $sContentSecurityPolicy = implode(';', $aPieces); |
219: | } |
220: | @\header('Content-Security-Policy: ' . $sContentSecurityPolicy, true); |
221: | } |
222: | } |
223: | |
224: | |
225: | |
226: | |
227: | public function EntryDefault() |
228: | { |
229: | $sResult = ''; |
230: | |
231: | $oIntegrator = \Aurora\System\Managers\Integrator::getInstance(); |
232: | |
233: | self::Decorator()->SetHtmlOutputHeaders(); |
234: | |
235: | $sUserAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; |
236: | if (!\strpos(\strtolower($sUserAgent), 'firefox')) { |
237: | @\header('Last-Modified: ' . \gmdate('D, d M Y H:i:s') . ' GMT'); |
238: | } |
239: | |
240: | $oSettings = &\Aurora\System\Api::GetSettings(); |
241: | if ($oSettings) { |
242: | if (($oSettings->CacheCtrl && isset($_COOKIE['aft-cache-ctrl']))) { |
243: | \Aurora\System\Api::setCookie( |
244: | 'aft-cache-ctrl', |
245: | '', |
246: | \strtotime('-1 hour') |
247: | ); |
248: | \MailSo\Base\Http::SingletonInstance()->StatusHeader(304); |
249: | exit(); |
250: | } |
251: | } |
252: | |
253: | $sResult = \file_get_contents($this->GetPath() . '/templates/Index.html'); |
254: | if (\is_string($sResult)) { |
255: | if ($oSettings) { |
256: | $sFrameOptions = $oSettings->XFrameOptions; |
257: | if (0 < \strlen($sFrameOptions)) { |
258: | @\header('X-Frame-Options: ' . $sFrameOptions); |
259: | } |
260: | } |
261: | |
262: | $sResult = strtr($sResult, array( |
263: | '{{AppVersion}}' => Application::GetVersion(), |
264: | '{{IntegratorDir}}' => $oIntegrator->isRtl() ? 'rtl' : 'ltr', |
265: | '{{IntegratorLinks}}' => $oIntegrator->buildHeadersLink(), |
266: | '{{IntegratorBody}}' => $oIntegrator->buildBody() |
267: | )); |
268: | } |
269: | |
270: | |
271: | return $sResult; |
272: | } |
273: | |
274: | |
275: | |
276: | |
277: | public function EntryCompatibility() |
278: | { |
279: | $mResult = ''; |
280: | if (basename(\MailSo\Base\Http::SingletonInstance()->GetFullUrl()) !== 'adminpanel') { |
281: | \header("Location: ./"); |
282: | } |
283: | |
284: | $aCompatibilities = \Aurora\Modules\Core\Module::Decorator()->GetCompatibilities(); |
285: | $sContent = ''; |
286: | $bResult = true; |
287: | foreach ($aCompatibilities as $sModule => $aItems) { |
288: | $sContent .= "<div class=\"row\"> |
289: | <h2>Module: " . $sModule . "</h2> |
290: | </div><br />"; |
291: | foreach ($aItems as $aItem) { |
292: | $sValue = ''; |
293: | if ($aItem['Result']) { |
294: | $sValue = $this->getSuccessHtmlValue($aItem['Value']); |
295: | } else { |
296: | if (is_array($aItem['Value']) && count($aItem['Value']) > 0) { |
297: | $sValue = $this->getErrorHtmlValue($aItem['Value'][0], isset($aItem['Value'][1]) ? $aItem['Value'][1] : ''); |
298: | } |
299: | } |
300: | $sContent .= "<div class=\"row\"> |
301: | <span class=\"field_label\"><b>" . $aItem['Name'] . ":</b> </span> |
302: | <span class=\"field_value_limit\">" . $sValue . "</span> |
303: | </div>"; |
304: | $bResult &= $aItem['Result']; |
305: | } |
306: | } |
307: | $sContent .= "<br />"; |
308: | |
309: | $sPath = $this->GetPath() . '/templates/Compatibility.html'; |
310: | if (\file_exists($sPath)) { |
311: | $sResult = \file_get_contents($sPath); |
312: | if (\is_string($sResult)) { |
313: | $sResult = strtr($sResult, array( |
314: | '{{Compatibilities}}' => $sContent, |
315: | '{{Result}}' => $bResult ? |
316: | 'The current server environment meets all the requirements. Click Next to proceed.' : |
317: | 'Please make sure that all the requirements are met and click Retry.', |
318: | |
319: | '{{NextButtonHref}}' => ($bResult) ? './' : './?install', |
320: | '{{ResultClassSuffix}}' => ($bResult) ? '_ok' : '_error', |
321: | '{{NextButtonName}}' => ($bResult) ? 'next_btn' : 'retry_btn', |
322: | '{{NextButtonValue}}' => ($bResult) ? 'Next' : 'Retry' |
323: | |
324: | )); |
325: | |
326: | $mResult = $sResult; |
327: | } |
328: | } |
329: | |
330: | return $mResult; |
331: | } |
332: | |
333: | protected function getSuccessHtmlValue($sValue) |
334: | { |
335: | return '<span class="state_ok">' . $sValue . '</span>'; |
336: | } |
337: | |
338: | protected function getErrorHtmlValue($sError, $sErrorHelp = '') |
339: | { |
340: | $sResult = '<span class="state_error">' . $sError . '</span>'; |
341: | if (!empty($sErrorHelp)) { |
342: | $sResult .= '<span class="field_description">' . $sErrorHelp . '</span>'; |
343: | } |
344: | return $sResult; |
345: | } |
346: | |
347: | protected function getWarningHtmlValue($sVarning, $sVarningHelp = '') |
348: | { |
349: | $sResult = '<span class="state_warning"><img src="./images/alarm.png"> Not detected. <br />' . $sVarning . '</span>'; |
350: | if (!empty($sVarningHelp)) { |
351: | $sResult .= '<span class="field_description">' . $sVarningHelp . '</span>'; |
352: | } |
353: | return $sResult; |
354: | } |
355: | |
356: | |
357: | |
358: | |
359: | public function onAfterRunEntry(&$aArgs, &$mResult) |
360: | { |
361: | $sXClientHeader = $this->oHttp->GetHeader('X-Client'); |
362: | |
363: | $bWebClient = strtolower($sXClientHeader) === 'webclient'; |
364: | |
365: | if ($aArgs['EntryName'] === 'api' && $bWebClient ) { |
366: | $sAuthTokenKey = \Aurora\System\Application::AUTH_TOKEN_KEY; |
367: | |
368: | $oResult = @json_decode($mResult, true); |
369: | |
370: | if ($oResult) { |
371: | if (isset($oResult['ErrorCode']) && in_array($oResult['ErrorCode'], [\Aurora\System\Notifications::AuthError, \Aurora\System\Notifications::InvalidToken])) { |
372: | Api::unsetAuthTokenCookie(); |
373: | } elseif (isset($oResult['Result']) && isset($oResult['Result'][$sAuthTokenKey])) { |
374: | |
375: | Api::setAuthTokenCookie($oResult['Result'][$sAuthTokenKey]); |
376: | $oResult['Result'][$sAuthTokenKey] = true; |
377: | $mResult = \Aurora\System\Managers\Response::GetJsonFromObject('Json', $oResult); |
378: | } elseif (isset($aArgs['Module']) && $aArgs['Module'] === 'Core' && $aArgs['Method'] === 'Logout' && $oResult['Result'] === true) { |
379: | Api::unsetAuthTokenCookie(); |
380: | } |
381: | } |
382: | } |
383: | } |
384: | } |
385: | |