Page MenuHomePhorge

No OneTemporary

diff --git a/CHANGELOG b/CHANGELOG
index d49c3f4e5..084ee462b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,2011 +1,2012 @@
CHANGELOG Roundcube Webmail
===========================
- Fix bug where max_group_members was ignored when adding a new contact (#1490214)
+- Hide MDN and DSN options in compose if disabled by admin (#1490221)
RELEASE 1.1-rc
--------------
- Update jQuery to version 2.1.3
- Allow to override any config option through env variables
- Improve system security by using optional special URL with security token - use_secure_urls
- Allow to define separate server/path for image/js/css files - assets_url/assets_dir
- Sync vendor folder if exists in source package (#1490145)
- Avoid useless reloading list when resetting search with active filter (#1490057)
- Fix invalid folder selection if clicked while busy (#1490158)
- Fix import of multiple contact email addresses from Outlook-csv format (#1490169)
- Fix drag-n-drop to folders expanded while dragging (#1490157)
- Fix import of multiple contact groups from Google-csv format (#1490159)
- Fix import of contacts with multiple email addresses from Google-csv format (#1490178)
- Fix bugs where CSRF attacks were still possible on some requests
- Fix some rcube_utils::anytodatetime() corner cases with timezone mismatches (#1490163)
- Improve move-to and contact-export button in classic skin (#1490166)
- Fix wrong icon for download button in classic skin
- Fix bug where sent message was saved in Sent folder even if disabled by user (#1490208)
RELEASE 1.1-beta
----------------
- Fix skin path handling in plugin context (#1488967)
- Prevent memory exhaustion on image resizing with GD on Windows (#1489937)
- Add plugin hook for database table name lookups as requested in #1489837
- Added Oracle database support
- Support contacts import in GMail CSV format
- Added namespace filter in Folder Manager
- Added folder searching in Folder Manager
- Fix restoring draft messages from localStorage if editor mode differs (#1490016)
- Added config option/user preference to disable saving messages in localStorage (#1489979)
- Added config option 'imap_log_session' to enable Roundcube <-> IMAP session ID logging
- Added config option 'log_session_id' to control the lengh of the session identifer in logs
- Implemented 'storage_connected' API hook after successful IMAP login (#1490025)
- Intergrate Net_LDAP3 and rcube_ldap_generic classes
- Add option (disabled_actions) to disable UI elements/actions (#1489638)
- Support password encryption using openssl extension (#1489989)
- Create/rename groups in UI dialogs (#1489951)
- Added 'contact_search_name' option to define autocompletion entry format
- Display quota information for current folder not INBOX only (#1487993)
- Support images in HTML signatures (#1488676)
- Display full quota information in popup (#1485769, #1486604)
- Mail compose: Selecting contact inserts recipient to previously focused input - to/cc/bcc accordingly (#1489684)
- Close "no subject" prompt with Enter key (#1489580)
- Password: Add option to force new users to change their password (#1486884)
- Improve support for screen readers and assistive technology using WCAG 2.0 and WAI ARIA standards
- Enable basic keyboard navigation throughout the UI (#1487845)
- Select/scroll to previously selected message when returning from message page (#1489023)
- Display a warning if popup window was blocked (#1489618)
- Remove (was: ...) from message subject on reply (#1489375)
- Update to TinyMCE 4.1 (#1489057)
- Enable autolink plugin in TinyMCE (#1488845)
- Support image operations with Imagick extension (#1489734)
- Support upload progress with session.upload_progress and PECL uploadprogress module (#1488702)
- Make identity name field optional (#1489510)
- Utility script to remove user records from the local database
- Plugin API: Added message_saved hook (#1489752)
- Plugin API: Added imap_search_before hook
- Support messages import from zip archives
- Zipdownload: Added mbox format support (#1486069)
- Drop support for IE6, move IE7/IE8 support to legacy_browser plugin
- Update to jQuery-2.1.1
- Search across multiple folders (#1485234)
- Improve UI integration of ACL settings
- Drop support for PHP < 5.3.7
- Set In-Reply-To and References for forwarded messages (#1489593)
- Removed redundant default_folders config option (#1489737)
- Implemented IMAP SPECIAL-USE extension support [RFC6154] (#1487830)
- Optimize some framed pages content for better performance (#1489792)
- Improve text messages display and conversion to HTML (#1488937)
- Don't remove links when html signature is converted to text (#1489621)
- Fix page title when using search filter (#1490023)
- Fix mbox files import
- Fix some character sets detection (#1490135)
- Fix so attachment charset is set in headers of forward/draft message (#1490109)
- Fix bug where wrong charset could be used for text attachment preview page (#1490106)
RELEASE 1.0.4
-------------
- Disable TinyMCE contextmenu plugin as there are more cons than pros in using it (#1490118)
- Fix bug where show_real_foldernames setting wasn't honored on compose page (#1490153)
- Fix issue where Archive folder wasn't protected in Folder Manager (#1490154)
- Fix compatibility with PHP 5.2. in rcube_imap_generic (#1490115)
- Fix setting flags on servers with no PERMANENTFLAGS response (#1490087)
- Fix regression in SHAA password generation in ldap driver of password plugin (#1490094)
- Fix displaying of HTML messages with absolutely positioned elements in Larry skin (#1490103)
- Fix font style display issue in HTML messages with styled <span> elements (#1490101)
- Fix download of attachments that are part of TNEF message (#1490091)
- Fix handling of uuencoded messages if messages_cache is enabled (#1490108)
- Fix handling of base64-encoded attachments with extra spaces (#1490111)
- Fix handling of UNKNOWN-CTE response, try do decode content client-side (#1490046)
- Fix bug where creating subfolders in shared folders wasn't possible without ACL extension (#1490113)
- Fix reply scrolling issue with text mode and start message below the quote (#1490114)
- Fix possible issues in skin/skin_path config handling (#1490125)
- Fix lack of delimiter for recipient addresses in smtp_log (#1490150)
- Fix generation of Blowfish-based password hashes (#1490184)
- Fix bugs where CSRF attacks were still possible on some requests
RELEASE 1.0.3
-------------
- Initialize HTML editor before restoring a message from localStorage (#1490016)
- Add 'sig_max_lines' config option to default config file (#1490071)
- Add config option to specify IMAP connection socket parameters - imap_conn_options (#1489948)
- Add option to set default message list mode - default_list_mode (#1487312)
- Enable contextmenu plugin for TinyMCE editor (#1487014)
- Fix insert-signature command in external compose window if opened from inline compose screen (#1490074)
- Fix some mime-type to extension mapping checks in Installer (#1489983)
- Fix errors when using localStorage in Safari's private browsing mode (#1489996)
- Fix bug where $Forwarded flag was being set even if server didn't support it (#1490000)
- Fix various iCloud vCard issues, added fallback for external photos (#1489993)
- Fix invalid Content-Type header when send_format_flowed=false (#1489992)
- Fix errors when adding/updating contacts in active search (#1490015)
- Fix incorrect thumbnail rotation with GD and exif orientation data (#1490029)
- Fix contacts list update after adding/deleting/moving a contact (#1490028, #1490033)
- Fix handling of email addresses with quoted domain part (#1490040)
- Fix comm_path update on task switch (#1490041)
- Fix error in MSSQL update script 2013061000.sql (#1490061)
- Fix validation of email addresses with IDNA domains (#1490067)
RELEASE 1.0.2
-------------
- Fix storing unsaved drafts in localStorage (#1489818)
- Add configurable LDAP_OPT_DEREF option (#1489864)
- Fix so when switching editor mode original version of signature is used (#1488849)
- Fix unintentional draft autosave request if autosave is disabled (#1489882)
- Fix malformed References: header in send/saved mail (#1489891)
- Fix handling unicode characters in links (#1489898)
- Fix incorrect handling of HTML comments in messages sanitization code (#1489904)
- Fix so current page is reset on list-mode change (#1489907)
- Fix so responses menu hides on click in classic skin (#1489915)
- Fix unintentional line-height style modification in HTML messages (#1489917)
- Fix broken normalize_string(), add support for ISO-8859-2 (#1489918)
- Support csv contacts import in German localization (#1489920)
- Fix so message list and counters are updated when a message is opened in new window (#1489919)
- Fix malformed recipient name when composing a message by clicking on mailto link (#1489942)
- Fix list reload after sending message in another window (#1489931)
- Fix so address format errors are ignored when saving a draft (#1489954)
- Fix incorrect label translation in return receipt (#1489963)
- Fix security issue in delete-response action - allow only ajax request
- Fix Delete button state after deleting identity/response (#1489972)
- Fix bug where contacts with no email address were listed on compose addressbook (#1489970)
- Fix images import from various vCard formats (#1489977)
- Fix sorting messages by size on servers without SORT capability (#1489981)
RELEASE 1.0.1
-------------
- Support 'error' and 'body_file' return attribs in 'message_before_send' hook (#1489595)
- Apply user-specific replacements to group's base_dn property (#1489779)
- Fix missing email address when importing contacts from outlook csv (#1489830)
- Fix bug where "With attachment" option in search filter wasn't selected after return from mail view (#1489774)
- Fix "washing" of unicoded style attributes (#1489777)
- Fix unintentional redirect from compose page in Webkit browsers (#1489789)
- Fix messages index cache update under some conditions (e.g. proxy) (#1489756)
- Fix lack of translation of special folders in some configurations (#1489799)
- Fix XSS issue in plain text spellchecker (#1489806)
- Fix invalid page title for some folders (1489804)
- Fix redundant alert message on over-size uploads (#1489817)
- Fix next message display after removing a message (#1489800)
- Fix missing Mail-Followup-To header in sent mail (#1489829)
- Fix error when spell-checking an empty text (#1489831)
- Avoid popupmenus being closed when scrollbar is clicked (#1489832)
- Add proxy_whitelist configuration option (#1489729)
- Fix identities_level=4 handling in new_user_dialog plugin (#1489840)
- Fix various db_prefix issues (#1489839)
- Fix too small length of users.preferences column data type on MySQL
- Fix redundant warning when switching from html to text in empty editor (#1489819)
- Fix invalid host validation on login (#1489841)
- Fix IMAP connection test in installer so it is aware of imap_auth_type (#1489746)
RELEASE 1.0.0
-------------
- Added toolbar button to move message in message view
- Fix style of disabled protocol handler link on IE (#1489569)
- Fix message import dialog when no file is selected (#1489685)
- Fix opening compose screen in new window after saving as draft (#1489643)
- Fix directories check in Installer on Windows (#1489576)
- Fix issue when default_addressbook option is set to integer value (#1489407)
- Fix Opera > 15 detection (#1489562)
- Fix security issue in DomainFactory driver of Password plugin
- Fix invalid X-Draft-Info on forwarded message draft (#1489587)
- Fix regression in handling of 'attachments' result in message_compose hook (#1489627)
- Fix issue where msgexport.sh printed the message to STDOUT instead of a file (#1489634)
- Fix fatal error in database_attachments plugin under some conditions (#1489726)
RELEASE 1.0-rc
--------------
- Small CSS fix with message notice boxes in Larry skin (#1489497)
- Include groups in contacts search on mail compose (#1489082)
- Add mime-type mapping for .7z files (#1489512)
- Invoke update scripts with php to circumvent execution restrictions (#1489322)
- Fix drag & drop message/contact moving on touch device (#1489431)
- Fix canned responses in HTML mode (#1489536)
- Check/create default folders on every login not only the first (#1489423)
- Update to jQuery-1.11.0 and jQuery-UI-1.9.2
- Support SMTP socket context options via new config option 'smtp_conn_options'
- Fix compatibility with PHP 5.2 in html.php file (#1489514)
- Remove expand/collapse with plus/minus keys (on numeric keypad) (#1489513)
- Fix issue where filesystem path was added to all-attachments (zip) file (#1489507)
- Fix case-sensitivity of email addresses handling on compose (#1485499)
- Don't alter Message-ID of a draft when sending (#1489409)
- Fix issue where deprecated syntax for HTML lists was not handled properly (#1488768)
- Display different icons when Trash folder is empty or full (#1485775)
- Remember last position of more headers switch (#1488323)
- Fix so message flags modified by another client are applied on the list on refresh (#1485186)
- Fix broken text/* attachments when forwarding/editing a message (#1489426)
- Improved minified files handling, added css minification (#1486988)
- Fix handling of X-Forwarded-For header with multiple addresses (#1489481)
- Fix border issue on folders list in classic skin (#1489473)
- Implemented menu actions to copy/move messages, added folder-selector widget (#1484086)
- Fix security rules in .htaccess preventing access to base URL without the ending slash (#1489477)
- Fix regression where only first new folder was placed in correct place on the list (#1489472)
- Fix issue where children of selected and collapsed thread were skipped on various actions (#1489457)
- Fix issue where groups were not deleted when "Replace entire addressbook" option on contacts import was used (#1489420)
- Fix unreliable mimetype tests in Installer (#1489453)
- Fix performance of listing writeable folders (#1489451)
RELEASE 1.0-beta
----------------
- Fix handling of invalid closing tags in HTML messages (#1489446)
- Set real content-type for file downloads (#1489439)
- Update TinyMCE to version 3.5.10 (#1489442)
- Fix keyboard navigation in list widgets (#1489392)
- Allow plugins to grab the reference of opened windows (#1489413)
- Larry skin: Improved status message display for better visibility (#1488974)
- Fix Internet Explorer 11 detection (#1489434)
- Fix date column width to fit the widest possible date format (#1489368)
- Move certain user preference options to a collapsed "advanced" block (#1488829)
- Add file type icons for Powerpoint and Open Office presentations (#1489225)
- Fix operations on folders with trailing spaces in name (#1489419)
- Improve identity selection based on From: header (#1489378)
- Fix issue where mails with inline images of the same name contained only the first image multiple times (#1489406)
- Use left/right arrow keys to collapse/expand thread and spacebar to select a row, change Ctrl key behavior (#1489392)
- Fix an issue where using arrow keys to go up a list can result in selected message being under headers (#1489403)
- Fix an issue where Home/End keys don't focus list row properly, don't scrollTo properly (#1489396)
- Add an option to disable smart Reply-List behaviour - reply_all_mode (#1488734)
- Fix an issue where pressing minus key on contacts list was hiding list records (#1489393)
- Fix an issue where shift + arrow-up key wasn't selecting all messages in collapsed thread (#1489397)
- Added icon for priority column in messages list header (#1489234)
- New feature "Canned Responses" to save and recall boilerplate text snippets
- Fix HTML part detection when encapsulated inside multipart/signed (#1489372)
- Add spellchecker backend for the After the Deadline service
- Replace markdown-style [1] link indexes in plain text email bodies
- Improved mailto: link arguments handling (#1489363)
- Use DOMDocument LIBXML_PARSEHUGE and LIBXML_COMPACT options if possible (#1489302)
- Support HTTP_HOST, SERVER_NAME and SERVER_ADDR values in include_host_config feature
- Make default font size for HTML messages configurable (request #118)
- Fix XSS issue in addressbook group name field [CVE-2013-5646] (#1489333)
- After message is sent refresh messages list of replied message folder (#1489249)
- Add option force specified domain in user login - username_domain_forced (#1489264)
- Add option to import Vcards with group assignments
- Save groups membership in Vcard export (#1488509)
- Workaround broken PHP function timezone_name_from_abbr (#1489261)
- Make cached message size limit configurable - messages_cache_threshold (#1489317)
- Log also failed logins to userlogins log
- Add temp_dir_ttl configuration option (#1489304)
- Allow setting INBOX as Sent folder (#1489219)
- Fix replacement variables in user-specific base_dn in some LDAP requests (#1489279)
- Fix image scaling issues when image has only one dimension smaller than the limit (#1489274)
- Fix issue where uploaded photo was lost when contact form did not validate (#1489274)
- Move identity selection based on non-standard headers into (new) identity_select plugin (#1488553)
- Fix downloading binary files with (wrong) text/* content-type (#1489267)
- Respect HTTP_X_FORWARDED_FOR and HTTP_X_REAL_IP variables for session IP check
- Simplified configuration by merging it into one file + defaults (#1487311)
- Make message list header stay on top when scrolling (#1295420)
- Add support for 'enchant' spellcheck engine
- Check filetype detection in installer and update script (#1489193)
- Fix folder names truncation in Classic skin (#1489220)
- Make possible to disable some (broken) IMAP extensions with imap_disable_caps option (#1489184)
- Contacts drag-n-drop default action is to move contacts (#1488751)
- Added possibility to choose to move or copy contacts from drag-n-drop menu (#1488751)
- Fix Close link and remove About link on error pages (#1489109)
- Improved/unified attachment preview screen, added print button
- Fix lack of space between searchfiler and quicksearchbar in Larry skin (#1489158)
- Cache LDAP's user_specific search and use vlv for better performance (#1489186)
- LDAP: auto-detect and use VLV indices for all search operations
- LDAP: additional group configuration options for address books
- LDAP: separated address book implementation from a generic LDAP wrapper class
- Allow address books to browse a multi-level group hierarchy in the contacts list
- Fix session issues when local and database time differs (#1486132)
- Fix thread cache syncronization/validation (#1489028)
- Added feature to import messages to the currently selected folder
- Add option show_real_foldernames to disable localization of special folders
- Fix database cache expunge issues (#1489149)
- Fix date format issues on MS SQL Server (#1488918)
- Add imap_cache_ttl option to configure TTL of imap_cache
- Make LDAP cache engine configurable via ldap_cache and ldap_cache_ttl options
- Fix "duplicate entry" errors on inserts to imap cache tables (#1489146)
- Improved handling of Reply-To/Bcc addresses of identity in compose form (#1489016)
- Added user preference to open all popups as standard windows
- Implemented shared cache (rcube_cache_shared)
- Change Reply-All button label/title when mailing list is detected (#1488938)
- Fix SMTP connection using IPv6 address in smtp_server option (#1489024)
- Added attachment_reminder plugin
- Make PHP code eval() free, use create_function()
- Add option to display email address together with a name in mail preview (#1488732)
- Support CSV import from Atmail (#1489045)
- 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
- Fix parsing invalid date string (#1489035)
- Add "with attachment" option to messages list filter (#1485382)
- Call resize handler in intervals to prevent lags and double onresize calls in Chrome (#1489005)
- Add rel="noreferrer" for links in displayed messages (#1484686)
- Add ability to toggle between HTML and text while viewing a message (#1486939)
- Remove "HTML message" from attachments list while viewing a message in text mode (#1486939)
- Support IMAP MOVE extension [RFC 6851]
- Add attachment menu with Open and Download options (#1488975)
- Display user-friendly message on IMAP "over quota" errors (#1484164)
- Extended archive plugin with user-configurable options to store messages into subfolders
- Fix export of selected contacts from search result (#1488905)
- Feature to export only selected contacts from addressbook (by Phil Weir)
RELEASE 0.9.5
-------------
- Fix failing vCard import when email address field contains spaces (#1489386)
- Fix default spell-check configuration after Google suspended their spell service
- Fix vulnerability in handling _session argument of utils/save-prefs [CVE-2013-6172] (#1489382)
- Fix iframe onload for upload errors handling (#1489379)
- Fix address matching in Return-Path header on identity selection (#1489374)
- Fix text wrapping issue with long unwrappable lines (#1489371)
- Fixed issues where HTML comments inside style tag would hang Internet Explorer
- Hide Delivery Status Notification option when smtp_server is unset (#1489336)
- Display full attachment name using title attribute when name is too long to display (#1489320)
- Fix attachment icon issue when rare font/language is used (#1489326)
- Fix expanded thread root message styling after refreshing messages list (#1489327)
- Fix issue where From address was removed from Cc and Bcc fields when editing a draft (#1489319)
- Fix error_reporting directive check (#1489323)
- Fix de_DE localization of "About" label in Help plugin (#1489325)
RELEASE 0.9.4
-------------
- Make identities matching case insensitive (#1485480)
- Fix issue where too big message data was stored in cache causing sql errors (#1489316)
- Fix iframe scrollbars on webkit desktop browsers (#1489306)
- Fix issue where legacy config was overriden by default config (#1489288)
- Fix newmail_notifier issue where favicon wasn't changed back to default (#1489313)
- Fix setting of Junk and NonJunk flags by markasjunk plugin (#1489285)
- Fix lack of Reply-To address in header of forwarded message body (#1489298)
- Fix bugs when invoking contact creation form when read-only addressbook is selected (#1489296)
- Fix identity selection on reply (#1489291)
- Fix so additional headers are added to all messages sent (#1489284)
- Fix display issue after moving folder in Folder Manager (#1489293)
- Fix handling of non-default date formats (#1489294)
- Fix unquoted path in PREG expression on Windows (#1489290)
- Fix wrong close tag in /template/mail.html (#1489295)
RELEASE 0.9.3
-------------
- Fix setting refresh_interval to "Never" in Preferences (#1489286)
- Fixed iframe scrolling on touch devices
- Optimized message list for touch devices
- Fix purge action in folder manager (#1489280)
- Fix base URL resolving on attribute values with no quotes (#1489275)
- Fix wrong handling of links with '|' character (#1489276)
- Fix colorspace issue on image conversion using ImageMagick (#1489270)
- Fix XSS vulnerability when editing a message "as new" or draft [CVE-2013-5645] (#1489251)
- Fix XSS vulnerability when saving HTML signatures [CVE-2013-5645] (#1489251)
- Fix rewrite rule in .htaccess (#1489240)
- Fix detecting Turkish language in ISO-8859-9 encoding (#1489252)
- Fix identity-selection using Return-Path headers (#1489241)
- Fix parsing of links with ... in URL (#1489192)
- Fix compose priority selector when opening in new window (#1489257)
- Fix bug where signature wasn't changed on identity selection when editing a draft (#1489229)
- Fix IMAP SETMETADATA parameters quoting (#1489231)
- Fix "could not load message" error on valid empty message body (#1489228)
- Fix handling of message/rfc822 attachments on message forward and edit (#1489214)
- Fix parsing of square bracket characters in IMAP response strings (#1489223)
- Don't clear References and in-Reply-To when a message is "edited as new" (#1489216)
- Fix messages list sorting with THREAD=REFS
- Remove deprecated (in PHP 5.5) PREG /e modifier usage (#1489174)
- Fix empty messages list when register_globals is enabled (#1489157)
- Fix so valid and set date.timezone is not required by installer checks (#1489180)
- Canonize boolean ini_get() results (#1489189)
- Fix so install do not fail when one of DB driver checks fails but other drivers exist (#1489178)
- Fix so exported vCard specifies encoding in v3-compatible format (#1489183)
RELEASE 0.9.2
-------------
- Fix image thumbnails display in print mode (#1489134)
- Fix height of message headers block (#1489108)
- Fix timeout issue on drag&drop uploads (#1489170)
- Fix default sorting of threaded list when THREAD=REFS isn't supported
- Fix list mode switch to 'List' after saving list settings in Larry skin (#1489164)
- Fix error when there's no writeable addressbook source (#1489162)
- Fix zipdownload plugin issue with filenames charset (#1489156)
- Fix so non-inline images aren't skipped on forward (#1489150)
- Fix "null" instead of empty string on messages list in IE10 (#1489145)
- Fix legacy options handling
- Fix so bounces addresses in Sender headers are skipped on Reply-All (#1489011)
- Fix bug where serialized strings were truncated in PDO::quote() (#1489142)
- Fix displaying messages with invalid self-closing HTML tags (#1489137)
- Fix PHP warning when responding to a message with many Return-Path headers (#1489136)
- Fix unintentional compose window resize (#1489114)
- Fix performance regression in text wrapping function (#1489133)
- Fix connection to posgtres db using unix socket (#1489132)
- Fix handling of comma when adding contact from contacts widget (#1489107)
- Fix bug where a message was opened in both preview pane and new window on double-click (#1489122)
- Fix fatal error when xdebug.max_nesting_level was exceeded in rcube_washtml (#1489110)
- Fix PHP warning in html_table::set_row_attribs() in PHP 5.4 (#1489094)
- Fix invalid option selected in default_font selector when font is unset (#1489112)
- Fix displaying contact with ID divisible by 100 in sql addressbook (#1489121)
- Fix browser warnings on PDF plugin detection (#1489118)
- Fix fatal error when parsing UUencoded messages (#1489119)
RELEASE 0.9.1
-------------
- Better German labels for from/to to avoid conflicts with 'sender' (#1489084)
- Fix problem where security warning was displayed for valid images with image/jpg type (#1489097)
- Fix handling of invalid email addresses in headers (#1489092)
- 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)
- 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)
- 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 possible collision in generated thumbnail cache key (#1489069)
- Fix exit code on bootsrap errors in CLI mode (#1489044)
- Fix error handling in CLI mode, use STDERR and non-empty exit code (#1489043)
- Fix error when using check_referer=true
- Fix incorrect handling of some specific links (#1489060)
- Fix incorrect handling of leading spaces in text wrapping
- Fix unintentional messages list jumps on click in Internet Explorer (#1489056)
- Fix list of required configuration options (#1489055)
- Fix DB error when creating a new contact and a group is selected (#1489051)
- Fix handling of deprecated boolean value of reply_mode option (#1489052)
RELEASE 0.9.0
-------------
- Fix display of HTML entities in protected folder name (#1489042)
- Set minimal permissions to temp files (#1488996)
- Improve content check for embedded images without filename (#1489029)
- Fix handling of invalid characters in message headers and output (#1489032)
- Fix selecting collapsed rows on select-all (#1489036)
- Avoid race-conditions with concurrent attachment uploads (#1488422)
- Fix possible header duplicates when using additional headers (#1489033)
- Fix session issues with use_https=true (#1488986)
- Fix blockquote width in sent mail (#1489031)
- Fix keyboard events on list widgets in Internet Explorer (#1489025)
RELEASE 0.9-rc2
---------------
- Fix security issue in save-pref command
- Remove sig_above configuration option, use reply_mode only (#1489001)
- Refresh current folder in opener window after draft save or message sent (#1488997)
- Fix saving draft just after entering compose window (#1489012)
- Fix javascript error in IE9 when loading form with placeholders into an iframe (#1489008)
- Fix handling of some conditional comment tags in HTML message (#1489004)
- Fix so forward as attachment works if additional attachment is added by message_compose hook (#1489000)
- Better handling of session errors in ajax requests (#1488960)
- Fix HTML part detection for some specific message structures (#1488992)
- Don't show fake address - phishing prevention (#1488981)
- Fix forward as attachment bug with editormode != 1 (#1488991)
- Fix LIMIT/OFFSET queries handling on MS SQL Server (#1488984)
- Fix so task name can really contain all from a-z0-9_- characters (#1488941)
- Fix javascript errors when working in a page opened with taget="_blank"
- Mention SQLite database format change in UPGRADING file (#1488983)
- Increase maxlength to 254 chars for email input fields in addressbook (#1488987)
- Fix thumbnail size when GD extension is used for image resize (#1488985)
- Display notice that message is encrypted also for application/pkcs7-mime messages (#1488526)
RELEASE 0.9-rc
--------------
- Fix plain text spellchecker incorrect highlighting in non-ASCII text (#1488973)
- Add workaround for invalid message charset detection by IMAP servers (#1488968)
- Fix NUL characters in content-type of ms-tnef attachment (#1488964)
- Fix regression in handling LDAP contact identifiers (#1488959)
- Updated translations from Transifex
- Fix buggy error template in a frame (#1488938)
- Add addressbook widget on compose page in classic skin
- Add search box to compose address book widget (#1488381)
- Fix login in case when default_host is an array with one element (#1488928)
- Use LDAP fallback hosts on connect + bind instead of ldap_connect() only.
- Add config option for LDAP bind timeout (sets LDAP_OPT_NETWORK_TIMEOUT option)
- Submit Addressbook advanced search form with Enter key (#1488568)
- Also block remote images in HTML part view (#1488827)
- Improved database schema upgrade procedure, added updatedb.sh script
- Force autocommit mode in mysql database driver (#1488902)
RELEASE 0.9-beta
----------------
- Fix searching by date in address book (#1488888)
- Improve charset detection by prioritizing charset according to user language (#1485669)
- Fix handling of escaped separator in vCard file (#1488896)
- Add option to use envelope From address for MDN responses (#1488880)
- Add possibility to search in message body only (#1488770)
- Support "multipart/relative" as an alias for "multipart/related" type (#1488886)
- Display PGP/MIME signature attachments as "Digital Signature" (#1488570)
- Workaround UW-IMAP bug where hierarchy separator is added to the shared folder name (#1488879)
- Fix version comparisons with -stable suffix (#1488876)
- Add unsupported alternative parts to attachments list (#1488870)
- Add Compose button on message view page (#1488747)
- Display 'Sender' header in message preview
- Plugin API: Added message_before_send hook
- Fix contact copy/add-to-group operations on search result (#1488862)
- Use matching identity in MDN response (#1488864)
- Fix handling of signatures on draft edit (#1488798)
- Fix so compacting of non-empty folder is possible also when messages list is empty (#1488858)
- Allow forwarding of multiple emails (#1486854)
- Fix big memory consumption of DB layer (#1488856)
- Fix broken message/part bodies when FETCH response contains more untagged lines (#1488836)
- Fix empty email on identities list after identity update (#1488834)
- Add new identities_level: (4) one identity with possibility to edit only signature
- Use Delivered-To and Envelope-To headers for identity selection (#1488840, #1488553)
- Fix XSS vulnerability using Flash files (#1488828)
- Always save drafts with format=flowed in order to keep original line wraps (#1488799)
- Select default_addressbook on the list in Address Book (#1488280)
- Fix so mobile phone has TYPE=CELL in exported vCard (#1488812)
- Support contacts import from CSV file (#1486399)
- Improved keep-alive action. Now the interval is based on session_lifetime (#1488507)
- Added cross-task 'refresh' request for system state updates (#1488507)
- Renamed config options: keep_alive to refresh_interval, min_keep_alive to min_refresh_interval
- Fix handling of text/enriched content on message reply/forward/edit
- Option to display attached images as thumbnails below message body
- Upgraded to jQuery 1.8.3 and jQuery UI 1.9.1
- Add config option to automatically generate LDAP attributes for new entries
- Add user settings to open message view and compose form in new windows (#1485486)
- Better client-side timezone detection using the jsTimezoneDetect library (#1488725)
- Add option to disable saving sent mail in Sent folder - no_save_sent_messages (#1488686)
- Fix handling dont_override with message_sort_col and message_sort_order settings (#1488760)
- Fix handling of URLs with asterisk characters (#1488759)
- Remove automatic to-lowercase conversion of usernames (#1488715)
- Plugin API: Add 'email_list' argument for identities data in user_create hook
- Integrated zipdownload plugin to download all attachments (#1445509)
- Fix HTML special characters handling in message list/header display (#1488523)
- List related text/html part as attachment in plain text mode (#1488677)
- Use IMAP BINARY (RFC3516) extension to fetch message/part bodies
- Fix folder creation under public namespace root (#1488665)
- Fix so "Edit as new" on draft creates a new message (#1488687)
- Fix invalid error message on deleting mail from read only folder (#1488694)
- Replace data URIs of images (pasted in HTML editor) with inline attachments (#1488502)
- Remove (too big) min-width on mail screen
- Added template object 'frame'
- Add option to enable HTML editor on forwarding (#1488517)
- Add option to not include original message on reply, rename option top_posting to reply_mode (#1485149)
- Added session_path config option and unified cookies settings in javascript
- Added "Undeleted" option to messages list filter
- Rewritten test scripts for PHPUnit
- Add new DB abstraction layer based on PHP PDO, supporting SQLite3 (#1488332)
- Removed PEAR::MDB2 package
- Removed users.alias column, added option ('user_aliases')
to use email address from identities as username (#1488581)
- Removed redundant cache.cache_id column (#1488528)
- Fix order of attachments in sent mail (#1488423)
- Fix Shift + delete button does not permanently delete messages (#1488243)
- Add Content-Length for attachments where possible (#1485478)
- Fix attachment sizes in message print page and attachment preview page (#1488515)
- Add mail attachments using drag & drop on HTML5 enabled browsers
- Add workaround for invalid BODYSTRUCTURE response - parse message with Mail_mimeDecode package (#1485585)
- Display Tiff as Jpeg in browsers without Tiff support (#1488452)
- Don't display Pdf/Tiff/Flash attachments inline without browser support (#1488452, #1487929)
- Add is_escaped attribute for html_select and html_textarea (#1488485)
- Fix issue where draft auto-save wasn't executed after some inactivity time
- Add vCard import from multiple files at once (#1488015)
- Roundcube Framework:
Add possibility to replace IMAP driver with custom class
Add IMAP auto-connection feature, improving performance with caching enabled
Replace imap_init hook with storage_init (with additional 'driver' argument)
Improved performance by caching IMAP server's capabilities in session
Unified global functions naming (rcube_ prefix)
Better classes separation
Framework files moved to lib/Roundcube
RELEASE 0.8.5
-------------
- Fix #countcontrols issue in IE<=8 when text is very long (#1488890)
- Fix unwanted horizontal scrollbar in message preview header (#1488866)
- Add workaround for IE<=8 bug where Content-Disposition:inline was ignored (#1488844)
- Fix XSS vulnerability in vbscript: and data:text links handling [CVE-2012-6121] (#1488850)
- Fix absolute positioning in HTML messages (#1488819)
- Fix cache (in)validation after setting \Deleted flag
- Fix keybord events on messages list in opera browser (#1488823)
- Fix selection of collapsed thread rows (#1488772)
- Fix wrapping of quoted text with format=flowed (#1488177)
RELEASE 0.8.4
-------------
- Fix regression where unintentional page reload was done after request abort (#1488802)
- Fix XSS vulnerability in handling of text/enriched messages (#1488806)
- Fix handling of 'media' attribute on linked css (#1488789)
- Fix excessive LFs at the end of composed message with top_posting=true (#1488797)
- Fix bug where leading blanks were stripped from quoted lines (#1488795)
RELEASE 0.8.3
-------------
- Fix AREA links handling (#1488792)
- Fix possible HTTP DoS on error in keep-alive requests (#1488782)
- Fix compatybility with MDB2 2.5.0b4 (#1488779)
- Fix a bug where saving a message in INBOX wasn't possible
- Fix HTML part detection in messages with attachments (#1488769)
- Fix bug where wrong words were highlighted on spell-before-send check
- Fix scrolling quirk in email preview frame using Opera 12 (#1488763)
- Fix displaying of multipart/alternative messages with empty parts (#1488750)
- Fix threaded list sorting on PHP < 5.2.9 (#1488748)
- Fix Warning: htmlspecialchars(): charset `RCMAIL_CHARSET' not supported warning in Installer (#1488744)
RELEASE 0.8.2
-------------
- Fix XSS vulnerability from HTTP User-Agent header (#1488737)
- Force fonts in compose fields to be all the same (#1488690)
- Fix handling vCard entries with TEL;TYPE=CELL (#1488728)
- Fix error where session wasn't updated after folder rename/delete (#1488692)
- Fix PLAIN authentication for some IMAP servers (#1488674)
- Fix encoding vCard file when contains PHOTO;ENCODING=b (#1488683)
- Fix focus issue in IE when selecting message row (#1488620)
- Add full headers view in message preview window (#1488538)
- Fix message display page issues - unified with message preview (#1488590, #1488642)
- Fix displaying all headers when they contain malformed characters (#1488666)
- Fix decoding of HTML messages with UTF-16 charset specified (#1488654)
- Fix quota capability detection so it can be overwritten by a plugin (#1488655)
- Fix identity selection on reply (#1488101)
- Fix Larry's messages list filter in IE (#1488632)
- Fix more IE issues by disabling Compat. mode with X-UA-Compatible meta tag (#1488626)
- Fix setting locales under Solaris - use additional .UTF-8 suffix (#1488628)
- Fix email address validation for addresses with IP address in domain part
- Fix Larry skin issues in IE7 compat. mode (#1488618)
- Fix so subscribed non-existing/non-accessible shared folder can be unsubscribed
RELEASE 0.8.1
-------------
- Fix bug where domain name was converted to lower-case even with login_lc=false (#1488593)
- Fix lower-casing email address on replies (#1488598)
- Fix line separator in exported messages (#1488603)
- Fix XSS issue where plain signatures wasn't secured in HTML mode [CVE-2012-4668] (#1488613)
- Fix XSS issue where href="javascript:" wasn't secured [CVE-2012-3508] (#1488613)
- Fix impossible to create message with empty plain text part (#1488610)
- Fix stripped apostrophes when replying in plain text to HTML message (#1488606)
- Fix inactive Save search option after advanced search (#1488607)
- Fix Remove from group option is active for contact search result (#1488608)
- Disable autocapitalization in login form on iPad/iPhone (#1488609)
- Fix focus on the list when list row is clicked (#1488600)
- Added separate From and To columns apart from smart From/To column (#1486891)
- Fix fallback to Larry skin when configured skin isn't available (#1488591)
- Fix (workaround) delete operations with some versions of memcache (#1488592)
- Fix (disable) request validation for spell and spell_html actions
RELEASE 0.8.0
-------------
- Don't show product version on login screen (can be enabled by config)
- Renamed old default skin to 'classic'. Larry is the new default skin.
- Support connections to memcached socket file (#1488577)
- Enable TinyMCE inlinepopups plugin
- Update to TinyMCE 3.5.6
- Correctly escape localized labels in javascript variable (#1488567)
- Update Net_SMTP/Auth_SASL packages to fix Digest-MD5/Cram-MD5 authentication (#1488571)
- Don't add attachments content into reply/forward/draft message body (#1488557)
- Fix 'no connection' errors on page unloads (#1488547)
- Plugin API: Add 'unauthenticated' hook (#1488138)
- Show explicit error message when provided hostname is invalid (#1488550)
- Fix wrong compose screen elements focus in IE9 (#1488541)
- Fix fatal error when date.timezone isn't set (#1488546)
- Update to TinyMCE 3.5.4.1
- Better icons with distinct shapes for priority columns (#1488377)
- Show dedicated icon for multipart/report messages (#1488524)
- Properly hide text of icon links/buttons (#1488534)
- Fix handling of unitless CSS size values in HTML message (#1488535)
- Fix removing contact photo using LDAP addressbook (#1488420)
- Fix storing X-ANNIVERSARY date in vCard format (#1488527)
- Update to Mail_Mime-1.8.5 (#1488521)
- Fix XSS vulnerability in message subject handling using Larry skin [CVE-2012-3507] (#1488519)
- Fix handling of links with various URI schemes e.g. "skype:" (#1488106)
- Fix handling of links inside PRE elements on html to text conversion
- Fix indexing of links on html to text conversion
- Decode header value in rcube_mime::get() by default (#1488511)
- Fix errors with enabled PHP magic_quotes_sybase option (#1488506)
- Fix SQL query for contacts listing on MS SQL Server (#1488505)
- Fix window.resize handler on IE8 and Opera (#1488453)
- Don't let error message popups cover the login form (#1488500)
- Update to TinyMCE 3.5.2
- Don't show errors when moving contacts into groups they are already in (#1488493)
- Make folders with unread messages in subfolders bold again (#1486793)
- Abbreviate long attachment file names with ellipsis (#1488499)
- Fix html2text conversion of strong|b|a|th|h tags when used in upper case
- Add listcontrols template container in Larry skin (#1488498)
- Fix host autoselection when default_host is an array (#1488495)
- Move messages forwarding mode setting into Preferences
- Fix HTML entities handling in HTML editor (#1488483)
- Fix listing shared folders on Courier IMAP (#1488466)
RELEASE 0.8-rc
--------------
- Added new translations in Belarusian, Interlingua and Malayalam
- Flipped compose options arrow (#1488474)
- Fix handling of large uuencode attachments (#1488473)
- Fix handling of "usemap" attribute (#1488472)
- Fix handling of some HTML tags e.g. IMG (#1488471)
- Use similar language as a fallback for plugin localization (#1488401)
- Fix issue where signature wasn't re-added on draft compose (#1488322)
- Update to TinyMCE 3.5 (#1488459)
- Fixed multi-threaded autocompletion when number of threads > number of sources
- Allow to configure the number of values allowed for each LDAP attribute
- Support for serialized LDAP address values (usually delimited with a $)
- Less restrictive session auth checks, repeat keep-alive requests on failure (#1488449)
- Fix redirect to mail/compose on re-login (#1488226)
- Add IE8 hack for messages list issue (#1487821)
- Fix handling errors on draft auto-save
- Fix importing vCard photo with ENCODING param specified (#1488432)
- Support mutliple name/email pairs for Bcc and Reply-To identity settings (#1488445)
- Set flexible width to login form fields (#1488418)
- Fix re-draw bug on list columns change in IE8 (#1487822)
- Allow mass-removal of addresses from a group (#1487748)
- Fix removing all contacts on import to LDAP addressbook
- Fix so "Back" from compose/show doesn't reset search request (#1488238)
- Add option to delete messages instead of moving to Trash when in Junk folder (#1486686)
- Fix invisible cursor when replying to a html message (#1487073)
- Reset IP stored in session when destroying session data (#1488056)
- Fix bug where memory_limit = -1 wasn't handled properly
- Support LDAP RFC2256's country object class read/write (#1488123)
- Upgraded to jQuery 1.7.2
- Image resize with GD extension (#1488383)
- Fix lack of warning when switching task in compose window (#1488399)
- Fix bug where it wasn't possible to enter ( or & characters in autocomplete fields
- Request all needed fields from address book backends (#1488394)
- Unified (single) spellchecker button
- Scroll long lists on drag&drop (#1485946)
- Copy all skins in installto script (#1488376)
RELEASE 0.8-beta
----------------
- Upgraded to jQuery 1.7.1 (#1488337) and jQuery UI 1.8.18
- Add Russian to the spellchecker languages list (#1488135)
- Remember custom skin selection after logout (#1488355)
- Make sure About tab is always the last tab (#1488257)
- Fix issue with folder creation under INBOX. namespace (#1488349)
- Added mailto: protocol handler registration link in User Preferences (#1486580)
- Handle identity details box with an iframe (#1487020)
- Fix issue where some text from original message was missing on reply (#1488340)
- Fix autoselect_host() for login (#1488297)
- Changed license to GNU GPLv3+ with exceptions for skins & plugins
- Added address book widget on compose screen
- Use proper timezones from PHP's internal timezonedb (#1485592)
- Add separate pagesize setting for mail messages and contacts (#1488269)
- Deprecate $DB, $USER, $IMAP global variables, Use $RCMAIL instead
- Add option to set default font for HTML message (#1484137)
- Fix issues with big memory allocation of IMAP results
- Prevent from memory_limit exceeding when trying to parse big messages bodies (#1487424)
- Add possibility to add SASL mechanisms for SMTP in smtp_connect hook (#1487937)
- Mark (with different color) folders with recent messages (#1486234)
- Added About tab in Settings
- TinyMCE updated to 3.4.6
RELEASE 0.7.2
-------------
- Fix encoding of attachment with comma in name (#1488389)
- Fix handling of % character in IMAP protocol (#1488382)
- Fix duplicate names handling in addressbook searches (#1488375)
- Fix displaying of HTML messages from Disqus (#1488372)
- Disable E_STRICT warnings on PHP 5.4
- Prevent from folder selection on virtual folder collapsing (#1488346)
- Fix automatic unsubscribe of non-existent folders
- Fix double-quotes handling in recipient names
- User configurable setting how to display contact names in list
- Make contacts list sorting configurable for the admin/user
- Fix parse errors in DDL files for MS SQL Server
- Revert SORT=DISPLAY support, removed by mistake (#1488327)
- Add lost translation label in de_DE (#1488315)
- Fix drafts update issues when edited from preview pane (#1488314)
- Fix wrong variable name in rcube_ldap.php (#1488302)
- Make mime type detection based on filename extension to be case-insensitive
- Fix failure on MySQL database upgrade from 0.7 - text column can't have default value (#1488300)
RELEASE 0.7.1
-------------
- Fix bug in handling of base href and inline content (#1488290)
- Fix SQL Error when saving a contact with many email addresses (#1488286)
- Fix strict email address searching if contact has more than one address
- Remove duplicated 'organization' label (#1488287)
- Fix so editor selector is hidden when 'htmleditor' is listed in 'dont_override'
- Fix wrong (long) label usage (#1488283)
- Fix handling of INBOX's subfolders in special folders config (#1488279)
- Add ifModule statement for setting Options -Indexes in .htaccess file (#1488274)
- Fix crashes with eAccelerator (#1488256)
- Fix searching on IMAP servers without CHARSET specifier support (#1488271)
- Fix expanding folders during drag&drop (#1488260)
- Fix wrong postgres sequence name in upgrade from 0.6
- Fix broken CREATE INDEX queries in SQLite DDL files (#1488255)
RELEASE 0.7
-----------
- Make Roundcube render the Email Standards Project Acid Test correctly
- Replace prompt() with jQuery UI dialog (#1485135)
- Fix navigation in messages search results
- Improved handling of some malformed values encoded with quoted-printable (#1488232)
- Add possibility to do LDAP bind before searching for bind DN
- Fix handling of empty <U> tags in HTML messages (#1488225)
- Add content filter for embedded attachments to protect from XSS on IE [CVE-2012-1253] (#1487895)
- Use strpos() instead of strstr() when possible (#1488211)
- Fix handling HTML entities when converting HTML to text (#1488212)
- Fix fit_string_to_size() renders browser and ui unresponsive (#1488207)
- Fix handling of invalid characters in request (#1488124)
- Fix merging some configuration options in update.sh script (#1485864)
- Fix so TEXT key will remove all HEADER keys in IMAP SEARCH (#1488208)
- Fix handling contact photo url with https:// prefix (#1488202)
- Fix possible infinite redirect on attachment preview (#1488199)
- Improved clickjacking protection for browsers which don't support X-Frame-Options headers
- Fixed bug where similar folder names were highlighted wrong (#1487860)
- Fixed bug in handling link with '!' character in it (#1488195)
- Fixed bug where session ID's length was limited to 40 characters (#1488196)
- TinyMCE security issue: removed moxieplayer (embedding flv and mp4 is not supported anymore)
RELEASE 0.7-beta
----------------
- Fix handling of HTML form elements in messages (#1485137)
- Fix regression in setting recipient to self when replying to a Sent message (#1487074)
- Fix listing of folders in hidden namespaces (#1486796)
- Don't consider \Noselect flag when building folders tree (#1488004)
- Fix sorting autocomplete results (#1488084)
- Add option to set session name (#1486433)
- Add option to skip alternative email addresses in autocompletion
- Fix inconsistent behaviour of Compose button in Drafts folder, add Edit button for drafts
- Fix problem with parsing HTML message body with non-unicode characters (#1487813)
- Add option to define matching method for addressbook search (#1486564, #1487907)
- Make email recipients separator configurable
- Fix so folders with \Noinferiors attribute aren't listed in parent selector
- Fix handling of curly brackets in URLs (#1488168)
- Fix handling of dates (birthday/anniversary) in contact data (#1488147)
- Fix error on opening searched LDAP contact (#1488144)
- Fix redundant line break in flowed format (#1488146)
- Fix IDN address validation issue (#1488137)
- Fix JS error when dst_active checkbox doesn't exist (#1488133)
- Autocomplete LDAP records when adding contacts from mail (#1488073)
- Plugin API: added 'ready' hook (#1488063)
- Ignore DSN request when it isn't supported by SMTP server (#1487800)
- Make sure LDAP name fields aren't arrays (#1488108)
- Fixed imap test to non-default port when using ssl (#1488118)
- Force all files to be overwritten when updating (#1488117)
- Fix issue where it wasn't possible to change list view mode in folder manager for INBOX (#1488107)
- Fix namespace handling in special folders settings (#1488112)
- Disable time limit for CLI scripts (#1488109)
- Fix misleading display when chaning editor type (#1488104)
- Add loading indicator on contact delete
- Fix bug where after delete message rows can be added to the list of another folder (#1487752)
- Add notice on autocompletion that not all records were displayed
- Add option 'searchonly' for LDAP address books
- Add Priority filter to the messages list
- Cache synchronization using QRESYNC/CONDSTORE
- Trigger 'new_messages' hook for all checked folders (#1488083)
- Make date/time format user configurable; drop 'date_today' config option
- Fix setting title for truncated subject in IE (#1487128)
- Fix displaying multipart/alternative messages with only one part (#1487938)
- Rewritten messages caching:
Indexes are stored in a separate table, so there's no need to store all messages in a folder
Added threads data caching
Flags are stored separately, so flag change doesn't cause DELETE+INSERT, just UPDATE
- Improved FETCH response handling
- Improvements in response tokenization method
- Use 'From' and 'To' labels instead of 'Sender' and 'Recipient'
- Fix username case-insensitivity issue in MySQL (#1488021)
- Addressbook Saved Searches
- Added spellchecker exceptions dictionary (shared or per-user)
- Added possibility to ignore words containing caps, numbers, symbols (spellcheck_ignore_* options)
- Added 'priority' column on messages list (#1486782)
- Localize forwarded message header (#1488058)
RELEASE 0.6
-----------
- Fix bug where the last identity is used on reply (#1488101)
- Fix locked folder rename option on servers supporting RFC2086 only (#1488089)
- Fix session race conditions when composing new messages
- Fix encoding of LDAP contacts identifiers (#1488079)
- jQuery 1.6.4
- Fix handling of binary attachments encoded with quoted-printable (#1488065)
- Fix text-overflow:ellipsis issues on messages list in FF7 and Webkit (#1488061)
- Fix handling of links with IP address
- Fix compacting folder resets message list filter (#1488076)
RELEASE 0.6-rc
----------------
- Send X-Frame-Options headers to protect from clickjacking (#1487037)
- Fallback to mail_domain in LDAP variable replacements; added 'host' to 'user_create' hook arguments (#1488024)
- Fixed wrong vCard type parameter mobile (#1488067)
- Fixed vCard WORKFAX issue (#1488046)
- Add vCard's Profile URL support (#1488062)
- jQuery 1.6.3
- Fix imap_cache setting to values other than 'db' (#1488060)
- Fix handling of attachments inside message/rfc822 parts (#1488026)
- Make list of mimetypes that open in preview window configurable (#1487625)
- Added plugin hook 'message_part_get' for attachment downloads
- Added unique connection identifier to IMAP debug messages
- Fix image type check for contact photo uploads
RELEASE 0.6-beta
----------------
- Fixed selecting identity on reply/forward (#1487981)
- Add option to hide selected LDAP addressbook on the list
- Add client-side checking of uploaded files size
- Add newlines between organization, department, jobtitle (#1488028)
- Recalculate date when replying to a message and localize the cite header (#1487675)
- Fix handling of email addresses with quoted local part (#1487939)
- Fix EOL character in vCard exports (#1487873)
- Added optional "multithreading" autocomplete feature
- Plugin API: Added 'config_get' hook
- Fixed new_user_identity plugin to work with updated rcube_ldap class (#1487994)
- Plugin API: added folder_delete and folder_rename hooks
- Added possibility to undo last contact delete operation
- Fix sorting of contact groups after group create (#1487747)
- Add optional textual upload progress indicator (#1486039)
- Fix parsing URLs containing commas (#1487970)
- Added vertical splitter for books/groups list in addressbook (#1487923)
- Improved namespace roots handling in folder manager
- Added searching in all addressbook sources
- Added addressbook source selection in contacts import
- Implement LDAPv3 Virtual List View (VLV) for paged results listing
- Use 'address_template' config option when adding a new address block (#1487944)
- Added addressbook advanced search
- Add popup with basic fields selection for addressbook search
- Case-insensitive matching in autocompletion (#1487933)
- Added option to force spellchecking before sending a message (#1485458)
- Fix handling of "<" character in contact data, search fields and folder names (#1487864)
- Fix saving "<" character in identity name and organization fields (#1487864)
- Added option to specify to which address book add new contacts
- Added plugin hook for keep-alive requests
- Store user preferences in session when write-master is not available and session is stored in memcache, write them later
- Improve performence of folder manager operations
- Fix default_port option handling in Installer when config.inc.php file exists (#1487925)
- Removed option focus_on_new_message, added newmail_notifier plugin
- Added general rcube_cache class with Memcache and APC support
- Improved caching performance by skipping writes of unchanged data
- Option enable_caching replaced by imap_cache and messages_cache options
- Fix WORKFAX saving in address book (#1487910)
- Add forward-as-attachment feature
- jQuery-1.6.2 (#1487913, #1487144)
- Improve display name composition when saving contacts (#1487143)
- Fix problems with subfolders of INBOX folder on some IMAP servers (#1487725)
- Fix handling of folders that doesn't belong to any namespace (#1487637)
- Enable multiselection for attachments uploading in capable browsers (#1485969)
- Add possibility to change HTML editor configuration by skin
- Fix a bug where selecting too many contacts would produce too large URI request (#1487892)
- Improve performance by including files with absolute path (#1487849)
- Move folder name truncation to client/skin (#1485412)
- Added plugin hook for request token creation
- Replace LDAP vars in group queries (#1487837)
- Fix vcard folding with uncode characters (#1487868)
- Keep all submitted data if contact form validation fails (#1487865)
- Handle uncode strings in rcube_addressbook::normalize_string() (#1487866)
- Fix handling of debug_level=4 in ajax requests (#1487831)
- Enable TinyMCE's contextmenu (#1487014)
- Allow multiple concurrent compose sessions
- New config option for custom logo
- Allow skins to define/override texts with <roundcube:label />
- Add simple ACL rights/namespace handling in folder manager
- Force IE to send referers (#1487806)
- Better display of vcard import results (#1485457)
- Improved vcard import
- Interactive update script with improved DB schema check
- Fix problem with contactgroupmembers table creation on MySQL 4.x, add index on contact_id column
- Add LDAP SASL bind and proxy authentication (#1486692)
- Replying to a sent message puts the old recipient as the new recipient (#1487074)
- Fulltext search over (almost) all data for contacts
- Extend address book with rich contact information
RELEASE 0.5.4
-------------
- Fix XSS vulnerability in UI messages [CVE-2011-2937] (#1488030)
RELEASE 0.5.3
-------------
- Fix identities "reply-to" and "bcc" fields have a bogus value when left empty (#1487943)
- Fix issue which cases IMAP disconnection when encrypt() method was used (#1487900)
- Fix some CSS issues in Settings for Internet Explorer
- Fixed handling of folder with name "0" in folder selector
- Fix bug where messages were deleted instead moved to trash folder after Shift key was used (#1487902)
- Fix relative URLs handling according to a <base> in HTML (#1487889)
- Fix handling of top-level domains with more than 5 chars or unicode chars (#1487883)
- Fix usage of non-standard HTTP error codes (#1487797)
- Fix PHP warning on mistaken in_array() usage (#1487901)
RELEASE 0.5.2
-------------
- TinyMCE 3.4.2 now compatible with IE9
- PEAR::Net_SMTP 1.5.2, fixed timeout issue (#1487843)
- Fix bug where template name without plugin prefix was used in render_page hook
- Support 'abort' and 'result' response in 'preferences_save' hook, add error handling
- Fix bug where some content would cause hang on html2text conversion (#1487863)
- Improve space-stuffing handling in format=flowed messages (#1487861)
- Fix bug where some dates would produce SQL error in MySQL (#1487856)
- Added workaround for some IMAP server with broken STATUS response (#1487859)
- Fix bug where default_charset was not used for text messages (#1487836)
- Stateless request tokens. No keep-alive necessary on login page (#1487829)
- Force names of unique constraints in PostgreSQL DDL
- Add code for prevention from IMAP connection hangs when server closes socket unexpectedly
- Remove redundant DELETE query (for old session deletion) on login
- Get around unreliable rand() and mt_rand() in session ID generation (#1486281)
- Fix some emails are not shown using Cyrus IMAP (#1487820)
- Fix handling of mime-encoded words with non-integral number of octets in a word (#1487801)
- Fix parsing links with non-printable characters inside (#1487805)
- Fixed de_CH Localization bugs (#1487773)
- Add variable for 'Today' label in date_today option (#1486120)
- Fix dont_override setting does not override existing user preferences (#1487664)
- Use only one from IMAP authentication methods to prevent login delays (1487784)
- Support strftime format in date_today option
- Fix SQL query in rcube_user::query() so it uses index on MySQL again
- Removed redundant </form> tags from contact add/edit pages
- Fix CSS error in contact details screen on IE7 (#1487775)
RELEASE 0.5.1
-------------
- Fix handling of attachments with invalid content type (#1487767)
- Add workaround for DBMail's bug http://www.dbmail.org/mantis/view.php?id=881 (#1487766)
- Use IMAP's ID extension (RFC2971) to print more info into debug log
- Security: add optional referer check to prevent CSRF in GET requests
- Fix email_dns_check setting not used for identities/contacts (#1487740)
- Fix ICANN example addresses doesn't validate (#1487742)
- Security: protect login form submission from CSRF [CVE-2011-1491]
- Security: prevent from relaying malicious requests through modcss.inc [CVE-2011-1492]
- Fix handling of non-image attachments in multipart/related messages (#1487750)
- Fix IDNA support when IDN/INTL modules are in use (#1487742)
- Fix handling of invalid HTML comments in messages (#1487759)
- Fix parsing FETCH response for very long headers (#1487753)
- Fix add/remove columns in message list when message_sort_order isn't set (#1487751)
- Check mime headers before attempt to parse them (#1487745)
- Quote header values in show_additional_headers plugin (#1487744)
- Fix settings UI on IE 6 (#1487724)
- Remove double borders in folder listing (#1487713)
- Separate full message headers UI element from headers table (#1487715)
- Add part MIME ID to message_part_* hooks (#1487718)
- Improve parsing of MS Outlook vCards (#1487716)
- Updated PEAR::Net_Socket to 1.0.10
- Updated PEAR::Net_IDNA2 to 0.1.1
- Fix handling of comments inside an email address spec. (#1487673)
- Show full mail subject as title when hovering a cut subject link (#1487128)
- Fix randomly disappearing folders list in IE (#1487704)
- Fix list column add/removal in IE (#1487703)
- Fix login redirect issues (#1487686)
- Require PHP 5.2.1 or greater
- Fix %h/%z variables in username_domain option (#1487701)
- Workaround for setting charset in case of malformed bodystructure response (#1487700)
- Fix impossible to subscribe to protected folders (#1487656)
- Fix setting timezone in Preferences (#1487705)
RELEASE 0.5
-----------
- Fix double-login/session issue (#1487104)
- Wrap HTML parts with <html><body> and add Doctype declaration (#1487098)
- Make rcube_autoload silently skip unknown classes (#1487109)
- Fix charset detection in vcards with encoded values (#1485542)
- Better CSS cursors for splitters (#1486874)
- Show the same message only once (#1487641)
- Fix namespaces handling (#1487649)
- Add handling of multifolder METADATA/ANNOTATION responses
- Fix handling of INBOX when personal namespace prefix is non-empty (#1487657)
- Fix handling square brackets in links (#1487672)
- Add description of 'use_https' option in main.inc.php.dist file
RELEASE 0.5-RC
--------------
- Plugin API: Add 'pass' argument in 'authenticate' hook (#1487134)
- Fix attachments of type message/rfc822 are not listed on attachments list
- Add 'login_lc' config option for case-insensitive authentication (#1487113)
- Fix window is blur'ed in IE when selecting a message (#1487316)
- Fix cursor position on compose form in Webkit browsers (#1486674)
- Fix setting charset of attachment filenames (#1487122)
- Allow setting autocomplete attribute for all inputs separately (#1487313)
- New Folder Manager UI
- Fix invalid Request when creating a folder (#1487443)
- Add folder size and quota indicator in folder manager (#1485780)
- Add possibility to move a subfolder into root folder (#1486791)
- Fix copying all messages in a folder copies only messages from current page
- Improve performance of moving or copying of all messages in a folder
- Fix plaintext versions of HTML messages don't contain placeholders for emotions (#1485206)
- Improve performance of folder rename and delete actions
- Better support for READ-ONLY and NOPERM responses handling (#1487083)
- Add confirmation message on purge/expunge command response
- Fix handling of untagged responses for AUTHENTICATE command (#1487450)
- Add username and IP address to log message on unsuccessful login (#1487626)
- Improved Mail-Followup-To and Mail-Reply-To headers handling
- Fix charset conversion for text attachments without charset specification (#1487634)
RELEASE 0.5-BETA
----------------
- Make session data storage more robust against garbage session data (#1487136)
- Config option for autocomplete on login screen
- Allow plugin templates to include local files (#1487133)
- List groups in address detail view and allow to subscribe/unsubscribe from there (#1486753)
- Messages caching: performance improvements, fixed syncing, fixes related with #1486748
- Add link to identities in compose window (#1486729)
- Add Internationalized Domain Name (IDNA) support (#1483894)
- Add option to automatically send read notifications for known senders (#1485883)
- Add option to "Return receipt" will be always checked (#1486352)
- Fix HTML to plain text conversion doesn't handle citation blocks (#1486921)
- Use custom sorting when SORT is disabled by IMAP admin (#1486959)
- Allow setting some washtml options from plugin (#1486578)
- Add option do bind for an individual LDAP address book (#1486997)
- Change reply prefix to display email address only if sender name doesn't exist (#1486550)
- Plugin API: improved 'abort' flag handling, added 'result' item in some hooks (#1486914)
- Fix mailto optional params in plain text messages aren't handled (#1487026)
- Add Reply-to-List feature (#1484252)
- Add Mail-Followup-To/Mail-Reply-To support (#1485547)
- Fix confirmation message isn't displayed after sending mail on Chrome (#1486177)
- Fix keyboard doesn't work with autocomplete list with Chrome (#1487029)
- Improve tabs to fixed width and add tabs in identities info (#1486974)
- Add unique index on users.username+users.mail_host
- Make htmleditor option more consistent and add option to use HTML on reply to HTML message (#1485840)
- Use empty envelope sender address for message disposition notifications (RFC 2298.3)
- Support SMTP Delivery Status Notifications - RFC 3461 (#1486142)
- Use css sprite image for messages list
- Add (different) attachment icon for messages of type multipart/report (#1486165)
- Prevent from inserting empty link when composing HTML message (#1486944)
- Add caching support in id2uid and uid2id functions (#1487019)
- Add SASL proxy authentication for SMTP (#1486693)
- Improve displaying of UI messages (#1486977)
- Fix double e-mail filed in identity form (#1487054)
- Display IMAP errors for LIST/THREAD/SEARCH commands (#1486905)
- Add LITERAL+ (IMAP4 non-synchronizing literals) support (RFC 2088)
- Add separate column for message status icon (#1486665)
- Add ACL extension support into IMAP classes (RFC 4314)
- Add ANNOTATEMORE extension support into IMAP classes (draft-daboo-imap-annotatemore)
- Add METADATA extension support into IMAP classes (RFC 5464)
- Fix decoding of e-mail address strings in message headers (#1487068)
- Fix handling of attachments when Content-Disposition is not inline nor attachment (#1487051)
- Improve performance of unseen messages counting (#1487058)
- Improve performance of messages counting using ESEARCH extension (RFC4731)
- Add LIST-STATUS support in rcube_imap_generic class (RFC 5819)
- Add SASL-IR support in IMAP (RFC 4959)
- Add LOGINDISABLED support (RFC 2595)
- Add support for AUTH=PLAIN in IMAP authentication
- Re-implemented SMTP proxy authentication support
- Add support for IMAP proxy authentication (#1486690)
- Add support for AUTH=DIGEST-MD5 in IMAP (RFC 2831)
- Fix parent folder with unread subfolder not bold when message is open (#1487078)
- Add basic IMAP LIST's \Noselect option support
- Add support for selection options from LIST-EXTENDED extension (RFC 5258)
- Don't list subscribed but non-existent folders (#1486225)
- Fix handling of URLs with tilde (~) or semicolon (;) character (#1487087, #1487088)
- Plugin API: added 'contact_form' hook
- Add SORT=DISPLAY support (RFC 5957)
- Plugin API: add possibility to disable plugin in AJAX mode, 'noajax' property
- Plugin API: add possibility to disable plugin in framed mode, 'noframe' property
- Improve performance of setting IMAP flags using .SILENT suffix
- Improve performance of message cache status checking with skip_disabled=true
- Support contact's email addresses up to 255 characters long (#1487095)
- Add option to place replies in the folder of the message being replied to (#1485945)
- Add missing confirmation/error messages on contact/group/message actions (#1486845)
- Add 'loading' message on message move/copy/delete/mark actions
- Improve responsiveness of messages displaying (#1486986)
- Add option for minimum length of autocomplete's string (#1486428)
- Fix operations on messages in unsubscribed folder (#1487107)
- Add support for shared folders (#1403507)
- Fix handling of folders with name "0" (#1487119)
- Fix handling of folders with "<>" characters in name
- jQuery 1.4.4
- Fix handling of HTML entity strings in plain text messages
- Fix focused elements aren't unfocused when clicking on the list (#1487123)
- Fix error in MSSQL DDL scripts (#1487112)
- Lock submit button in onsubmit event on login page (#1487036)
- Don't set attachment's charset in Content-type header (#1487122)
- Fix handling of message bodies (quoted-printable encoded) with NULL characters (#1486189)
- Add workaround for MSOE's multipart/related messages with non-related attachments
RELEASE 0.4.2
-------------
- Fix handling of backslash as IMAP delimiter
- Fix charset replacement in HTML message bodies (#1487021)
- Fix: contact group input is empty when using rename action more than once on the same group record
- Fix "Server Error! (Not Found)" when using utils/save-pref action (#1487023)
- Fix handling of Thunderbird's vCards (#1487024)
RELEASE 0.4.1
-------------
- Fix space-stuffing in format=flowed messages (#1487018)
- Fix msgexport.sh now using the new imap wrapper
- Avoid displaying password on shell (#1486947)
- Only lower-case user name if first login attempt failed (#1486393)
- Make alias setting in squirrelmail_usercopy plugin configurable (patch by pommi, #1487007)
- Prevent from saving a non-existing skin path in user prefs (#1486936)
- Improve handling of single-part messages with bogus BODYSTRUCTURE (#1486898)
- Fix path to SQL files when using pgsql/mysqli/sqlsrv drivers (#1486902)
- Fix upgrade script for SQLite (#1486903)
- Fixes in SQL init script + added update script for MSSQL database
- Remove redundant date in syslog messages (#1486945)
- Fix contacts list page controls when a group is selected (#1486946)
- Fix SMTP test in Installer (#1486952)
- Fix "Select all" causes message to be opened in folder with exactly one message (#1486913)
- Fix Tab key doesn't work in HTML editor in Google Chrome (#1486925)
- Fix TinyMCE uses zh_CN when zh_TW locale is set (#1486929)
- Fix TinyMCE buttons are hidden in Opera (#1486922)
- Fix JS error on IE when trying to send HTML message with enabled spellchecker (#1486940)
- Display inline images with known extensions and non-image content-type (#1486934)
- Fix "Threaded" checkbox after subfolder creation (#1486928)
- Fix timezone string in sent mail (#1486961)
- Show disabled checkboxes for protected folders instead of dots (#1485498)
- Added fieldsets in Identity form, added 'identity_form' hook
- Re-added 'Close' button in upload form (#1486930, #1486823)
- Fix handling of charsets with LATIN-* label
- Fix messages background image handling in some cases (#1486990)
- Fix format=flowed handling (#1486989)
- Fix when IMAP connection fails in 'get' action session shouldn't be destroyed (#1486995)
- Fix list_cols is not updated after column dragging (#1486999)
- Support %z variable in host configuration options (#1487003)
RELEASE 0.4
-----------
- Fix disapearing upload form disapears when user selects a file on Safari (#1486823)
- Don't replace error messages with loading info (#1486300)
- Fix JS errors on compose mode switch (#1486870)
- Fix message structure parsing when it lacks optional fields (#1486881)
- Include all recipients in sendmail log
- Support HTTP_X_FORWARDED_PROTO header for HTTPS detecting (#1486866)
- Fix default IMAP port configuration (#1486864)
- Create Sent folder when starting to compose a new message (#1486802)
- Fix handling of messages with Content-Type: application/* and no filename (#1484050)
- Improved compose screen: resizable body and attachments list, vertical splitter, options menu
- Fix RC forgets search results (#1483883)
- TinyMCE 3.3.7
- Improve parsing of styled empty tags in HTML messages (#1486812)
- Add %dc variable support in base_dn/bind_dn config (#1486779)
- Add button to hide/unhide the preview pane (#1484215)
- Fix no-cache headers on https to prevent content caching by proxies (#1486798)
- Fix attachment filenames broken with TNEF decoder using long filenames (#1486795)
- Use user's timezone in Date header, not server's timezone (#1486119)
- Add option to set separate footer for HTML messages (#1486660)
- Add real SMTP error description to displayed error messages (#1485927)
- Fix some IMAP errors handling when opening the message (#1485443)
- Fix related parts aren't displayed when got mimetype other than image/* (#1486432)
- Multiple identity and database support for squirrelmail_usercopy plugin (#1486517)
- Support dynamic hostname (%d/%n) variables in configuration options (#1485438)
- Add 'messages_list' hook (#1486266)
- Add request* event triggers in http_post/http_request (#1486054)
- Fix use RFC-compliant line-delimiter when saving messages on IMAP (#1486712)
- Add 'imap_timeout' option (#1486760)
- Fix forwarding of messages with winmail attachments
- Fix handling of uuencoded attachments in message body (#1485839)
- Added list_mailboxes hook in rcube_imap::list_unsubscribed() (#1486668)
- Fix wrong message on file upload error (#1486725)
- Add support for data URI scheme [RFC2397] (#1486740)
- Added 'actionbefore', 'actionafter', 'responsebefore', 'responseafter' events
- Fix double-addition of e-mail domain to content ID in HTML images
- Read and send messages with format=flowed (#1484370), fixes word wrapping issues (#1486543)
- Fix duplicated attachments when forwarding a message (#1486487)
- Fix message/rfc822 attachments containing only attachments are not parsed properly (#1486743)
- Fix %00 character in winmail.dat attachments names (#1486738)
- Fix handling errors of folder deletion (#1486705)
- Parse untagged CAPABILITY response for LOGIN command (#1486742)
- Renamed all php-cli scripts to use .sh extension
- Some files from /bin + spellchecking actions moved to the new 'utils' task
- Added thread tree icons
- Extend contact groups support (#1486682)
- Fix check-recent action issues and performance (#1486526)
- Fix messages order after checking for recent (#1484664)
- Fix autocomplete shows entries without email (#1486452)
- Fix listupdate event doesn't trigger on search response (#1486708)
- Fix select_all_mode value after selecting a message (#1486720)
- Set focus to editor on reply in HTML mode (#1486632)
- Fix composing in HTML jumps cursor to body instead of recipients (#1486674)
- Allow columns order change per user - drag&drop (#1485795)
- Add References header in read receipt (#1486681)
- Fix database constraint violation when opening a message (#1486696)
- Add 'loading' message while login is in progress (#1486667)
- Fix quota_zero_as_unlimited (#1486662)
- Fix folder subscription checking (#1486684)
- Fix INBOX appears (sometimes) twice in mailbox list (#1486672)
- Fix listing of attachments of some types e.g. "x-epoc/x-sisx-app" (#1486653)
- Fix DB Schema checking when some db_table_* options are not set (#1486654)
RELEASE 0.4-beta
----------------
- Add sizelimit and timelimit variables in LDAP config (#1486544)
- Hide IMAP host dropdown when single host is defined (#1486326)
- Add images pre-loading on login page (#1451160)
- Add HTTP_X_REAL_IP and HTTP_X_FORWARDED_FOR to successful logins log (#1486441)
- Fix setting spellcheck languages with extended codes (#1486605)
- Fix messages list scrolling in FF3.6 (#1486472)
- Fix quicksearch input focus (#1486637)
- Always set changed date when flagging a DB record as deleted + provide a cleanup script
- Fix address book/group selection (#1486619)
- Assign newly created contacts to the active group (#1486626)
- Added option not to mark messages as read when viewed in preview pane (#1485012)
- Allow plugins modify the Sent folder when composing (#1486548)
- Added optional (max_recipients) support to restrict total number of recipients per message (#1484542)
- Re-organize editor buttons, add blockquote and search buttons
- Make possible to write inside or after a quoted html message (#1485476)
- Fix bugs on unexpected IMAP connection close (#1486190, #1486270)
- Iloha's imap.inc rewritten into rcube_imap_generic class
- Added contact groups in address book (not finished yet)
- Added PageUp/PageDown/Home/End keys support on lists (#1486430)
- Added possibility to select all messages in a folder (#1484756)
- Added 'imap_force_caps' option for after-login CAPABILITY checking (#1485750)
- Password: Support dovecotpw encryption
- TinyMCE 3.3.1
- Implemented messages copying using drag&drop + SHIFT (#1484086)
- Improved performance of folders operations (#1486525)
- Fix blocked.gif attachment is not attached to the message (#1486516)
- Managesieve: import from Horde-INGO
- Managesieve: support for more than one match (#1486078)
- Managesieve: support for selectively disabling rules within a single sieve script (#1485882)
- Threaded message listing now available
- Added sorting by ARRIVAL and CC
- Message list columns configurable by the user
- Removed 'index_sort' option, now we're using empty 'message_sort_col' for this
- virtuser_query: support other identity data (#1486148)
- Options virtuser_* replaced with virtuser_* plugins
- Plugin API: Implemented 'email2user' and 'user2email' hooks
- Fix forwarding message omits CC header (#1486305)
- Add 'default_charset' option to user preferences (#1485451)
- Add 'delete_always' option to user preferences
- Support/Require tls:// prefix in 'smtp_server' option for TLS connections
- Fix inconsistent behaviour of 'delete_always' option (#1486299)
- Fix deleting all messages from last list page (#1486293)
- Flag original messages when sending a draft (#1486203)
- Changed signature separator when top-posting (#1486330)
- Let the admin define defaults for search modifiers (#1485897)
- Fix long e-mail addresses validation (#1486453)
- Remember search modifiers in user prefs (#1486146)
- Added force_7bit option to force MIME encoding of plain/text messages (#1486510)
- Use case sensitive check when checking for default folders (#1486346)
- Fix checking for new mail: now checks unseen count of inbox (#1485794)
- Improve performance by avoiding unnecessary updates to the session table (#1486325)
- Fix invalid <font> tags which cause HTML message rendering problems (#1486521)
- Fix CVE-2010-0464: Disable DNS prefetching (#1486449)
- Fix Received headers to behave better with SpamAssassin (#1486513)
- Password: Make passwords encoding consistent with core, add 'password_charset' global option (#1486473)
- Fix adding contacts SQL error on mysql (#1486459)
- Squirrelmail_usercopy: support reply-to field (#1486506)
- Fix IE spellcheck suggestion popup issue (#1486471)
- Fix email address auto-completion shows regexp pattern (#1486258)
- Fix merging of configuration parameters: user prefs always survive (#1486368)
- Fix quota indicator value after folder purge/expunge (#1486488)
- Fix external mailto links support for use as protocol handler (#1486037)
- Fix attachment excessive memory use, support messages of any size (#1484660)
- Fix setting task name according to auth state
- Password: fix vpopmaild driver (#1486478)
- Add workaround for MySQL bug [http://bugs.mysql.com/bug.php?id=46293] (#1486474)
- Fix quoted text wrapping when replying to an HTML email in plain text (#1484141)
- Fix handling of extended mailto links (with params) (#1486354)
- Fix sorting by date of messages without date header on servers without SORT (#1486286)
- Fix inconsistency when not using default table names (#1486467)
- Fix folder rename/delete buttons do not appear on creation of first folder (#1486468)
- Fix character set conversion fails on systems where iconv doesn't accept //IGNORE (#1486375)
- Log in performance: Create default folders on first login only
- Import contacts into the selected address book (by Phil Weir)
- Add support for MDB2's 'sqlsrv' driver (#1486395)
- Use jQuery-1.4
- Removed problematic browser-caching of messages
- Fix incompatybility with suhosin.executor.disable_emodifier (#1486321)
- Use PLAIN auth when CRAM fails and imap_auth_type='check' (#1486371)
- Fix removal of <title> tag from HTML messages (#1486432)
- Fix 'force_https' to specified port when URL contains a port number (#1486411)
- Fix to-text converting of HTML entities inside b/strong/th/hX tags (#1486422)
- Bug in spellchecker suggestions when server charset != UTF8 (#1486406)
- Managesieve: Fix requires generation for multiple actions (#1486397)
- Fix LDAP problem with special characters in RDN (#1486320)
- Improved handling of message parts of type message/rfc822
- Plugin API: added 'quota' hook
- Fix parsing conditional comments in HTML messages (#1486350)
- Use built-in json_encode() for proper JSON format in AJAX replies
- Allow setting only selected params in 'message_compose' hook (#1486312)
- Plugin API: added 'message_compose_body' hook (#1486285)
- Fix counters of all folders are checked in 'getunread' action with check_all_folders disabled (#1486128)
- Fix displaying alternative parts in messages of type message/rfc822 (#1486246)
- Fix possible messages exposure when using Roundcube behind a proxy (#1486281)
- Fix unicode para and line separators in javascript response (#1486310)
- Additional_message_headers: allow unsetting headers, support plugin's config file (#1486268)
- Fix displaying of hidden directories in skins list (#1486301)
- Fix open_basedir restriction error when reading skins list (#1486304)
- Fix pasting from Office apps into html editor (#1486271)
- Fix empty <a> tags parsing (#1486272)
- Don't cut off attachment names when using non-RFC2231 encoding (#1485515)
- Allow inserting signatures above replied message body (#1484272)
- Managesieve 2.0: multi-script support
- Fix imap_auth_type regression (#1486263)
RELEASE 0.3.1
------------------
- Specify toolbar container in compose template (#1486247)
- Fix $_SERVER['HTTPS'] check for SSL forcing on IIS (#1486243)
- Avoid unnecessary page loads for selected tab (#1486032)
- Fix quota indicator issues by content generation on client-size (#1486197, #1486220)
- Don't display disabled sections in Settings (#1486099)
- Added server-side e-mail address validation with 'email_dns_check' option (#1485857)
- Fix login page loading into an iframe when session expires (#1485952)
- Allow setting port number in 'force_https' option (#1486091)
- Option 'force_https' replaced by 'force_https' plugin
- Fix IE issue with non-UTF-8 characters in AJAX response (#1486159)
- Partially fixed "empty body" issue by showing raw body of malformed message (#1486166)
- Fix importing/sending to email address with whitespace (#1486214)
- Added XIMSS (CommuniGate) driver for Password plugin
- Fix newly attached files are not saved in drafts w/o editing any text (#1486202)
- Added attachment upload indicator with parallel upload (#1486058)
- Use default_charset for bodies of messages without charset definition (#1486187)
- Password: added cPanel driver
- Fix return to first page from e-mail screen (#1486105)
- Fix handling HTML comments in HTML messages (#1486189)
- Fix folder/messagelist controls alignment - icons used (#1486072)
- Fix LDAP addressbook shows 'Contact not found' error sometimes (#1486178)
- Fix cache status checking + improve cache operations performance (#1486104)
- Prevent from setting INBOX as any of special folders (#1486114)
- Fix regular expression for e-mail address (#1486152)
- Fix Received header format
- Implemented sorting by message index - added 'index_sort' option (#1485936)
- Fix dl() use in installer (#1486150)
- Added 'ldap_debug' option
- Fix "Empty startup greeting" bug (#1486085)
- Fix setting user name in 'new_user_identity' plugin (#1486137)
- Fix incorrect count of new messages in folder list when using multiple IMAP clients (#1485995)
- Fix all folders checking for new messages with disabled caching (#1486128)
- Support skins in 'archive' and 'markasjunk' plugins
- Added 'html_editor' hook (#1486068)
- Fix DB constraint violation when populating messages cache (#1486052)
- Password: added password strength options (#1486062)
- Fix LDAP partial result warning (#1485536)
- Fix delete in message view deletes permanently with flag_for_deletion=true (#1486101)
- Use faster/secure mt_rand() (#1486094)
- Fix roundcube hangs on empty inbox with bincimapd (#1486093)
- Fix wrong headers for IE on servers without $_SERVER['HTTPS'] (#1485926)
- Force IE style headers for attachments in non-HTTPS session, 'use_https' option (#1485655)
- Check 'post_max_size' for upload max filesize (#1486089)
- Password Plugin: Fix %d inserts username instead of domain (#1486088)
- Fix rcube_mdb2::affected_rows() (#1486082)
RELEASE 0.3-stable
------------------
- Fix gn and givenName should be synonymous in LDAP addressbook (#1485892)
- Add mail_domain to LDAP email entries without @ sign (#1485201)
- Fix saving empty values in LDAP contact data (#1485781)
- Fix LDAP contact update when RDN field is changed (#1485788)
- Fix LDAP attributes case senitivity problems (#1485830)
- Fix LDAP addressbook browsing when only one directory is used (#1486022)
- Fix endless loop on error response for APPEND command (#1486060)
- Don't require date.timezone setting in installer (#1485989)
- Fix date sorting problem with Courier IMAP server (#1486065)
- Unselect pressed buttons on mouse up (#1485987)
- Don't set php_value error_log in .htaccess but mention in INSTALL (#1485924)
- Fix too small status/flag/attachment columns in Safari 4 (#1486063)
- Fix selection disabling while dragging splitter in webkit browsers (#1486056)
- Added 'new_messages' plugin hook (#1486005)
- Added 'logout_after' plugin hook (#1486042)
- Added 'message_compose' hook
- Added 'imap_connect' hook (#1485956)
- Fix vcard_attachments plugin (#1486035)
- Updated PEAR::Auth_SASL to 1.0.3 version
- Use sequence names only with PostgreSQL (#1486018)
- Re-designed User Preferences interface
- Fix MS SQL DDL (#1486020)
- Fix rcube_mdb2.php: call to setCharset not implemented in mssql driver (#1486019)
- Added 'display_next' option
- Fix rcube_mdb2::unixtimestamp for MS SQL (#1486015)
- Fix HTML washing to respect character encoding
- Fix endless loop in iil_C_Login() with Courier IMAP (#1486010)
- Fix #messagemenu display on IE (#1486006)
- Speedup UI by using sprites for (toolbar) buttons
- Fix charset names with X- prefix handling
- Fix displaying of HTML messages with unknown/malformed tags (#1486003)
RELEASE 0.3-RC1
---------------
- Fix import of vCard entries with params (#1485453)
- Fix HTML messages output with empty block elements (#1485974)
- Use request tokens to protect POST requests from CSRF [CVE-2009-4076, CVE-2009-4077]
- Added hook when killing a session
- Added hook to write_log function (#1485971)
- Performance improvements by use UID commands (#1485690)
- Fix HTML editor tabIndex setting (#1485972)
- Added 'imap_debug' and 'smtp_debug' options
- Support strftime's format modifiers in date_* options (#1484806)
- Support %h variable in 'smtp_server' option (#1485766)
- Show SMTP errors in browser (#1485927)
- Allow WBR tag in HTML message (#1485960)
- Use spl_autoload_register() instead of __autoload (#1485947)
- Add hook for identities listing (#1485958)
- Trigger hook 'smtp_connect' when opening an SMTP connection (#1485954)
- Added config option to enforce HTTPS connections
- Fix non-unicode characters caching in unicode database (#1484608)
- Performance improvements of messages caching
- Fix empty Date header issue (#1485923)
- Open collapsed folders during drag & drop (#1485914)
- Fixed link text replacements (#1485789)
- Also trigger 'insertrow' events on page load (#1485826)
- No link on subject in IE browsers (#1484913)
- Fixed filename encoding according to RFC2231 (#1485875)
- Added message Edit feature (#1483891, #1484440)
- Fix message Etag generation for counter issues (#1485623)
- Fix messages searching on MailEnable IMAP (#1485762)
- Fixed many 'skip_deleted' issues (#1485634)
- Fixed messages list sorting on servers without SORT capability
- Colorized signatures in plain text messages
- Reviewed/fixed skip_deleted/read_when_deleted/flag_for_deletion options handling in UI
- Fix displaying of big maximum upload filesize (#1485889)
- Added possibility to invert messages selection
- After move/delete from 'show' action display next message instead of messages list (#1485887)
- Fixed problem with double quote at the end of folder name (#1485884)
- Speedup UI by using CSS sprites and etags/expires/deflate in Apache config (#1484858,#1485800)
- Support UID EXPUNGE: remove only moved/deleted messages
- Add drag cancelling with ESC key (#1484344)
- Support initial identity name from virtuser_query (#1484003)
- Added message menu, removed Print and Source buttons
- Added possibility to save message as .eml file (#1485861)
- Added 1 minute interval in autosave options (#1485854)
- Support UTF-7 encoding in messages (#1485832)
- Better support for malformed character names (#1485758)
RELEASE 0.3-BETA
----------------
- Plugin API + jQuery engine
- Added possibility to encrypt received header, option 'http_received_header_encrypt',
added some more logic in encrypt/decrypt functions for security
- Fix Answered/Forwarded flag setting for messages in subfolders
- Fix autocomplete problem with capital letters (#1485792)
- Support UUencode content encoding (#1485839)
- Minimize chance of race condition in session handling (#1485659, #1484678)
- Fix session handling on non-session SQL query error (#1485734)
- Fix html editor mode setting when reopening draft message (#1485834)
- Added quick search box menu (#1484304)
- Fix wrong column sort order icons (#1485823)
- Updated TinyMCE to 3.2.3 version
- Fix attachment names encoding when charset isn't specified in attachment part (#1484969)
- Fix message normal priority problem (#1485820)
- Fix autocomplete spinning wheel does not disappear (#1485804)
- Added log_date_format option (#1485709)
- Fix text wrapping in HTML editor after switching from plain text to HTML (#1485521)
- Fix auto-complete function hangs with plus sign (#1485815)
- Fix AJAX requests errors handler (#1485000)
- Speed up message list displaying on IE
- Fix read/write database recognition (#1485811)
RELEASE 0.2.2
-------------
- Fix quicksearchbox look in Chrome and Konqueror (#1484841)
- Fix UTF-8 byte-order mark removing (#1485514)
- Fix folders subscribtions on Konqueror (#1484841)
- Fix debug console on Konqueror and Safari
- Fix messagelist focus issue when modifying status of selected messages (#1485807)
- Support STARTTLS in IMAP connection (#1485284)
- Fix DEL key problem in search boxes (#1485528)
- Support several e-mail addresses per user from virtuser_file (#1485678)
- Fix drag&drop with scrolling on IE (#1485786)
- Fix adding signature separator in html mode (#1485350)
- Fix opening attachment marks message as read (#1485803)
- Fix 'temp_dir' does not support relative path under Windows (#1484529)
- Fix "Initialize Database" button missing from installer (#1485802)
- Fix compose window doesn't fit 1024x768 window (#1485396)
- Fix service not available error when pressing back from compose dialog (#1485552)
- Fix using mail() on Windows (#1485779)
- Fix word wrapping in message-part's <PRE>s for printing (#1485787)
- Fix incorrect word wrapping in outgoing plaintext multibyte messages (#1485714)
- Fix double footer in HTML message with embedded images
- Fix TNEF implementation bug (#1485773)
- Fix incorrect row id parsing for LDAP contacts list (#1485784)
- Fix 'mode' parameter in sqlite DSN (#1485772)
RELEASE 0.2.1
------------------
- Use US-ASCII as failover when Unicode searching fails (#1485762)
- Fix errors handling in IMAP command continuations (#1485762)
- Fix FETCH result parsing for servers returning flags at the end of result (#1485763)
- Fix datetime columns defaults in mysql's DDL (#1485641)
- Fix attaching more than nine inline images (#1485759)
- Support 'UNICODE-1-1-UTF-7' alias for UTF-7 encoding (#1485758)
- Fix mime-type detection using a hard-coded map (#1485311)
- Don't return empty string if charset conversion failed (#1485757)
- Disable concurrent autocomplete query results display (#1485743)
- Fix new lines stripped from message footer (#1485751)
- Fix IE problem with mouse click autocomplete (#1485739)
- Fix html body washing on reply/forward + fix attachments handling (#1485676)
- Fix multiple recipients input parsing (#1485733)
- Fix replying to message with html attachment (#1485676)
- Use default_charset for messages without specified charset (#1485661, #1484961)
- Support non-standard "GMT-XXXX" literal in date header (#1485729)
- Added TNEF support to decode MS Outlook attachments (winmail.dat)
- Fix "value continuation" MIME headers by adding required semicolon (#1485727)
- Fix pressing select all/unread multiple times (#1485723)
- Fix selecting all unread does not honor new messages (#1485724)
- Fix some base64 encoded attachments handling (#1485725)
- Support NGINX as IMAP backend: better BAD response handling (#1485720)
- Performance fix: don't fetch attachment parts headers twice to parse filename
- Fix checking for recent messages on various IMAP servers (#1485702)
- Performance fix: Don't fetch quota and recent messages in "message view" mode
- Fix displaying of alternative-inside-alternative messages (#1485713)
- Fix MDNSent flag checking, use arbitrary keywords (asterisk) flag (#1485706)
- Fix creation of folders with '&' sign in name
- Fix parsing of email addresses without angle brackets (#1485693)
- Save spellcheck corrections when switching from plain to html editor (and spellchecking is on)
- Fix large search results on server without SORT capability (#1485668)
- Get rid of preg_replace() with eval modifier and create_function usage (#1485686)
- Bring back <base> and <link> tags in HTML messages
- Fix XSS vulnerability through background attributes [CVE-2009-0413]
- Fix problems with backslash as IMAP hierarchy delimiter (#1484467)
- Secure vcard export by getting rid of preg's 'e' modifier use (#1485689)
- Fix authentication when submitting form with existing session (#1485679)
- Allow absolute URLs to images in HTML messages/sigs (#1485666)
- Fix message body which contains both inline attachments and emotions
- Fix SQL query execution errors handling in rcube_mdb2 class (#1485509)
- Fix address names with '@' sign handling (#1485654)
- Improve messages display performance
- Fix messages searching with 'to:' modifier
RELEASE 0.2-STABLE
------------------
- Fix mark popup in IE 7 (#1485369)
- Fix line-break issue when copy & paste in Firefox (#1485425)
- Fix autocomplete "unknown server error" (#1485637)
- Fix STARTTLS before AUTH in SMTP connection (#1484883)
- Support multiple quota values in QUOTAROOT resonse (#1485626)
- Only abbreviate file name for IE < 7 browsers (#1485063)
- Performance: allow setting imap rootdir and delimiter before connect (#1485172)
- Fix sorting of folders with more than 2 levels (#1485569)
- Fix search results page jumps in LDAP addressbook (#1485253)
- Fix empty line before the signature in IE (#1485351)
- Fix horizontal scrollbar in preview pane on IE (#1484633)
- Add Robots meta tag in login page and installer (#1484846)
- Added 'show_images' option, removed 'addrbook_show_images' (#1485597)
- Option to check for new mails in all folders (#1484374)
- Don't set client busy when checking for new messages (#1485276)
- Allow UTF-8 folder names in config (#1485579)
- Add junk_mbox option configuration in installer (#1485579)
- Do serverside addressbook queries for autocompletion (#1485531)
- Allow setting attachment col position in 'list_cols' option
- Allow override 'list_cols' via skin (#1485577)
- Fix 'cache' table cleanup on session destroy (#1485516)
- Increase speed of session destroy and garbage clean up
- Fix session timeout when DB server got clock skew (#1485490)
- Fix handling of some malformed messages (#1484438)
- Speed up raw message body handling
- Better HTML entities conversion in html2text (#1485519)
- Fix big memory consumption and speed up searching on servers without SORT capability
- Fix setting locale to tr_TR, ku and az_AZ (#1485470)
- Use SORT for searching on servers with SORT capability
- Added message status filter
- Fix empty file sending (#1485389)
- Improved searching with many criterias (calling one SEARCH command)
- Fix HTML editor initialization on IE (#1485304)
- Add warning when switching editor mode from html to plain (#1485488)
- Make identities list scrollable (#1485538)
- Fix problem with numeric folder names (#1485527)
- Added BYE response simple support to prevent from endless loops in imap.inc (#1483956)
- Fix unread message unintentionally marked as read if read_when_deleted=true (#1485409)
- Remove port number from SERVER_NAME in smtp_helo_host (#1485518)
- Don't send disposition notification receipts for messages marked as 'read' (#1485523)
- Added 'keep_alive' and 'min_keep_alive' options (#1485360)
- Added option 'identities_level', removed 'multiple_identities'
- Allow deleting identities when multiple_identities=false (#1485435)
- Added option focus_on_new_message (#1485374)
- Fix html2text class autoloading on Windows (#1485505)
- Fix html signature formatting when identity save error occurred (#1485426)
- Add feedback and set busy when moving folder (#1485497)
- Fix 'Empty' link visibility for some languages e.g. Slovak (#1485489)
- Fix messages count bar overlapping (#1485270)
- Fix adding signature in drafts compose mode (#1485484)
- Fix iil_C_Sort() to support very long and/or divided responses (#1485283)
- Fix matching case sensitivity when setting identity on reply (#1485480)
- Prefer default identity on reply
- Fix imap searching on ISMail server (#1485466)
- Add css class for flagged messages (#1485464)
- Write username instead of id in sendmail log (#1485477)
- Fix htmlspecialchars() use for PHP version < 5.2.3 (#1485475)
- Fix js keywords escaping in json_serialize() for IE/Opera (#1485472)
- Added bin/killcache.php script (#1485434)
- Add support for SJIS, GB2312, BIG5 in rc_detect_encoding()
- Fix vCard file encoding detection for non-UTF-8 strings (#1485410)
- Add 'skip_deleted' option in User Preferences (#1485445)
- Minimize "inline" javascript scripts use (#1485433)
- Fix css class setting for folders with names matching defined classes names (#1485355)
- Fix race conditions when changing mailbox
- Fix spellchecking when switching to html editor (#1485362)
- Fix compose window width/height (#1485396)
- Allow calling msgimport.sh/msgexport.sh from any directory (#1485431)
- Localized filesize units (#1485340)
- Better handling of "no identity" and "no email in identity" situations (#1485117)
- Added 'mime_param_folding' option with possibility to choose long/non-ascii attachment names encoding eg. to be readable in MS Outlook/OE (#1485320)
- Added "advanced options" feature in User Preferences
- Fix unread counter when displaying cached massage in preview panel (#1485290)
- Fix htmleditor spellchecking on MS Windows (#1485397)
- Fix problem with non-ascii attachment names in Mail_mime (#1485267, #1485096)
- Fix language autodetection (#1485401)
- Fix button label in folders management (#1485405)
- Fix collapsed folder not indicating unread msgs count of all subfolders (#1485403)
- Fix handling of apostrophes in filenames decoded according to rfc2231
RELEASE 0.2-BETA
----------------
- Made config files location configurable (#1485215)
- Reduced memory footprint when forwarding attachments (#1485345)
- Allow and use spellcheck attribute for input/textarea fields (#1485060)
- Added icons for forwarded/forwarded+replied messages (#1485257)
- Added Reply-To to forwarded emails (#1485315)
- Display progress message for folders create/delete/rename (#1485357)
- Smart Tags and NOBR tag support in html messages (#1485363, #1485327)
- Redesign of the identities settings (#1484042)
- Add config option to disable creation/deletion of identities (#1484498)
- Added 'sendmail_delay' option to restrict messages sending interval (#1484491)
- Added vertical splitter for folders list resizing
- Added possibility to view all headers in message view
- Fixed splitter drag/resize on Opera (#1485170)
- Fixed quota img height/width setting from template (#1484857)
- Refactor drag & drop functionality. Don't rely on browser events anymore (#1484453)
- Insert "virtual" folders in subscription list (#1484779)
- Added link to open message in new window
- Enable export of address book contacts as vCard
- Add feature to import contacts from vcard files (#1326103)
- Respect Content-Location headers in multipart/related messages according to RFC2110 (#1484946)
- Allowed max. attachment size now indicated in compose screen (#1485030)
- Also capture backspace key in list mode (#1484566)
- Allow application/pgp parts to be displayed (#1484753)
- Correctly handle options in mailto-links (#1485228)
- Immediately save sort_col/sort_order in user prefs (#1485265)
- Truncate very long (above 50 characters) attachment filenames when displaying
- Allow to auto-detect client language if none set (#1484434)
- Auto-detect the client timezone (user configurable)
- Add RFC2231 header value continuations support for attachment filenames + hack for servers that not support that feature
- Fix Reply-To header displaying (#1485314)
- Mark form buttons that provide the most obvious operation (mainaction)
- Added option 'quota_zero_as_unlimited' (#1484604)
- Added PRE handling in html2text class (#1484740)
- Added folder hierarchy collapsing
- Added options to use syslog instead of log file (#1484850)
- Added Logging & Debugging section in Installer
- Fix In-Reply-To and References headers when composing saved draft message (#1485288)
- Fix html message charset conversion for charsets with underline (#1485287)
- Fix buttons status after contacts deletion (#1485233)
- Fix escaping of To: and From: fields when building message body for reply or forward in the HTML editor (#1484904)
- Use current mailbox name in template (#1485256)
- Better fix for skipping untagged responses (#1485261)
- Added pspell support patch by Kris Steinhoff (#1483960)
- Enable spellchecker for HTML editor (#1485114)
- Respect spellcheck_uri in tinyMCE spellchecker (#1484196)
- Case insensitive contacts searching using PostgreSQL (#1485259)
- Make default imap folders configurable for each user (#1485075)
- Save outgoing mail to selectable folder (#1324581)
- Fix hiding of mark menu when clicking th button again (#1484944)
- Use long date format in print mode (#1485191)
- Updated TinyMCE to version 3.1.0.1
- Re-enable autocomplete attribute for login form (#1485211)
- Check PERMANENTFLAGS before saving $MDNSent flag (#1484963, #1485163)
- Added flag column on messages list (#1484623)
- Patched Mail/MimePart.php (http://pear.php.net/bugs/bug.php?id=14232)
- Allow trash/junk subfolders to be purged (#1485085)
- Store compose parameters in session and redirect to a unique URL
- Fixed CRAM-MD5 authentication (#1484819)
- Fixed forwarding messages with one HTML attachment (#1484442)
- Fixed encoding of message/rfc822 attachments and image/pjpeg handling (#1484914)
- Added option to select skin in user preferences
- Added option to configure displaying of attached images below the message body
- Added option to display images in messages from known senders (#1484601)
- User preferences grouped in more fieldsets
- Fix corrupted MIME headers of messages in Sent folder (#1485111)
- Fixed bug in MDB2 package: http://pear.php.net/bugs/bug.php?id=14124
- Use keypress instead of keydown to select list's row (#1484816)
- Don't call expunge and don't remove message row after message move if flag_for_deletion is set to true (#1485002)
RELEASE 0.2-ALPHA
-----------------
- Added option to disable autocompletion from selected LDAP address books (#1484922)
- TLS support in LDAP connections: 'use_tls' property (#1485104)
- Fixed removing messages from search set after deleting them (#1485106)
- imap.inc: Fixed iil_C_FetchStructureString() to handle many
literal strings in response (#1484969)
- Support for subfolders in default/protected folders (#1484665)
- Disallowed delimiter in folder name (#1484803)
- Support " and \ in folder names
- Escape \ in login (#1484614)
- Better HTML sanitization with the DOM-based washtml script (#1484701)
- Fixed sorting of folders with non-ascii characters
- Fixed Mysql DDL for default identities creation (#1485070)
- In Preferences added possibility to configure 'read_when_deleted',
'mdn_requests', 'flag_for_deletion' options
- Made IMAP auth type configurable (#1483825)
- Fixed empty values with FROM_UNIXTIME() in rcube_mdb2 (#1485055)
- Fixed attachment list on IE 6/7 (#1484807)
- Fixed JavaScript in compose.html that shows cc/bcc fields if populated
- Make password input fields of type password in installer (#1484886)
- Don't attempt to delete cache entries if enable_caching is FALSE (#1485051)
- Optimized messages sorting on servers without sort capability (#1485049)
- Corrected message headers decoding when charset isn't specified and improved
support for native languages (#1485050, #1485048)
- Expanded LDAP configuration options to support LDAP server writes.
- Installer: encode special characters in DB username/password (#1485042)
- Fixed management of folders with national characters in names (#1485036, #1485001)
- Fixed identities saving when using MDB2 pgsql driver (#1485032)
- Fixed BCC header reset (#1484997)
- Improved messages list performance - patch from Justin Heesemann
- Append skin_path to images location only when it starts with '/' sign (#1484859)
- Fix IMAP response in message body when message has no body (#1484964)
- Fixed non-RFC dates formatting (#1484901)
- Fixed typo in set_charset() (#1484991)
- Decode entities when inserting HTML signature to plain text message (#1484990)
- HTML editing is now working with PHP5 updates and TinyMCE v3.0.6
- Fixed signature loading on Windows (#1484545)
- Added language support to HTML editing (#1484862)
- Fixed remove signature when replying (#1333167)
- Fixed problem with line with a space at the end (#1484916)
- Fixed <!DOCTYPE> tag filtering (#1484391)
- Fixed <?xml> tag filtering (#1484403)
- Added sections (fieldset+label) in Settings interface
- Mark as read in one action with message preview (#1484972)
- Deleted redundant quota reads (#1484972)
- Added options for empty trash and expunge inbox on logout (#1483863)
- Removed lines wrapping when displaying message
- Fixed month localization
- Changed codebase to PHP5 with autoloader
RELEASE 0.1.1
-------------
- Clear selection when selecting single item (#1484942)
- Remove hard-coded image size in skin templates (#1484893)
- Database schema improvements (dropped unnecessary indexes)
- Fixed creating a new folder with a comma in its name (#1484681)
- Fixed sorting of messages when default mailbox is empty (#1484317)
- Improve message previewpane - less loading (#1484316)
- Fixed login form autoompletion (#1484839)
- Fixed virtuser_query option for mdb2 backend (#1484874)
- Fixed attachment resoting from Drafts when message body was empty (#1484506)
- Fixed usage of ob_gzhandler (#1484851)
- Fixed message part window in IE6 (#1484610)
- Fixed decoding of mime-encoded strings (#1484191)
- Fixed some iconv/mb_string problems (#1484598)
- Correctly quote mailbox name when using in URL (#1484313)
- Fixed "headers already sent" errors (#1484860)
RELEASE 0.1-STABLE
------------------
- Added interactive installer script
- Fix folder adding/renaming inspired by #1484800
- Localize folder name in page title (#1484785)
- Fix code using wrong variable name (#1484018)
- Allow to send mail with BCC recipients only
- condense TinyMCE toolbar down to one line, removing table buttons (#1484747)
- Add function to mark the selected messages as read/unread (#1457360)
- Also do charset decoding as suggested in RFC 2231 (fix #1484321)
- Show message count in folder list and hint when creating a subfolder
- Distinguish ssl and tls for imap connections (#1484667)
- Added some charset aliases to fix typical mis-labelling (#1484565)
- Remember decision to display images for a certain message during session (#1484754)
- Truncate attachment filenames to 55 characters due to an IE bug (#1484757)
- Make sending of read receipts configurable
- Respect config when localize folder names (#1484707)
- Also respect receipt and priority settings when re-opening a draft message
- Remember search results (closes #1483883), patch by the_glu
- Add Received header on outgoing mail
- Upgrade to TinyMCE 2.1.3
- Allow inserting image attachments into HTML messages while composing (#1484557)
- Implement Message-Disposition-Notification (Receipts)
- Fix overriding of session vars when register_globals is on (#1484670)
- Fix bug with case-sensitive folder names (#1484245)
- Don't create default folders by default
- Fixed some potential security risks (audited by Andris)
- Only show new messages if they match the current search (#1484176)
- Switch to/from when searcing in Sent folder (#1484555)
- Correctly read the References header (#1484646)
- Unset old cookie before sending a new value (#1484639)
- Correctly decode attachments when downloading them (#1484645 and #1484642)
- Suppress IE errors when clearing attachments form (#1484356)
- Log error when login fails due to auto_create_user turned off
- Filter linked/imported CSS files (closes #1484056)
- Improve message compose screen (closes #1484383)
- Select next row after removing one from list (#1484387)
RELEASE 0.1-RC2
---------------
- Enable drag-&-dropping of folders to a new parent and allow to create subfolders (#1457344)
- Suppress IE errors when clearing attachments form (#1484356)
- Set preferences field in user table to NULL (#1484386)
- Log error when login fails due to auto_create_user turned off
- Filter linked/imported CSS files (closes #1484056)
- Improve message compose screen (closes #1484383)
- Select next row after removing one from list (#1484387)
- Make smtp HELO/EHLO hostname configurable (#1484067)
- IPv6 Compatability (#1484322), Patch #1484373
- Unlock interface when message sending fails (#1484570)
- Eval PHP code in template includes (if configured)
- Show message when folder is empty. Mo more static text in table (#1484395)
- Only display unread count in page title when new messages arrived
- Fixed wrong delete button tooltip (#1483965)
- Fixed charset encoding bug (#1484429)
- Applied patch for LDAP version (#1484552)
- Improved XHTML validation
- Fix message list selection (#1484550)
- Better fix lowercased usernames (#1484473)
- Update pngbehavior Script as suggested in #1484490
- Fixed moving/deleting messages when more than 1 is selected
- Applied patch for LDAP contacts listing by Glen Ogilvie
- Applied patch for more address fields in LDAP contacts (#1484402)
- Add alternative for getallheaders() (fix #1484508)
- Identify mailboxes case-sensitive
- Sort mailbox list case-insensitive (closes #1484338)
- Fix display of multipart messages from Apple Mail (closes #1484027)
- Protect AJAX request from being fetched by a foreign site (XSS)
- Make autocomplete for loginform configurable by the skin template
- Fix compose function from address book (closes #1484426)
- Added //IGNORE to iconv call (patch #1484420, closes #1484023)
- Check if mbstring supports charset (#1484290 and #1484292)
- Prefer iconv over mbstring (as suggested in #1484292)
- Check filesize of template includes (#1484409)
- Fixed bug with buttons not dimming/enabling properly after switching folders
- Fixed compose window becoming unresponsive after saving a draft (#1484487)
- Re-enabled "Back" button in compose window now that bug #1484487 is fixed
- Fixed unresponsive interface issue when downloading attachments (#1484496)
- Lowered status message time from 5 to 3 seconds to improve responsiveness
- Raised .htaccess upload_max_filesize from 2M to 5M to differ from default php.ini
- Increased "mailboxcontrols" mail.css width from 160 to 170px to fix non-english languages (#1484499)
- Fix status message bug #1484464 with regard to #1484353
- Fix address adding bug reported by David Koblas
- Applied socket error patch by Thomas Mangin
- Pass-by-reference workarround for PHP5 in sendmail.inc
- Fixed buggy imap_root settings (closes #1484379)
- Prevent default events on subject links (#1484399)
- Use HTTP-POST requests for actions that change state
RELEASE 0.1-RC1
---------------
- Use global filters and bind username/ for Ldap searches (#1484159)
- Hide quota display if imap server does not support it
- Hide address groups if no LDAP servers configured
- Add link to message subjects (closes #1484257)
- Better SQL query for contact listing/search (closes #1484369)
- Fixed marking as read in preview pane (closes #1484364)
- CSS hack to display attachments correctly in IE6
- Wrap message body text (closes #1484148)
- LDAP access is back in address book (closes #1484087)
- Added search function for contacts
- New Template parsing and output encoding
- Fixed bugs #1484119 and #1483978
- Fixed message moving procedure (closes #1484308)
- Fixed display of multiple attachments (closes #1466563)
- Fixed check for new messages (closes #1484310)
- List attachments without filename
- New session authentication: Change sessid cookie when login, authentication with sessauth cookie is now configurable.
Should close bugs #1483951 and #1484299
- Correctly translate mailbox names (closes #1484276)
- Quote e-mail address links (closes #1484300)
- Updated PEAR::Mail_mime package
- Accept single quotes for HTML attributes when modifying message body (thanks Jason)
- Sanitize input for new users/identities (thanks Colin Alston)
- Don't download HTML message parts
- Convert HTML parts to plaintext if 'prefer_html' is off
- Correctly parse message/rfc822 parts (closes #1484045)
- Also use user_id for unique key in messages table (closes #1484074)
- Hide contacts drop down on blur (closes #1484203)
- Make entries in contacts drop down clickable
- Turn off browser autocompletion on login page
- Quote <? in text/html message parts
- Hide border around radio buttons
- Applied patch for attachment download by crichardson (closes #1484198)
- Fixed bug in Postgres DB handling (closes #1484068)
- Fixed bug of invalid calls to fetchRow() in rcube_db.inc (closes #1484280)
- Fixed array_merge bug (closes #1484281)
- Fixed flag for deletion in list view (closes #1484264)
- Finally support semicolons as recipient separator (closes ##1484251)
- Fixed message headers (subject) encoding
- check if safe mode is on or not (closes #1484269)
- Show "no subject" in message list if subject is missing (closes #1484243)
- Solved page caching of message preview (closes #1484153)
- Only use gzip compression if configured (closes #1484236)
- Fixed priority selector issue (#1484150)
- Fixed some CSS issues in default skin (closes #1484210 and #1484161)
- Prevent from double quoting of numeric HTML character references (closes #1484253)
- Fixed display of HTML message attachments (closes #1484178)
- Applied patch for preview caching (closes #1484186)
- Added error handling for attachment uploads
- Use multibyte safe string functions where necessary (closes #1483988)
- Applied security patch to validate the submitted host value (by Kees Cook)
- Applied security patch to validate input values when deleting contacts (by Kees Cook)
- Applied security patch that sanitizes emoticon paths when attaching them (by Kees Cook)
- Applied a patch to more aggressively sanitize a HTML message
- Visualize blocked images in HTML messages
- Fixed wrong message listing when showing search results (closes #1484131)
- Show remote images when opening HTML message part as attachment
- Improve memory usage when sending mail (closes #1484098)
- Mark messages as read once the preview is loaded (closes #1484132)
- Include smtp final response in log (closes #1484081)
- Corrected date string in sent message header (closes #1484125)
- Correclty choose "To" column in sent and draft mailboxes (closes #1483943)
- Changed srong tooltips for message browse buttons (closes #1483930)
- Fixed signature delimeter character to be standard (Bug #1484035)
- Fixed XSS vulnerability (Bug #1484109)
- Remove newlines from mail headers (Bug #1484031)
- Selection issues when moving/deleting (Bug #1484044)
- Applied patch of Clement Moulin for imap host auto-selection
- ISO-encode IMAP password for plaintext login (Bugs #1483977 & #1483886)
- Fixed folder name encoding in subscription list (Bug #1484113)
- Fixed JS errors in identity list (Bug #1484120)
- Translate foldernames in folder form (closes #1484113)
- Added first and last buttons to message list, address book
and message detail
- Pressing Shift-Del bypasses Trash folder
- Enable purge command for Junk folder
- Fetch all aliases if virtuser_query is used instead
- Re-enabled multi select of contacts (Bug #1484017)
- Enable contact editing right after creation (Bug #1459641)
- Correct UTF-7 to UTF-8 conversion if mbstring is not available
- Fixed IMAP fetch of message body (Bug #1484019)
- Fixed safe_mode problems (Bug #1418381)
- Fixed wrong header encoding (Bug #1483976)
- Made automatic draft saving configurable
- Fixed JS bug when renaming folders (Bug #1483989)
- Added quota display as image (by Brett Patterson)
- Corrected creation of a message-id
- New indentation for quoted message text
- Improved HTML validity
- Fixed URL character set (Ticket #1445501)
- Fixed saving of contact into MySQL from LDAP query results (Ticket #1483820)
- Fixed folder renaming: unsubscribe before rename (Bug #1483920)
- Finalized new message parsing (+ chaching)
- Fixed wrong usage of mbstring (Bug #1462439)
- Set default spelling language (Ticket #1483938)
- Added support for Nox Spell Server
- Re-built message parsing (Bug #1327068)
Now based on the message structure delivered by the IMAP server.
- Fixed some XSS and SQL injection issues
- Fixed charset problems with folder renaming
diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc
index 92296e525..20a27ecb0 100644
--- a/program/steps/mail/compose.inc
+++ b/program/steps/mail/compose.inc
@@ -1,1889 +1,1890 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/mail/compose.inc |
| |
| This file is part 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. |
| |
| PURPOSE: |
| Compose a new mail message with all headers and attachments |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
// define constants for message compose mode
define('RCUBE_COMPOSE_REPLY', 'reply');
define('RCUBE_COMPOSE_FORWARD', 'forward');
define('RCUBE_COMPOSE_DRAFT', 'draft');
define('RCUBE_COMPOSE_EDIT', 'edit');
$MESSAGE_FORM = null;
$COMPOSE_ID = rcube_utils::get_input_value('_id', rcube_utils::INPUT_GET);
$COMPOSE = null;
if ($COMPOSE_ID && $_SESSION['compose_data_'.$COMPOSE_ID])
$COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID];
// give replicated session storage some time to synchronize
$retries = 0;
while ($COMPOSE_ID && !is_array($COMPOSE) && $RCMAIL->db->is_replicated() && $retries++ < 5) {
usleep(500000);
$RCMAIL->session->reload();
if ($_SESSION['compose_data_'.$COMPOSE_ID]) {
$COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID];
}
}
// Nothing below is called during message composition, only at "new/forward/reply/draft" initialization or
// if a compose-ID is given (i.e. when the compose step is opened in a new window/tab).
if (!is_array($COMPOSE)) {
// Infinite redirect prevention in case of broken session (#1487028)
if ($COMPOSE_ID) {
rcube::raise_error(array('code' => 500, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Invalid compose ID"), true, true);
}
$COMPOSE_ID = uniqid(mt_rand());
$_SESSION['compose_data_'.$COMPOSE_ID] = array(
'id' => $COMPOSE_ID,
'param' => rcube_utils::request2param(rcube_utils::INPUT_GET, 'task|action', true),
'mailbox' => $RCMAIL->storage->get_folder(),
);
$COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID];
rcmail_process_compose_params($COMPOSE);
// check if folder for saving sent messages exists and is subscribed (#1486802)
if ($sent_folder = $COMPOSE['param']['sent_mbox']) {
rcmail_check_sent_folder($sent_folder, true);
}
// redirect to a unique URL with all parameters stored in session
$OUTPUT->redirect(array(
'_action' => 'compose',
'_id' => $COMPOSE['id'],
'_search' => $_REQUEST['_search'],
));
}
// add some labels to client
$OUTPUT->add_label('nosubject', 'nosenderwarning', 'norecipientwarning', 'nosubjectwarning', 'cancel',
'nobodywarning', 'notsentwarning', 'notuploadedwarning', 'savingmessage', 'sendingmessage',
'messagesaved', 'converting', 'editorwarning', 'searching', 'uploading', 'uploadingmany',
'fileuploaderror', 'sendmessage', 'newresponse', 'responsename', 'responsetext', 'save',
'savingresponse', 'restoresavedcomposedata', 'restoremessage', 'delete', 'restore', 'ignore',
'selectimportfile');
$OUTPUT->set_pagetitle($RCMAIL->gettext('compose'));
$OUTPUT->set_env('compose_id', $COMPOSE['id']);
$OUTPUT->set_env('session_id', session_id());
$OUTPUT->set_env('mailbox', $RCMAIL->storage->get_folder());
$OUTPUT->set_env('top_posting', intval($RCMAIL->config->get('reply_mode')) > 0);
$OUTPUT->set_env('recipients_separator', trim($RCMAIL->config->get('recipients_separator', ',')));
$OUTPUT->set_env('save_localstorage', (bool)$RCMAIL->config->get('compose_save_localstorage'));
$drafts_mbox = $RCMAIL->config->get('drafts_mbox');
$config_show_sig = $RCMAIL->config->get('show_sig', 1);
// add config parameters to client script
if (strlen($drafts_mbox)) {
$OUTPUT->set_env('drafts_mailbox', $drafts_mbox);
$OUTPUT->set_env('draft_autosave', $RCMAIL->config->get('draft_autosave'));
}
// default font for HTML editor
$font = rcmail::font_defs($RCMAIL->config->get('default_font'));
if ($font && !is_array($font)) {
$OUTPUT->set_env('default_font', $font);
}
// default font size for HTML editor
if ($font_size = $RCMAIL->config->get('default_font_size')) {
$OUTPUT->set_env('default_font_size', $font_size);
}
// get reference message and set compose mode
if ($msg_uid = $COMPOSE['param']['draft_uid']) {
$compose_mode = RCUBE_COMPOSE_DRAFT;
$OUTPUT->set_env('draft_id', $msg_uid);
$RCMAIL->storage->set_folder($drafts_mbox);
}
else if ($msg_uid = $COMPOSE['param']['reply_uid']) {
$compose_mode = RCUBE_COMPOSE_REPLY;
}
else if ($msg_uid = $COMPOSE['param']['forward_uid']) {
$compose_mode = RCUBE_COMPOSE_FORWARD;
$COMPOSE['forward_uid'] = $msg_uid;
$COMPOSE['as_attachment'] = !empty($COMPOSE['param']['attachment']);
}
else if ($msg_uid = $COMPOSE['param']['uid']) {
$compose_mode = RCUBE_COMPOSE_EDIT;
}
if ($compose_mode) {
$COMPOSE['mode'] = $compose_mode;
$OUTPUT->set_env('compose_mode', $compose_mode);
}
if ($compose_mode == RCUBE_COMPOSE_EDIT || $compose_mode == RCUBE_COMPOSE_DRAFT) {
// don't add signature in draft/edit mode, we'll also not remove the old-one
// but only on page display, later we should be able to change identity/sig (#1489229)
if ($config_show_sig == 1 || $config_show_sig == 2) {
$OUTPUT->set_env('show_sig_later', true);
}
}
else if ($config_show_sig == 1)
$OUTPUT->set_env('show_sig', true);
else if ($config_show_sig == 2 && empty($compose_mode))
$OUTPUT->set_env('show_sig', true);
else if ($config_show_sig == 3 && ($compose_mode == RCUBE_COMPOSE_REPLY || $compose_mode == RCUBE_COMPOSE_FORWARD))
$OUTPUT->set_env('show_sig', true);
// set line length for body wrapping
$LINE_LENGTH = $RCMAIL->config->get('line_length', 72);
if (!empty($msg_uid) && empty($COMPOSE['as_attachment'])) {
$mbox_name = $RCMAIL->storage->get_folder();
// set format before rcube_message construction
// use the same format as for the message view
if (isset($_SESSION['msg_formats'][$mbox_name.':'.$msg_uid])) {
$RCMAIL->config->set('prefer_html', $_SESSION['msg_formats'][$mbox_name.':'.$msg_uid]);
}
else {
$prefer_html = $RCMAIL->config->get('prefer_html') || $RCMAIL->config->get('htmleditor')
|| $compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT;
$RCMAIL->config->set('prefer_html', $prefer_html);
}
$MESSAGE = new rcube_message($msg_uid);
// make sure message is marked as read
if ($MESSAGE->headers && empty($MESSAGE->headers->flags['SEEN'])) {
$RCMAIL->storage->set_flag($msg_uid, 'SEEN');
}
if (!empty($MESSAGE->headers->charset)) {
$RCMAIL->storage->set_charset($MESSAGE->headers->charset);
}
if (!$MESSAGE->headers) {
// error
}
else if ($compose_mode == RCUBE_COMPOSE_FORWARD || $compose_mode == RCUBE_COMPOSE_REPLY) {
if ($compose_mode == RCUBE_COMPOSE_REPLY) {
$COMPOSE['reply_uid'] = $msg_uid;
if (!empty($COMPOSE['param']['all'])) {
$MESSAGE->reply_all = $COMPOSE['param']['all'];
}
}
else {
$COMPOSE['forward_uid'] = $msg_uid;
}
$COMPOSE['reply_msgid'] = $MESSAGE->headers->messageID;
$COMPOSE['references'] = trim($MESSAGE->headers->references . " " . $MESSAGE->headers->messageID);
// Save the sent message in the same folder of the message being replied to
if ($RCMAIL->config->get('reply_same_folder') && ($sent_folder = $COMPOSE['mailbox'])
&& rcmail_check_sent_folder($sent_folder, false)
) {
$COMPOSE['param']['sent_mbox'] = $sent_folder;
}
}
else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) {
if ($compose_mode == RCUBE_COMPOSE_DRAFT) {
if ($draft_info = $MESSAGE->headers->get('x-draft-info')) {
// get reply_uid/forward_uid to flag the original message when sending
$info = rcmail_draftinfo_decode($draft_info);
if ($info['type'] == 'reply')
$COMPOSE['reply_uid'] = $info['uid'];
else if ($info['type'] == 'forward')
$COMPOSE['forward_uid'] = $info['uid'];
$COMPOSE['mailbox'] = $info['folder'];
// Save the sent message in the same folder of the message being replied to
if ($RCMAIL->config->get('reply_same_folder') && ($sent_folder = $info['folder'])
&& rcmail_check_sent_folder($sent_folder, false)
) {
$COMPOSE['param']['sent_mbox'] = $sent_folder;
}
}
$COMPOSE['param']['message-id'] = $MESSAGE->headers->get('message-id');
// use message UID as draft_id
$OUTPUT->set_env('draft_id', $msg_uid);
}
if ($in_reply_to = $MESSAGE->headers->get('in-reply-to')) {
$COMPOSE['reply_msgid'] = '<' . $in_reply_to . '>';
}
$COMPOSE['references'] = $MESSAGE->headers->references;
}
}
else {
$MESSAGE = new stdClass();
// apply mailto: URL parameters
if (!empty($COMPOSE['param']['in-reply-to'])) {
$COMPOSE['reply_msgid'] = '<' . $COMPOSE['param']['in-reply-to'] . '>';
}
if (!empty($COMPOSE['param']['references'])) {
$COMPOSE['references'] = $COMPOSE['param']['references'];
}
}
if (!empty($COMPOSE['reply_msgid'])) {
$OUTPUT->set_env('reply_msgid', $COMPOSE['reply_msgid']);
}
$MESSAGE->compose = array();
// get user's identities
$MESSAGE->identities = $RCMAIL->user->list_identities(null, true);
// Set From field value
if (!empty($_POST['_from'])) {
$MESSAGE->compose['from'] = rcube_utils::get_input_value('_from', rcube_utils::INPUT_POST);
}
else if (!empty($COMPOSE['param']['from'])) {
$MESSAGE->compose['from'] = $COMPOSE['param']['from'];
}
else if (count($MESSAGE->identities)) {
$ident = rcmail_identity_select($MESSAGE, $MESSAGE->identities, $compose_mode);
$MESSAGE->compose['from_email'] = $ident['email'];
$MESSAGE->compose['from'] = $ident['identity_id'];
}
// Set other headers
$a_recipients = array();
$parts = array('to', 'cc', 'bcc', 'replyto', 'followupto');
$separator = trim($RCMAIL->config->get('recipients_separator', ',')) . ' ';
$from_email = @mb_strtolower($MESSAGE->compose['from_email']);
foreach ($parts as $header) {
$fvalue = '';
$decode_header = true;
$charset = $MESSAGE->headers->charset;
// we have a set of recipients stored is session
if ($header == 'to' && ($mailto_id = $COMPOSE['param']['mailto'])
&& $_SESSION['mailto'][$mailto_id]
) {
$fvalue = urldecode($_SESSION['mailto'][$mailto_id]);
$decode_header = false;
$charset = $RCMAIL->output->charset;
// make session to not grow up too much
unset($_SESSION['mailto'][$mailto_id]);
$COMPOSE['param']['to'] = $fvalue;
}
else if (!empty($_POST['_'.$header])) {
$fvalue = rcube_utils::get_input_value('_'.$header, rcube_utils::INPUT_POST, TRUE);
$charset = $RCMAIL->output->charset;
}
else if (!empty($COMPOSE['param'][$header])) {
$fvalue = $COMPOSE['param'][$header];
$charset = $RCMAIL->output->charset;
}
else if ($compose_mode == RCUBE_COMPOSE_REPLY) {
// get recipent address(es) out of the message headers
if ($header == 'to') {
$mailfollowup = $MESSAGE->headers->others['mail-followup-to'];
$mailreplyto = $MESSAGE->headers->others['mail-reply-to'];
// Reply to mailing list...
if ($MESSAGE->reply_all == 'list' && $mailfollowup)
$fvalue = $mailfollowup;
else if ($MESSAGE->reply_all == 'list'
&& preg_match('/<mailto:([^>]+)>/i', $MESSAGE->headers->others['list-post'], $m))
$fvalue = $m[1];
// Reply to...
else if ($MESSAGE->reply_all && $mailfollowup)
$fvalue = $mailfollowup;
else if ($mailreplyto)
$fvalue = $mailreplyto;
else if (!empty($MESSAGE->headers->replyto))
$fvalue = $MESSAGE->headers->replyto;
else if (!empty($MESSAGE->headers->from))
$fvalue = $MESSAGE->headers->from;
// Reply to message sent by yourself (#1487074, #1489230)
if (!empty($ident) && in_array($ident['ident'], array($fvalue, $MESSAGE->headers->from))) {
$fvalue = $MESSAGE->headers->to;
}
}
// add recipient of original message if reply to all
else if ($header == 'cc' && !empty($MESSAGE->reply_all) && $MESSAGE->reply_all != 'list') {
if ($v = $MESSAGE->headers->to)
$fvalue .= $v;
if ($v = $MESSAGE->headers->cc)
$fvalue .= (!empty($fvalue) ? $separator : '') . $v;
// Use Sender header (#1489011)
if (($v = $MESSAGE->headers->get('Sender', false)) && strpos($v, '-bounces@') === 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, $charset, true);
$to = rcube_mime::decode_address_list($MESSAGE->headers->to, null, false, $charset, true);
$replyto = rcube_mime::decode_address_list($MESSAGE->headers->replyto, null, false, $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))) {
// get drafted headers
if ($header=='to' && !empty($MESSAGE->headers->to))
$fvalue = $MESSAGE->get_header('to', true);
else if ($header=='cc' && !empty($MESSAGE->headers->cc))
$fvalue = $MESSAGE->get_header('cc', true);
else if ($header=='bcc' && !empty($MESSAGE->headers->bcc))
$fvalue = $MESSAGE->get_header('bcc', true);
else if ($header=='replyto' && !empty($MESSAGE->headers->others['mail-reply-to']))
$fvalue = $MESSAGE->get_header('mail-reply-to');
else if ($header=='replyto' && !empty($MESSAGE->headers->replyto))
$fvalue = $MESSAGE->get_header('reply-to');
else if ($header=='followupto' && !empty($MESSAGE->headers->others['mail-followup-to']))
$fvalue = $MESSAGE->get_header('mail-followup-to');
}
// split recipients and put them back together in a unique way
if (!empty($fvalue) && in_array($header, array('to', 'cc', 'bcc'))) {
$to_addresses = rcube_mime::decode_address_list($fvalue, null, $decode_header, $charset);
$fvalue = array();
foreach ($to_addresses as $addr_part) {
if (empty($addr_part['mailto'])) {
continue;
}
// According to RFC5321 local part of email address is case-sensitive
// however, here it is better to compare addresses in case-insensitive manner
$mailto = format_email(rcube_utils::idn_to_utf8($addr_part['mailto']));
$mailto_lc = mb_strtolower($addr_part['mailto']);
if (($header == 'to' || $compose_mode != RCUBE_COMPOSE_REPLY || $mailto_lc != $from_email)
&& !in_array($mailto_lc, $a_recipients)
) {
if ($addr_part['name'] && $mailto != $addr_part['name']) {
$mailto = format_email_recipient($mailto, $addr_part['name']);
}
$fvalue[] = $mailto;
$a_recipients[] = $mailto_lc;
}
}
$fvalue = implode($separator, $fvalue);
}
$MESSAGE->compose[$header] = $fvalue;
}
unset($a_recipients);
// process $MESSAGE body/attachments, set $MESSAGE_BODY/$HTML_MODE vars and some session data
$MESSAGE_BODY = rcmail_prepare_message_body();
// register UI objects
$OUTPUT->add_handlers(array(
'composeheaders' => 'rcmail_compose_headers',
'composesubject' => 'rcmail_compose_subject',
'composebody' => 'rcmail_compose_body',
'composeattachmentlist' => 'rcmail_compose_attachment_list',
'composeattachmentform' => 'rcmail_compose_attachment_form',
'composeattachment' => 'rcmail_compose_attachment_field',
'filedroparea' => 'compose_file_drop_area',
'priorityselector' => 'rcmail_priority_selector',
'editorselector' => 'rcmail_editor_selector',
- 'receiptcheckbox' => 'rcmail_receipt_checkbox',
+ 'receiptcheckbox' => 'rcmail_mdn_checkbox', // deprecated
+ 'mdncheckbox' => 'rcmail_mdn_checkbox',
'dsncheckbox' => 'rcmail_dsn_checkbox',
'storetarget' => 'rcmail_store_target_selection',
'addressbooks' => 'rcmail_addressbook_list',
'addresslist' => 'rcmail_contacts_list',
'responseslist' => 'rcmail_compose_responses_list',
));
$OUTPUT->send('compose');
/****** compose mode functions ********/
// process compose request parameters
function rcmail_process_compose_params(&$COMPOSE)
{
if ($COMPOSE['param']['to']) {
$mailto = explode('?', $COMPOSE['param']['to'], 2);
// #1486037: remove "mailto:" prefix
$COMPOSE['param']['to'] = preg_replace('/^mailto:/i', '', $mailto[0]);
// Supported case-insensitive tokens in mailto URL
$url_tokens = array('to', 'cc', 'bcc', 'reply-to', 'in-reply-to', 'references', 'subject', 'body');
if (!empty($mailto[1])) {
parse_str($mailto[1], $query);
foreach ($query as $f => $val) {
if (($key = array_search(strtolower($f), $url_tokens)) !== false) {
$f = $url_tokens[$key];
}
// merge mailto: addresses with addresses from 'to' parameter
if ($f == 'to' && !empty($COMPOSE['param']['to'])) {
$to_addresses = rcube_mime::decode_address_list($COMPOSE['param']['to'], null, true, null, true);
$add_addresses = rcube_mime::decode_address_list($val, null, true);
foreach ($add_addresses as $addr) {
if (!in_array($addr['mailto'], $to_addresses)) {
$to_addresses[] = $addr['mailto'];
$COMPOSE['param']['to'] = (!empty($to_addresses) ? ', ' : '') . $addr['string'];
}
}
}
else {
$COMPOSE['param'][$f] = $val;
}
}
}
}
// resolve _forward_uid=* to an absolute list of messages from a search result
if ($COMPOSE['param']['forward_uid'] == '*' && is_object($_SESSION['search'][1])) {
$COMPOSE['param']['forward_uid'] = $_SESSION['search'][1]->get();
}
// clean HTML message body which can be submitted by URL
if (!empty($COMPOSE['param']['body'])) {
$COMPOSE['param']['body'] = rcmail_wash_html($COMPOSE['param']['body'], array('safe' => false, 'inline_html' => true), array());
}
$RCMAIL = rcmail::get_instance();
// select folder where to save the sent message
$COMPOSE['param']['sent_mbox'] = $RCMAIL->config->get('sent_mbox');
// pipe compose parameters thru plugins
$plugin = $RCMAIL->plugins->exec_hook('message_compose', $COMPOSE);
$COMPOSE['param'] = array_merge($COMPOSE['param'], $plugin['param']);
// add attachments listed by message_compose hook
if (is_array($plugin['attachments'])) {
foreach ($plugin['attachments'] as $attach) {
// we have structured data
if (is_array($attach)) {
$attachment = $attach + array('group' => $COMPOSE_ID);
}
// only a file path is given
else {
$filename = basename($attach);
$attachment = array(
'group' => $COMPOSE_ID,
'name' => $filename,
'mimetype' => rcube_mime::file_content_type($attach, $filename),
'path' => $attach,
);
}
// save attachment if valid
if (($attachment['data'] && $attachment['name']) || ($attachment['path'] && file_exists($attachment['path']))) {
$attachment = rcmail::get_instance()->plugins->exec_hook('attachment_save', $attachment);
}
if ($attachment['status'] && !$attachment['abort']) {
unset($attachment['data'], $attachment['status'], $attachment['abort']);
$COMPOSE['attachments'][$attachment['id']] = $attachment;
}
}
}
}
function rcmail_compose_headers($attrib)
{
global $RCMAIL, $MESSAGE;
list($form_start,) = get_form_tags($attrib);
$out = '';
$part = strtolower($attrib['part']);
switch ($part) {
case 'from':
return $form_start . rcmail_compose_header_from($attrib);
case 'to':
case 'cc':
case 'bcc':
$fname = '_' . $part;
$header = $param = $part;
$allow_attrib = array('id', 'class', 'style', 'cols', 'rows', 'tabindex');
$field_type = 'html_textarea';
break;
case 'replyto':
case 'reply-to':
$fname = '_replyto';
$param = 'replyto';
$header = 'reply-to';
case 'followupto':
case 'followup-to':
if (!$fname) {
$fname = '_followupto';
$param = 'followupto';
$header = 'mail-followup-to';
}
$allow_attrib = array('id', 'class', 'style', 'size', 'tabindex');
$field_type = 'html_inputfield';
break;
}
if ($fname && $field_type) {
// pass the following attributes to the form class
$field_attrib = array('name' => $fname, 'spellcheck' => 'false');
foreach ($attrib as $attr => $value) {
if (in_array($attr, $allow_attrib)) {
$field_attrib[$attr] = $value;
}
}
// create teaxtarea object
$input = new $field_type($field_attrib);
$out = $input->show($MESSAGE->compose[$param]);
}
if ($form_start) {
$out = $form_start . $out;
}
// configure autocompletion
$RCMAIL->autocomplete_init();
return $out;
}
function rcmail_compose_header_from($attrib)
{
global $MESSAGE, $OUTPUT, $RCMAIL, $COMPOSE, $compose_mode;
// pass the following attributes to the form class
$field_attrib = array('name' => '_from');
foreach ($attrib as $attr => $value) {
if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex'))) {
$field_attrib[$attr] = $value;
}
}
if (count($MESSAGE->identities)) {
$a_signatures = array();
$identities = array();
$separator = intval($RCMAIL->config->get('reply_mode')) > 0
&& ($compose_mode == RCUBE_COMPOSE_REPLY || $compose_mode == RCUBE_COMPOSE_FORWARD) ? '---' : '-- ';
$field_attrib['onchange'] = rcmail_output::JS_OBJECT_NAME.".change_identity(this)";
$select_from = new html_select($field_attrib);
// create SELECT element
foreach ($MESSAGE->identities as $sql_arr) {
$identity_id = $sql_arr['identity_id'];
$select_from->add(format_email_recipient($sql_arr['email'], $sql_arr['name']), $identity_id);
// add signature to array
if (!empty($sql_arr['signature']) && empty($COMPOSE['param']['nosig'])) {
$text = $html = $sql_arr['signature'];
if ($sql_arr['html_signature']) {
$h2t = new rcube_html2text($sql_arr['signature'], false, true);
$text = trim($h2t->get_text());
}
else {
$html = htmlentities($html, ENT_NOQUOTES, RCUBE_CHARSET);
}
if (!preg_match('/^--[ -]\r?\n/m', $text)) {
$text = $separator . "\n" . $text;
$html = $separator . "<br>" . $html;
}
if (!$sql_arr['html_signature']) {
$t2h = new rcube_text2html($sql_arr['signature'], false);
$html = $t2h->get_html();
}
$a_signatures[$identity_id]['text'] = $text;
$a_signatures[$identity_id]['html'] = $html;
}
// add bcc and reply-to
if (!empty($sql_arr['reply-to'])) {
$identities[$identity_id]['replyto'] = $sql_arr['reply-to'];
}
if (!empty($sql_arr['bcc'])) {
$identities[$identity_id]['bcc'] = $sql_arr['bcc'];
}
}
$out = $select_from->show($MESSAGE->compose['from']);
// add signatures to client
$OUTPUT->set_env('signatures', $a_signatures);
$OUTPUT->set_env('identities', $identities);
}
// no identities, display text input field
else {
$field_attrib['class'] = 'from_address';
$input_from = new html_inputfield($field_attrib);
$out = $input_from->show($MESSAGE->compose['from']);
}
return $out;
}
function rcmail_compose_editor_mode()
{
global $RCMAIL, $compose_mode;
static $useHtml;
if ($useHtml !== null) {
return $useHtml;
}
$html_editor = intval($RCMAIL->config->get('htmleditor'));
if (isset($_POST['_is_html'])) {
$useHtml = !empty($_POST['_is_html']);
}
else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) {
$useHtml = rcmail_message_is_html();
}
else if ($compose_mode == RCUBE_COMPOSE_REPLY) {
$useHtml = ($html_editor == 1 || ($html_editor >= 2 && rcmail_message_is_html()));
}
else if ($compose_mode == RCUBE_COMPOSE_FORWARD) {
$useHtml = ($html_editor == 1 || ($html_editor == 3 && rcmail_message_is_html()));
}
else {
$useHtml = ($html_editor == 1);
}
return $useHtml;
}
function rcmail_message_is_html()
{
global $RCMAIL, $MESSAGE;
return $RCMAIL->config->get('prefer_html') && ($MESSAGE instanceof rcube_message) && $MESSAGE->has_html_part(true);
}
function rcmail_prepare_message_body()
{
global $RCMAIL, $MESSAGE, $COMPOSE, $compose_mode, $HTML_MODE;
// use posted message body
if (!empty($_POST['_message'])) {
$body = rcube_utils::get_input_value('_message', rcube_utils::INPUT_POST, true);
$isHtml = (bool) rcube_utils::get_input_value('_is_html', rcube_utils::INPUT_POST);
}
else if ($COMPOSE['param']['body']) {
$body = $COMPOSE['param']['body'];
$isHtml = (bool) $COMPOSE['param']['html'];
}
// forward as attachment
else if ($compose_mode == RCUBE_COMPOSE_FORWARD && $COMPOSE['as_attachment']) {
$isHtml = rcmail_compose_editor_mode();
$body = '';
rcmail_write_forward_attachments();
}
// reply/edit/draft/forward
else if ($compose_mode && ($compose_mode != RCUBE_COMPOSE_REPLY || intval($RCMAIL->config->get('reply_mode')) != -1)) {
$isHtml = rcmail_compose_editor_mode();
$messages = array();
if (!empty($MESSAGE->parts)) {
// collect IDs of message/rfc822 parts
if ($compose_mode == RCUBE_COMPOSE_EDIT || $compose_mode == RCUBE_COMPOSE_DRAFT) {
foreach ($MESSAGE->attachments as $part) {
if ($part->mimetype == 'message/rfc822') {
$messages[] = $part->mime_id;
}
}
}
foreach ($MESSAGE->parts as $part) {
// skip no-content and attachment parts (#1488557)
if ($part->type != 'content' || !$part->size || $MESSAGE->is_attachment($part)) {
continue;
}
// skip all content parts inside the message/rfc822 part in DRAFT/EDIT mode
foreach ($messages as $mimeid) {
if (strpos($part->mime_id, $mimeid . '.') === 0) {
continue 2;
}
}
if ($part_body = rcmail_compose_part_body($part, $isHtml)) {
$body .= ($body ? ($isHtml ? '<br/>' : "\n") : '') . $part_body;
}
}
}
else {
$body = rcmail_compose_part_body($MESSAGE, $isHtml);
}
// compose reply-body
if ($compose_mode == RCUBE_COMPOSE_REPLY)
$body = rcmail_create_reply_body($body, $isHtml);
// forward message body inline
else if ($compose_mode == RCUBE_COMPOSE_FORWARD)
$body = rcmail_create_forward_body($body, $isHtml);
// load draft message body
else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT)
$body = rcmail_create_draft_body($body, $isHtml);
}
else { // new message
$isHtml = rcmail_compose_editor_mode();
}
$plugin = $RCMAIL->plugins->exec_hook('message_compose_body',
array('body' => $body, 'html' => $isHtml, 'mode' => $compose_mode));
$body = $plugin['body'];
unset($plugin);
// add blocked.gif attachment (#1486516)
if ($isHtml && preg_match('#<img src="\./program/resources/blocked\.gif"#', $body)) {
if ($attachment = rcmail_save_image('program/resources/blocked.gif', 'image/gif')) {
$COMPOSE['attachments'][$attachment['id']] = $attachment;
$url = sprintf('%s&_id=%s&_action=display-attachment&_file=rcmfile%s',
$RCMAIL->comm_path, $COMPOSE['id'], $attachment['id']);
$body = preg_replace('#\./program/resources/blocked\.gif#', $url, $body);
}
}
$HTML_MODE = $isHtml;
return $body;
}
function rcmail_compose_part_body($part, $isHtml = false)
{
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
if (!rcube_utils::mem_check($part->size * 10)) {
return '';
}
// fetch part if not available
$body = $MESSAGE->get_part_body($part->mime_id, true);
// message is cached but not exists (#1485443), or other error
if ($body === false) {
return '';
}
if ($isHtml) {
if ($part->ctype_secondary == 'html') {
}
else if ($part->ctype_secondary == 'enriched') {
$body = rcube_enriched::to_html($body);
}
else {
// try to remove the signature
if ($compose_mode != RCUBE_COMPOSE_DRAFT && $compose_mode != RCUBE_COMPOSE_EDIT) {
if ($RCMAIL->config->get('strip_existing_sig', true)) {
$body = rcmail_remove_signature($body);
}
}
// add HTML formatting
$body = rcmail_plain_body($body, $part->ctype_parameters['format'] == 'flowed');
}
}
else {
if ($part->ctype_secondary == 'enriched') {
$body = rcube_enriched::to_html($body);
$part->ctype_secondary = 'html';
}
if ($part->ctype_secondary == 'html') {
// use html part if it has been used for message (pre)viewing
// decrease line length for quoting
$len = $compose_mode == RCUBE_COMPOSE_REPLY ? $LINE_LENGTH-2 : $LINE_LENGTH;
$txt = new rcube_html2text($body, false, true, $len);
$body = $txt->get_text();
}
else {
if ($part->ctype_secondary == 'plain' && $part->ctype_parameters['format'] == 'flowed') {
$body = rcube_mime::unfold_flowed($body);
}
// try to remove the signature
if ($compose_mode != RCUBE_COMPOSE_DRAFT && $compose_mode != RCUBE_COMPOSE_EDIT) {
if ($RCMAIL->config->get('strip_existing_sig', true)) {
$body = rcmail_remove_signature($body);
}
}
}
}
return $body;
}
function rcmail_compose_body($attrib)
{
global $RCMAIL, $OUTPUT, $HTML_MODE, $MESSAGE_BODY;
list($form_start, $form_end) = get_form_tags($attrib);
unset($attrib['form']);
if (empty($attrib['id']))
$attrib['id'] = 'rcmComposeBody';
$attrib['name'] = '_message';
$isHtml = $HTML_MODE;
$out = $form_start ? "$form_start\n" : '';
$saveid = new html_hiddenfield(array('name' => '_draft_saveid', 'value' => $RCMAIL->output->get_env('draft_id')));
$out .= $saveid->show();
$drafttoggle = new html_hiddenfield(array('name' => '_draft', 'value' => 'yes'));
$out .= $drafttoggle->show();
$msgtype = new html_hiddenfield(array('name' => '_is_html', 'value' => ($isHtml ? "1" : "0")));
$out .= $msgtype->show();
$framed = new html_hiddenfield(array('name' => '_framed', 'value' => '1'));
$out .= $framed->show();
// If desired, set this textarea to be editable by TinyMCE
if ($isHtml) {
$MESSAGE_BODY = htmlentities($MESSAGE_BODY, ENT_NOQUOTES, RCUBE_CHARSET);
$attrib['class'] = 'mce_editor';
$attrib['is_escaped'] = true;
$textarea = new html_textarea($attrib);
$out .= $textarea->show($MESSAGE_BODY);
}
else {
$textarea = new html_textarea($attrib);
$out .= $textarea->show('');
// quote plain text, inject into textarea
$table = get_html_translation_table(HTML_SPECIALCHARS);
$MESSAGE_BODY = strtr($MESSAGE_BODY, $table);
$out = substr($out, 0, -11) . $MESSAGE_BODY . '</textarea>';
}
$out .= $form_end ? "\n$form_end" : '';
$OUTPUT->set_env('composebody', $attrib['id']);
// include HTML editor
$RCMAIL->html_editor();
// Set language list
if ($RCMAIL->config->get('enable_spellcheck')) {
$engine = new rcube_spellchecker();
$dictionary = (bool) $RCMAIL->config->get('spellcheck_dictionary');
$spellcheck_langs = $engine->languages();
$lang = $_SESSION['language'];
// if not found in the list, try with two-letter code
if (!$spellcheck_langs[$lang]) {
$lang = strtolower(substr($lang, 0, 2));
}
if (!$spellcheck_langs[$lang]) {
$lang = 'en';
}
$OUTPUT->set_env('spell_langs', $spellcheck_langs);
$OUTPUT->set_env('spell_lang', $lang);
$editor_lang_set = array();
foreach ($spellcheck_langs as $key => $name) {
$editor_lang_set[] = ($key == $lang ? '+' : '') . rcube::JQ($name).'='.rcube::JQ($key);
}
// include GoogieSpell
$OUTPUT->include_script('googiespell.js');
$OUTPUT->add_script(sprintf(
"var googie = new GoogieSpell('%s/images/googiespell/','%s&lang=', %s);\n".
"googie.lang_chck_spell = \"%s\";\n".
"googie.lang_rsm_edt = \"%s\";\n".
"googie.lang_close = \"%s\";\n".
"googie.lang_revert = \"%s\";\n".
"googie.lang_no_error_found = \"%s\";\n".
"googie.lang_learn_word = \"%s\";\n".
"googie.setLanguages(%s);\n".
"googie.setCurrentLanguage('%s');\n".
"googie.setDecoration(false);\n".
"googie.decorateTextarea('%s');\n",
$RCMAIL->output->asset_url($RCMAIL->output->get_skin_path()),
$RCMAIL->url(array('_task' => 'utils', '_action' => 'spell', '_remote' => 1)),
!empty($dictionary) ? 'true' : 'false',
rcube::JQ(rcube::Q($RCMAIL->gettext('checkspelling'))),
rcube::JQ(rcube::Q($RCMAIL->gettext('resumeediting'))),
rcube::JQ(rcube::Q($RCMAIL->gettext('close'))),
rcube::JQ(rcube::Q($RCMAIL->gettext('revertto'))),
rcube::JQ(rcube::Q($RCMAIL->gettext('nospellerrors'))),
rcube::JQ(rcube::Q($RCMAIL->gettext('addtodict'))),
rcube_output::json_serialize($spellcheck_langs),
$lang,
$attrib['id']), 'foot');
$OUTPUT->add_label('checking');
$OUTPUT->set_env('spellcheck_langs', join(',', $editor_lang_set));
}
$out .= "\n".'<iframe name="savetarget" src="program/resources/blank.gif" style="width:0;height:0;border:none;visibility:hidden;" aria-hidden="true"></iframe>';
return $out;
}
function rcmail_create_reply_body($body, $bodyIsHtml)
{
global $RCMAIL, $MESSAGE, $LINE_LENGTH;
// build reply prefix
$from = array_pop(rcube_mime::decode_address_list($MESSAGE->get_header('from'), 1, false, $MESSAGE->headers->charset));
$prefix = $RCMAIL->gettext(array(
'name' => 'mailreplyintro',
'vars' => array(
'date' => $RCMAIL->format_date($MESSAGE->headers->date, $RCMAIL->config->get('date_long')),
'sender' => $from['name'] ? $from['name'] : rcube_utils::idn_to_utf8($from['mailto']),
)
));
$reply_mode = intval($RCMAIL->config->get('reply_mode'));
if (!$bodyIsHtml) {
$body = preg_replace('/\r?\n/', "\n", $body);
$body = trim($body, "\n");
// soft-wrap and quote message text
$body = rcmail_wrap_and_quote($body, $LINE_LENGTH);
$prefix .= "\n";
if ($reply_mode > 0) { // top-posting
$prefix = "\n\n\n" . $prefix;
$suffix = '';
}
else {
$suffix = "\n";
}
}
else {
// save inline images to files
$cid_map = rcmail_write_inline_attachments($MESSAGE);
// set is_safe flag (we need this for html body washing)
rcmail_check_safe($MESSAGE);
// clean up html tags
$body = rcmail_wash_html($body, array('safe' => $MESSAGE->is_safe), $cid_map);
// build reply (quote content)
$prefix = '<p>' . rcube::Q($prefix) . "</p>\n";
$prefix .= '<blockquote>';
if ($reply_mode > 0) { // top-posting
$prefix = '<br>' . $prefix;
$suffix = '</blockquote>';
}
else {
$suffix = '</blockquote><p></p>';
}
}
return $prefix . $body . $suffix;
}
function rcmail_create_forward_body($body, $bodyIsHtml)
{
global $RCMAIL, $MESSAGE, $COMPOSE;
// add attachments
if (!isset($COMPOSE['forward_attachments']) && is_array($MESSAGE->mime_parts)) {
$cid_map = rcmail_write_compose_attachments($MESSAGE, $bodyIsHtml);
}
$date = $RCMAIL->format_date($MESSAGE->headers->date, $RCMAIL->config->get('date_long'));
if (!$bodyIsHtml) {
$prefix = "\n\n\n-------- " . $RCMAIL->gettext('originalmessage') . " --------\n";
$prefix .= $RCMAIL->gettext('subject') . ': ' . $MESSAGE->subject . "\n";
$prefix .= $RCMAIL->gettext('date') . ': ' . $date . "\n";
$prefix .= $RCMAIL->gettext('from') . ': ' . $MESSAGE->get_header('from') . "\n";
$prefix .= $RCMAIL->gettext('to') . ': ' . $MESSAGE->get_header('to') . "\n";
if ($cc = $MESSAGE->headers->get('cc')) {
$prefix .= $RCMAIL->gettext('cc') . ': ' . $cc . "\n";
}
if (($replyto = $MESSAGE->headers->get('reply-to')) && $replyto != $MESSAGE->get_header('from')) {
$prefix .= $RCMAIL->gettext('replyto') . ': ' . $replyto . "\n";
}
$prefix .= "\n";
$body = trim($body, "\r\n");
}
else {
// set is_safe flag (we need this for html body washing)
rcmail_check_safe($MESSAGE);
// clean up html tags
$body = rcmail_wash_html($body, array('safe' => $MESSAGE->is_safe), $cid_map);
$prefix = sprintf(
"<br /><p>-------- " . $RCMAIL->gettext('originalmessage') . " --------</p>" .
"<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody>" .
"<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>" .
"<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>" .
"<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>" .
"<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>",
$RCMAIL->gettext('subject'), rcube::Q($MESSAGE->subject),
$RCMAIL->gettext('date'), rcube::Q($date),
$RCMAIL->gettext('from'), rcube::Q($MESSAGE->get_header('from'), 'replace'),
$RCMAIL->gettext('to'), rcube::Q($MESSAGE->get_header('to'), 'replace'));
if ($cc = $MESSAGE->headers->get('cc'))
$prefix .= sprintf("<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>",
$RCMAIL->gettext('cc'), rcube::Q($cc, 'replace'));
if (($replyto = $MESSAGE->headers->get('reply-to')) && $replyto != $MESSAGE->get_header('from'))
$prefix .= sprintf("<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>",
$RCMAIL->gettext('replyto'), rcube::Q($replyto, 'replace'));
$prefix .= "</tbody></table><br>";
}
return $prefix . $body;
}
function rcmail_create_draft_body($body, $bodyIsHtml)
{
global $MESSAGE, $COMPOSE;
// add attachments
// sizeof($MESSAGE->mime_parts can be 1 - e.g. attachment, but no text!
if (empty($COMPOSE['forward_attachments'])
&& is_array($MESSAGE->mime_parts)
&& count($MESSAGE->mime_parts) > 0
) {
$cid_map = rcmail_write_compose_attachments($MESSAGE, $bodyIsHtml);
}
// clean up HTML tags - XSS prevention (#1489251)
if ($bodyIsHtml) {
$body = rcmail_wash_html($body, array('safe' => 1), $cid_map);
// remove comments (produced by washtml)
$body = preg_replace('/<!--[^>]+-->/', '', $body);
// replace cid with href in inline images links
if (!empty($cid_map)) {
$body = str_replace(array_keys($cid_map), array_values($cid_map), $body);
}
}
return $body;
}
function rcmail_remove_signature($body)
{
global $RCMAIL;
$body = str_replace("\r\n", "\n", $body);
$len = strlen($body);
$sig_max_lines = $RCMAIL->config->get('sig_max_lines', 15);
while (($sp = strrpos($body, "-- \n", $sp ? -$len+$sp-1 : 0)) !== false) {
if ($sp == 0 || $body[$sp-1] == "\n") {
// do not touch blocks with more that X lines
if (substr_count($body, "\n", $sp) < $sig_max_lines) {
$body = substr($body, 0, max(0, $sp-1));
}
break;
}
}
return $body;
}
function rcmail_write_compose_attachments(&$message, $bodyIsHtml)
{
global $RCMAIL, $COMPOSE, $compose_mode;
$loaded_attachments = array();
foreach ((array)$COMPOSE['attachments'] as $attachment) {
$loaded_attachments[$attachment['name'] . $attachment['mimetype']] = $attachment;
}
$cid_map = array();
$messages = array();
foreach ((array)$message->mime_parts as $pid => $part) {
if ($part->disposition == 'attachment' || ($part->disposition == 'inline' && $bodyIsHtml) || $part->filename) {
// skip parts that aren't valid attachments
if ($part->ctype_primary == 'multipart' || $part->mimetype == 'application/ms-tnef') {
continue;
}
// skip message attachments in reply mode
if ($part->ctype_primary == 'message' && $compose_mode == RCUBE_COMPOSE_REPLY) {
continue;
}
// skip inline images when forwarding in text mode
if ($part->content_id && $part->disposition == 'inline' && !$bodyIsHtml && $compose_mode == RCUBE_COMPOSE_FORWARD) {
continue;
}
// skip message/rfc822 attachments on forwards (#1489214)
// Thunderbird when forwarding in inline mode displays such attachments
// and skips any attachments from inside of such part, this however
// skipped e.g. images used in HTML body or other attachments. So,
// better to skip .eml attachments but not their content (included files).
if ($part->mimetype == 'message/rfc822') {
if ($compose_mode == RCUBE_COMPOSE_FORWARD) {
continue;
}
$messages[] = $part->mime_id;
}
else if ($compose_mode != RCUBE_COMPOSE_FORWARD) {
// skip attachments included in message/rfc822 attachment (#1486487)
foreach ($messages as $mimeid) {
if (strpos($part->mime_id, $mimeid . '.') === 0) {
continue 2;
}
}
}
if (($attachment = $loaded_attachments[rcmail_attachment_name($part) . $part->mimetype])
|| ($attachment = rcmail_save_attachment($message, $pid))
) {
$COMPOSE['attachments'][$attachment['id']] = $attachment;
if ($bodyIsHtml && ($part->content_id || $part->content_location)) {
$url = sprintf('%s&_id=%s&_action=display-attachment&_file=rcmfile%s',
$RCMAIL->comm_path, $COMPOSE['id'], $attachment['id']);
if ($part->content_id)
$cid_map['cid:'.$part->content_id] = $url;
else
$cid_map[$part->content_location] = $url;
}
}
}
}
$COMPOSE['forward_attachments'] = true;
return $cid_map;
}
function rcmail_write_inline_attachments(&$message)
{
global $RCMAIL, $COMPOSE;
$cid_map = array();
foreach ((array)$message->mime_parts as $pid => $part) {
if (($part->content_id || $part->content_location) && $part->filename) {
if ($attachment = rcmail_save_attachment($message, $pid)) {
$COMPOSE['attachments'][$attachment['id']] = $attachment;
$url = sprintf('%s&_id=%s&_action=display-attachment&_file=rcmfile%s',
$RCMAIL->comm_path, $COMPOSE['id'], $attachment['id']);
if ($part->content_id)
$cid_map['cid:'.$part->content_id] = $url;
else
$cid_map[$part->content_location] = $url;
}
}
}
return $cid_map;
}
// Creates attachment(s) from the forwarded message(s)
function rcmail_write_forward_attachments()
{
global $RCMAIL, $COMPOSE, $MESSAGE;
$storage = $RCMAIL->get_storage();
$names = array();
$refs = array();
$loaded_attachments = array();
foreach ((array)$COMPOSE['attachments'] as $attachment) {
$loaded_attachments[$attachment['name'] . $attachment['mimetype']] = $attachment;
}
if ($COMPOSE['forward_uid'] == '*') {
$index = $storage->index(null, rcmail_sort_column(), rcmail_sort_order());
$COMPOSE['forward_uid'] = $index->get();
}
else if (!is_array($COMPOSE['forward_uid']) && strpos($COMPOSE['forward_uid'], ':')) {
$COMPOSE['forward_uid'] = rcube_imap_generic::uncompressMessageSet($COMPOSE['forward_uid']);
}
else if (is_string($COMPOSE['forward_uid'])) {
$COMPOSE['forward_uid'] = explode(',', $COMPOSE['forward_uid']);
}
foreach ((array)$COMPOSE['forward_uid'] as $uid) {
$message = new rcube_message($uid);
if (empty($message->headers)) {
continue;
}
if (!empty($message->headers->charset)) {
$storage->set_charset($message->headers->charset);
}
if (empty($MESSAGE->subject)) {
$MESSAGE->subject = $message->subject;
}
// generate (unique) attachment name
$name = strlen($message->subject) ? mb_substr($message->subject, 0, 64) : 'message_rfc822';
if (!empty($names[$name])) {
$names[$name]++;
$name .= '_' . $names[$name];
}
$names[$name] = 1;
$name .= '.eml';
$data = $path = null;
if (!empty($loaded_attachments[$name . 'message/rfc822'])) {
continue;
}
// don't load too big attachments into memory
if (!rcube_utils::mem_check($message->size)) {
$temp_dir = unslashify($RCMAIL->config->get('temp_dir'));
$path = tempnam($temp_dir, 'rcmAttmnt');
if ($fp = fopen($path, 'w')) {
$storage->get_raw_body($message->uid, $fp);
fclose($fp);
}
else {
return false;
}
}
else {
$data = $storage->get_raw_body($message->uid);
}
$attachment = array(
'group' => $COMPOSE['id'],
'name' => $name,
'mimetype' => 'message/rfc822',
'data' => $data,
'path' => $path,
'size' => $path ? filesize($path) : strlen($data),
);
$attachment = $RCMAIL->plugins->exec_hook('attachment_save', $attachment);
if ($attachment['status']) {
unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']);
$COMPOSE['attachments'][$attachment['id']] = $attachment;
}
else if ($path) {
@unlink($path);
}
if ($message->headers->messageID) {
$refs[] = $message->headers->messageID;
}
}
// set In-Reply-To and References headers
if (count($refs) == 1) {
$COMPOSE['reply_msgid'] = $refs[0];
}
if (!empty($refs)) {
$COMPOSE['references'] = implode(' ', $refs);
}
}
function rcmail_save_attachment(&$message, $pid)
{
global $COMPOSE;
$rcmail = rcmail::get_instance();
$part = $message->mime_parts[$pid];
$data = $path = null;
// don't load too big attachments into memory
if (!rcube_utils::mem_check($part->size)) {
$temp_dir = unslashify($rcmail->config->get('temp_dir'));
$path = tempnam($temp_dir, 'rcmAttmnt');
if ($fp = fopen($path, 'w')) {
$message->get_part_body($pid, false, 0, $fp);
fclose($fp);
}
else {
return false;
}
}
else {
$data = $message->get_part_body($pid);
}
$mimetype = $part->ctype_primary . '/' . $part->ctype_secondary;
$filename = rcmail_attachment_name($part);
$attachment = array(
'group' => $COMPOSE['id'],
'name' => $filename,
'mimetype' => $mimetype,
'content_id' => $part->content_id,
'data' => $data,
'path' => $path,
'size' => $path ? filesize($path) : strlen($data),
'charset' => $part->charset,
);
$attachment = $rcmail->plugins->exec_hook('attachment_save', $attachment);
if ($attachment['status']) {
unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']);
return $attachment;
}
else if ($path) {
@unlink($path);
}
return false;
}
function rcmail_save_image($path, $mimetype='')
{
global $COMPOSE;
// handle attachments in memory
$data = file_get_contents($path);
$name = rcmail_basename($path);
$attachment = array(
'group' => $COMPOSE['id'],
'name' => $name,
'mimetype' => $mimetype ? $mimetype : rcube_mime::file_content_type($path, $name),
'data' => $data,
'size' => strlen($data),
);
$attachment = rcmail::get_instance()->plugins->exec_hook('attachment_save', $attachment);
if ($attachment['status']) {
unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']);
return $attachment;
}
return false;
}
function rcmail_basename($filename)
{
// basename() is not unicode safe and locale dependent
if (stristr(PHP_OS, 'win') || stristr(PHP_OS, 'netware')) {
return preg_replace('/^.*[\\\\\\/]/', '', $filename);
}
else {
return preg_replace('/^.*[\/]/', '', $filename);
}
}
function rcmail_compose_subject($attrib)
{
global $MESSAGE, $COMPOSE, $compose_mode;
list($form_start, $form_end) = get_form_tags($attrib);
unset($attrib['form']);
$attrib['name'] = '_subject';
$attrib['spellcheck'] = 'true';
$textfield = new html_inputfield($attrib);
$subject = '';
// use subject from post
if (isset($_POST['_subject'])) {
$subject = rcube_utils::get_input_value('_subject', rcube_utils::INPUT_POST, TRUE);
}
else if (!empty($COMPOSE['param']['subject'])) {
$subject = $COMPOSE['param']['subject'];
}
// create a reply-subject
else if ($compose_mode == RCUBE_COMPOSE_REPLY) {
if (preg_match('/^re:/i', $MESSAGE->subject))
$subject = $MESSAGE->subject;
else
$subject = 'Re: '.$MESSAGE->subject;
// replace (was: ...) (#1489375)
$subject = preg_replace('/\s*\([wW]as:[^\)]+\)\s*$/', '', $subject);
}
// create a forward-subject
else if ($compose_mode == RCUBE_COMPOSE_FORWARD) {
if (preg_match('/^fwd:/i', $MESSAGE->subject))
$subject = $MESSAGE->subject;
else
$subject = 'Fwd: '.$MESSAGE->subject;
}
// creeate a draft-subject
else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) {
$subject = $MESSAGE->subject;
}
$out = $form_start ? "$form_start\n" : '';
$out .= $textfield->show($subject);
$out .= $form_end ? "\n$form_end" : '';
return $out;
}
function rcmail_compose_attachment_list($attrib)
{
global $RCMAIL, $OUTPUT, $COMPOSE;
// add ID if not given
if (!$attrib['id'])
$attrib['id'] = 'rcmAttachmentList';
$out = "\n";
$jslist = array();
$button = '';
if (is_array($COMPOSE['attachments'])) {
if ($attrib['deleteicon']) {
$button = html::img(array(
'src' => $RCMAIL->output->abs_url($attrib['deleteicon'], true),
'alt' => $RCMAIL->gettext('delete')
));
}
else if (rcube_utils::get_boolean($attrib['textbuttons'])) {
$button = rcube::Q($RCMAIL->gettext('delete'));
}
foreach ($COMPOSE['attachments'] as $id => $a_prop) {
if (empty($a_prop)) {
continue;
}
$out .= html::tag('li', array(
'id' => 'rcmfile'.$id,
'class' => rcube_utils::file2class($a_prop['mimetype'], $a_prop['name']),
'onmouseover' => "rcube_webmail.long_subject_title_ex(this, 0)",
),
html::a(array(
'href' => "#delete",
'title' => $RCMAIL->gettext('delete'),
'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%s', this)", rcmail_output::JS_OBJECT_NAME, $id),
'class' => 'delete',
'tabindex' => $attrib['tabindex'] ?: '0',
'aria-label' => $RCMAIL->gettext('delete') . ' ' . $a_prop['name'],
),
$button
) . rcube::Q($a_prop['name'])
);
$jslist['rcmfile'.$id] = array(
'name' => $a_prop['name'],
'complete' => true,
'mimetype' => $a_prop['mimetype']
);
}
}
if ($attrib['deleteicon'])
$COMPOSE['deleteicon'] = $RCMAIL->output->abs_url($attrib['deleteicon'], true);
else if (rcube_utils::get_boolean($attrib['textbuttons']))
$COMPOSE['textbuttons'] = true;
if ($attrib['cancelicon'])
$OUTPUT->set_env('cancelicon', $RCMAIL->output->abs_url($attrib['cancelicon'], true));
if ($attrib['loadingicon'])
$OUTPUT->set_env('loadingicon', $RCMAIL->output->abs_url($attrib['loadingicon'], true));
$OUTPUT->set_env('attachments', $jslist);
$OUTPUT->add_gui_object('attachmentlist', $attrib['id']);
// put tabindex value into data-tabindex attribute
if (isset($attrib['tabindex'])) {
$attrib['data-tabindex'] = $attrib['tabindex'];
unset($attrib['tabindex']);
}
return html::tag('ul', $attrib, $out, html::$common_attrib);
}
function rcmail_compose_attachment_form($attrib)
{
global $OUTPUT, $RCMAIL;
// set defaults
$attrib += array('id' => 'rcmUploadbox', 'buttons' => 'yes');
// Get filesize, enable upload progress bar
$max_filesize = $RCMAIL->upload_init();
$button = new html_inputfield(array('type' => 'button'));
$content = html::div(null, rcmail_compose_attachment_field())
. html::div('hint', $RCMAIL->gettext(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize))));
if (rcube_utils::get_boolean($attrib['buttons'])) {
$content .= html::div('buttons',
$button->show($RCMAIL->gettext('close'), array('class' => 'button', 'onclick' => "$('#$attrib[id]').hide()")) . ' ' .
$button->show($RCMAIL->gettext('upload'), array('class' => 'button mainaction', 'onclick' => rcmail_output::JS_OBJECT_NAME . ".command('send-attachment', this.form)"))
);
}
$out = html::div($attrib, $OUTPUT->form_tag(array(
'id' => $attrib['id'] . 'Frm',
'name' => 'uploadform',
'method' => 'post',
'enctype' => 'multipart/form-data'
), $content
));
$OUTPUT->add_gui_object('uploadform', $attrib['id'] . 'Frm');
return $out;
}
function rcmail_compose_attachment_field($attrib = array())
{
$attrib['type'] = 'file';
$attrib['name'] = '_attachments[]';
$attrib['multiple'] = 'multiple';
$field = new html_inputfield($attrib);
return $field->show();
}
function rcmail_priority_selector($attrib)
{
global $RCMAIL, $MESSAGE;
list($form_start, $form_end) = get_form_tags($attrib);
unset($attrib['form']);
$attrib['name'] = '_priority';
$prio_list = array(
$RCMAIL->gettext('lowest') => 5,
$RCMAIL->gettext('low') => 4,
$RCMAIL->gettext('normal') => 0,
$RCMAIL->gettext('high') => 2,
$RCMAIL->gettext('highest') => 1,
);
$selector = new html_select($attrib);
$selector->add(array_keys($prio_list), array_values($prio_list));
if (isset($_POST['_priority']))
$sel = $_POST['_priority'];
else if (isset($MESSAGE->headers->priority) && intval($MESSAGE->headers->priority) != 3)
$sel = $MESSAGE->headers->priority;
else
$sel = 0;
$out = $form_start ? "$form_start\n" : '';
$out .= $selector->show((int) $sel);
$out .= $form_end ? "\n$form_end" : '';
return $out;
}
-function rcmail_receipt_checkbox($attrib)
+function rcmail_mdn_checkbox($attrib)
{
global $RCMAIL, $MESSAGE, $compose_mode;
list($form_start, $form_end) = get_form_tags($attrib);
unset($attrib['form']);
if (!isset($attrib['id']))
$attrib['id'] = 'receipt';
- $attrib['name'] = '_receipt';
+ $attrib['name'] = '_mdn';
$attrib['value'] = '1';
$checkbox = new html_checkbox($attrib);
- if (isset($_POST['_receipt']))
- $mdn_default = $_POST['_receipt'];
+ if (isset($_POST['_mdn']))
+ $mdn_default = $_POST['_mdn'];
else if (in_array($compose_mode, array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT)))
$mdn_default = (bool) $MESSAGE->headers->mdn_to;
else
$mdn_default = $RCMAIL->config->get('mdn_default');
$out = $form_start ? "$form_start\n" : '';
$out .= $checkbox->show($mdn_default);
$out .= $form_end ? "\n$form_end" : '';
return $out;
}
function rcmail_dsn_checkbox($attrib)
{
global $RCMAIL;
list($form_start, $form_end) = get_form_tags($attrib);
unset($attrib['form']);
if (!isset($attrib['id']))
$attrib['id'] = 'dsn';
$attrib['name'] = '_dsn';
$attrib['value'] = '1';
$checkbox = new html_checkbox($attrib);
if (isset($_POST['_dsn']))
$dsn_value = (int) $_POST['_dsn'];
else
$dsn_value = $RCMAIL->config->get('dsn_default');
$out = $form_start ? "$form_start\n" : '';
$out .= $checkbox->show($dsn_value);
$out .= $form_end ? "\n$form_end" : '';
return $out;
}
function rcmail_editor_selector($attrib)
{
global $RCMAIL;
// determine whether HTML or plain text should be checked
$useHtml = rcmail_compose_editor_mode();
if (empty($attrib['editorid']))
$attrib['editorid'] = 'rcmComposeBody';
if (empty($attrib['name']))
$attrib['name'] = 'editorSelect';
$attrib['onchange'] = "return rcmail.command('toggle-editor', {id: '".$attrib['editorid']."', html: this.value == 'html'}, '', event)";
$select = new html_select($attrib);
$select->add(rcube::Q($RCMAIL->gettext('htmltoggle')), 'html');
$select->add(rcube::Q($RCMAIL->gettext('plaintoggle')), 'plain');
return $select->show($useHtml ? 'html' : 'plain');
}
function rcmail_store_target_selection($attrib)
{
global $COMPOSE, $RCMAIL;
$attrib['name'] = '_store_target';
$select = $RCMAIL->folder_selector(array_merge($attrib, array(
'noselection' => '- ' . $RCMAIL->gettext('dontsave') . ' -',
'folder_filter' => 'mail',
'folder_rights' => 'w',
)));
return $select->show(isset($_POST['_store_target']) ? $_POST['_store_target'] : $COMPOSE['param']['sent_mbox'], $attrib);
}
function rcmail_check_sent_folder($folder, $create=false)
{
global $RCMAIL;
// we'll not save the message, so it doesn't matter
if ($RCMAIL->config->get('no_save_sent_messages')) {
return true;
}
if ($RCMAIL->storage->folder_exists($folder, true)) {
return true;
}
// folder may exist but isn't subscribed (#1485241)
if ($create) {
if (!$RCMAIL->storage->folder_exists($folder))
return $RCMAIL->storage->create_folder($folder, true);
else
return $RCMAIL->storage->subscribe($folder);
}
return false;
}
function get_form_tags($attrib)
{
global $RCMAIL, $MESSAGE_FORM, $COMPOSE;
$form_start = '';
if (!$MESSAGE_FORM) {
$hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $RCMAIL->task));
$hiddenfields->add(array('name' => '_action', 'value' => 'send'));
$hiddenfields->add(array('name' => '_id', 'value' => $COMPOSE['id']));
$hiddenfields->add(array('name' => '_attachments'));
$form_start = empty($attrib['form']) ? $RCMAIL->output->form_tag(array('name' => "form", 'method' => "post")) : '';
$form_start .= $hiddenfields->show();
}
$form_end = ($MESSAGE_FORM && !strlen($attrib['form'])) ? '</form>' : '';
$form_name = !empty($attrib['form']) ? $attrib['form'] : 'form';
if (!$MESSAGE_FORM)
$RCMAIL->output->add_gui_object('messageform', $form_name);
$MESSAGE_FORM = $form_name;
return array($form_start, $form_end);
}
function rcmail_addressbook_list($attrib = array())
{
global $RCMAIL, $OUTPUT;
$attrib += array('id' => 'rcmdirectorylist');
$out = '';
$line_templ = html::tag('li', array(
'id' => 'rcmli%s', 'class' => '%s'),
html::a(array('href' => '#list',
'rel' => '%s',
'onclick' => "return ".rcmail_output::JS_OBJECT_NAME.".command('list-adresses','%s',this)"), '%s'));
foreach ($RCMAIL->get_address_sources(false, true) as $j => $source) {
$id = strval(strlen($source['id']) ? $source['id'] : $j);
$js_id = rcube::JQ($id);
// set class name(s)
$class_name = 'addressbook';
if ($source['class_name'])
$class_name .= ' ' . $source['class_name'];
$out .= sprintf($line_templ,
rcube_utils::html_identifier($id,true),
$class_name,
$source['id'],
$js_id, (!empty($source['name']) ? $source['name'] : $id));
}
$OUTPUT->add_gui_object('addressbookslist', $attrib['id']);
return html::tag('ul', $attrib, $out, html::$common_attrib);
}
// return the contacts list as HTML table
function rcmail_contacts_list($attrib = array())
{
global $RCMAIL, $OUTPUT;
$attrib += array('id' => 'rcmAddressList');
// set client env
$OUTPUT->add_gui_object('contactslist', $attrib['id']);
$OUTPUT->set_env('pagecount', 0);
$OUTPUT->set_env('current_page', 0);
$OUTPUT->include_script('list.js');
return $RCMAIL->table_output($attrib, array(), array('name'), 'ID');
}
/**
* Register a certain container as active area to drop files onto
*/
function compose_file_drop_area($attrib)
{
global $OUTPUT;
if ($attrib['id']) {
$OUTPUT->add_gui_object('filedrop', $attrib['id']);
$OUTPUT->set_env('filedrop', array('action' => 'upload', 'fieldname' => '_attachments'));
}
}
/**
*
*/
function rcmail_compose_responses_list($attrib)
{
global $RCMAIL, $OUTPUT;
$attrib += array('id' => 'rcmresponseslist', 'tagname' => 'ul', 'cols' => 1);
$jsenv = array();
$list = new html_table($attrib);
foreach ($RCMAIL->get_compose_responses(true) as $response) {
$key = $response['key'];
$item = html::a(array(
'href' => '#'.urlencode($response['name']),
'class' => rtrim('insertresponse ' . $attrib['itemclass']),
'unselectable' => 'on',
'tabindex' => '0',
'rel' => $key,
), rcube::Q($response['name']));
$jsenv[$key] = $response;
$list->add(array(), $item);
}
// set client env
$OUTPUT->set_env('textresponses', $jsenv);
$OUTPUT->add_gui_object('responseslist', $attrib['id']);
return $list->show();
}
diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc
index c55e40064..4ad43e433 100644
--- a/program/steps/mail/sendmail.inc
+++ b/program/steps/mail/sendmail.inc
@@ -1,938 +1,940 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/mail/sendmail.inc |
| |
| This file is part 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. |
| |
| PURPOSE: |
| Compose a new mail message with all headers and attachments |
| and send it using the PEAR::Net_SMTP class or with PHP mail() |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
// remove all scripts and act as called in frame
$OUTPUT->reset();
$OUTPUT->framed = TRUE;
$savedraft = !empty($_POST['_draft']) ? true : false;
$sendmail_delay = (int) $RCMAIL->config->get('sendmail_delay');
$drafts_mbox = $RCMAIL->config->get('drafts_mbox');
$COMPOSE_ID = rcube_utils::get_input_value('_id', rcube_utils::INPUT_GPC);
$COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID];
/****** checks ********/
if (!isset($COMPOSE['id'])) {
rcube::raise_error(array('code' => 500, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Invalid compose ID"), true, false);
$OUTPUT->show_message('internalerror', 'error');
$OUTPUT->send('iframe');
}
if (!$savedraft) {
if (empty($_POST['_to']) && empty($_POST['_cc']) && empty($_POST['_bcc'])
&& empty($_POST['_subject']) && $_POST['_message']
) {
$OUTPUT->show_message('sendingfailed', 'error');
$OUTPUT->send('iframe');
}
if ($sendmail_delay) {
$wait_sec = time() - $sendmail_delay - intval($RCMAIL->config->get('last_message_time'));
if ($wait_sec < 0) {
$OUTPUT->show_message('senttooquickly', 'error', array('sec' => $wait_sec * -1));
$OUTPUT->send('iframe');
}
}
}
/****** compose message ********/
if (empty($COMPOSE['param']['message-id'])) {
$COMPOSE['param']['message-id'] = $RCMAIL->gen_message_id();
}
$message_id = $COMPOSE['param']['message-id'];
// set default charset
$message_charset = isset($_POST['_charset']) ? $_POST['_charset'] : $OUTPUT->get_charset();
$EMAIL_FORMAT_ERROR = NULL;
$RECIPIENT_COUNT = 0;
$mailto = rcmail_email_input_format(rcube_utils::get_input_value('_to', rcube_utils::INPUT_POST, TRUE, $message_charset), true);
$mailcc = rcmail_email_input_format(rcube_utils::get_input_value('_cc', rcube_utils::INPUT_POST, TRUE, $message_charset), true);
$mailbcc = rcmail_email_input_format(rcube_utils::get_input_value('_bcc', rcube_utils::INPUT_POST, TRUE, $message_charset), true);
if ($EMAIL_FORMAT_ERROR && !$savedraft) {
$OUTPUT->show_message('emailformaterror', 'error', array('email' => $EMAIL_FORMAT_ERROR));
$OUTPUT->send('iframe');
}
if (empty($mailto) && !empty($mailcc)) {
$mailto = $mailcc;
$mailcc = null;
}
else if (empty($mailto)) {
$mailto = 'undisclosed-recipients:;';
}
// Get sender name and address...
$from = rcube_utils::get_input_value('_from', rcube_utils::INPUT_POST, true, $message_charset);
// ... from identity...
if (is_numeric($from)) {
if (is_array($identity_arr = rcmail_get_identity($from))) {
if ($identity_arr['mailto'])
$from = $identity_arr['mailto'];
if ($identity_arr['string'])
$from_string = $identity_arr['string'];
}
else {
$from = null;
}
}
// ... if there is no identity record, this might be a custom from
else if ($from_string = rcmail_email_input_format($from)) {
if (preg_match('/(\S+@\S+)/', $from_string, $m))
$from = trim($m[1], '<>');
else
$from = null;
}
if (!$from_string && $from) {
$from_string = $from;
}
// compose headers array
$headers = array();
// if configured, the Received headers goes to top, for good measure
if ($RCMAIL->config->get('http_received_header')) {
$nldlm = "\r\n\t";
$encrypt = $RCMAIL->config->get('http_received_header_encrypt');
// FROM/VIA
$http_header = 'from ';
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$hosts = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'], 2);
$hostname = gethostbyaddr($hosts[0]);
if ($encrypt) {
$http_header .= rcmail_encrypt_header($hostname);
if ($host != $hostname)
$http_header .= ' ('. rcmail_encrypt_header($host) . ')';
}
else {
$http_header .= (($host != $hostname) ? $hostname : '[' . $host . ']');
if ($host != $hostname)
$http_header .= ' (['. $host .'])';
}
$http_header .= $nldlm . ' via ';
}
- $host = $_SERVER['REMOTE_ADDR'];
+ $host = $_SERVER['REMOTE_ADDR'];
$hostname = gethostbyaddr($host);
if ($encrypt) {
$http_header .= rcmail_encrypt_header($hostname);
if ($host != $hostname)
$http_header .= ' ('. rcmail_encrypt_header($host) . ')';
}
else {
$http_header .= (($host != $hostname) ? $hostname : '[' . $host . ']');
if ($host != $hostname)
$http_header .= ' (['. $host .'])';
}
// BY
$http_header .= $nldlm . 'by ' . $_SERVER['HTTP_HOST'];
// WITH
$http_header .= $nldlm . 'with HTTP (' . $_SERVER['SERVER_PROTOCOL'] .
' '.$_SERVER['REQUEST_METHOD'] . '); ' . date('r');
$http_header = wordwrap($http_header, 69, $nldlm);
$headers['Received'] = $http_header;
}
$headers['Date'] = $RCMAIL->user_date();
$headers['From'] = rcube_charset::convert($from_string, RCUBE_CHARSET, $message_charset);
-$headers['To'] = $mailto;
+$headers['To'] = $mailto;
// additional recipients
if (!empty($mailcc)) {
$headers['Cc'] = $mailcc;
}
if (!empty($mailbcc)) {
$headers['Bcc'] = $mailbcc;
}
if (($max_recipients = (int) $RCMAIL->config->get('max_recipients')) > 0) {
if ($RECIPIENT_COUNT > $max_recipients) {
$OUTPUT->show_message('toomanyrecipients', 'error', array('max' => $max_recipients));
$OUTPUT->send('iframe');
}
}
+$dont_override = (array) $RCMAIL->config->get('dont_override');
+$mdn_enabled = in_array('mdn_default', $dont_override) ? $RCMAIL->config->get('mdn_default') : !empty($_POST['_mdn']);
+$dsn_enabled = in_array('dsn_default', $dont_override) ? $RCMAIL->config->get('dsn_default') : !empty($_POST['_dsn']);
+
// add subject
$headers['Subject'] = trim(rcube_utils::get_input_value('_subject', rcube_utils::INPUT_POST, TRUE, $message_charset));
if (!empty($identity_arr['organization'])) {
$headers['Organization'] = $identity_arr['organization'];
}
if ($hdr = rcube_utils::get_input_value('_replyto', rcube_utils::INPUT_POST, TRUE, $message_charset)) {
$headers['Reply-To'] = rcmail_email_input_format($hdr);
}
if (!empty($headers['Reply-To'])) {
$headers['Mail-Reply-To'] = $headers['Reply-To'];
}
if ($hdr = rcube_utils::get_input_value('_followupto', rcube_utils::INPUT_POST, TRUE, $message_charset)) {
$headers['Mail-Followup-To'] = rcmail_email_input_format($hdr);
}
// remember reply/forward UIDs in special headers
if (!empty($COMPOSE['reply_uid']) && $savedraft) {
$headers['X-Draft-Info'] = array('type' => 'reply', 'uid' => $COMPOSE['reply_uid']);
}
else if (!empty($COMPOSE['forward_uid']) && $savedraft) {
$headers['X-Draft-Info'] = array('type' => 'forward', 'uid' => rcube_imap_generic::compressMessageSet($COMPOSE['forward_uid']));
}
if (!empty($COMPOSE['reply_msgid'])) {
$headers['In-Reply-To'] = $COMPOSE['reply_msgid'];
}
if (!empty($COMPOSE['references'])) {
$headers['References'] = $COMPOSE['references'];
}
if (!empty($_POST['_priority'])) {
$priority = intval($_POST['_priority']);
$a_priorities = array(1 => 'highest', 2 => 'high', 4 => 'low', 5 => 'lowest');
if ($str_priority = $a_priorities[$priority]) {
$headers['X-Priority'] = sprintf("%d (%s)", $priority, ucfirst($str_priority));
}
}
-if (!empty($_POST['_receipt'])) {
+if ($mdn_enabled) {
$headers['Return-Receipt-To'] = $from_string;
$headers['Disposition-Notification-To'] = $from_string;
}
// additional headers
$headers['Message-ID'] = $message_id;
$headers['X-Sender'] = $from;
if (is_array($headers['X-Draft-Info'])) {
$headers['X-Draft-Info'] = rcmail_draftinfo_encode($headers['X-Draft-Info'] + array('folder' => $COMPOSE['mailbox']));
}
if ($hdr = $RCMAIL->config->get('useragent')) {
$headers['User-Agent'] = $hdr;
}
// exec hook for header checking and manipulation
// Depracated: use message_before_send hook instead
$data = $RCMAIL->plugins->exec_hook('message_outgoing_headers', array('headers' => $headers));
// sending aborted by plugin
if ($data['abort'] && !$savedraft) {
$OUTPUT->show_message($data['message'] ? $data['message'] : 'sendingfailed');
$OUTPUT->send('iframe');
}
else {
$headers = $data['headers'];
}
$isHtml = (bool) rcube_utils::get_input_value('_is_html', rcube_utils::INPUT_POST);
// fetch message body
$message_body = rcube_utils::get_input_value('_message', rcube_utils::INPUT_POST, TRUE, $message_charset);
if ($isHtml) {
$bstyle = array();
if ($font_size = $RCMAIL->config->get('default_font_size')) {
$bstyle[] = 'font-size: ' . $font_size;
}
if ($font_family = $RCMAIL->config->get('default_font')) {
$bstyle[] = 'font-family: ' . rcmail::font_defs($font_family);
}
// append doctype and html/body wrappers
$bstyle = !empty($bstyle) ? (" style='" . implode($bstyle, '; ') . "'") : '';
$message_body = '<html><head>'
. '<meta http-equiv="Content-Type" content="text/html; charset=' . $message_charset . '" /></head>'
. "<body" . $bstyle . ">\r\n" . $message_body;
}
if (!$savedraft) {
if ($isHtml) {
$b_style = 'padding: 0 0.4em; border-left: #1010ff 2px solid; margin: 0';
$pre_style = 'margin: 0; padding: 0; font-family: monospace';
$message_body = preg_replace(
array(
// remove signature's div ID
'/\s*id="_rc_sig"/',
// add inline css for blockquotes and container
'/<blockquote>/',
'/<div class="pre">/'
),
array(
'',
'<blockquote type="cite" style="'.$b_style.'">',
'<div class="pre" style="'.$pre_style.'">'
),
$message_body);
}
// Check spelling before send
if ($RCMAIL->config->get('spellcheck_before_send') && $RCMAIL->config->get('enable_spellcheck')
&& empty($COMPOSE['spell_checked']) && !empty($message_body)
) {
$message_body = str_replace("\r\n", "\n", $message_body);
$spellchecker = new rcube_spellchecker(rcube_utils::get_input_value('_lang', rcube_utils::INPUT_GPC));
$spell_result = $spellchecker->check($message_body, $isHtml);
$COMPOSE['spell_checked'] = true;
if (!$spell_result) {
if ($isHtml) {
$result['words'] = $spellchecker->get();
$result['dictionary'] = (bool) $RCMAIL->config->get('spellcheck_dictionary');
}
else {
$result = $spellchecker->get_xml();
}
$OUTPUT->show_message('mispellingsfound', 'error');
$OUTPUT->command('spellcheck_resume', $result);
$OUTPUT->send('iframe');
}
}
// generic footer for all messages
if ($footer = rcmail_generic_message_footer($isHtml)) {
$footer = rcube_charset::convert($footer, RCUBE_CHARSET, $message_charset);
$message_body .= "\r\n" . $footer;
}
}
if ($isHtml) {
$message_body .= "\r\n</body></html>\r\n";
}
// sort attachments to make sure the order is the same as in the UI (#1488423)
if ($files = rcube_utils::get_input_value('_attachments', rcube_utils::INPUT_POST)) {
$files = explode(',', $files);
$files = array_flip($files);
foreach ($files as $idx => $val) {
$files[$idx] = $COMPOSE['attachments'][$idx];
unset($COMPOSE['attachments'][$idx]);
}
$COMPOSE['attachments'] = array_merge(array_filter($files), $COMPOSE['attachments']);
}
// set line length for body wrapping
$LINE_LENGTH = $RCMAIL->config->get('line_length', 72);
// Since we can handle big messages with disk usage, we need more time to work
@set_time_limit(0);
// create PEAR::Mail_mime instance
$MAIL_MIME = new Mail_mime("\r\n");
// Check if we have enough memory to handle the message in it
// It's faster than using files, so we'll do this if we only can
if (is_array($COMPOSE['attachments']) && $RCMAIL->config->get('smtp_server')
&& ($mem_limit = parse_bytes(ini_get('memory_limit')))
) {
$memory = 0;
foreach ($COMPOSE['attachments'] as $id => $attachment) {
$memory += $attachment['size'];
}
// Yeah, Net_SMTP needs up to 12x more memory, 1.33 is for base64
if (!rcube_utils::mem_check($memory * 1.33 * 12)) {
$MAIL_MIME->setParam('delay_file_io', true);
}
}
// For HTML-formatted messages, construct the MIME message with both
// the HTML part and the plain-text part
if ($isHtml) {
$plugin = $RCMAIL->plugins->exec_hook('message_outgoing_body',
array('body' => $message_body, 'type' => 'html', 'message' => $MAIL_MIME));
$MAIL_MIME->setHTMLBody($plugin['body']);
// replace emoticons
$plugin['body'] = $RCMAIL->replace_emoticons($plugin['body']);
// add a plain text version of the e-mail as an alternative part.
$h2t = new rcube_html2text($plugin['body'], false, true, 0, $message_charset);
$plainTextPart = rcube_mime::wordwrap($h2t->get_text(), $LINE_LENGTH, "\r\n", false, $message_charset);
$plainTextPart = wordwrap($plainTextPart, 998, "\r\n", true);
// make sure all line endings are CRLF (#1486712)
$plainTextPart = preg_replace('/\r?\n/', "\r\n", $plainTextPart);
$plugin = $RCMAIL->plugins->exec_hook('message_outgoing_body',
array('body' => $plainTextPart, 'type' => 'alternative', 'message' => $MAIL_MIME));
$MAIL_MIME->setTXTBody($plugin['body']);
// look for "emoticon" images from TinyMCE and change their src paths to
// be file paths on the server instead of URL paths.
rcmail_fix_emoticon_paths($MAIL_MIME);
// Extract image Data URIs into message attachments (#1488502)
rcmail_extract_inline_images($MAIL_MIME, $from);
}
else {
$plugin = $RCMAIL->plugins->exec_hook('message_outgoing_body',
array('body' => $message_body, 'type' => 'plain', 'message' => $MAIL_MIME));
$message_body = $plugin['body'];
// compose format=flowed content if enabled
if ($flowed = ($savedraft || $RCMAIL->config->get('send_format_flowed', true)))
$message_body = rcube_mime::format_flowed($message_body, min($LINE_LENGTH+2, 79), $message_charset);
else
$message_body = rcube_mime::wordwrap($message_body, $LINE_LENGTH, "\r\n", false, $message_charset);
$message_body = wordwrap($message_body, 998, "\r\n", true);
$MAIL_MIME->setTXTBody($message_body, false, true);
}
// add stored attachments, if any
if (is_array($COMPOSE['attachments'])) {
foreach ($COMPOSE['attachments'] as $id => $attachment) {
// This hook retrieves the attachment contents from the file storage backend
$attachment = $RCMAIL->plugins->exec_hook('attachment_get', $attachment);
if ($isHtml) {
$dispurl = '/[\'"]\S+display-attachment\S+file=rcmfile' . preg_quote($attachment['id']) . '[\'"]/';
$message_body = $MAIL_MIME->getHTMLBody();
$is_inline = preg_match($dispurl, $message_body);
}
else {
$is_inline = false;
}
// inline image
if ($is_inline) {
// Mail_Mime does not support many inline attachments with the same name (#1489406)
// we'll generate cid: urls here to workaround this
$cid = preg_replace('/[^0-9a-zA-Z]/', '', uniqid(time(), true));
if (preg_match('#(@[0-9a-zA-Z\-\.]+)#', $from, $matches)) {
$cid .= $matches[1];
}
else {
$cid .= '@localhost';
}
$message_body = preg_replace($dispurl, '"cid:' . $cid . '"', $message_body);
$MAIL_MIME->setHTMLBody($message_body);
if ($attachment['data'])
$MAIL_MIME->addHTMLImage($attachment['data'], $attachment['mimetype'], $attachment['name'], false, $cid);
else
$MAIL_MIME->addHTMLImage($attachment['path'], $attachment['mimetype'], $attachment['name'], true, $cid);
}
else {
$ctype = str_replace('image/pjpeg', 'image/jpeg', $attachment['mimetype']); // #1484914
$file = $attachment['data'] ? $attachment['data'] : $attachment['path'];
$folding = (int) $RCMAIL->config->get('mime_param_folding');
$MAIL_MIME->addAttachment($file,
$ctype,
$attachment['name'],
$attachment['data'] ? false : true,
$ctype == 'message/rfc822' ? '8bit' : 'base64',
'attachment',
$attachment['charset'],
'', '',
$folding ? 'quoted-printable' : NULL,
$folding == 2 ? 'quoted-printable' : NULL,
'', RCUBE_CHARSET
);
}
}
}
// choose transfer encoding for plain/text body
if (preg_match('/[^\x00-\x7F]/', $MAIL_MIME->getTXTBody())) {
$text_charset = $message_charset;
$transfer_encoding = $RCMAIL->config->get('force_7bit') ? 'quoted-printable' : '8bit';
}
else {
$text_charset = 'US-ASCII';
$transfer_encoding = '7bit';
}
if ($flowed) {
$text_charset .= ";\r\n format=flowed";
}
// encoding settings for mail composing
$MAIL_MIME->setParam('text_encoding', $transfer_encoding);
$MAIL_MIME->setParam('html_encoding', 'quoted-printable');
$MAIL_MIME->setParam('head_encoding', 'quoted-printable');
$MAIL_MIME->setParam('head_charset', $message_charset);
$MAIL_MIME->setParam('html_charset', $message_charset);
$MAIL_MIME->setParam('text_charset', $text_charset);
// encoding subject header with mb_encode provides better results with asian characters
if (function_exists('mb_encode_mimeheader')) {
mb_internal_encoding($message_charset);
$headers['Subject'] = mb_encode_mimeheader($headers['Subject'],
$message_charset, 'Q', "\r\n", 8);
mb_internal_encoding(RCUBE_CHARSET);
}
// pass headers to message object
$MAIL_MIME->headers($headers);
// Begin SMTP Delivery Block
if (!$savedraft) {
// check 'From' address (identity may be incomplete)
if (empty($from)) {
$OUTPUT->show_message('nofromaddress', 'error');
$OUTPUT->send('iframe');
}
// Handle Delivery Status Notification request
- if (!empty($_POST['_dsn'])) {
- $smtp_opts['dsn'] = true;
- }
+ $smtp_opts['dsn'] = $dsn_enabled;
$sent = $RCMAIL->deliver_message($MAIL_MIME, $from, $mailto,
$smtp_error, $mailbody_file, $smtp_opts);
// return to compose page if sending failed
if (!$sent) {
// remove temp file
if ($mailbody_file) {
unlink($mailbody_file);
}
if ($smtp_error)
$OUTPUT->show_message($smtp_error['label'], 'error', $smtp_error['vars']);
else
$OUTPUT->show_message('sendingfailed', 'error');
$OUTPUT->send('iframe');
}
// save message sent time
if ($sendmail_delay) {
$RCMAIL->user->save_prefs(array('last_message_time' => time()));
}
// set replied/forwarded flag
if ($COMPOSE['reply_uid']) {
foreach (rcmail::get_uids($COMPOSE['reply_uid'], $COMPOSE['mailbox']) as $mbox => $uids) {
$RCMAIL->storage->set_flag($uids, 'ANSWERED', $mbox);
}
}
else if ($COMPOSE['forward_uid']) {
foreach (rcmail::get_uids($COMPOSE['forward_uid'], $COMPOSE['mailbox']) as $mbox => $uids) {
$RCMAIL->storage->set_flag($uids, 'FORWARDED', $mbox);
}
}
}
// Determine which folder to save message
if ($savedraft) {
$store_target = $drafts_mbox;
}
else if (!$RCMAIL->config->get('no_save_sent_messages')) {
if (isset($_POST['_store_target'])) {
$store_target = rcube_utils::get_input_value('_store_target', rcube_utils::INPUT_POST);
}
else {
$store_target = $RCMAIL->config->get('sent_mbox');
}
}
if ($store_target) {
// check if folder is subscribed
if ($RCMAIL->storage->folder_exists($store_target, true)) {
$store_folder = true;
}
// folder may be existing but not subscribed (#1485241)
else if (!$RCMAIL->storage->folder_exists($store_target)) {
$store_folder = $RCMAIL->storage->create_folder($store_target, true);
}
else if ($RCMAIL->storage->subscribe($store_target)) {
$store_folder = true;
}
// append message to sent box
if ($store_folder) {
// message body in file
if ($mailbody_file || $MAIL_MIME->getParam('delay_file_io')) {
$headers = $MAIL_MIME->txtHeaders();
// file already created
if ($mailbody_file) {
$msg = $mailbody_file;
}
else {
$temp_dir = $RCMAIL->config->get('temp_dir');
$mailbody_file = tempnam($temp_dir, 'rcmMsg');
if (!PEAR::isError($msg = $MAIL_MIME->saveMessageBody($mailbody_file))) {
$msg = $mailbody_file;
}
}
}
else {
$msg = $MAIL_MIME->getMessage();
$headers = '';
}
if (PEAR::isError($msg)) {
rcube::raise_error(array('code' => 650, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Could not create message: ".$msg->getMessage()),
true, false);
}
else {
$saved = $RCMAIL->storage->save_message($store_target, $msg, $headers,
$mailbody_file ? true : false, array('SEEN'));
}
if ($mailbody_file) {
unlink($mailbody_file);
$mailbody_file = null;
}
}
// raise error if saving failed
if (!$saved) {
rcube::raise_error(array('code' => 800, 'type' => 'imap',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Could not save message in $store_target"), true, false);
if ($savedraft) {
$OUTPUT->show_message('errorsaving', 'error');
// start the auto-save timer again
$OUTPUT->command('auto_save_start');
$OUTPUT->send('iframe');
}
}
// delete previous saved draft
if ($saved && ($old_id = rcube_utils::get_input_value('_draft_saveid', rcube_utils::INPUT_POST))) {
$deleted = $RCMAIL->storage->delete_message($old_id, $drafts_mbox);
// raise error if deletion of old draft failed
if (!$deleted) {
rcube::raise_error(array('code' => 800, 'type' => 'imap',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Could not delete message from $drafts_mbox"), true, false);
}
}
}
// remove temp file
else if ($mailbody_file) {
unlink($mailbody_file);
}
if ($savedraft) {
// remember new draft-uid ($saved could be an UID or true/false here)
if ($saved && is_bool($saved)) {
$index = $RCMAIL->storage->search_once($drafts_mbox, 'HEADER Message-ID ' . $message_id);
$saved = @max($index->get());
}
if ($saved) {
$plugin = $RCMAIL->plugins->exec_hook('message_draftsaved',
array('msgid' => $message_id, 'uid' => $saved, 'folder' => $store_target));
// display success
$OUTPUT->show_message($plugin['message'] ? $plugin['message'] : 'messagesaved', 'confirmation');
// update "_draft_saveid" and the "cmp_hash" to prevent "Unsaved changes" warning
$COMPOSE['param']['draft_uid'] = $plugin['uid'];
$OUTPUT->command('set_draft_id', $plugin['uid']);
$OUTPUT->command('compose_field_hash', true);
}
// start the auto-save timer again
$OUTPUT->command('auto_save_start');
}
else {
$folders = array();
if ($COMPOSE['mode'] == 'reply' || $COMPOSE['mode'] == 'forward') {
$folders[] = $COMPOSE['mailbox'];
}
rcmail_compose_cleanup($COMPOSE_ID);
$OUTPUT->command('remove_compose_data', $COMPOSE_ID);
if ($store_folder && !$saved) {
$OUTPUT->command('sent_successfully', 'error', $RCMAIL->gettext('errorsavingsent'), $folders);
}
else if ($store_folder) {
$folders[] = $store_target;
}
$OUTPUT->command('sent_successfully', 'confirmation', $RCMAIL->gettext('messagesent'), $folders);
}
$OUTPUT->send('iframe');
/****** message sending functions ********/
// encrypt parts of the header
function rcmail_encrypt_header($what)
{
global $RCMAIL;
if (!$RCMAIL->config->get('http_received_header_encrypt')) {
return $what;
}
return $RCMAIL->encrypt($what);
}
// get identity record
function rcmail_get_identity($id)
{
global $RCMAIL, $message_charset;
if ($sql_arr = $RCMAIL->user->get_identity($id)) {
$out = $sql_arr;
if ($message_charset != RCUBE_CHARSET) {
foreach ($out as $k => $v) {
$out[$k] = rcube_charset::convert($v, RCUBE_CHARSET, $message_charset);
}
}
$out['mailto'] = $sql_arr['email'];
$out['string'] = format_email_recipient($sql_arr['email'], $sql_arr['name']);
return $out;
}
return false;
}
/**
* go from this:
* <img src="http[s]://.../tinymce/plugins/emoticons/img/smiley-cool.gif" border="0" alt="Cool" title="Cool" />
*
* to this:
*
* <img src="/path/on/server/.../tinymce/plugins/emoticons/img/smiley-cool.gif" border="0" alt="Cool" title="Cool" />
*/
function rcmail_fix_emoticon_paths($mime_message)
{
global $RCMAIL;
$body = $mime_message->getHTMLBody();
// remove any null-byte characters before parsing
$body = preg_replace('/\x00/', '', $body);
$searchstr = 'program/js/tinymce/plugins/emoticons/img/';
$offset = 0;
// keep track of added images, so they're only added once
$included_images = array();
if (preg_match_all('# src=[\'"]([^\'"]+)#', $body, $matches, PREG_OFFSET_CAPTURE)) {
foreach ($matches[1] as $m) {
// find emoticon image tags
if (preg_match('#'.$searchstr.'(.*)$#', $m[0], $imatches)) {
$image_name = $imatches[1];
// sanitize image name so resulting attachment doesn't leave images dir
$image_name = preg_replace('/[^a-zA-Z0-9_\.\-]/i', '', $image_name);
$img_file = INSTALL_PATH . '/' . $searchstr . $image_name;
if (! in_array($image_name, $included_images)) {
// add the image to the MIME message
if (!$mime_message->addHTMLImage($img_file, 'image/gif', '', true, $image_name)) {
$RCMAIL->output->show_message("emoticonerror", 'error');
}
array_push($included_images, $image_name);
}
$body = substr_replace($body, $img_file, $m[1] + $offset, strlen($m[0]));
$offset += strlen($img_file) - strlen($m[0]);
}
}
}
$mime_message->setHTMLBody($body);
}
/**
* Extract image attachments from HTML content (data URIs)
*/
function rcmail_extract_inline_images($mime_message, $from)
{
$body = $mime_message->getHTMLBody();
$offset = 0;
$list = array();
$domain = 'localhost';
$regexp = '#img[^>]+src=[\'"](data:([^;]*);base64,([a-z0-9+/=\r\n]+))([\'"])#i';
if (preg_match_all($regexp, $body, $matches, PREG_OFFSET_CAPTURE)) {
// get domain for the Content-ID, must be the same as in Mail_Mime::get()
if (preg_match('#@([0-9a-zA-Z\-\.]+)#', $from, $m)) {
$domain = $m[1];
}
foreach ($matches[1] as $idx => $m) {
$data = preg_replace('/\r\n/', '', $matches[3][$idx][0]);
$data = base64_decode($data);
if (empty($data)) {
continue;
}
$hash = md5($data) . '@' . $domain;
$mime_type = $matches[2][$idx][0];
$name = $list[$hash];
if (empty($mime_type)) {
$mime_type = rcube_mime::image_content_type($data);
}
// add the image to the MIME message
if (!$name) {
$ext = preg_replace('#^[^/]+/#', '', $mime_type);
$name = substr($hash, 0, 8) . '.' . $ext;
$list[$hash] = $name;
$mime_message->addHTMLImage($data, $mime_type, $name, false, $hash);
}
$body = substr_replace($body, $name, $m[1] + $offset, strlen($m[0]));
$offset += strlen($name) - strlen($m[0]);
}
}
$mime_message->setHTMLBody($body);
}
/**
* Parse and cleanup email address input (and count addresses)
*
* @param string Address input
* @param boolean Do count recipients (saved in global $RECIPIENT_COUNT)
* @param boolean Validate addresses (errors saved in global $EMAIL_FORMAT_ERROR)
* @return string Canonical recipients string separated by comma
*/
function rcmail_email_input_format($mailto, $count=false, $check=true)
{
global $RCMAIL, $EMAIL_FORMAT_ERROR, $RECIPIENT_COUNT;
// simplified email regexp, supporting quoted local part
$email_regexp = '(\S+|("[^"]+"))@\S+';
$delim = trim($RCMAIL->config->get('recipients_separator', ','));
$regexp = array("/[,;$delim]\s*[\r\n]+/", '/[\r\n]+/', "/[,;$delim]\s*\$/m", '/;/', '/(\S{1})(<'.$email_regexp.'>)/U');
$replace = array($delim.' ', ', ', '', $delim, '\\1 \\2');
// replace new lines and strip ending ', ', make address input more valid
$mailto = trim(preg_replace($regexp, $replace, $mailto));
$items = rcube_utils::explode_quoted_string($delim, $mailto);
$result = array();
foreach ($items as $item) {
$item = trim($item);
// address in brackets without name (do nothing)
if (preg_match('/^<'.$email_regexp.'>$/', $item)) {
$item = rcube_utils::idn_to_ascii(trim($item, '<>'));
$result[] = $item;
}
// address without brackets and without name (add brackets)
else if (preg_match('/^'.$email_regexp.'$/', $item)) {
$item = rcube_utils::idn_to_ascii($item);
$result[] = $item;
}
// address with name (handle name)
else if (preg_match('/<*'.$email_regexp.'>*$/', $item, $matches)) {
$address = $matches[0];
$name = trim(str_replace($address, '', $item));
if ($name[0] == '"' && $name[count($name)-1] == '"') {
$name = substr($name, 1, -1);
}
$name = stripcslashes($name);
$address = rcube_utils::idn_to_ascii(trim($address, '<>'));
$result[] = format_email_recipient($address, $name);
$item = $address;
}
else if (trim($item)) {
continue;
}
// check address format
$item = trim($item, '<>');
if ($item && $check && !rcube_utils::check_email($item)) {
$EMAIL_FORMAT_ERROR = $item;
return;
}
}
if ($count) {
$RECIPIENT_COUNT += count($result);
}
return implode(', ', $result);
}
function rcmail_generic_message_footer($isHtml)
{
global $RCMAIL;
if ($isHtml && ($file = $RCMAIL->config->get('generic_message_footer_html'))) {
$html_footer = true;
}
else {
$file = $RCMAIL->config->get('generic_message_footer');
$html_footer = false;
}
if ($file && realpath($file)) {
// sanity check
if (!preg_match('/\.(php|ini|conf)$/', $file) && strpos($file, '/etc/') === false) {
$footer = file_get_contents($file);
if ($isHtml && !$html_footer) {
$t2h = new rcube_text2html($footer, false);
$footer = $t2h->get_html();
}
return $footer;
}
}
return false;
}
diff --git a/skins/classic/templates/compose.html b/skins/classic/templates/compose.html
index 1515eeb06..805032504 100644
--- a/skins/classic/templates/compose.html
+++ b/skins/classic/templates/compose.html
@@ -1,221 +1,223 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title><roundcube:object name="productname" /> :: <roundcube:label name="compose" /></title>
<roundcube:include file="/includes/links.html" />
<roundcube:if condition="config:enable_spellcheck" />
<link rel="stylesheet" type="text/css" href="/googiespell.css" />
<roundcube:endif />
<script type="text/javascript" src="/functions.js"></script>
<script type="text/javascript" src="/splitter.js"></script>
<style type="text/css">
#compose-contacts { width: <roundcube:exp expression="!empty(cookie:composesplitterv1) ? cookie:composesplitterv1-5 : 195" />px; }
#compose-container { left: <roundcube:exp expression="!empty(cookie:composesplitterv1) ? cookie:composesplitterv1+5 : 205" />px; }
</style>
</head>
<roundcube:if condition="env:extwin" />
<body class="extwin">
<roundcube:object name="message" id="message" />
<roundcube:else />
<body>
<roundcube:include file="/includes/taskbar.html" />
<roundcube:include file="/includes/header.html" />
<roundcube:endif />
<div id="messagetoolbar">
<roundcube:if condition="env:extwin" />
<roundcube:button command="close" type="link" class="button back" classAct="button back" classSel="button backSel" title="close" content=" " />
<roundcube:else />
<roundcube:button command="list" type="link" class="button back" classAct="button back" classSel="button backSel" title="backtolist" content=" " />
<roundcube:endif />
<roundcube:button command="send" type="link" class="buttonPas send" classAct="button send" classSel="button sendSel" title="sendmessage" content=" " />
<roundcube:button name="addattachment" type="link" class="button attach" classAct="button attach" classSel="button attachSel" title="addattachment" onclick="rcmail_ui.show_popup('uploadmenu', true);return false" content=" " />
<roundcube:button command="insert-sig" type="link" class="buttonPas insertsig" classAct="button insertsig" classSel="button insertsigSel" title="insertsignature" content=" " />
<roundcube:button command="savedraft" type="link" class="buttonPas savedraft" classAct="button savedraft" classSel="button savedraftSel" title="savemessage" content=" " />
<roundcube:if condition="config:enable_spellcheck" />
<span class="dropbutton">
<roundcube:button command="spellcheck" type="link" class="buttonPas spellcheck" classAct="button spellcheck" classSel="button spellcheckSel" title="checkspelling" content=" " />
<span id="spellmenulink" onclick="rcmail_ui.show_popup('spellmenu');return false"></span>
</span>
<roundcube:endif />
<a href="#responses" class="button responses" label="responses" title="<roundcube:label name='insertresponse' />" id="responsesmenulink" unselectable="on" onmousedown="return false" onclick="rcmail_ui.show_popup('responsesmenu');return false">&nbsp;</a>
<roundcube:container name="toolbar" id="compose-toolbar" />
<roundcube:button name="messageoptions" id="composemenulink" type="link" class="button messagemenu" title="messageoptions" onclick="rcmail_ui.show_popup('composemenu', true);return false" content=" " />
</div>
<roundcube:form name="form" method="post">
<div id="mainscreen">
<div id="compose-contacts">
<div class="boxtitle"><roundcube:label name="contacts" /></div>
<div class="boxlistcontent">
<div class="searchbox">
<img id="searchmenulink" src="/images/icons/glass.png" width="16" height="16" />
<roundcube:object name="searchform" id="quicksearchbox" form="true" tabindex="13" />
<roundcube:button command="reset-search" id="searchreset" image="/images/icons/reset.gif" title="resetsearch" width="13" height="13" />
</div>
<roundcube:object name="addressbooks" id="directorylist" />
<roundcube:object name="addresslist" id="contacts-table" class="records-table" cellspacing="0" noheader="true" />
</div>
<div class="boxfooter">
<div id="abookactions" class="pagenav">
<roundcube:button command="add-recipient" prop="to" type="link" title="to" class="button disabled" classAct="button" content="To &amp;raquo;" />
<roundcube:button command="add-recipient" prop="cc" type="link" title="cc" class="button disabled" classAct="button" content="Cc &amp;raquo;" />
<roundcube:button command="add-recipient" prop="bcc" type="link" title="bcc" class="button disabled" classAct="button" content="Bcc &amp;raquo;" />
</div>
<div id="abookcountbar" class="pagenav">
<roundcube:button command="firstpage" type="link" class="buttonPas firstpage" classAct="button firstpage" classSel="button firstpageSel" title="firstpage" content=" " />
<roundcube:button command="previouspage" type="link" class="buttonPas prevpage" classAct="button prevpage" classSel="button prevpageSel" title="previouspage" content=" " />
<span style="float:left">&nbsp;</span>
<roundcube:button command="nextpage" type="link" class="buttonPas nextpage" classAct="button nextpage" classSel="button nextpageSel" title="nextpage" content=" " />
<roundcube:button command="lastpage" type="link" class="buttonPas lastpage" classAct="button lastpage" classSel="button lastpageSel" title="lastpage" content=" " />
</div>
</div>
</div>
<script type="text/javascript">
var composesplitv1 = new rcube_splitter({id:'composesplitterv1', p1: 'compose-contacts', p2: 'compose-container', orientation: 'v', relative: true, start: 200});
rcmail.add_onload('composesplitv1.init()');
</script>
<div id="compose-container">
<div id="compose-headers-div" style="width: 100%;">
<table border="0" cellspacing="0" cellpadding="1" id="compose-headers">
<tr>
<td class="title"><label for="_from"><roundcube:label name="from" /></label></td>
<td class="editfield formlinks">
<roundcube:object name="composeHeaders" part="from" form="form" id="_from" tabindex="1" />
<a href="#identities" onclick="return rcmail.command('identities')"><roundcube:label name="editidents" /></a>
<roundcube:button command="extwin" image="/images/icons/extwin.png" width="15" height="15" title="openinextwin" id="openextwinlink" condition="!env:extwin" />
</td>
</tr><tr>
<td class="title top"><label for="_to"><roundcube:label name="to" /></label></td>
<td class="editfield"><roundcube:object name="composeHeaders" part="to" form="form" id="_to" cols="70" rows="2" tabindex="2" /></td>
</tr><tr id="compose-cc">
<td class="title top">
<a href="#cc" onclick="return rcmail_ui.hide_header_form('cc');"><img src="/images/icons/minus.gif" alt="" width="13" height="11" title="<roundcube:label name='delete' />" /></a>
<label for="_cc"><roundcube:label name="cc" /></label>
</td>
<td class="editfield"><roundcube:object name="composeHeaders" part="cc" form="form" id="_cc" cols="70" rows="2" tabindex="3" /></td>
</tr><tr id="compose-bcc">
<td class="title top">
<a href="#bcc" onclick="return rcmail_ui.hide_header_form('bcc');"><img src="/images/icons/minus.gif" alt="" width="13" height="11" title="<roundcube:label name='delete' />" /></a>
<label for="_bcc"><roundcube:label name="bcc" /></label>
</td>
<td class="editfield"><roundcube:object name="composeHeaders" part="bcc" form="form" id="_bcc" cols="70" rows="2" tabindex="4" /></td>
</tr><tr id="compose-replyto">
<td class="title top">
<a href="#replyto" onclick="return rcmail_ui.hide_header_form('replyto');"><img src="/images/icons/minus.gif" alt="" width="13" height="11" title="<roundcube:label name='delete' />" /></a>
<label for="_replyto"><roundcube:label name="replyto" /></label>
</td>
<td class="editfield"><roundcube:object name="composeHeaders" part="replyto" form="form" id="_replyto" size="70" tabindex="5" /></td>
</tr><tr id="compose-followupto">
<td class="title top">
<a href="#followupto" onclick="return rcmail_ui.hide_header_form('followupto');"><img src="/images/icons/minus.gif" alt="" width="13" height="11" title="<roundcube:label name='delete' />" /></a>
<label for="_followupto"><roundcube:label name="followupto" /></label>
</td>
<td class="editfield"><roundcube:object name="composeHeaders" part="followupto" form="form" id="_followupto" size="70" tabindex="7" /></td>
</tr><tr>
<td></td>
<td class="formlinks">
<a href="#cc" onclick="return rcmail_ui.show_header_form('cc')" id="cc-link"><roundcube:label name="addcc" /></a>
<span class="separator">|</span>
<a href="#bcc" onclick="return rcmail_ui.show_header_form('bcc')" id="bcc-link"><roundcube:label name="addbcc" /></a>
<span class="separator">|</span>
<a href="#reply-to" onclick="return rcmail_ui.show_header_form('replyto')" id="replyto-link"><roundcube:label name="addreplyto" /></a>
<span class="separator">|</span>
<a href="#followup-to" onclick="return rcmail_ui.show_header_form('followupto')" id="followupto-link"><roundcube:label name="addfollowupto" /></a>
</td>
</tr><tr>
<td class="title"><label for="compose-subject"><roundcube:label name="subject" /></label></td>
<td class="editfield"><roundcube:object name="composeSubject" id="compose-subject" form="form" tabindex="8" /></td>
</tr>
</table>
</div>
<div id="compose-div">
<div id="compose-body-div">
<div class="boxlistcontent" style="overflow: hidden; top: 0">
<roundcube:object name="composeBody" id="compose-body" form="form" cols="70" rows="20" tabindex="9" />
</div>
<div class="boxfooter">
<div id="compose-buttons">
<roundcube:button type="input" command="send" class="button mainaction" label="sendmessage" tabindex="10" />
<roundcube:button type="input" command="list" class="button" label="cancel" tabindex="11" />
</div>
<div id="compose-editorfooter" class="pagenav">
<roundcube:if condition="!in_array('htmleditor', (array)config:dont_override)" />
<span>
<label><roundcube:label name="editortype" /></label>
<roundcube:object name="editorSelector" editorid="compose-body" tabindex="12" />
</span>
<roundcube:endif />
</div>
</div>
</div>
<script type="text/javascript">
var composesplitv2 = new rcube_splitter({id:'composesplitterv2', p1: 'compose-body-div', p2: 'compose-attachments', orientation: 'v', relative: true, start: $('#compose-headers-div').width() - 175});
rcmail.add_onload('composesplitv2.init()');
</script>
<div id="compose-attachments">
<div class="boxtitle"><roundcube:label name="attachments" /></div>
<div class="boxlistcontent">
<roundcube:object name="composeAttachmentList" id="attachmentslist" loadingIcon="/images/display/loading_blue.gif" />
</div>
<div class="boxfooter">
<roundcube:button name="uploadmenulink" id="uploadmenulink" type="link" title="addattachment" class="button addgroup" onclick="rcmail_ui.show_popup('uploadmenu', true);return false" content=" " />
</div>
</div>
<roundcube:object name="fileDropArea" id="compose-attachments" />
</div>
</div>
</div>
<div id="composeoptionsmenu" class="popupmenu">
<table>
+ <roundcube:if condition="!in_array('mdn_default', (array)config:dont_override)" />
<tr>
<td><label for="rcmcomposereceipt"><roundcube:label name="returnreceipt" />:</label></td>
- <td><roundcube:object name="receiptCheckBox" form="form" id="rcmcomposereceipt" /></td>
+ <td><roundcube:object name="mdnCheckBox" form="form" id="rcmcomposereceipt" /></td>
</tr>
- <roundcube:if condition="config:smtp_server != ''" />
+ <roundcube:endif />
+ <roundcube:if condition="config:smtp_server != '' and !in_array('dsn_default', (array)config:dont_override)" />
<tr>
<td><label for="rcmcomposedsn"><roundcube:label name="dsn" />:</label></td>
<td><roundcube:object name="dsnCheckBox" form="form" id="rcmcomposedsn" /></td>
</tr>
<roundcube:endif />
<tr>
<td><label for="rcmcomposepriority"><roundcube:label name="priority" />:</label></td>
<td><roundcube:object name="prioritySelector" form="form" id="rcmcomposepriority" /></td>
</tr>
<roundcube:if condition="!config:no_save_sent_messages" />
<tr>
<td><label><roundcube:label name="savesentmessagein" />:</label></td>
<td><roundcube:object name="storetarget" maxlength="30" /></td>
</tr>
<roundcube:endif />
</table>
</div>
<div id="responsesmenu" class="popupmenu">
<ul id="textresponsesmenu">
<li><label class="comment"><roundcube:label name="insertresponse" /></label></li>
<roundcube:object name="responseslist" id="responseslist" tagname="ul" itemclass="active" />
<li><label class="comment"><roundcube:label name="manageresponses" /></label></li>
<roundcube:button command="save-response" type="link-menuitem" label="newresponse" classAct="active" unselectable="on" />
<roundcube:button command="responses" type="link-menuitem" label="editresponses" classAct="active" />
</ul>
</div>
<div id="spellmenu" class="popupmenu selectable"></div>
</form>
<roundcube:object name="composeAttachmentForm" id="attachment-form" attachmentFieldSize="40" class="popupmenu" />
<script type="text/javascript">
rcube_init_mail_ui();
</script>
</body>
</html>
diff --git a/skins/larry/templates/compose.html b/skins/larry/templates/compose.html
index 04a987f89..3e2eaac6a 100644
--- a/skins/larry/templates/compose.html
+++ b/skins/larry/templates/compose.html
@@ -1,223 +1,225 @@
<roundcube:object name="doctype" value="html5" />
<html>
<head>
<title><roundcube:object name="pagetitle" /></title>
<roundcube:include file="/includes/links.html" />
<roundcube:if condition="config:enable_spellcheck" />
<link rel="stylesheet" type="text/css" href="/googiespell.css" />
<roundcube:endif />
</head>
<roundcube:if condition="env:extwin" /><body class="extwin"><roundcube:else /><body><roundcube:endif />
<roundcube:include file="/includes/header.html" />
<div id="mainscreen">
<h1 class="voice"><roundcube:object name="pagetitle" /></h1>
<!-- toolbar -->
<h2 id="aria-label-toolbar" class="voice"><roundcube:label name="arialabeltoolbar" /></h2>
<div id="messagetoolbar" class="toolbar fullwidth" role="toolbar" aria-labelledby="aria-label-toolbar">
<roundcube:button command="list" type="link" class="button back disabled" classAct="button back" label="cancel" condition="!env:extwin" tabindex="2" />
<roundcube:button command="close" type="link" class="button close disabled" classAct="button close" label="cancel" condition="env:extwin" tabindex="2" />
<span class="spacer"></span>
<roundcube:button command="send" type="link" class="button send disabled" classAct="button send" label="send" title="sendmessage" tabindex="2" />
<roundcube:button command="savedraft" type="link" class="button savedraft disabled" classAct="button savedraft" label="save" title="savemessage" tabindex="2" />
<span class="spacer"></span>
<roundcube:if condition="config:enable_spellcheck" />
<span class="dropbutton">
<roundcube:button command="spellcheck" type="link" class="button spellcheck disabled" classAct="button spellcheck" classSel="button spellcheck pressed" label="spellcheck" title="checkspelling" tabindex="2" />
<a href="#languages" class="dropbuttontip" id="spellmenulink" onclick="UI.toggle_popup('spellmenu',event);return false" aria-haspopup="true" aria-expanded="false" tabindex="2">Select Spell Language</a>
</span>
<roundcube:endif />
<roundcube:button name="addattachment" type="link" class="button attach" label="attach" title="addattachment" onclick="UI.show_uploadform(event);return false" aria-haspopup="true" aria-expanded="false"tabindex="2" />
<roundcube:button command="insert-sig" type="link" class="button insertsig disabled" classAct="button insertsig" label="signature" title="insertsignature" tabindex="2" />
<a href="#responses" class="button responses" label="responses" title="<roundcube:label name='insertresponse' />" id="responsesmenulink" unselectable="on" onmousedown="return false" onclick="UI.toggle_popup('responsesmenu',event);return false" tabindex="2" aria-haspopup="true" aria-expanded="false" aria-owns="textresponsesmenu"><roundcube:label name="responses" /></a>
<roundcube:container name="toolbar" id="compose-toolbar" />
</div>
<div id="mainscreencontent">
<div id="composeview-left">
<!-- inline address book -->
<div id="compose-contacts" class="uibox listbox" role="region" aria-labelledby="aria-label-composecontacts">
<h2 id="aria-label-composecontacts" class="boxtitle"><roundcube:label name="contacts" /></h2>
<div class="listsearchbox" role="search" aria-labelledby="aria-label-composequicksearch">
<h3 id="aria-label-composequicksearch" class="voice"><roundcube:label name="arialabelcontactquicksearch" /></h3>
<div class="searchbox">
<label for="contactsearchbox" class="voice"><roundcube:label name="arialabelcontactsearchbox" /></label>
<roundcube:object name="searchform" id="contactsearchbox" />
<a id="searchmenulink" class="iconbutton searchicon"> </a>
<roundcube:button command="reset-search" class="iconbutton reset" title="resetsearch" content=" " />
</div>
</div>
<roundcube:object name="addressbooks" id="directorylist" class="treelist listing" summary="ariasummarycomposecontacts" />
<div class="scroller withfooter" tabindex="-1">
<roundcube:object name="addresslist" id="contacts-table" class="listing iconized" noheader="true" role="listbox" />
</div>
<div class="boxfooter">
<roundcube:button command="add-recipient" prop="to" type="link" title="to" class="listbutton addto disabled" classAct="listbutton addto" innerClass="inner" content="To+" /><roundcube:button command="add-recipient" prop="cc" type="link" title="cc" class="listbutton addcc disabled" classAct="listbutton addcc" innerClass="inner" content="Cc+" /><roundcube:button command="add-recipient" prop="bcc" type="link" title="bcc" class="listbutton addbcc disabled" classAct="listbutton addbcc" innerClass="inner" content="Bcc+" />
</div>
<div class="boxpagenav">
<roundcube:button command="firstpage" type="link" class="icon firstpage disabled" classAct="icon firstpage" title="firstpage" label="first" />
<roundcube:button command="previouspage" type="link" class="icon prevpage disabled" classAct="icon prevpage" title="previouspage" label="previous" />
<roundcube:button command="nextpage" type="link" class="icon nextpage disabled" classAct="icon nextpage" title="nextpage" label="next" />
<roundcube:button command="lastpage" type="link" class="icon lastpage disabled" classAct="icon lastpage" title="lastpage" label="last" />
</div>
</div>
</div>
<div id="composeview-right" role="main">
<roundcube:form name="form" method="post" id="compose-content" class="uibox">
<!-- message headers -->
<div id="composeheaders" role="region" aria-labelledby="aria-label-composeheaders">
<h2 id="aria-label-composeheaders" class="voice"><roundcube:label name="arialabelmessageheaders" /></h2>
<a href="#options" id="composeoptionstoggle" class="moreheaderstoggle" title="<roundcube:label name='togglecomposeoptions' />" aria-exapnded="false"><span class="iconlink"></span></a>
<table class="headers-table compose-headers">
<tbody>
<tr>
<td class="title"><label for="_from"><roundcube:label name="from" /></label></td>
<td class="editfield">
<roundcube:object name="composeHeaders" part="from" form="form" id="_from" tabindex="1" />
<a href="#identities" onclick="return rcmail.command('identities')" class="iconlink edit" tabindex="0"><roundcube:label name="editidents" /></a>
</td>
</tr><tr>
<td class="title top"><label for="_to"><roundcube:label name="to" /></label></td>
<td class="editfield"><roundcube:object name="composeHeaders" part="to" form="form" id="_to" cols="70" rows="1" tabindex="1" aria-required="true" /></td>
</tr><tr id="compose-cc">
<td class="title top">
<label for="_cc"><roundcube:label name="cc" /></label>
<a href="#cc" onclick="return UI.hide_header_row('cc');" class="iconbutton cancel" title="<roundcube:label name='delete' />" tabindex="3"><roundcube:label name="delete" /> <roundcube:label name="cc" /></a>
</td>
<td class="editfield"><roundcube:object name="composeHeaders" part="cc" form="form" id="_cc" cols="70" rows="1" tabindex="1" /></td>
</tr><tr id="compose-bcc">
<td class="title top">
<label for="_bcc"><roundcube:label name="bcc" /></label>
<a href="#bcc" onclick="return UI.hide_header_row('bcc');" class="iconbutton cancel" title="<roundcube:label name='delete' />" tabindex="3"><roundcube:label name="delete" /> <roundcube:label name="bcc" /></a>
</td>
<td class="editfield"><roundcube:object name="composeHeaders" part="bcc" form="form" id="_bcc" cols="70" rows="1" tabindex="1" /></td>
</tr><tr id="compose-replyto">
<td class="title top">
<label for="_replyto"><roundcube:label name="replyto" /></label>
<a href="#replyto" onclick="return UI.hide_header_row('replyto');" class="iconbutton cancel" title="<roundcube:label name='delete' />" tabindex="3"><roundcube:label name="delete" /> <roundcube:label name="replyto" /></a>
</td>
<td class="editfield"><roundcube:object name="composeHeaders" part="replyto" form="form" id="_replyto" size="70" tabindex="1" /></td>
</tr><tr id="compose-followupto">
<td class="title top">
<label for="_followupto"><roundcube:label name="followupto" /></label>
<a href="#followupto" onclick="return UI.hide_header_row('followupto');" class="iconbutton cancel" title="<roundcube:label name='delete' />" tabindex="3"><roundcube:label name="delete" /> <roundcube:label name="followupto" /></a>
</td>
<td class="editfield"><roundcube:object name="composeHeaders" part="followupto" form="form" id="_followupto" size="70" tabindex="1" /></td>
</tr><tr>
<td></td>
<td class="formlinks">
<a href="#cc" onclick="return UI.show_header_row('cc')" id="cc-link" class="iconlink add" tabindex="3"><roundcube:label name="addcc" /></a>
<a href="#bcc" onclick="return UI.show_header_row('bcc')" id="bcc-link" class="iconlink add" tabindex="3"><roundcube:label name="addbcc" /></a>
<a href="#reply-to" onclick="return UI.show_header_row('replyto')" id="replyto-link" class="iconlink add" tabindex="3"><roundcube:label name="addreplyto" /></a>
<a href="#followup-to" onclick="return UI.show_header_row('followupto')" id="followupto-link" class="iconlink add" tabindex="3"><roundcube:label name="addfollowupto" /></a>
</td>
</tr><tr>
<td class="title"><label for="compose-subject"><roundcube:label name="subject" /></label></td>
<td class="editfield"><roundcube:object name="composeSubject" id="compose-subject" form="form" tabindex="1" /></td>
</tr>
</tbody>
</table>
<div id="composebuttons" class="formbuttons">
<roundcube:button command="extwin" type="link" class="button extwin" classSel="button extwin pressed" innerClass="icon" title="openinextwin" label="openinextwin" condition="!env:extwin" />
</div>
<!-- (collapsable) message options -->
<div id="composeoptions" role="region" aria-labelledby="aria-label-composeoptions">
<h2 id="aria-label-composeoptions" class="voice"><roundcube:label name="arialabelcomposeoptions" /></h2>
<roundcube:if condition="!in_array('htmleditor', (array)config:dont_override)" />
<span class="composeoption">
<label><roundcube:label name="editortype" />
<roundcube:object name="editorSelector" editorid="composebody" tabindex="4" /></label>
</span>
<roundcube:endif />
<span class="composeoption">
<label for="rcmcomposepriority"><roundcube:label name="priority" />
<roundcube:object name="prioritySelector" form="form" id="rcmcomposepriority" tabindex="4" /></label>
</span>
+ <roundcube:if condition="!in_array('mdn_default', (array)config:dont_override)" />
<span class="composeoption">
- <label><roundcube:object name="receiptCheckBox" form="form" id="rcmcomposereceipt" tabindex="4" /> <roundcube:label name="returnreceipt" /></label>
+ <label><roundcube:object name="mdnCheckBox" form="form" id="rcmcomposereceipt" tabindex="4" /> <roundcube:label name="returnreceipt" /></label>
</span>
- <roundcube:if condition="config:smtp_server != ''" />
+ <roundcube:endif />
+ <roundcube:if condition="config:smtp_server != '' and !in_array('dsn_default', (array)config:dont_override)" />
<span class="composeoption">
<label><roundcube:object name="dsnCheckBox" form="form" id="rcmcomposedsn" tabindex="4" /> <roundcube:label name="dsn" /></label>
</span>
<roundcube:endif />
<roundcube:if condition="!config:no_save_sent_messages" />
<span class="composeoption">
<label><roundcube:label name="savesentmessagein" /> <roundcube:object name="storetarget" maxlength="30" style="max-width:12em" tabindex="4" /></label>
</span>
<roundcube:endif />
<roundcube:container name="composeoptions" id="composeoptions" />
</div>
</div>
<!-- message compose body -->
<div id="composeview-bottom">
<div id="composebodycontainer">
<label for="composebody" class="voice"><roundcube:label name="arialabelmessagebody" /></label>
<roundcube:object name="composeBody" id="composebody" form="form" cols="70" rows="20" tabindex="1" />
</div>
<div id="compose-attachments" class="rightcol" role="region" aria-labelledby="aria-label-composeattachments">
<h2 id="aria-label-composeattachments" class="voice"><roundcube:label name="attachments" /></h2>
<div style="text-align:center; margin-bottom:20px">
<roundcube:button name="addattachment" type="input" class="button" classSel="button pressed" label="addattachment" onclick="UI.show_uploadform(event);return false" tabindex="1" />
</div>
<roundcube:object name="composeAttachmentList" id="attachment-list" class="attachmentslist" tabindex="1" />
<roundcube:object name="fileDropArea" id="compose-attachments" />
</div>
<!--
<div id="composeformbuttons" class="footerleft formbuttons floating">
<roundcube:button type="input" command="send" class="button mainaction" label="sendmessage" tabindex="11" />
<roundcube:button type="input" command="savedraft" class="button" label="savemessage" tabindex="12" />
<roundcube:button type="input" command="list" class="button" label="cancel" tabindex="13" />
</div>
-->
</div>
</form>
</div><!-- end mailview-right -->
</div><!-- end mainscreencontent -->
</div><!-- end mainscreen -->
<div id="upload-dialog" class="propform popupdialog" title="<roundcube:label name='addattachment' />" aria-hidden="true">
<h2 id="aria-label-uploaddialog" class="voice"><roundcube:label name="arialabelattachmentuploadform" /></h2>
<roundcube:object name="composeAttachmentForm" id="uploadform" buttons="no" />
<div class="formbuttons">
<roundcube:button command="send-attachment" type="input" class="button mainaction" label="upload" />
<roundcube:button name="close" type="input" class="button" label="cancel" onclick="UI.show_uploadform()" />
</div>
</div>
<div id="spellmenu" class="popupmenu" aria-hidden="true"></div>
<div id="responsesmenu" class="popupmenu" aria-hidden="true">
<h3 id="aria-label-responsesmenu" class="voice"><roundcube:label name="arialabelresponsesmenu" /></h3>
<ul class="toolbarmenu" id="textresponsesmenu" role="menu" aria-labelledby="aria-label-responsesmenu">
<li role="separator" class="separator" id=""><label><roundcube:label name="insertresponse" /></label></li>
<roundcube:object name="responseslist" id="responseslist" tagname="ul" itemclass="active" />
<li role="separator" class="separator"><label><roundcube:label name="manageresponses" /></label></li>
<roundcube:button command="save-response" type="link-menuitem" label="newresponse" classAct="active" unselectable="on" />
<roundcube:button command="responses" type="link-menuitem" label="editresponses" classAct="active" />
</ul>
</div>
<roundcube:include file="/includes/footer.html" />
</body>
</html>

File Metadata

Mime Type
text/x-diff
Expires
Sat, Mar 1, 3:09 AM (1 d, 3 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
165613
Default Alt Text
(249 KB)

Event Timeline