1: <?php
2: /**
3: * This code is licensed under AGPLv3 license or Afterlogic Software License
4: * if commercial version of the product was purchased.
5: * For full statements of the licenses see LICENSE-AFTERLOGIC and LICENSE-AGPL3 files.
6: */
7:
8: namespace Aurora\Modules\Ios;
9:
10: use Aurora\System\Api;
11:
12: /**
13: * @license https://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0
14: * @license https://afterlogic.com/products/common-licensing Afterlogic Software License
15: * @copyright Copyright (c) 2023, Afterlogic Corp.
16: *
17: * @property Module $oModule
18: */
19: class Manager extends \Aurora\System\Managers\AbstractManager
20: {
21: /**
22: * @var \Aurora\Modules\Dav\Module
23: */
24: private $oDavModule;
25:
26: /**
27: * @param \Aurora\System\Module\AbstractModule $oModule
28: */
29: public function __construct($oModule = null)
30: {
31: parent::__construct($oModule);
32:
33: $this->oDavModule = Api::GetModule('Dav');
34: }
35:
36: /**
37: *
38: * @param \DOMDocument $oXmlDocument
39: * @param array $aPayload
40: *
41: * @return \DOMElement
42: */
43: private function _generateDict($oXmlDocument, $aPayload)
44: {
45: $oDictElement = $oXmlDocument->createElement('dict');
46:
47: foreach ($aPayload as $sKey => $mValue) {
48: $oDictElement->appendChild($oXmlDocument->createElement('key', $sKey));
49:
50: if (is_int($mValue)) {
51: $oDictElement->appendChild($oXmlDocument->createElement('integer', $mValue));
52: } elseif (is_bool($mValue)) {
53: $oDictElement->appendChild($oXmlDocument->createElement($mValue ? 'true' : 'false'));
54: } else {
55: $oDictElement->appendChild($oXmlDocument->createElement('string', $mValue));
56: }
57: }
58: return $oDictElement;
59: }
60:
61: /**
62: *
63: * @param \DOMDocument $oXmlDocument
64: * @param string $sPayloadId
65: * @param \Aurora\System\Classes\Account $oAccount
66: * @param bool $bIsDemo Default false
67: *
68: * @return \DOMElement|bool
69: */
70: private function _generateEmailDict($oXmlDocument, $sPayloadId, $oAccount, $bIsDemo = false)
71: {
72: $result = false;
73:
74: if (class_exists('\Aurora\Modules\Mail\Models\MailAccount')) {
75: /** @var \Aurora\Modules\Mail\Models\MailAccount $oAccount */
76: Api::Log('Generating email part for account: ' . $oAccount->Email);
77:
78: $oModuleManager = Api::GetModuleManager();
79:
80: $oServer = $oAccount->GetServer();
81: $sIncomingServer = $oServer->IncomingServer;
82: $iIncomingPort = $oServer->IncomingPort;
83: $bIncomingUseSsl = $oServer->IncomingUseSsl;
84:
85: if ($sIncomingServer == 'localhost' || $sIncomingServer == '127.0.0.1') {
86: $sIncomingServer = $oServer->ExternalAccessImapServer;
87:
88: if (!empty($sIncomingServer)) {
89: $iIncomingPort = $oServer->ExternalAccessImapPort;
90: $bIncomingUseSsl = $oServer->ExternalAccessImapUseSsl;
91: }
92: }
93:
94: $sOutgoingServer = $oServer->OutgoingServer;
95: $iOutgoingPort = $oServer->OutgoingPort;
96: $bOutgoingUseSsl = $oServer->OutgoingUseSsl;
97:
98: if ($sOutgoingServer == 'localhost' || $sOutgoingServer == '127.0.0.1') {
99: $sOutgoingServer = $oServer->ExternalAccessSmtpServer;
100:
101: if (!empty($sOutgoingServer)) {
102: $iOutgoingPort = $oServer->ExternalAccessSmtpPort;
103: $bOutgoingUseSsl = $oServer->ExternalAccessSmtpUseSsl;
104: }
105: }
106:
107: if (empty($sIncomingServer) || empty($sOutgoingServer)) {
108: Api::Log('Error: IncomingServer or OutgoingServer is empty');
109: return false;
110: }
111:
112: $bIncludePasswordInProfile = $this->oModule->oModuleSettings->IncludePasswordInProfile;
113: $sOutgoingMailServerUsername = $oAccount->IncomingLogin;
114: $sOutgoingPassword = $oAccount->getPassword();
115: $sOutgoingMailServerAuthentication = 'EmailAuthPassword';
116: if (class_exists('\Aurora\Modules\Mail\Enums\SmtpAuthType')) {
117: if ($oServer->SmtpAuthType === \Aurora\Modules\Mail\Enums\SmtpAuthType::UseSpecifiedCredentials) {
118: $sOutgoingMailServerUsername = $oServer->SmtpLogin;
119: $sOutgoingPassword = $oServer->SmtpLogin;
120: }
121: if ($oServer->SmtpAuthType === \Aurora\Modules\Mail\Enums\SmtpAuthType::NoAuthentication) {
122: $sOutgoingMailServerAuthentication = 'EmailAuthNone';
123: }
124: }
125:
126: $aEmail = array(
127: 'PayloadVersion' => 1,
128: 'PayloadUUID' => \Sabre\DAV\UUIDUtil::getUUID(),
129: 'PayloadType' => 'com.apple.mail.managed',
130: 'PayloadIdentifier' => $sPayloadId . '.' . $oAccount->Email . '.email',
131: 'PayloadDisplayName' => $oAccount->Email . ' Email Account',
132: 'PayloadOrganization' => $oModuleManager->getModuleConfigValue('Core', 'SiteName'),
133: 'PayloadDescription' => 'Configures email account',
134: 'EmailAddress' => $oAccount->Email,
135: 'EmailAccountType' => 'EmailTypeIMAP',
136: 'EmailAccountDescription' => $oAccount->Email,
137: 'EmailAccountName' => 0 === strlen($oAccount->FriendlyName)
138: ? $oAccount->Email : $oAccount->FriendlyName,
139: 'IncomingMailServerHostName' => $sIncomingServer,
140: 'IncomingMailServerPortNumber' => $iIncomingPort,
141: 'IncomingMailServerUseSSL' => $bIncomingUseSsl,
142: 'IncomingMailServerUsername' => $oAccount->IncomingLogin,
143: 'IncomingPassword' => $bIsDemo ? 'demo' : ($bIncludePasswordInProfile ? $oAccount->getPassword() : ''),
144: 'IncomingMailServerAuthentication' => 'EmailAuthPassword',
145: 'OutgoingMailServerHostName' => $sOutgoingServer,
146: 'OutgoingMailServerPortNumber' => $iOutgoingPort,
147: 'OutgoingMailServerUseSSL' => $bOutgoingUseSsl,
148: 'OutgoingMailServerUsername' => $sOutgoingMailServerUsername,
149: 'OutgoingPassword' => $bIsDemo ? 'demo' : ($bIncludePasswordInProfile ? $sOutgoingPassword : ''),
150: 'OutgoingMailServerAuthentication' => $sOutgoingMailServerAuthentication,
151: );
152:
153: $result = $this->_generateDict($oXmlDocument, $aEmail);
154: }
155:
156: return $result;
157: }
158:
159: private function getAuthenticatedAccountPassword()
160: {
161: $aUserInfo = Api::getAuthenticatedUserInfo();
162:
163: $sAccountPassword = '';
164:
165: if (isset($aUserInfo['account']) && isset($aUserInfo['accountType'])) {
166: $oAccount = call_user_func_array([$aUserInfo['accountType'], 'find'], [(int)$aUserInfo['account']]);
167: if ($oAccount) {
168: $sAccountPassword = $oAccount->getPassword();
169: }
170: }
171:
172: return $sAccountPassword;
173: }
174:
175: /**
176: *
177: * @param \DOMDocument $oXmlDocument
178: * @param string $sPayloadId
179: * @param \Aurora\Modules\Core\Models\User $oUser
180: * @param bool $bIsDemo Default false
181: *
182: * @return \DOMElement
183: */
184: private function _generateCaldavDict($oXmlDocument, $sPayloadId, $oUser, $bIsDemo = false)
185: {
186: Api::Log('Generating caldav part for user: ' . $oUser->PublicId);
187:
188: $oModuleManager = Api::GetModuleManager();
189: $bIncludePasswordInProfile = $this->oModule->oModuleSettings->IncludePasswordInProfile;
190: $aCaldav = array(
191: 'PayloadVersion' => 1,
192: 'PayloadUUID' => \Sabre\DAV\UUIDUtil::getUUID(),
193: 'PayloadType' => 'com.apple.caldav.account',
194: 'PayloadIdentifier' => $sPayloadId . '.caldav',
195: 'PayloadDisplayName' => $oUser->PublicId . ' - CalDAV Account',
196: 'PayloadOrganization' => $oModuleManager->getModuleConfigValue('Core', 'SiteName'),
197: 'PayloadDescription' => 'Configures CalDAV Account',
198: 'CalDAVAccountDescription' => $oModuleManager->getModuleConfigValue('Core', 'SiteName') . ' Calendars',
199: 'CalDAVHostName' => $this->oDavModule ? $this->oDavModule->GetServerHost() : '',
200: 'CalDAVUsername' => $oUser->PublicId,
201: 'CalDAVPassword' => $bIsDemo ? 'demo' : ($bIncludePasswordInProfile ? $this->getAuthenticatedAccountPassword() : ''),
202: 'CalDAVUseSSL' => $this->oDavModule ? $this->oDavModule->IsSsl() : '',
203: 'CalDAVPort' => $this->oDavModule ? $this->oDavModule->GetServerPort() : '',
204: 'CalDAVPrincipalURL' => $this->oDavModule ? $this->oDavModule->GetPrincipalUrl() : '',
205: );
206:
207: return $this->_generateDict($oXmlDocument, $aCaldav);
208: }
209:
210: /**
211: *
212: * @param \DOMDocument $oXmlDocument
213: * @param string $sPayloadId
214: * @param \Aurora\Modules\Core\Models\User $oUser
215: * @param bool $bIsDemo Default false
216: *
217: * @return \DOMElement
218: */
219:
220: private function _generateCarddavDict($oXmlDocument, $sPayloadId, $oUser, $bIsDemo = false)
221: {
222: Api::Log('Generating carddav part for user: ' . $oUser->PublicId);
223:
224: $oModuleManager = Api::GetModuleManager();
225: $bIncludePasswordInProfile = $this->oModule->oModuleSettings->IncludePasswordInProfile;
226: $aCarddav = array(
227: 'PayloadVersion' => 1,
228: 'PayloadUUID' => \Sabre\DAV\UUIDUtil::getUUID(),
229: 'PayloadType' => 'com.apple.carddav.account',
230: 'PayloadIdentifier' => $sPayloadId . '.carddav',
231: 'PayloadDisplayName' => $oUser->PublicId . ' - CardDAV Account',
232: 'PayloadOrganization' => $oModuleManager->getModuleConfigValue('Core', 'SiteName'),
233: 'PayloadDescription' => 'Configures CardDAV Account',
234: 'CardDAVAccountDescription' => $oModuleManager->getModuleConfigValue('Core', 'SiteName') . ' Contacts',
235: 'CardDAVHostName' => $this->oDavModule ? $this->oDavModule->GetServerHost() : '',
236: 'CardDAVUsername' => $oUser->PublicId,
237: 'CardDAVPassword' => $bIsDemo ? 'demo' : ($bIncludePasswordInProfile ? $this->getAuthenticatedAccountPassword() : ''),
238: 'CardDAVUseSSL' => $this->oDavModule ? $this->oDavModule->IsSsl() : '',
239: 'CardDAVPort' => $this->oDavModule ? $this->oDavModule->GetServerPort() : '',
240: 'CardDAVPrincipalURL' => $this->oDavModule ? $this->oDavModule->GetPrincipalUrl() : '',
241: );
242:
243: return $this->_generateDict($oXmlDocument, $aCarddav);
244: }
245:
246: /**
247: * @param \Aurora\Modules\Core\Models\User $oUser
248: * @return string
249: */
250: public function generateXMLProfile($oUser)
251: {
252: Api::Log('Generating Ios profile.');
253:
254: $mResult = false;
255:
256: if ($oUser) {
257: $oDomImplementation = new \DOMImplementation();
258: $oDocumentType = $oDomImplementation->createDocumentType(
259: 'plist',
260: '-//Apple//DTD PLIST 1.0//EN',
261: 'http://www.apple.com/DTDs/PropertyList-1.0.dtd'
262: );
263:
264: $oXmlDocument = $oDomImplementation->createDocument('', '', $oDocumentType);
265: $oXmlDocument->xmlVersion = '1.0';
266: $oXmlDocument->encoding = 'UTF-8';
267: $oXmlDocument->formatOutput = true;
268:
269: $oPlist = $oXmlDocument->createElement('plist');
270: $oPlist->setAttribute('version', '1.0');
271:
272: $sPayloadId = $this->oDavModule ? 'afterlogic.' . $this->oDavModule->GetServerHost() . '.' . $oUser->PublicId : '';
273:
274: $oModuleManager = Api::GetModuleManager();
275: $aPayload = array(
276: 'PayloadVersion' => 1,
277: 'PayloadUUID' => \Sabre\DAV\UUIDUtil::getUUID(),
278: 'PayloadType' => 'Configuration',
279: 'PayloadRemovalDisallowed' => false,
280: 'PayloadIdentifier' => $sPayloadId,
281: 'PayloadOrganization' => $oModuleManager->getModuleConfigValue('Core', 'SiteName'),
282: 'PayloadDescription' => $oModuleManager->getModuleConfigValue('Core', 'SiteName') . ' Mobile',
283: 'PayloadDisplayName' => $oModuleManager->getModuleConfigValue('Core', 'SiteName') . ' (' . $oUser->PublicId . ') Mobile Profile',
284: );
285:
286: $oArrayElement = $oXmlDocument->createElement('array');
287:
288: $bIsDemo = false;
289:
290: if (class_exists('\Aurora\Modules\DemoModePlugin\Module')) {
291: $oDemoModePlugin = \Aurora\Modules\DemoModePlugin\Module::getInstance();
292: if ($oDemoModePlugin && $oDemoModePlugin->IsDemoUser()) {
293: $bIsDemo = true;
294: }
295: }
296:
297: if (class_exists('\Aurora\Modules\Mail\Module')) {
298: $oMailModule = Api::GetModule('Mail');
299: /** @var \Aurora\Modules\Mail\Module $oMailModule */
300: if ($oMailModule && !$bIsDemo) {
301: $aAccounts = $oMailModule->GetAccounts($oUser->Id);
302: if (is_array($aAccounts) && 0 < count($aAccounts)) {
303: foreach ($aAccounts as $oAccountItem) {
304: $oEmailDictElement = $this->_generateEmailDict($oXmlDocument, $sPayloadId, $oAccountItem, $bIsDemo);
305:
306: if ($oEmailDictElement === false) {
307: Api::Log('Error: incorrect email part is for account: ' . $oAccountItem->Email);
308: return false;
309: } else {
310: $oArrayElement->appendChild($oEmailDictElement);
311: }
312:
313: unset($oAccountItem);
314: unset($oEmailDictElement);
315: }
316: }
317: }
318: }
319:
320: if (class_exists('\Aurora\Modules\MobileSync\Module')) {
321: // $oMobileSyncModule = Api::GetModule('MobileSync');
322: $oMobileSyncModule = \Aurora\Modules\MobileSync\Module::getInstance();
323:
324: if ($oMobileSyncModule && !$oMobileSyncModule->oModuleSettings->Disabled) {
325: // Calendars
326: $oCaldavDictElement = $this->_generateCaldavDict($oXmlDocument, $sPayloadId, $oUser, $bIsDemo);
327: $oArrayElement->appendChild($oCaldavDictElement);
328:
329: // Contacts
330: $oCarddavDictElement = $this->_generateCarddavDict($oXmlDocument, $sPayloadId, $oUser, $bIsDemo);
331: $oArrayElement->appendChild($oCarddavDictElement);
332: }
333: }
334:
335: $oDictElement = $this->_generateDict($oXmlDocument, $aPayload);
336: $oPayloadContentElement = $oXmlDocument->createElement('key', 'PayloadContent');
337: $oDictElement->appendChild($oPayloadContentElement);
338: $oDictElement->appendChild($oArrayElement);
339: $oPlist->appendChild($oDictElement);
340:
341: $oXmlDocument->appendChild($oPlist);
342: $mResult = $oXmlDocument->saveXML();
343: }
344:
345: return $mResult;
346: }
347: }
348: