Merge branch 'master' of github.com:roundcube/roundcubemail
Conflicts:
program/js/list.js
15 files added
67 files modified
| | |
| | | CHANGELOG Roundcube Webmail |
| | | =========================== |
| | | |
| | | - Added attachment_reminder plugin |
| | | - Fix IMAP connection issue with default_socket_timeout < 0 and imap_timeout < 0 (#1489090) |
| | | - Fix various PHP code bugs found using static analysis (#1489086) |
| | | - Fix backslash character handling on vCard import (#1489085) |
| | | - Fix csv import from Thunderbird with French localization (#1489059) |
| | | - Fix messages list focus issue in Opera and Webkit (#1489058) |
| | | - Make PHP code eval() free, use create_function() |
| | | - Add option to display email address together with a name in mail preview (#1488732) |
| | | - Fix Reply-To header handling in Reply-All action (#1489037) |
| | | - Fix so Sender: address is added to Cc: field on reply to all (#1489011) |
| | | - Fix so addressbook_search_mode works also for group search (#1489079) |
| | | - Fix removal of a contact from a group in LDAP addressbook (#1489081) |
| | | - Support CSV import from Atmail (#1489045) |
| | | - Inlcude SQL query in the log on SQL error (#1489064) |
| | | - Fix handling untagged responses in IMAP FETCH - "could not load message" error (#1489074) |
| | | - Fix very small window size in Chrome (#1488931) |
| | | - Fix list page reset when viewing a message in Larry skin (#1489076) |
| | | - Fix min_refresh_interval handling on preferences save (#1489073) |
| | | - Fix PDF support detection for Firefox PDF.js (#1488972) |
| | | - Fix messages list focus issue in Internet Explorer (#1489058) |
| | | - Add db_prefix configuration option in place of db_table_*/db_sequence_* options |
| | | - Make possible to use db_prefix for schema initialization in Installer (#1489067) |
| | | - Fix updatedb.sh script so it recognizes also table prefix for external DDL files |
New file |
| | |
| | | #!/usr/bin/env php |
| | | <?php |
| | | /* |
| | | +-----------------------------------------------------------------------+ |
| | | | bin/updatecss.sh | |
| | | | | |
| | | | This file is part of the Roundcube Webmail client | |
| | | | Copyright (C) 2010-2013, The Roundcube Dev Team | |
| | | | | |
| | | | Licensed under the GNU General Public License version 3 or | |
| | | | any later version with exceptions for skins & plugins. | |
| | | | See the README file for a full license statement. | |
| | | | | |
| | | | PURPOSE: | |
| | | | Update cache-baster marks for css background images | |
| | | +-----------------------------------------------------------------------+ |
| | | | Author: Aleksander Machniak <alec@alec.pl> | |
| | | +-----------------------------------------------------------------------+ |
| | | */ |
| | | |
| | | define('INSTALL_PATH', realpath(dirname(__FILE__) . '/..') . '/' ); |
| | | |
| | | require_once INSTALL_PATH . 'program/include/clisetup.php'; |
| | | |
| | | // get arguments |
| | | $opts = rcube_utils::get_opt(array( |
| | | 'd' => 'dir', |
| | | )); |
| | | |
| | | if (empty($opts['dir'])) { |
| | | print "Skin directory not specified (--dir). Using skins/ and plugins/skins/.\n"; |
| | | |
| | | $dir = INSTALL_PATH . 'skins'; |
| | | $dir_p = INSTALL_PATH . 'plugins'; |
| | | $skins = glob("$dir/*", GLOB_ONLYDIR); |
| | | $skins_p = glob("$dir_p/*/skins/*", GLOB_ONLYDIR); |
| | | |
| | | $dirs = array_merge($skins, $skins_p); |
| | | } |
| | | // Check if directory exists |
| | | else if (!file_exists($opts['dir'])) { |
| | | rcube::raise_error("Specified directory doesn't exist.", false, true); |
| | | } |
| | | else { |
| | | $dirs = array($opts['dir']); |
| | | } |
| | | |
| | | foreach ($dirs as $dir) { |
| | | $img_dir = $dir . '/images'; |
| | | if (!file_exists($img_dir)) { |
| | | continue; |
| | | } |
| | | |
| | | $files = get_files($dir); |
| | | $images = get_images($img_dir); |
| | | $find = array(); |
| | | $replace = array(); |
| | | |
| | | // build regexps array |
| | | foreach ($images as $path => $sum) { |
| | | $path_ex = str_replace('.', '\\.', $path); |
| | | $find[] = "#url\(['\"]?images/$path_ex(\?v=[a-f0-9-\.]+)?['\"]?\)#"; |
| | | $replace[] = "url(images/$path?v=$sum)"; |
| | | } |
| | | |
| | | foreach ($files as $file) { |
| | | $file = $dir . '/' . $file; |
| | | print "File: $file\n"; |
| | | $content = file_get_contents($file); |
| | | $content = preg_replace($find, $replace, $content, -1, $count); |
| | | if ($count) { |
| | | file_put_contents($file, $content); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | function get_images($dir) |
| | | { |
| | | $images = array(); |
| | | $dh = opendir($dir); |
| | | |
| | | while ($file = readdir($dh)) { |
| | | if (preg_match('/^(.+)\.(gif|ico|png|jpg|jpeg)$/', $file, $m)) { |
| | | $filepath = "$dir/$file"; |
| | | $images[$file] = substr(md5_file($filepath), 0, 4) . '.' . filesize($filepath); |
| | | print "Image: $filepath ({$images[$file]})\n"; |
| | | } |
| | | else if ($file != '.' && $file != '..' && is_dir($dir . '/' . $file)) { |
| | | foreach (get_images($dir . '/' . $file) as $img => $sum) { |
| | | $images[$file . '/' . $img] = $sum; |
| | | } |
| | | } |
| | | } |
| | | |
| | | closedir($dh); |
| | | |
| | | return $images; |
| | | } |
| | | |
| | | function get_files($dir) |
| | | { |
| | | $files = array(); |
| | | $dh = opendir($dir); |
| | | |
| | | while ($file = readdir($dh)) { |
| | | if (preg_match('/^(.+)\.(css|html)$/', $file, $m)) { |
| | | $files[] = $file; |
| | | } |
| | | else if ($file != '.' && $file != '..' && is_dir($dir . '/' . $file)) { |
| | | foreach (get_files($dir . '/' . $file) as $f) { |
| | | $files[] = $file . '/' . $f; |
| | | } |
| | | } |
| | | } |
| | | |
| | | closedir($dh); |
| | | |
| | | return $files; |
| | | } |
| | | |
| | | ?> |
| | |
| | | // Georgia, Helvetica, Impact, Tahoma, Terminal, Times New Roman, Trebuchet MS, Verdana |
| | | $rcmail_config['default_font'] = ''; |
| | | |
| | | // Enables display of email address with name instead of a name (and address in title) |
| | | $rcmail_config['message_show_email'] = false; |
| | | |
| | | // end of config file |
| | |
| | | |
| | | $this->config = array_merge($this->config, $current); |
| | | |
| | | foreach ((array)$current['ldap_public'] as $key => $values) { |
| | | foreach (array_keys((array)$current['ldap_public']) as $key) { |
| | | $this->config['ldap_public'][$key] = $current['ldap_public'][$key]; |
| | | } |
| | | } |
| | |
| | | * Compare the local database schema with the reference schema |
| | | * required for this version of Roundcube |
| | | * |
| | | * @param boolean True if the schema schould be updated |
| | | * @param rcube_db Database object |
| | | * |
| | | * @return boolean True if the schema is up-to-date, false if not or an error occured |
| | | */ |
| | | function db_schema_check($DB, $update = false) |
| | | function db_schema_check($DB) |
| | | { |
| | | if (!$this->configured) |
| | | return false; |
| | |
| | | } |
| | | else { // check if all keys are numeric |
| | | $isnum = true; |
| | | foreach ($var as $key => $value) { |
| | | foreach (array_keys($var) as $key) { |
| | | if (!is_numeric($key)) { |
| | | $isnum = false; |
| | | break; |
| | |
| | | $table->add_header(array('class' => 'acl'.$key, 'title' => $label), $label); |
| | | } |
| | | |
| | | $i = 1; |
| | | $js_table = array(); |
| | | foreach ($acl as $user => $rights) { |
| | | if ($this->rc->storage->conn->user == $user) { |
| | |
| | | |
| | | $acl = array_intersect(str_split($acl), $this->rights_supported()); |
| | | $users = $oldid ? array($user) : explode(',', $user); |
| | | $result = 0; |
| | | |
| | | foreach ($users as $user) { |
| | | $user = trim($user); |
New file |
| | |
| | | /* Attachment Reminder plugin script */ |
| | | |
| | | function rcmail_get_compose_message() |
| | | { |
| | | var msg; |
| | | |
| | | if (window.tinyMCE && (ed = tinyMCE.get(rcmail.env.composebody))) { |
| | | msg = ed.getContent(); |
| | | msg = msg.replace(/<blockquote[^>]*>(.|[\r\n])*<\/blockquote>/gmi, ''); |
| | | } |
| | | else { |
| | | msg = $('#' + rcmail.env.composebody).val(); |
| | | msg = msg.replace(/^>.*$/gmi, ''); |
| | | } |
| | | |
| | | return msg; |
| | | } |
| | | |
| | | function rcmail_check_message(msg) |
| | | { |
| | | var i, rx, keywords = rcmail.gettext('keywords', 'attachment_reminder').split(",").concat([".doc", ".pdf"]); |
| | | |
| | | $.each(keywords, function(n) { return RegExp.escape(n); }); |
| | | rx = new RegExp('(' + keywords.join('|') + ')', 'i'); |
| | | |
| | | return msg.search(rx) != -1; |
| | | } |
| | | |
| | | function rcmail_have_attachments() |
| | | { |
| | | return rcmail.env.attachments && $('li', rcmail.gui_objects.attachmentlist).length; |
| | | } |
| | | |
| | | |
| | | if (window.rcmail) { |
| | | rcmail.addEventListener('beforesend', function(evt) { |
| | | var msg = rcmail_get_compose_message(), |
| | | subject = $('#compose-subject').val(); |
| | | |
| | | if (!rcmail_have_attachments() && (rcmail_check_message(msg) || rcmail_check_message(subject))) { |
| | | if (confirm(rcmail.gettext('forgotattachment', 'attachment_reminder'))) { |
| | | if (window.UI && UI.show_uploadform) // Larry skin |
| | | UI.show_uploadform(); |
| | | else if (window.rcmail_ui && rcmail_ui.show_popup) // classic skin |
| | | rcmail_ui.show_popup('uploadmenu', true); |
| | | |
| | | return false; |
| | | } |
| | | } |
| | | }); |
| | | } |
New file |
| | |
| | | <?php |
| | | /** |
| | | * Attachement Reminder |
| | | * |
| | | * A plugin that reminds a user to attach the files |
| | | * |
| | | * @version @package_version@ |
| | | * @author Thomas Yu - Sian, Liu |
| | | * @author Aleksander Machniak <machniak@kolabsys.com> |
| | | * |
| | | * Copyright (C) 2013 Thomas Yu - Sian, Liu |
| | | * Copyright (C) 2013, Kolab Systems AG |
| | | * |
| | | * This program is free software: you can redistribute it and/or modify |
| | | * it under the terms of the GNU General Public License as published by |
| | | * the Free Software Foundation, either version 3 of the License, or |
| | | * (at your option) any later version. |
| | | * |
| | | * This program is distributed in the hope that it will be useful, |
| | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| | | * GNU General Public License for more details. |
| | | * |
| | | * You should have received a copy of the GNU General Public License |
| | | * along with this program. If not, see <http://www.gnu.org/licenses/> |
| | | */ |
| | | |
| | | class attachment_reminder extends rcube_plugin |
| | | { |
| | | public $task = 'mail|settings'; |
| | | public $noajax = true; |
| | | |
| | | |
| | | function init() |
| | | { |
| | | $rcmail = rcube::get_instance(); |
| | | |
| | | if ($rcmail->task == 'mail' && $rcmail->action == 'compose') { |
| | | $this->include_script('attachment_reminder.js'); |
| | | $this->add_texts('localization/', array('keywords', 'forgotattachment')); |
| | | } |
| | | |
| | | if ($rcmail->task == 'settings') { |
| | | $dont_override = $rcmail->config->get('dont_override', array()); |
| | | |
| | | if (!in_array('attachment_reminder', $dont_override)) { |
| | | $this->add_hook('preferences_list', array($this, 'prefs_list')); |
| | | $this->add_hook('preferences_save', array($this, 'prefs_save')); |
| | | } |
| | | } |
| | | } |
| | | |
| | | function prefs_list($args) |
| | | { |
| | | if ($args['section'] == 'compose') { |
| | | $this->add_texts('localization/'); |
| | | $reminder = rcube::get_instance()->config->get('attachment_reminder'); |
| | | $field_id = 'rcmfd_attachment_reminder'; |
| | | $checkbox = new html_checkbox(array('name' => '_attachment_reminder', 'id' => $field_id, 'value' => 1)); |
| | | |
| | | $args['blocks']['main']['options']['attachment_reminder'] = array( |
| | | 'title' => html::label($field_id, rcube::Q($this->gettext('reminderoption'))), |
| | | 'content' => $checkbox->show($reminder ? 1 : 0), |
| | | ); |
| | | } |
| | | |
| | | return $args; |
| | | } |
| | | |
| | | function prefs_save($args) |
| | | { |
| | | if ($args['section'] == 'compose') { |
| | | $dont_override = rcube::get_instance()->config->get('dont_override', array()); |
| | | if (!in_array('attachment_reminder', $dont_override)) { |
| | | $args['prefs']['attachment_reminder'] = !empty($_POST['_attachment_reminder']); |
| | | } |
| | | } |
| | | return $args; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | <?php |
| | | |
| | | $messages = array(); |
| | | $messages['forgotattachment'] = "Haben Sie möglicherweise vergessen eine Datei anzuhängen?"; |
| | | $messages['keywords'] = "anbei,im anhang,angehängt,angefügt,beigefügt,beliegend"; |
New file |
| | |
| | | <?php |
| | | |
| | | $messages = array(); |
| | | $messages['forgotattachment'] = "Haben Sie möglicherweise vergessen eine Datei anzuhängen?"; |
| | | $messages['keywords'] = "anbei,im anhang,angehängt,angefügt,beigefügt,beliegend"; |
New file |
| | |
| | | <?php |
| | | |
| | | $messages = array(); |
| | | $messages['forgotattachment'] = "Did you forget to attach a file?"; |
| | | $messages['reminderoption'] = "Remind about forgotten attachments"; |
| | | $messages['keywords'] = "attachment,file,attach,attached,attaching,enclosed,CV,cover letter"; |
New file |
| | |
| | | <?php |
| | | |
| | | $messages = array(); |
| | | $messages['forgotattachment'] = "¿Olvidó adjuntar un fichero al mensaje?"; |
| | | $messages['keywords'] = "adjunto"; |
New file |
| | |
| | | <?php |
| | | |
| | | $messages = array(); |
| | | $messages['forgotattachment'] = "Avez vous oublié d'attacher un fichier ?"; |
| | | $messages['keywords'] = "joins,joint,attaché,CV"; |
New file |
| | |
| | | <?php |
| | | |
| | | $messages = array(); |
| | | $messages['forgotattachment'] = "Sembra che tu abbia dimenticato di allegare un file!\nPremere Annulla per inviare lo stesso.\nOK per tornare al messaggio senza inviare."; |
| | | $messages['keywords'] = "allegato,allegati,allegata,allegate,allega,allego,alleghi,attaccato,file,attachment,attach"; |
| | | |
New file |
| | |
| | | <?php |
| | | |
| | | $messages = array(); |
| | | $messages['forgotattachment'] = "Ben je vergeten het bestand bij te voegen?"; |
| | | $messages['keywords'] = "attachment,bestand,bijgaand,bijgaande,brief,bijgevoegd,bijgesloten,CV"; |
New file |
| | |
| | | <?php |
| | | |
| | | $messages = array(); |
| | | $messages['forgotattachment'] = "Czy nie zapomniałeś załączyć pliku?"; |
| | | $messages['reminderoption'] = "Włącz przypominanie o brakującym załączniku"; |
| | | $messages['keywords'] = "załącznik,plik,załącz,CV"; |
New file |
| | |
| | | <?php |
| | | |
| | | $messages = array(); |
| | | $messages['forgotattachment'] = "您似乎忘記加入附件了,你確定要寄出?"; |
| | | $messages['keywords'] = "附件,附加,附檔,附上,附加檔案"; |
New file |
| | |
| | | <?php |
| | | |
| | | $messages = array(); |
| | | $messages['forgotattachment'] = "您似乎忘記加入附件了,你確定要寄出?"; |
| | | $messages['keywords'] = "附件,附加,附檔,附上,附加檔案"; |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <package xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" packagerversion="1.9.0" version="2.0" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 |
| | | http://pear.php.net/dtd/tasks-1.0.xsd |
| | | http://pear.php.net/dtd/package-2.0 |
| | | http://pear.php.net/dtd/package-2.0.xsd"> |
| | | <name>Attachment Reminder</name> |
| | | <summary>Roundcube plugin that prompts you if it looks like you wanted to attach a file but you didn't.</summary> |
| | | <description> |
| | | This Roundcube plugin reminds the user to attach a file if the composed message text indicates that there should be any. |
| | | </description> |
| | | <lead> |
| | | <name>Aleksander Machniak</name> |
| | | <user>alec</user> |
| | | <email>alec@alec.pl</email> |
| | | <active>yes</active> |
| | | </lead> |
| | | <lead> |
| | | <name>Thomas Yu - Sian , Liu</name> |
| | | <active>yes</active> |
| | | </lead> |
| | | <version> |
| | | <release>1.1</release> |
| | | <api>1.0</api> |
| | | </version> |
| | | <stability> |
| | | <release>stable</release> |
| | | <api>stable</api> |
| | | </stability> |
| | | <license uri="http://www.gnu.org/licenses/gpl.html">GNU GPLv3+</license> |
| | | <notes>-</notes> |
| | | <contents> |
| | | <dir baseinstalldir="/" name="/"> |
| | | <file name="attachment_reminder.php" role="php"> |
| | | <tasks:replace from="@name@" to="name" type="package-info"/> |
| | | <tasks:replace from="@package_version@" to="version" type="package-info"/> |
| | | </file> |
| | | <file name="attachment_reminder.js" role="data"> |
| | | <tasks:replace from="@name@" to="name" type="package-info"/> |
| | | <tasks:replace from="@package_version@" to="version" type="package-info"/> |
| | | </file> |
| | | |
| | | <file name="localization/de_CH.inc" role="data"></file> |
| | | <file name="localization/de_DE.inc" role="data"></file> |
| | | <file name="localization/en_US.inc" role="data"></file> |
| | | <file name="localization/es_ES.inc" role="data"></file> |
| | | <file name="localization/fr_FR.inc" role="data"></file> |
| | | <file name="localization/it_IT.inc" role="data"></file> |
| | | <file name="localization/nl_NL.inc" role="data"></file> |
| | | <file name="localization/pl_PL.inc" role="data"></file> |
| | | <file name="localization/zh_CN.inc" role="data"></file> |
| | | <file name="localization/zh_TW.inc" role="data"></file> |
| | | </dir> |
| | | <!-- / --> |
| | | </contents> |
| | | <dependencies> |
| | | <required> |
| | | <php> |
| | | <min>5.2.1</min> |
| | | </php> |
| | | <pearinstaller> |
| | | <min>1.7.0</min> |
| | | </pearinstaller> |
| | | </required> |
| | | </dependencies> |
| | | <phprelease/> |
| | | </package> |
| | |
| | | |
| | | function startup($args) |
| | | { |
| | | $rcmail = rcmail::get_instance(); |
| | | |
| | | // change action to login |
| | | if (empty($_SESSION['user_id']) && !empty($_GET['_autologin']) && $this->is_localhost()) |
| | | $args['action'] = 'login'; |
| | |
| | | |
| | | public function print_totals(){ |
| | | $totals = array(); |
| | | foreach ( $this->run_log as $k => $entry ) { |
| | | foreach ($this->run_log as $entry) { |
| | | if ( $entry['type'] == 'start' && $entry['ended'] == true) { |
| | | $totals[$entry['value']]['duration'] += $entry['duration']; |
| | | $totals[$entry['value']]['count'] += 1; |
| | |
| | | $rcmail = rcmail::get_instance(); |
| | | $this->rc = $rcmail; |
| | | |
| | | $section = rcube_utils::get_input_value('_section', rcube_utils::INPUT_GET); |
| | | |
| | | if ($this->rc->task == 'mail') { |
| | | // message parse/display hooks |
| | | $this->add_hook('message_part_structure', array($this, 'parse_structure')); |
| | |
| | | $this->register_action('plugin.enigma', array($this, 'preferences_ui')); |
| | | |
| | | // grab keys/certs management iframe requests |
| | | $section = rcube_utils::get_input_value('_section', rcube_utils::INPUT_GET); |
| | | if ($this->rc->action == 'edit-prefs' && preg_match('/^enigma(certs|keys)/', $section)) { |
| | | $this->load_ui(); |
| | | $this->ui->init($section); |
| | |
| | | */ |
| | | function parse_structure($p) |
| | | { |
| | | $struct = $p['structure']; |
| | | // $struct = $p['structure']; |
| | | |
| | | if ($p['mimetype'] == 'text/plain' || $p['mimetype'] == 'application/pgp') { |
| | | $this->parse_plain($p); |
| | |
| | | } |
| | | } |
| | | // the same with message bodies |
| | | foreach ((array)$this->message->parts as $idx => $part) { |
| | | foreach ((array)$this->message->parts as $part) { |
| | | if ($this->is_keys_part($part)) { |
| | | $this->keys_parts[] = $part->mime_id; |
| | | $this->keys_bodies[] = $part->mime_id; |
| | |
| | | { |
| | | // @TODO: Handle big bodies using (temp) files |
| | | // @TODO: caching of verification result |
| | | |
| | | $sig = $this->pgp_driver->verify($msg_body, $sig_body); |
| | | |
| | | if (($sig instanceof enigma_error) && $sig->getCode() != enigma_error::E_KEYNOTFOUND) |
| | | rcube::raise_error(array( |
| | | 'code' => 600, 'type' => 'php', |
| | | 'file' => __FILE__, 'line' => __LINE__, |
| | | 'message' => "Enigma plugin: " . $error->getMessage() |
| | | 'message' => "Enigma plugin: " . $sig->getMessage() |
| | | ), true, false); |
| | | |
| | | //print_r($sig); |
| | | return $sig; |
| | | } |
| | | |
| | |
| | | { |
| | | // @TODO: Handle big bodies using (temp) files |
| | | // @TODO: caching of verification result |
| | | |
| | | $key = ''; $pass = ''; // @TODO |
| | | $result = $this->pgp_driver->decrypt($msg_body, $key, $pass); |
| | | |
| | | //print_r($result); |
| | | |
| | | if ($result instanceof enigma_error) { |
| | | $err_code = $result->getCode(); |
| | |
| | | $uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST); |
| | | $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST); |
| | | $mime_id = rcube_utils::get_input_value('_part', rcube_utils::INPUT_POST); |
| | | $storage = $this->rc->get_storage(); |
| | | |
| | | if ($uid && $mime_id) { |
| | | $part = $this->rc->storage->get_message_part($uid, $mime_id); |
| | | $storage->set_folder($mbox); |
| | | $part = $storage->get_message_part($uid, $mime_id); |
| | | } |
| | | |
| | | if ($part && is_array($result = $this->import_key($part))) { |
| | |
| | | $part->body = $this->rc->storage->get_message_part( |
| | | $uid, $part->mime_id, $part); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Adds CSS style file to the page header. |
| | | */ |
| | | private function add_css() |
| | | { |
| | | $skin = $this->rc->config->get('skin'); |
| | | if (!file_exists($this->home . "/skins/$skin/enigma.css")) |
| | | $skin = 'default'; |
| | | |
| | | $this->include_stylesheet("skins/$skin/enigma.css"); |
| | | } |
| | | } |
| | |
| | | $search = rcube_utils::get_input_value('_q', rcube_utils::INPUT_GPC); |
| | | |
| | | // define list of cols to be displayed |
| | | $a_show_cols = array('name'); |
| | | $result = array(); |
| | | // $a_show_cols = array('name'); |
| | | |
| | | // Get the list |
| | | $list = $this->enigma->engine->list_keys($search); |
| | |
| | | $size = count($list); |
| | | |
| | | // Add rows |
| | | foreach($list as $idx => $key) { |
| | | foreach ($list as $key) { |
| | | $this->rc->output->command('enigma_add_list_row', |
| | | array('name' => rcube::Q($key->name), 'id' => $key->id)); |
| | | } |
| | |
| | | |
| | | function init() |
| | | { |
| | | $rcmail = rcmail::get_instance(); |
| | | |
| | | $this->add_texts('localization/', false); |
| | | |
| | | // register task |
| | |
| | | |
| | | // rules |
| | | foreach ($this->content as $rule) { |
| | | $extension = ''; |
| | | $script = ''; |
| | | $tests = array(); |
| | | $i = 0; |
| | |
| | | * @param mixed $num Number of tokens to return, 0 for all |
| | | * or True for all tokens until separator is found. |
| | | * Separator will be returned as last token. |
| | | * @param int $in_list Enable to call recursively inside a list |
| | | * |
| | | * @return mixed Tokens array or string if $num=1 |
| | | */ |
| | | static function tokenize(&$str, $num=0, $in_list=false) |
| | | static function tokenize(&$str, $num=0) |
| | | { |
| | | $result = array(); |
| | | |
| | |
| | | // Parenthesized list |
| | | case '[': |
| | | $str = substr($str, 1); |
| | | $result[] = self::tokenize($str, 0, true); |
| | | $result[] = self::tokenize($str, 0); |
| | | break; |
| | | case ']': |
| | | $str = substr($str, 1); |
| | |
| | | .'value="' . rcube::Q($action['value']) . '" size="35" ' |
| | | . $this->error_class($id, 'action', 'value', 'action_varvalue') .' />'; |
| | | $out .= '<br /><span class="label">' .rcube::Q($this->gettext('setvarmodifiers')) . '</span><br />'; |
| | | foreach ($set_modifiers as $j => $s_m) { |
| | | foreach ($set_modifiers as $s_m) { |
| | | $s_m_id = 'action_varmods' . $id . $s_m; |
| | | $out .= sprintf('<input type="checkbox" name="_action_varmods[%s][]" value="%s" id="%s"%s />%s<br>', |
| | | $id, $s_m, $s_m_id, |
| | |
| | | $user_script = $_SESSION['managesieve_user_script']; |
| | | |
| | | // if the script is not active... |
| | | if ($user_script && ($key = array_search($name, $this->active)) === false) { |
| | | if ($user_script && array_search($name, $this->active) === false) { |
| | | // ...rewrite USER file adding appropriate include command |
| | | if ($this->sieve->load($user_script)) { |
| | | $script = $this->sieve->script->as_array(); |
| | |
| | | |
| | | // get all active scripts for sorting |
| | | foreach ($script as $rid => $rules) { |
| | | foreach ($rules['actions'] as $aid => $action) { |
| | | foreach ($rules['actions'] as $action) { |
| | | if ($action['type'] == 'include' && empty($action['global'])) { |
| | | $target = $extension ? preg_replace($regexp, '', $action['target']) : $action['target']; |
| | | $list[] = $target; |
| | |
| | | $name = $name.$extension; |
| | | |
| | | foreach ($script as $rid => $rules) { |
| | | foreach ($rules['actions'] as $aid => $action) { |
| | | foreach ($rules['actions'] as $action) { |
| | | if ($action['type'] == 'include' && empty($action['global']) |
| | | && $action['target'] == $name |
| | | ) { |
| | |
| | | |
| | | function lookup_user_name($args) |
| | | { |
| | | $rcmail = rcmail::get_instance(); |
| | | |
| | | if ($this->init_ldap($args['host'])) { |
| | | $results = $this->ldap->search('*', $args['user'], true); |
| | | if (count($results->records) == 1) { |
| | |
| | | $status = socket_get_status($socket); |
| | | $startTime = time(); |
| | | $length = 0; |
| | | $prevSecond = 0; |
| | | while ( !feof($socket) && !$status['timed_out'] ) |
| | | { |
| | | $chunk = fgets($socket,1024); |
| | |
| | | function save($currpass, $newpass) |
| | | { |
| | | $user = $_SESSION['username']; |
| | | $error = ''; |
| | | |
| | | if (extension_loaded('pam') || extension_loaded('pam_auth')) { |
| | | if (pam_auth($user, $currpass, $error, false)) { |
| | |
| | | $db = $rcmail->get_dbh(); |
| | | } |
| | | |
| | | if ($err = $db->is_error()) |
| | | if ($db->is_error()) { |
| | | return PASSWORD_ERROR; |
| | | } |
| | | |
| | | // crypted password |
| | | if (strpos($sql, '%c') !== FALSE) { |
| | |
| | | $res = $db->query($sql, $sql_vars); |
| | | |
| | | if (!$db->is_error()) { |
| | | if (strtolower(substr(trim($query),0,6))=='select') { |
| | | if ($result = $db->fetch_array($res)) |
| | | if (strtolower(substr(trim($sql),0,6)) == 'select') { |
| | | if ($db->fetch_array($res)) |
| | | return PASSWORD_SUCCESS; |
| | | } else { |
| | | // This is the good case: 1 row updated |
| | |
| | | function send($msg) |
| | | { |
| | | socket_write($this->socket,$msg); |
| | | if (substr($in = socket_read($this->socket, 512, PHP_BINARY_READ),0,1) != "+") { |
| | | if (substr(socket_read($this->socket, 512, PHP_BINARY_READ),0,1) != "+") { |
| | | return false; |
| | | } |
| | | return true; |
| | |
| | | return false; |
| | | } |
| | | |
| | | if (substr($in = socket_read($this->socket, 512, PHP_BINARY_READ),0,1) != "+") { |
| | | if (substr(socket_read($this->socket, 512, PHP_BINARY_READ),0,1) != "+") { |
| | | socket_close($this->socket); |
| | | return false; |
| | | } |
| | |
| | | if ($this->prefs['___sig'.$i.'___']) |
| | | $ident_data['signature'] = $this->prefs['___sig'.$i.'___']; |
| | | // insert identity |
| | | $identid = $rcmail->user->insert_identity($ident_data); |
| | | $rcmail->user->insert_identity($ident_data); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | // the same with message bodies |
| | | foreach ((array)$this->message->parts as $idx => $part) { |
| | | foreach ((array)$this->message->parts as $part) { |
| | | if ($this->is_vcard($part)) { |
| | | $this->vcard_parts[] = $part->mime_id; |
| | | $this->vcard_bodies[] = $part->mime_id; |
| | |
| | | function html_output($p) |
| | | { |
| | | $attach_script = false; |
| | | $icon = 'plugins/vcard_attachments/' .$this->local_skin_path(). '/vcard_add_contact.png'; |
| | | |
| | | foreach ($this->vcard_parts as $part) { |
| | | $vcards = rcube_vcard::import($this->message->get_part_content($part, null, true)); |
| | |
| | | for ($i = 0; ($i * $imap->get_pagesize()) <= $count; $i++) { |
| | | $a_headers = $imap->list_messages($mbox_name, ($i + 1)); |
| | | |
| | | foreach ($a_headers as $n => $header) { |
| | | foreach ($a_headers as $header) { |
| | | if (empty($header)) |
| | | continue; |
| | | |
| | |
| | | $zip = new ZipArchive(); |
| | | $zip->open($tmpfname, ZIPARCHIVE::OVERWRITE); |
| | | |
| | | foreach ($uids as $key => $uid){ |
| | | foreach ($uids as $uid){ |
| | | $headers = $imap->get_message_headers($uid); |
| | | $subject = rcube_mime::decode_mime_string((string)$headers->subject); |
| | | $subject = $this->_convert_filename($subject); |
| | |
| | | |
| | | function rcmail_temp_gc() |
| | | { |
| | | $rcmail = rcmail::get_instance()->temp_gc(); |
| | | rcmail::get_instance()->temp_gc(); |
| | | } |
| | | |
| | | function rcube_charset_convert($str, $from, $to=NULL) |
| | |
| | | $post_host = rcube_utils::get_input_value('_host', rcube_utils::INPUT_POST); |
| | | $post_user = rcube_utils::get_input_value('_user', rcube_utils::INPUT_POST); |
| | | |
| | | list($user, $domain) = explode('@', $post_user); |
| | | list(, $domain) = explode('@', $post_user); |
| | | |
| | | // direct match in default_host array |
| | | if ($default_host[$post_host] || in_array($post_host, array_values($default_host))) { |
| | |
| | | $token = rcube_utils::get_input_value('_token', $mode); |
| | | $sess_id = $_COOKIE[ini_get('session.name')]; |
| | | return !empty($sess_id) && $token == $this->get_request_token(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Create unique authorization hash |
| | | * |
| | | * @param string Session ID |
| | | * @param int Timestamp |
| | | * @return string The generated auth hash |
| | | */ |
| | | private function get_auth_hash($sess_id, $ts) |
| | | { |
| | | $auth_string = sprintf('rcmail*sess%sR%s*Chk:%s;%s', |
| | | $sess_id, |
| | | $ts, |
| | | $this->config->get('ip_check') ? $_SERVER['REMOTE_ADDR'] : '***.***.***.***', |
| | | $_SERVER['HTTP_USER_AGENT']); |
| | | |
| | | if (function_exists('sha1')) |
| | | return sha1($auth_string); |
| | | else |
| | | return md5($auth_string); |
| | | } |
| | | |
| | | |
| | |
| | | */ |
| | | public function table_output($attrib, $table_data, $a_show_cols, $id_col) |
| | | { |
| | | $table = new html_table(/*array('cols' => count($a_show_cols))*/); |
| | | $table = new html_table($attrib); |
| | | |
| | | // add table header |
| | | if (!$attrib['noheader']) { |
| | |
| | | $collapsed = $this->config->get('collapsed_folders'); |
| | | |
| | | $out = ''; |
| | | foreach ($arrFolders as $key => $folder) { |
| | | foreach ($arrFolders as $folder) { |
| | | $title = null; |
| | | $folder_class = $this->folder_classname($folder['id']); |
| | | $is_collapsed = strpos($collapsed, '&'.rawurlencode($folder['id']).'&') !== false; |
| | |
| | | { |
| | | $out = ''; |
| | | |
| | | foreach ($arrFolders as $key => $folder) { |
| | | foreach ($arrFolders as $folder) { |
| | | // skip exceptions (and its subfolders) |
| | | if (!empty($opts['exceptions']) && in_array($folder['id'], $opts['exceptions'])) { |
| | | continue; |
| | |
| | | /** |
| | | * Determines if a given condition is met |
| | | * |
| | | * @todo Get rid off eval() once I understand what this does. |
| | | * @todo Extend this to allow real conditions, not just "set" |
| | | * @param string Condition statement |
| | | * @return boolean True if condition is met, False if not |
| | | */ |
| | | protected function check_condition($condition) |
| | | { |
| | | return eval("return (".$this->parse_expression($condition).");"); |
| | | return $this->eval_expression($condition); |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * Parses expression and replaces variables |
| | | * Parse & evaluate a given expression and return its result. |
| | | * |
| | | * @param string Expression statement |
| | | * @return string Expression value |
| | | * |
| | | * @return mixed Expression result |
| | | */ |
| | | protected function parse_expression($expression) |
| | | protected function eval_expression ($expression) |
| | | { |
| | | return preg_replace( |
| | | $expression = preg_replace( |
| | | array( |
| | | '/session:([a-z0-9_]+)/i', |
| | | '/config:([a-z0-9_]+)(:([a-z0-9_]+))?/i', |
| | |
| | | ), |
| | | array( |
| | | "\$_SESSION['\\1']", |
| | | "\$this->app->config->get('\\1',rcube_utils::get_boolean('\\3'))", |
| | | "\$this->env['\\1']", |
| | | "\$app->config->get('\\1',rcube_utils::get_boolean('\\3'))", |
| | | "\$env['\\1']", |
| | | "rcube_utils::get_input_value('\\1', rcube_utils::INPUT_GPC)", |
| | | "\$_COOKIE['\\1']", |
| | | "\$this->browser->{'\\1'}", |
| | | "\$browser->{'\\1'}", |
| | | $this->template_name, |
| | | ), |
| | | $expression); |
| | | $expression |
| | | ); |
| | | |
| | | $fn = create_function('$app,$browser,$env', "return ($expression);"); |
| | | if (!$fn) { |
| | | rcube::raise_error(array( |
| | | 'code' => 505, |
| | | 'type' => 'php', |
| | | 'file' => __FILE__, |
| | | 'line' => __LINE__, |
| | | 'message' => "Expression parse error on: ($expression)"), true, false); |
| | | |
| | | return null; |
| | | } |
| | | |
| | | return $fn($this->app, $this->browser, $this->env); |
| | | } |
| | | |
| | | |
| | |
| | | // show a label |
| | | case 'label': |
| | | if ($attrib['expression']) |
| | | $attrib['name'] = eval("return " . $this->parse_expression($attrib['expression']) .";"); |
| | | $attrib['name'] = $this->eval_expression($attrib['expression']); |
| | | |
| | | if ($attrib['name'] || $attrib['command']) { |
| | | // @FIXME: 'noshow' is useless, remove? |
| | |
| | | |
| | | // return code for a specified eval expression |
| | | case 'exp': |
| | | $value = $this->parse_expression($attrib['expression']); |
| | | return eval("return html::quote($value);"); |
| | | return html::quote($this->eval_expression($attrib['expression'])); |
| | | |
| | | // return variable |
| | | case 'var': |
| | |
| | | url._to = props; |
| | | } |
| | | else { |
| | | // use contact_id passed as command parameter |
| | | var n, len, a_cids = []; |
| | | var a_cids = []; |
| | | // use contact id passed as command parameter |
| | | if (props) |
| | | a_cids.push(props); |
| | | // get selected contacts |
| | | else if (this.contact_list) { |
| | | var selection = this.contact_list.get_selection(); |
| | | for (n=0, len=selection.length; n<len; n++) |
| | | a_cids.push(selection[n]); |
| | | } |
| | | else if (this.contact_list) |
| | | a_cids = this.contact_list.get_selection(); |
| | | |
| | | if (a_cids.length) |
| | | this.http_post('mailto', { _cid: a_cids.join(','), _source: this.env.source }, true); |
| | |
| | | |
| | | this.msglist_set_coltypes = function(list) |
| | | { |
| | | var i, found, name, cols = list.list.tHead.rows[0].cells; |
| | | var i, found, name, cols = list.thead.rows[0].cells; |
| | | |
| | | this.env.coltypes = []; |
| | | |
| | |
| | | |
| | | this.open_window = function(url, width, height) |
| | | { |
| | | var w = Math.min(width, screen.width - 10), |
| | | h = Math.min(height, screen.height - 100), |
| | | l = (screen.width - w) / 2 + (screen.left || 0), |
| | | t = Math.max(0, (screen.height - h) / 2 + (screen.top || 0) - 20), |
| | | var dh = (window.outerHeight || 0) - (window.innerHeight || 0), |
| | | dw = (window.outerWidth || 0) - (window.innerWidth || 0), |
| | | sh = screen.availHeight || screen.height, |
| | | sw = screen.availWidth || screen.width, |
| | | w = Math.min(width, sw), |
| | | h = Math.min(height, sh), |
| | | l = Math.max(0, (sw - w) / 2 + (screen.left || 0)), |
| | | t = Math.max(0, (sh - h) / 2 + (screen.top || 0)), |
| | | wname = 'rcmextwin' + new Date().getTime(), |
| | | extwin = window.open(url + (url.match(/\?/) ? '&' : '?') + '_extwin=1', wname, |
| | | 'width='+w+',height='+h+',top='+t+',left='+l+',resizable=yes,toolbar=no,status=no,location=no'); |
| | | 'width='+(w-dw)+',height='+(h-dh)+',top='+t+',left='+l+',resizable=yes,toolbar=no,status=no,location=no'); |
| | | |
| | | // write loading... message to empty windows |
| | | if (!url && extwin.document) { |
| | |
| | | + (flags.flagged ? ' flagged' : '') |
| | | + (flags.unread_children && flags.seen && !this.env.autoexpand_threads ? ' unroot' : '') |
| | | + (message.selected ? ' selected' : ''), |
| | | // for performance use DOM instead of jQuery here |
| | | row = document.createElement('tr'); |
| | | |
| | | row.id = 'rcmrow'+uid; |
| | | row = { cols:[], style:{}, id:'rcmrow'+uid }; |
| | | |
| | | // message status icons |
| | | css_class = 'msgicon'; |
| | |
| | | // add each submitted col |
| | | for (n in this.env.coltypes) { |
| | | c = this.env.coltypes[n]; |
| | | col = document.createElement('td'); |
| | | col.className = String(c).toLowerCase(); |
| | | col = { className: String(c).toLowerCase() }; |
| | | |
| | | if (c == 'flag') { |
| | | css_class = (flags.flagged ? 'flagged' : 'unflagged'); |
| | |
| | | html = cols[c]; |
| | | |
| | | col.innerHTML = html; |
| | | |
| | | row.appendChild(col); |
| | | row.cols.push(col); |
| | | } |
| | | |
| | | list.insert_row(row, attop); |
| | |
| | | if (root) |
| | | row = rows[root] ? rows[root].obj : null; |
| | | else |
| | | row = this.message_list.list.tBodies[0].firstChild; |
| | | row = this.message_list.tbody.firstChild; |
| | | |
| | | while (row) { |
| | | if (row.nodeType == 1 && (r = rows[row.uid])) { |
| | |
| | | this.delete_excessive_thread_rows = function() |
| | | { |
| | | var rows = this.message_list.rows, |
| | | tbody = this.message_list.list.tBodies[0], |
| | | tbody = this.message_list.tbody, |
| | | row = tbody.firstChild, |
| | | cnt = this.env.pagesize + 1; |
| | | |
| | |
| | | newcid = newcid+'-'+source; |
| | | } |
| | | |
| | | if (list.rows[cid] && (row = list.rows[cid].obj)) { |
| | | for (c=0; c<cols_arr.length; c++) |
| | | if (row.cells[c]) |
| | | $(row.cells[c]).html(cols_arr[c]); |
| | | |
| | | // cid change |
| | | if (newcid) { |
| | | newcid = this.html_identifier(newcid); |
| | | row.id = 'rcmrow' + newcid; |
| | | list.remove_row(cid); |
| | | list.init_row(row); |
| | | list.selection[0] = newcid; |
| | | row.style.display = ''; |
| | | } |
| | | } |
| | | list.update_row(cid, cols_arr, newcid, true); |
| | | }; |
| | | |
| | | // add row to contacts list |
| | |
| | | return false; |
| | | |
| | | var c, col, list = this.contact_list, |
| | | row = document.createElement('tr'); |
| | | row = { cols:[] }; |
| | | |
| | | row.id = 'rcmrow'+this.html_identifier(cid); |
| | | row.className = 'contact ' + (classes || ''); |
| | |
| | | |
| | | // add each submitted col |
| | | for (c in cols) { |
| | | col = document.createElement('td'); |
| | | col = {}; |
| | | col.className = String(c).toLowerCase(); |
| | | col.innerHTML = cols[c]; |
| | | row.appendChild(col); |
| | | row.cols.push(col); |
| | | } |
| | | |
| | | list.insert_row(row); |
| | |
| | | this.name_input.bind('keydown', function(e){ return rcmail.add_input_keydown(e); }); |
| | | this.name_input_li = $('<li>').addClass(type).append(this.name_input); |
| | | |
| | | var li = type == 'contactsearch' ? $('li:last', this.gui_objects.folderlist) : $('ul.groups li:last', this.get_folder_li(this.env.source,'',true)); |
| | | var ul, li; |
| | | |
| | | // find list (UL) element |
| | | if (type == 'contactsearch') |
| | | ul = this.gui_objects.folderlist; |
| | | else |
| | | ul = $('ul.groups', this.get_folder_li(this.env.source,'',true)); |
| | | |
| | | // append to the list |
| | | li = $('li:last', ul); |
| | | if (li.length) |
| | | this.name_input_li.insertAfter(li); |
| | | else |
| | | this.name_input_li.appendTo(type == 'contactsearch' ? this.gui_objects.folderlist : $('ul.groups', this.get_folder_li(this.env.source,'',true))); |
| | | else { |
| | | this.name_input_li.appendTo(ul); |
| | | ul.show(); // make sure the list is visible |
| | | } |
| | | } |
| | | |
| | | this.name_input.select().focus(); |
| | |
| | | this.reset_add_input = function() |
| | | { |
| | | if (this.name_input) { |
| | | if (this.env.group_renaming) { |
| | | var li = this.name_input.parent(); |
| | | if (this.env.group_renaming) { |
| | | li.children().last().show(); |
| | | this.env.group_renaming = false; |
| | | } |
| | | else if ($('li', li.parent()).length == 1) |
| | | li.parent().hide(); |
| | | |
| | | this.name_input.remove(); |
| | | |
| | |
| | | |
| | | this.update_identity_row = function(id, name, add) |
| | | { |
| | | var row, col, list = this.identity_list, |
| | | var list = this.identity_list, |
| | | rid = this.html_identifier(id); |
| | | |
| | | if (list.rows[rid] && (row = list.rows[rid].obj)) { |
| | | $(row.cells[0]).html(name); |
| | | } |
| | | else if (add) { |
| | | row = $('<tr>').attr('id', 'rcmrow'+rid).get(0); |
| | | col = $('<td>').addClass('mail').html(name).appendTo(row); |
| | | list.insert_row(row); |
| | | if (add) { |
| | | list.insert_row({ id:'rcmrow'+rid, cols:[ { className:'mail', innerHTML:name } ] }); |
| | | list.select(rid); |
| | | } |
| | | else { |
| | | list.update_row(rid, [ name ]); |
| | | } |
| | | }; |
| | | |
| | |
| | | this.set_message_coltypes = function(coltypes, repl, smart_col) |
| | | { |
| | | var list = this.message_list, |
| | | thead = list ? list.list.tHead : null, |
| | | thead = list ? list.thead : null, |
| | | cell, col, n, len, th, tr; |
| | | |
| | | this.env.coltypes = coltypes; |
| | |
| | | this.BACKSPACE_KEY = 8; |
| | | |
| | | this.list = list ? list : null; |
| | | this.tagname = this.list ? this.list.nodeName.toLowerCase() : 'table'; |
| | | this.thead; |
| | | this.tbody; |
| | | this.frame = null; |
| | | this.rows = []; |
| | | this.selection = []; |
| | |
| | | this.focused = false; |
| | | this.drag_mouse_start = null; |
| | | this.dblclick_time = 600; |
| | | this.row_init = function(){}; |
| | | this.row_init = function(){}; // @deprecated; use list.addEventListener('initrow') instead |
| | | |
| | | // overwrite default paramaters |
| | | if (p && typeof p === 'object') |
| | |
| | | */ |
| | | init: function() |
| | | { |
| | | if (this.list && this.list.tBodies[0]) { |
| | | if (this.tagname == 'table' && this.list && this.list.tBodies[0]) { |
| | | this.thead = this.list.tHead; |
| | | this.tbody = this.list.tBodies[0]; |
| | | } |
| | | else if (this.tagname != 'table' && this.list) { |
| | | this.tbody = this.list; |
| | | } |
| | | |
| | | if (this.tbody) { |
| | | this.rows = []; |
| | | this.rowcount = 0; |
| | | |
| | | var r, len, rows = this.list.tBodies[0].rows; |
| | | var r, len, rows = this.tbody.childNodes; |
| | | |
| | | for (r=0, len=rows.length; r<len; r++) { |
| | | this.init_row(rows[r]); |
| | |
| | | if (document.all) |
| | | row.onselectstart = function() { return false; }; |
| | | |
| | | this.row_init(this.rows[uid]); |
| | | this.row_init(this.rows[uid]); // legacy support |
| | | this.triggerEvent('initrow', this.rows[uid]); |
| | | } |
| | | }, |
| | | |
| | |
| | | */ |
| | | init_header: function() |
| | | { |
| | | if (this.list && this.list.tHead) { |
| | | if (this.thead) { |
| | | this.colcount = 0; |
| | | |
| | | var col, r, p = this; |
| | | // add events for list columns moving |
| | | if (this.column_movable && this.list.tHead && this.list.tHead.rows) { |
| | | for (r=0; r<this.list.tHead.rows[0].cells.length; r++) { |
| | | if (this.column_movable && this.thead && this.thead.rows) { |
| | | for (r=0; r<this.thead.rows[0].cells.length; r++) { |
| | | if (this.column_fixed == r) |
| | | continue; |
| | | col = this.list.tHead.rows[0].cells[r]; |
| | | col = this.thead.rows[0].cells[r]; |
| | | col.onmousedown = function(e){ return p.drag_column(e, this); }; |
| | | this.colcount++; |
| | | } |
| | |
| | | */ |
| | | clear: function(sel) |
| | | { |
| | | if (this.tagname == 'table') { |
| | | var tbody = document.createElement('tbody'); |
| | | |
| | | this.list.insertBefore(tbody, this.list.tBodies[0]); |
| | | this.list.insertBefore(tbody, this.tbody); |
| | | this.list.removeChild(this.list.tBodies[1]); |
| | | this.tbody = tbody; |
| | | } |
| | | else { |
| | | $(this.row_tagname() + ':not(.thead)', this.tbody).remove(); |
| | | } |
| | | |
| | | this.rows = []; |
| | | this.rowcount = 0; |
| | | |
| | |
| | | */ |
| | | remove_row: function(uid, sel_next) |
| | | { |
| | | var obj = this.rows[uid] ? this.rows[uid].obj : null; |
| | | var node = this.rows[uid] ? this.rows[uid].obj : null; |
| | | |
| | | if (!obj) |
| | | if (!node) |
| | | return; |
| | | |
| | | obj.style.display = 'none'; |
| | | node.style.display = 'none'; |
| | | |
| | | if (sel_next) |
| | | this.select_next(); |
| | |
| | | */ |
| | | insert_row: function(row, before) |
| | | { |
| | | var tbody = this.list.tBodies[0]; |
| | | var tbody = this.tbody; |
| | | |
| | | if (before && tbody.rows.length) |
| | | // create a real dom node first |
| | | if (row.nodeName === undefined) { |
| | | // for performance reasons use DOM instead of jQuery here |
| | | var domrow = document.createElement(this.row_tagname()); |
| | | if (row.id) domrow.id = row.id; |
| | | if (row.className) domrow.className = row.className; |
| | | if (row.style) $.extend(domrow.style, row.style); |
| | | |
| | | for (var domcell, col, i=0; row.cols && i < row.cols.length; i++) { |
| | | col = row.cols[i]; |
| | | domcell = document.createElement(this.col_tagname()); |
| | | if (col.className) domcell.className = col.className; |
| | | if (col.innerHTML) domcell.innerHTML = col.innerHTML; |
| | | domrow.appendChild(domcell); |
| | | } |
| | | |
| | | row = domrow; |
| | | } |
| | | |
| | | if (before && tbody.childNodes.length) |
| | | tbody.insertBefore(row, (typeof before == 'object' && before.parentNode == tbody) ? before : tbody.firstChild); |
| | | else |
| | | tbody.appendChild(row); |
| | |
| | | this.rowcount++; |
| | | }, |
| | | |
| | | /** |
| | | * |
| | | */ |
| | | update_row: function(id, cols, newid, select) |
| | | { |
| | | var row = this.rows[id]; |
| | | if (!row) return false; |
| | | |
| | | var domrow = row.obj; |
| | | for (var domcell, col, i=0; cols && i < cols.length; i++) { |
| | | this.get_cell(domrow, i).html(cols[i]); |
| | | } |
| | | |
| | | if (newid) { |
| | | delete this.rows[id]; |
| | | domrow.id = 'rcmrow' + newid; |
| | | this.init_row(domrow); |
| | | |
| | | if (select) |
| | | this.selection[0] = newid; |
| | | } |
| | | }, |
| | | |
| | | |
| | | /** |
| | |
| | | } |
| | | |
| | | // Un-focus already focused elements (#1487123, #1487316, #1488600, #1488620) |
| | | // It looks that window.focus() does the job for all browsers, but not Firefox (#1489058) |
| | | $(':focus:not(body)').blur(); |
| | | // un-focus iframe bodies (#1489058), this doesn't work in Opera and Chrome |
| | | $('iframe').contents().find('body').blur(); |
| | | window.focus(); |
| | | |
| | | if (e || (e = window.event)) |
| | | rcube_event.cancel(e); |
| | |
| | | this.add_dragfix(); |
| | | |
| | | // find selected column number |
| | | for (var i=0; i<this.list.tHead.rows[0].cells.length; i++) { |
| | | if (col == this.list.tHead.rows[0].cells[i]) { |
| | | for (var i=0; i<this.thead.rows[0].cells.length; i++) { |
| | | if (col == this.thead.rows[0].cells[i]) { |
| | | this.selected_column = i; |
| | | break; |
| | | } |
| | |
| | | this.triggerEvent('expandcollapse', { uid:row.uid, expanded:row.expanded, obj:row.obj }); |
| | | } |
| | | else { |
| | | var tbody = this.list.tBodies[0]; |
| | | var tbody = this.tbody; |
| | | new_row = tbody.firstChild; |
| | | depth = 0; |
| | | last_expanded_parent_depth = 0; |
| | |
| | | return false; |
| | | } |
| | | else { |
| | | new_row = this.list.tBodies[0].firstChild; |
| | | new_row = this.tbody.firstChild; |
| | | depth = 0; |
| | | } |
| | | |
| | |
| | | this.triggerEvent('expandcollapse', { uid:row.uid, expanded:row.expanded, obj:row.obj }); |
| | | } |
| | | else { |
| | | new_row = this.list.tBodies[0].firstChild; |
| | | new_row = this.tbody.firstChild; |
| | | depth = 0; |
| | | } |
| | | |
| | |
| | | get_first_row: function() |
| | | { |
| | | if (this.rowcount) { |
| | | var i, len, rows = this.list.tBodies[0].rows; |
| | | var i, len, rows = this.tbody.childNodes; |
| | | |
| | | for (i=0, len=rows.length-1; i<len; i++) |
| | | if (rows[i].id && String(rows[i].id).match(/^rcmrow([a-z0-9\-_=\+\/]+)/i) && this.rows[RegExp.$1] != null) |
| | |
| | | get_last_row: function() |
| | | { |
| | | if (this.rowcount) { |
| | | var i, rows = this.list.tBodies[0].rows; |
| | | var i, rows = this.tbody.childNodes; |
| | | |
| | | for (i=rows.length-1; i>=0; i--) |
| | | if (rows[i].id && String(rows[i].id).match(/^rcmrow([a-z0-9\-_=\+\/]+)/i) && this.rows[RegExp.$1] != null) |
| | |
| | | return null; |
| | | }, |
| | | |
| | | row_tagname: function() |
| | | { |
| | | var row_tagnames = { table:'tr', ul:'li', '*':'div' }; |
| | | return row_tagnames[this.tagname] || row_tagnames['*']; |
| | | }, |
| | | |
| | | col_tagname: function() |
| | | { |
| | | var col_tagnames = { table:'td', '*':'span' }; |
| | | return col_tagnames[this.tagname] || col_tagnames['*']; |
| | | }, |
| | | |
| | | get_cell: function(row, index) |
| | | { |
| | | return $(this.col_tagname(), row).eq(index); |
| | | }, |
| | | |
| | | /** |
| | | * selects or unselects the proper row depending on the modifier key pressed |
| | |
| | | this.shift_start = id; |
| | | |
| | | var n, i, j, to_row = this.rows[id], |
| | | from_rowIndex = this.rows[this.shift_start].obj.rowIndex, |
| | | to_rowIndex = to_row.obj.rowIndex; |
| | | from_rowIndex = this._rowIndex(this.rows[this.shift_start].obj), |
| | | to_rowIndex = this._rowIndex(to_row.obj); |
| | | |
| | | if (!to_row.expanded && to_row.has_children) |
| | | if (to_row = this.rows[(this.row_children(id)).pop()]) |
| | | to_rowIndex = to_row.obj.rowIndex; |
| | | to_rowIndex = this._rowIndex(to_row.obj); |
| | | |
| | | i = ((from_rowIndex < to_rowIndex) ? from_rowIndex : to_rowIndex), |
| | | j = ((from_rowIndex > to_rowIndex) ? from_rowIndex : to_rowIndex); |
| | | |
| | | // iterate through the entire message list |
| | | for (n in this.rows) { |
| | | if (this.rows[n].obj.rowIndex >= i && this.rows[n].obj.rowIndex <= j) { |
| | | if (this._rowIndex(this.rows[n].obj) >= i && this._rowIndex(this.rows[n].obj) <= j) { |
| | | if (!this.in_selection(n)) { |
| | | this.highlight_row(n, true); |
| | | } |
| | |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * Helper method to emulate the rowIndex property of non-tr elements |
| | | */ |
| | | _rowIndex: function(obj) |
| | | { |
| | | return (obj.rowIndex !== undefined) ? obj.rowIndex : $(obj).prevAll().length; |
| | | }, |
| | | |
| | | /** |
| | | * Check if given id is part of the current selection |
| | |
| | | this.draglayer.html(''); |
| | | |
| | | // get subjects of selected messages |
| | | var i, n, obj; |
| | | var i, n, obj, me; |
| | | for (n=0; n<this.selection.length; n++) { |
| | | // only show 12 lines |
| | | if (n>12) { |
| | |
| | | break; |
| | | } |
| | | |
| | | me = this; |
| | | if (obj = this.rows[this.selection[n]].obj) { |
| | | for (i=0; i<obj.childNodes.length; i++) { |
| | | if (obj.childNodes[i].nodeName == 'TD') { |
| | | $('> '+this.col_tagname(), obj).each(function(i,elem){ |
| | | if (n == 0) |
| | | this.drag_start_pos = $(obj.childNodes[i]).offset(); |
| | | me.drag_start_pos = $(elem).offset(); |
| | | |
| | | if (this.subject_col < 0 || (this.subject_col >= 0 && this.subject_col == i)) { |
| | | var subject = $(obj.childNodes[i]).text(); |
| | | if (me.subject_col < 0 || (me.subject_col >= 0 && me.subject_col == i)) { |
| | | var subject = $(elem).text(); |
| | | |
| | | if (!subject) |
| | | break; |
| | | |
| | | if (subject) { |
| | | // remove leading spaces |
| | | subject = $.trim(subject); |
| | | // truncate line to 50 characters |
| | | subject = (subject.length > 50 ? subject.substring(0, 50) + '...' : subject); |
| | | |
| | | var entry = $('<div>').text(subject); |
| | | this.draglayer.append(entry); |
| | | break; |
| | | me.draglayer.append(entry); |
| | | } |
| | | |
| | | return false; // break |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | if (!this.col_draglayer) { |
| | | var lpos = $(this.list).offset(), |
| | | cells = this.list.tHead.rows[0].cells; |
| | | cells = this.thead.rows[0].cells; |
| | | |
| | | // create dragging layer |
| | | this.col_draglayer = $('<div>').attr('id', 'rcmcoldraglayer') |
| | |
| | | */ |
| | | column_replace: function(from, to) |
| | | { |
| | | var len, cells = this.list.tHead.rows[0].cells, |
| | | // only supported for <table> lists |
| | | if (!this.thead || !this.thead.rows) |
| | | return; |
| | | |
| | | var len, cells = this.thead.rows[0].cells, |
| | | elem = cells[from], |
| | | before = cells[to], |
| | | td = document.createElement('td'); |
| | |
| | | cells[0].parentNode.replaceChild(elem, td); |
| | | |
| | | // replace list cells |
| | | for (r=0, len=this.list.tBodies[0].rows.length; r<len; r++) { |
| | | row = this.list.tBodies[0].rows[r]; |
| | | for (r=0, len=this.tbody.rows.length; r<len; r++) { |
| | | row = this.tbody.rows[r]; |
| | | |
| | | elem = row.cells[from]; |
| | | before = row.cells[to]; |
| | |
| | | { |
| | | $default_attrib = self::$doctype == 'xhtml' ? array('summary' => '', 'border' => 0) : array(); |
| | | $this->attrib = array_merge($attrib, $default_attrib); |
| | | |
| | | if (!empty($attrib['tagname']) && $attrib['tagname'] != 'table') { |
| | | $this->tagname = $attrib['tagname']; |
| | | $this->allowed = self::$common_attrib; |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | if (!empty($this->header)) { |
| | | $rowcontent = ''; |
| | | foreach ($this->header as $c => $col) { |
| | | $rowcontent .= self::tag('td', $col->attrib, $col->content); |
| | | $rowcontent .= self::tag($this->_col_tagname(), $col->attrib, $col->content); |
| | | } |
| | | $thead = self::tag('thead', null, self::tag('tr', null, $rowcontent, parent::$common_attrib)); |
| | | $thead = $this->tagname == 'table' ? self::tag('thead', null, self::tag('tr', null, $rowcontent, parent::$common_attrib)) : |
| | | self::tag($this->_row_tagname(), array('class' => 'thead'), $rowcontent, parent::$common_attrib); |
| | | } |
| | | |
| | | foreach ($this->rows as $r => $row) { |
| | | $rowcontent = ''; |
| | | foreach ($row->cells as $c => $col) { |
| | | $rowcontent .= self::tag('td', $col->attrib, $col->content); |
| | | $rowcontent .= self::tag($this->_col_tagname(), $col->attrib, $col->content); |
| | | } |
| | | |
| | | if ($r < $this->rowindex || count($row->cells)) { |
| | | $tbody .= self::tag('tr', $row->attrib, $rowcontent, parent::$common_attrib); |
| | | $tbody .= self::tag($this->_row_tagname(), $row->attrib, $rowcontent, parent::$common_attrib); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | // add <tbody> |
| | | $this->content = $thead . self::tag('tbody', null, $tbody); |
| | | $this->content = $thead . ($this->tagname == 'table' ? self::tag('tbody', null, $tbody) : $tbody); |
| | | |
| | | unset($this->attrib['cols'], $this->attrib['rowsonly']); |
| | | return parent::show(); |
| | |
| | | $this->rowindex = 0; |
| | | } |
| | | |
| | | /** |
| | | * Getter for the corresponding tag name for table row elements |
| | | */ |
| | | private function _row_tagname() |
| | | { |
| | | static $row_tagnames = array('table' => 'tr', 'ul' => 'li', '*' => 'div'); |
| | | return $row_tagnames[$this->tagname] ?: $row_tagnames['*']; |
| | | } |
| | | |
| | | /** |
| | | * Getter for the corresponding tag name for table cell elements |
| | | */ |
| | | private function _col_tagname() |
| | | { |
| | | static $col_tagnames = array('table' => 'td', '*' => 'span'); |
| | | return $col_tagnames[$this->tagname] ?: $col_tagnames['*']; |
| | | } |
| | | |
| | | } |
| | |
| | | * List all active contact groups of this source |
| | | * |
| | | * @param string Optional search string to match group name |
| | | * @param int Matching mode: |
| | | * 0 - partial (*abc*), |
| | | * 1 - strict (=), |
| | | * 2 - prefix (abc*) |
| | | * |
| | | * @return array Indexed list of contact groups, each a hash array |
| | | */ |
| | | function list_groups($search = null) |
| | | function list_groups($search = null, $mode = 0) |
| | | { |
| | | /* empty for address books don't supporting groups */ |
| | | return array(); |
| | |
| | | * Add the given contact records the a certain group |
| | | * |
| | | * @param string Group identifier |
| | | * @param array List of contact identifiers to be added |
| | | * @param array|string List of contact identifiers to be added |
| | | * |
| | | * @return int Number of contacts added |
| | | */ |
| | | function add_to_group($group_id, $ids) |
| | |
| | | * Remove the given contact records from a certain group |
| | | * |
| | | * @param string Group identifier |
| | | * @param array List of contact identifiers to be removed |
| | | * @param array|string List of contact identifiers to be removed |
| | | * |
| | | * @return int Number of deleted group members |
| | | */ |
| | | function remove_from_group($group_id, $ids) |
| | |
| | | $out = array_merge($out, (array)$values); |
| | | } |
| | | else { |
| | | list($f, $type) = explode(':', $c); |
| | | list(, $type) = explode(':', $c); |
| | | $out[$type] = array_merge((array)$out[$type], (array)$values); |
| | | } |
| | | } |
| | |
| | | */ |
| | | public static function compose_contact_key($contact, $sort_col) |
| | | { |
| | | $key = $contact[$sort_col] . ':' . $row['sourceid']; |
| | | $key = $contact[$sort_col] . ':' . $contact['sourceid']; |
| | | |
| | | // add email to a key to not skip contacts with the same name (#1488375) |
| | | if (!empty($contact['email'])) { |
| | |
| | | |
| | | return $key; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Compare search value with contact data |
| | |
| | | * List all active contact groups of this source |
| | | * |
| | | * @param string Search string to match group name |
| | | * @param int Matching mode: |
| | | * 0 - partial (*abc*), |
| | | * 1 - strict (=), |
| | | * 2 - prefix (abc*) |
| | | * |
| | | * @return array Indexed list of contact groups, each a hash array |
| | | */ |
| | | function list_groups($search = null) |
| | | function list_groups($search = null, $mode = 0) |
| | | { |
| | | $results = array(); |
| | | |
| | | if (!$this->groups) |
| | | return $results; |
| | | |
| | | $sql_filter = $search ? " AND " . $this->db->ilike('name', '%'.$search.'%') : ''; |
| | | if ($search) { |
| | | switch (intval($mode)) { |
| | | case 1: |
| | | $sql_filter = $this->db->ilike('name', $search); |
| | | break; |
| | | case 2: |
| | | $sql_filter = $this->db->ilike('name', $search . '%'); |
| | | break; |
| | | default: |
| | | $sql_filter = $this->db->ilike('name', '%' . $search . '%'); |
| | | } |
| | | |
| | | $sql_filter = " AND $sql_filter"; |
| | | } |
| | | |
| | | $sql_result = $this->db->query( |
| | | "SELECT * FROM ".$this->db->table_name($this->db_groups). |
| | |
| | | * Add the given contact records the a certain group |
| | | * |
| | | * @param string Group identifier |
| | | * @param array List of contact identifiers to be added |
| | | * @param array|string List of contact identifiers to be added |
| | | * |
| | | * @return int Number of contacts added |
| | | */ |
| | | function add_to_group($group_id, $ids) |
| | |
| | | * Remove the given contact records from a certain group |
| | | * |
| | | * @param string Group identifier |
| | | * @param array List of contact identifiers to be removed |
| | | * @param array|string List of contact identifiers to be removed |
| | | * |
| | | * @return int Number of deleted group members |
| | | */ |
| | | function remove_from_group($group_id, $ids) |
| | |
| | | 'work_state' => 'region:work', |
| | | 'home_city_short' => 'locality:home', |
| | | 'home_state_short' => 'region:home', |
| | | |
| | | // Atmail |
| | | 'date_of_birth' => 'birthday', |
| | | 'email' => 'email:pref', |
| | | 'home_mobile' => 'phone:cell', |
| | | 'home_zip' => 'zipcode:home', |
| | | 'info' => 'notes', |
| | | 'user_photo' => 'photo', |
| | | 'url' => 'website:homepage', |
| | | 'work_company' => 'organization', |
| | | 'work_dept' => 'departament', |
| | | 'work_fax' => 'phone:work,fax', |
| | | 'work_mobile' => 'phone:work,cell', |
| | | 'work_title' => 'jobtitle', |
| | | 'work_zip' => 'zipcode:work', |
| | | ); |
| | | |
| | | /** |
| | |
| | | 'work_phone' => "Work Phone", |
| | | 'work_address' => "Work Address", |
| | | //'work_address_2' => "Work Address 2", |
| | | 'work_city' => "Work City", |
| | | 'work_country' => "Work Country", |
| | | 'work_state' => "Work State", |
| | | 'work_zipcode' => "Work ZipCode", |
| | | |
| | | // Atmail |
| | | 'date_of_birth' => "Date of Birth", |
| | | 'email' => "Email", |
| | | //'email_2' => "Email2", |
| | | //'email_3' => "Email3", |
| | | //'email_4' => "Email4", |
| | | //'email_5' => "Email5", |
| | | 'home_mobile' => "Home Mobile", |
| | | 'home_zip' => "Home Zip", |
| | | 'info' => "Info", |
| | | 'user_photo' => "User Photo", |
| | | 'url' => "URL", |
| | | 'work_company' => "Work Company", |
| | | 'work_dept' => "Work Dept", |
| | | 'work_fax' => "Work Fax", |
| | | 'work_mobile' => "Work Mobile", |
| | | 'work_title' => "Work Title", |
| | | 'work_zip' => "Work Zip", |
| | | ); |
| | | |
| | | protected $local_label_map = array(); |
| | |
| | | { |
| | | // convert to UTF-8 |
| | | $head = substr($csv, 0, 4096); |
| | | $fallback = rcube::get_instance()->config->get('default_charset', 'ISO-8859-1'); // fallback to Latin-1? |
| | | $charset = rcube_charset::detect($head, RCUBE_CHARSET); |
| | | $csv = rcube_charset::convert($csv, $charset); |
| | | $head = ''; |
| | |
| | | $this->map = array(); |
| | | |
| | | // Parse file |
| | | foreach (preg_split("/[\r\n]+/", $csv) as $i => $line) { |
| | | foreach (preg_split("/[\r\n]+/", $csv) as $line) { |
| | | $elements = $this->parse_line($line); |
| | | if (empty($elements)) { |
| | | continue; |
| | |
| | | if (!empty($this->local_label_map)) { |
| | | for ($i = 0; $i < $size; $i++) { |
| | | $label = $this->local_label_map[$elements[$i]]; |
| | | |
| | | // special localization label |
| | | if ($label && $label[0] == '_') { |
| | | $label = substr($label, 1); |
| | | } |
| | | |
| | | if ($label && !empty($this->csv2vcard_map[$label])) { |
| | | $map2[$i] = $this->csv2vcard_map[$label]; |
| | | } |
| | |
| | | $contact['birthday'] = $contact['birthday-y'] .'-' .$contact['birthday-m'] . '-' . $contact['birthday-d']; |
| | | } |
| | | |
| | | // Empty dates, e.g. "0/0/00", "0000-00-00 00:00:00" |
| | | foreach (array('birthday', 'anniversary') as $key) { |
| | | if (!empty($contact[$key]) && $contact[$key] == '0/0/00') { // @TODO: localization? |
| | | if (!empty($contact[$key])) { |
| | | $date = preg_replace('/[0[:^word:]]/', '', $contact[$key]); |
| | | if (empty($date)) { |
| | | unset($contact[$key]); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!empty($contact['gender']) && ($gender = strtolower($contact['gender']))) { |
| | | if (!in_array($gender, array('male', 'female'))) { |
| | |
| | | $dsn_string = $this->dsn_string($dsn); |
| | | $dsn_options = $this->dsn_options($dsn); |
| | | |
| | | if ($db_pconn) { |
| | | if ($this->db_pconn) { |
| | | $dsn_options[PDO::ATTR_PERSISTENT] = true; |
| | | } |
| | | |
| | |
| | | $this->db_error_msg = null; |
| | | |
| | | // send query |
| | | $query = $this->dbh->query($query); |
| | | $result = $this->dbh->query($query); |
| | | |
| | | if ($query === false) { |
| | | if ($result === false) { |
| | | $error = $this->dbh->errorInfo(); |
| | | $this->db_error = true; |
| | | $this->db_error_msg = sprintf('[%s] %s', $error[1], $error[2]); |
| | | |
| | | rcube::raise_error(array('code' => 500, 'type' => 'db', |
| | | 'line' => __LINE__, 'file' => __FILE__, |
| | | 'message' => $this->db_error_msg), true, false); |
| | | 'message' => $this->db_error_msg . " (SQL Query: $query)" |
| | | ), true, false); |
| | | } |
| | | |
| | | $this->last_result = $query; |
| | | $this->last_result = $result; |
| | | |
| | | return $query; |
| | | return $result; |
| | | } |
| | | |
| | | /** |
| | |
| | | $result[PDO::MYSQL_ATTR_FOUND_ROWS] = true; |
| | | |
| | | // Enable AUTOCOMMIT mode (#1488902) |
| | | $dsn_options[PDO::ATTR_AUTOCOMMIT] = true; |
| | | $result[PDO::ATTR_AUTOCOMMIT] = true; |
| | | |
| | | return $result; |
| | | } |
| | |
| | | |
| | | $result = $this->query('SHOW VARIABLES'); |
| | | |
| | | while ($sql_arr = $this->fetch_array($result)) { |
| | | while ($row = $this->fetch_array($result)) { |
| | | $this->variables[$row[0]] = $row[1]; |
| | | } |
| | | } |
| | |
| | | $quoted = ''; |
| | | $lines = explode('<br>', $a[2]); |
| | | |
| | | foreach ($lines as $n => $line) |
| | | foreach ($lines as $line) |
| | | $quoted .= '>'.$line.'<br>'; |
| | | |
| | | $body = $a[1].'<span class="quotes">'.$quoted.'</span>'.$a[3]; |
| | |
| | | // use memory less expensive (and quick) method for big result set |
| | | $index = clone $this->index('', $this->sort_field, $this->sort_order); |
| | | // get messages uids for one page... |
| | | $index->slice($start_msg, min($cnt-$from, $this->page_size)); |
| | | $index->slice($from, min($cnt-$from, $this->page_size)); |
| | | |
| | | if ($slice) { |
| | | $index->slice(-$slice, $slice); |
| | |
| | | */ |
| | | protected function search_index($folder, $criteria='ALL', $charset=NULL, $sort_field=NULL) |
| | | { |
| | | $orig_criteria = $criteria; |
| | | |
| | | if (!$this->check_connection()) { |
| | | if ($this->threading) { |
| | | return new rcube_result_thread(); |
| | |
| | | |
| | | // filter folders list according to rights requirements |
| | | if ($rights && $this->get_capability('ACL')) { |
| | | $a_folders = $this->filter_rights($a_folders, $rights); |
| | | $a_mboxes = $this->filter_rights($a_mboxes, $rights); |
| | | } |
| | | |
| | | // filter folders and sort them |
| | |
| | | */ |
| | | private function list_folders_update(&$result, $type = null) |
| | | { |
| | | $delim = $this->get_hierarchy_delimiter(); |
| | | $namespace = $this->get_namespace(); |
| | | $search = array(); |
| | | |
| | |
| | | $delimiter = $this->get_hierarchy_delimiter(); |
| | | |
| | | // find default folders and skip folders starting with '.' |
| | | foreach ($a_folders as $i => $folder) { |
| | | foreach ($a_folders as $folder) { |
| | | if ($folder[0] == '.') { |
| | | continue; |
| | | } |
| | |
| | | ." AND uid = ?", |
| | | $flags, $msg, $this->userid, $mailbox, (int) $message->uid); |
| | | |
| | | if ($this->db->affected_rows()) { |
| | | if ($this->db->affected_rows($res)) { |
| | | return; |
| | | } |
| | | } |
| | |
| | | $uids, true, array('FLAGS'), $index['modseq'], $qresync); |
| | | |
| | | if (!empty($result)) { |
| | | foreach ($result as $id => $msg) { |
| | | foreach ($result as $msg) { |
| | | $uid = $msg->uid; |
| | | // Remove deleted message |
| | | if ($this->skip_deleted && !empty($msg->flags['DELETED'])) { |
| | |
| | | } |
| | | |
| | | if ($this->prefs['timeout'] <= 0) { |
| | | $this->prefs['timeout'] = ini_get('default_socket_timeout'); |
| | | $this->prefs['timeout'] = max(0, intval(ini_get('default_socket_timeout'))); |
| | | } |
| | | |
| | | // Connect |
| | |
| | | } |
| | | |
| | | if (!$this->data['READ-WRITE']) { |
| | | $this->setError(self::ERROR_READONLY, "Mailbox is read-only", 'EXPUNGE'); |
| | | $this->setError(self::ERROR_READONLY, "Mailbox is read-only"); |
| | | return false; |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | if (!empty($criteria)) { |
| | | $modseq = stripos($criteria, 'MODSEQ') !== false; |
| | | $params .= ($params ? ' ' : '') . $criteria; |
| | | } |
| | | else { |
| | |
| | | if ($skip_deleted && preg_match('/FLAGS \(([^)]+)\)/', $line, $matches)) { |
| | | $flags = explode(' ', strtoupper($matches[1])); |
| | | if (in_array('\\DELETED', $flags)) { |
| | | $deleted[$id] = $id; |
| | | continue; |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | if (!$this->data['READ-WRITE']) { |
| | | $this->setError(self::ERROR_READONLY, "Mailbox is read-only", 'STORE'); |
| | | $this->setError(self::ERROR_READONLY, "Mailbox is read-only"); |
| | | return false; |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | if (!$this->data['READ-WRITE']) { |
| | | $this->setError(self::ERROR_READONLY, "Mailbox is read-only", 'STORE'); |
| | | $this->setError(self::ERROR_READONLY, "Mailbox is read-only"); |
| | | return false; |
| | | } |
| | | |
| | |
| | | // create array with header field:data |
| | | if (!empty($headers)) { |
| | | $headers = explode("\n", trim($headers)); |
| | | foreach ($headers as $hid => $resln) { |
| | | foreach ($headers as $resln) { |
| | | if (ord($resln[0]) <= 32) { |
| | | $lines[$ln] .= (empty($lines[$ln]) ? '' : "\n") . trim($resln); |
| | | } else { |
| | |
| | | } |
| | | } |
| | | |
| | | while (list($lines_key, $str) = each($lines)) { |
| | | foreach ($lines as $str) { |
| | | list($field, $string) = explode(':', $str, 2); |
| | | |
| | | $field = strtolower($field); |
| | |
| | | $tokens = $this->tokenizeResponse(preg_replace('/(^\(|\)$)/', '', $line)); |
| | | |
| | | for ($i=0; $i<count($tokens); $i+=2) { |
| | | if (preg_match('/^(BODY|BINARY)/i', $token)) { |
| | | if (preg_match('/^(BODY|BINARY)/i', $tokens[$i])) { |
| | | $result = $tokens[$i+1]; |
| | | $found = true; |
| | | break; |
| | |
| | | |
| | | if (is_array($element)) { |
| | | reset($element); |
| | | while (list($key, $value) = each($element)) { |
| | | foreach ($element as $value) { |
| | | $string .= ' ' . self::r_implode($value); |
| | | } |
| | | } |
| | |
| | | // Build sub_fields filter |
| | | if (!empty($this->prop['sub_fields']) && is_array($this->prop['sub_fields'])) { |
| | | $this->sub_filter = ''; |
| | | foreach ($this->prop['sub_fields'] as $attr => $class) { |
| | | foreach ($this->prop['sub_fields'] as $class) { |
| | | if (!empty($class)) { |
| | | $class = is_array($class) ? array_pop($class) : $class; |
| | | $this->sub_filter .= '(objectClass=' . $class . ')'; |
| | |
| | | $mail_field = $this->fieldmap['email']; |
| | | |
| | | // try to extract surname and firstname from displayname |
| | | $reverse_map = array_flip($this->fieldmap); |
| | | $name_parts = preg_split('/[\s,.]+/', $save_data['name']); |
| | | |
| | | if ($sn_field && $missing[$sn_field]) { |
| | |
| | | // Remove attributes that need to be added separately (child objects) |
| | | $xfields = array(); |
| | | if (!empty($this->prop['sub_fields']) && is_array($this->prop['sub_fields'])) { |
| | | foreach ($this->prop['sub_fields'] as $xf => $xclass) { |
| | | foreach (array_keys($this->prop['sub_fields']) as $xf) { |
| | | if (!empty($newentry[$xf])) { |
| | | $xfields[$xf] = $newentry[$xf]; |
| | | unset($newentry[$xf]); |
| | |
| | | } |
| | | } |
| | | |
| | | foreach ($this->fieldmap as $col => $fld) { |
| | | foreach ($this->fieldmap as $fld) { |
| | | if ($fld) { |
| | | $val = $ldap_data[$fld]; |
| | | $old = $old_data[$fld]; |
| | |
| | | */ |
| | | protected function add_autovalues(&$attrs) |
| | | { |
| | | if (empty($this->prop['autovalues'])) { |
| | | return; |
| | | } |
| | | |
| | | $attrvals = array(); |
| | | foreach ($attrs as $k => $v) { |
| | | $attrvals['{'.$k.'}'] = is_array($v) ? $v[0] : $v; |
| | |
| | | |
| | | foreach ((array)$this->prop['autovalues'] as $lf => $templ) { |
| | | if (empty($attrs[$lf])) { |
| | | // replace {attr} placeholders with concrete attribute values |
| | | $templ = preg_replace('/\{\w+\}/', '', strtr($templ, $attrvals)); |
| | | if (strpos($templ, '(') !== false) { |
| | | // replace {attr} placeholders with (escaped!) attribute values to be safely eval'd |
| | | $code = preg_replace('/\{\w+\}/', '', strtr($templ, array_map('addslashes', $attrvals))); |
| | | $fn = create_function('', "return ($code);"); |
| | | if (!$fn) { |
| | | rcube::raise_error(array( |
| | | 'code' => 505, 'type' => 'php', |
| | | 'file' => __FILE__, 'line' => __LINE__, |
| | | 'message' => "Expression parse error on: ($code)"), true, false); |
| | | continue; |
| | | } |
| | | |
| | | if (strpos($templ, '(') !== false) |
| | | $attrs[$lf] = eval("return ($templ);"); |
| | | else |
| | | $attrs[$lf] = $templ; |
| | | $attrs[$lf] = $fn(); |
| | | } |
| | | else { |
| | | // replace {attr} placeholders with concrete attribute values |
| | | $attrs[$lf] = preg_replace('/\{\w+\}/', '', strtr($templ, $attrvals)); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | * List all active contact groups of this source |
| | | * |
| | | * @param string Optional search string to match group name |
| | | * @param int Matching mode: |
| | | * 0 - partial (*abc*), |
| | | * 1 - strict (=), |
| | | * 2 - prefix (abc*) |
| | | * |
| | | * @return array Indexed list of contact groups, each a hash array |
| | | */ |
| | | function list_groups($search = null) |
| | | function list_groups($search = null, $mode = 0) |
| | | { |
| | | if (!$this->groups) |
| | | return array(); |
| | |
| | | |
| | | $groups = array(); |
| | | if ($search) { |
| | | $search = mb_strtolower($search); |
| | | foreach ($group_cache as $group) { |
| | | if (strpos(mb_strtolower($group['name']), $search) !== false) |
| | | if ($this->compare_search_value('name', $group['name'], $search, $mode)) { |
| | | $groups[] = $group; |
| | | } |
| | | } |
| | | } |
| | | else |
| | |
| | | $vlv_active = $this->_vlv_set_controls($this->prop['groups'], $vlv_page+1, $page_size); |
| | | } |
| | | |
| | | $function = $this->_scope2func($this->prop['groups']['scope'], $ns_function); |
| | | $function = $this->_scope2func($this->prop['groups']['scope']); |
| | | $res = @$function($this->conn, $base_dn, $filter, array_unique(array('dn', 'objectClass', $name_attr, $email_attr, $sort_attr))); |
| | | if ($res === false) |
| | | { |
| | |
| | | * Add the given contact records the a certain group |
| | | * |
| | | * @param string Group identifier |
| | | * @param array List of contact identifiers to be added |
| | | * @param array|string List of contact identifiers to be added |
| | | * |
| | | * @return int Number of contacts added |
| | | */ |
| | | function add_to_group($group_id, $contact_ids) |
| | |
| | | $group_name = $group_cache[$group_id]['name']; |
| | | $member_attr = $group_cache[$group_id]['member_attr']; |
| | | $group_dn = "cn=$group_name,$base_dn"; |
| | | |
| | | $new_attrs = array(); |
| | | |
| | | foreach ($contact_ids as $id) |
| | | $new_attrs[$member_attr][] = self::dn_decode($id); |
| | | |
| | |
| | | |
| | | $this->cache->remove('groups'); |
| | | |
| | | return count($new_attrs['member']); |
| | | return count($new_attrs[$member_attr]); |
| | | } |
| | | |
| | | /** |
| | | * Remove the given contact records from a certain group |
| | | * |
| | | * @param string Group identifier |
| | | * @param array List of contact identifiers to be removed |
| | | * @param array|string List of contact identifiers to be removed |
| | | * |
| | | * @return int Number of deleted group members |
| | | */ |
| | | function remove_from_group($group_id, $contact_ids) |
| | |
| | | if (($group_cache = $this->cache->get('groups')) === null) |
| | | $group_cache = $this->_fetch_groups(); |
| | | |
| | | if (!is_array($contact_ids)) |
| | | $contact_ids = explode(',', $contact_ids); |
| | | |
| | | $base_dn = $this->groups_base_dn; |
| | | $group_name = $group_cache[$group_id]['name']; |
| | | $member_attr = $group_cache[$group_id]['member_attr']; |
| | | $group_dn = "cn=$group_name,$base_dn"; |
| | | |
| | | $del_attrs = array(); |
| | | foreach (explode(",", $contact_ids) as $id) |
| | | |
| | | foreach ($contact_ids as $id) |
| | | $del_attrs[$member_attr][] = self::dn_decode($id); |
| | | |
| | | if (!$this->ldap_mod_del($group_dn, $del_attrs)) { |
| | |
| | | |
| | | $this->cache->remove('groups'); |
| | | |
| | | return count($del_attrs['member']); |
| | | return count($del_attrs[$member_attr]); |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | // parse headers from message/rfc822 part |
| | | if (!isset($structure->headers['subject']) && !isset($structure->headers['from'])) { |
| | | list($headers, $dump) = explode("\r\n\r\n", $this->get_part_content($structure->mime_id, null, true, 32768)); |
| | | list($headers, ) = explode("\r\n\r\n", $this->get_part_content($structure->mime_id, null, true, 32768)); |
| | | $structure->headers = rcube_mime::parse_headers($headers); |
| | | } |
| | | } |
| | |
| | | * @param int $max List only this number of addresses |
| | | * @param boolean $decode Decode address strings |
| | | * @param string $fallback Fallback charset if none specified |
| | | * @param boolean $addronly Return flat array with e-mail addresses only |
| | | * |
| | | * @return array Indexed list of addresses |
| | | */ |
| | | static function decode_address_list($input, $max = null, $decode = true, $fallback = null) |
| | | static function decode_address_list($input, $max = null, $decode = true, $fallback = null, $addronly = false) |
| | | { |
| | | $a = self::parse_address_list($input, $decode, $fallback); |
| | | $out = array(); |
| | |
| | | foreach ($a as $val) { |
| | | $j++; |
| | | $address = trim($val['address']); |
| | | $name = trim($val['name']); |
| | | |
| | | if ($addronly) { |
| | | $out[$j] = $address; |
| | | } |
| | | else { |
| | | $name = trim($val['name']); |
| | | if ($name && $address && $name != $address) |
| | | $string = sprintf('%s <%s>', preg_match("/$special_chars/", $name) ? '"'.addcslashes($name, '"').'"' : $name, $address); |
| | | else if ($address) |
| | |
| | | else if ($name) |
| | | $string = $name; |
| | | |
| | | $out[$j] = array( |
| | | 'name' => $name, |
| | | 'mailto' => $address, |
| | | 'string' => $string |
| | | ); |
| | | $out[$j] = array('name' => $name, 'mailto' => $address, 'string' => $string); |
| | | } |
| | | |
| | | if ($max && $j==$max) |
| | | break; |
| | |
| | | $q_level = 0; |
| | | |
| | | foreach ($text as $idx => $line) { |
| | | if ($line[0] == '>') { |
| | | // remove quote chars, store level in $q |
| | | $line = preg_replace('/^>+/', '', $line, -1, $q); |
| | | if (preg_match('/^(>+)/', $line, $m)) { |
| | | // remove quote chars |
| | | $q = strlen($m[1]); |
| | | $line = preg_replace('/^>+/', '', $line); |
| | | // remove (optional) space-staffing |
| | | $line = preg_replace('/^ /', '', $line); |
| | | |
| | |
| | | |
| | | foreach ($text as $idx => $line) { |
| | | if ($line != '-- ') { |
| | | if ($line[0] == '>') { |
| | | // remove quote chars, store level in $level |
| | | $line = preg_replace('/^>+/', '', $line, -1, $level); |
| | | if (preg_match('/^(>+)/', $line, $m)) { |
| | | // remove quote chars |
| | | $level = strlen($m[1]); |
| | | $line = preg_replace('/^>+/', '', $line); |
| | | // remove (optional) space-staffing and spaces before the line end |
| | | $line = preg_replace('/(^ | +$)/', '', $line); |
| | | $prefix = str_repeat('>', $level) . ' '; |
| | |
| | | $cutLength = $spacePos + 1; |
| | | } |
| | | else { |
| | | $subString = $string; |
| | | $cutLength = null; |
| | | $subString = $substr_func($string, 0, $breakPos, $charset); |
| | | $cutLength = $breakPos + 1; |
| | | } |
| | | } |
| | | else { |
| | |
| | | header("Cache-Control: private, must-revalidate"); |
| | | } |
| | | else { |
| | | header("Cache-Control: private, no-cache, must-revalidate, post-check=0, pre-check=0"); |
| | | header("Cache-Control: private, no-cache, no-store, must-revalidate, post-check=0, pre-check=0"); |
| | | header("Pragma: no-cache"); |
| | | } |
| | | } |
| | |
| | | $doc->loadXML($file); |
| | | $xpath = new DOMXPath($doc); |
| | | $xpath->registerNamespace('rc', "http://pear.php.net/dtd/package-2.0"); |
| | | $data = array(); |
| | | |
| | | // XPaths of plugin metadata elements |
| | | $metadata = array( |
| | |
| | | } |
| | | |
| | | // try to connect to server and exit on failure |
| | | $result = $this->conn->connect($smtp_timeout); |
| | | $result = $this->conn->connect($CONFIG['smtp_timeout']); |
| | | |
| | | if (PEAR::isError($result)) { |
| | | $this->response[] = "Connection failed: ".$result->getMessage(); |
| | |
| | | $recipients = rcube_utils::explode_quoted_string(',', $recipients); |
| | | |
| | | reset($recipients); |
| | | while (list($k, $recipient) = each($recipients)) { |
| | | foreach ($recipients as $recipient) { |
| | | $a = rcube_utils::explode_quoted_string(' ', $recipient); |
| | | while (list($k2, $word) = each($a)) { |
| | | foreach ($a as $word) { |
| | | if (strpos($word, "@") > 0 && $word[strlen($word)-1] != '"') { |
| | | $word = preg_replace('/^<|>$/', '', trim($word)); |
| | | if (in_array($word, $addresses) === false) { |
| | |
| | | if (!$this->plink) { |
| | | if (!extension_loaded('pspell')) { |
| | | $this->error = "Pspell extension not available"; |
| | | rcube::raise_error(array( |
| | | 'code' => 500, 'type' => 'php', |
| | | 'file' => __FILE__, 'line' => __LINE__, |
| | | 'message' => $this->error), true, false); |
| | | |
| | | return; |
| | | } |
| | | |
| | |
| | | fclose($fp); |
| | | } |
| | | |
| | | // parse HTTP response |
| | | if (preg_match('!^HTTP/1.\d (\d+)(.+)!', $store, $m)) { |
| | | $http_status = $m[1]; |
| | | if ($http_status != '200') |
| | | $this->error = 'HTTP ' . $m[1] . $m[2]; |
| | | } |
| | | |
| | | if (!$store) { |
| | | $this->error = "Empty result from spelling engine"; |
| | | } |
| | | else if (preg_match('/<spellresult error="([^"]+)"/', $store, $m)) { |
| | | $this->error = "Error code $m[1] returned"; |
| | | } |
| | | |
| | | preg_match_all('/<c o="([^"]*)" l="([^"]*)" s="([^"]*)">([^<]*)<\/c>/', $store, $matches, PREG_SET_ORDER); |
| | |
| | | |
| | | if (empty($plugin['abort'])) { |
| | | $dict = array(); |
| | | $this->rc->db->query( |
| | | $sql_result = $this->rc->db->query( |
| | | "SELECT data FROM ".$this->rc->db->table_name('dictionary') |
| | | ." WHERE user_id ". ($plugin['userid'] ? "= ".$this->rc->db->quote($plugin['userid']) : "IS NULL") |
| | | ." AND " . $this->rc->db->quoteIdentifier('language') . " = ?", |
| | |
| | | $out = array(); |
| | | $src = $mode == self::INPUT_GET ? $_GET : ($mode == self::INPUT_POST ? $_POST : $_REQUEST); |
| | | |
| | | foreach ($src as $key => $value) { |
| | | foreach (array_keys($src) as $key) { |
| | | $fname = $key[0] == '_' ? substr($key, 1) : $key; |
| | | if ($ignore && !preg_match('/^(' . $ignore . ')$/', $fname)) { |
| | | $out[$fname] = self::get_input_value($key, $mode); |
| | |
| | | */ |
| | | public function __construct($vcard = null, $charset = RCUBE_CHARSET, $detect = false, $fieldmap = array()) |
| | | { |
| | | if (!empty($fielmap)) { |
| | | if (!empty($fieldmap)) { |
| | | $this->extend_fieldmap($fieldmap); |
| | | } |
| | | |
| | |
| | | $vcard_block = ''; |
| | | $in_vcard_block = false; |
| | | |
| | | foreach (preg_split("/[\r\n]+/", $data) as $i => $line) { |
| | | foreach (preg_split("/[\r\n]+/", $data) as $line) { |
| | | if ($in_vcard_block && !empty($line)) { |
| | | $vcard_block .= $line . "\n"; |
| | | } |
| | |
| | | } |
| | | return $result; |
| | | } |
| | | |
| | | $s = strtr($s, $rep2); |
| | | } |
| | | |
| | | return strtr($s, array("\r" => '', '\\\\' => '\\', '\n' => "\n", '\N' => "\n", '\,' => ',', '\;' => ';')); |
| | | // some implementations (GMail) use non-standard backslash before colon (#1489085) |
| | | // we will handle properly any backslashed character - removing dummy backslahes |
| | | // return strtr($s, array("\r" => '', '\\\\' => '\\', '\n' => "\n", '\N' => "\n", '\,' => ',', '\;' => ';')); |
| | | |
| | | $s = str_replace("\r", '', $s); |
| | | $pos = 0; |
| | | |
| | | while (($pos = strpos($s, '\\', $pos)) !== false) { |
| | | $next = substr($s, $pos + 1, 1); |
| | | if ($next == 'n' || $next == 'N') { |
| | | $s = substr_replace($s, "\n", $pos, 2); |
| | | } |
| | | else { |
| | | $s = substr_replace($s, '', $pos, 1); |
| | | } |
| | | |
| | | $pos += 1; |
| | | } |
| | | |
| | | return $s; |
| | | } |
| | | |
| | | /** |
| | |
| | | function loadCharset($charset) { |
| | | |
| | | $charset = preg_replace(array('/^WINDOWS-*125([0-8])$/', '/^CP-/'), array('CP125\\1', 'CP'), $charset); |
| | | if (isset($aliases[$charset])) |
| | | $charset = $aliases[$charset]; |
| | | if (isset($this->aliases[$charset])) |
| | | $charset = $this->aliases[$charset]; |
| | | |
| | | $this->charset = $charset; |
| | | |
| | |
| | | $labels['signature'] = 'Signature'; |
| | | $labels['dstactive'] = 'Summer time'; |
| | | $labels['showinextwin'] = 'Open message in a new window'; |
| | | $labels['showemail'] = 'Show email address with display name'; |
| | | $labels['composeextwin'] = 'Compose in a new window'; |
| | | $labels['htmleditor'] = 'Compose HTML messages'; |
| | | $labels['htmlonreply'] = 'on reply to HTML message only'; |
| | |
| | | $map['work_address'] = "Work Address"; |
| | | $map['work_country'] = "Work Country"; |
| | | $map['work_zipcode'] = "Work ZipCode"; |
| | | |
| | | // Atmail |
| | | $map['date_of_birth'] = "Date of Birth"; |
| | | $map['email'] = "Email"; |
| | | $map['home_mobile'] = "Home Mobile"; |
| | | $map['home_zip'] = "Home Zip"; |
| | | $map['info'] = "Info"; |
| | | $map['user_photo'] = "User Photo"; |
| | | $map['url'] = "URL"; |
| | | $map['work_city'] = "Work City"; |
| | | $map['work_company'] = "Work Company"; |
| | | $map['work_dept'] = "Work Dept"; |
| | | $map['work_fax'] = "Work Fax"; |
| | | $map['work_mobile'] = "Work Mobile"; |
| | | $map['work_state'] = "Work State"; |
| | | $map['work_title'] = "Work Title"; |
| | | $map['work_zip'] = "Work Zip"; |
| | |
| | | $labels['htmlonreply'] = 'on reply to HTML message'; |
| | | $labels['htmlonreplyandforward'] = 'on forward or reply to HTML message'; |
| | | $labels['htmlsignature'] = 'HTML signature'; |
| | | $labels['showemail'] = 'Show email address with display name'; |
| | | $labels['previewpane'] = 'Show preview pane'; |
| | | $labels['skin'] = 'Interface skin'; |
| | | $labels['logoutclear'] = 'Clear Trash on logout'; |
New file |
| | |
| | | <?php |
| | | |
| | | /* |
| | | +-----------------------------------------------------------------------+ |
| | | | localization/<lang>/csv2vcard.inc | |
| | | | | |
| | | | Localization file of the Roundcube Webmail client | |
| | | | Copyright (C) 2005-2013, The Roundcube Dev Team | |
| | | | | |
| | | | Licensed under the GNU General Public License version 3 or | |
| | | | any later version with exceptions for skins & plugins. | |
| | | | See the README file for a full license statement. | |
| | | | | |
| | | +-----------------------------------------------------------------------+ |
| | | | Author: Aleksander Machniak <alec@alec.pl> | |
| | | +-----------------------------------------------------------------------+ |
| | | */ |
| | | |
| | | // This is a list of CSV column names specified in CSV file header |
| | | // These must be original texts used in Outlook/Thunderbird exported csv files |
| | | // Encoding UTF-8 |
| | | |
| | | $map = array(); |
| | | |
| | | // MS Outlook 2010 |
| | | $map['anniversary'] = "Anniversaire de mariage ou fête"; |
| | | $map['assistants_name'] = "Nom de l''assistant(e)"; |
| | | $map['assistants_phone'] = "Téléphone de l''assistant(e)"; |
| | | $map['birthday'] = "Anniversaire"; |
| | | $map['business_city'] = "Ville (bureau)"; |
| | | $map['business_countryregion'] = "Pays/Région (bureau)"; |
| | | $map['business_fax'] = "Télécopie (bureau)"; |
| | | $map['business_phone'] = "Téléphone (bureau)"; |
| | | $map['business_phone_2'] = "Téléphone 2 (bureau)"; |
| | | $map['business_postal_code'] = "Code postal (bureau)"; |
| | | $map['business_state'] = "Dép/Région (bureau)"; |
| | | $map['business_street'] = "Rue (bureau)"; |
| | | $map['car_phone'] = "Téléphone (voiture)"; |
| | | $map['categories'] = "Catégories"; |
| | | $map['company'] = "Société"; |
| | | $map['department'] = "Service"; |
| | | $map['email_address'] = "Adresse de messagerie"; |
| | | $map['first_name'] = "Prénom"; |
| | | $map['gender'] = "Sexe"; |
| | | $map['home_city'] = "Ville (domicile)"; |
| | | $map['home_countryregion'] = "Pays/Région (domicile)"; |
| | | $map['home_fax'] = "Télécopie (domicile)"; |
| | | $map['home_phone'] = "Téléphone (domicile)"; |
| | | $map['home_phone_2'] = "Téléphone 2 (domicile)"; |
| | | $map['home_postal_code'] = "Code postal (domicile)"; |
| | | $map['home_state'] = "Dép/Région (domicile)"; |
| | | $map['home_street'] = "Rue (domicile)"; |
| | | $map['job_title'] = "Profession"; |
| | | $map['last_name'] = "Nom"; |
| | | $map['managers_name'] = "Manager's Name"; |
| | | $map['middle_name'] = "Deuxième prénom"; |
| | | $map['mobile_phone'] = "Tél. mobile"; |
| | | $map['notes'] = "Notes"; |
| | | $map['other_city'] = "Ville (autre)"; |
| | | $map['other_countryregion'] = "Pays/Région (autre)"; |
| | | $map['other_fax'] = "Télécopie (autre)"; |
| | | $map['other_phone'] = "Téléphone (autre)"; |
| | | $map['other_postal_code'] = "Code postal (autre)"; |
| | | $map['other_state'] = "Dép/Région (autre)"; |
| | | $map['other_street'] = "Rue (autre)"; |
| | | $map['pager'] = "Récepteur de radiomessagerie"; |
| | | $map['primary_phone'] = "Téléphone principal"; |
| | | $map['spouse'] = "Conjoint(e)"; |
| | | $map['suffix'] = "Suffixe"; |
| | | $map['title'] = "Titre"; |
| | | $map['web_page'] = "Page Web"; |
| | | |
| | | // Thunderbird |
| | | $map['birth_day'] = "Jour"; |
| | | $map['birth_month'] = "Mois"; |
| | | $map['birth_year'] = "Année de naissance"; |
| | | $map['display_name'] = "Nom à afficher"; |
| | | $map['fax_number'] = "Fax"; |
| | | $map['home_address'] = "Adresse privée"; |
| | | $map['home_country'] = "Région"; |
| | | $map['home_zipcode'] = "Code postal"; |
| | | $map['mobile_number'] = "Portable"; |
| | | $map['nickname'] = "Surnom"; |
| | | $map['organization'] = "Société"; |
| | | $map['pager_number'] = "Pager"; |
| | | $map['primary_email'] = "Adresse électronique principale"; |
| | | $map['secondary_email'] = "Adresse électronique secondaire"; |
| | | $map['web_page_1'] = "Site Web 1"; |
| | | $map['web_page_2'] = "Site Web 2"; |
| | | $map['work_phone'] = "Tél. professionnel"; |
| | | $map['work_address'] = "Adresse professionnelle"; |
| | | $map['work_country'] = "Région"; |
| | | $map['work_zipcode'] = "Code postal"; |
| | | |
| | | // Other |
| | | $map['_home_city'] = "Ville"; |
| | |
| | | // get address book name (for display) |
| | | if ($abook && $_SESSION['addressbooks_count'] > 1) { |
| | | $name = $abook->get_name(); |
| | | if (!$name && $source == 0) { |
| | | if (!$name) { |
| | | $name = rcube_label('personaladrbook'); |
| | | } |
| | | $OUTPUT->set_env('sourcename', html_entity_decode($name, ENT_COMPAT, 'UTF-8')); |
| | |
| | | $attrib['id'] = 'rcmdirectorylist'; |
| | | |
| | | $out = ''; |
| | | $local_id = '0'; |
| | | $jsdata = array(); |
| | | |
| | | $line_templ = html::tag('li', array( |
| | |
| | | |
| | | $groups_html = ''; |
| | | $groups = $RCMAIL->get_address_book($args['source'])->list_groups(); |
| | | $js_id = $RCMAIL->JQ($args['source']); |
| | | |
| | | if (!empty($groups)) { |
| | | $line_templ = html::tag('li', array( |
| | |
| | | $is_collapsed = strpos($RCMAIL->config->get('collapsed_abooks',''), '&'.rawurlencode($args['source']).'&') !== false; |
| | | $args['out'] .= html::div('treetoggle ' . ($is_collapsed ? 'collapsed' : 'expanded'), ' '); |
| | | |
| | | $jsdata = array(); |
| | | foreach ($groups as $group) { |
| | | $groups_html .= sprintf($line_templ, |
| | | rcube_utils::html_identifier('G' . $args['source'] . $group['ID'], true), |
| | |
| | | } |
| | | |
| | | $args['out'] .= html::tag('ul', |
| | | array('class' => 'groups', 'style' => ($is_collapsed ? "display:none;" : null)), |
| | | array('class' => 'groups', 'style' => ($is_collapsed || empty($groups) ? "display:none;" : null)), |
| | | $groups_html); |
| | | |
| | | return $args; |
| | |
| | | |
| | | $content = html::p(null, rcube_label(array( |
| | | 'name' => 'importconfirm', |
| | | 'nr' => $IMORT_STATS->inserted, |
| | | 'nr' => $IMPORT_STATS->inserted, |
| | | 'vars' => $vars, |
| | | )) . ($IMPORT_STATS->names ? ':' : '.')); |
| | | |
| | |
| | | if ($IMPORT_STATS->skipped) { |
| | | $content .= html::p(null, rcube_label(array( |
| | | 'name' => 'importconfirmskipped', |
| | | 'nr' => $IMORT_STATS->skipped, |
| | | 'nr' => $IMPORT_STATS->skipped, |
| | | 'vars' => $vars, |
| | | )) . ':'); |
| | | $content .= html::p('em', join(', ', array_map('Q', $IMPORT_STATS->skipped_names))); |
| | |
| | | return false; |
| | | } |
| | | |
| | | $microformats = array('name' => 'fn', 'email' => 'email'); |
| | | |
| | | $form = array( |
| | | 'head' => array( // section 'head' is magic! |
| | | 'content' => array( |
| | |
| | | } |
| | | |
| | | |
| | | function rcmail_render_email_value($email, $col) |
| | | function rcmail_render_email_value($email) |
| | | { |
| | | return html::a(array( |
| | | 'href' => 'mailto:' . $email, |
| | |
| | | } |
| | | |
| | | |
| | | function rcmail_render_url_value($url, $col) |
| | | function rcmail_render_url_value($url) |
| | | { |
| | | $prefix = preg_match('!^(http|ftp)s?://!', $url) ? '' : 'http://'; |
| | | return html::a(array( |
| | |
| | | } |
| | | |
| | | $hiddenfields = new html_hiddenfield(array('name' => '_source', 'value' => get_input_value('_source', RCUBE_INPUT_GPC))); |
| | | $hiddenfields->add(array('name' => '_cid', 'value' => $record['ID'])); |
| | | $hiddenfields->add(array('name' => '_cid', 'value' => $contact_id)); |
| | | |
| | | $form_start = $RCMAIL->output->request_form(array( |
| | | 'name' => "form", 'method' => "post", |
| | |
| | | |
| | | // also list matching contact groups |
| | | if ($abook->groups && count($contacts) < $MAXNUM) { |
| | | foreach ($abook->list_groups($search) as $group) { |
| | | foreach ($abook->list_groups($search, $mode) as $group) { |
| | | $abook->reset(); |
| | | $abook->set_group($group['ID']); |
| | | $group_prop = $abook->get_group($group['ID']); |
| | |
| | | $fvalue .= $v; |
| | | if ($v = $MESSAGE->headers->cc) |
| | | $fvalue .= (!empty($fvalue) ? $separator : '') . $v; |
| | | if ($v = $MESSAGE->headers->get('Sender', false)) |
| | | $fvalue .= (!empty($fvalue) ? $separator : '') . $v; |
| | | |
| | | // When To: and Reply-To: are the same we add From: address to the list (#1489037) |
| | | if ($v = $MESSAGE->headers->from) { |
| | | $from = rcube_mime::decode_address_list($v, null, false, $MESSAGE->headers->charset, true); |
| | | $to = rcube_mime::decode_address_list($MESSAGE->headers->to, null, false, $MESSAGE->headers->charset, true); |
| | | $replyto = rcube_mime::decode_address_list($MESSAGE->headers->replyto, null, false, $MESSAGE->headers->charset, true); |
| | | |
| | | if (count($replyto) && !count(array_diff($to, $replyto)) && count(array_diff($from, $to))) { |
| | | $fvalue .= (!empty($fvalue) ? $separator : '') . $v; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | else if (in_array($compose_mode, array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT))) { |
| | |
| | | { |
| | | global $MESSAGE; |
| | | |
| | | list($form_start, $form_end) = get_form_tags($attrib); |
| | | list($form_start,) = get_form_tags($attrib); |
| | | |
| | | $out = ''; |
| | | $part = strtolower($attrib['part']); |
| | |
| | | |
| | | function rcmail_compose_header_from($attrib) |
| | | { |
| | | global $MESSAGE, $OUTPUT, $RCMAIL, $compose_mode; |
| | | global $MESSAGE, $OUTPUT, $RCMAIL, $COMPOSE, $compose_mode; |
| | | |
| | | // pass the following attributes to the form class |
| | | $field_attrib = array('name' => '_from'); |
| | |
| | | |
| | | function rcmail_prepare_message_body() |
| | | { |
| | | global $RCMAIL, $MESSAGE, $COMPOSE, $compose_mode, $LINE_LENGTH, $HTML_MODE; |
| | | global $RCMAIL, $MESSAGE, $COMPOSE, $compose_mode, $HTML_MODE; |
| | | |
| | | // use posted message body |
| | | if (!empty($_POST['_message'])) { |
| | |
| | | |
| | | function rcmail_compose_part_body($part, $isHtml = false) |
| | | { |
| | | global $RCMAIL, $MESSAGE, $compose_mode; |
| | | global $RCMAIL, $MESSAGE, $LINE_LENGTH, $compose_mode; |
| | | |
| | | // Check if we have enough memory to handle the message in it |
| | | // #1487424: we need up to 10x more memory than the body |
| | |
| | | |
| | | function rcmail_compose_body($attrib) |
| | | { |
| | | global $RCMAIL, $CONFIG, $OUTPUT, $MESSAGE, $compose_mode, $LINE_LENGTH, $HTML_MODE, $MESSAGE_BODY; |
| | | global $RCMAIL, $CONFIG, $OUTPUT, $MESSAGE, $compose_mode, $HTML_MODE, $MESSAGE_BODY; |
| | | |
| | | list($form_start, $form_end) = get_form_tags($attrib); |
| | | unset($attrib['form']); |
| | |
| | | $cid_map = rcmail_write_compose_attachments($MESSAGE, $bodyIsHtml); |
| | | |
| | | $date = format_date($MESSAGE->headers->date, $RCMAIL->config->get('date_long')); |
| | | $charset = $RCMAIL->output->get_charset(); |
| | | |
| | | if (!$bodyIsHtml) { |
| | | $prefix = "\n\n\n-------- " . rcube_label('originalmessage') . " --------\n"; |
| | |
| | | |
| | | function rcmail_create_draft_body($body, $bodyIsHtml) |
| | | { |
| | | global $MESSAGE, $OUTPUT, $COMPOSE; |
| | | global $MESSAGE, $COMPOSE; |
| | | |
| | | /** |
| | | * add attachments |
| | |
| | | global $RCMAIL, $COMPOSE, $compose_mode; |
| | | |
| | | $loaded_attachments = array(); |
| | | foreach ((array)$COMPOSE['attachments'] as $id => $attachment) { |
| | | foreach ((array)$COMPOSE['attachments'] as $attachment) { |
| | | $loaded_attachments[$attachment['name'] . $attachment['mimetype']] = $attachment; |
| | | } |
| | | |
| | |
| | | $names = array(); |
| | | |
| | | $loaded_attachments = array(); |
| | | foreach ((array)$COMPOSE['attachments'] as $id => $attachment) { |
| | | foreach ((array)$COMPOSE['attachments'] as $attachment) { |
| | | $loaded_attachments[$attachment['name'] . $attachment['mimetype']] = $attachment; |
| | | } |
| | | |
| | |
| | | |
| | | // handle attachments in memory |
| | | $data = file_get_contents($path); |
| | | $name = rcmail_basename($path); |
| | | |
| | | $attachment = array( |
| | | 'group' => $COMPOSE['id'], |
| | | 'name' => rcmail_basename($path), |
| | | 'name' => $name, |
| | | 'mimetype' => $mimetype ? $mimetype : rc_mime_content_type($path, $name), |
| | | 'data' => $data, |
| | | 'size' => strlen($data), |
| | |
| | | $select->add(Q(rcube_label('plaintoggle')), 'plain'); |
| | | |
| | | return $select->show($useHtml ? 'html' : 'plain'); |
| | | |
| | | /* |
| | | foreach ($choices as $value => $text) { |
| | | $attrib['id'] = '_' . $value; |
| | | $attrib['value'] = $value; |
| | |
| | | } |
| | | |
| | | return $selector; |
| | | */ |
| | | } |
| | | |
| | | |
| | |
| | | if (!in_array('threads', $a_show_cols)) |
| | | array_unshift($a_show_cols, 'threads'); |
| | | |
| | | $skin_path = $_SESSION['skin_path'] = $CONFIG['skin_path']; |
| | | $_SESSION['skin_path'] = $CONFIG['skin_path']; |
| | | |
| | | // set client env |
| | | $OUTPUT->add_gui_object('messagelist', $attrib['id']); |
| | |
| | | |
| | | $OUTPUT->include_script('list.js'); |
| | | |
| | | $thead = ''; |
| | | $table = new html_table($attrib); |
| | | if (!$attrib['noheader']) { |
| | | foreach (rcmail_message_list_head($attrib, $a_show_cols) as $cell) |
| | | $thead .= html::tag('td', array('class' => $cell['className'], 'id' => $cell['id']), $cell['html']); |
| | | $table->add_header(array('class' => $cell['className'], 'id' => $cell['id']), $cell['html']); |
| | | } |
| | | |
| | | return html::tag('table', |
| | | $attrib, |
| | | html::tag('thead', null, html::tag('tr', null, $thead)) . |
| | | html::tag('tbody', null, ''), |
| | | array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border', 'summary')); |
| | | return $table->show(); |
| | | } |
| | | |
| | | |
| | |
| | | $thead = $head_replace ? rcmail_message_list_head($_SESSION['list_attrib'], $a_show_cols) : NULL; |
| | | |
| | | // get name of smart From/To column in folder context |
| | | if (($f = array_search('fromto', $a_show_cols)) !== false) { |
| | | if (array_search('fromto', $a_show_cols) !== false) { |
| | | $smart_col = rcmail_message_list_smart_column_name(); |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | // loop through message headers |
| | | foreach ($a_headers as $n => $header) { |
| | | foreach ($a_headers as $header) { |
| | | if (empty($header)) |
| | | continue; |
| | | |
| | |
| | | global $RCMAIL; |
| | | |
| | | $skin_path = $_SESSION['skin_path']; |
| | | $image_tag = html::img(array('src' => "%s%s", 'alt' => "%s")); |
| | | |
| | | // check to see if we have some settings for sorting |
| | | $sort_col = $_SESSION['sort_col']; |
| | |
| | | $cells = array(); |
| | | |
| | | // get name of smart From/To column in folder context |
| | | if (($f = array_search('fromto', $a_show_cols)) !== false) { |
| | | if (array_search('fromto', $a_show_cols) !== false) { |
| | | $smart_col = rcmail_message_list_smart_column_name(); |
| | | } |
| | | |
| | |
| | | */ |
| | | function rcmail_message_headers($attrib, $headers=null) |
| | | { |
| | | global $OUTPUT, $MESSAGE, $PRINT_MODE, $RCMAIL; |
| | | global $MESSAGE, $PRINT_MODE, $RCMAIL; |
| | | static $sa_attrib; |
| | | |
| | | // keep header table attrib |
| | |
| | | $header_attrib[$regs[1]] = $value; |
| | | |
| | | if (!empty($MESSAGE->parts)) { |
| | | foreach ($MESSAGE->parts as $i => $part) { |
| | | foreach ($MESSAGE->parts as $part) { |
| | | if ($part->type == 'headers') { |
| | | $out .= html::div('message-partheaders', rcmail_message_headers(sizeof($header_attrib) ? $header_attrib : null, $part->headers)); |
| | | } |
| | |
| | | $j = 0; |
| | | $out = ''; |
| | | $allvalues = array(); |
| | | $show_email = $RCMAIL->config->get('message_show_email'); |
| | | |
| | | if ($addicon && !isset($_SESSION['writeable_abook'])) { |
| | | $_SESSION['writeable_abook'] = $RCMAIL->get_address_sources(true) ? true : false; |
| | |
| | | $string = $part['string']; |
| | | |
| | | // phishing email prevention (#1488981), e.g. "valid@email.addr <phishing@email.addr>" |
| | | if ($name && $name != $mailto && strpos($name, '@')) { |
| | | if (!$show_email && $name && $name != $mailto && strpos($name, '@')) { |
| | | $name = ''; |
| | | } |
| | | |
| | |
| | | } |
| | | else if (check_email($part['mailto'], false)) { |
| | | if ($linked) { |
| | | $address = html::a(array( |
| | | $attrs = array( |
| | | 'href' => 'mailto:'.$mailto, |
| | | 'onclick' => sprintf("return %s.command('compose','%s',this)", JS_OBJECT_NAME, JQ($mailto)), |
| | | 'title' => $mailto, |
| | | 'class' => "rcmContactAddress", |
| | | ), |
| | | Q($name ? $name : $mailto)); |
| | | ); |
| | | |
| | | if ($show_email && $name && $mailto) { |
| | | $content = Q($name ? sprintf('%s <%s>', $name, $mailto) : $mailto); |
| | | } |
| | | else { |
| | | $content = Q($name ? $name : $mailto); |
| | | $attrs['title'] = $mailto; |
| | | } |
| | | |
| | | $address = html::a($attrs, $content); |
| | | } |
| | | else { |
| | | $address = html::span(array('title' => $mailto, 'class' => "rcmContactAddress"), |
| | |
| | | |
| | | $sent = rcmail_deliver_message($compose, $identity['email'], $mailto, $smtp_error, $body_file, $options); |
| | | |
| | | if ($sent) |
| | | { |
| | | if ($sent) { |
| | | $RCMAIL->storage->set_flag($message->uid, 'MDNSENT'); |
| | | return true; |
| | | } |
| | |
| | | |
| | | function rcmail_message_buttons() |
| | | { |
| | | global $MESSAGE, $RCMAIL, $CONFIG; |
| | | global $RCMAIL; |
| | | |
| | | $mbox = $RCMAIL->storage->get_folder(); |
| | | $delim = $RCMAIL->storage->get_hierarchy_delimiter(); |
| | | $dbox = $CONFIG['drafts_mbox']; |
| | | $dbox = $RCMAIL->config->get('drafts_mbox'); |
| | | |
| | | // the message is not a draft |
| | | if ($mbox != $dbox && strpos($mbox, $dbox.$delim) !== 0) { |
| | |
| | | |
| | | $out = $form_start; |
| | | |
| | | foreach ($SECTIONS[$CURR_SECTION]['blocks'] as $idx => $block) { |
| | | foreach ($SECTIONS[$CURR_SECTION]['blocks'] as $block) { |
| | | if (!empty($block['options'])) { |
| | | $table = new html_table(array('cols' => 2)); |
| | | |
| | |
| | | $noselect = false; |
| | | $classes = array($i%2 ? 'even' : 'odd'); |
| | | |
| | | $folder_js = Q($folder['id']); |
| | | $folder_utf8 = rcube_charset_convert($folder['id'], 'UTF7-IMAP'); |
| | | $display_folder = str_repeat(' ', $folder['level']) |
| | | . Q($protected ? rcmail_localize_foldername($folder['id']) : $folder['name']); |
| | |
| | | $a_threaded = (array) $RCMAIL->config->get('message_threading', array()); |
| | | $oldprefix = '/^' . preg_quote($oldname . $delimiter, '/') . '/'; |
| | | |
| | | foreach ($a_threaded as $key => $val) { |
| | | foreach (array_keys($a_threaded) as $key) { |
| | | if ($key == $oldname) { |
| | | unset($a_threaded[$key]); |
| | | $a_threaded[$newname] = true; |
| | |
| | | ); |
| | | } |
| | | |
| | | // show checkbox to show email instead of name |
| | | if (!isset($no_override['message_show_email'])) { |
| | | $field_id = 'rcmfd_message_show_email'; |
| | | $input_msgshowemail = new html_checkbox(array('name' => '_message_show_email', 'id' => $field_id, 'value' => 1)); |
| | | |
| | | $blocks['main']['options']['message_show_email'] = array( |
| | | 'title' => html::label($field_id, Q(rcube_label('showemail'))), |
| | | 'content' => $input_msgshowemail->show($config['message_show_email']?1:0), |
| | | ); |
| | | } |
| | | |
| | | // show checkbox for HTML/plaintext messages |
| | | if (!isset($no_override['prefer_html'])) { |
| | | $field_id = 'rcmfd_htmlmsg'; |
| | |
| | | case 'mailview': |
| | | $a_user_prefs = array( |
| | | 'message_extwin' => intval($_POST['_message_extwin']), |
| | | 'message_show_email' => isset($_POST['_message_show_email']) ? TRUE : FALSE, |
| | | 'prefer_html' => isset($_POST['_prefer_html']) ? TRUE : FALSE, |
| | | 'inline_images' => isset($_POST['_inline_images']) ? TRUE : FALSE, |
| | | 'show_images' => isset($_POST['_show_images']) ? intval($_POST['_show_images']) : 0, |
| | |
| | | $result = $spellchecker->get_xml(); |
| | | } |
| | | |
| | | if ($err = $spellchecker->error()) { |
| | | rcube::raise_error(array('code' => 500, 'type' => 'php', |
| | | 'file' => __FILE__, 'line' => __LINE__, |
| | | 'message' => sprintf("Spell check engine error: " . $err)), |
| | | true, false); |
| | | } |
| | | |
| | | // set response length |
| | | header("Content-Length: " . strlen($result)); |
| | | |
| | |
| | | } |
| | | |
| | | if ($error = $spellchecker->error()) { |
| | | rcube::raise_error(array('code' => 500, 'type' => 'php', |
| | | 'file' => __FILE__, 'line' => __LINE__, |
| | | 'message' => sprintf("Spell check engine error: " . $error)), |
| | | true, false); |
| | | |
| | | echo '{"error":{"errstr":"' . addslashes($error) . '","errfile":"","errline":null,"errcontext":"","level":"FATAL"}}'; |
| | | exit; |
| | | } |
| | |
| | | array("----------------------------------------------------------------------------------------\nabc def123456789012345", 76), |
| | | "----------------------------------------------------------------------------------------\nabc def123456789012345", |
| | | ), |
| | | array( |
| | | array("-------\nabc def", 5), |
| | | "-------\nabc\ndef", |
| | | ), |
| | | ); |
| | | |
| | | foreach ($samples as $sample) { |
| | |
| | | $this->assertEquals("prefix", $vcard['prefix'], "Decode backslash character"); |
| | | } |
| | | |
| | | /** |
| | | * Backslash parsing test (#1489085) |
| | | */ |
| | | function test_parse_five() |
| | | { |
| | | $vcard = "BEGIN:VCARD\nVERSION:3.0\nN:last\\\\\\a;fir\\nst\nURL:http\\://domain.tld\nEND:VCARD"; |
| | | $vcard = new rcube_vcard($vcard, null); |
| | | $vcard = $vcard->get_assoc(); |
| | | |
| | | $this->assertEquals("last\\a", $vcard['surname'], "Decode dummy backslash character"); |
| | | $this->assertEquals("fir\nst", $vcard['firstname'], "Decode backslash character"); |
| | | $this->assertEquals("http://domain.tld", $vcard['website:other'][0], "Decode dummy backslash character"); |
| | | } |
| | | |
| | | function test_import() |
| | | { |
| | | $input = file_get_contents($this->_srcpath('apple.vcf')); |
| | |
| | | First Name,Last Name,Display Name,Nickname,Primary Email,Secondary Email,Screen Name,Work Phone,Home Phone,Fax Number,Pager Number,Mobile Number,Home Address,Home Address 2,Home City,Home State,Home ZipCode,Home Country,Work Address,Work Address 2,Work City,Work State,Work ZipCode,Work Country,Job Title,Department,Organization,Web Page 1,Web Page 2,Birth Year,Birth Month,Birth Day,Custom 1,Custom 2,Custom 3,Custom 4,Notes, |
| | | Firstname,Lastname,Displayname,Nick,test@domain.tld,next@domain.tld,,phone work,phone home,fax,pager,mobile,Priv address,,City,region,xx-xxx,USA,Addr work,,city,region,33-333,Poland,title,department,Organization,http://page.com,http://webpage.tld,1970,11,15,,,,,, |
| | | Firstname,Lastname,Displayname,Nick,test@domain.tld,next@domain.tld,,phone work,phone home,fax,pager,mobile,Priv address,,City,region,xx-xxx,USA,Addr work,,Wcity,Wstate,33-333,Poland,title,department,Organization,http://page.com,http://webpage.tld,1970,11,15,,,,,, |
| | |
| | | URL;TYPE=other:http://webpage.tld |
| | | BDAY;VALUE=date:1970-11-15 |
| | | ADR;TYPE=home:;;Priv address;City;region;xx-xxx;USA |
| | | ADR;TYPE=work:;;Addr work;;;33-333;Poland |
| | | ADR;TYPE=work:;;Addr work;Wcity;Wstate;33-333;Poland |
| | | END:VCARD |
| | |
| | |
|
| | | On XX.YY.YYYY Y:YY, Somebody wrote:
|
| | | > This part is a reply wihtout any flowing lines. rcube_mime::unfold_flowed()
|
| | | > has to be careful with empty quoted lines because they might end with a
|
| | | >> has to be careful with empty quoted lines because they might end with a
|
| | | > space but still shouldn't be considered as flowed!
|
| | | >
|
| | | > The above empty line should persist after unfolding.
|
| | |
| | |
|
| | | On XX.YY.YYYY Y:YY, Somebody wrote:
|
| | | > This part is a reply wihtout any flowing lines. rcube_mime::unfold_flowed()
|
| | | > has to be careful with empty quoted lines because they might end with a
|
| | | >> has to be careful with empty quoted lines because they might end with a
|
| | | > space but still shouldn't be considered as flowed!
|
| | | >
|
| | | > The above empty line should persist after unfolding.
|