diff --git a/CHANGELOG b/CHANGELOG index 4faf7cbaf..04779351d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG RoundCube Webmail =========================== +- Fix LDAP contact update when RDN field is changed (#1485788) - Fix LDAP attributes case senitivity problems (#1485830) - Fix LDAP addressbook browsing when only one directory is used (#1486022) - Fix endless loop on error response for APPEND command (#1486060) diff --git a/program/include/rcube_ldap.php b/program/include/rcube_ldap.php index 37edca7aa..b13e88395 100644 --- a/program/include/rcube_ldap.php +++ b/program/include/rcube_ldap.php @@ -480,32 +480,43 @@ class rcube_ldap extends rcube_addressbook } // end if } // end foreach - // Update the entry as required. $dn = base64_decode($id); + + // Update the entry as required. if (!empty($deletedata)) { // Delete the fields. - $res = ldap_mod_del($this->conn, $dn, $deletedata); - if ($res === FALSE) { + if (!ldap_mod_del($this->conn, $dn, $deletedata)) return false; - } // end if } // end if if (!empty($replacedata)) { + // Handle RDN change + if ($replacedata[$this->prop['LDAP_rdn']]) { + $newdn = $this->prop['LDAP_rdn'].'='.$replacedata[$this->prop['LDAP_rdn']].','.$this->prop['base_dn']; + if ($dn != $newdn) { + $newrdn = $this->prop['LDAP_rdn'].'='.$replacedata[$this->prop['LDAP_rdn']]; + unset($replacedata[$this->prop['LDAP_rdn']]); + } + } // Replace the fields. - $res = ldap_mod_replace($this->conn, $dn, $replacedata); - if ($res === FALSE) { - return false; + if (!empty($replacedata)) { + if (!ldap_mod_replace($this->conn, $dn, $replacedata)) + return false; } // end if } // end if if (!empty($newdata)) { // Add the fields. - $res = ldap_mod_add($this->conn, $dn, $newdata); - if ($res === FALSE) { + if (!ldap_mod_add($this->conn, $dn, $newdata)) return false; - } // end if } // end if + // Handle RDN change + if (!empty($newrdn)) { + if (@ldap_rename($this->conn, $dn, $newrdn, NULL, TRUE)) + return base64_encode($newdn); + } + return true; } diff --git a/program/js/app.js b/program/js/app.js index 6adc7f4e6..2d0be0f31 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -2926,7 +2926,7 @@ function rcube_webmail() }; // update a contact record in the list - this.update_contact_row = function(cid, cols_arr) + this.update_contact_row = function(cid, cols_arr, newcid) { var row; if (this.contact_list.rows[cid] && (row = this.contact_list.rows[cid].obj)) { @@ -2934,12 +2934,51 @@ function rcube_webmail() if (row.cells[c]) $(row.cells[c]).html(cols_arr[c]); + // cid change + if (newcid) { + row.id = 'rcmrow' + newcid; + this.contact_list.remove_row(cid); + this.contact_list.init_row(row); + this.contact_list.selection[0] = newcid; + row.style.display = ''; + } + return true; } return false; }; + // add row to contacts list + this.add_contact_row = function(cid, cols, select) + { + if (!this.gui_objects.contactslist || !this.gui_objects.contactslist.tBodies[0]) + return false; + + var tbody = this.gui_objects.contactslist.tBodies[0]; + var rowcount = tbody.rows.length; + var even = rowcount%2; + + var row = document.createElement('tr'); + row.id = 'rcmrow'+cid; + row.className = 'contact '+(even ? 'even' : 'odd'); + + if (this.contact_list.in_selection(cid)) + row.className += ' selected'; + + // add each submitted col + for (var c in cols) { + col = document.createElement('td'); + col.className = String(c).toLowerCase(); + col.innerHTML = cols[c]; + row.appendChild(col); + } + + this.contact_list.insert_row(row); + + this.enable_command('export', (this.contact_list.rowcount > 0)); + }; + /*********************************************************/ /********* user settings methods *********/ @@ -2993,7 +3032,7 @@ function rcube_webmail() this.load_identity(id, 'edit-identity'); }; - // load contact record + // load identity record this.load_identity = function(id, action) { if (action=='edit-identity' && (!id || id==this.env.iid)) @@ -3884,36 +3923,6 @@ function rcube_webmail() window.focus(); } - // add row to contacts list - this.add_contact_row = function(cid, cols, select) - { - if (!this.gui_objects.contactslist || !this.gui_objects.contactslist.tBodies[0]) - return false; - - var tbody = this.gui_objects.contactslist.tBodies[0]; - var rowcount = tbody.rows.length; - var even = rowcount%2; - - var row = document.createElement('tr'); - row.id = 'rcmrow'+cid; - row.className = 'contact '+(even ? 'even' : 'odd'); - - if (this.contact_list.in_selection(cid)) - row.className += ' selected'; - - // add each submitted col - for (var c in cols) { - col = document.createElement('td'); - col.className = String(c).toLowerCase(); - col.innerHTML = cols[c]; - row.appendChild(col); - } - - this.contact_list.insert_row(row); - - this.enable_command('export', (this.contact_list.rowcount > 0)); - }; - this.toggle_prefer_html = function(checkbox) { var addrbook_show_images; diff --git a/program/steps/addressbook/save.inc b/program/steps/addressbook/save.inc index 639e0f2d1..b28294eea 100644 --- a/program/steps/addressbook/save.inc +++ b/program/steps/addressbook/save.inc @@ -57,17 +57,24 @@ if (!empty($cid)) $plugin = $RCMAIL->plugins->exec_hook('save_contact', array('id' => $cid, 'record' => $a_record, 'source' => get_input_value('_source', RCUBE_INPUT_GPC))); $a_record = $plugin['record']; - if (!$plugin['abort'] && $CONTACTS->update($cid, $a_record)) + if (!$plugin['abort'] && ($result = $CONTACTS->update($cid, $a_record))) { + // LDAP DN change + if (is_string($result) && strlen($result)>1) { + $newcid = $result; + // change cid in POST for 'show' action + $_POST['_cid'] = $newcid; + } + // define list of cols to be displayed $a_js_cols = array(); - $record = $CONTACTS->get_record($cid, true); + $record = $CONTACTS->get_record($newcid ? $newcid : $cid, true); foreach (array('name', 'email') as $col) $a_js_cols[] = (string)$record[$col]; // update the changed col in list - $OUTPUT->command('parent.update_contact_row', $cid, $a_js_cols); + $OUTPUT->command('parent.update_contact_row', $cid, $a_js_cols, $newcid); // show confirmation $OUTPUT->show_message('successfullysaved', 'confirmation', null, false);