1: <?php
2:
3: /**
4: * Profile modules
5: * @package modules
6: * @subpackage profile
7: */
8:
9: if (!defined('DEBUG_MODE')) { die(); }
10:
11: require_once APP_PATH.'modules/profiles/hm-profiles.php';
12: require APP_PATH.'modules/profiles/functions.php';
13:
14: /**
15: * @subpackage profile/handler
16: */
17: class Hm_Handler_profile_edit_data extends Hm_Handler_Module {
18: public function process() {
19: $id = false;
20: if (array_key_exists('profile_id', $this->request->get)) {
21: $id = $this->request->get['profile_id'];
22: }
23: $accounts = $this->get('profiles');
24:
25: foreach ($accounts as $acc) {
26: if ($acc['id'] == $id) {
27: $account = $acc;
28: }
29: }
30:
31: if ($id !== false) {
32: $this->out('edit_profile', $account);
33: $this->out('default_email_domain', $this->config->get('default_email_domain'));
34: $this->out('edit_profile_id', $id);
35: }
36: else {
37: $this->out('new_profile_id', count($accounts));
38: }
39: }
40: }
41:
42: /**
43: * @subpackage profile/handler
44: */
45: class Hm_Handler_compose_profile_data extends Hm_Handler_Module {
46: public function process() {
47: Hm_Profiles::init($this);
48: $compose_profiles = array();
49: foreach (Hm_Profiles::getAll() as $id => $vals) {
50: if (! empty($vals['smtp_id'])) {
51: $compose_profiles[] = $vals;
52: }
53: }
54: $this->out('compose_profiles', $compose_profiles);
55: $this->out('profiles', Hm_Profiles::getAll());
56: }
57: }
58:
59: /**
60: * @subpackage profile/handler
61: */
62: class Hm_Handler_process_smtp_server_data_delete extends Hm_Handler_Module {
63: public function process() {
64: if (isset($this->request->post['smtp_delete'])) {
65: $deleted_server_id = $this->get('deleted_server_id', '');
66: Hm_Profiles::init($this);
67: $servers = Hm_Profiles::getBy($deleted_server_id,'smtp_id');
68: if ($servers) {
69: foreach ($servers as $server) {
70: Hm_Profiles::del($server['id']);
71: Hm_Msgs::add("Profile {$server['name']} has been deleted since its server was removed.");
72: }
73: }
74: }
75: }
76: }
77:
78: /**
79: * @subpackage profile/handler
80: */
81: class Hm_Handler_process_imap_server_data_delete extends Hm_Handler_Module {
82: public function process() {
83: if (isset($this->request->post['imap_delete'])) {
84: $deleted_server_id = $this->get('deleted_server_id', '');
85: Hm_Profiles::init($this);
86: $servers = Hm_Profiles::getBy($deleted_server_id,'imap_id');
87: if ($servers) {
88: foreach ($servers as $server) {
89: Hm_Profiles::del($server['id']);
90: Hm_Msgs::add("Profile {$server['name']} has been deleted since its server was removed.");
91: }
92: }
93: }
94: }
95: }
96:
97: /**
98: * @subpackage profile/handler
99: */
100: class Hm_Handler_process_profile_delete extends Hm_Handler_Module {
101: public function process() {
102: list($success, $form) = $this->process_form(array('profile_delete', 'profile_id'));
103: if (!$success) {
104: return;
105: }
106:
107: if (($profile = Hm_Profiles::get($form['profile_id']))) {
108:
109: $server = Hm_SMTP_List::get($profile['smtp_id'], false);
110:
111: if (array_key_exists('autocreate', $profile) && $server) {
112: Hm_Msgs::add('Automatically created profile cannot be deleted', 'warning');
113: return;
114: }
115: Hm_Profiles::del($form['profile_id']);
116: Hm_Msgs::add('Profile Deleted');
117: } else {
118: Hm_Msgs::add('Profile ID not found', 'warning');
119: return;
120: }
121: }
122: }
123: /**
124: * @subpackage profile/handler
125: */
126: class Hm_Handler_process_profile_update extends Hm_Handler_Module {
127: public function process() {
128: if (array_key_exists('profile_delete', $this->request->post)) {
129: return;
130: }
131: list($success, $form) = $this->process_form(array('profile_id', 'profile_address',
132: 'profile_smtp', 'profile_replyto', 'profile_name', 'profile_imap', 'profile_rmk'));
133:
134: if (isset($this->request->post['profile_quickly_create_value']) && $this->request->post['profile_quickly_create_value'] === "yes") {
135: $array_profil_imap = explode("|", $form['profile_imap']);
136: if (count($array_profil_imap) == 2) {
137: $profile_name = explode("@", $array_profil_imap[1]);
138: $form['profile_name'] = $profile_name[0];
139: $form['profile_address'] = $array_profil_imap[1];
140: $form['profile_replyto'] = $array_profil_imap[1];
141: }
142: }
143: if (!$success) {
144: return;
145: }
146: $default = false;
147: $sig = '';
148: $rmk = '';
149: $user = false;
150: $server = false;
151:
152: $imap_server = explode('|', $form['profile_imap']);
153: if (count($imap_server) == 2) {
154: $server = $imap_server[0];
155: $user = $imap_server[1];
156: }
157: if (!$user || !$server || !$form['profile_name']) {
158: return;
159: }
160:
161: if (array_key_exists('profile_sig', $this->request->post)) {
162: $sig = $this->request->post['profile_sig'];
163: }
164: if (array_key_exists('profile_rmk', $this->request->post)) {
165: $rmk = $this->request->post['profile_rmk'];
166: }
167: if (array_key_exists('profile_default', $this->request->post)) {
168: $default = true;
169: }
170:
171: $profile = array(
172: 'name' => html_entity_decode($form['profile_name'], ENT_QUOTES),
173: 'sig' => $sig,
174: 'rmk' => $rmk,
175: 'smtp_id' => $form['profile_smtp'],
176: 'replyto' => $form['profile_replyto'],
177: 'default' => $default,
178: 'address' => $form['profile_address'],
179: 'server' => $server,
180: 'user' => $user,
181: 'type' => 'imap'
182: );
183: if (Hm_Profiles::get($form['profile_id'])) {
184: $profile['id'] = $form['profile_id'];
185: Hm_Profiles::edit($form['profile_id'], $profile);
186: } else {
187: $profiles = $this->get('profiles');
188:
189: foreach ($profiles as $existing_profile) {
190: if (
191: ($existing_profile["address"] === $profile["address"] && $existing_profile["smtp_id"] === $profile["smtp_id"]) ||
192: ($existing_profile["replyto"] === $profile["replyto"] && $existing_profile["smtp_id"] === $profile["smtp_id"])
193: ) {
194: Hm_Msgs::add('Profile with this email address or reply-to address already exists', 'warning');
195: return;
196: }
197: }
198: Hm_Profiles::add($profile);
199: Hm_Msgs::add('Profile Created');
200: }
201:
202: if ($default) {
203: Hm_Profiles::setDefault($form['profile_id']);
204: }
205: }
206: }
207:
208: /**
209: * @subpackage profile/handler
210: * If no 'imap_server_id' is provided, we select a default server based on the user profile.
211: * This handler works in conjunction with imap_folders/Hm_Handler_folders_server_id,
212: * which handles the case where 'imap_server_id' is explicitly provided.
213: */
214: class Hm_Handler_load_default_server_from_profiles extends Hm_Handler_Module {
215: public function process() {
216: if (!array_key_exists('imap_server_id', $this->request->get)) {
217: Hm_Profiles::init($this);
218: $defaultProfile = Hm_Profiles::getDefault();
219: $server = Hm_IMAP_List::getBy($defaultProfile['server'],'server', true);
220: if (!is_null($server) && !empty($server['id'])) {
221: $this->out('folder_server', $server['id']);
222: $this->out('trigger_default_submit', true);
223: }
224: }
225: }
226: }
227:
228: /**
229: * @subpackage profile/handler
230: */
231: class Hm_Handler_profile_data extends Hm_Handler_Module {
232: public function process() {
233: Hm_Profiles::init($this);
234: $this->out('profiles', Hm_Profiles::getAll());
235: }
236: }
237:
238: /**id
239: * @subpackage profile/output
240: */
241: class Hm_Output_profile_edit_form extends Hm_Output_Module {
242: protected function output() {
243: $new_id = $this->get('new_profile_id', -1);
244: $res = '<div class="profile_content p-0"><div class="content_title px-3 d-flex justify-content-between"><span class="profile_content_title">'.$this->trans('Profiles').'</span>';
245: $smtp_servers = $this->get('smtp_servers', array());
246: $imap_servers = $this->get('imap_servers', array());
247: if ($this->get('edit_profile')) {
248: $profile = $this->get('edit_profile');
249: $id = $this->get('edit_profile_id');
250: $res .= profile_form($profile, $id, $smtp_servers, $imap_servers, $this);
251: }
252: if ($new_id !== -1) {
253: $res .= profile_form(array('default' => '', 'name' => '', 'address' => '', 'replyto' => '',
254: 'smtp_id' => '', 'sig' => '', 'user' => '', 'server' => '', 'rmk' => ''), $new_id, $smtp_servers,
255: $imap_servers, $this);
256: }
257: $res .= '</div>';
258: return $res;
259: }
260: }
261:
262: /**
263: * @subpackage profile/output
264: */
265: class Hm_Output_profile_page_link extends Hm_Output_Module {
266: protected function output() {
267: $res = '<li class="menu_profiles"><a class="unread_link" href="?page=profiles">';
268: if (!$this->get('hide_folder_icons')) {
269: $res .= '<i class="bi bi-person-fill menu-icon"></i>';
270: }
271: $res .= $this->trans('Profiles').'</a></li>';
272: if ($this->format == 'HTML5') {
273: return $res;
274: }
275: $this->concat('formatted_folder_list', $res);
276: }
277: }
278:
279: /**
280: * @subpackage profile/output
281: */
282: class Hm_Output_compose_signature_button extends Hm_Output_Module {
283: protected function output() {
284: return '<input type="hidden" value="'.$this->trans('You need at least one profile with a signature to sign messages. Please configure a signature in your profile settings.').'" id="sign_msg" />'.
285: '<input class="compose_sign btn btn-light float-end mt-3 me-2 border" type="button" value="'.$this->trans('Sign').'" />';
286: }
287: }
288:
289: /**
290: * @subpackage profile/output
291: */
292: class Hm_Output_compose_signature_values extends Hm_Output_Module {
293: protected function output() {
294: $res = '<script type="text/javascript">var profile_signatures = {';
295: $sigs = array();
296: $used = array();
297: $profiles = $this->get('profiles');
298: foreach ($this->get('compose_profiles', array()) as $vals) {
299: $smtp_profiles = profiles_by_smtp_id($profiles, $vals['smtp_id']);
300: if (count($smtp_profiles) > 0) {
301: foreach ($smtp_profiles as $index => $smtp_vals) {
302: if (in_array($smtp_vals['id'], $used, true)) {
303: continue;
304: }
305: if (mb_strlen(trim($smtp_vals['sig']))) {
306: $sigs[] = sprintf("\"%s\": \"\\n%s\\n\"", $smtp_vals['smtp_id'].'.'.($index+1), $this->html_safe(str_replace("\r\n", "\\n", $smtp_vals['sig'])));
307: $used[] = $smtp_vals['id'];
308: }
309: }
310: }
311: else {
312: if (in_array($vals['id'], $used, true)) {
313: continue;
314: }
315: if (mb_strlen(trim($vals['sig']))) {
316: $sigs[] = sprintf("\"%s\": \"\\n%s\\n\"", $vals['smtp_id'], $this->html_safe(str_replace("\r\n", "\\n", $vals['sig'])));
317: $used[] = $vals['id'];
318: }
319: }
320: }
321: $res .= implode(', ', $sigs).'}</script>';
322: return $res;
323: }
324: }
325:
326: /**
327: * @subpackage profile/output
328: */
329: class Hm_Output_profile_content extends Hm_Output_Module {
330: protected function output() {
331: $profiles = $this->get('profiles');
332: $res = '';
333: if (count($profiles) > 0) {
334: $smtp_servers = $this->get('smtp_servers', array());
335: $res .= '<div class="table-responsive p-3"><table class="table table-striped"><tr>'.
336: '<th>'.$this->trans('Display Name').'</th>'.
337: '<th class="d-none d-sm-table-cell">'.$this->trans('IMAP Server').'</th>'.
338: '<th class="d-none d-sm-table-cell">'.$this->trans('Username').'</th>'.
339: '<th class="d-none d-sm-table-cell">'.$this->trans('E-mail Address').'</th>'.
340: '<th class="d-none d-sm-table-cell">'.$this->trans('Reply-to').'</th>'.
341: '<th class="d-none d-sm-table-cell">'.$this->trans('SMTP Server').'</th>'.
342: '<th class="d-none d-sm-table-cell">'.$this->trans('Signature').'</th>'.
343: '<th class="d-none d-sm-table-cell">'.$this->trans('Remark').'</th>'.
344: '<th class="d-none d-sm-table-cell">'.$this->trans('Default').'</th>'.
345: '<th></th></tr>';
346:
347: foreach ($profiles as $id => $profile) {
348: $smtp = '';
349: if (isset($profile['smtp_id']) && is_scalar($profile['smtp_id']) && array_key_exists($profile['smtp_id'], $smtp_servers)) {
350: $smtp = $smtp_servers[$profile['smtp_id']]['name'];
351: }
352: $res .= '<tr>'.
353: '<td>'.$this->html_safe($profile['name']).'</td>'.
354: '<td class="d-none d-sm-table-cell">'.$this->html_safe($profile['server']).'</td>'.
355: '<td class="d-none d-sm-table-cell">'.$this->html_safe($profile['user']).'</td>'.
356: '<td class="d-none d-sm-table-cell">'.$this->html_safe($profile['address']).'</td>'.
357: '<td class="d-none d-sm-table-cell">'.$this->html_safe($profile['replyto']).'</td>'.
358: '<td class="d-none d-sm-table-cell">'.$this->html_safe($smtp).'</td>'.
359: '<td class="d-none d-sm-table-cell">'.(mb_strlen($profile['sig']) > 0 ? $this->trans('Yes') : $this->trans('No')).'</td>'.
360: '<td class="d-none d-sm-table-cell">'.(mb_strlen($profile['rmk']) > 0 ? $this->trans('Yes') : $this->trans('No')).'</td>'.
361: '<td class="d-none d-sm-table-cell">'.($profile['default'] ? $this->trans('Yes') : $this->trans('No')).'</td>'.
362: '<td class="text-right"><a href="?page=profiles&amp;profile_id='.$this->html_safe($profile['id']).'" title="'.$this->trans('Edit').'">'.
363: '<i class="bi bi-pencil-fill"></i></a></td>'.
364: '</tr>';
365: }
366: $res .= '</table></div>';
367: }
368: else {
369: $res .= '<div class="d-flex flex-column align-items-center justify-content-center p-5 mt-5"><i class="bi bi-folder2-open fs-4"></i><span>'.$this->trans('No Profiles Found').'</span></div>';
370: }
371: $res .= '</div>';
372: return $res;
373: }
374: }
375:
376: /**
377: * @subpackage profile/functions
378: */
379: if (!hm_exists('profile_form')) {
380: function profile_form($form_vals, $id, $smtp_servers, $imap_servers, $out_mod) {
381: $res = '';
382: if ($form_vals['name']) {
383: $res .= '<span>';
384: $res .= '<i class="bi bi-caret-right-fill"></i>';
385: $res .= $out_mod->html_safe($form_vals['name']);
386: $res .= '</span>';
387: }
388: else {
389: $res .= '<button class="refresh_list add_profile btn btn-light btn-sm d-flex" title="'.$out_mod->trans('Add a profile').'"><i class="bi bi-plus"></i><span class="d-none d-sm-table-cell">'.$out_mod->trans('Add a profile').'</span></button>';
390: }
391: $res .= '</div>';
392:
393: $res .= '<div class="edit_profile row p-3" '.($form_vals['name'] ? '' : 'style="display: none;"').'><div class="col-12 col-lg-8 col-xl-5">';
394:
395: $res .= '<form method="post" action="?page=profiles">';
396: if (empty($form_vals['id'])) {
397: $res .= '<div class="form-check form-switch mt-3 mb-3">';
398: $res .= '<input class="form-check-input" name="profile_quickly_create" type="checkbox" role="switch" id="profile_quickly_create">';
399: $res .= '<input type="hidden" name="profile_quickly_create_value" id="profile_quickly_create_value" value="non">';
400: $res .= '<label class="form-check-label" for="profile_quickly_create">'.$out_mod->trans('Quickly create Profile').'</label>';
401: $res .= '</div>';
402: }
403: $res .= '<input type="hidden" name="profile_id" value="'.$out_mod->html_safe($id).'" />';
404: $res .= '<input type="hidden" name="hm_page_key" value="'.$out_mod->html_safe(Hm_Request_Key::generate()).'" />';
405:
406: // Display Name
407: $res .= '<div class="form-floating mb-3 form-check-create-profile">';
408: $res .= '<input type="text" required name="profile_name" class="form-control" value="'.$out_mod->html_safe($form_vals['name']).'" placeholder="'.$out_mod->trans('Display Name').' *">';
409: $res .= '<label>'.$out_mod->trans('Display Name').' *</label></div>';
410:
411: // Email Address
412: $res .= '<div class="form-floating mb-3 form-check-create-profile">';
413: $res .= '<input type="email" required name="profile_address" class="form-control" value="'.$out_mod->html_safe($form_vals['address']).'" placeholder="'.$out_mod->trans('E-mail Address').' *">';
414: $res .= '<label>'.$out_mod->trans('E-mail Address').' *</label></div>';
415:
416: // Reply-to
417: $res .= '<div class="form-floating mb-3 form-check-create-profile">';
418: $res .= '<input type="email" name="profile_replyto" class="form-control" value="'.$out_mod->html_safe($form_vals['replyto']).'" placeholder="'.$out_mod->trans('Reply-to').' *">';
419: $res .= '<label>'.$out_mod->trans('Reply-to').' *</label></div>';
420:
421: // IMAP Server
422: $res .= '<div class="form-floating mb-3">';
423: $res .= '<select required name="profile_imap" class="form-select">';
424: foreach ($imap_servers as $id => $server) {
425: $res .= '<option '.(($server['user'] == $form_vals['user'] && $server['server'] == $form_vals['server']) ? 'selected="selected"' : '').' value="'.$out_mod->html_safe($server['server'].'|'.$server['user']).'">'.$out_mod->html_safe($server['name']).'</option>';
426: }
427: $res .= '</select>';
428: $res .= '<label>'.$out_mod->trans('IMAP Server').' *</label></div>';
429:
430: // SMTP Server
431: $res .= '<div class="form-floating mb-3">';
432: $res .= '<select required name="profile_smtp" class="form-select">';
433: foreach ($smtp_servers as $id => $server) {
434: $res .= '<option ';
435: if ($server['id'] == $form_vals['smtp_id']) {
436: $res .= 'selected="selected"';
437: }
438: $res .= 'value="'.$out_mod->html_safe($server['id']).'">'.$out_mod->html_safe($server['name']).'</option>';
439: }
440: $res .= '</select>';
441: $res .= '<label>'.$out_mod->trans('SMTP Server').' *</label></div>';
442:
443: // Signature
444: $res .= '<div class="form-floating mb-3 form-check-create-profile">';
445: $res .= '<textarea cols="80" rows="4" name="profile_sig" class="form-control" style="min-height : 120px" placeholder="'.$out_mod->trans('Signature').'">'.$out_mod->html_safe($form_vals['sig']).'</textarea>';
446: $res .= '<label>'.$out_mod->trans('Signature').'</label></div>';
447:
448: // Remark
449: $res .= '<div class="form-floating mb-3 form-check-create-profile">';
450: $res .= '<textarea cols="80" rows="4" name="profile_rmk" class="form-control" style="min-height : 120px" placeholder="'.$out_mod->trans('Remark').'">'.$out_mod->html_safe($form_vals['rmk']).'</textarea>';
451: $res .= '<label>'.$out_mod->trans('Remark').'</label></div>';
452:
453: // Set as default
454: $res .= '<div class="form-check mb-3">';
455: $res .= '<input type="checkbox" class="form-check-input" '.($form_vals['default'] ? 'checked="checked"' : '').' name="profile_default" id="profile_default">';
456: $res .= '<label for="profile_default" class="form-check-label">'.$out_mod->trans('Set as default').'</label></div>';
457:
458: // Submit buttons
459: $res .= '<div>';
460: if ($form_vals['name']) {
461: $res .= '<input type="submit" class="btn btn-primary profile_update" value="'.$out_mod->trans('Update').'" /> ';
462: $res .= '<input type="submit" class="btn btn-danger" name="profile_delete" value="'.$out_mod->trans('Delete').'" /> ';
463: $res .= '<a href="?page=profiles" class="btn btn-secondary">'.$out_mod->trans('Cancel').'</a>';
464: }
465: else {
466: $res .= '<input type="submit" class="btn btn-primary submit_profile" value="'.$out_mod->trans('Create').'" />';
467: }
468: $res .= '</div></form></div>';
469:
470: return $res;
471:
472: }}
473: