You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

save.inc 9.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. <?php
  2. /**
  3. +-----------------------------------------------------------------------+
  4. | program/steps/addressbook/save.inc |
  5. | |
  6. | This file is part of the Roundcube Webmail client |
  7. | Copyright (C) 2005-2013, The Roundcube Dev Team |
  8. | |
  9. | Licensed under the GNU General Public License version 3 or |
  10. | any later version with exceptions for skins & plugins. |
  11. | See the README file for a full license statement. |
  12. | |
  13. | PURPOSE: |
  14. | Save a contact entry or to add a new one |
  15. | |
  16. +-----------------------------------------------------------------------+
  17. | Author: Thomas Bruederli <roundcube@gmail.com> |
  18. +-----------------------------------------------------------------------+
  19. */
  20. $CONTACTS = rcmail_contact_source(null, true, true);
  21. $cid = rcube_utils::get_input_value('_cid', rcube_utils::INPUT_POST);
  22. $return_action = empty($cid) ? 'add' : 'edit';
  23. // Source changed, display the form again
  24. if (!empty($_GET['_reload'])) {
  25. $RCMAIL->overwrite_action($return_action);
  26. return;
  27. }
  28. // cannot edit record
  29. if ($CONTACTS->readonly) {
  30. $OUTPUT->show_message('contactreadonly', 'error');
  31. $RCMAIL->overwrite_action($return_action);
  32. return;
  33. }
  34. // read POST values into hash array
  35. $a_record = array();
  36. foreach ($GLOBALS['CONTACT_COLTYPES'] as $col => $colprop) {
  37. if ($colprop['composite']) {
  38. continue;
  39. }
  40. $fname = '_'.$col;
  41. // gather form data of composite fields
  42. if ($colprop['childs']) {
  43. $values = array();
  44. foreach ($colprop['childs'] as $childcol => $cp) {
  45. $vals = rcube_utils::get_input_value('_'.$childcol, rcube_utils::INPUT_POST, true);
  46. foreach ((array)$vals as $i => $val) {
  47. $values[$i][$childcol] = $val;
  48. }
  49. }
  50. $subtypes = isset($_REQUEST['_subtype_' . $col]) ? (array)rcube_utils::get_input_value('_subtype_' . $col, rcube_utils::INPUT_POST) : array('');
  51. foreach ($subtypes as $i => $subtype) {
  52. $suffix = $subtype ? ':'.$subtype : '';
  53. if ($values[$i]) {
  54. $a_record[$col.$suffix][] = $values[$i];
  55. }
  56. }
  57. }
  58. // assign values and subtypes
  59. else if (is_array($_POST[$fname])) {
  60. $values = rcube_utils::get_input_value($fname, rcube_utils::INPUT_POST, true);
  61. $subtypes = rcube_utils::get_input_value('_subtype_' . $col, rcube_utils::INPUT_POST);
  62. foreach ($values as $i => $val) {
  63. if ($col == 'email') {
  64. // extract email from full address specification, e.g. "Name" <addr@domain.tld>
  65. $addr = rcube_mime::decode_address_list($val, 1, false);
  66. if (!empty($addr) && ($addr = array_pop($addr)) && $addr['mailto']) {
  67. $val = $addr['mailto'];
  68. }
  69. }
  70. $subtype = $subtypes[$i] ? ':'.$subtypes[$i] : '';
  71. $a_record[$col.$subtype][] = $val;
  72. }
  73. }
  74. else if (isset($_POST[$fname])) {
  75. $a_record[$col] = rcube_utils::get_input_value($fname, rcube_utils::INPUT_POST, true);
  76. // normalize the submitted date strings
  77. if ($colprop['type'] == 'date') {
  78. if ($a_record[$col] && ($dt = rcube_utils::anytodatetime($a_record[$col]))) {
  79. $a_record[$col] = $dt->format('Y-m-d');
  80. }
  81. else {
  82. unset($a_record[$col]);
  83. }
  84. }
  85. }
  86. }
  87. // Generate contact's display name (must be before validation)
  88. if (empty($a_record['name'])) {
  89. $a_record['name'] = rcube_addressbook::compose_display_name($a_record, true);
  90. // Reset it if equals to email address (from compose_display_name())
  91. $email = rcube_addressbook::get_col_values('email', $a_record, true);
  92. if ($a_record['name'] == $email[0]) {
  93. $a_record['name'] = '';
  94. }
  95. }
  96. // do input checks (delegated to $CONTACTS instance)
  97. if (!$CONTACTS->validate($a_record)) {
  98. $err = (array)$CONTACTS->get_error();
  99. $OUTPUT->show_message($err['message'] ? rcube::Q($err['message']) : 'formincomplete', 'warning');
  100. $GLOBALS['EDIT_RECORD'] = $a_record; // store submitted data to be used in edit form
  101. $RCMAIL->overwrite_action($return_action);
  102. return;
  103. }
  104. // get raw photo data if changed
  105. if (isset($a_record['photo'])) {
  106. if ($a_record['photo'] == '-del-') {
  107. $a_record['photo'] = '';
  108. }
  109. else if ($tempfile = $_SESSION['contacts']['files'][$a_record['photo']]) {
  110. $tempfile = $RCMAIL->plugins->exec_hook('attachment_get', $tempfile);
  111. if ($tempfile['status'])
  112. $a_record['photo'] = $tempfile['data'] ?: @file_get_contents($tempfile['path']);
  113. }
  114. else
  115. unset($a_record['photo']);
  116. // cleanup session data
  117. $RCMAIL->plugins->exec_hook('attachments_cleanup', array('group' => 'contact'));
  118. $RCMAIL->session->remove('contacts');
  119. }
  120. $source = rcube_utils::get_input_value('_source', rcube_utils::INPUT_GPC);
  121. // update an existing contact
  122. if (!empty($cid)) {
  123. $plugin = $RCMAIL->plugins->exec_hook('contact_update',
  124. array('id' => $cid, 'record' => $a_record, 'source' => $source));
  125. $a_record = $plugin['record'];
  126. if (!$plugin['abort'])
  127. $result = $CONTACTS->update($cid, $a_record);
  128. else
  129. $result = $plugin['result'];
  130. if ($result) {
  131. // show confirmation
  132. $OUTPUT->show_message('successfullysaved', 'confirmation', null, false);
  133. // in search mode, just reload the list (#1490015)
  134. if ($_REQUEST['_search']) {
  135. $OUTPUT->command('parent.command', 'list');
  136. $OUTPUT->send('iframe');
  137. }
  138. // LDAP DN change
  139. if (is_string($result) && strlen($result)>1) {
  140. $newcid = $result;
  141. // change cid in POST for 'show' action
  142. $_POST['_cid'] = $newcid;
  143. }
  144. // refresh contact data for list update and 'show' action
  145. $CONTACT_RECORD = $CONTACTS->get_record($newcid ?: $cid, true);
  146. // Update contacts list
  147. $a_js_cols = array();
  148. $record = $CONTACT_RECORD;
  149. $record['email'] = reset($CONTACTS->get_col_values('email', $record, true));
  150. $record['name'] = rcube_addressbook::compose_list_name($record);
  151. foreach (array('name') as $col) {
  152. $a_js_cols[] = rcube::Q((string)$record[$col]);
  153. }
  154. // performance: unset some big data items we don't need here
  155. $record = array_intersect_key($record, array('ID' => 1,'email' => 1,'name' => 1));
  156. $record['_type'] = 'person';
  157. // update the changed col in list
  158. $OUTPUT->command('parent.update_contact_row', $cid, $a_js_cols, $newcid, $source, $record);
  159. $RCMAIL->overwrite_action('show');
  160. }
  161. else {
  162. // show error message
  163. $err = $CONTACTS->get_error();
  164. $OUTPUT->show_message($plugin['message'] ?: ($err['message'] ?: 'errorsaving'), 'error', null, false);
  165. $RCMAIL->overwrite_action('show');
  166. }
  167. }
  168. // insert a new contact
  169. else {
  170. // Name of the addressbook already selected on the list
  171. $orig_source = rcube_utils::get_input_value('_orig_source', rcube_utils::INPUT_GPC);
  172. if (!strlen($source)) {
  173. $source = $orig_source;
  174. }
  175. // show notice if existing contacts with same e-mail are found
  176. foreach ($CONTACTS->get_col_values('email', $a_record, true) as $email) {
  177. if ($email && ($res = $CONTACTS->search('email', $email, 1, false, true)) && $res->count) {
  178. $OUTPUT->show_message('contactexists', 'notice', null, false);
  179. break;
  180. }
  181. }
  182. $plugin = $RCMAIL->plugins->exec_hook('contact_create', array(
  183. 'record' => $a_record, 'source' => $source));
  184. $a_record = $plugin['record'];
  185. // insert record and send response
  186. if (!$plugin['abort'])
  187. $insert_id = $CONTACTS->insert($a_record);
  188. else
  189. $insert_id = $plugin['result'];
  190. if ($insert_id) {
  191. $CONTACTS->reset();
  192. // add new contact to the specified group
  193. if ($CONTACTS->groups && $CONTACTS->group_id) {
  194. $plugin = $RCMAIL->plugins->exec_hook('group_addmembers', array(
  195. 'group_id' => $CONTACTS->group_id, 'ids' => $insert_id, 'source' => $source));
  196. if (!$plugin['abort']) {
  197. if (($maxnum = $RCMAIL->config->get('max_group_members', 0)) && ($CONTACTS->count()->count + 1 > $maxnum)) {
  198. // @FIXME: should we remove the contact?
  199. $msgtext = $RCMAIL->gettext(array('name' => 'maxgroupmembersreached', 'vars' => array('max' => $maxnum)));
  200. $OUTPUT->command('parent.display_message', $msgtext, 'warning');
  201. }
  202. else {
  203. $CONTACTS->add_to_group($plugin['group_id'], $plugin['ids']);
  204. }
  205. }
  206. }
  207. // show confirmation
  208. $OUTPUT->show_message('successfullysaved', 'confirmation', null, false);
  209. $OUTPUT->command('parent.set_rowcount', $RCMAIL->gettext('loading'));
  210. $OUTPUT->command('parent.list_contacts');
  211. $OUTPUT->send('iframe');
  212. }
  213. else {
  214. // show error message
  215. $err = $CONTACTS->get_error();
  216. $OUTPUT->show_message($plugin['message'] ?: ($err['message'] ?: 'errorsaving'), 'error', null, false);
  217. $RCMAIL->overwrite_action('add');
  218. }
  219. }