Skip to content

Commit 835a8ed

Browse files
committed
fix(backend): fix issues related to "Send To" resulting empty To field on compose page
1 parent 9e15141 commit 835a8ed

File tree

7 files changed

+250
-105
lines changed

7 files changed

+250
-105
lines changed

modules/contacts/js_modules/route_handlers.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
function applyContactsPageHandlers() {
2-
$('.delete_contact').on("click", function() {
3-
let ldap_dn = $(this).data('ldap-dn') || '';
4-
delete_contact($(this).data('id'), $(this).data('source'), $(this).data('type'), ldap_dn);
2+
$('.delete_contact:not([data-ldap-dn])').on("click", function() {
3+
delete_contact($(this).data('id'), $(this).data('source'), $(this).data('type'));
54
return false;
65
});
76
$('.show_contact').on("click", function() {

modules/contacts/modules.php

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ public function process() {
123123
if (array_key_exists('contact_id', $this->request->get)) {
124124
$contacts = $this->get('contact_store');
125125
$contact = $contacts->get($this->request->get['contact_id']);
126+
126127
if ($contact) {
127128
$to = sprintf('%s <%s>', $contact->value('display_name'), $contact->value('email_address'));
128129
$this->out('compose_draft', array('draft_to' => $to, 'draft_subject' => '', 'draft_body' => ''));
@@ -397,29 +398,32 @@ protected function output() {
397398
'<td class="text-end" style="width : 100px">';
398399
if (in_array($c->value('type').':'.$c->value('source'), $editable, true)) {
399400
$delete_attrs = 'data-id="'.$this->html_safe($c->value('id')).'" data-type="'.$this->html_safe($c->value('type')).'" data-source="'.$this->html_safe($c->value('source')).'"';
400-
if ($c->value('type') == 'ldap' && $c->value('all_fields')) {
401-
$all_fields = $c->value('all_fields');
402-
if (isset($all_fields['dn'])) {
403-
$delete_attrs .= ' data-ldap-dn="'.$this->html_safe($all_fields['dn']).'"';
404-
}
401+
402+
if (class_exists('Hm_LDAP_Contact')) {
403+
$delete_attrs .= Hm_LDAP_Contact::generateDeleteAttributes($c, [$this, 'html_safe']);
405404
}
405+
406406
$edit_url = '?page=contacts&amp;contact_id='.$this->html_safe($c->value('id')).'&amp;contact_source='.
407407
$this->html_safe($c->value('source')).'&amp;contact_type='.
408408
$this->html_safe($c->value('type')).'&amp;contact_page='.$current_page;
409409

410-
// Add DN parameter for LDAP contacts lookup
411-
if ($c->value('type') == 'ldap' && $c->value('all_fields')) {
412-
$all_fields = $c->value('all_fields');
413-
if (isset($all_fields['dn'])) {
414-
$edit_url .= '&amp;dn='.urlencode($all_fields['dn']);
415-
}
410+
if (class_exists('Hm_LDAP_Contact')) {
411+
$edit_url = Hm_LDAP_Contact::addDNToUrl($c, $edit_url);
416412
}
417413

418414
$res .= '<a '.$delete_attrs.' class="delete_contact cursor-pointer" title="'.$this->trans('Delete').'"><i class="bi bi-trash3 text-danger ms-2"></i></a>'.
419415
'<a href="'.$edit_url.'" class="edit_contact cursor-pointer" title="'.$this->trans('Edit').'"><i class="bi bi-pencil-square ms-2"></i></a>';
420416
}
421-
$res .= '<a href="?page=compose&amp;contact_id='.$this->html_safe($c->value('id')).
422-
'" class="send_to_contact cursor-pointer" title="'.$this->trans('Send To').'">'.
417+
418+
$send_to_url = '?page=compose&amp;contact_id='.$this->html_safe($c->value('id')).
419+
'&amp;contact_source='.$this->html_safe($c->value('source')).
420+
'&amp;contact_type='.$this->html_safe($c->value('type'));
421+
422+
if (class_exists('Hm_LDAP_Contact')) {
423+
$send_to_url = Hm_LDAP_Contact::addDNToUrl($c, $send_to_url);
424+
}
425+
426+
$res .= '<a href="'.$send_to_url.'" class="send_to_contact cursor-pointer" title="'.$this->trans('Send To').'">'.
423427
'<i class="bi bi-envelope-arrow-up ms-2"></i></a>';
424428

425429
$res .= '</td></tr>';
@@ -622,6 +626,7 @@ function build_contact_detail($output_mod, $contact, $id) {
622626
$all_fields = false;
623627
$contacts = $contact->export();
624628
ksort($contacts);
629+
625630
foreach ($contacts as $name => $val) {
626631
if ($name == 'all_fields') {
627632
$all_fields = $val;
@@ -639,7 +644,7 @@ function build_contact_detail($output_mod, $contact, $id) {
639644
if ($all_fields) {
640645
ksort($all_fields);
641646
foreach ($all_fields as $name => $val) {
642-
if (in_array($name, array(0, 'raw', 'objectclass', 'dn', 'ID', 'APP:EDITED', 'UPDATED'), true)) {
647+
if (in_array($name, array(0, 'raw', 'objectclass', 'ID', 'APP:EDITED', 'UPDATED'), true)) {
643648
continue;
644649
}
645650
$res .= '<tr><th>'.$output_mod->trans(name_map($name)).'</th>';
@@ -696,7 +701,8 @@ function name_map($val) {
696701
'fn' => 'Full Name',
697702
'uid' => 'Uid',
698703
'src_url' => 'URL',
699-
'adr' => 'Address'
704+
'adr' => 'Address',
705+
'dn' => 'Distinguished Name'
700706
);
701707
if (array_key_exists($val, $names)) {
702708
return $names[$val];

modules/contacts/site.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
var delete_contact = function(id, source, type, ldap_dn) {
3+
var delete_contact = function(id, source, type) {
44
if (!hm_delete_prompt()) {
55
return false;
66
}
@@ -11,10 +11,6 @@ var delete_contact = function(id, source, type, ldap_dn) {
1111
{'name': 'contact_source', 'value': source}
1212
];
1313

14-
if (ldap_dn) {
15-
request_data.push({'name': 'ldap_dn', 'value': ldap_dn});
16-
}
17-
1814
Hm_Ajax.request(
1915
request_data,
2016
function(res) {

modules/ldap_contacts/hm-ldap-contacts.php

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,83 @@ public function fetch() {
104104
return array();
105105
}
106106
}
107+
108+
/**
109+
* @subpackage ldap_contacts/lib
110+
*/
111+
class Hm_LDAP_Contact extends Hm_Contact {
112+
113+
public function getDN() {
114+
$all_fields = $this->value('all_fields');
115+
if ($all_fields && isset($all_fields['dn'])) {
116+
return $all_fields['dn'];
117+
}
118+
return null;
119+
}
120+
121+
public static function findByDN($contact_store, $target_dn, $contact_source) {
122+
$all_contacts = $contact_store->dump();
123+
124+
foreach ($all_contacts as $contact_id => $contact_obj) {
125+
if ($contact_obj->value('source') == $contact_source &&
126+
$contact_obj->value('type') == 'ldap') {
127+
128+
$all_fields = $contact_obj->value('all_fields');
129+
130+
if (isset($all_fields['dn']) && $all_fields['dn'] === $target_dn) {
131+
return $contact_obj;
132+
}
133+
}
134+
}
135+
return null;
136+
}
137+
138+
public static function isLdapContact($contact) {
139+
return $contact instanceof self || $contact->value('type') === 'ldap';
140+
}
141+
142+
public static function decodeDN($encoded_dn) {
143+
return urldecode($encoded_dn);
144+
}
145+
146+
public static function generateDeleteAttributes($contact, $html_safe) {
147+
if (!self::isLdapContact($contact)) {
148+
return '';
149+
}
150+
151+
$all_fields = $contact->value('all_fields');
152+
if ($all_fields && isset($all_fields['dn'])) {
153+
return ' data-ldap-dn="'.$html_safe($all_fields['dn']).'"';
154+
}
155+
156+
return '';
157+
}
158+
159+
public static function addDNToUrl($contact, $base_url) {
160+
if (!self::isLdapContact($contact)) {
161+
return $base_url;
162+
}
163+
164+
$all_fields = $contact->value('all_fields');
165+
if ($all_fields && isset($all_fields['dn'])) {
166+
return $base_url . '&amp;dn='.urlencode($all_fields['dn']);
167+
}
168+
169+
return $base_url;
170+
}
171+
172+
public static function fromContact($contact) {
173+
if ($contact->value('type') !== 'ldap') {
174+
return null;
175+
}
176+
177+
if ($contact instanceof self) {
178+
return $contact;
179+
}
180+
181+
$contact_data = $contact->export();
182+
$ldap_contact = new self($contact_data);
183+
184+
return $ldap_contact;
185+
}
186+
}

modules/ldap_contacts/modules.php

Lines changed: 63 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -69,64 +69,35 @@ public function process() {
6969
list($success, $form) = $this->process_form(array('contact_type', 'contact_source', 'contact_id'));
7070
if ($success && $form['contact_type'] == 'ldap' && in_array($form['contact_source'], $sources, true)) {
7171
$config = $ldap_config[$form['contact_source']];
72-
$contact = $contacts->get($form['contact_id']);
73-
if (!$contact) {
74-
$all_contacts = $contacts->dump();
75-
$found_contact = null;
76-
$target_dn = null;
77-
78-
if (isset($this->request->post['ldap_dn']) && !empty($this->request->post['ldap_dn'])) {
79-
$target_dn = $this->request->post['ldap_dn'];
80-
}
81-
82-
if (!$target_dn && isset($this->request->get['dn'])) {
83-
$target_dn = $this->request->get['dn'];
84-
}
85-
86-
foreach ($all_contacts as $contact_id => $contact_obj) {
87-
if ($contact_obj->value('source') == $form['contact_source'] &&
88-
$contact_obj->value('type') == 'ldap') {
89-
90-
$all_fields = $contact_obj->value('all_fields');
91-
92-
if ($target_dn && isset($all_fields['dn']) && $all_fields['dn'] === $target_dn) {
93-
$found_contact = $contact_obj;
94-
break;
95-
}
96-
}
97-
}
98-
99-
if (!$found_contact) {
100-
$ldap_contacts = array();
101-
foreach ($all_contacts as $contact_id => $contact_obj) {
102-
if ($contact_obj->value('source') == $form['contact_source'] &&
103-
$contact_obj->value('type') == 'ldap') {
104-
$ldap_contacts[] = array('id' => $contact_id, 'obj' => $contact_obj);
105-
}
106-
}
107-
108-
if (count($ldap_contacts) == 1) {
109-
$found_contact = $ldap_contacts[0]['obj'];
110-
}
111-
}
112-
113-
if (!$found_contact) {
114-
Hm_Msgs::add('Unable to find contact to delete', 'danger');
115-
return;
116-
}
117-
$contact = $found_contact;
72+
73+
// For LDAP contacts, skip contact ID lookup and use DN-based lookup directly
74+
$contacts = $this->get('contact_store');
75+
$dn = null;
76+
$contact = null;
77+
78+
// Get DN from request data
79+
$target_dn = null;
80+
if (isset($this->request->post['ldap_dn']) && !empty($this->request->post['ldap_dn'])) {
81+
$target_dn = $this->request->post['ldap_dn'];
82+
} elseif (isset($this->request->get['dn'])) {
83+
$target_dn = Hm_LDAP_Contact::decodeDN($this->request->get['dn']);
84+
} elseif (isset($this->request->post['dn'])) {
85+
$target_dn = Hm_LDAP_Contact::decodeDN($this->request->post['dn']);
86+
}
87+
88+
if ($target_dn) {
89+
$contact = Hm_LDAP_Contact::findByDN($contacts, $target_dn, $form['contact_source']);
90+
$dn = $target_dn;
91+
}
92+
93+
if (!$contact || !$dn) {
94+
Hm_Msgs::add('Unable to find contact to delete', 'danger');
95+
return;
11896
}
11997

12098
$ldap = new Hm_LDAP_Contacts($config);
12199
if ($ldap->connect()) {
122-
$flds = $contact->value('all_fields');
123-
124-
if (!$flds || !isset($flds['dn']) || empty($flds['dn'])) {
125-
Hm_Msgs::add('Contact DN not found, cannot delete', 'danger');
126-
return;
127-
}
128-
129-
if ($ldap->delete($flds['dn'])) {
100+
if ($ldap->delete($dn)) {
130101
Hm_Msgs::add('Contact Deleted');
131102
$this->out('contact_deleted', 1);
132103
}
@@ -383,40 +354,22 @@ public function process() {
383354
array_key_exists('contact_id', $this->request->get)) {
384355

385356
$contacts = $this->get('contact_store');
386-
$contact = $contacts->get($this->request->get['contact_id']);
387-
388357
$contact_id = $this->request->get['contact_id'];
389358
$contact_source = $this->request->get['contact_source'];
390-
$target_dn = isset($this->request->get['dn']) ? urldecode($this->request->get['dn']) : null;
391-
392-
if (!$contact) {
393-
$all_contacts = $contacts->dump();
394-
$found_contact = null;
359+
360+
$target_dn = isset($this->request->get['dn']) ? Hm_LDAP_Contact::decodeDN($this->request->get['dn']) : null;
361+
362+
if ($target_dn) {
363+
$contact = Hm_LDAP_Contact::findByDN($contacts, $target_dn, $contact_source);
395364

396-
if ($target_dn) {
397-
foreach ($all_contacts as $contact_id_key => $contact_obj) {
398-
if ($contact_obj->value('source') == $contact_source &&
399-
$contact_obj->value('type') == 'ldap') {
400-
401-
$all_fields = $contact_obj->value('all_fields');
402-
403-
if (isset($all_fields['dn']) && $all_fields['dn'] === $target_dn) {
404-
$found_contact = $contact_obj;
405-
break;
406-
}
407-
}
408-
}
365+
if ($contact) {
366+
$current = $contact->export();
367+
$current['id'] = $contact_id;
368+
$this->out('current_ldap_contact', $current);
369+
$this->handler_response['ldap_edit'] = true;
409370
}
410-
411-
$contact = $found_contact;
412371
}
413372

414-
if (is_object($contact)) {
415-
$current = $contact->export();
416-
$current['id'] = $contact_id;
417-
$this->out('current_ldap_contact', $current);
418-
$this->handler_response['ldap_edit'] = true;
419-
}
420373
} else {
421374
$missing = array();
422375
if (!array_key_exists('contact_source', $this->request->get)) $missing[] = 'contact_source';
@@ -482,6 +435,34 @@ public function process() {
482435
}
483436
}
484437

438+
/**
439+
* @subpackage ldap_contacts/handler
440+
*/
441+
class Hm_Handler_ldap_send_to_contact extends Hm_Handler_Module {
442+
public function process() {
443+
if (!$this->get('compose_draft') &&
444+
array_key_exists('contact_id', $this->request->get) &&
445+
array_key_exists('contact_type', $this->request->get) &&
446+
array_key_exists('contact_source', $this->request->get) &&
447+
array_key_exists('dn', $this->request->get) &&
448+
$this->request->get['contact_type'] == 'ldap') {
449+
450+
$contacts = $this->get('contact_store');
451+
$contact_id = $this->request->get['contact_id'];
452+
$contact_source = $this->request->get['contact_source'];
453+
454+
// For LDAP contacts, use DN-based lookup directly (contact_id is unreliable for LDAP)
455+
$target_dn = Hm_LDAP_Contact::decodeDN($this->request->get['dn']);
456+
$contact = Hm_LDAP_Contact::findByDN($contacts, $target_dn, $contact_source);
457+
458+
if ($contact) {
459+
$to = sprintf('%s <%s>', $contact->value('display_name'), $contact->value('email_address'));
460+
$this->out('compose_draft', array('draft_to' => $to, 'draft_subject' => '', 'draft_body' => ''));
461+
}
462+
}
463+
}
464+
}
465+
485466
/**
486467
* @subpackage ldap_contacts/output
487468
*/

modules/ldap_contacts/setup.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
add_handler('ajax_delete_contact', 'process_delete_ldap_contact', true, 'ldap_contacts', 'load_ldap_contacts', 'after');
4848
add_handler('ajax_add_contact', 'load_ldap_contacts', true, 'ldap_contacts', 'load_contacts', 'after');
4949
add_handler('ajax_add_contact', 'process_add_ldap_contact_from_message', true, 'ldap_contacts', 'save_user_data', 'before');
50+
add_handler('compose', 'ldap_send_to_contact', true, 'ldap_contacts', 'process_send_to_contact', 'after');
5051

5152
add_handler('settings', 'load_ldap_settings', true, 'ldap_contacts', 'load_user_data', 'after');
5253
add_handler('settings', 'process_ldap_auth_settings', true, 'ldap_contacts', 'save_user_settings', 'before');

0 commit comments

Comments
 (0)