Issues (752)

modules/class.outofofficesettingsmodule.php (4 issues)

1
<?php
2
3
/**
4
 * OutOfOfficeSettingsModule Module.
5
 */
6
class OutOfOfficeSettingsModule extends Module {
7
	/**
8
	 * Constructor.
9
	 *
10
	 * @param int   $id   unique id
11
	 * @param array $data list of all actions
12
	 */
13
	public function __construct($id, $data) {
14
		parent::__construct($id, $data);
15
16
		$this->properties = $GLOBALS["properties"]->getOutOfOfficeProperties();
17
	}
18
19
	/**
20
	 * Executes all the actions in the $data variable.
21
	 */
22
	#[Override]
23
	public function execute() {
24
		foreach ($this->data as $actionType => $action) {
25
			if (isset($actionType)) {
26
				try {
27
					match ($actionType) {
28
						"list" => $this->getOofSettings(),
0 ignored issues
show
Are you sure the usage of $this->getOofSettings() targeting OutOfOfficeSettingsModule::getOofSettings() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
29
						"save" => $this->saveOofSettings($action),
0 ignored issues
show
Are you sure the usage of $this->saveOofSettings($action) targeting OutOfOfficeSettingsModule::saveOofSettings() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
30
						default => $this->handleUnknownActionType($actionType),
0 ignored issues
show
Are you sure the usage of $this->handleUnknownActionType($actionType) targeting Module::handleUnknownActionType() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
31
					};
32
				}
33
				catch (MAPIException|SettingsException $e) {
34
					$this->processException($e, $actionType);
35
				}
36
			}
37
		}
38
	}
39
40
	/**
41
	 * Read 'out of office' settings from PR_EC_OUTOFOFFICE_*.
42
	 *
43
	 * Internal function to retrieve the 'out of office' settings from the store, these settings are normal properties on the store
44
	 */
45
	public function getOofSettings() {
46
		$otherStores = $this->getOwnerPermissionStores();
47
		array_unshift($otherStores, $GLOBALS['mapisession']->getDefaultMessageStore());
48
49
		$oofSettings = [];
50
		foreach ($otherStores as $storeEntryId => $storeObj) {
51
			$props = mapi_getprops($storeObj, $this->properties);
52
			if (!isset($props[PR_EC_OUTOFOFFICE])) {
53
				$props[PR_EC_OUTOFOFFICE] = false;
54
			}
55
			if (!isset($props[PR_EC_OUTOFOFFICE_MSG])) {
56
				$props[PR_EC_OUTOFOFFICE_MSG] = '';
57
			}
58
			if (!isset($props[PR_EC_OUTOFOFFICE_SUBJECT])) {
59
				$props[PR_EC_OUTOFOFFICE_SUBJECT] = '';
60
			}
61
			if (!isset($props[PR_EC_OUTOFOFFICE_FROM])) {
62
				$props[PR_EC_OUTOFOFFICE_FROM] = 0;
63
			}
64
			if (!isset($props[PR_EC_OUTOFOFFICE_UNTIL]) || $props[PR_EC_OUTOFOFFICE_UNTIL] === FUTURE_ENDDATE) {
65
				$props[PR_EC_OUTOFOFFICE_UNTIL] = 0;
66
			}
67
			if (!isset($props[PR_EC_ALLOW_EXTERNAL])) {
68
				$props[PR_EC_ALLOW_EXTERNAL] = 0;
69
			}
70
			if (!isset($props[PR_EC_EXTERNAL_AUDIENCE])) {
71
				$props[PR_EC_EXTERNAL_AUDIENCE] = 0;
72
			}
73
			if (!isset($props[PR_EC_EXTERNAL_REPLY])) {
74
				$props[PR_EC_EXTERNAL_REPLY] = '';
75
			}
76
			if (!isset($props[PR_EC_EXTERNAL_SUBJECT])) {
77
				$props[PR_EC_EXTERNAL_SUBJECT] = '';
78
			}
79
80
			$externalProps['props']['entryid'] = bin2hex((string) $props[PR_MAILBOX_OWNER_ENTRYID]);
81
			$externalProps['props']['store_entryid'] = bin2hex((string) $props[PR_ENTRYID]);
82
			$externalProps['props']['set'] = $props[PR_EC_OUTOFOFFICE];
83
			$externalProps['props']['internal_reply'] = trim((string) $props[PR_EC_OUTOFOFFICE_MSG]);
84
			$externalProps['props']['internal_subject'] = trim((string) $props[PR_EC_OUTOFOFFICE_SUBJECT]);
85
			$externalProps['props']['from'] = $props[PR_EC_OUTOFOFFICE_FROM];
86
			$externalProps['props']['until'] = $props[PR_EC_OUTOFOFFICE_UNTIL];
87
			$externalProps['props']['allow_external'] = $props[PR_EC_ALLOW_EXTERNAL];
88
			$externalProps['props']['external_audience'] = $props[PR_EC_EXTERNAL_AUDIENCE];
89
			$externalProps['props']['external_reply'] = trim((string) $props[PR_EC_EXTERNAL_REPLY]);
90
			$externalProps['props']['external_subject'] = trim((string) $props[PR_EC_EXTERNAL_SUBJECT]);
91
92
			array_push($oofSettings, $externalProps);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $externalProps seems to be defined later in this foreach loop on line 80. Are you sure it is defined here?
Loading history...
93
		}
94
95
		// Send success message to client
96
		$this->addActionData('list', ['item' => $oofSettings]);
97
98
		$GLOBALS["bus"]->addData($this->getResponseData());
99
	}
100
101
	/**
102
	 * Function returns array of user stores who has given 'Owner' permission to logged in user.
103
	 * Internal function to retrieve the shared stores with 'owner' permission.
104
	 *
105
	 * @return array array of user stores who has given 'owner' permission
106
	 */
107
	public function getOwnerPermissionStores() {
108
		$stores = $GLOBALS['mapisession']->getOtherUserStore();
109
110
		// $sharedOwnerStores array will contains store of users who has given 'owner' permission.
111
		// Or store of users which can be fully accessible by default user in case of 'Admin User'.
112
		$sharedOwnerStores = [];
113
114
		foreach ($stores as $storeEntryId => $storeObj) {
115
			$subTree = mapi_getprops($storeObj, [PR_IPM_SUBTREE_ENTRYID]);
116
117
			try {
118
				$subtreeObj = mapi_msgstore_openentry($storeObj, $subTree[PR_IPM_SUBTREE_ENTRYID]);
119
			}
120
			catch (MAPIException $e) {
121
				// we don't have rights to open folder, so don't include User's store.
122
				if ($e->getCode() === MAPI_E_NO_ACCESS) {
123
					continue;
124
				}
125
126
				// rethrow other errors
127
				throw $e;
128
			}
129
130
			$permission = mapi_getprops($subtreeObj, [PR_RIGHTS]);
131
			$hasSufficientPermission = $permission[PR_RIGHTS] & ecRightsSecretary === ecRightsSecretary;
132
133
			// If User store's IPM subtree has rights higher than 'secretary' then include that User's store.
134
			if ($hasSufficientPermission) {
135
				$sharedOwnerStores[$storeEntryId] = $storeObj;
136
			}
137
		}
138
139
		return $sharedOwnerStores;
140
	}
141
142
	/**
143
	 * Internal function to save the 'out of office' settings to the correct properties on the store.
144
	 * On success function will send 'success' feedback to user.
145
	 *
146
	 * Writes some properties to the PR_EC_OUTOFOFFICE_* properties
147
	 *
148
	 * @param array $action the action data, sent by the client
149
	 */
150
	public function saveOofSettings($action) {
151
		$storeEntryId = $action['store_entryid'];
152
		$oofSettings = $action['props'];
153
		$store = $GLOBALS['mapisession']->openMessageStore(hex2bin((string) $storeEntryId));
154
		$props = Conversion::mapXML2MAPI($this->properties, $oofSettings);
155
		$oofProps = mapi_getprops($store, [PR_EC_OUTOFOFFICE, PR_EC_OUTOFOFFICE_FROM, PR_EC_OUTOFOFFICE_UNTIL]);
156
157
		// If client sent until value as 0 or User set OOF to true but don't set until
158
		// then save FUTURE_ENDDATE as until date. Also when OOF is already ON and User
159
		// don't change 'until' field then check if 'until' value is available in User's store
160
		// and if not then set until date to FUTURE_ENDDATE.
161
		// Note: If we remove PR_EC_OUTOFOFFICE_UNTIL property from User's store,
162
		// then gromox is setting past value "1970-01-01 00:00:00" as until date.
163
		// To avoid this issue and for OOF to work as expected, we are setting until date as FUTURE_ENDDATE.
164
		if (isset($oofSettings['until']) && $oofSettings['until'] === 0 ||
165
			!isset($oofSettings['until']) && isset($oofSettings['set']) ||
166
			(!isset($oofSettings['until'], $oofSettings['set']) &&
167
				(!isset($oofProps[PR_EC_OUTOFOFFICE_UNTIL]) || $oofProps[PR_EC_OUTOFOFFICE_UNTIL] === 0))) {
168
			$props[$this->properties['until']] = FUTURE_ENDDATE;
169
		}
170
171
		// Check if the OOF is set for the future
172
		$oofSet = (isset($oofSettings['set']) && $oofSettings['set']) || (!isset($oofSettings['set']) && $oofProps[PR_EC_OUTOFOFFICE]);
173
		if ($oofSet && isset($oofSettings['from']) && intval($oofSettings['from']) > time()) {
174
			$props[$this->properties['set']] = 2;
175
		}
176
		if (!empty($props)) {
177
			mapi_setprops($store, $props);
178
			mapi_savechanges($store);
179
		}
180
		$this->sendFeedback(true);
181
	}
182
}
183