diff options
Diffstat (limited to 'program')
-rw-r--r-- | program/include/rcube_addressbook.php | 5 | ||||
-rw-r--r-- | program/include/rcube_ldap.php | 59 | ||||
-rw-r--r-- | program/include/rcube_vcard.php | 24 | ||||
-rw-r--r-- | program/js/app.js | 26 | ||||
-rw-r--r-- | program/localization/en_US/labels.inc | 3 | ||||
-rw-r--r-- | program/steps/mail/func.inc | 88 | ||||
-rw-r--r-- | program/steps/settings/folders.inc | 60 |
7 files changed, 183 insertions, 82 deletions
diff --git a/program/include/rcube_addressbook.php b/program/include/rcube_addressbook.php index f4f255322..892ae263a 100644 --- a/program/include/rcube_addressbook.php +++ b/program/include/rcube_addressbook.php @@ -434,6 +434,11 @@ abstract class rcube_addressbook } } + // remove duplicates + if ($flat && !empty($out)) { + $out = array_unique($out); + } + return $out; } diff --git a/program/include/rcube_ldap.php b/program/include/rcube_ldap.php index ad2ccddeb..b9b6490fa 100644 --- a/program/include/rcube_ldap.php +++ b/program/include/rcube_ldap.php @@ -109,24 +109,22 @@ class rcube_ldap extends rcube_addressbook if (!is_array($this->coltypes[$col])) { $subtypes = $type ? array($type) : null; - $this->coltypes[$col] = array('limit' => $limit, 'subtypes' => $subtypes); + $this->coltypes[$col] = array('limit' => $limit, 'subtypes' => $subtypes, 'attributes' => array($lf)); } elseif ($type) { $this->coltypes[$col]['subtypes'][] = $type; + $this->coltypes[$col]['attributes'][] = $lf; $this->coltypes[$col]['limit'] += $limit; } if ($delim) $this->coltypes[$col]['serialized'][$type] = $delim; - if ($type && !$this->fieldmap[$col]) - $this->fieldmap[$col] = $lf; - - $this->fieldmap[$colv] = $lf; + $this->fieldmap[$colv] = $lf; } // support for composite address - if ($this->fieldmap['street'] && $this->fieldmap['locality']) { + if ($this->coltypes['street'] && $this->coltypes['locality']) { $this->coltypes['address'] = array( 'limit' => max(1, $this->coltypes['locality']['limit'] + $this->coltypes['address']['limit']), 'subtypes' => array_merge((array)$this->coltypes['address']['subtypes'], (array)$this->coltypes['locality']['subtypes']), @@ -134,7 +132,7 @@ class rcube_ldap extends rcube_addressbook ) + (array)$this->coltypes['address']; foreach (array('street','locality','zipcode','region','country') as $childcol) { - if ($this->fieldmap[$childcol]) { + if ($this->coltypes[$childcol]) { $this->coltypes['address']['childs'][$childcol] = array('type' => 'text'); unset($this->coltypes[$childcol]); // remove address child col from global coltypes list } @@ -468,8 +466,8 @@ class rcube_ldap extends rcube_addressbook */ function set_sort_order($sort_col, $sort_order = null) { - if ($this->fieldmap[$sort_col]) - $this->sort_col = $this->fieldmap[$sort_col]; + if ($this->coltypes[$sort_col]['attributes']) + $this->sort_col = $this->coltypes[$sort_col]['attributes'][0]; } @@ -858,8 +856,13 @@ class rcube_ldap extends rcube_addressbook { foreach ((array)$fields as $idx => $field) { $val = is_array($value) ? $value[$idx] : $value; - if ($f = $this->_map_field($field)) { - $filter .= "($f=$wp" . $this->_quote_string($val) . "$ws)"; + if ($attrs = $this->_map_field($field)) { + if (count($attrs) > 1) + $filter .= '(|'; + foreach ($attrs as $f) + $filter .= "($f=$wp" . $this->_quote_string($val) . "$ws)"; + if (count($attrs) > 1) + $filter .= ')'; } } } @@ -867,9 +870,16 @@ class rcube_ldap extends rcube_addressbook // add required (non empty) fields filter $req_filter = ''; - foreach ((array)$required as $field) - if ($f = $this->_map_field($field)) - $req_filter .= "($f=*)"; + foreach ((array)$required as $field) { + if ($attrs = $this->_map_field($field)) { + if (count($attrs) > 1) + $req_filter .= '(|'; + foreach ($attrs as $f) + $req_filter .= "($f=*)"; + if (count($attrs) > 1) + $req_filter .= ')'; + } + } if (!empty($req_filter)) $filter = '(&' . $req_filter . $filter . ')'; @@ -1498,7 +1508,7 @@ class rcube_ldap extends rcube_addressbook list($col, $subtype) = explode(':', $rf); $out['_raw_attrib'][$lf][$i] = $value; - if ($rf == 'email' && $this->mail_domain && !strpos($value, '@')) + if ($col == 'email' && $this->mail_domain && !strpos($value, '@')) $out[$rf][] = sprintf('%s@%s', $value, $this->mail_domain); else if (in_array($col, array('street','zipcode','locality','country','region'))) $out['address'.($subtype?':':'').$subtype][$i][$col] = $value; @@ -1521,11 +1531,11 @@ class rcube_ldap extends rcube_addressbook /** - * Return real field name (from fields map) + * Return LDAP attribute(s) for the given field */ private function _map_field($field) { - return $this->fieldmap[$field]; + return (array)$this->coltypes[$field]['attributes']; } @@ -1558,8 +1568,19 @@ class rcube_ldap extends rcube_addressbook } $ldap_data = array(); - foreach ($this->fieldmap as $col => $fld) { - $val = $save_cols[$col]; + foreach ($this->fieldmap as $rf => $fld) { + $val = $save_cols[$rf]; + + // check for value in base field (eg.g email instead of email:foo) + list($col, $subtype) = explode(':', $rf); + if (!$val && !empty($save_cols[$col])) { + $val = $save_cols[$col]; + unset($save_cols[$col]); // only use this value once + } + else if (!$val && !$subtype) { // extract values from subtype cols + $val = $this->get_col_values($col, $save_cols, true); + } + if (is_array($val)) $val = array_filter($val); // remove empty entries if ($fld && $val) { diff --git a/program/include/rcube_vcard.php b/program/include/rcube_vcard.php index 49b312c5c..00903c257 100644 --- a/program/include/rcube_vcard.php +++ b/program/include/rcube_vcard.php @@ -50,7 +50,7 @@ class rcube_vcard 'spouse' => 'X-SPOUSE', 'edit' => 'X-AB-EDIT', ); - private $typemap = array('iPhone' => 'mobile', 'CELL' => 'mobile', 'WORK,FAX' => 'workfax'); + private $typemap = array('IPHONE' => 'mobile', 'CELL' => 'mobile', 'WORK,FAX' => 'workfax'); private $phonetypemap = array('HOME1' => 'HOME', 'BUSINESS1' => 'WORK', 'BUSINESS2' => 'WORK2', 'BUSINESSFAX' => 'WORK,FAX'); private $addresstypemap = array('BUSINESS' => 'WORK'); private $immap = array('X-JABBER' => 'jabber', 'X-ICQ' => 'icq', 'X-MSN' => 'msn', 'X-AIM' => 'aim', 'X-YAHOO' => 'yahoo', 'X-SKYPE' => 'skype', 'X-SKYPE-USERNAME' => 'skype'); @@ -159,7 +159,18 @@ class rcube_vcard if (!empty($raw['type'])) { $combined = join(',', self::array_filter((array)$raw['type'], 'internet,pref', true)); - $subtype = $typemap[$combined] ? $typemap[$combined] : ($typemap[$raw['type'][++$k]] ? $typemap[$raw['type'][$k]] : strtolower($raw['type'][$k])); + $combined = strtoupper($combined); + + if ($typemap[$combined]) { + $subtype = $typemap[$combined]; + } + else if ($typemap[$raw['type'][++$k]]) { + $subtype = $typemap[$raw['type'][$k]]; + } + else { + $subtype = strtolower($raw['type'][$k]); + } + while ($k < count($raw['type']) && ($subtype == 'internet' || $subtype == 'pref')) $subtype = $typemap[$raw['type'][++$k]] ? $typemap[$raw['type'][$k]] : strtolower($raw['type'][$k]); } @@ -167,8 +178,11 @@ class rcube_vcard // read vcard 2.1 subtype if (!$subtype) { foreach ($raw as $k => $v) { - if (!is_numeric($k) && $v === true && !in_array(strtolower($k), array('pref','internet','voice','base64'))) { - $subtype = $typemap[$k] ? $typemap[$k] : strtolower($k); + if (!is_numeric($k) && $v === true && ($k = strtolower($k)) + && !in_array($k, array('pref','internet','voice','base64')) + ) { + $k_uc = strtoupper($k); + $subtype = $typemap[$k_uc] ? $typemap[$k_uc] : $k; break; } } @@ -335,7 +349,7 @@ class rcube_vcard $index = count($this->raw[$tag]); $this->raw[$tag][$index] = (array)$value; if ($type) - $this->raw[$tag][$index]['type'] = explode(',', ($typemap[$type] ? $typemap[$type] : $type)); + $this->raw[$tag][$index]['type'] = explode(',', ($typemap[$type_uc] ? $typemap[$type_uc] : $type)); } break; } diff --git a/program/js/app.js b/program/js/app.js index 4d784e532..06eb9295c 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -5624,6 +5624,32 @@ function rcube_webmail() this.messages = {}; }; + // open a jquery UI dialog with the given content + this.show_popup_dialog = function(html, title) + { + // forward call to parent window + if (this.is_framed()) { + parent.rcmail.show_popup_dialog(html, title); + return; + } + + var popup = $('<div class="popup">') + .html(html) + .dialog({ + title: title, + modal: true, + resizable: true, + width: 580, + close: function(event, ui) { $(this).remove() } + }); + + // resize and center popup + var win = $(window), w = win.width(), h = win.height(), + width = popup.width(), height = popup.height(); + popup.dialog('option', { height: Math.min(h-40, height+50), width: Math.min(w-20, width+50) }) + .dialog('option', 'position', ['center', 'center']); // only works in a separate call (!?) + }; + // enable/disable buttons for page shifting this.set_page_buttons = function() { diff --git a/program/localization/en_US/labels.inc b/program/localization/en_US/labels.inc index 9882c19b5..fbc154b88 100644 --- a/program/localization/en_US/labels.inc +++ b/program/localization/en_US/labels.inc @@ -236,6 +236,9 @@ $labels['nosubject'] = '(no subject)'; $labels['showimages'] = 'Display images'; $labels['alwaysshow'] = 'Always show images from $sender'; $labels['isdraft'] = 'This is a draft message.'; +$labels['andnmore'] = '$nr more...'; +$labels['togglemoreheaders'] = 'Show more message headers'; +$labels['togglefullheaders'] = 'Toggle raw message headers'; $labels['htmltoggle'] = 'HTML'; $labels['plaintoggle'] = 'Plain text'; diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index 8bf80a6ee..e3866aa57 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -319,7 +319,7 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $a_show_cols=null $col_name = $col == 'fromto' ? $smart_col : $col; if (in_array($col_name, array('from', 'to', 'cc', 'replyto'))) - $cont = Q(rcmail_address_string($header->$col_name, 3, false, null, $header->charset), 'show'); + $cont = rcmail_address_string($header->$col_name, 3, false, null, $header->charset); else if ($col == 'subject') { $cont = trim(rcube_mime::decode_header($header->$col, $header->charset)); if (!$cont) $cont = rcube_label('nosubject'); @@ -957,6 +957,8 @@ function rcmail_message_headers($attrib, $headers=NULL) $output_headers = array(); foreach ($standard_headers as $hkey) { + $ishtml = false; + if ($headers[$hkey]) $value = $headers[$hkey]; else if ($headers['others'][$hkey]) @@ -967,6 +969,8 @@ function rcmail_message_headers($attrib, $headers=NULL) if (in_array($hkey, $exclude_headers)) continue; + $header_title = rcube_label(preg_replace('/(^mail-|-)/', '', $hkey)); + if ($hkey == 'date') { if ($PRINT_MODE) $header_value = format_date($value, $RCMAIL->config->get('date_long', 'x')); @@ -981,32 +985,41 @@ function rcmail_message_headers($attrib, $headers=NULL) continue; } else if ($hkey == 'replyto') { - if ($headers['replyto'] != $headers['from']) - $header_value = rcmail_address_string($value, null, true, $attrib['addicon'], $headers['charset']); + if ($headers['replyto'] != $headers['from']) { + $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title); + $ishtml = true; + } else continue; } else if ($hkey == 'mail-reply-to') { if ($headers['mail-replyto'] != $headers['reply-to'] && $headers['reply-to'] != $headers['from'] - ) - $header_value = rcmail_address_string($value, null, true, $attrib['addicon'], $headers['charset']); + ) { + $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title); + $ishtml = true; + } else continue; } else if ($hkey == 'mail-followup-to') { - $header_value = rcmail_address_string($value, null, true, $attrib['addicon'], $headers['charset']); + $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title); + $ishtml = true; + } + else if (in_array($hkey, array('from', 'to', 'cc', 'bcc'))) { + $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title); + $ishtml = true; } - else if (in_array($hkey, array('from', 'to', 'cc', 'bcc'))) - $header_value = rcmail_address_string($value, null, true, $attrib['addicon'], $headers['charset']); else if ($hkey == 'subject' && empty($value)) $header_value = rcube_label('nosubject'); else $header_value = trim(rcube_mime::decode_header($value, $headers['charset'])); $output_headers[$hkey] = array( - 'title' => rcube_label(preg_replace('/(^mail-|-)/', '', $hkey)), - 'value' => $header_value, 'raw' => $value + 'title' => $header_title, + 'value' => $header_value, + 'raw' => $value, + 'html' => $ishtml, ); } @@ -1022,7 +1035,7 @@ function rcmail_message_headers($attrib, $headers=NULL) foreach ($plugin['output'] as $hkey => $row) { $table->add(array('class' => 'header-title'), Q($row['title'])); - $table->add(array('class' => 'header '.$hkey), Q($row['value'], ($hkey == 'subject' ? 'strict' : 'show'))); + $table->add(array('class' => 'header '.$hkey), $row['html'] ? $row['value'] : Q($row['value'], ($hkey == 'subject' ? 'strict' : 'show'))); } return $table->show($attrib); @@ -1055,17 +1068,12 @@ function rcmail_message_full_headers($attrib, $headers=NULL) global $OUTPUT; $html = html::div(array('id' => "all-headers", 'class' => "all", 'style' => 'display:none'), html::div(array('id' => 'headers-source'), '')); - - if (!get_boolean($attrib['no-switch'])) { - $html .= html::div(array('class' => "more-headers show-headers", 'onclick' => "return ".JS_OBJECT_NAME.".command('show-headers','',this)"), ''); - } - - unset($attrib['no-switch']); + $html .= html::div(array('class' => "more-headers show-headers", 'onclick' => "return ".JS_OBJECT_NAME.".command('show-headers','',this)", 'title' => rcube_label('togglefullheaders')), ''); $OUTPUT->add_gui_object('all_headers_row', 'all-headers'); $OUTPUT->add_gui_object('all_headers_box', 'headers-source'); - return count($attrib) > 1 ? html::div($attrib, $html) : $html; + return html::div($attrib, $html); } @@ -1399,7 +1407,7 @@ function rcmail_alter_html_link($matches) /** * decode address string and re-format it as HTML links */ -function rcmail_address_string($input, $max=null, $linked=false, $addicon=null, $default_charset=null) +function rcmail_address_string($input, $max=null, $linked=false, $addicon=null, $default_charset=null, $title=null) { global $RCMAIL, $PRINT_MODE, $CONFIG; @@ -1411,6 +1419,7 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null, $c = count($a_parts); $j = 0; $out = ''; + $allvalues = array(); if ($addicon && !isset($_SESSION['writeable_abook'])) { $_SESSION['writeable_abook'] = $RCMAIL->get_address_sources(true) ? true : false; @@ -1418,7 +1427,6 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null, foreach ($a_parts as $part) { $j++; - $name = $part['name']; $mailto = $part['mailto']; $string = $part['string']; @@ -1449,7 +1457,7 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null, } if ($addicon && $_SESSION['writeable_abook']) { - $address = html::span(null, $address . html::a(array( + $address .= html::a(array( 'href' => "#add", 'onclick' => sprintf("return %s.command('add-contact','%s',this)", JS_OBJECT_NAME, $string), 'title' => rcube_label('addtoaddressbook'), @@ -1458,26 +1466,46 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null, html::img(array( 'src' => $CONFIG['skin_path'] . $addicon, 'alt' => "Add contact", - )))); + ))); } - $out .= $address; } else { + $address = ''; if ($name) - $out .= Q($name); + $address .= Q($name); if ($mailto) - $out .= (strlen($out) ? ' ' : '') . sprintf('<%s>', Q($mailto)); + $address .= (strlen($address) ? ' ' : '') . sprintf('<%s>', Q($mailto)); } - if ($c>$j) - $out .= ','.($max ? ' ' : ' '); + $address = html::span('adr', $address); + $allvalues[] = $address; - if ($max && $j==$max && $c>$j) { - $out .= '...'; - break; + if (!$moreadrs) + $out .= ($out ? ', ' : '') . $address; + + if ($max && $j == $max && $c > $j) { + if ($linked) { + $moreadrs = $c - $j; + } + else { + $out .= '...'; + break; + } } } + if ($moreadrs) { + $out .= ' ' . html::a(array( + 'href' => '#more', + 'class' => 'morelink', + 'onclick' => sprintf("return %s.show_popup_dialog('%s','%s')", + JS_OBJECT_NAME, + JQ(join(', ', $allvalues)), + JQ($title)) + ), + Q(rcube_label(array('name' => 'andnmore', 'vars' => array('nr' => $moreadrs))))); + } + return $out; } diff --git a/program/steps/settings/folders.inc b/program/steps/settings/folders.inc index 3231ed644..12e449e80 100644 --- a/program/steps/settings/folders.inc +++ b/program/steps/settings/folders.inc @@ -299,40 +299,44 @@ function rcube_subscription_form($attrib) $disabled = (($protected && $subscribed) || $noselect); - // check if the folder is a namespace prefix, then disable subscription option on it - if (!$disabled && $folder['virtual'] && $folder['level'] == 0 && !empty($namespace)) { - $fname = $folder['id'] . $delimiter; - foreach ($namespace as $ns) { - if (is_array($ns)) { - foreach ($ns as $item) { - if ($item[0] === $fname) { - $disabled = true; - break 2; + // Below we will disable subscription option for "virtual" folders + // according to namespaces, but only if they aren't already subscribed. + // User should be able to unsubscribe from the folder + // even if it doesn't exists or is not accessible (OTRS:1000059) + if (!$subscribed && !$disabled && !empty($namespace) && $folder['virtual']) { + // check if the folder is a namespace prefix, then disable subscription option on it + if (!$disabled && $folder['level'] == 0) { + $fname = $folder['id'] . $delimiter; + foreach ($namespace as $ns) { + if (is_array($ns)) { + foreach ($ns as $item) { + if ($item[0] === $fname) { + $disabled = true; + break 2; + } } } } } - } - // check if the folder is an other users virtual-root folder, then disable subscription option on it - if (!$disabled && $folder['virtual'] && $folder['level'] == 1 - && !empty($namespace) && !empty($namespace['other']) - ) { - $parts = explode($delimiter, $folder['id']); - $fname = $parts[0] . $delimiter; - foreach ($namespace['other'] as $item) { - if ($item[0] === $fname) { - $disabled = true; - break; + // check if the folder is an other users virtual-root folder, then disable subscription option on it + if (!$disabled && $folder['level'] == 1 && !empty($namespace['other'])) { + $parts = explode($delimiter, $folder['id']); + $fname = $parts[0] . $delimiter; + foreach ($namespace['other'] as $item) { + if ($item[0] === $fname) { + $disabled = true; + break; + } } } - } - // check if the folder is shared, then disable subscription option on it (if not subscribed already) - if (!$disabled && !$subscribed && $folder['virtual'] && !empty($namespace)) { - $tmp_ns = array_merge((array)$namespace['other'], (array)$namespace['shared']); - foreach ($tmp_ns as $item) { - if (strpos($folder['id'], $item[0]) === 0) { - $disabled = true; - break; + // check if the folder is shared, then disable subscription option on it (if not subscribed already) + if (!$disabled) { + $tmp_ns = array_merge((array)$namespace['other'], (array)$namespace['shared']); + foreach ($tmp_ns as $item) { + if (strpos($folder['id'], $item[0]) === 0) { + $disabled = true; + break; + } } } } |