Compare commits

..

3 Commits

Author SHA1 Message Date
Aleksander Machniak 05db0f5d87 Push: Describe deployment on Cyrus IMAP 7 years ago
Aleksander Machniak 77b6e2606a Push: Support cyrus's URI format 7 years ago
Aleksander Machniak ad5f2f0e6f Push plugin (#6544) 7 years ago

@ -1,30 +0,0 @@
<?php
$config = array();
// Database configuration
$config['db_dsnw'] = 'sqlite:////tmp/sqlite.db?mode=0646';
// Test user credentials
$config['tests_username'] = 'test';
$config['tests_password'] = 'test';
// GreenMail
$config['smtp_port'] = 25;
// Settings required by the tests
$config['create_default_folders'] = true;
$config['skin'] = 'elastic';
$config['support_url'] = 'http://support.url';
// Plugins with tests
$config['plugins'] = [
'archive',
'attachment_reminder',
'markasjunk',
'zipdownload'
];
$config['archive_mbox'] = 'Archive';

@ -1,22 +0,0 @@
#!/bin/bash
# The script is intended for use on Travis with Trusty distribution
DIR=$(dirname $0)
# Enable xdebug for code coverage
if [ "$CODE_COVERAGE" != 1 ]; then phpenv config-rm xdebug.ini || true; fi
cd $DIR/..
cp composer.json-dist composer.json
# Add laravel/dusk for Browser tests
if [ "$BROWSER_TESTS" = 1 ]; then composer require "laravel/dusk:~5.9.1" --no-update; fi
# Remove qr-code as it requires php-gd which is not always available on Travis
# and we don't really need it for tests
composer remove endroid/qr-code --no-update
# Install PHP dependencies
composer install --prefer-dist

@ -1,25 +0,0 @@
#!/bin/bash
# The script is intended for use on Travis with Trusty distribution
# It executes unit and functional tests
DIR=$(dirname $0)
cd $DIR/..
if [ "$CODE_COVERAGE" = 1 ]
then
CODE_COVERAGE_ARGS="--coverage-text"
fi
vendor/bin/phpunit -c tests/phpunit.xml $CODE_COVERAGE_ARGS
if [ "$BROWSER_TESTS" = 1 ] && [ $? = 0 ]
then
.ci/setup.sh \
&& echo "TESTS_MODE: DESKTOP" \
&& TESTS_MODE=desktop vendor/bin/phpunit -c tests/Browser/phpunit.xml \
&& echo "TESTS_MODE: PHONE" \
&& TESTS_MODE=phone vendor/bin/phpunit -c tests/Browser/phpunit.xml \
&& echo "TESTS_MODE: TABLET" \
&& TESTS_MODE=tablet vendor/bin/phpunit -c tests/Browser/phpunit.xml
fi

@ -1,30 +0,0 @@
#!/bin/bash
# The script is intended for use on Travis with Trusty distribution
# It installs in-browser tests dependencies and prepares Roundcube instance
GMV=1.5.11
CHROMEVERSION=$(google-chrome-stable --version | tr -cd [:digit:]. | cut -d . -f 1)
GMARGS="-Dgreenmail.setup.all -Dgreenmail.users=test:test -Dgreenmail.startup.timeout=3000"
# Roundcube tests and instance configuration
cp .ci/config-test.inc.php config/config-test.inc.php
# Make temp and logs writeable
sudo chmod 777 temp logs
# Install javascript dependencies
bin/install-jsdeps.sh
# Compile Elastic's styles
lessc skins/elastic/styles/styles.less > skins/elastic/styles/styles.css
lessc skins/elastic/styles/print.less > skins/elastic/styles/print.css
lessc skins/elastic/styles/embed.less > skins/elastic/styles/embed.css
# Install proper WebDriver version for installed Chrome browser
php tests/Browser/install.php $CHROMEVERSION
# GreenMail server download, setup and start
wget https://repo1.maven.org/maven2/com/icegreen/greenmail-standalone/$GMV/greenmail-standalone-$GMV.jar \
&& (sudo java $GMARGS -jar greenmail-standalone-$GMV.jar &) \
&& sleep 5

@ -34,8 +34,8 @@ Options -Indexes
# Disable page indexing # Disable page indexing
Header set X-Robots-Tag "noindex, nofollow" Header set X-Robots-Tag "noindex, nofollow"
# replace 'merge' with 'append' for Apache < 2.2.9 # replace 'append' with 'merge' for Apache version 2.2.9 and later
#Header merge Cache-Control public env=!NO_CACHE #Header append Cache-Control public env=!NO_CACHE
# Optional security headers # Optional security headers
# Only provides increased security if the browser supports those features # Only provides increased security if the browser supports those features

@ -1,6 +1,5 @@
language: php language: php
dist: trusty #
sudo: false sudo: false
matrix: matrix:
@ -14,24 +13,18 @@ matrix:
env: CODE_COVERAGE=1 env: CODE_COVERAGE=1
- php: 7.2 - php: 7.2
- php: 7.3 - php: 7.3
dist: bionic # for proper node-less version
env: BROWSER_TESTS=1
addons:
chrome: stable
apt:
packages:
- node-less
- php: 7.4
cache: cache:
directories: directories:
- $HOME/.composer - $HOME/.composer
install: install:
- .ci/install.sh - if [ "$CODE_COVERAGE" != 1 ]; then phpenv config-rm xdebug.ini || true; fi
- cp composer.json-dist composer.json
- composer install --prefer-dist
script: script:
- .ci/run.sh - if [ "$CODE_COVERAGE" = 1 ]; then CODE_COVERAGE_ARGS="--coverage-text"; fi; vendor/bin/phpunit -c tests/phpunit.xml $CODE_COVERAGE_ARGS
notifications: notifications:
email: false email: false

@ -33,11 +33,6 @@ file_filter = plugins/attachment_reminder/localization/<lang>.inc
source_file = plugins/attachment_reminder/localization/en_US.inc source_file = plugins/attachment_reminder/localization/en_US.inc
source_lang = en_US source_lang = en_US
[roundcube-webmail.plugin-emoticons]
file_filter = plugins/emoticons/localization/<lang>.inc
source_file = plugins/emoticons/localization/en_US.inc
source_lang = en_US
[roundcube-webmail.plugin-enigma] [roundcube-webmail.plugin-enigma]
file_filter = plugins/enigma/localization/<lang>.inc file_filter = plugins/enigma/localization/<lang>.inc
source_file = plugins/enigma/localization/en_US.inc source_file = plugins/enigma/localization/en_US.inc

@ -1,281 +1,6 @@
CHANGELOG Roundcube Webmail CHANGELOG Roundcube Webmail
=========================== ===========================
- Allow array in smtp_host config (#7296)
- Remove use of ext-iconv
- Support RFC8438: IMAP STATUS=SIZE - for faster folder size calculation (#7269)
- MySQL: Use utf8mb4 charset and utf8mb4_unicode_ci collation (#6535, #7113)
- Support for language codes up to 16 chars long (e.g. es-419) in database schema (#6851)
- Relaxed domain name validation for extended TLDs support (#5588)
- Allow opening application/octet-stream attachments according to filename extension (#6821)
- Added support for INSERT OR REPLACE queries (#6771)
- Allow skins to define which layout options they support (#7235)
- Extract RFC2231 attachment name from message headers (#6729, #6783)
- Archive: Added options to split archive by year or year+month and folder (#7216)
- Managesieve: Allow display name with email address in vacation :from field (#6760)
- Managesieve: Improve UX on custom header input (#7207)
- Managesieve: Fix bug where activation of forward/vacation rule could activate a wrong script (#7423)
- Managesieve: Fix bug where forward/vacation rule could end up being duplicated (#7349)
- Password: Added 'pwned' password strength driver (#7274)
- Add support for SameSite cookie attribute via session_samesite option (req PHP >= 7.3.0) (#6772)
- Elastic: Moving single recipients between recipient inputs with drag-n-drop (#5069)
- Elastic: Display a special icon for other users and shared namespace roots (#5012)
- Elastic: Support space-separated email addresses in recipient input (#6529, #6457)
- Change folders sorting so shared/other users namespaces are listed last (#5012)
- Display a warning and do not try to open empty attachments (#7332)
- Templates: Add support for expressions in object attributes (#7237)
- Templates: Add support for nested if conditions (#6818)
- Templates: Make [space][slash] ending of condition objects optional (#6954)
- Fix ISO-2022-JP-MS encoding issues (#7091)
- Fix so messages in threads with no root aren't displayed separately (#4999)
- Fix so anchor tags without href attribute are not modified (#7413)
- Fix bug where subfolders of special folders could have been duplicated on folder list
- Increase maximum size of contact jobtitle and department fields to 128 characters
- Fix missing newline after the logged line when writing to stdout (#7418)
- Elastic: Fix context menu (paste) on the recipient input (#7431)
- Fix problem with forwarding inline images attached to messages with no HTML part (#7414)
RELEASE 1.4.6
-------------
- Installer: Fix regression in SMTP test section (#7417)
RELEASE 1.4.5
-------------
- Fix bug in extracting required plugins from composer.json that led to spurious error in log (#7364)
- Fix so the database setup description is compatible with MySQL 8 (#7340)
- Markasjunk: Fix regression in jsevent driver (#7361)
- Fix missing flag indication on collapsed thread in Larry and Elastic (#7366)
- Fix default keyservers (use keys.openpgp.org), add note about CORS (#7373, #7367)
- Password: Fix issue with Modoboa driver (#7372)
- Mailvelope: Use sender's address to find pubkeys to check signatures (#7348)
- Mailvelope: Fix Encrypt button hidden in Elastic (#7353)
- Fix PHP warning: count(): Parameter must be an array or an object... in ID command handler (#7392)
- Fix error when user-configured skin does not exist anymore (#7271)
- Elastic: Fix aspect ratio of a contact photo in mail preview (#7339)
- Fix bug where PDF attachments marked as inline could have not been attached on mail forward (#7382)
- Security: Fix a couple of XSS issues in Installer (#7406)
- Security: Fix XSS issue in template object 'username' (#7406)
- Security: Better fix for CVE-2020-12641
- Security: Fix cross-site scripting (XSS) via malicious XML attachment
RELEASE 1.4.4
-------------
- Fix bug where attachments with Content-Id were attached to the message on reply (#7122)
- Fix identity selection on reply when both sender and recipient addresses are included in identities (#7211)
- Elastic: Fix text selection with Shift+PageUp and Shift+PageDown in plain text editor when using Chrome (#7230)
- Elastic: Fix recipient input bug when using click to select a contact from autocomplete list (#7231)
- Elastic: Fix color of a folder with recent messages (#7281)
- Elastic: Restrict logo size in print view (#7275)
- Fix invalid Content-Type for messages with only html part and inline images - Mail_Mime-1.10.7 (#7261)
- Fix missing contact display name in QR Code data (#7257)
- Fix so button label in Select image/media dialogs is "Close" not "Cancel" (#7246)
- Fix regression in testing database schema on MSSQL (#7227)
- Fix cursor position after inserting a group to a recipient input using autocompletion (#7267)
- Fix string literals handling in IMAP STATUS (and various other) responses (#7290)
- Fix bug where multiple images in a message were replaced by the first one on forward/reply/edit (#7293)
- Fix handling keyservers configured with protocol prefix (#7295)
- Markasjunk: Fix marking as spam/ham on moving messages with Move menu (#7189)
- Markasjunk: Fix bug where moving to Junk was failing on messages selected with Select > All (#7206)
- Fix so imap error message is displayed to the user on folder create/update (#7245)
- Fix bug where a special folder couldn't be created if a special-use flag is not supported (#7147)
- Mailvelope: Fix bug where recipients with name were not handled properly in mail compose (#7312)
- Fix characters encoding in group rename input after group creation/rename (#7330)
- Fix bug where some message/rfc822 parts could not be attached on forward (#7323)
- Make install-jsdeps.sh script working without the 'file' program installed (#7325)
- Fix performance issue of parsing big HTML messages by disabling HTML5 parser for these (#7331)
- Fix so Print button for PDF attachments works on Firefox >= 75 (#5125)
- Security: Fix XSS issue in handling of CDATA in HTML messages [CVE-2020-12625]
- Security: Fix remote code execution via crafted 'im_convert_path' or 'im_identify_path' settings [CVE-2020-12641]
- Security: Fix local file inclusion (and code execution) via crafted 'plugins' option [CVE-2020-12640]
- Security: Fix CSRF bypass that could be used to log out an authenticated user [CVE-2020-12626] (#7302)
RELEASE 1.4.3
-------------
- Enigma: Fix so key list selection is reset when opening key creation form (#7154)
- Enigma: Fix so using list checkbox selection does not load the key preview frame
- Enigma: Fix generation of key pairs for identities with IDN domains (#7181)
- Enigma: Display IDN domains of key users and identities in UTF8
- Enigma: Fix bug where "Send unencrypted" button didn't work in Elastic skin (#7205)
- Managesieve: Fix bug where it wasn't possible to save flag actions (#7188)
- Markasjunk: Fix bug where marking as spam/ham didn't work on moving messages with drag-and-drop (#7137)
- Password: Make chpass-wrapper.py Python 3 compatible (#7135)
- Elastic: Fix disappearing sidebar in mail compose after clicking Mail button
- Elastic: Fix incorrect aria-disabled attribute on Mail taskmenu button in mail compose
- Elastic: Fix bug where it was possible to switch editor mode when 'htmleditor' was in 'dont_override' (#7143)
- Elastic: Fix text selection in recipient inputs (#7129)
- Elastic: Fix missing Close button in "more recipients" dialog
- Elastic: Fix non-working folder subscription checkbox for newly added folders (#7174)
- Fix regression where "Open in new window" action didn't work (#7155)
- Fix PHP Warning: array_filter() expects parameter 1 to be array, null given in subscriptions_option plugin (#7165)
- Fix unexpected error message when mail refresh involves folder auto-unsubscribe (#6923)
- Fix recipient duplicates in print-view when the recipient list has been expanded (#7169)
- Fix bug where files in skins/ directory were listed on skins list (#7180)
- Fix bug where message parts with no Content-Disposition header and no name were not listed on attachments list (#7117)
- Fix display issues with mail subject that contains line-breaks (#7191)
- Fix invalid Content-Transfer-Encoding on multipart messages - Mail_Mime fix (#7170)
- Fix regression where using an absolute path to SQLite database file on Windows didn't work (#7196)
- Fix using unix:///path/to/socket.file in memcached driver (#7210)
RELEASE 1.4.2
-------------
- Add support for PHPUnit 6 and 7 (#6870)
- Plugin API: Make actionbefore, before<action>, actionafter and after<action> events working with plugin actions (#7106)
- Managesieve: Replace "Filter disabled" with "Filter enabled" (#7028)
- Managesieve: Fix so modifier type select wasn't hidden after hiding modifier select on header change
- Managesieve: Fix filter selection after removing a first filter (#7079)
- Markasjunk: Fix marking more than one message as spam/ham with email_learn driver (#7121)
- Password: Fix kpasswd and smb drivers' double-escaping bug (#7092)
- Enigma: Add script to import keys from filesystem to the db storage (for multihost)
- Installer: Fix DB Write test on SQLite database ("database is locked" error) (#7064)
- Installer: Fix so SQLite DSN with a relative path to the database file works in Installer
- Elastic: Fix contrast of warning toasts (#7058)
- Elastic: Simple search in pretty selects (#7072)
- Elastic: Fix hidden list widget on mobile/tablet when selecting folder while search menu is open (#7120)
- Fix so type attribute on script tags is not used on HTML5 pages (#6975)
- Fix unread count after purge on a folder that is not currently selected (#7051)
- Fix bug where Enter key didn't work on messages list in "List" layout (#7052)
- Fix bug where deleting a saved search in addressbook caused display issue on sources/groups list (#7061)
- Fix bug where a new saved search added after removing all searches wasn't added to the list (#7061)
- Fix bug where a new contact group added after removing all groups from addressbook wasn't added to the list
- Fix bug where Ctype extension wasn't required in Installer and INSTALL file (#7049)
- Fix so install-jsdeps.sh removes Bootstrap's sourceMappingURL (#7035)
- Fix so use of Ctrl+A does not scroll the list (#7020)
- Fix/remove useless keyup event handler on username input in logon form (#6970)
- Fix bug where cancelling switching from HTML to plain text didn't set the flag properly (#7077)
- Fix bug where HTML reply could add an empty line with extra indentation above the original message (#7088)
- Fix matching multiple X-Forwarded-For addresses with 'proxy_whitelist' (#7107)
- Fix so displayed maximum attachment size depends also on 'max_message_size' (#7105)
- Fix bug where 'skins_allowed' option didn't enforce user skin preference (#7080)
- Fix so contact's organization field accepts up to 128 characters (it was 50)
- Fix bug where listing tables in PostgreSQL database with db_prefix didn't work (#7093)
- Fix bug where 'text' attribute on body tag was ignored when displaying HTML message (#7109)
- Fix bug where next message wasn't displayed after delete in List mode (#7096)
- Fix so number of contacts in a group is not limited to 200 when redirecting to mail composer from Contacts (#6972)
- Fix malformed characters in HTML message with charset meta tag not in head (#7116)
RELEASE 1.4.1
-------------
- Elastic: Change HTML editor widget to improve form flow (#6992)
- Elastic: Fix position of mobile floating action button (#7038)
- Managesieve: Fix locked UI after opening filter frame (#7007)
- Fix PHP warning: "array_merge(): Expected parameter 2 to be an array, null given in sendmail.inc (#7003)
- Fix bug where cache keys could exceed length limit specified in db schema (#7004)
- Fix invalid Signature button state after escaping Mailvelope mode (#7015)
- Fix so 401 error is returned only on failed logon requests (#7010)
- Fix db_prefix handling in queries with `TRUNCATE TABLE <name>` and `UNIQUE <name>` (#7013)
- Fix so update.sh script warns about changed defaults (#7011)
- Fix tables listing routine when DSN contained a database with unsupported suffix (#7034)
- Fix so Elastic is also a default in jqueryui plugin (#7039)
- Fix bug where the Installer would not warn about required schema upgrade (#7042)
RELEASE 1.4.0
-------------
- Elastic: Resizeable columns (#6929)
- Elastic: Fix position and style of auto-complete dropdown on small screens (#6951)
- Elastic: Fix initial focus on recipients input in mail compose screen
- Elastic: Fix inserting responses at cursor position (#6971)
- Elastic: Fix unread filter icon and search state on folder change (#6978)
- Elastic: Fix regression where Encrypt button wasn't displayed in mail compose toolbar (#6982)
- Elastic: Fix regression where recipient input didn't update internal input state (#6988)
- Enigma: Fix bug where signing option was set to disabled after saving a draft in Elastic skin (#6515)
- Redis: Improve error handling and phpredis 5.X support (#6888)
- Archive: Fix bug where next email was not displayed after Archive button use (#6965)
- Archive: Fix missing Archive icon in folder selector popup in Elastic
- Fix bug where cache keys were not case-sensitive on MySQL/MSSQL (#6942)
- Fix so an error is logged when encryption fails (#6948)
- Fix bug where inline images could have been ignored if Content-Id header contained redundant spaces (#6980)
- Fix and document skin_logo setup (#6981)
RELEASE 1.4-rc2
---------------
- Update to jQuery 3.4.1
- Clarified 'address_book_type' option behavior (#6680)
- Added cookie mismatch detection, display an error message informing the user to clear cookies
- Renamed 'log_session' option to 'session_debug'
- Removed 'delete_always' option (#6782)
- Don't log full session identifiers in userlogins log (#6625)
- Support $HasAttachment/$HasNoAttachment keywords (#6201)
- Support PECL memcached extension as a session and cache storage driver (experimental)
- Switch to IDNA2008 variant (#6806)
- installto.sh: Add possibility to run the update even on the up-to-date installation (#6533)
- Plugin API: Add 'render_folder_selector' hook
- Added 'keyservers' option to define list of HKP servers for Enigma/Mailvelope (#6326)
- Added flag to disable server certificate validation via Mysql DSN argument (#6848)
- Select all records on the current list page with CTRL + A (#6813)
- Use Left/Right Arrow keys to faster move over threaded messages list (#6399)
- Changes in `display_next` setting (#6795):
- Move it to Preferences > User Interface > Main Options
- Make it apply to Contacts interface too
- Make it apply only if deleting/moving a previewed message/contact
- Redis: Support connection to unix socket
- Put charset meta specification before a title tag, add page title automatically (#6811)
- Elastic: Various internal refactorings
- Elastic: Add Prev/Next buttons on message page toolbar (#6648)
- Elastic: Close search options on Enter key press in quick-search input (#6660)
- Elastic: Changed some icons (#6852)
- Elastic: Changed read/unread icons (#6636)
- Elastic: Changed "Move to..." icon (#6637)
- Elastic: Add hide/show for advanced preferences (#6632)
- Elastic: Add default icon on Settings/Preferences lists for external plugins (#6814)
- Elastic: Add indicator for popover menu items that open a submenu (#6868)
- Elastic: Move compose attachments/options to the right side (#6839)
- Elastic: Add border/background to attachments list widget (#6842)
- Elastic: Add "Show unread messages" button to the search bar (#6587)
- Elastic: Fix bug where toolbar disappears on attachment menu use in Chrome (#6677)
- Elastic: Fix folders list scrolling on touch devices (#6706)
- Elastic: Fix non-working pretty selects in Chrome browser (#6705)
- Elastic: Fix issue with absolute positioned mail content (#6739)
- Elastic: Fix bug where some menu actions could cause a browser popup warning
- Elastic: Fix handling mailto: URL parameters in contact menu (#6751)
- Elastic: Fix keyboard navigation in some menus, e.g. the contact menu
- Elastic: Fix visual issue with long buttons in .boxwarning (#6797)
- Elastic: Fix handling new-line in text pasted to a recipient input
- Elastic: Fix so search is not reset when returning from the message preview page (#6847)
- Larry: Fix regression where menu actions didn't work with keyboard (#6740)
- ACL: Display user/group names (from ldap) instead of acl identifier
- Password: Added ldap_exop driver (#4992)
- Password: Added support for SSHA512 password algorithm (#6805)
- Managesieve: Fix bug where global includes were requested for vacation (#6716)
- Managesieve: Use RFC-compliant line endings, CRLF instead of LF (#6686)
- Managesieve: Fix so "Create filter" option does not show up when Filters menu is disabled (#6723)
- Enigma: For verified signatures, display the user id associated with the sender address (#5958)
- Enigma: Fix bug where revoked users/keys were not greyed out in key info
- Enigma: Fix error message when trying to encrypt with a revoked key (#6607)
- Enigma: Fix "decryption oracle" bug [CVE-2019-10740] (#6638)
- Enigma: Fix bug where signature verification could have been skipped for some message structures (#6838)
- Fix language selection for spellchecker in html mode (#6915)
- Fix css styles leak from replied/forwarded message to the rest of the composed text (#6831)
- Fix invalid path to "add contact" icon when using assets_path setting
- Fix invalid path to blocked.gif when using assets_path setting (#6752)
- Fix so advanced search dialog is not automatically displayed on searchonly addressbooks (#6679)
- Fix so an error is logged when more than one attachment plugin has been enabled, initialize the first one (#6735)
- Fix bug where flag change could have been passed to a preview frame when not expected
- Fix bug in HTML parser that could cause missing text fragments when there was no head/body tag (#6713)
- Fix bug where HTML messages with a xml:namespace tag were not rendered (#6697)
- Fix TinyMCE download location (#6694)
- Fix so "Open in new window" consistently displays "external window" interface (#6659)
- Fix bug where next row wasn't selected after deleting a collapsed thread (#6655)
- Fix bug where external content (e.g. mail body) was passed to templates parsing code (#6640)
- Fix bug where attachment preview didn't work with x_frame_options=deny (#6688)
- Fix so bin/install-jsdeps.sh returns error code on error (#6704)
- Fix bug where bmp images couldn't be displayed on some systems (#6728)
- Fix bug in parsing vCard data using PHP 7.3 due to an invalid regexp (#6744)
- Fix bug where bold/strong text was converted to upper-case on html-to-text conversion (6758)
- Fix bug in rcube_utils::parse_hosts() where %t, %d, %z could return only tld (#6746)
- Fix bug where Next/Prev button in mail view didn't work with multi-folder search result (#6793)
- Fix bug where selection of columns on messages list wasn't working
- Fix bug in converting multi-page Tiff images to Jpeg (#6824)
- Fix bug where handling multiple messages from multi-folder search result could not work (#6845)
- Fix bug where unread count wasn't updated after moving multi-folder result (#6846)
- Fix wrong messages order after returning to a multi-folder search result (#6836)
- Fix some PHP 7.4 compat. issues (#6884, #6866)
- Fix bug where it was possible to bypass the position:fixed CSS check in received messages (#6898)
- Fix bug where some strict remote URIs in url() style were unintentionally blocked (#6899)
- Fix bug where it was possible to bypass the CSS jail in HTML messages using :root pseudo-class (#6897)
- Fix bug where it was possible to bypass href URI check with data:application/xhtml+xml URIs (#6896)
RELEASE 1.4-rc1
---------------
- Changed 'password_charset' default to 'UTF-8' (#6522) - Changed 'password_charset' default to 'UTF-8' (#6522)
- Add skins_allowed option (#6483) - Add skins_allowed option (#6483)
- SMTP GSSAPI support via krb_authentication plugin (#6417) - SMTP GSSAPI support via krb_authentication plugin (#6417)
@ -284,20 +9,16 @@ RELEASE 1.4-rc1
- Use constant prefix for temp file names, don't remove temp files from other apps (#6511) - Use constant prefix for temp file names, don't remove temp files from other apps (#6511)
- Ignore 'Sender' header on Reply-All action (#6506) - Ignore 'Sender' header on Reply-All action (#6506)
- deluser.sh: Add option to delete users who have not logged in for more than X days (#6340) - deluser.sh: Add option to delete users who have not logged in for more than X days (#6340)
- HTML5 Upload Progress - as a replacement for the old server-side solution (#6177)
- Update to TinyMCE 4.8.2 - Update to TinyMCE 4.8.2
- Update to jQuery-MiniColors 2.3.4
- Prevent from using deprecated timezone names from jsTimezoneDetect - Prevent from using deprecated timezone names from jsTimezoneDetect
- Force session.gc_probability=1 when using custom session handlers (#6560) - Force session.gc_probability=1 when using custom session handlers (#6560)
- Support simple field labels (e.g. LetterHub examples) in csv imports (#6541) - Support simple field labels (e.g. LetterHub examples) in csv imports (#6541)
- Add cache busters also to images used by templates (#6610)
- Plugin API: Added 'raise_error' hook (#6199) - Plugin API: Added 'raise_error' hook (#6199)
- Plugin API: Added 'common_headers' hook (#6385) - Plugin API: Added 'common_headers' hook (#6385)
- Plugin API: Added 'ldap_connected' hook - Plugin API: Added 'ldap_connected' hook
- Enigma: Update to OpenPGPjs 4.2.1 - fixes user name encoding issues in key generation (#6524) - Enigma: Update to OpenPGPjs 4.2.1 - fixes user name encoding issues in key generation (#6524)
- Enigma: Fixed multi-host synchronization of private and deleted keys and pubring.kbx file - Enigma: Fixed multi-host synchronization of private and deleted keys and pubring.kbx file
- Managesieve: Added support for 'editheader' extension - RFC5293 (#5954) - Managesieve: Added support for 'editheader' extension - RFC5293 (#5954)
- Managesieve: Fix bug where custom header or variable could be lost on form submission (#6594)
- Markasjunk: Integrate markasjunk2 features into markasjunk - marking as non-junk + learning engine (#6504) - Markasjunk: Integrate markasjunk2 features into markasjunk - marking as non-junk + learning engine (#6504)
- Password: Added 'modoboa' driver (#6361) - Password: Added 'modoboa' driver (#6361)
- Password: Fix bug where password_dovecotpw_with_method setting could be ignored (#6436) - Password: Fix bug where password_dovecotpw_with_method setting could be ignored (#6436)
@ -317,14 +38,8 @@ RELEASE 1.4-rc1
- Elastic: Support new-line char as a separator for pasted recipients (#6460) - Elastic: Support new-line char as a separator for pasted recipients (#6460)
- Elastic: Improved UX of search dialogs (#6416) - Elastic: Improved UX of search dialogs (#6416)
- Elastic: Fix unwanted thread expanding when selecting a collapsed thread in non-mobile mode (#6445) - Elastic: Fix unwanted thread expanding when selecting a collapsed thread in non-mobile mode (#6445)
- Elastic: Fix too small height of mailvelope mail preview frame (#6600)
- Elastic: Add "status bar" for mobile in mail composer - Elastic: Add "status bar" for mobile in mail composer
- Elastic: Add selection options on contacts list (#6595)
- Elastic: Fix unintentional layout preference overwrite (#6613)
- Elastic: Fix bug where Enigma options in mail compose could sometimes be ignored (#6515)
- Log errors caused by low pcre.backtrack_limit when sending a mail message (#6433) - Log errors caused by low pcre.backtrack_limit when sending a mail message (#6433)
- Fix regression where drafts were not deleted after sending the message (#6756)
- Fix so max_message_size limit is checked also when forwarding messages as attachments (#6580)
- Fix so performance stats are logged to the main console log also when per_user_logging=true - Fix so performance stats are logged to the main console log also when per_user_logging=true
- Fix malformed message saved into Sent folder when using big attachments and low memory limit (#6498) - Fix malformed message saved into Sent folder when using big attachments and low memory limit (#6498)
- Fix incorrect IMAP SASL GSSAPI negotiation (#6308) - Fix incorrect IMAP SASL GSSAPI negotiation (#6308)
@ -339,11 +54,6 @@ RELEASE 1.4-rc1
- Fix dummy Message-Id when resuming a draft without Message-Id header (#6548) - Fix dummy Message-Id when resuming a draft without Message-Id header (#6548)
- Fix handling of empty entries in vCard import (#6564) - Fix handling of empty entries in vCard import (#6564)
- Fix bug in parsing some IMAP command responses that include unsolicited replies (#6577) - Fix bug in parsing some IMAP command responses that include unsolicited replies (#6577)
- Fix PHP 7.2 compatibility in debug_logger plugin (#6586)
- Fix so ANY record is not used for email domain validation, use A, MX, CNAME, AAAA instead (#6581)
- Fix so mime_content_type check in Installer uses files that should always be available (i.e. from program/resources) (#6599)
- Fix missing CSRF token on a link to download too-big message part (#6621)
- Fix bug when aborting dragging with ESC key didn't stop the move action (#6623)
RELEASE 1.4-beta RELEASE 1.4-beta
---------------- ----------------

@ -12,9 +12,9 @@ REQUIREMENTS
* An IMAP, HTTP and SMTP server * An IMAP, HTTP and SMTP server
* .htaccess support allowing overrides for DirectoryIndex * .htaccess support allowing overrides for DirectoryIndex
* PHP Version 5.4 or greater including: * PHP Version 5.4 or greater including:
- PCRE, DOM, JSON, Session, Sockets, OpenSSL, Mbstring, Filter, Ctype (required) - PCRE, DOM, JSON, Session, Sockets, OpenSSL, Mbstring (required)
- PHP PDO with driver for either MySQL, PostgreSQL, SQL Server, Oracle or SQLite (required) - PHP PDO with driver for either MySQL, PostgreSQL, SQL Server, Oracle or SQLite (required)
- Zip, Fileinfo, Intl, Exif (recommended) - Iconv, Zip, Fileinfo, Intl, Exif (recommended)
- LDAP for LDAP addressbook support (optional) - LDAP for LDAP addressbook support (optional)
- GD, Imagick (optional thumbnails generation, QR-code) - GD, Imagick (optional thumbnails generation, QR-code)
* PEAR and PEAR packages distributed with Roundcube or external: * PEAR and PEAR packages distributed with Roundcube or external:
@ -26,8 +26,6 @@ REQUIREMENTS
- Net_Sieve 1.4.3 or newer (for managesieve plugin) - Net_Sieve 1.4.3 or newer (for managesieve plugin)
- Crypt_GPG 1.6.3 or newer (for enigma plugin) - Crypt_GPG 1.6.3 or newer (for enigma plugin)
- Endroid/QrCode 1.6.0 or newer (https://github.com/endroid/QrCode) - Endroid/QrCode 1.6.0 or newer (https://github.com/endroid/QrCode)
- Kolab/Net_LDAP3 1.0.6 or newer (for LDAP addressbook)
- Masterminds/HTML5 2.5.x (optional HTML parser)
* php.ini options: * php.ini options:
- error_reporting E_ALL & ~E_NOTICE & ~E_STRICT - error_reporting E_ALL & ~E_NOTICE & ~E_STRICT
- memory_limit > 16MB - memory_limit > 16MB
@ -44,9 +42,7 @@ REQUIREMENTS
INSTALLATION INSTALLATION
============ ============
1. Decompress and put this folder somewhere inside your document root. 1. Decompress and put this folder somewhere inside your document root
Note: Make sure files have proper owner/group for your setup. If you use
tar command `--no-same-owner` option might be helpful.
2. In case you don't use the so-called "complete" release package, 2. In case you don't use the so-called "complete" release package,
you have to install PHP and javascript dependencies. you have to install PHP and javascript dependencies.
2.1. Install PHP dependencies using composer: 2.1. Install PHP dependencies using composer:
@ -65,11 +61,7 @@ INSTALLATION
5. Point your browser to http://url-to-roundcube/installer/ 5. Point your browser to http://url-to-roundcube/installer/
6. Follow the instructions of the install script (or see MANUAL CONFIGURATION) 6. Follow the instructions of the install script (or see MANUAL CONFIGURATION)
7. After creating and testing the configuration, remove the installer directory 7. After creating and testing the configuration, remove the installer directory
------------------------------------------ 8. If you use git sources compile css files for the Elastic skin:
IMPORTANT: REMOVE THE INSTALLER DIRECTORY!
------------------------------------------
8. If you use git sources compile css files for the Elastic skin (required
lessc >= 1.5.0):
$ cd skins/elastic $ cd skins/elastic
$ lessc -x styles/styles.less > styles/styles.css $ lessc -x styles/styles.less > styles/styles.css
$ lessc -x styles/print.less > styles/print.css $ lessc -x styles/print.less > styles/print.css
@ -83,7 +75,7 @@ CONFIGURATION HINTS
IMPORTANT! Read all comments in defaults.inc.php, understand them IMPORTANT! Read all comments in defaults.inc.php, understand them
and configure your installation to be not surprised by default behaviour. and configure your installation to be not surprised by default behaviour.
Roundcube writes internal errors to the 'errors.log' log file located in the logs Roundcube writes internal errors to the 'errors' log file located in the logs
directory which can be configured in config/config.inc.php. If you want ordinary directory which can be configured in config/config.inc.php. If you want ordinary
PHP errors to be logged there as well, set error_log in php.ini or .htaccess file. PHP errors to be logged there as well, set error_log in php.ini or .htaccess file.
@ -109,9 +101,9 @@ importing the table layout and granting the proper permissions to the
roundcube user. Here is an example of that procedure: roundcube user. Here is an example of that procedure:
# mysql # mysql
> CREATE DATABASE roundcubemail CHARACTER SET utf8 COLLATE utf8_general_ci; > CREATE DATABASE roundcubemail /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
> CREATE USER roundcube@localhost IDENTIFIED BY 'password'; > GRANT ALL PRIVILEGES ON roundcubemail.* TO roundcube@localhost
> GRANT ALL PRIVILEGES ON roundcubemail.* TO roundcube@localhost; IDENTIFIED BY 'password';
> quit > quit
# mysql roundcubemail < SQL/mysql.initial.sql # mysql roundcubemail < SQL/mysql.initial.sql
@ -120,11 +112,6 @@ Note 1: 'password' is the master password for the roundcube user. It is strongly
recommended you replace this with a more secure password. Please keep in recommended you replace this with a more secure password. Please keep in
mind: You need to specify this password later in 'config/db.inc.php'. mind: You need to specify this password later in 'config/db.inc.php'.
Note 2: When using MySQL < 5.7.7 or MariaDB < 10.2.2 it is required to configure
the database engine with:
innodb_large_prefix=true
innodb_file_format=Barracuda
* SQLite * SQLite
-------- --------
@ -255,6 +242,11 @@ To enable these features in apache the following modules need to be enabled:
The optimisation is already included in the .htaccess file in the top The optimisation is already included in the .htaccess file in the top
directory of your installation. directory of your installation.
If you are using Apache version 2.2.9 and later, in the .htaccess file
change the 'append' word to 'merge' for a more correct response. Keeping
as 'append' shouldn't cause any problems though changing to merge will
eliminate the possibility of duplicate 'public' headers in Cache-control.
Lighttpd: Lighttpd:
--------- ---------
With Lightty the addition of Expire: tags by mod_expire is incompatible with With Lightty the addition of Expire: tags by mod_expire is incompatible with
@ -296,20 +288,3 @@ PHP >= 5.6 validates the ssl certificates by default. It means that
if IMAP/SMTP certificates are self-signed or use wrong host name you'll get if IMAP/SMTP certificates are self-signed or use wrong host name you'll get
connection errors. A solution in such cases is to set imap_conn_options, connection errors. A solution in such cases is to set imap_conn_options,
smtp_conn_options and managesieve_conn_options in a way described in config/defaults.inc.php. smtp_conn_options and managesieve_conn_options in a way described in config/defaults.inc.php.
If you have problems with temp files or non-working logs make sure temp and logs folders
are writeable to the user used by http server. Access to them may also be blocked by
SELINUX. Here's some sample commands for SELINUX:
$ semanage fcontext -a -t httpd_sys_rw_content_t "/path_to_roundcube/logs(/.*)?"
$ semanage fcontext -a -t httpd_sys_rw_content_t "/path_to_roundcube/temp(/.*)?"
$ restorecon -Rv /path_to_roundcube/
Microsoft IIS Server by default does not support WOFF fonts used in Elastic skin. It might be
needed to add following MIME Types definitions (via web.config or IIS Manager):
.woff application/font-woff
.woff2 application/font-woff2
When installing on Windows be aware we're using symbolic links which may need an additional
attention. See https://github.com/roundcube/roundcubemail/issues/7151.

@ -19,11 +19,17 @@ application-like user interface. It provides full functionality you expect
from an email client, including MIME support, address book, folder management, from an email client, including MIME support, address book, folder management,
message searching and spell checking. Roundcube Webmail is written in PHP and message searching and spell checking. Roundcube Webmail is written in PHP and
requires the MySQL, PostgreSQL or SQLite database. With its plugin API it is requires the MySQL, PostgreSQL or SQLite database. With its plugin API it is
easily extendable and the user interface is fully customizable using skins. easily extendable and the user interface is fully customizable using skins
which are pure XHTML and CSS 2.
The code designed to run on a webserver is mainly written in PHP and Javascript. The code is mainly written in PHP and is designed to run on a webserver.
It includes a custom framework with an IMAP library derived from [IlohaMail][iloha] It includes other open-source classes/libraries from [PEAR][pear],
and requires a set of external libraries (see composer.json and jsdeps.json files). an IMAP library derived from [IlohaMail][iloha] the [TinyMCE][tinymce] rich
text editor, [Googiespell][googiespell] (archive) library for spell checking or
the [HTML5-PHP][html5-php] sanitizer by Masterminds.
The current default skin 'Larry' was kindly created by FLINT / Büro für
Gestaltung, Berne, Switzerland.
INSTALLATION INSTALLATION
@ -43,7 +49,7 @@ support from there. This currently includes:
- Chrome: (Current - 1) and Current - Chrome: (Current - 1) and Current
- Edge: (Current - 1) and Current - Edge: (Current - 1) and Current
- Firefox: (Current - 1) and Current, ESR - Firefox: (Current - 1) and Current, ESR
- Internet Explorer: 9+ (11+ for the Elastic skin) - Internet Explorer: 9+
- Safari: (Current - 1) and Current - Safari: (Current - 1) and Current
- Opera: Current - Opera: Current
@ -96,7 +102,11 @@ You're always welcome to send a message to the project admin:
hello(at)roundcube(dot)net hello(at)roundcube(dot)net
[pear]: https://pear.php.net/
[iloha]: https://sourceforge.net/projects/ilohamail/ [iloha]: https://sourceforge.net/projects/ilohamail/
[tinymce]: https://www.tiny.cloud/
[googiespell]: https://web.archive.org/web/20170314162746/orangoo.com/labs/GoogieSpell/
[html5-php]: https://github.com/Masterminds/html5-php
[gpl]: https://www.gnu.org/licenses/ [gpl]: https://www.gnu.org/licenses/
[license]: https://roundcube.net/license [license]: https://roundcube.net/license
[contrib]: https://roundcube.net/contribute [contrib]: https://roundcube.net/contribute

@ -1,13 +1,13 @@
CREATE TABLE [dbo].[cache] ( CREATE TABLE [dbo].[cache] (
[user_id] [int] NOT NULL , [user_id] [int] NOT NULL ,
[cache_key] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL , [cache_key] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
[expires] [datetime] NULL , [expires] [datetime] NULL ,
[data] [text] COLLATE Latin1_General_CI_AI NOT NULL [data] [text] COLLATE Latin1_General_CI_AI NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO GO
CREATE TABLE [dbo].[cache_shared] ( CREATE TABLE [dbo].[cache_shared] (
[cache_key] [varchar] (255) COLLATE Latin1_General_CS_AS NOT NULL , [cache_key] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL ,
[expires] [datetime] NULL , [expires] [datetime] NULL ,
[data] [text] COLLATE Latin1_General_CI_AI NOT NULL [data] [text] COLLATE Latin1_General_CI_AI NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
@ -15,7 +15,7 @@ GO
CREATE TABLE [dbo].[cache_index] ( CREATE TABLE [dbo].[cache_index] (
[user_id] [int] NOT NULL , [user_id] [int] NOT NULL ,
[mailbox] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL , [mailbox] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
[expires] [datetime] NULL , [expires] [datetime] NULL ,
[valid] [char] (1) COLLATE Latin1_General_CI_AI NOT NULL , [valid] [char] (1) COLLATE Latin1_General_CI_AI NOT NULL ,
[data] [text] COLLATE Latin1_General_CI_AI NOT NULL [data] [text] COLLATE Latin1_General_CI_AI NOT NULL
@ -24,7 +24,7 @@ GO
CREATE TABLE [dbo].[cache_thread] ( CREATE TABLE [dbo].[cache_thread] (
[user_id] [int] NOT NULL , [user_id] [int] NOT NULL ,
[mailbox] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL , [mailbox] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
[expires] [datetime] NULL , [expires] [datetime] NULL ,
[data] [text] COLLATE Latin1_General_CI_AI NOT NULL [data] [text] COLLATE Latin1_General_CI_AI NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
@ -32,7 +32,7 @@ GO
CREATE TABLE [dbo].[cache_messages] ( CREATE TABLE [dbo].[cache_messages] (
[user_id] [int] NOT NULL , [user_id] [int] NOT NULL ,
[mailbox] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL , [mailbox] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
[uid] [int] NOT NULL , [uid] [int] NOT NULL ,
[expires] [datetime] NULL , [expires] [datetime] NULL ,
[data] [text] COLLATE Latin1_General_CI_AI NOT NULL , [data] [text] COLLATE Latin1_General_CI_AI NOT NULL ,
@ -96,20 +96,20 @@ GO
CREATE TABLE [dbo].[users] ( CREATE TABLE [dbo].[users] (
[user_id] [int] IDENTITY (1, 1) NOT NULL , [user_id] [int] IDENTITY (1, 1) NOT NULL ,
[username] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL , [username] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
[mail_host] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL , [mail_host] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
[created] [datetime] NOT NULL , [created] [datetime] NOT NULL ,
[last_login] [datetime] NULL , [last_login] [datetime] NULL ,
[failed_login] [datetime] NULL , [failed_login] [datetime] NULL ,
[failed_login_counter] [int] NULL , [failed_login_counter] [int] NULL ,
[language] [varchar] (16) COLLATE Latin1_General_CI_AI NULL , [language] [varchar] (5) COLLATE Latin1_General_CI_AI NULL ,
[preferences] [text] COLLATE Latin1_General_CI_AI NULL [preferences] [text] COLLATE Latin1_General_CI_AI NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO GO
CREATE TABLE [dbo].[dictionary] ( CREATE TABLE [dbo].[dictionary] (
[user_id] [int] , [user_id] [int] ,
[language] [varchar] (16) COLLATE Latin1_General_CI_AI NOT NULL , [language] [varchar] (5) COLLATE Latin1_General_CI_AI NOT NULL ,
[data] [text] COLLATE Latin1_General_CI_AI NOT NULL [data] [text] COLLATE Latin1_General_CI_AI NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO GO
@ -422,6 +422,6 @@ CREATE TRIGGER [contact_delete_member] ON [dbo].[contacts]
WHERE [contact_id] IN (SELECT [contact_id] FROM deleted) WHERE [contact_id] IN (SELECT [contact_id] FROM deleted)
GO GO
INSERT INTO [dbo].[system] ([name], [value]) VALUES ('roundcube-version', '2020020101') INSERT INTO [dbo].[system] ([name], [value]) VALUES ('roundcube-version', '2018122300')
GO GO

@ -1,18 +0,0 @@
ALTER TABLE [dbo].[cache] ALTER COLUMN
[cache_key] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL
GO
ALTER TABLE [dbo].[cache_shared] ALTER COLUMN
[cache_key] [varchar] (255) COLLATE Latin1_General_CS_AS NOT NULL
GO
ALTER TABLE [dbo].[cache_index] ALTER COLUMN
[mailbox] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL
GO
ALTER TABLE [dbo].[cache_messages] ALTER COLUMN
[mailbox] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL
GO
ALTER TABLE [dbo].[cache_thread] ALTER COLUMN
[mailbox] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL
GO
ALTER TABLE [dbo].[users] ALTER COLUMN
[username] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL
GO

@ -1,4 +0,0 @@
ALTER TABLE [dbo].[users] ALTER COLUMN [language] [varchar] (16) COLLATE Latin1_General_CI_AI NULL
GO
ALTER TABLE [dbo].[dictionary] ALTER COLUMN [language] [varchar] (16) COLLATE Latin1_General_CI_AI NOT NULL
GO

@ -12,7 +12,7 @@ CREATE TABLE `session` (
`vars` mediumtext NOT NULL, `vars` mediumtext NOT NULL,
PRIMARY KEY(`sess_id`), PRIMARY KEY(`sess_id`),
INDEX `changed_index` (`changed`) INDEX `changed_index` (`changed`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */; ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
-- Table structure for table `users` -- Table structure for table `users`
@ -25,36 +25,36 @@ CREATE TABLE `users` (
`last_login` datetime DEFAULT NULL, `last_login` datetime DEFAULT NULL,
`failed_login` datetime DEFAULT NULL, `failed_login` datetime DEFAULT NULL,
`failed_login_counter` int(10) UNSIGNED DEFAULT NULL, `failed_login_counter` int(10) UNSIGNED DEFAULT NULL,
`language` varchar(16), `language` varchar(5),
`preferences` longtext, `preferences` longtext,
PRIMARY KEY(`user_id`), PRIMARY KEY(`user_id`),
UNIQUE `username` (`username`, `mail_host`) UNIQUE `username` (`username`, `mail_host`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */; ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
-- Table structure for table `cache` -- Table structure for table `cache`
CREATE TABLE `cache` ( CREATE TABLE `cache` (
`user_id` int(10) UNSIGNED NOT NULL, `user_id` int(10) UNSIGNED NOT NULL,
`cache_key` varchar(128) BINARY NOT NULL, `cache_key` varchar(128) /*!40101 CHARACTER SET ascii COLLATE ascii_general_ci */ NOT NULL,
`expires` datetime DEFAULT NULL, `expires` datetime DEFAULT NULL,
`data` longtext NOT NULL, `data` longtext NOT NULL,
PRIMARY KEY (`user_id`, `cache_key`), PRIMARY KEY (`user_id`, `cache_key`),
CONSTRAINT `user_id_fk_cache` FOREIGN KEY (`user_id`) CONSTRAINT `user_id_fk_cache` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE, REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
INDEX `expires_index` (`expires`) INDEX `expires_index` (`expires`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */; ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
-- Table structure for table `cache_shared` -- Table structure for table `cache_shared`
CREATE TABLE `cache_shared` ( CREATE TABLE `cache_shared` (
`cache_key` varchar(255) BINARY NOT NULL, `cache_key` varchar(255) /*!40101 CHARACTER SET ascii COLLATE ascii_general_ci */ NOT NULL,
`expires` datetime DEFAULT NULL, `expires` datetime DEFAULT NULL,
`data` longtext NOT NULL, `data` longtext NOT NULL,
PRIMARY KEY (`cache_key`), PRIMARY KEY (`cache_key`),
INDEX `expires_index` (`expires`) INDEX `expires_index` (`expires`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */; ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
-- Table structure for table `cache_index` -- Table structure for table `cache_index`
@ -69,7 +69,7 @@ CREATE TABLE `cache_index` (
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE, REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
INDEX `expires_index` (`expires`), INDEX `expires_index` (`expires`),
PRIMARY KEY (`user_id`, `mailbox`) PRIMARY KEY (`user_id`, `mailbox`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */; ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
-- Table structure for table `cache_thread` -- Table structure for table `cache_thread`
@ -83,7 +83,7 @@ CREATE TABLE `cache_thread` (
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE, REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
INDEX `expires_index` (`expires`), INDEX `expires_index` (`expires`),
PRIMARY KEY (`user_id`, `mailbox`) PRIMARY KEY (`user_id`, `mailbox`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */; ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
-- Table structure for table `cache_messages` -- Table structure for table `cache_messages`
@ -99,7 +99,7 @@ CREATE TABLE `cache_messages` (
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE, REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
INDEX `expires_index` (`expires`), INDEX `expires_index` (`expires`),
PRIMARY KEY (`user_id`, `mailbox`, `uid`) PRIMARY KEY (`user_id`, `mailbox`, `uid`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */; ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
-- Table structure for table `contacts` -- Table structure for table `contacts`
@ -119,7 +119,7 @@ CREATE TABLE `contacts` (
CONSTRAINT `user_id_fk_contacts` FOREIGN KEY (`user_id`) CONSTRAINT `user_id_fk_contacts` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE, REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
INDEX `user_contacts_index` (`user_id`,`del`) INDEX `user_contacts_index` (`user_id`,`del`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */; ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
-- Table structure for table `contactgroups` -- Table structure for table `contactgroups`
@ -133,7 +133,7 @@ CREATE TABLE `contactgroups` (
CONSTRAINT `user_id_fk_contactgroups` FOREIGN KEY (`user_id`) CONSTRAINT `user_id_fk_contactgroups` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE, REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
INDEX `contactgroups_user_index` (`user_id`,`del`) INDEX `contactgroups_user_index` (`user_id`,`del`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */; ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
CREATE TABLE `contactgroupmembers` ( CREATE TABLE `contactgroupmembers` (
`contactgroup_id` int(10) UNSIGNED NOT NULL, `contactgroup_id` int(10) UNSIGNED NOT NULL,
@ -168,7 +168,7 @@ CREATE TABLE `identities` (
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE, REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
INDEX `user_identities_index` (`user_id`, `del`), INDEX `user_identities_index` (`user_id`, `del`),
INDEX `email_identities_index` (`email`, `del`) INDEX `email_identities_index` (`email`, `del`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */; ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
-- Table structure for table `dictionary` -- Table structure for table `dictionary`
@ -176,12 +176,12 @@ CREATE TABLE `identities` (
CREATE TABLE `dictionary` ( CREATE TABLE `dictionary` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, -- redundant, for compat. with Galera Cluster `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, -- redundant, for compat. with Galera Cluster
`user_id` int(10) UNSIGNED DEFAULT NULL, -- NULL here is for "shared dictionaries" `user_id` int(10) UNSIGNED DEFAULT NULL, -- NULL here is for "shared dictionaries"
`language` varchar(16) NOT NULL, `language` varchar(5) NOT NULL,
`data` longtext NOT NULL, `data` longtext NOT NULL,
CONSTRAINT `user_id_fk_dictionary` FOREIGN KEY (`user_id`) CONSTRAINT `user_id_fk_dictionary` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE, REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
UNIQUE `uniqueness` (`user_id`, `language`) UNIQUE `uniqueness` (`user_id`, `language`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */; ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
-- Table structure for table `searches` -- Table structure for table `searches`
@ -196,7 +196,7 @@ CREATE TABLE `searches` (
CONSTRAINT `user_id_fk_searches` FOREIGN KEY (`user_id`) CONSTRAINT `user_id_fk_searches` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE, REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
UNIQUE `uniqueness` (`user_id`, `type`, `name`) UNIQUE `uniqueness` (`user_id`, `type`, `name`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */; ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
-- Table structure for table `filestore` -- Table structure for table `filestore`
@ -211,7 +211,7 @@ CREATE TABLE `filestore` (
CONSTRAINT `user_id_fk_filestore` FOREIGN KEY (`user_id`) CONSTRAINT `user_id_fk_filestore` FOREIGN KEY (`user_id`)
REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE, REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
UNIQUE `uniqueness` (`user_id`, `context`, `filename`) UNIQUE `uniqueness` (`user_id`, `context`, `filename`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */; );
-- Table structure for table `system` -- Table structure for table `system`
@ -219,8 +219,8 @@ CREATE TABLE `system` (
`name` varchar(64) NOT NULL, `name` varchar(64) NOT NULL,
`value` mediumtext, `value` mediumtext,
PRIMARY KEY(`name`) PRIMARY KEY(`name`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */; ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
/*!40014 SET FOREIGN_KEY_CHECKS=1 */; /*!40014 SET FOREIGN_KEY_CHECKS=1 */;
INSERT INTO `system` (`name`, `value`) VALUES ('roundcube-version', '2020020101'); INSERT INTO `system` (`name`, `value`) VALUES ('roundcube-version', '2018122300');

@ -8,4 +8,4 @@ CREATE TABLE `filestore` (
CONSTRAINT `user_id_fk_filestore` FOREIGN KEY (`user_id`) CONSTRAINT `user_id_fk_filestore` FOREIGN KEY (`user_id`)
REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE, REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
UNIQUE `uniqueness` (`user_id`, `filename`) UNIQUE `uniqueness` (`user_id`, `filename`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */; );

@ -1,2 +0,0 @@
ALTER TABLE `cache` CHANGE `cache_key` `cache_key` varchar(128) BINARY NOT NULL;
ALTER TABLE `cache_shared` CHANGE `cache_key` `cache_key` varchar(255) BINARY NOT NULL;

@ -1,2 +0,0 @@
ALTER TABLE `users` MODIFY `language` varchar(16);
ALTER TABLE `dictionary` MODIFY `language` varchar(16) NOT NULL;

@ -1,21 +0,0 @@
ALTER TABLE `session` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `users` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `cache` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `cache_shared` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `cache_index` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `cache_thread` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `cache_messages` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `contacts` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `contactgroups` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `identities` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `dictionary` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `searches` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `filestore` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `system` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `users` CHANGE `username` `username` varchar(128) BINARY NOT NULL;
ALTER TABLE `cache` CHANGE `cache_key` `cache_key` varchar(128) BINARY NOT NULL;
ALTER TABLE `cache_shared` CHANGE `cache_key` `cache_key` varchar(255) BINARY NOT NULL;
ALTER TABLE `cache_index` CHANGE `mailbox` `mailbox` varchar(255) BINARY NOT NULL;
ALTER TABLE `cache_thread` CHANGE `mailbox` `mailbox` varchar(255) BINARY NOT NULL;
ALTER TABLE `cache_messages` CHANGE `mailbox` `mailbox` varchar(255) BINARY NOT NULL;

@ -9,7 +9,7 @@ CREATE TABLE "users" (
"last_login" timestamp with time zone DEFAULT NULL, "last_login" timestamp with time zone DEFAULT NULL,
"failed_login" timestamp with time zone DEFAULT NULL, "failed_login" timestamp with time zone DEFAULT NULL,
"failed_login_counter" integer DEFAULT NULL, "failed_login_counter" integer DEFAULT NULL,
"language" varchar(16), "language" varchar(5),
"preferences" long DEFAULT NULL, "preferences" long DEFAULT NULL,
CONSTRAINT "users_username_key" UNIQUE ("username", "mail_host") CONSTRAINT "users_username_key" UNIQUE ("username", "mail_host")
); );
@ -186,7 +186,7 @@ CREATE INDEX "cache_messages_expires_idx" ON "cache_messages" ("expires");
CREATE TABLE "dictionary" ( CREATE TABLE "dictionary" (
"user_id" integer DEFAULT NULL "user_id" integer DEFAULT NULL
REFERENCES "users" ("user_id") ON DELETE CASCADE, REFERENCES "users" ("user_id") ON DELETE CASCADE,
"language" varchar(16) NOT NULL, "language" varchar(5) NOT NULL,
"data" long DEFAULT NULL, "data" long DEFAULT NULL,
CONSTRAINT "dictionary_user_id_lang_key" UNIQUE ("user_id", "language") CONSTRAINT "dictionary_user_id_lang_key" UNIQUE ("user_id", "language")
); );
@ -238,4 +238,4 @@ CREATE TABLE "system" (
"value" long "value" long
); );
INSERT INTO "system" ("name", "value") VALUES ('roundcube-version', '2020020101'); INSERT INTO "system" ("name", "value") VALUES ('roundcube-version', '2018122300');

@ -1,2 +0,0 @@
ALTER TABLE "users" MODIFY "language" varchar(16) NOT NULL;
ALTER TABLE "dictionary" MODIFY "language" varchar(16);

@ -24,7 +24,7 @@ CREATE TABLE users (
last_login timestamp with time zone DEFAULT NULL, last_login timestamp with time zone DEFAULT NULL,
failed_login timestamp with time zone DEFAULT NULL, failed_login timestamp with time zone DEFAULT NULL,
failed_login_counter integer DEFAULT NULL, failed_login_counter integer DEFAULT NULL,
"language" varchar(16), "language" varchar(5),
preferences text DEFAULT ''::text NOT NULL, preferences text DEFAULT ''::text NOT NULL,
CONSTRAINT users_username_key UNIQUE (username, mail_host) CONSTRAINT users_username_key UNIQUE (username, mail_host)
); );
@ -246,7 +246,7 @@ CREATE INDEX cache_messages_expires_idx ON cache_messages (expires);
CREATE TABLE dictionary ( CREATE TABLE dictionary (
user_id integer DEFAULT NULL user_id integer DEFAULT NULL
REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE, REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
"language" varchar(16) NOT NULL, "language" varchar(5) NOT NULL,
data text NOT NULL, data text NOT NULL,
CONSTRAINT dictionary_user_id_language_key UNIQUE (user_id, "language") CONSTRAINT dictionary_user_id_language_key UNIQUE (user_id, "language")
); );
@ -314,4 +314,4 @@ CREATE TABLE "system" (
value text value text
); );
INSERT INTO "system" (name, value) VALUES ('roundcube-version', '2020020101'); INSERT INTO "system" (name, value) VALUES ('roundcube-version', '2018122300');

@ -1,2 +0,0 @@
ALTER TABLE "dictionary" ALTER COLUMN "language" TYPE varchar(16);
ALTER TABLE "users" ALTER COLUMN "language" TYPE varchar(16);

@ -74,7 +74,7 @@ CREATE TABLE users (
last_login datetime DEFAULT NULL, last_login datetime DEFAULT NULL,
failed_login datetime DEFAULT NULL, failed_login datetime DEFAULT NULL,
failed_login_counter integer DEFAULT NULL, failed_login_counter integer DEFAULT NULL,
language varchar(16), language varchar(5),
preferences text NOT NULL default '' preferences text NOT NULL default ''
); );
@ -99,11 +99,11 @@ CREATE INDEX ix_session_changed ON session (changed);
CREATE TABLE dictionary ( CREATE TABLE dictionary (
user_id integer DEFAULT NULL, user_id integer DEFAULT NULL,
language varchar(16) NOT NULL, "language" varchar(5) NOT NULL,
data text NOT NULL data text NOT NULL
); );
CREATE UNIQUE INDEX ix_dictionary_user_language ON dictionary (user_id, language); CREATE UNIQUE INDEX ix_dictionary_user_language ON dictionary (user_id, "language");
-- --
-- Table structure for table searches -- Table structure for table searches
@ -215,4 +215,4 @@ CREATE TABLE system (
value text NOT NULL value text NOT NULL
); );
INSERT INTO system (name, value) VALUES ('roundcube-version', '2020020101'); INSERT INTO system (name, value) VALUES ('roundcube-version', '2018122300');

@ -1,57 +0,0 @@
CREATE TABLE tmp_users (
user_id integer NOT NULL PRIMARY KEY,
username varchar(128) NOT NULL default '',
mail_host varchar(128) NOT NULL default '',
created datetime NOT NULL default '0000-00-00 00:00:00',
last_login datetime DEFAULT NULL,
failed_login datetime DEFAULT NULL,
failed_login_counter integer DEFAULT NULL,
language varchar(16),
preferences text NOT NULL default ''
);
INSERT INTO tmp_users (user_id, username, mail_host, created, last_login, failed_login, failed_login_counter, language, preferences)
SELECT user_id, username, mail_host, created, last_login, failed_login, failed_login_counter, language, preferences FROM users;
DROP TABLE users;
CREATE TABLE users (
user_id integer NOT NULL PRIMARY KEY,
username varchar(128) NOT NULL default '',
mail_host varchar(128) NOT NULL default '',
created datetime NOT NULL default '0000-00-00 00:00:00',
last_login datetime DEFAULT NULL,
failed_login datetime DEFAULT NULL,
failed_login_counter integer DEFAULT NULL,
language varchar(16),
preferences text NOT NULL default ''
);
INSERT INTO users (user_id, username, mail_host, created, last_login, failed_login, failed_login_counter, language, preferences)
SELECT user_id, username, mail_host, created, last_login, failed_login, failed_login_counter, language, preferences FROM tmp_users;
CREATE UNIQUE INDEX ix_users_username ON users(username, mail_host);
DROP TABLE tmp_users;
DROP TABLE users;
CREATE TABLE tmp_dictionary (
user_id integer DEFAULT NULL,
language varchar(16) NOT NULL,
data text NOT NULL
);
INSERT INTO tmp_dictionary (user_id, language, data) SELECT user_id, language, data FROM dictionary;
CREATE TABLE dictionary (
user_id integer DEFAULT NULL,
language varchar(16) NOT NULL,
data text NOT NULL
);
INSERT INTO dictionary (user_id, language, data) SELECT user_id, language, data FROM tmp_dictionary;
CREATE UNIQUE INDEX ix_dictionary_user_language ON dictionary (user_id, language);
DROP TABLE tmp_dictionary;

@ -20,12 +20,7 @@ target location and check and update the configuration and database schema.
After all is done, the temporary folder with the new Roundcube files can be After all is done, the temporary folder with the new Roundcube files can be
removed again. removed again.
WARNING: Make sure files have proper owner/group for your setup. If you use
tar to extract the package, `--no-same-owner` option might be helpful.
WARNING: See Post-Upgrade Activities section below. WARNING: See Post-Upgrade Activities section below.
WARNING: If you use MySQL < 5.7.7 or MariaDB < 10.2.2 make sure to configure it with:
innodb_large_prefix=true
innodb_file_format=Barracuda
Updating manually Updating manually
@ -58,8 +53,7 @@ it on a unix system, you need to do the following operations by hand:
- run `php composer.phar install --no-dev`. - run `php composer.phar install --no-dev`.
4c. If you use git sources or the release package without dependencies 4c. If you use git sources or the release package without dependencies
update javascript dependencies by executing `bin/install-jsdeps.sh` script. update javascript dependencies by executing `bin/install-jsdeps.sh` script.
4d. If you use git sources compile css files for the Elastic skin (required 4d. If you use git sources compile css files for the Elastic skin:
lessc >= 1.5.0):
$ cd skins/elastic $ cd skins/elastic
$ lessc -x styles/styles.less > styles/styles.css $ lessc -x styles/styles.less > styles/styles.css
$ lessc -x styles/print.less > styles/print.css $ lessc -x styles/print.less > styles/print.css

@ -2,9 +2,10 @@
<?php <?php
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client | | bin/cleandb.sh |
| | | |
| Copyright (C) The Roundcube Dev Team | | This file is part of the Roundcube Webmail client |
| Copyright (C) 2010-2015, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
@ -12,6 +13,7 @@
| | | |
| PURPOSE: | | PURPOSE: |
| Finally remove all db records marked as deleted some time ago | | Finally remove all db records marked as deleted some time ago |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> | | Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
@ -27,3 +29,5 @@ else
$days = 7; $days = 7;
rcmail_utils::db_clean($days); rcmail_utils::db_clean($days);
?>

@ -5,42 +5,42 @@ VERSION='2.4.8'
COMPILER_URL="https://github.com/yui/yuicompressor/releases/download/v${VERSION}/yuicompressor-${VERSION}.zip" COMPILER_URL="https://github.com/yui/yuicompressor/releases/download/v${VERSION}/yuicompressor-${VERSION}.zip"
do_shrink() { do_shrink() {
rm -f "$2" rm -f "$2"
java -jar $JAR_DIR/yuicompressor.jar -v -o "$2" "$1" java -jar $JAR_DIR/yuicompressor.jar -v -o "$2" "$1"
} }
if [ ! -w "$JAR_DIR" ]; then if [ ! -w "$JAR_DIR" ]; then
JAR_DIR=$PWD JAR_DIR=$PWD
fi fi
if java -version >/dev/null 2>&1; then if java -version >/dev/null 2>&1; then
: :
else else
echo "Java not found. Please ensure that the 'java' program is in your PATH." echo "Java not found. Please ensure that the 'java' program is in your PATH."
exit 1 exit 1
fi fi
if [ ! -r "$JAR_DIR/yuicompressor.jar" ]; then if [ ! -r "$JAR_DIR/yuicompressor.jar" ]; then
if which wget >/dev/null 2>&1 && which unzip >/dev/null 2>&1; then if which wget >/dev/null 2>&1 && which unzip >/dev/null 2>&1; then
wget "$COMPILER_URL" -O "/tmp/$$.zip" wget "$COMPILER_URL" -O "/tmp/$$.zip"
elif which curl >/dev/null 2>&1 && which unzip >/dev/null 2>&1; then elif which curl >/dev/null 2>&1 && which unzip >/dev/null 2>&1; then
curl -L "$COMPILER_URL" -o "/tmp/$$.zip" curl "$COMPILER_URL" -o "/tmp/$$.zip"
else else
echo "Please download $COMPILER_URL and extract compiler.jar to $JAR_DIR/." echo "Please download $COMPILER_URL and extract compiler.jar to $JAR_DIR/."
exit 1 exit 1
fi fi
(cd $JAR_DIR && unzip "/tmp/$$.zip" && mv "yuicompressor-${VERSION}.jar" "yuicompressor.jar") (cd $JAR_DIR && unzip "/tmp/$$.zip" && mv "yuicompressor-${VERSION}.jar" "yuicompressor.jar")
rm -f "/tmp/$$.zip" rm -f "/tmp/$$.zip"
fi fi
# compress single file from argument # compress single file from argument
if [ $# -gt 0 ]; then if [ $# -gt 0 ]; then
CSS_FILE="$1" CSS_FILE="$1"
echo "Shrinking $CSS_FILE" echo "Shrinking $CSS_FILE"
minfile=`echo $CSS_FILE | sed -e 's/\.css$/\.min\.css/'` minfile=`echo $CSS_FILE | sed -e 's/\.css$/\.min\.css/'`
do_shrink "$CSS_FILE" "$minfile" do_shrink "$CSS_FILE" "$minfile"
exit exit
fi fi
DIRS="$PWD/../skins/* $PWD/../plugins/* $PWD/../plugins/*/skins/*" DIRS="$PWD/../skins/* $PWD/../plugins/* $PWD/../plugins/*/skins/*"

@ -2,9 +2,10 @@
<?php <?php
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client | | bin/decrypt.sh |
| | | |
| Copyright (C) The Roundcube Dev Team | | This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2009, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
@ -12,6 +13,7 @@
| | | |
| PURPOSE: | | PURPOSE: |
| Decrypt the encrypted parts of the HTTP Received: headers | | Decrypt the encrypted parts of the HTTP Received: headers |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Author: Tomas Tevesz <ice@extreme.hu> | | Author: Tomas Tevesz <ice@extreme.hu> |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
@ -55,11 +57,11 @@ define('INSTALL_PATH', realpath(__DIR__ .'/..') . '/');
require INSTALL_PATH . 'program/include/clisetup.php'; require INSTALL_PATH . 'program/include/clisetup.php';
if ($argc < 2) { if ($argc < 2) {
die("Usage: " . basename($argv[0]) . " encrypted-hdr-part [encrypted-hdr-part ...]\n"); die("Usage: " . basename($argv[0]) . " encrypted-hdr-part [encrypted-hdr-part ...]\n");
} }
$RCMAIL = rcube::get_instance(); $RCMAIL = rcube::get_instance();
for ($i = 1; $i < $argc; $i++) { for ($i = 1; $i < $argc; $i++) {
printf("%s\n", $RCMAIL->decrypt($argv[$i])); printf("%s\n", $RCMAIL->decrypt($argv[$i]));
}; };

@ -3,9 +3,10 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client | | bin/deluser.sh |
| | | |
| Copyright (C) The Roundcube Dev Team | | This file is part of the Roundcube Webmail client |
| Copyright (C) 2014, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
@ -33,7 +34,7 @@ function print_usage()
function _die($msg, $usage=false) function _die($msg, $usage=false)
{ {
fwrite(STDERR, $msg . "\n"); fputs(STDERR, $msg . "\n");
if ($usage) print_usage(); if ($usage) print_usage();
exit(1); exit(1);
} }

@ -0,0 +1,97 @@
#!/usr/bin/env php
<?php
/*
+-----------------------------------------------------------------------+
| bin/dumpschema.sh |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2009, 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: |
| Dumps database schema in XML format using MDB2_Schema |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
require INSTALL_PATH.'program/include/clisetup.php';
/** callback function for schema dump **/
function print_schema($dump)
{
foreach ((array)$dump as $part)
echo $dump . "\n";
}
$config = new rcube_config();
// don't allow public access if not in devel_mode
if (!$config->get('devel_mode') && $_SERVER['REMOTE_ADDR']) {
header("HTTP/1.0 401 Access denied");
die("Access denied!");
}
$options = array(
'use_transactions' => false,
'log_line_break' => "\n",
'idxname_format' => '%s',
'debug' => false,
'quote_identifier' => true,
'force_defaults' => false,
'portability' => false,
);
$dsnw = $config->get('db_dsnw');
$dsn_array = MDB2::parseDSN($dsnw);
// set options for postgres databases
if ($dsn_array['phptype'] == 'pgsql') {
$options['disable_smart_seqname'] = true;
$options['seqname_format'] = '%s';
}
$schema =& MDB2_Schema::factory($dsnw, $options);
$schema->db->supported['transactions'] = false;
// send as text/xml when opened in browser
if ($_SERVER['REMOTE_ADDR'])
header('Content-Type: text/xml');
if (PEAR::isError($schema)) {
$error = $schema->getMessage() . ' ' . $schema->getUserInfo();
}
else {
$dump_config = array(
// 'output_mode' => 'file',
'output' => 'print_schema',
);
$definition = $schema->getDefinitionFromDatabase();
$definition['charset'] = 'utf8';
if (PEAR::isError($definition)) {
$error = $definition->getMessage() . ' ' . $definition->getUserInfo();
}
else {
$operation = $schema->dumpDatabase($definition, $dump_config, MDB2_SCHEMA_DUMP_STRUCTURE);
if (PEAR::isError($operation)) {
$error = $operation->getMessage() . ' ' . $operation->getUserInfo();
}
}
}
$schema->disconnect();
if ($error && !$_SERVER['REMOTE_ADDR'])
fputs(STDERR, $error);
?>

@ -0,0 +1,233 @@
#!/usr/bin/env php
<?php
/*
+-----------------------------------------------------------------------+
| bin/exportgettext.sh |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2011, The Roundcube Dev Team |
| Licensed under the GNU General Public License |
| |
| PURPOSE: |
| Export PHP-based localization files to PO files for gettext |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
require INSTALL_PATH.'program/include/clisetup.php';
if ($argc < 2) {
die("Usage: " . basename($argv[0]) . " SRCDIR DESTDIR\n");
}
$srcdir = unslashify(realpath($argv[1]));
$destdir = unslashify($argv[2]);
$layout = 'launchpad'; # or 'narro';
$langcode_map = array(
'hy_AM' => 'hy',
'ar_SA' => 'ar',
'az_AZ' => 'az',
'bg_BG' => 'bg',
'bs_BA' => 'bs',
'ca_ES' => 'ca',
'cs_CZ' => 'cs',
'cy_GB' => 'cy',
'da_DK' => 'da',
'et_EE' => 'et',
'el_GR' => 'el',
'eu_ES' => 'eu',
'fa_IR' => 'fa',
'ga_IE' => 'ga',
'ka_GE' => 'ka',
'gl_ES' => 'gl',
'he_IL' => 'he',
'hi_IN' => 'hi',
'hr_HR' => 'hr',
'ja_JP' => 'ja',
'ko_KR' => 'ko',
'km_KH' => 'km',
'ms_MY' => 'ms',
'mr_IN' => 'mr',
'ml_IN' => 'ml',
'pl_PL' => 'pl',
'si_LK' => 'si',
'sl_SI' => 'sl',
'sq_AL' => 'sq',
'sr_CS' => 'sr',
'sv_SE' => 'sv',
'uk_UA' => 'uk',
'vi_VN' => 'vi',
);
// converting roundcube localization dir
if (is_dir($srcdir.'/en_US')) {
load_en_US($srcdir.'/en_US');
foreach (glob($srcdir.'/*') as $locdir) {
if (is_dir($locdir)) {
$lang = basename($locdir);
//echo "$locdir => $destdir$lang\n";
convert_dir($locdir, $destdir . ($layout != 'launchpad' ? $lang : ''));
}
}
}
// converting single localization directory
else if (is_dir($srcdir)) {
if (is_file($srcdir.'/en_US.inc')) // plugin localization
load_en_US($srcdir.'/en_US.inc');
else
load_en_US(realpath($srcdir.'/../en_US')); // single language
convert_dir($srcdir, $destdir);
}
// converting a single file
else if (is_file($srcdir)) {
//load_en_US();
convert_file($srcdir, $destdir);
}
/**
* Load en_US localization which is used to build msgids
*/
function load_en_US($fn)
{
$texts = array();
if (is_dir($fn)) {
foreach (glob($fn.'/*.inc') as $ifn) {
include($ifn);
$texts = array_merge($texts, (array)$labels, (array)$messages);
}
}
else if (is_file($fn)) {
include($fn);
$texts = array_merge($texts, (array)$labels, (array)$messages);
}
$GLOBALS['en_US'] = $texts;
}
/**
* Convert all .inc files in the given src directory
*/
function convert_dir($indir, $outdir)
{
global $layout;
if (!is_dir($outdir)) // attempt to create destination dir
mkdir($outdir, 0777, true);
foreach (glob($indir.'/*.inc') as $fn) {
$filename = basename($fn);
// create subdir for each template (launchpad rules)
if ($layout == 'launchpad' && preg_match('/^(labels|messages)/', $filename, $m)) {
$lang = end(explode('/', $indir));
$destdir = $outdir . '/' . $m[1];
if (!is_dir($destdir))
mkdir($destdir, 0777, true);
$outfn = $destdir . '/' . $lang . '.po';
}
else {
$outfn = $outdir . '/' . preg_replace('/\.[a-z0-9]+$/i', '', basename($fn)) . '.po';
}
convert_file($fn, $outfn);
}
}
/**
* Convert the given Roundcube localization file into a gettext .po file
*/
function convert_file($fn, $outfn)
{
global $layout, $langcode_map;
$basename = basename($fn);
$srcname = str_replace(INSTALL_PATH, '', $fn);
$product = preg_match('!plugins/(\w+)!', $srcname, $m) ? 'roundcube-plugin-' . $m[1] : 'roundcubemail';
$lang = preg_match('!/([a-z]{2}(_[A-Z]{2})?)[./]!', $outfn, $m) ? $m[1] : '';
$labels = $messages = $seen = array();
if (is_dir($outfn))
$outfn .= '/' . $basename . '.po';
// launchpad requires the template file to have the same name as the directory
if (strstr($outfn, '/en_US') && $layout == 'launchpad') {
$a = explode('/', $outfn);
array_pop($a);
$templ = end($a);
$a[] = $templ . '.pot';
$outfn = join('/', $a);
$is_pot = true;
}
// launchpad is very picky about file names
else if ($layout == 'launchpad' && preg_match($regex = '!/([a-z]{2})_([A-Z]{2})!', $outfn, $m)) {
if ($shortlang = $langcode_map[$lang])
$outfn = preg_replace($regex, '/'.$shortlang, $outfn);
else if ($m[1] == strtolower($m[2]))
$outfn = preg_replace($regex, '/\1', $outfn);
}
include($fn);
$texts = array_merge($labels, $messages);
// write header
$header = <<<EOF
# Converted from Roundcube PHP localization files
# Copyright (C) 2011 The Roundcube Dev Team
# This file is distributed under the same license as the Roundcube package.
#
#: %s
msgid ""
msgstr ""
"Project-Id-Version: %s\\n"
"Report-Msgid-Bugs-To: \\n"
"%s: %s\\n"
"Last-Translator: \\n"
"Language-Team: Translations <hello@roundcube.net>\\n"
"Language: %s\\n"
"Content-Type: text/plain; charset=UTF-8\\n"
"Content-Transfer-Encoding: 8bit\\n"
EOF;
$out = sprintf($header, $srcname, $product, $is_pot ? "POT-Creation-Date" : "PO-Revision-Date", date('c'), $shortlang ? $shortlang : $lang);
$out .= "\n";
$messages = array();
foreach ((array)$texts as $label => $msgstr) {
$msgid = $is_pot ? $msgstr : ($GLOBALS['en_US'][$label] ?: $label);
$messages[$msgid][] = $label;
}
foreach ($messages as $msgid => $labels) {
$out .= "\n";
foreach ($labels as $label)
$out .= "#: $srcname:$label\n";
$msgstr = $texts[$label];
$out .= 'msgid ' . gettext_quote($msgid) . "\n";
$out .= 'msgstr ' . gettext_quote(!$is_pot ? $msgstr : '') . "\n";
}
if ($outfn == '-')
echo $out;
else {
echo "$fn\t=>\t$outfn\n";
file_put_contents($outfn, $out);
}
}
function gettext_quote($str)
{
$out = "";
$lines = explode("\n", wordwrap(stripslashes($str)));
$last = count($lines) - 1;
foreach ($lines as $i => $line)
$out .= '"' . addcslashes($line, '"') . ($i < $last ? ' ' : '') . "\"\n";
return rtrim($out);
}
?>

@ -2,9 +2,10 @@
<?php <?php
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client | | bin/gc.sh |
| | | |
| Copyright (C) The Roundcube Dev Team | | This file is part of the Roundcube Webmail client |
| Copyright (C) 2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
@ -12,6 +13,7 @@
| | | |
| PURPOSE: | | PURPOSE: |
| Trigger garbage collecting routines manually (e.g. via cronjob) | | Trigger garbage collecting routines manually (e.g. via cronjob) |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> | | Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+

@ -0,0 +1,196 @@
#!/usr/bin/env php
<?php
/*
+-----------------------------------------------------------------------+
| bin/importgettext.sh |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2011, The Roundcube Dev Team |
| Licensed under the GNU General Public License |
| |
| PURPOSE: |
| Import localizations from gettext PO format |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
require INSTALL_PATH.'program/include/clisetup.php';
if ($argc < 2) {
die("Usage: " . basename($argv[0]) . " SRCDIR\n");
}
$srcdir = unslashify(realpath($argv[1]));
if (is_dir($srcdir)) {
$out = import_dir($srcdir);
}
else if (is_file($srcdir)) {
$out = import_file($srcdir);
}
// write output files
foreach ($out as $outfn => $texts) {
$lang = preg_match('!/([a-z]{2}(_[A-Z]{2})?)[./]!', $outfn, $m) ? $m[1] : '';
$varname = strpos($outfn, 'messages.inc') !== false ? 'messages' : 'labels';
$header = <<<EOF
<?php
/*
+-----------------------------------------------------------------------+
| localization/%s/%-51s|
| |
| Language file of the Roundcube Webmail client |
| Copyright (C) %s, The Roundcube Dev Team |
| Licensed under the GNU General Public License |
| |
+-----------------------------------------------------------------------+
| Author: %-62s|
+-----------------------------------------------------------------------+
*/
$%s = array();
EOF;
$author = preg_replace('/\s*<Unknown>/i', '', $texts['_translator']);
$output = sprintf($header, $lang, $varname.'.inc', date('Y'), $author, $varname);
foreach ($texts as $label => $value) {
if (is_array($value)) { var_dump($outfn, $label, $value); exit; }
if ($label[0] != '_' && strlen($value))
$output .= sprintf("\$%s['%s'] = '%s';\n", $varname, $label, strtr(addcslashes($value, "'"), array("\r" => '', "\n" => '\n')));
}
$output .= "\n";
$dir = dirname($outfn);
@mkdir($dir, 0755, true);
if (file_put_contents($outfn, $output))
echo "-> $outfn\n";
}
/**
* Convert all .po files in the given src directory
*/
function import_dir($indir)
{
$out = array();
foreach (glob($indir.'/*.po') as $fn) {
$out = array_merge_recursive($out, import_file($fn));
}
return $out;
}
/**
* Convert the given .po file into a Roundcube localization array
*/
function import_file($fn)
{
$out = array();
$lines = file($fn);
$language = '';
$translator = '';
// get language code from file name
if (preg_match('/-([a-z_]+).po$/i', $fn, $m))
$language = expand_langcode($m[1]);
$is_header = true;
$msgid = null;
$msgstr = '';
$dests = array();
foreach ($lines as $i => $line) {
$line = trim($line);
// parse header
if ($is_header && $line[0] == '"') {
list($key, $val) = explode(": ", preg_replace('/\\\n$/', '', trim($line, '"')), 2);
switch (strtolower($key)) {
case 'language':
$language = expand_langcode($val);
break;
case 'last-translator':
$translator = $val;
break;
}
}
// empty line
if ($line == '') {
if ($msgid && $dests) {
foreach ($dests as $dest) {
list($file, $label) = explode(':', $dest);
$out[$file][$label] = $msgstr;
$out[$file]['_translator'] = $translator;
}
}
$msgid = null;
$msgstr = '';
$dests = array();
}
// meta line
if ($line[0] == '#') {
$value = trim(substr($line, 2));
if ($line[1] == ':')
$dests[] = str_replace('en_US', $language, $value);
}
else if (strpos($line, 'msgid') === 0) {
$msgid = gettext_decode(substr($line, 6));
if (!empty($msgid))
$is_header = false;
}
else if (strpos($line, 'msgstr') === 0) {
$msgstr = gettext_decode(substr($line, 7));
}
else if ($msgid && $line[0] == '"') {
$msgstr .= gettext_decode($line);
}
else if ($msgid !== null && $line[0] == '"') {
$msgid .= gettext_decode($line);
}
}
if ($msgid && $dests) {
foreach ($dests as $dest) {
list($file, $label) = explode(':', $dest);
$out[$file][$label] = $msgstr;
$out[$file]['_translator'] = $translator;
}
}
return $language ? $out : array();
}
function gettext_decode($str)
{
return stripslashes(trim($str, '"'));
}
/**
* Translate two-chars language codes to our internally used language identifiers
*/
function expand_langcode($lang)
{
static $rcube_language_aliases, $rcube_languages;
if (!$rcube_language_aliases)
include(INSTALL_PATH . 'program/localization/index.inc');
if ($rcube_language_aliases[$lang])
return $rcube_language_aliases[$lang];
else if (strlen($lang) == 2 && !isset($rcube_languages[$lang]))
return strtolower($lang) . '_' . strtoupper($lang);
else
return $lang;
}
?>

@ -2,9 +2,10 @@
<?php <?php
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client | | bin/indexcontacts.sh |
| | | |
| Copyright (C) The Roundcube Dev Team | | This file is part of the Roundcube Webmail client |
| Copyright (C) 2011, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
@ -24,3 +25,5 @@ require_once INSTALL_PATH.'program/include/clisetup.php';
ini_set('memory_limit', -1); ini_set('memory_limit', -1);
rcmail_utils::indexcontacts(); rcmail_utils::indexcontacts();
?>

@ -2,10 +2,11 @@
<?php <?php
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client | | bin/initdb.sh |
| | | |
| Copyright (C) The Roundcube Dev Team | | This file is part of the Roundcube Webmail client |
| Copyright (C) Kolab Systems AG | | Copyright (C) 2010-2015, The Roundcube Dev Team |
| Copyright (C) 2010-2015, Kolab Systems AG |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
@ -37,3 +38,5 @@ if (!file_exists($opts['dir'])) {
} }
rcmail_utils::db_init($opts['dir']); rcmail_utils::db_init($opts['dir']);
?>

@ -2,9 +2,10 @@
<?php <?php
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client | | bin/install-jsdeps.sh |
| | | |
| Copyright (C) The Roundcube Dev Team | | This file is part of the Roundcube Webmail client |
| Copyright (C) 2016, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
@ -12,7 +13,7 @@
| | | |
| PURPOSE: | | PURPOSE: |
| Utility script to fetch and install all 3rd party javascript | | Utility script to fetch and install all 3rd party javascript |
| libraries used in Roundcube from source. | | libraries unsed in Roundcube from source. |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Author: Thomas Bruederli <thomas@roundcube.net> | | Author: Thomas Bruederli <thomas@roundcube.net> |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
@ -23,28 +24,28 @@ define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
require_once INSTALL_PATH . 'program/include/clisetup.php'; require_once INSTALL_PATH . 'program/include/clisetup.php';
if (!function_exists('exec')) { if (!function_exists('exec')) {
rcube::raise_error("PHP exec() function is required. Check disable_functions in php.ini.", false, true); die("PHP exec() function is required. Check disable_functions in php.ini\n");
} }
$cfgfile = INSTALL_PATH . 'jsdeps.json'; $SOURCES = json_decode(file_get_contents(INSTALL_PATH . 'jsdeps.json'), true);
$SOURCES = json_decode(file_get_contents($cfgfile), true);
if (empty($SOURCES['dependencies'])) { if (empty($SOURCES['dependencies'])) {
rcube::raise_error("Failed to read dependencies list from $cfgfile", false, true); die("ERROR: Failed to read sources from " . INSTALL_PATH . "jsdeps.json\n");
} }
$CURL = trim(`which curl`); $CURL = trim(`which curl`);
$WGET = trim(`which wget`); $WGET = trim(`which wget`);
$UNZIP = trim(`which unzip`); $UNZIP = trim(`which unzip`);
$FILEINFO = trim(`which file`);
if (($CACHEDIR = getenv("CACHEDIR")) && is_writeable($CACHEDIR)) { if (($CACHEDIR = getenv("CACHEDIR")) && is_writeable($CACHEDIR)) {
// use $CACHEDIR // use $CACHEDIR
} }
else if (is_writeable(INSTALL_PATH . 'temp/js_cache') || @mkdir(INSTALL_PATH . 'temp/js_cache', 0774, true)) { else if (is_writeable(INSTALL_PATH . 'temp/js_cache') || @mkdir(INSTALL_PATH . 'temp/js_cache', 0774, true)) {
$CACHEDIR = INSTALL_PATH . 'temp/js_cache'; $CACHEDIR = INSTALL_PATH . 'temp/js_cache';
} }
else { else {
$CACHEDIR = sys_get_temp_dir(); $CACHEDIR = sys_get_temp_dir();
} }
@ -109,43 +110,43 @@ EOL;
*/ */
function fetch_from_source($package, $useCache = true, &$filetype = null) function fetch_from_source($package, $useCache = true, &$filetype = null)
{ {
global $CURL, $WGET; global $CURL, $WGET;
$cache_file = extract_filetype($package, $filetype); $cache_file = extract_filetype($package, $filetype);
if (!is_readable($cache_file) || !$useCache) { if (!is_readable($cache_file) || !$useCache) {
if (empty($CURL) && empty($WGET)) { if (empty($CURL) && empty($WGET)) {
rcube::raise_error("Required 'wget' or 'curl' program not found.", false, true); die("ERROR: Required program 'wget' or 'curl' not found\n");
} }
$url = str_replace('$v', $package['version'], $package['url']); $url = str_replace('$v', $package['version'], $package['url']);
echo "Fetching $url\n"; echo "Fetching $url\n";
if ($CURL) if ($CURL)
exec(sprintf('%s -L -s %s -o %s', $CURL, escapeshellarg($url), $cache_file), $out, $retval); exec(sprintf('%s -L -s %s -o %s', $CURL, escapeshellarg($url), $cache_file), $out, $retval);
else else
exec(sprintf('%s -q %s -O %s', $WGET, escapeshellarg($url), $cache_file), $out, $retval); exec(sprintf('%s -q %s -O %s', $WGET, escapeshellarg($url), $cache_file), $out, $retval);
// Try Github API as a fallback (#6248) // Try Github API as a fallback (#6248)
if ($retval !== 0 && $package['api_url']) { if ($retval !== 0 && $package['api_url']) {
$url = str_replace('$v', $package['version'], $package['api_url']); $url = str_replace('$v', $package['version'], $package['api_url']);
$header = 'Accept:application/vnd.github.v3.raw'; $header = 'Accept:application/vnd.github.v3.raw';
rcube::raise_error("Fetching failed. Using Github API on $url"); echo "Fetching failed. Using Github API on $url\n";
if ($CURL) if ($CURL)
exec(sprintf('%s -L -H %s -s %s -o %s', $CURL, escapeshellarg($header), escapeshellarg($url), $cache_file), $out, $retval); exec(sprintf('%s -L -H %s -s %s -o %s', $CURL, escapeshellarg($header), escapeshellarg($url), $cache_file), $out, $retval);
else else
exec(sprintf('%s --header %s -q %s -O %s', $WGET, escapeshellarg($header), escapeshellarg($url), $cache_file), $out, $retval); exec(sprintf('%s --header %s -q %s -O %s', $WGET, escapeshellarg($header), escapeshellarg($url), $cache_file), $out, $retval);
} }
if ($retval !== 0) { if ($retval !== 0) {
rcube::raise_error("Failed to download source file from $url", false, true); die("ERROR: Failed to download source file from " . $url . "\n");
}
} }
}
return $cache_file; return $cache_file;
} }
/** /**
@ -153,20 +154,22 @@ function fetch_from_source($package, $useCache = true, &$filetype = null)
*/ */
function extract_filetype($package, &$filetype = null) function extract_filetype($package, &$filetype = null)
{ {
global $CACHEDIR; global $FILEINFO, $CACHEDIR;
$filetype = pathinfo($package['url'], PATHINFO_EXTENSION) ?: 'tmp'; $filetype = pathinfo($package['url'], PATHINFO_EXTENSION) ?: 'tmp';
$cache_file = $CACHEDIR . '/' . $package['lib'] . '-' . $package['version'] . '.' . $filetype; $cache_file = $CACHEDIR . '/' . $package['lib'] . '-' . $package['version'] . '.' . $filetype;
// Make sure it is a zip file if (empty($FILEINFO)) {
if (file_exists($cache_file)) { die("ERROR: Required program 'file' not found\n");
$magic = file_get_contents($cache_file, false, null, 0, 4); }
if ($magic === "PK\003\004") {
$filetype = 'zip'; // detect downloaded/cached file type
} exec(sprintf('%s -b %s', $FILEINFO, $cache_file), $out);
} if (stripos($out[0], 'zip') === 0) {
$filetype = 'zip';
}
return $cache_file; return $cache_file;
} }
/** /**
@ -174,38 +177,38 @@ function extract_filetype($package, &$filetype = null)
*/ */
function compose_destfile($package, $srcfile) function compose_destfile($package, $srcfile)
{ {
global $LICENSES; global $LICENSES;
$header = sprintf("/**\n * %s - v%s\n *\n", $package['name'], $package['version']); $header = sprintf("/**\n * %s - v%s\n *\n", $package['name'], $package['version']);
if (!empty($package['source'])) { if (!empty($package['source'])) {
$header .= " * @source " . str_replace('$v', $package['version'], $package['source']) . "\n"; $header .= " * @source " . str_replace('$v', $package['version'], $package['source']) . "\n";
$header .= " *\n"; $header .= " *\n";
}
if (!empty($package['license']) && isset($LICENSES[$package['license']])) {
$header .= " * @licstart The following is the entire license notice for the\n";
$header .= " * JavaScript code in this file.\n";
$header .= " *\n";
if (!empty($package['copyright'])) {
$header .= " * " . $package['copyright'] . "\n";
$header .= " *\n";
} }
if (!empty($package['license']) && isset($LICENSES[$package['license']])) { $header .= $LICENSES[$package['license']];
$header .= " * @licstart The following is the entire license notice for the\n"; $header .= " *\n";
$header .= " * JavaScript code in this file.\n"; $header .= " * @licend The above is the entire license notice\n";
$header .= " *\n"; $header .= " * for the JavaScript code in this file.\n";
if (!empty($package['copyright'])) { }
$header .= " * " . $package['copyright'] . "\n";
$header .= " *\n";
}
$header .= $LICENSES[$package['license']]; $header .= " */\n";
$header .= " *\n";
$header .= " * @licend The above is the entire license notice\n";
$header .= " * for the JavaScript code in this file.\n";
}
$header .= " */\n";
if (file_put_contents(INSTALL_PATH . $package['dest'], $header . file_get_contents($srcfile))) { if (file_put_contents(INSTALL_PATH . $package['dest'], $header . file_get_contents($srcfile))) {
echo "Wrote file " . INSTALL_PATH . $package['dest'] . "\n"; echo "Wrote file " . INSTALL_PATH . $package['dest'] . "\n";
} }
else { else {
rcube::raise_error("Failed to write destination file " . INSTALL_PATH . $package['dest'], false, true); die("ERROR: Failed to write destination file " . INSTALL_PATH . $package['dest'] . "\n");
} }
} }
/** /**
@ -213,107 +216,94 @@ function compose_destfile($package, $srcfile)
*/ */
function extract_zipfile($package, $srcfile) function extract_zipfile($package, $srcfile)
{ {
global $UNZIP, $CACHEDIR; global $UNZIP, $CACHEDIR;
if (empty($UNZIP)) { if (empty($UNZIP)) {
rcube::raise_error("Required 'unzip' program not found.", false, true); die("ERROR: Required program 'unzip' not found\n");
}
$destdir = INSTALL_PATH . $package['dest'];
if (!is_dir($destdir)) {
mkdir($destdir, 0775, true);
}
if (!is_writeable($destdir)) {
die("ERROR: Cannot write to destination directory $destdir\n");
}
// pick files from zip archive
if (!empty($package['pick'])) {
foreach ($package['pick'] as $pattern) {
echo "Extracting files $pattern into $destdir\n";
exec(sprintf('%s -o %s %s -d %s', $UNZIP, escapeshellarg($srcfile), escapeshellarg($pattern), $destdir), $out, $retval);
if ($retval !== 0) {
echo "ERROR: Failed to unpack $pattern; " . join('; ' . $out) . "\n";
}
} }
}
$destdir = INSTALL_PATH . $package['dest']; // unzip the archive and map source to dest files/directories
if (!is_dir($destdir)) { else if (!empty($package['map'])) {
mkdir($destdir, 0775, true); $extract = $CACHEDIR . '/' . $package['lib'] . '-extract';
if (!is_dir($extract)) {
mkdir($extract, 0774, true);
} }
if (!is_writeable($destdir)) { $zip_command = '%s -' . ($package['flat'] ? 'j' : 'o') . ' %s -d %s';
rcube::raise_error("Cannot write to destination directory: $destdir", false, true); exec(sprintf($zip_command, $UNZIP, escapeshellarg($srcfile), $extract), $out, $retval);
}
// pick files from zip archive // get the root folder of the extracted package
if (!empty($package['pick'])) { $extract_tree = glob("$extract/*", GLOB_ONLYDIR);
foreach ($package['pick'] as $pattern) { $sourcedir = count($extract_tree) ? $extract_tree[0] : $extract;
echo "Extracting files $pattern into $destdir\n";
exec(sprintf('%s -o %s %s -d %s', $UNZIP, escapeshellarg($srcfile), escapeshellarg($pattern), $destdir), $out, $retval);
if ($retval !== 0) {
rcube::raise_error("Failed to unpack $pattern; " . implode('; ' . $out));
}
}
}
// unzip the archive and map source to dest files/directories
else if (!empty($package['map'])) {
$extract = $CACHEDIR . '/' . $package['lib'] . '-extract';
if (!is_dir($extract)) {
mkdir($extract, 0774, true);
}
$zip_command = '%s -' . ($package['flat'] ? 'j' : 'o') . ' %s -d %s'; foreach ($package['map'] as $src => $dest) {
exec(sprintf($zip_command, $UNZIP, escapeshellarg($srcfile), $extract), $out, $retval); echo "Installing $sourcedir/$src into $destdir/$dest\n";
// get the root folder of the extracted package
$extract_tree = glob("$extract/*", GLOB_ONLYDIR);
$sourcedir = count($extract_tree) ? $extract_tree[0] : $extract;
foreach ($package['map'] as $src => $dest) {
echo "Installing $sourcedir/$src into $destdir/$dest\n";
$dest_file = $destdir . '/' . $dest;
$src_file = $sourcedir . '/' . $src;
// make sure the destination's parent directory exists
if (strpos($dest, '/') !== false) {
$parentdir = dirname($dest_file);
if (!is_dir($parentdir)) {
mkdir($parentdir, 0775, true);
}
}
// avoid copying source directory as a child into destination
if (is_dir($src_file) && is_dir($dest_file)) {
exec(sprintf('rm -rf %s', $dest_file));
}
exec(sprintf('mv -f %s %s', $src_file, $dest_file), $out, $retval);
if ($retval !== 0) {
rcube::raise_error("Failed to move $src into $dest_file; " . implode('; ' . $out));
}
// Remove sourceMappingURL
else if (isset($package['sourcemap']) && $package['sourcemap'] === false) {
if ($content = file($dest_file)) {
$index = count($content);
if (preg_match('|sourceMappingURL=|', $content[$index-1])) {
array_pop($content);
file_put_contents($dest_file, implode('', $content));
}
}
}
}
// remove temp extraction dir // make sure the destination's parent directory exists
exec('rm -rf ' . $extract); if (strpos($dest, '/') !== false) {
} $parentdir = dirname($destdir . '/' . $dest);
// extract the archive into the destination directory if (!is_dir($parentdir)) {
else { mkdir($parentdir, 0775, true);
echo "Extracting zip archive into $destdir\n";
exec(sprintf('%s -o %s -d %s', $UNZIP, escapeshellarg($srcfile), $destdir), $out, $retval);
if ($retval !== 0) {
rcube::raise_error("Failed to unzip $srcfile; " . implode('; ' . $out));
} }
}
// avoid copying source directory as a child into destination
if (is_dir($sourcedir . '/' . $src) && is_dir($destdir . '/' . $dest)) {
exec(sprintf('rm -rf %s/%s', $destdir, $dest));
}
exec(sprintf('mv -f %s/%s %s/%s', $sourcedir, $src, $destdir, $dest), $out, $retval);
if ($retval !== 0) {
echo "ERROR: Failed to move $src into $destdir/$dest; " . join('; ' . $out) . "\n";
}
} }
// remove some files from the destination // remove temp extraction dir
if (!empty($package['omit'])) { exec('rm -rf ' . $extract);
foreach ((array)$package['omit'] as $glob) { }
exec(sprintf('rm -rf %s/%s', $destdir, escapeshellarg($glob))); // extract the archive into the destination directory
} else {
echo "Extracting zip archive into $destdir\n";
exec(sprintf('%s -o %s -d %s', $UNZIP, escapeshellarg($srcfile), $destdir), $out, $retval);
if ($retval !== 0) {
echo "ERROR: Failed to unzip $srcfile; " . join('; ' . $out) . "\n";
} }
}
// prepend license header to extracted files // remove some files from the destination
if (!empty($package['addlicense'])) { if (!empty($package['omit'])) {
foreach ((array)$package['addlicense'] as $filename) { foreach ((array)$package['omit'] as $glob) {
$pkg = $package; exec(sprintf('rm -rf %s/%s', $destdir, escapeshellarg($glob)));
$pkg['dest'] = $package['dest'] . '/' . $filename;
compose_destfile($pkg, $destdir . '/' . $filename);
}
} }
}
// prepend license header to extracted files
if (!empty($package['addlicense'])) {
foreach ((array)$package['addlicense'] as $filename) {
$pkg = $package;
$pkg['dest'] = $package['dest'] . '/' . $filename;
compose_destfile($pkg, $destdir . '/' . $filename);
}
}
} }
/** /**
@ -321,16 +311,16 @@ function extract_zipfile($package, $srcfile)
*/ */
function delete_destfile($package) function delete_destfile($package)
{ {
$destdir = INSTALL_PATH . ($package['rm'] ?: $package['dest']); $destdir = INSTALL_PATH . ($package['rm'] ?: $package['dest']);
if (file_exists($destdir)) { if (file_exists($destdir)) {
if (PHP_OS === 'Windows') { if (PHP_OS === 'Windows') {
exec(sprintf("rd /s /q %s", escapeshellarg($destdir))); exec(sprintf("rd /s /q %s", escapeshellarg($destdir)));
}
else {
exec(sprintf("rm -rf %s", escapeshellarg($destdir)));
}
} }
else {
exec(sprintf("rm -rf %s", escapeshellarg($destdir)));
}
}
} }
@ -342,44 +332,44 @@ $WHAT = $args[0];
$useCache = !$args['force'] && !$args['get']; $useCache = !$args['force'] && !$args['get'];
if (!$args['get'] && !$args['extract'] && !$args['delete']) { if (!$args['get'] && !$args['extract'] && !$args['delete']) {
$args['get'] = $args['extract'] = 1; $args['get'] = $args['extract'] = 1;
} }
foreach ($SOURCES['dependencies'] as $package) { foreach ($SOURCES['dependencies'] as $package) {
if (!isset($package['name'])) { if (!isset($package['name'])) {
$package['name'] = $package['lib']; $package['name'] = $package['lib'];
} }
if ($WHAT && $package['lib'] !== $WHAT) { if ($WHAT && $package['lib'] !== $WHAT) {
continue; continue;
} }
if ($args['delete']) { if ($args['delete']) {
delete_destfile($package); delete_destfile($package);
continue; continue;
} }
if ($args['get']) { if ($args['get']) {
$srcfile = fetch_from_source($package, $useCache, $filetype); $srcfile = fetch_from_source($package, $useCache, $filetype);
}
else {
$srcfile = extract_filetype($package, $filetype);
}
if (!empty($package['sha1']) && ($sum = sha1_file($srcfile)) !== $package['sha1']) {
die("ERROR: Incorrect sha1 sum of $srcfile. Expected: {$package['sha1']}, got: $sum\n");
}
if ($args['extract']) {
echo "Installing {$package['name']}...\n";
if ($filetype === 'zip') {
extract_zipfile($package, $srcfile);
} }
else { else {
$srcfile = extract_filetype($package, $filetype); compose_destfile($package, $srcfile);
}
if (!empty($package['sha1']) && ($sum = sha1_file($srcfile)) !== $package['sha1']) {
rcube::raise_error("Incorrect sha1 sum of $srcfile. Expected: {$package['sha1']}, got: $sum", false, true);
} }
if ($args['extract']) { echo "Done.\n";
echo "Installing {$package['name']}...\n"; }
if ($filetype === 'zip') {
extract_zipfile($package, $srcfile);
}
else {
compose_destfile($package, $srcfile);
}
echo "Done.\n";
}
} }

@ -2,9 +2,10 @@
<?php <?php
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client | | bin/installto.sh |
| | | |
| Copyright (C) The Roundcube Dev Team | | This file is part of the Roundcube Webmail client |
| Copyright (C) 2014-2016, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
@ -23,126 +24,112 @@ define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
require_once INSTALL_PATH . 'program/include/clisetup.php'; require_once INSTALL_PATH . 'program/include/clisetup.php';
if (!function_exists('system')) { if (!function_exists('system')) {
rcube::raise_error("PHP system() function is required. Check disable_functions in php.ini.", false, true); rcube::raise_error("PHP system() function is required. Check disable_functions in php.ini.", false, true);
} }
$target_dir = unslashify(end($_SERVER['argv'])); $target_dir = unslashify($_SERVER['argv'][1]);
$accept = in_array('-y', $_SERVER['argv']) ? 'y' : null;
if (empty($target_dir) || !is_dir(realpath($target_dir))) if (empty($target_dir) || !is_dir(realpath($target_dir)))
rcube::raise_error("Invalid target: not a directory\nUsage: installto.sh [-y] <TARGET>", false, true); rcube::raise_error("Invalid target: not a directory\nUsage: installto.sh <TARGET>", false, true);
// read version from iniset.php // read version from iniset.php
$iniset = @file_get_contents($target_dir . '/program/include/iniset.php'); $iniset = @file_get_contents($target_dir . '/program/include/iniset.php');
if (!preg_match('/define\(.RCMAIL_VERSION.,\s*.([0-9.]+[a-z0-9-]*)/', $iniset, $m)) if (!preg_match('/define\(.RCMAIL_VERSION.,\s*.([0-9.]+[a-z-]*)/', $iniset, $m))
rcube::raise_error("No valid Roundcube installation found at $target_dir", false, true); rcube::raise_error("No valid Roundcube installation found at $target_dir", false, true);
$oldversion = $m[1]; $oldversion = $m[1];
if (version_compare(version_parse($oldversion), version_parse(RCMAIL_VERSION), '>')) if (version_compare(version_parse($oldversion), version_parse(RCMAIL_VERSION), '>='))
rcube::raise_error("Target installation already in version $oldversion.", false, true); rcube::raise_error("Installation at target location is up-to-date!", false, true);
if (version_compare(version_parse($oldversion), version_parse(RCMAIL_VERSION), '==')) {
echo "Target installation already in version $oldversion. Do you want to update again? (y/N)\n";
}
else {
echo "Upgrading from $oldversion. Do you want to continue? (y/N)\n";
}
$input = $accept ?: trim(fgets(STDIN)); echo "Upgrading from $oldversion. Do you want to continue? (y/N)\n";
$input = trim(fgets(STDIN));
if (strtolower($input) == 'y') { if (strtolower($input) == 'y') {
echo "Copying files to target location..."; echo "Copying files to target location...";
$adds = array(); $adds = array();
$dirs = array('bin','SQL','plugins','skins','program'); $dirs = array('program','bin','SQL','plugins','skins');
if (is_dir(INSTALL_PATH . 'vendor') && !is_file("$target_dir/composer.json")) { if (is_dir(INSTALL_PATH . 'vendor') && !is_file("$target_dir/composer.json")) {
$dirs[] = 'vendor'; $dirs[] = 'vendor';
}
if (file_exists("$target_dir/installer")) {
$dirs[] = 'installer';
}
foreach ($dirs as $dir) {
// @FIXME: should we use --delete for all directories?
$delete = in_array($dir, array('program', 'vendor', 'installer')) ? '--delete ' : '';
$command = "rsync -aC --out-format=%n " . $delete . INSTALL_PATH . "$dir/ $target_dir/$dir/";
if (system($command, $ret) === false || $ret > 0) {
rcube::raise_error("Failed to execute command: $command", false, true);
} }
if (file_exists("$target_dir/installer")) { }
$dirs[] = 'installer';
}
foreach ($dirs as $dir) {
// @FIXME: should we use --delete for all directories?
$delete = in_array($dir, array('program', 'vendor', 'installer')) ? '--delete ' : '';
$command = "rsync -aC --out-format=%n " . $delete . INSTALL_PATH . "$dir/ $target_dir/$dir/";
if (system($command, $ret) === false || $ret > 0) { foreach (array('index.php','config/defaults.inc.php','composer.json-dist','jsdeps.json','CHANGELOG','README.md','UPGRADING','LICENSE','INSTALL') as $file) {
rcube::raise_error("Failed to execute command: $command", false, true); $command = "rsync -a --out-format=%n " . INSTALL_PATH . "$file $target_dir/$file";
} if (file_exists(INSTALL_PATH . $file) && (system($command, $ret) === false || $ret > 0)) {
rcube::raise_error("Failed to execute command: $command", false, true);
} }
}
foreach (array('index.php','config/defaults.inc.php','composer.json-dist','jsdeps.json','CHANGELOG','README.md','UPGRADING','LICENSE','INSTALL') as $file) {
$command = "rsync -a --out-format=%n " . INSTALL_PATH . "$file $target_dir/$file"; // Copy .htaccess or .user.ini if needed
foreach (array('.htaccess','.user.ini') as $file) {
if (file_exists(INSTALL_PATH . $file) && (system($command, $ret) === false || $ret > 0)) { if (file_exists(INSTALL_PATH . $file)) {
rcube::raise_error("Failed to execute command: $command", false, true); if (!file_exists("$target_dir/$file") || file_get_contents(INSTALL_PATH . $file) != file_get_contents("$target_dir/$file")) {
if (copy(INSTALL_PATH . $file, "$target_dir/$file.new")) {
echo "$file.new\n";
$adds[] = "NOTICE: New $file file saved as $file.new.";
} }
}
} }
}
// Copy .htaccess or .user.ini if needed
foreach (array('.htaccess','.user.ini') as $file) { // remove old (<1.0) .htaccess file
if (file_exists(INSTALL_PATH . $file)) { @unlink("$target_dir/program/.htaccess");
if (!file_exists("$target_dir/$file") || file_get_contents(INSTALL_PATH . $file) != file_get_contents("$target_dir/$file")) { echo "done.\n\n";
if (copy(INSTALL_PATH . $file, "$target_dir/$file.new")) {
echo "$file.new\n"; if (is_dir("$target_dir/skins/default")) {
$adds[] = "NOTICE: New $file file saved as $file.new."; echo "Removing old default skin...";
} system("rm -rf $target_dir/skins/default $target_dir/plugins/jqueryui/themes/default");
} foreach (glob(INSTALL_PATH . "plugins/*/skins") as $plugin_skin_dir) {
} $plugin_skin_dir = preg_replace('!^.*' . INSTALL_PATH . '!', '', $plugin_skin_dir);
} if (is_dir("$target_dir/$plugin_skin_dir/classic"))
system("rm -rf $target_dir/$plugin_skin_dir/default");
// remove old (<1.0) .htaccess file }
@unlink("$target_dir/program/.htaccess"); echo "done.\n\n";
echo "done.\n\n"; }
if (is_dir("$target_dir/skins/default")) { // check if js-deps are up-to-date
echo "Removing old default skin..."; if (file_exists("$target_dir/jsdeps.json") && file_exists("$target_dir/bin/install-jsdeps.sh")) {
system("rm -rf $target_dir/skins/default $target_dir/plugins/jqueryui/themes/default"); $jsdeps = json_decode(file_get_contents("$target_dir/jsdeps.json"));
foreach (glob(INSTALL_PATH . "plugins/*/skins") as $plugin_skin_dir) { $package = $jsdeps->dependencies[0];
$plugin_skin_dir = preg_replace('!^.*' . INSTALL_PATH . '!', '', $plugin_skin_dir); $dest_file = $target_dir . '/' . $package->dest;
if (is_dir("$target_dir/$plugin_skin_dir/classic")) { if (!file_exists($dest_file) || sha1_file($dest_file) !== $package->sha1) {
system("rm -rf $target_dir/$plugin_skin_dir/default"); echo "Installing JavaScript dependencies...";
} system("cd $target_dir && bin/install-jsdeps.sh");
}
echo "done.\n\n"; echo "done.\n\n";
} }
}
// Warn about situation when using "complete" package to update "custom" installation (#7087) else {
// Note: "Complete" package do not include jsdeps.json nor install-jsdeps.sh $adds[] = "NOTICE: JavaScript dependencies installation skipped...";
if (file_exists("$target_dir/jsdeps.json") && !file_exists(INSTALL_PATH . "jsdeps.json")) { }
$adds[] = "WARNING: JavaScript dependencies update skipped.";
} if (file_exists("$target_dir/installer")) {
// check if js-deps are up-to-date $adds[] = "NOTICE: The 'installer' directory still exists. You should remove it after the upgrade.";
else if (file_exists("$target_dir/jsdeps.json") && file_exists("$target_dir/bin/install-jsdeps.sh")) { }
$jsdeps = json_decode(file_get_contents("$target_dir/jsdeps.json"));
$package = $jsdeps->dependencies[0]; if (!empty($adds)) {
$dest_file = $target_dir . '/' . $package->dest; echo implode($adds, "\n") . "\n\n";
}
if (!file_exists($dest_file) || sha1_file($dest_file) !== $package->sha1) {
echo "Installing JavaScript dependencies..."; echo "Running update script at target...\n";
system("cd $target_dir && bin/install-jsdeps.sh"); system("cd $target_dir && php bin/update.sh --version=$oldversion");
echo "done.\n\n"; echo "All done.\n";
}
}
else {
$adds[] = "NOTICE: JavaScript dependencies installation skipped.";
}
if (file_exists("$target_dir/installer")) {
$adds[] = "NOTICE: The 'installer' directory still exists. You should remove it after the upgrade.";
}
if (!empty($adds)) {
echo implode("\n", $adds) . "\n\n";
}
echo "Running update script at target...\n";
system("cd $target_dir && php bin/update.sh --version=$oldversion" . ($accept ? ' -y' : ''));
echo "All done.\n";
} }
else { else {
echo "Update cancelled. See ya!\n"; echo "Update cancelled. See ya!\n";
} }
?>

@ -6,54 +6,54 @@ LANG_IN='ECMASCRIPT5'
CLOSURE_COMPILER_URL='http://dl.google.com/closure-compiler/compiler-latest.zip' CLOSURE_COMPILER_URL='http://dl.google.com/closure-compiler/compiler-latest.zip'
do_shrink() { do_shrink() {
rm -f "$2" rm -f "$2"
# copy the first comment block with license information for LibreJS # copy the first comment block with license information for LibreJS
grep -q '@lic' $1 && sed -n '/\/\*/,/\*\// { p; /\*\//q; }' $1 > $2 grep -q '@lic' $1 && sed -n '/\/\*/,/\*\// { p; /\*\//q; }' $1 > $2
java -jar $JAR_DIR/compiler.jar --compilation_level=SIMPLE_OPTIMIZATIONS --js="$1" --language_in="$3" >> $2 java -jar $JAR_DIR/compiler.jar --compilation_level=SIMPLE_OPTIMIZATIONS --js="$1" --language_in="$3" >> $2
} }
if [ ! -d "$JS_DIR" ]; then if [ ! -d "$JS_DIR" ]; then
echo "Directory $JS_DIR not found." echo "Directory $JS_DIR not found."
exit 1 exit 1
fi fi
if [ ! -w "$JAR_DIR" ]; then if [ ! -w "$JAR_DIR" ]; then
JAR_DIR=$PWD JAR_DIR=$PWD
fi fi
if java -version >/dev/null 2>&1; then if java -version >/dev/null 2>&1; then
: :
else else
echo "Java not found. Please ensure that the 'java' program is in your PATH." echo "Java not found. Please ensure that the 'java' program is in your PATH."
exit 1 exit 1
fi fi
if [ ! -r "$JAR_DIR/compiler.jar" ]; then if [ ! -r "$JAR_DIR/compiler.jar" ]; then
if which wget >/dev/null 2>&1 && which unzip >/dev/null 2>&1; then if which wget >/dev/null 2>&1 && which unzip >/dev/null 2>&1; then
wget "$CLOSURE_COMPILER_URL" -O "/tmp/$$.zip" wget "$CLOSURE_COMPILER_URL" -O "/tmp/$$.zip"
elif which curl >/dev/null 2>&1 && which unzip >/dev/null 2>&1; then elif which curl >/dev/null 2>&1 && which unzip >/dev/null 2>&1; then
curl "$CLOSURE_COMPILER_URL" -o "/tmp/$$.zip" curl "$CLOSURE_COMPILER_URL" -o "/tmp/$$.zip"
else else
echo "Please download $CLOSURE_COMPILER_URL and extract compiler.jar to $JAR_DIR/." echo "Please download $CLOSURE_COMPILER_URL and extract compiler.jar to $JAR_DIR/."
exit 1 exit 1
fi fi
unzip -p "/tmp/$$.zip" "*.jar" > "$JAR_DIR/compiler.jar" unzip -p "/tmp/$$.zip" "*.jar" > "$JAR_DIR/compiler.jar"
rm -f "/tmp/$$.zip" rm -f "/tmp/$$.zip"
fi fi
# compress single file from argument # compress single file from argument
if [ $# -gt 0 ]; then if [ $# -gt 0 ]; then
JS_DIR=`dirname "$1"` JS_DIR=`dirname "$1"`
JS_FILE="$1" JS_FILE="$1"
if [ $# -gt 1 ]; then if [ $# -gt 1 ]; then
LANG_IN="$2" LANG_IN="$2"
fi fi
echo "Shrinking $JS_FILE" echo "Shrinking $JS_FILE"
minfile=`echo $JS_FILE | sed -e 's/\.js$/\.min\.js/'` minfile=`echo $JS_FILE | sed -e 's/\.js$/\.min\.js/'`
do_shrink "$JS_FILE" "$minfile" "$LANG_IN" do_shrink "$JS_FILE" "$minfile" "$LANG_IN"
exit exit
fi fi
DIRS="$PWD/../program/js $PWD/../skins/* $PWD/../plugins/* $PWD/../plugins/*/skins/* $PWD/../plugins/managesieve/codemirror/lib" DIRS="$PWD/../program/js $PWD/../skins/* $PWD/../plugins/* $PWD/../plugins/*/skins/* $PWD/../plugins/managesieve/codemirror/lib"

@ -19,5 +19,6 @@ OUTPUTFORMAT=HTML
TEMPLATE=responsive-twig TEMPLATE=responsive-twig
# make documentation # make documentation
$BIN_PHPDOC -d $PATH_PROJECT,$PATH_FRAMEWORK -t $PATH_DOCS --title "$TITLE" \ $BIN_PHPDOC -d $PATH_PROJECT,$PATH_FRAMEWORK -t $PATH_DOCS --title "$TITLE" --defaultpackagename $PACKAGES \
--defaultpackagename $PACKAGES --template=$TEMPLATE --template=$TEMPLATE

@ -2,9 +2,10 @@
<?php <?php
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client | | bin/moduserprefs.sh |
| | | |
| Copyright (C) The Roundcube Dev Team | | This file is part of the Roundcube Webmail client |
| Copyright (C) 2012-2015, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
@ -63,3 +64,5 @@ if ($args['config']) {
} }
rcmail_utils::mod_pref($pref_name, $pref_value, $args['user'], $args['type']); rcmail_utils::mod_pref($pref_name, $pref_value, $args['user'], $args['type']);
?>

@ -1,18 +1,5 @@
#!/usr/bin/env php #!/usr/bin/env php
<?php <?php
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <thomas@roundcube.net> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' ); define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
ini_set('memory_limit', -1); ini_set('memory_limit', -1);
@ -21,84 +8,89 @@ require_once INSTALL_PATH.'program/include/clisetup.php';
function print_usage() function print_usage()
{ {
print "Usage: msgexport -h imap-host -u user-name -m mailbox name\n"; print "Usage: msgexport -h imap-host -u user-name -m mailbox name\n";
print "--host IMAP host\n"; print "--host IMAP host\n";
print "--user IMAP user name\n"; print "--user IMAP user name\n";
print "--mbox Folder name, set to '*' for all\n"; print "--mbox Folder name, set to '*' for all\n";
print "--file Output file\n"; print "--file Output file\n";
} }
function vputs($str) function vputs($str)
{ {
$out = $GLOBALS['args']['file'] ? STDOUT : STDERR; $out = $GLOBALS['args']['file'] ? STDOUT : STDERR;
fwrite($out, $str); fwrite($out, $str);
} }
function progress_update($pos, $max) function progress_update($pos, $max)
{ {
$percent = round(100 * $pos / $max); $percent = round(100 * $pos / $max);
vputs(sprintf("%3d%% [%-51s] %d/%d\033[K\r", $percent, @str_repeat('=', $percent / 2) . '>', $pos, $max)); vputs(sprintf("%3d%% [%-51s] %d/%d\033[K\r", $percent, @str_repeat('=', $percent / 2) . '>', $pos, $max));
} }
function export_mailbox($mbox, $filename) function export_mailbox($mbox, $filename)
{ {
global $IMAP; global $IMAP;
$IMAP->set_folder($mbox); $IMAP->set_folder($mbox);
$index = $IMAP->index($mbox, null, 'ASC'); $index = $IMAP->index($mbox, null, 'ASC');
$count = $index->count(); $count = $index->count();
$index = $index->get(); $index = $index->get();
vputs("Getting message list of {$mbox}..."); vputs("Getting message list of {$mbox}...");
vputs("$count messages\n"); vputs("$count messages\n");
if ($filename) { if ($filename)
if (!($out = fopen($filename, 'w'))) { {
vputs("Cannot write to output file\n"); if (!($out = fopen($filename, 'w')))
return; {
} vputs("Cannot write to output file\n");
vputs("Writing to $filename\n"); return;
} }
else { vputs("Writing to $filename\n");
$out = STDOUT; }
} else
$out = STDOUT;
for ($i = 0; $i < $count; $i++) {
$headers = $IMAP->get_message_headers($index[$i]); for ($i = 0; $i < $count; $i++)
$from = current(rcube_mime::decode_address_list($headers->from, 1, false)); {
$headers = $IMAP->get_message_headers($index[$i]);
fwrite($out, sprintf("From %s %s UID %d\n", $from['mailto'], $headers->date, $headers->uid)); $from = current(rcube_mime::decode_address_list($headers->from, 1, false));
$IMAP->get_raw_body($headers->uid, $out);
fwrite($out, "\n\n\n"); fwrite($out, sprintf("From %s %s UID %d\n", $from['mailto'], $headers->date, $headers->uid));
$IMAP->get_raw_body($headers->uid, $out);
progress_update($i+1, $count); fwrite($out, "\n\n\n");
}
vputs("\ncomplete.\n"); progress_update($i+1, $count);
}
if ($filename) { vputs("\ncomplete.\n");
fclose($out);
} if ($filename)
fclose($out);
} }
// get arguments // get arguments
$opts = array('h' => 'host', 'u' => 'user', 'p' => 'pass', 'm' => 'mbox', 'f' => 'file'); $opts = array('h' => 'host', 'u' => 'user', 'p' => 'pass', 'm' => 'mbox', 'f' => 'file');
$args = rcube_utils::get_opt($opts) + array('host' => 'localhost', 'mbox' => 'INBOX'); $args = rcube_utils::get_opt($opts) + array('host' => 'localhost', 'mbox' => 'INBOX');
if ($_SERVER['argv'][1] == 'help') { if ($_SERVER['argv'][1] == 'help')
print_usage(); {
exit; print_usage();
exit;
} }
else if (!$args['host']) { else if (!$args['host'])
vputs("Missing required parameters.\n"); {
print_usage(); vputs("Missing required parameters.\n");
exit; print_usage();
exit;
} }
// prompt for username if not set // prompt for username if not set
if (empty($args['user'])) { if (empty($args['user']))
vputs("IMAP user: "); {
$args['user'] = trim(fgets(STDIN)); vputs("IMAP user: ");
$args['user'] = trim(fgets(STDIN));
} }
// prompt for password // prompt for password
@ -107,39 +99,45 @@ $args['pass'] = rcube_utils::prompt_silent("Password: ");
// parse $host URL // parse $host URL
$a_host = parse_url($args['host']); $a_host = parse_url($args['host']);
if ($a_host['host']) { if ($a_host['host'])
$host = $a_host['host']; {
$imap_ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? TRUE : FALSE; $host = $a_host['host'];
$imap_port = isset($a_host['port']) ? $a_host['port'] : ($imap_ssl ? 993 : 143); $imap_ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? TRUE : FALSE;
$imap_port = isset($a_host['port']) ? $a_host['port'] : ($imap_ssl ? 993 : 143);
} }
else { else
$host = $args['host']; {
$imap_port = 143; $host = $args['host'];
$imap_port = 143;
} }
// instantiate IMAP class // instantiate IMAP class
$IMAP = new rcube_imap(null); $IMAP = new rcube_imap(null);
// try to connect to IMAP server // try to connect to IMAP server
if ($IMAP->connect($host, $args['user'], $args['pass'], $imap_port, $imap_ssl)) { if ($IMAP->connect($host, $args['user'], $args['pass'], $imap_port, $imap_ssl))
vputs("IMAP login successful.\n"); {
vputs("IMAP login successful.\n");
$filename = null; $filename = null;
$mailboxes = $args['mbox'] == '*' ? $IMAP->list_folders(null) : array($args['mbox']); $mailboxes = $args['mbox'] == '*' ? $IMAP->list_folders(null) : array($args['mbox']);
foreach ($mailboxes as $mbox) { foreach ($mailboxes as $mbox)
if ($args['file']) {
$filename = preg_replace('/\.[a-z0-9]{3,4}$/i', '', $args['file']) . asciiwords($mbox) . '.mbox'; if ($args['file'])
else if ($args['mbox'] == '*') $filename = preg_replace('/\.[a-z0-9]{3,4}$/i', '', $args['file']) . asciiwords($mbox) . '.mbox';
$filename = asciiwords($mbox) . '.mbox'; else if ($args['mbox'] == '*')
$filename = asciiwords($mbox) . '.mbox';
if ($args['mbox'] == '*' && in_array(strtolower($mbox), array('junk','spam','trash'))) { if ($args['mbox'] == '*' && in_array(strtolower($mbox), array('junk','spam','trash')))
continue; continue;
}
export_mailbox($mbox, $filename); export_mailbox($mbox, $filename);
} }
} }
else { else
vputs("IMAP login failed.\n"); {
vputs("IMAP login failed.\n");
} }
?>

@ -1,18 +1,5 @@
#!/usr/bin/env php #!/usr/bin/env php
<?php <?php
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <thomas@roundcube.net> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' ); define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
ini_set('memory_limit', -1); ini_set('memory_limit', -1);
@ -21,11 +8,11 @@ require_once INSTALL_PATH.'program/include/clisetup.php';
function print_usage() function print_usage()
{ {
print "Usage: msgimport -h imap-host -u user-name -m mailbox -f message-file\n"; print "Usage: msgimport -h imap-host -u user-name -m mailbox -f message-file\n";
print "--host IMAP host\n"; print "--host IMAP host\n";
print "--user IMAP user name\n"; print "--user IMAP user name\n";
print "--mbox Target mailbox\n"; print "--mbox Target mailbox\n";
print "--file Message file to upload\n"; print "--file Message file to upload\n";
} }
@ -33,80 +20,94 @@ function print_usage()
$opts = array('h' => 'host', 'u' => 'user', 'p' => 'pass', 'm' => 'mbox', 'f' => 'file'); $opts = array('h' => 'host', 'u' => 'user', 'p' => 'pass', 'm' => 'mbox', 'f' => 'file');
$args = rcube_utils::get_opt($opts) + array('host' => 'localhost', 'mbox' => 'INBOX'); $args = rcube_utils::get_opt($opts) + array('host' => 'localhost', 'mbox' => 'INBOX');
if ($_SERVER['argv'][1] == 'help') { if ($_SERVER['argv'][1] == 'help')
print_usage(); {
exit; print_usage();
exit;
} }
else if (!($args['host'] && $args['file'])) { else if (!($args['host'] && $args['file']))
print "Missing required parameters.\n"; {
print_usage(); print "Missing required parameters.\n";
exit; print_usage();
exit;
} }
else if (!is_file($args['file'])) { else if (!is_file($args['file']))
rcube::raise_error("Cannot read message file.", false, true); {
rcube::raise_error("Cannot read message file.", false, true);
} }
// prompt for username if not set // prompt for username if not set
if (empty($args['user'])) { if (empty($args['user']))
//fwrite(STDOUT, "Please enter your name\n"); {
echo "IMAP user: "; //fwrite(STDOUT, "Please enter your name\n");
$args['user'] = trim(fgets(STDIN)); echo "IMAP user: ";
$args['user'] = trim(fgets(STDIN));
} }
// prompt for password // prompt for password
if (empty($args['pass'])) { if (empty($args['pass']))
$args['pass'] = rcube_utils::prompt_silent("Password: "); {
$args['pass'] = rcube_utils::prompt_silent("Password: ");
} }
// parse $host URL // parse $host URL
$a_host = parse_url($args['host']); $a_host = parse_url($args['host']);
if ($a_host['host']) { if ($a_host['host'])
$host = $a_host['host']; {
$imap_ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? TRUE : FALSE; $host = $a_host['host'];
$imap_port = isset($a_host['port']) ? $a_host['port'] : ($imap_ssl ? 993 : 143); $imap_ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? TRUE : FALSE;
$imap_port = isset($a_host['port']) ? $a_host['port'] : ($imap_ssl ? 993 : 143);
} }
else { else
$host = $args['host']; {
$imap_port = 143; $host = $args['host'];
$imap_port = 143;
} }
// instantiate IMAP class // instantiate IMAP class
$IMAP = new rcube_imap(null); $IMAP = new rcube_imap(null);
// try to connect to IMAP server // try to connect to IMAP server
if ($IMAP->connect($host, $args['user'], $args['pass'], $imap_port, $imap_ssl)) { if ($IMAP->connect($host, $args['user'], $args['pass'], $imap_port, $imap_ssl))
print "IMAP login successful.\n"; {
print "Uploading messages...\n"; print "IMAP login successful.\n";
print "Uploading messages...\n";
$count = 0;
$message = $lastline = ''; $count = 0;
$message = $lastline = '';
$fp = fopen($args['file'], 'r');
while (($line = fgets($fp)) !== false) { $fp = fopen($args['file'], 'r');
if (preg_match('/^From\s+-/', $line) && $lastline == '') { while (($line = fgets($fp)) !== false)
if (!empty($message)) { {
if ($IMAP->save_message($args['mbox'], rtrim($message))) if (preg_match('/^From\s+-/', $line) && $lastline == '')
$count++; {
else if (!empty($message))
rcube::raise_error("Failed to save message to {$args['mbox']}", false, true); {
$message = ''; if ($IMAP->save_message($args['mbox'], rtrim($message)))
} $count++;
continue; else
} rcube::raise_error("Failed to save message to {$args['mbox']}", false, true);
$message = '';
$message .= $line; }
$lastline = rtrim($line); continue;
} }
if (!empty($message) && $IMAP->save_message($args['mbox'], rtrim($message))) $message .= $line;
$count++; $lastline = rtrim($line);
}
// upload message from file
if ($count) if (!empty($message) && $IMAP->save_message($args['mbox'], rtrim($message)))
print "$count messages successfully added to {$args['mbox']}.\n"; $count++;
else
print "Adding messages failed!\n"; // upload message from file
if ($count)
print "$count messages successfully added to {$args['mbox']}.\n";
else
print "Adding messages failed!\n";
} }
else { else
rcube::raise_error("IMAP login failed.", false, true); {
rcube::raise_error("IMAP login failed.", false, true);
} }
?>

@ -2,9 +2,10 @@
<?php <?php
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client | | bin/package2composer.sh |
| | | |
| Copyright (C) The Roundcube Dev Team | | This file is part of the Roundcube Webmail client |
| Copyright (C) 2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
@ -12,6 +13,7 @@
| | | |
| PURPOSE: | | PURPOSE: |
| Convert a plugin's package.xml file into a composer.json description | | Convert a plugin's package.xml file into a composer.json description |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Author: Thomas Bruederli <thomas@roundcube.net> | | Author: Thomas Bruederli <thomas@roundcube.net> |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
@ -95,7 +97,7 @@ else if (defined('JSON_PRETTY_PRINT')) {
echo json_encode($data, $flags); echo json_encode($data, $flags);
} }
else { else {
fwrite(STDERR, fputs(STDERR,
"FAILED! composer.phar not found in current directory. "FAILED! composer.phar not found in current directory.
Please download it from http://getcomposer.org/download/ or with Please download it from http://getcomposer.org/download/ or with
@ -104,3 +106,4 @@ Please download it from http://getcomposer.org/download/ or with
} }
echo "\n"; echo "\n";

@ -2,9 +2,10 @@
<?php <?php
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client | | bin/update.sh |
| | | |
| Copyright (C) The Roundcube Dev Team | | This file is part of the Roundcube Webmail client |
| Copyright (C) 2010-2015, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
@ -27,267 +28,249 @@ $opts = rcube_utils::get_opt(array('v' => 'version', 'y' => 'accept:bool'));
// ask user if no version is specified // ask user if no version is specified
if (!$opts['version']) { if (!$opts['version']) {
echo "What version are you upgrading from? Type '?' if you don't know.\n"; echo "What version are you upgrading from? Type '?' if you don't know.\n";
if (($input = trim(fgets(STDIN))) && preg_match('/^[0-9.]+[a-z-]*$/', $input))
if (($input = trim(fgets(STDIN))) && preg_match('/^[0-9.]+[a-z0-9-]*$/', $input)) { $opts['version'] = $input;
$opts['version'] = $input; else
} $opts['version'] = RCMAIL_VERSION;
else {
$opts['version'] = RCMAIL_VERSION;
}
} }
$RCI = rcmail_install::get_instance(); $RCI = rcmail_install::get_instance();
$RCI->load_config(); $RCI->load_config();
if ($RCI->configured) { if ($RCI->configured) {
$success = true; $success = true;
if (($messages = $RCI->check_config($opts['version'])) || $RCI->legacy_config) { if (($messages = $RCI->check_config()) || $RCI->legacy_config) {
$success = false; $success = false;
$err = 0; $err = 0;
// list old/replaced config options
if (is_array($messages['replaced'])) {
echo "WARNING: Replaced config options:\n";
echo "(These config options have been replaced or renamed)\n";
foreach ($messages['replaced'] as $msg) {
echo "- '" . $msg['prop'] . "' was replaced by '" . $msg['replacement'] . "'\n";
$err++;
}
echo "\n";
}
// list old/replaced config options // list obsolete config options (just a notice)
if (is_array($messages['replaced'])) { if (is_array($messages['obsolete'])) {
echo "WARNING: Replaced config options:\n"; echo "NOTICE: Obsolete config options:\n";
echo "(These config options have been replaced or renamed)\n"; echo "(You still have some obsolete or inexistent properties set. This isn't a problem but should be noticed)\n";
foreach ($messages['replaced'] as $msg) { foreach ($messages['obsolete'] as $msg) {
echo "- '" . $msg['prop'] . "' was replaced by '" . $msg['replacement'] . "'\n"; echo "- '" . $msg['prop'] . ($msg['name'] ? "': " . $msg['name'] : "'") . "\n";
$err++; $err++;
} }
} echo "\n";
}
// list obsolete config options (just a notice) if (!$err && $RCI->legacy_config) {
if (is_array($messages['obsolete'])) { echo "WARNING: Your configuration needs to be migrated!\n";
echo "NOTICE: Obsolete config options:\n"; echo "We changed the configuration files structure and your two config files main.inc.php and db.inc.php have to be merged into one single file.\n";
echo "(You still have some obsolete or inexistent properties set." $err++;
. " This isn't a problem but should be noticed)\n"; }
foreach ($messages['obsolete'] as $msg) { // ask user to update config files
echo "- '" . $msg['prop'] . ($msg['name'] ? "': " . $msg['name'] : "'") . "\n"; if ($err) {
$err++; if (!$opts['accept']) {
} echo "Do you want me to fix your local configuration? (y/N)\n";
} $input = trim(fgets(STDIN));
}
if (!$err && $RCI->legacy_config) { // positive: let's merge the local config with the defaults
echo "WARNING: Your configuration needs to be migrated!\n"; if ($opts['accept'] || strtolower($input) == 'y') {
echo "We changed the configuration files structure and your two config files " $error = $written = false;
. "main.inc.php and db.inc.php have to be merged into one single file.\n";
$err++;
}
// ask user to update config files // backup current config
if ($err) { echo ". backing up the current config file(s)...\n";
if (!$opts['accept']) {
echo "Do you want me to fix your local configuration? (y/N)\n";
$input = trim(fgets(STDIN));
}
// positive: merge the local config with the defaults foreach (array('config', 'main', 'db') as $file) {
if ($opts['accept'] || strtolower($input) == 'y') { if (file_exists(RCMAIL_CONFIG_DIR . '/' . $file . '.inc.php')) {
$error = $written = false; if (!copy(RCMAIL_CONFIG_DIR . '/' . $file . '.inc.php', RCMAIL_CONFIG_DIR . '/' . $file . '.old.php')) {
$error = true;
echo ". backing up the current config file(s)...\n";
foreach (array('config', 'main', 'db') as $file) {
if (file_exists(RCMAIL_CONFIG_DIR . '/' . $file . '.inc.php')) {
if (!copy(RCMAIL_CONFIG_DIR . '/' . $file . '.inc.php', RCMAIL_CONFIG_DIR . '/' . $file . '.old.php')) {
$error = true;
}
}
}
if (!$error) {
$RCI->merge_config();
echo ". writing " . RCMAIL_CONFIG_DIR . "/config.inc.php...\n";
$written = $RCI->save_configfile($RCI->create_config());
}
// Success!
if ($written) {
echo "Done.\n";
echo "Your configuration files are now up-to-date!\n";
if ($messages['missing']) {
echo "But you still need to add the following missing options:\n";
foreach ($messages['missing'] as $msg) {
echo "- '" . $msg['prop'] . ($msg['name'] ? "': " . $msg['name'] : "'") . "\n";
}
}
if ($RCI->legacy_config) {
foreach (array('main', 'db') as $file) {
@unlink(RCMAIL_CONFIG_DIR . '/' . $file . '.inc.php');
}
}
}
else {
echo "Failed to write config file(s)!\n";
echo "Grant write privileges to the current user or update the files manually "
. "according to the above messages.\n";
}
}
else {
echo "Please update your config files manually according to the above messages.\n";
} }
}
} }
// list of config options with changed default (just a notice) if (!$error) {
if (!empty($messages['defaults'])) { $RCI->merge_config();
echo "WARNING: Changed defaults (These config options have new default values):\n"; echo ". writing " . RCMAIL_CONFIG_DIR . "/config.inc.php...\n";
$written = $RCI->save_configfile($RCI->create_config());
foreach ($messages['defaults'] as $opt) {
echo "- '{$opt}'\n";
}
} }
// check dependencies based on the current configuration // Success!
if (is_array($messages['dependencies'])) { if ($written) {
echo "WARNING: Dependency check failed!\n"; echo "Done.\n";
echo "(Some of your configuration settings require other options to be configured " echo "Your configuration files are now up-to-date!\n";
. "or additional PHP modules to be installed)\n";
foreach ($messages['dependencies'] as $msg) { if ($messages['missing']) {
echo "- " . $msg['prop'] . ': ' . $msg['explain'] . "\n"; echo "But you still need to add the following missing options:\n";
} foreach ($messages['missing'] as $msg)
echo "- '" . $msg['prop'] . ($msg['name'] ? "': " . $msg['name'] : "'") . "\n";
}
echo "Please fix your config files and run this script again!\n"; if ($RCI->legacy_config) {
echo "See ya.\n"; foreach (array('main', 'db') as $file) {
@unlink(RCMAIL_CONFIG_DIR . '/' . $file . '.inc.php');
}
}
}
else {
echo "Failed to write config file(s)!\n";
echo "Grant write privileges to the current user or update the files manually according to the above messages.\n";
} }
}
else {
echo "Please update your config files manually according to the above messages.\n";
}
} }
// check file type detection // check dependencies based on the current configuration
if ($RCI->check_mime_detection()) { if (is_array($messages['dependencies'])) {
echo "WARNING: File type detection doesn't work properly!\n"; echo "WARNING: Dependency check failed!\n";
echo "Please check the 'mime_magic' config option or the finfo functions of PHP and run this script again.\n"; echo "(Some of your configuration settings require other options to be configured or additional PHP modules to be installed)\n";
}
if ($RCI->check_mime_extensions()) {
echo "WARNING: Mimetype to file extension mapping doesn't work properly!\n";
echo "Please check the 'mime_types' config option and run this script again.\n";
}
// check database schema foreach ($messages['dependencies'] as $msg) {
if ($RCI->config['db_dsnw']) { echo "- " . $msg['prop'] . ': ' . $msg['explain'] . "\n";
echo "Executing database schema update.\n"; }
$success = rcmail_utils::db_update(INSTALL_PATH . 'SQL', 'roundcube', $opts['version'], echo "Please fix your config files and run this script again!\n";
array('errors' => true)); echo "See ya.\n";
} }
}
// update composer dependencies
if (is_file(INSTALL_PATH . 'composer.json') && is_readable(INSTALL_PATH . 'composer.json-dist')) { // check file type detection
$composer_data = json_decode(file_get_contents(INSTALL_PATH . 'composer.json'), true); if ($RCI->check_mime_detection()) {
$composer_template = json_decode(file_get_contents(INSTALL_PATH . 'composer.json-dist'), true); echo "WARNING: File type detection doesn't work properly!\n";
$comsposer_json = null; echo "Please check the 'mime_magic' config option or the finfo functions of PHP and run this script again.\n";
}
// update the require section with the new dependencies if ($RCI->check_mime_extensions()) {
if (is_array($composer_data['require']) && is_array($composer_template['require'])) { echo "WARNING: Mimetype to file extension mapping doesn't work properly!\n";
$composer_data['require'] = array_merge($composer_data['require'], $composer_template['require']); echo "Please check the 'mime_types' config option and run this script again.\n";
}
// remove obsolete packages
$old_packages = array( // check database schema
'pear-pear.php.net/net_socket', if ($RCI->config['db_dsnw']) {
'pear-pear.php.net/auth_sasl', echo "Executing database schema update.\n";
'pear-pear.php.net/net_idna2', $success = rcmail_utils::db_update(INSTALL_PATH . 'SQL', 'roundcube', $opts['version'],
'pear-pear.php.net/mail_mime', array('errors' => true));
'pear-pear.php.net/net_smtp', }
'pear-pear.php.net/crypt_gpg',
'pear-pear.php.net/net_sieve', // update composer dependencies
'pear/mail_mime-decode', if (is_file(INSTALL_PATH . 'composer.json') && is_readable(INSTALL_PATH . 'composer.json-dist')) {
'roundcube/net_sieve', $composer_data = json_decode(file_get_contents(INSTALL_PATH . 'composer.json'), true);
'endroid/qrcode', $composer_template = json_decode(file_get_contents(INSTALL_PATH . 'composer.json-dist'), true);
); $comsposer_json = null;
foreach ($old_packages as $pkg) { // update the require section with the new dependencies
if (array_key_exists($pkg, $composer_data['require'])) { if (is_array($composer_data['require']) && is_array($composer_template['require'])) {
unset($composer_data['require'][$pkg]); $composer_data['require'] = array_merge($composer_data['require'], $composer_template['require']);
}
} // remove obsolete packages
} $old_packages = array(
'pear-pear.php.net/net_socket',
// update the repositories section with the new dependencies 'pear-pear.php.net/auth_sasl',
if (is_array($composer_template['repositories'])) { 'pear-pear.php.net/net_idna2',
if (!is_array($composer_data['repositories'])) { 'pear-pear.php.net/mail_mime',
$composer_data['repositories'] = array(); 'pear-pear.php.net/net_smtp',
} 'pear-pear.php.net/crypt_gpg',
'pear-pear.php.net/net_sieve',
foreach ($composer_template['repositories'] as $repo) { 'pear/mail_mime-decode',
$rkey = $repo['type'] . preg_replace('/^https?:/', '', $repo['url']) . $repo['package']['name']; 'roundcube/net_sieve',
$existing = false; 'endroid/qrcode',
);
foreach ($composer_data['repositories'] as $k => $_repo) { foreach ($old_packages as $pkg) {
if ($rkey == $_repo['type'] . preg_replace('/^https?:/', '', $_repo['url']) . $_repo['package']['name']) { if (array_key_exists($pkg, $composer_data['require'])) {
// switch to https:// unset($composer_data['require'][$pkg]);
if (isset($_repo['url']) && strpos($_repo['url'], 'http://') === 0) {
$composer_data['repositories'][$k]['url'] = 'https:' . substr($_repo['url'], 5);
}
$existing = true;
break;
}
// remove old repos
if (strpos($_repo['url'], 'git://git.kolab.org') === 0) {
unset($composer_data['repositories'][$k]);
}
else if ($_repo['type'] == 'package' && $_repo['package']['name'] == 'Net_SMTP') {
unset($composer_data['repositories'][$k]);
}
}
if (!$existing) {
$composer_data['repositories'][] = $repo;
}
}
$composer_data['repositories'] = array_values($composer_data['repositories']);
} }
}
}
// use the JSON encoder from the Composer package // update the repositories section with the new dependencies
if (is_file('composer.phar')) { if (is_array($composer_template['repositories'])) {
include 'phar://composer.phar/src/Composer/Json/JsonFile.php'; if (!is_array($composer_data['repositories'])) {
$comsposer_json = \Composer\Json\JsonFile::encode($composer_data); $composer_data['repositories'] = array();
} }
// PHP 5.4's json_encode() does the job, too
else if (defined('JSON_PRETTY_PRINT')) { foreach ($composer_template['repositories'] as $repo) {
$comsposer_json = json_encode($composer_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); $rkey = $repo['type'] . preg_replace('/^https?:/', '', $repo['url']) . $repo['package']['name'];
} $existing = false;
else { foreach ($composer_data['repositories'] as $k => $_repo) {
$success = false; if ($rkey == $_repo['type'] . preg_replace('/^https?:/', '', $_repo['url']) . $_repo['package']['name']) {
$comsposer_json = null; // switch to https://
if (isset($_repo['url']) && strpos($_repo['url'], 'http://') === 0)
$composer_data['repositories'][$k]['url'] = 'https:' . substr($_repo['url'], 5);
$existing = true;
break;
}
// remove old repos
else if (strpos($_repo['url'], 'git://git.kolab.org') === 0) {
unset($composer_data['repositories'][$k]);
}
else if ($_repo['type'] == 'package' && $_repo['package']['name'] == 'Net_SMTP') {
unset($composer_data['repositories'][$k]);
}
} }
if (!$existing) {
// write updated composer.json back to disk $composer_data['repositories'][] = $repo;
if ($comsposer_json && is_writeable(INSTALL_PATH . 'composer.json')) {
$success &= (bool)file_put_contents(INSTALL_PATH . 'composer.json', $comsposer_json);
} }
else { }
echo "WARNING: unable to update composer.json!\n";
echo "Please replace the 'require' section in your composer.json with the following:\n";
$require_json = ''; $composer_data['repositories'] = array_values($composer_data['repositories']);
foreach ($composer_data['require'] as $pkg => $ver) { }
$require_json .= sprintf(' "%s": "%s",'."\n", $pkg, $ver);
}
echo ' "require": {'."\n";
echo rtrim($require_json, ",\n");
echo "\n }\n\n";
}
echo "NOTICE: Update dependencies by running `php composer.phar update --no-dev`\n"; // use the JSON encoder from the Composer package
if (is_file('composer.phar')) {
include 'phar://composer.phar/src/Composer/Json/JsonFile.php';
$comsposer_json = \Composer\Json\JsonFile::encode($composer_data);
}
// PHP 5.4's json_encode() does the job, too
else if (defined('JSON_PRETTY_PRINT')) {
$comsposer_json = json_encode($composer_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
}
else {
$success = false;
$comsposer_json = null;
} }
// index contacts for fulltext searching // write updated composer.json back to disk
if ($opts['version'] && version_compare(version_parse($opts['version']), '0.6.0', '<')) { if ($comsposer_json && is_writeable(INSTALL_PATH . 'composer.json')) {
rcmail_utils::indexcontacts(); $success &= (bool)file_put_contents(INSTALL_PATH . 'composer.json', $comsposer_json);
} }
else {
echo "WARNING: unable to update composer.json!\n";
echo "Please replace the 'require' section in your composer.json with the following:\n";
$require_json = '';
foreach ($composer_data['require'] as $pkg => $ver) {
$require_json .= sprintf(' "%s": "%s",'."\n", $pkg, $ver);
}
if ($success) { echo ' "require": {'."\n";
echo "This instance of Roundcube is up-to-date.\n"; echo rtrim($require_json, ",\n");
echo "Have fun!\n"; echo "\n }\n\n";
} }
echo "NOTE: Update dependencies by running `php composer.phar update --no-dev`\n";
}
// index contacts for fulltext searching
if ($opts['version'] && version_compare(version_parse($opts['version']), '0.6.0', '<')) {
rcmail_utils::indexcontacts();
}
if ($success) {
echo "This instance of Roundcube is up-to-date.\n";
echo "Have fun!\n";
}
} }
else { else {
echo "This instance of Roundcube is not yet configured!\n"; echo "This instance of Roundcube is not yet configured!\n";
echo "Open http://url-to-roundcube/installer/ in your browser and follow the instuctions.\n"; echo "Open http://url-to-roundcube/installer/ in your browser and follow the instuctions.\n";
} }
?>

@ -2,9 +2,10 @@
<?php <?php
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client | | bin/updatecss.sh |
| | | |
| Copyright (C) The Roundcube Dev Team | | This file is part of the Roundcube Webmail client |
| Copyright (C) 2010-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
@ -117,3 +118,5 @@ function get_files($dir)
return $files; return $files;
} }
?>

@ -2,10 +2,11 @@
<?php <?php
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client | | bin/updatedb.sh |
| | | |
| Copyright (C) The Roundcube Dev Team | | This file is part of the Roundcube Webmail client |
| Copyright (C) Kolab Systems AG | | Copyright (C) 2010-2012, The Roundcube Dev Team |
| Copyright (C) 2010-2012, Kolab Systems AG |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
@ -37,3 +38,5 @@ if (empty($opts['package'])) {
} }
rcmail_utils::db_update($opts['dir'], $opts['package'], $opts['version'], array('errors' => true)); rcmail_utils::db_update($opts['dir'], $opts['package'], $opts['version'], array('errors' => true));
?>

@ -18,14 +18,15 @@
"pear/crypt_gpg": "~1.6.3", "pear/crypt_gpg": "~1.6.3",
"pear/net_sieve": "~1.4.3", "pear/net_sieve": "~1.4.3",
"roundcube/plugin-installer": "~0.1.6", "roundcube/plugin-installer": "~0.1.6",
"masterminds/html5": "~2.5.0", "masterminds/html5": "~2.3.0",
"endroid/qr-code": "~1.6.5" "endroid/qr-code": "~1.6.5"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6 || ^7" "phpunit/phpunit": "^4.8.36 || ^5.7.21"
}, },
"suggest": { "suggest": {
"kolab/net_ldap3": "~1.1.1 required for connecting to LDAP", "pear/net_ldap2": "~2.2.0 required for connecting to LDAP",
"kolab/net_ldap3": "~1.0.6 required for connecting to LDAP",
"mkopinsky/zxcvbn-php": "^4.4.2 required for Zxcvbn password strength driver" "mkopinsky/zxcvbn-php": "^4.4.2 required for Zxcvbn password strength driver"
} }
} }

@ -9,7 +9,7 @@
| from defaults.inc.php to this file to override the defaults. | | from defaults.inc.php to this file to override the defaults. |
| | | |
| This file is part of the Roundcube Webmail client | | This file is part of the Roundcube Webmail client |
| Copyright (C) The Roundcube Dev Team | | Copyright (C) 2005-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
@ -30,8 +30,7 @@ $config['db_dsnw'] = 'mysql://roundcube:pass@localhost/roundcubemail';
// The IMAP host chosen to perform the log-in. // The IMAP host chosen to perform the log-in.
// Leave blank to show a textbox at login, give a list of hosts // Leave blank to show a textbox at login, give a list of hosts
// to display a pulldown menu or set one host as string. // to display a pulldown menu or set one host as string.
// Enter hostname with prefix ssl:// to use Implicit TLS, or use // To use SSL/TLS connection, enter hostname with prefix ssl:// or tls://
// prefix tls:// to use STARTTLS.
// Supported replacement variables: // Supported replacement variables:
// %n - hostname ($_SERVER['SERVER_NAME']) // %n - hostname ($_SERVER['SERVER_NAME'])
// %t - hostname without the first part // %t - hostname without the first part
@ -41,8 +40,8 @@ $config['db_dsnw'] = 'mysql://roundcube:pass@localhost/roundcubemail';
$config['default_host'] = 'localhost'; $config['default_host'] = 'localhost';
// SMTP server host (for sending mails). // SMTP server host (for sending mails).
// Enter hostname with prefix ssl:// to use Implicit TLS, or use // Enter hostname with prefix tls:// to use STARTTLS, or use
// prefix tls:// to use STARTTLS. // prefix ssl:// to use the deprecated SSL over SMTP (aka SMTPS)
// Supported replacement variables: // Supported replacement variables:
// %h - user's IMAP hostname // %h - user's IMAP hostname
// %n - hostname ($_SERVER['SERVER_NAME']) // %n - hostname ($_SERVER['SERVER_NAME'])
@ -50,11 +49,10 @@ $config['default_host'] = 'localhost';
// %d - domain (http hostname $_SERVER['HTTP_HOST'] without the first part) // %d - domain (http hostname $_SERVER['HTTP_HOST'] without the first part)
// %z - IMAP domain (IMAP hostname without the first part) // %z - IMAP domain (IMAP hostname without the first part)
// For example %n = mail.domain.tld, %t = domain.tld // For example %n = mail.domain.tld, %t = domain.tld
// To specify differnt SMTP servers for different IMAP hosts provide an array
// of IMAP host (no prefix or port) and SMTP server e.g. array('imap.example.com' => 'smtp.example.net')
$config['smtp_server'] = 'localhost'; $config['smtp_server'] = 'localhost';
// SMTP port. Use 25 for cleartext, 465 for Implicit TLS, or 587 for STARTTLS (default) // SMTP port (default is 25; use 587 for STARTTLS or 465 for the
// deprecated SSL over SMTP (aka SMTPS))
$config['smtp_port'] = 587; $config['smtp_port'] = 587;
// SMTP username (if required) if you use %u as the username Roundcube // SMTP username (if required) if you use %u as the username Roundcube
@ -72,9 +70,9 @@ $config['support_url'] = '';
// Name your service. This is displayed on the login screen and in the window title // Name your service. This is displayed on the login screen and in the window title
$config['product_name'] = 'Roundcube Webmail'; $config['product_name'] = 'Roundcube Webmail';
// This key is used to encrypt the users imap password which is stored // this key is used to encrypt the users imap password which is stored
// in the session record. For the default cipher method it must be // in the session record (and the client cookie if remember password is enabled).
// exactly 24 characters long. // please provide a string of exactly 24 chars.
// YOUR KEY MUST BE DIFFERENT THAN THE SAMPLE VALUE FOR SECURITY REASONS // YOUR KEY MUST BE DIFFERENT THAN THE SAMPLE VALUE FOR SECURITY REASONS
$config['des_key'] = 'rcmail-!24ByteDESkey*Str'; $config['des_key'] = 'rcmail-!24ByteDESkey*Str';
@ -85,4 +83,4 @@ $config['plugins'] = array(
); );
// skin name: folder from skins/ // skin name: folder from skins/
$config['skin'] = 'elastic'; $config['skin'] = 'larry';

@ -9,7 +9,7 @@
| Default settings for all configuration options | | Default settings for all configuration options |
| | | |
| This file is part of the Roundcube Webmail client | | This file is part of the Roundcube Webmail client |
| Copyright (C) The Roundcube Dev Team | | Copyright (C) 2005-2018, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
@ -27,12 +27,8 @@ $config = array();
// Format (compatible with PEAR MDB2): db_provider://user:password@host/database // Format (compatible with PEAR MDB2): db_provider://user:password@host/database
// Currently supported db_providers: mysql, pgsql, sqlite, mssql, sqlsrv, oracle // Currently supported db_providers: mysql, pgsql, sqlite, mssql, sqlsrv, oracle
// For examples see http://pear.php.net/manual/en/package.database.mdb2.intro-dsn.php // For examples see http://pear.php.net/manual/en/package.database.mdb2.intro-dsn.php
// Note: for SQLite use absolute path (Linux): 'sqlite:////full/path/to/sqlite.db?mode=0646' // NOTE: for SQLite use absolute path (Linux): 'sqlite:////full/path/to/sqlite.db?mode=0646'
// or (Windows): 'sqlite:///C:/full/path/to/sqlite.db' // or (Windows): 'sqlite:///C:/full/path/to/sqlite.db'
// Note: Various drivers support various additional arguments for connection,
// for Mysql: key, cipher, cert, capath, ca, verify_server_cert,
// for Postgres: application_name, sslmode, sslcert, sslkey, sslrootcert, sslcrl, sslcompression, service.
// e.g. 'mysql://roundcube:@localhost/roundcubemail?verify_server_cert=false'
$config['db_dsnw'] = 'mysql://roundcube:@localhost/roundcubemail'; $config['db_dsnw'] = 'mysql://roundcube:@localhost/roundcubemail';
// Database DSN for read-only operations (if empty write database will be used) // Database DSN for read-only operations (if empty write database will be used)
@ -96,34 +92,34 @@ $config['syslog_facility'] = LOG_USER;
// Data will only be logged if a directory <log_dir>/<username>/ exists and is writable. // Data will only be logged if a directory <log_dir>/<username>/ exists and is writable.
$config['per_user_logging'] = false; $config['per_user_logging'] = false;
// Log sent messages to <log_dir>/sendmail.log or to syslog // Log sent messages to <log_dir>/sendmail or to syslog
$config['smtp_log'] = true; $config['smtp_log'] = true;
// Log successful/failed logins to <log_dir>/userlogins.log or to syslog // Log successful/failed logins to <log_dir>/userlogins or to syslog
$config['log_logins'] = false; $config['log_logins'] = false;
// Log session debug information/authentication errors to <log_dir>/session.log or to syslog // Log session authentication errors to <log_dir>/session or to syslog
$config['session_debug'] = false; $config['log_session'] = false;
// Log SQL queries to <log_dir>/sql.log or to syslog // Log SQL queries to <log_dir>/sql or to syslog
$config['sql_debug'] = false; $config['sql_debug'] = false;
// Log IMAP conversation to <log_dir>/imap.log or to syslog // Log IMAP conversation to <log_dir>/imap or to syslog
$config['imap_debug'] = false; $config['imap_debug'] = false;
// Log LDAP conversation to <log_dir>/ldap.log or to syslog // Log LDAP conversation to <log_dir>/ldap or to syslog
$config['ldap_debug'] = false; $config['ldap_debug'] = false;
// Log SMTP conversation to <log_dir>/smtp.log or to syslog // Log SMTP conversation to <log_dir>/smtp or to syslog
$config['smtp_debug'] = false; $config['smtp_debug'] = false;
// Log Memcache conversation to <log_dir>/memcache.log or to syslog // Log Memcache conversation to <log_dir>/memcache or to syslog
$config['memcache_debug'] = false; $config['memcache_debug'] = false;
// Log APC conversation to <log_dir>/apc.log or to syslog // Log APC conversation to <log_dir>/apc or to syslog
$config['apc_debug'] = false; $config['apc_debug'] = false;
// Log Redis conversation to <log_dir>/redis.log or to syslog // Log Redis conversation to <log_dir>/redis or to syslog
$config['redis_debug'] = false; $config['redis_debug'] = false;
@ -134,8 +130,7 @@ $config['redis_debug'] = false;
// The IMAP host chosen to perform the log-in. // The IMAP host chosen to perform the log-in.
// Leave blank to show a textbox at login, give a list of hosts // Leave blank to show a textbox at login, give a list of hosts
// to display a pulldown menu or set one host as string. // to display a pulldown menu or set one host as string.
// Enter hostname with prefix ssl:// to use Implicit TLS, or use // To use SSL/TLS connection, enter hostname with prefix ssl:// or tls://
// prefix tls:// to use STARTTLS.
// Supported replacement variables: // Supported replacement variables:
// %n - hostname ($_SERVER['SERVER_NAME']) // %n - hostname ($_SERVER['SERVER_NAME'])
// %t - hostname without the first part // %t - hostname without the first part
@ -182,7 +177,7 @@ $config['imap_delimiter'] = null;
// If you know your imap's folder vendor, you can specify it here. // If you know your imap's folder vendor, you can specify it here.
// Otherwise it will be determined automatically. Use lower-case // Otherwise it will be determined automatically. Use lower-case
// identifiers, e.g. 'dovecot', 'cyrus', 'gimap', 'hmail', 'uw-imap'. // identifiers, e.g. 'dovecot', 'cyrus', 'gmail', 'hmail', 'uw-imap'.
$config['imap_vendor'] = null; $config['imap_vendor'] = null;
// If IMAP server doesn't support NAMESPACE extension, but you're // If IMAP server doesn't support NAMESPACE extension, but you're
@ -233,7 +228,7 @@ $config['imap_disabled_caps'] = array();
// This is used to relate IMAP session with Roundcube user sessions // This is used to relate IMAP session with Roundcube user sessions
$config['imap_log_session'] = false; $config['imap_log_session'] = false;
// Type of IMAP indexes cache. Supported values: 'db', 'apc' and 'memcache' or 'memcached'. // Type of IMAP indexes cache. Supported values: 'db', 'apc' and 'memcache'.
$config['imap_cache'] = null; $config['imap_cache'] = null;
// Enables messages cache. Only 'db' cache is supported. // Enables messages cache. Only 'db' cache is supported.
@ -258,8 +253,8 @@ $config['messages_cache_threshold'] = 50;
// ---------------------------------- // ----------------------------------
// SMTP server host (for sending mails). // SMTP server host (for sending mails).
// Enter hostname with prefix ssl:// to use Implicit TLS, or use // Enter hostname with prefix tls:// to use STARTTLS, or use
// prefix tls:// to use STARTTLS. // prefix ssl:// to use the deprecated SSL over SMTP (aka SMTPS)
// Supported replacement variables: // Supported replacement variables:
// %h - user's IMAP hostname // %h - user's IMAP hostname
// %n - hostname ($_SERVER['SERVER_NAME']) // %n - hostname ($_SERVER['SERVER_NAME'])
@ -267,11 +262,9 @@ $config['messages_cache_threshold'] = 50;
// %d - domain (http hostname $_SERVER['HTTP_HOST'] without the first part) // %d - domain (http hostname $_SERVER['HTTP_HOST'] without the first part)
// %z - IMAP domain (IMAP hostname without the first part) // %z - IMAP domain (IMAP hostname without the first part)
// For example %n = mail.domain.tld, %t = domain.tld // For example %n = mail.domain.tld, %t = domain.tld
// To specify differnt SMTP servers for different IMAP hosts provide an array
// of IMAP host (no prefix or port) and SMTP server e.g. array('imap.example.com' => 'smtp.example.net')
$config['smtp_server'] = 'localhost'; $config['smtp_server'] = 'localhost';
// SMTP port. Use 25 for cleartext, 465 for Implicit TLS, or 587 for STARTTLS (default) // SMTP port (default is 587)
$config['smtp_port'] = 587; $config['smtp_port'] = 587;
// SMTP username (if required) if you use %u as the username Roundcube // SMTP username (if required) if you use %u as the username Roundcube
@ -322,7 +315,7 @@ $config['smtp_conn_options'] = null;
// LDAP // LDAP
// ---------------------------------- // ----------------------------------
// Type of LDAP cache. Supported values: 'db', 'apc' and 'memcache' or 'memcached'. // Type of LDAP cache. Supported values: 'db', 'apc' and 'memcache'.
$config['ldap_cache'] = 'db'; $config['ldap_cache'] = 'db';
// Lifetime of LDAP cache. Possible units: s, m, h, d, w // Lifetime of LDAP cache. Possible units: s, m, h, d, w
@ -335,8 +328,7 @@ $config['ldap_cache_ttl'] = '10m';
// Use these hosts for accessing memcached // Use these hosts for accessing memcached
// Define any number of hosts in the form of hostname:port or unix:///path/to/socket.file // Define any number of hosts in the form of hostname:port or unix:///path/to/socket.file
// Example: array('localhost:11211', '192.168.1.12:11211', 'unix:///var/tmp/memcached.sock'); $config['memcache_hosts'] = null; // e.g. array( 'localhost:11211', '192.168.1.12:11211', 'unix:///var/tmp/memcached.sock' );
$config['memcache_hosts'] = null;
// Controls the use of a persistent connections to memcache servers // Controls the use of a persistent connections to memcache servers
// See http://php.net/manual/en/memcache.addserver.php // See http://php.net/manual/en/memcache.addserver.php
@ -351,15 +343,11 @@ $config['memcache_timeout'] = 1;
// See http://php.net/manual/en/memcache.addserver.php // See http://php.net/manual/en/memcache.addserver.php
$config['memcache_retry_interval'] = 15; $config['memcache_retry_interval'] = 15;
// Use these hosts for accessing Redis. // use these hosts for accessing Redis.
// Currently only one host is supported. Cluster support may come in a future release. // Currently only one host is supported. cluster support may come in a future release.
// You can pass 4 fields, host, port (optional), database (optional) and password (optional). // You can pass 4 fields, host, port, database and password.
// Unset fields will be set to the default values host=127.0.0.1, port=6379. // Unset fields will be set to the default values host=127.0.0.1, port=6379, database=0, password= (empty)
// Examples: $config['redis_hosts'] = null; // e.g. array( 'localhost:6379' ); array( '192.168.1.1:6379:1:secret' );
// array('localhost:6379');
// array('192.168.1.1:6379:1:secret');
// array('unix:///var/run/redis/redis-server.sock:1:secret');
$config['redis_hosts'] = null;
// Maximum size of an object in memcache (in bytes). Default: 2MB // Maximum size of an object in memcache (in bytes). Default: 2MB
$config['memcache_max_allowed_packet'] = '2M'; $config['memcache_max_allowed_packet'] = '2M';
@ -393,37 +381,16 @@ $config['advanced_prefs'] = array();
// PLEASE DO NOT LINK TO THE ROUNDCUBE.NET WEBSITE HERE! // PLEASE DO NOT LINK TO THE ROUNDCUBE.NET WEBSITE HERE!
$config['support_url'] = ''; $config['support_url'] = '';
// Logo image replacement. Specifies location of the image as: // replace Roundcube logo with this image
// - URL relative to the document root of this Roundcube installation // specify an URL relative to the document root of this Roundcube installation
// - full URL with http:// or https:// prefix // an array can be used to specify different logos for specific template files
// - URL relative to the current skin folder (when starts with a '/') // '*' for default logo
// // ':favicon' for favicon
// An array can be used to specify different logos for specific template files // ':print' for logo on all print templates (e.g. messageprint, contactprint)
// The array key specifies the place(s) the logo should be applied to and // ':small' for small screen logo in Elastic
// is made up of (up to) 3 parts: // different logos can be specified for different skins by prefixing the skin name to the array key
// - skin name prefix (always with colon, can be replaced with *) // config applied in order: <skin>:<template>, <skin>:*, <template>, *
// - template name (or * for all templates) // for example array("*" => "/images/roundcube_logo.png", "messageprint" => "/images/roundcube_logo_print.png", "elastic:*" => "/images/logo.png")
// - logo type - it is used for logos used on multiple templates
// the available types include '[favicon]' for favicon, '[print]' for logo on all print
// templates (e.g. messageprint, contactprint) and '[small]' for small screen logo in supported skins
//
// Example config for skin_logo
/*
array(
// show the image /images/logo_login_small.png for the Login screen in the Elastic skin on small screens
"elastic:login[small]" => "/images/logo_login_small.png",
// show the image /images/logo_login.png for the Login screen in the Elastic skin
"elastic:login" => "/images/logo_login.png",
// show the image /images/logo_small.png in the Elastic skin
"elastic:*[small]" => "/images/logo_small.png",
// show the image /images/larry.png in the Larry skin
"larry:*" => "/images/larry.png",
// show the image /images/logo_login.png on the login template in all skins
"login" => "/images/logo_login.png",
// show the image /images/logo_print.png for all print type logos in all skins
"[print]" => "/images/logo_print.png",
);
*/
$config['skin_logo'] = null; $config['skin_logo'] = null;
// automatically create a new Roundcube user when log-in the first time. // automatically create a new Roundcube user when log-in the first time.
@ -504,19 +471,13 @@ $config['session_auth_name'] = null;
// Session path. Defaults to PHP session.cookie_path setting. // Session path. Defaults to PHP session.cookie_path setting.
$config['session_path'] = null; $config['session_path'] = null;
// Session samesite. Defaults to PHP session.cookie_samesite setting.
// Requires PHP >= 7.3.0, see https://wiki.php.net/rfc/same-site-cookie for more info
// Possible values: null (default), 'Lax', or 'Strict'
$config['session_samesite'] = null;
// Backend to use for session storage. Can either be 'db' (default), 'redis', 'memcache', or 'php' // Backend to use for session storage. Can either be 'db' (default), 'redis', 'memcache', or 'php'
// //
// If set to 'memcache' or 'memcached', a list of servers need to be specified in 'memcache_hosts' // If set to 'memcache', a list of servers need to be specified in 'memcache_hosts'
// Make sure the Memcache extension (https://pecl.php.net/package/memcache) version >= 2.0.0 // Make sure the Memcache extension (http://pecl.php.net/package/memcache) version >= 2.0.0 is installed
// or the Memcached extension (https://pecl.php.net/package/memcached) version >= 2.0.0 is installed.
// //
// If set to 'redis', a server needs to be specified in 'redis_hosts' // If set to 'redis', a server needs to be specified in 'redis_hosts'
// Make sure the Redis extension (https://pecl.php.net/package/redis) version >= 2.0.0 is installed. // Make sure the Redis extension (http://pecl.php.net/package/redis) version >= 2.0.0 is installed
// //
// Setting this value to 'php' will use the default session save handler configured in PHP // Setting this value to 'php' will use the default session save handler configured in PHP
$config['session_storage'] = 'db'; $config['session_storage'] = 'db';
@ -544,10 +505,9 @@ $config['x_frame_options'] = 'sameorigin';
// This key is used for encrypting purposes, like storing of imap password // This key is used for encrypting purposes, like storing of imap password
// in the session. For historical reasons it's called DES_key, but it's used // in the session. For historical reasons it's called DES_key, but it's used
// with any configured cipher_method (see below). // with any configured cipher_method (see below).
// For the default cipher_method a required key length is 24 characters.
$config['des_key'] = 'rcmail-!24ByteDESkey*Str'; $config['des_key'] = 'rcmail-!24ByteDESkey*Str';
// Encryption algorithm. You can use any method supported by OpenSSL. // Encryption algorithm. You can use any method supported by openssl.
// Default is set for backward compatibility to DES-EDE3-CBC, // Default is set for backward compatibility to DES-EDE3-CBC,
// but you can choose e.g. AES-256-CBC which we consider a better choice. // but you can choose e.g. AES-256-CBC which we consider a better choice.
$config['cipher_method'] = 'DES-EDE3-CBC'; $config['cipher_method'] = 'DES-EDE3-CBC';
@ -655,12 +615,9 @@ $config['identities_level'] = 0;
$config['identity_image_size'] = 64; $config['identity_image_size'] = 64;
// Mimetypes supported by the browser. // Mimetypes supported by the browser.
// Attachments of these types will open in a preview window. // attachments of these types will open in a preview window
// Either a comma-separated list or an array. Default list includes: // either a comma-separated list or an array: 'text/plain,text/html,text/xml,image/jpeg,image/gif,image/png,application/pdf'
// text/plain,text/html, $config['client_mimetypes'] = null; # null == default
// image/jpeg,image/gif,image/png,image/bmp,image/tiff,image/webp,
// application/x-javascript,application/pdf,application/x-shockwave-flash
$config['client_mimetypes'] = null;
// Path to a local mime magic database file for PHPs finfo extension. // Path to a local mime magic database file for PHPs finfo extension.
// Set to null if the default path should be used. // Set to null if the default path should be used.
@ -839,6 +796,11 @@ $config['max_pagesize'] = 200;
// Minimal value of user's 'refresh_interval' setting (in seconds) // Minimal value of user's 'refresh_interval' setting (in seconds)
$config['min_refresh_interval'] = 60; $config['min_refresh_interval'] = 60;
// Enables files upload indicator. Requires APC installed and enabled apc.rfc1867 option.
// By default refresh time is set to 1 second. You can set this value to true
// or any integer value indicating number of seconds.
$config['upload_progress'] = false;
// Specifies for how many seconds the Undo button will be available // Specifies for how many seconds the Undo button will be available
// after object delete action. Currently used with supporting address book sources. // after object delete action. Currently used with supporting address book sources.
// Setting it to 0, disables the feature. // Setting it to 0, disables the feature.
@ -850,19 +812,17 @@ $config['compose_responses_static'] = array(
// array('name' => 'Canned Response 2', 'text' => 'Static Response Two'), // array('name' => 'Canned Response 2', 'text' => 'Static Response Two'),
); );
// List of HKP key servers for PGP public key lookups in Enigma/Mailvelope
// Note: Lookup is client-side, so the server must support Cross-Origin Resource Sharing
$config['keyservers'] = array('keys.openpgp.org');
// ---------------------------------- // ----------------------------------
// ADDRESSBOOK SETTINGS // ADDRESSBOOK SETTINGS
// ---------------------------------- // ----------------------------------
// This indicates which type of address book to use. Possible choises: // This indicates which type of address book to use. Possible choises:
// 'sql' - built-in sql addressbook enabled (default), // 'sql' (default), 'ldap' and ''.
// '' - built-in sql addressbook disabled. // If set to 'ldap' then it will look at using the first writable LDAP
// Still LDAP or plugin-added addressbooks will be available. // address book as the primary address book and it will not display the
// BC Note: The value can actually be anything except 'sql', it does not matter. // SQL address book in the 'Address Book' view.
// If set to '' then no address book will be displayed or only the
// addressbook which is created by a plugin (like CardDAV).
$config['address_book_type'] = 'sql'; $config['address_book_type'] = 'sql';
// In order to enable public ldap search, configure an array like the Verisign // In order to enable public ldap search, configure an array like the Verisign
@ -895,7 +855,6 @@ $config['ldap_public']['Verisign'] = array(
// %d - domain (http hostname $_SERVER['HTTP_HOST'] without the first part) // %d - domain (http hostname $_SERVER['HTTP_HOST'] without the first part)
// %z - IMAP domain (IMAP hostname without the first part) // %z - IMAP domain (IMAP hostname without the first part)
// For example %n = mail.domain.tld, %t = domain.tld // For example %n = mail.domain.tld, %t = domain.tld
// Note: Host can also be a full URI e.g. ldaps://hostname.local:636 (for SSL)
'hosts' => array('directory.verisign.com'), 'hosts' => array('directory.verisign.com'),
'port' => 389, 'port' => 389,
'use_tls' => false, 'use_tls' => false,
@ -1092,11 +1051,10 @@ $config['contact_search_name'] = '{name} <{email}>';
// Use this charset as fallback for message decoding // Use this charset as fallback for message decoding
$config['default_charset'] = 'ISO-8859-1'; $config['default_charset'] = 'ISO-8859-1';
// Skin name: folder from skins/ // skin name: folder from skins/
$config['skin'] = 'elastic'; $config['skin'] = 'larry';
// Limit skins available for the user. // limit skins available/shown in the settings section
// Note: When not empty, it should include the default skin set in 'skin' option.
$config['skins_allowed'] = array(); $config['skins_allowed'] = array();
// Enables using standard browser windows (that can be handled as tabs) // Enables using standard browser windows (that can be handled as tabs)
@ -1202,7 +1160,7 @@ $config['refresh_interval'] = 60;
// If true all folders will be checked for recent messages // If true all folders will be checked for recent messages
$config['check_all_folders'] = false; $config['check_all_folders'] = false;
// If true, after message/contact delete/move, the next message/contact will be displayed // If true, after message delete/move, the next message will be displayed
$config['display_next'] = true; $config['display_next'] = true;
// Default messages listing mode. One of 'threads' or 'list'. // Default messages listing mode. One of 'threads' or 'list'.
@ -1250,6 +1208,12 @@ $config['search_mods'] = null; // Example: array('*' => array('subject'=>1, 'fr
// Defaults of the addressbook search field configuration. // Defaults of the addressbook search field configuration.
$config['addressbook_search_mods'] = null; // Example: array('name'=>1, 'firstname'=>1, 'surname'=>1, 'email'=>1, '*'=>1); $config['addressbook_search_mods'] = null; // Example: array('name'=>1, 'firstname'=>1, 'surname'=>1, 'email'=>1, '*'=>1);
// 'Delete always'
// This setting reflects if mail should be always deleted
// when moving to Trash fails. This is necessary in some setups
// when user is over quota and Trash is included in the quota.
$config['delete_always'] = false;
// Directly delete messages in Junk instead of moving to Trash // Directly delete messages in Junk instead of moving to Trash
$config['delete_junk'] = false; $config['delete_junk'] = false;

@ -0,0 +1,27 @@
<?php
/*
+-----------------------------------------------------------------------+
| Roundcube Webmail Selenium Tests Entry Point |
| |
| Copyright (C) 2005-2014, 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: |
| This is the public entry point for all HTTP requests to the |
| Roundcube webmail application loading the 'tests' environment. |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <thomas@roundcube.net> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__) . '/');
$GLOBALS['env'] = 'test';
// include index.php from application root directory
include INSTALL_PATH . 'index.php';

@ -2,9 +2,9 @@
/** /**
+-------------------------------------------------------------------------+ +-------------------------------------------------------------------------+
| Roundcube Webmail IMAP Client | | Roundcube Webmail IMAP Client |
| Version 1.5-git | | Version 1.4-git |
| | | |
| Copyright (C) The Roundcube Dev Team | | Copyright (C) 2005-2018, The Roundcube Dev Team |
| | | |
| This program is free software: you can redistribute it and/or modify | | This program is free software: you can redistribute it and/or modify |
| it under the terms of the GNU General Public License (with exceptions | | it under the terms of the GNU General Public License (with exceptions |
@ -106,9 +106,7 @@ if ($RCMAIL->task == 'login' && $RCMAIL->action == 'login') {
$pass_charset = $RCMAIL->config->get('password_charset', 'UTF-8'); $pass_charset = $RCMAIL->config->get('password_charset', 'UTF-8');
// purge the session in case of new login when a session already exists // purge the session in case of new login when a session already exists
if ($request_valid) { $RCMAIL->kill_session();
$RCMAIL->kill_session();
}
$auth = $RCMAIL->plugins->exec_hook('authenticate', array( $auth = $RCMAIL->plugins->exec_hook('authenticate', array(
'host' => $RCMAIL->autoselect_host(), 'host' => $RCMAIL->autoselect_host(),
@ -182,15 +180,13 @@ if ($RCMAIL->task == 'login' && $RCMAIL->action == 'login') {
$RCMAIL->plugins->exec_hook('login_failed', array( $RCMAIL->plugins->exec_hook('login_failed', array(
'code' => $error_code, 'host' => $auth['host'], 'user' => $auth['user'])); 'code' => $error_code, 'host' => $auth['host'], 'user' => $auth['user']));
if (!isset($_SESSION['user_id'])) { $RCMAIL->kill_session();
$RCMAIL->kill_session();
}
} }
} }
// end session // end session
else if ($RCMAIL->task == 'logout' && isset($_SESSION['user_id'])) { else if ($RCMAIL->task == 'logout' && isset($_SESSION['user_id'])) {
$RCMAIL->request_security_check(rcube_utils::INPUT_GET | rcube_utils::INPUT_POST); $RCMAIL->request_security_check($mode = rcube_utils::INPUT_GET);
$userdata = array( $userdata = array(
'user' => $_SESSION['username'], 'user' => $_SESSION['username'],
@ -209,14 +205,24 @@ else if ($RCMAIL->task == 'logout' && isset($_SESSION['user_id'])) {
else if ($RCMAIL->task != 'login' && $_SESSION['user_id']) { else if ($RCMAIL->task != 'login' && $_SESSION['user_id']) {
if (!$RCMAIL->session->check_auth()) { if (!$RCMAIL->session->check_auth()) {
$RCMAIL->kill_session(); $RCMAIL->kill_session();
$session_error = 'sessionerror'; $session_error = true;
} }
} }
// not logged in -> show login page // not logged in -> show login page
if (empty($RCMAIL->user->ID)) { if (empty($RCMAIL->user->ID)) {
if ($session_error || $_REQUEST['_err'] === 'session' || ($session_error = $RCMAIL->session_error())) { // log session failures
$OUTPUT->show_message($session_error ?: 'sessionerror', 'error', null, true, -1); $task = rcube_utils::get_input_value('_task', rcube_utils::INPUT_GPC);
if ($task && !in_array($task, array('login','logout'))
&& !$session_error && ($sess_id = $_COOKIE[ini_get('session.name')])
) {
$RCMAIL->session->log("Aborted session $sess_id; no valid session data found");
$session_error = true;
}
if ($session_error || $_REQUEST['_err'] == 'session') {
$OUTPUT->show_message('sessionerror', 'error', null, true, -1);
} }
if ($OUTPUT->ajax_call || $OUTPUT->get_env('framed')) { if ($OUTPUT->ajax_call || $OUTPUT->get_env('framed')) {
@ -238,8 +244,7 @@ if (empty($RCMAIL->user->ID)) {
$plugin = $RCMAIL->plugins->exec_hook('unauthenticated', array( $plugin = $RCMAIL->plugins->exec_hook('unauthenticated', array(
'task' => 'login', 'task' => 'login',
'error' => $session_error, 'error' => $session_error,
// Return 401 only on failed logins (#7010) 'http_code' => !$session_error ? 401 : 200
'http_code' => empty($session_error) && !empty($error_message) ? 401 : 200
)); ));
$RCMAIL->set_task($plugin['task']); $RCMAIL->set_task($plugin['task']);

@ -1,19 +1,5 @@
<?php <?php
/**
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
if (!class_exists('rcmail_install', false) || !is_object($RCI)) { if (!class_exists('rcmail_install', false) || !is_object($RCI)) {
die("Not allowed! Please open installer/index.php instead."); die("Not allowed! Please open installer/index.php instead.");
} }
@ -31,12 +17,11 @@ $required_php_exts = array(
'PDO' => 'PDO', 'PDO' => 'PDO',
'Multibyte' => 'mbstring', 'Multibyte' => 'mbstring',
'OpenSSL' => 'openssl', 'OpenSSL' => 'openssl',
'Filter' => 'filter',
'Ctype' => 'ctype',
); );
$optional_php_exts = array( $optional_php_exts = array(
'FileInfo' => 'fileinfo', 'FileInfo' => 'fileinfo',
'Libiconv' => 'iconv',
'Intl' => 'intl', 'Intl' => 'intl',
'Exif' => 'exif', 'Exif' => 'exif',
'LDAP' => 'ldap', 'LDAP' => 'ldap',
@ -75,6 +60,7 @@ $source_urls = array(
'Session' => 'http://www.php.net/manual/en/book.session.php', 'Session' => 'http://www.php.net/manual/en/book.session.php',
'PCRE' => 'http://www.php.net/manual/en/book.pcre.php', 'PCRE' => 'http://www.php.net/manual/en/book.pcre.php',
'FileInfo' => 'http://www.php.net/manual/en/book.fileinfo.php', 'FileInfo' => 'http://www.php.net/manual/en/book.fileinfo.php',
'Libiconv' => 'http://www.php.net/manual/en/book.iconv.php',
'Multibyte' => 'http://www.php.net/manual/en/book.mbstring.php', 'Multibyte' => 'http://www.php.net/manual/en/book.mbstring.php',
'OpenSSL' => 'http://www.php.net/manual/en/book.openssl.php', 'OpenSSL' => 'http://www.php.net/manual/en/book.openssl.php',
'JSON' => 'http://www.php.net/manual/en/book.json.php', 'JSON' => 'http://www.php.net/manual/en/book.json.php',
@ -87,8 +73,6 @@ $source_urls = array(
'GD' => 'http://www.php.net/manual/en/book.image.php', 'GD' => 'http://www.php.net/manual/en/book.image.php',
'Imagick' => 'http://www.php.net/manual/en/book.imagick.php', 'Imagick' => 'http://www.php.net/manual/en/book.imagick.php',
'Zip' => 'http://www.php.net/manual/en/book.zip.php', 'Zip' => 'http://www.php.net/manual/en/book.zip.php',
'Filter' => 'http://www.php.net/manual/en/book.filter.php',
'Ctype' => 'http://www.php.net/manual/en/book.ctype.php',
'pdo_mysql' => 'http://www.php.net/manual/en/ref.pdo-mysql.php', 'pdo_mysql' => 'http://www.php.net/manual/en/ref.pdo-mysql.php',
'pdo_pgsql' => 'http://www.php.net/manual/en/ref.pdo-pgsql.php', 'pdo_pgsql' => 'http://www.php.net/manual/en/ref.pdo-pgsql.php',
'pdo_sqlite' => 'http://www.php.net/manual/en/ref.pdo-sqlite.php', 'pdo_sqlite' => 'http://www.php.net/manual/en/ref.pdo-sqlite.php',

@ -2,12 +2,13 @@
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Roundcube installer client function | | Roundcube installer client function |
| | | |
| This file is part of the Roundcube Webmail client | | This file is part of the Roundcube web development suite |
| Copyright (C) The Roundcube Dev Team | | Copyright (C) 2009-2012, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> | | Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+

@ -1,19 +1,5 @@
<?php <?php
/**
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
if (!class_exists('rcmail_install', false) || !is_object($RCI)) { if (!class_exists('rcmail_install', false) || !is_object($RCI)) {
die("Not allowed! Please open installer/index.php instead."); die("Not allowed! Please open installer/index.php instead.");
} }
@ -104,7 +90,7 @@ $input_support = new html_inputfield(array('name' => '_support_url', 'size' => 5
echo $input_support->show($RCI->getprop('support_url')); echo $input_support->show($RCI->getprop('support_url'));
?> ?>
<div>Provide a URL where a user can get support for this Roundcube installation.<br/>PLEASE DO NOT LINK TO THE ROUNDCUBE.NET WEBSITE HERE!</div> <div>Provide an URL where a user can get support for this Roundcube installation.<br/>PLEASE DO NOT LINK TO THE ROUNDCUBE.NET WEBSITE HERE!</div>
<p class="hint">Enter an absolute URL (including http://) to a support page/form or a mailto: link.</p> <p class="hint">Enter an absolute URL (including http://) to a support page/form or a mailto: link.</p>
</dd> </dd>

Before

Width:  |  Height:  |  Size: 653 B

After

Width:  |  Height:  |  Size: 653 B

Before

Width:  |  Height:  |  Size: 637 B

After

Width:  |  Height:  |  Size: 637 B

Before

Width:  |  Height:  |  Size: 565 B

After

Width:  |  Height:  |  Size: 565 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

@ -3,9 +3,9 @@
/** /**
+-------------------------------------------------------------------------+ +-------------------------------------------------------------------------+
| Roundcube Webmail setup tool | | Roundcube Webmail setup tool |
| Version 1.5-git | | Version 1.4-git |
| | | |
| Copyright (C) The Roundcube Dev Team | | Copyright (C) 2009-2017, The Roundcube Dev Team |
| | | |
| This program is free software: you can redistribute it and/or modify | | This program is free software: you can redistribute it and/or modify |
| it under the terms of the GNU General Public License (with exceptions | | it under the terms of the GNU General Public License (with exceptions |

@ -1,17 +1,4 @@
<?php <?php
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
if (!class_exists('rcmail_install', false) || !is_object($RCI)) { if (!class_exists('rcmail_install', false) || !is_object($RCI)) {
die("Not allowed! Please open installer/index.php instead."); die("Not allowed! Please open installer/index.php instead.");
@ -139,7 +126,7 @@ if ($RCI->configured) {
else { else {
$RCI->fail('DSN (write)', $db_error_msg); $RCI->fail('DSN (write)', $db_error_msg);
echo '<p class="hint">Make sure that the configured database exists and that the user has write privileges<br />'; echo '<p class="hint">Make sure that the configured database exists and that the user has write privileges<br />';
echo 'DSN: ' . rcube::Q($RCI->config['db_dsnw']) . '</p>'; echo 'DSN: ' . $RCI->config['db_dsnw'] . '</p>';
} }
} }
else { else {
@ -152,15 +139,15 @@ else {
// initialize db with schema found in /SQL/* // initialize db with schema found in /SQL/*
if ($db_working && $_POST['initdb']) { if ($db_working && $_POST['initdb']) {
if (!$RCI->init_db($DB)) { if (!($success = $RCI->init_db($DB))) {
$db_working = false; $db_working = false;
echo '<p class="warning">Please try to inizialize the database manually as described in the INSTALL guide. echo '<p class="warning">Please try to inizialize the database manually as described in the INSTALL guide.
Make sure that the configured database extists and that the user as write privileges</p>'; Make sure that the configured database extists and that the user as write privileges</p>';
} }
} }
else if ($db_working && $_POST['updatedb']) { else if ($db_working && $_POST['updatedb']) {
if (!$RCI->update_db($_POST['version'])) { if (!($success = $RCI->update_db($_POST['version']))) {
echo '<p class="warning">Database schema update failed.</p>'; echo '<p class="warning">Database schema update failed.</p>';
} }
} }
@ -178,7 +165,7 @@ if ($db_working) {
echo '<ul style="margin:0"><li>' . join("</li>\n<li>", $err) . "</li></ul>"; echo '<ul style="margin:0"><li>' . join("</li>\n<li>", $err) . "</li></ul>";
$select = $RCI->versions_select(array('name' => 'version')); $select = $RCI->versions_select(array('name' => 'version'));
$select->add('0.9 or newer', ''); $select->add('0.9 or newer', '');
echo '<p class="suggestion">You should run the update queries to get the schema fixed.<br/><br/>Version to update from: ' . $select->show('') . '&nbsp;<input type="submit" name="updatedb" value="Update" /></p>'; echo '<p class="suggestion">You should run the update queries to get the schema fixed.<br/><br/>Version to update from: ' . $select->show() . '&nbsp;<input type="submit" name="updatedb" value="Update" /></p>';
$db_working = false; $db_working = false;
} }
else { else {
@ -189,11 +176,6 @@ if ($db_working) {
// more database tests // more database tests
if ($db_working) { if ($db_working) {
// Using transactions to workaround SQLite bug (#7064)
if ($DB->db_provider == 'sqlite') {
$DB->startTransaction();
}
// write test // write test
$insert_id = md5(uniqid()); $insert_id = md5(uniqid());
$db_write = $DB->query("INSERT INTO " . $DB->quote_identifier($RCI->config['db_prefix'] . 'session') $db_write = $DB->query("INSERT INTO " . $DB->quote_identifier($RCI->config['db_prefix'] . 'session')
@ -209,11 +191,6 @@ if ($db_working) {
} }
echo '<br />'; echo '<br />';
// Transaction end
if ($DB->db_provider == 'sqlite') {
$DB->rollbackTransaction();
}
// check timezone settings // check timezone settings
$tz_db = 'SELECT ' . $DB->unixtimestamp($DB->now()) . ' AS tz_db'; $tz_db = 'SELECT ' . $DB->unixtimestamp($DB->now()) . ' AS tz_db';
$tz_db = $DB->query($tz_db); $tz_db = $DB->query($tz_db);
@ -263,15 +240,6 @@ else {
echo "<br/>"; echo "<br/>";
} }
$smtp_hosts = $RCI->get_hostlist('smtp_server');
if (!empty($smtp_hosts)) {
$smtp_host_field = new html_select(array('name' => '_smtp_host', 'id' => 'smtp_server'));
$smtp_host_field->add($smtp_hosts);
}
else {
$smtp_host_field = new html_inputfield(array('name' => '_smtp_host', 'id' => 'smtp_server'));
}
$user = $RCI->getprop('smtp_user', '(none)'); $user = $RCI->getprop('smtp_user', '(none)');
$pass = $RCI->getprop('smtp_pass', '(none)'); $pass = $RCI->getprop('smtp_pass', '(none)');
@ -279,16 +247,10 @@ if ($user == '%u') {
$user_field = new html_inputfield(array('name' => '_smtp_user', 'id' => 'smtp_user')); $user_field = new html_inputfield(array('name' => '_smtp_user', 'id' => 'smtp_user'));
$user = $user_field->show($_POST['_smtp_user']); $user = $user_field->show($_POST['_smtp_user']);
} }
else {
$user = html::quote($user);
}
if ($pass == '%p') { if ($pass == '%p') {
$pass_field = new html_passwordfield(array('name' => '_smtp_pass', 'id' => 'smtp_pass')); $pass_field = new html_passwordfield(array('name' => '_smtp_pass', 'id' => 'smtp_pass'));
$pass = $pass_field->show(); $pass = $pass_field->show();
} }
else {
$pass = html::quote($pass);
}
?> ?>
@ -299,11 +261,11 @@ else {
<tbody> <tbody>
<tr> <tr>
<td><label for="smtp_server">Server</label></td> <td><label for="smtp_server">Server</label></td>
<td><?php echo $smtp_host_field->show($_POST['_smtp_host']); ?></td> <td><?php echo rcube_utils::parse_host($RCI->getprop('smtp_server', 'localhost')); ?></td>
</tr> </tr>
<tr> <tr>
<td><label for="smtp_port">Port</label></td> <td><label for="smtp_port">Port</label></td>
<td><?php echo rcube::Q($RCI->getprop('smtp_port')); ?></td> <td><?php echo $RCI->getprop('smtp_port'); ?></td>
</tr> </tr>
<tr> <tr>
<td><label for="smtp_user">Username</label></td> <td><label for="smtp_user">Username</label></td>
@ -326,11 +288,8 @@ if (isset($_POST['sendmail'])) {
echo '<p>Trying to send email...<br />'; echo '<p>Trying to send email...<br />';
$smtp_host = trim($_POST['_smtp_host']); $from = idn_to_ascii(trim($_POST['_from']));
$smtp_port = $RCI->getprop('smtp_port'); $to = idn_to_ascii(trim($_POST['_to']));
$from = rcube_utils::idn_to_ascii(trim($_POST['_from']));
$to = rcube_utils::idn_to_ascii(trim($_POST['_to']));
if (preg_match('/^' . $RCI->email_pattern . '$/i', $from) && if (preg_match('/^' . $RCI->email_pattern . '$/i', $from) &&
preg_match('/^' . $RCI->email_pattern . '$/i', $to) preg_match('/^' . $RCI->email_pattern . '$/i', $to)
@ -358,7 +317,8 @@ if (isset($_POST['sendmail'])) {
$head = $mail_object->txtHeaders($send_headers); $head = $mail_object->txtHeaders($send_headers);
$SMTP = new rcube_smtp(); $SMTP = new rcube_smtp();
$SMTP->connect($smtp_host, $smtp_port, $CONFIG['smtp_user'], $CONFIG['smtp_pass']); $SMTP->connect(rcube_utils::parse_host($RCI->getprop('smtp_server')),
$RCI->getprop('smtp_port'), $CONFIG['smtp_user'], $CONFIG['smtp_pass']);
$status = $SMTP->send_mail($headers['From'], $headers['To'], $head, $body); $status = $SMTP->send_mail($headers['From'], $headers['To'], $head, $body);
$smtp_response = $SMTP->get_response(); $smtp_response = $SMTP->get_response();
@ -453,8 +413,8 @@ if (isset($_POST['imaptest']) && !empty($_POST['_host']) && !empty($_POST['_user
$imap_port = 993; $imap_port = 993;
} }
$imap_host = rcube_utils::idn_to_ascii($imap_host); $imap_host = idn_to_ascii($imap_host);
$imap_user = rcube_utils::idn_to_ascii($_POST['_user']); $imap_user = idn_to_ascii($_POST['_user']);
$imap = new rcube_imap(null); $imap = new rcube_imap(null);
$imap->set_options(array( $imap->set_options(array(

@ -3,10 +3,10 @@
{ {
"lib": "jquery", "lib": "jquery",
"name": "jQuery", "name": "jQuery",
"version": "3.4.1", "version": "3.3.1",
"url": "https://code.jquery.com/jquery-$v.min.js", "url": "https://code.jquery.com/jquery-$v.min.js",
"dest": "program/js/jquery.min.js", "dest": "program/js/jquery.min.js",
"sha1": "88523924351bac0b5d560fe0c5781e2556e7693d", "sha1": "0dc32db4aa9c5f03f3b38c47d883dbd4fed13aae",
"license": "MIT", "license": "MIT",
"copyright": "Copyright JS Foundation and other contributors", "copyright": "Copyright JS Foundation and other contributors",
"source": "https://github.com/jquery/jquery/tree/$v" "source": "https://github.com/jquery/jquery/tree/$v"
@ -37,7 +37,7 @@
{ {
"lib": "tinymce", "lib": "tinymce",
"version": "4.8.2", "version": "4.8.2",
"url": "https://download.tiny.cloud/tinymce/community/tinymce_$v.zip", "url": "http://download.ephox.com/tinymce/community/tinymce_$v.zip",
"dest": "program/js", "dest": "program/js",
"sha1": "d7fced05acdeeb78299585ea9909b0de2b3d759d", "sha1": "d7fced05acdeeb78299585ea9909b0de2b3d759d",
"license": "LGPL", "license": "LGPL",
@ -57,27 +57,27 @@
{ {
"lib": "tinymce-langs", "lib": "tinymce-langs",
"version": "4.8.2", "version": "4.8.2",
"url": "https://www.tiny.cloud/docs-4x/language/tinymce4x_languages.zip", "url": "https://tinymce-services.azurewebsites.net/1/i18n/download?langs=ar,hy,az,eu,be,bs,bg_BG,ca,zh_CN,zh_TW,hr,cs,cs_CZ,da,nl,en_CA,en_GB,eo,et,fo,fi,fr_FR,fr_CH,gd,gl,ka_GE,de,de_AT,el,he_IL,hi_IN,hu_HU,is_IS,id,ga,it,ja,kab,km_KH,ko_KR,ku,ku_IQ,lv,lt,lb,mk_MK,ml_IN,nb_NO,oc,fa,fa_IR,pl,pt_BR,pt_PT,ro,ru,sk,sl_SI,es,es_MX,sv_SE,tg,ta,ta_IN,tt,th_TH,tr,tr_TR,ug,uk,uk_UA,vi,vi_VN,cy&extension=.zip",
"dest": "program/js/tinymce" "dest": "program/js/tinymce"
}, },
{ {
"lib": "openpgp", "lib": "openpgp",
"name": "OpenPGP.js", "name": "OpenPGP.js",
"version": "4.4.6", "version": "4.2.1",
"url": "https://raw.githubusercontent.com/openpgpjs/openpgpjs/v$v/dist/openpgp.min.js", "url": "https://raw.githubusercontent.com/openpgpjs/openpgpjs/v$v/dist/openpgp.min.js",
"api_url": "https://api.github.com/repos/openpgpjs/openpgpjs/contents/dist/openpgp.min.js?ref=v$v", "api_url": "https://api.github.com/repos/openpgpjs/openpgpjs/contents/dist/openpgp.min.js?ref=v$v",
"dest": "plugins/enigma/openpgp.min.js", "dest": "plugins/enigma/openpgp.min.js",
"sha1": "e142168db8e666a40fcb4c48ef89c9d774134f8b", "sha1": "5f793a81236614f69d555545cb855c43521d2fa9",
"license": "LGPL", "license": "LGPL",
"copyright": "Copyright (c) OpenPGP Development Team", "copyright": "Copyright (c) OpenPGP Development Team",
"source": "https://github.com/openpgpjs/openpgpjs/blob/v$v/dist/openpgp.js" "source": "https://github.com/openpgpjs/openpgpjs/blob/v$v/dist/openpgp.js"
}, },
{ {
"lib": "codemirror", "lib": "codemirror",
"version": "5.46.0", "version": "5.34.0",
"url": "https://codemirror.net/codemirror-$v.zip", "url": "https://codemirror.net/codemirror-$v.zip",
"dest": "plugins/managesieve/codemirror", "dest": "plugins/managesieve/codemirror",
"sha1": "c11fcb9b63cee2b276e3b9f24a8ad6d7c374c624", "sha1": "24d0834c6a5c4b89c4c82ca2ea31e574b0751b32",
"license": "MIT", "license": "MIT",
"map": { "map": {
"lib": "lib", "lib": "lib",
@ -88,13 +88,12 @@
{ {
"lib": "bootstrap", "lib": "bootstrap",
"name": "Bootstrap", "name": "Bootstrap",
"version": "4.3.1", "version": "4.2.1",
"url": "https://github.com/twbs/bootstrap/releases/download/v$v/bootstrap-$v-dist.zip", "url": "https://github.com/twbs/bootstrap/releases/download/v$v/bootstrap-$v-dist.zip",
"dest": "skins/elastic/deps", "dest": "skins/elastic/deps",
"sha1": "ee9e9d6bbbb6181dc519778af2b38804a6aa62a4", "sha1": "2c80550e423a2500a98d4efbc7d6374cf131495e",
"license": "MIT", "license": "MIT",
"flat": true, "flat": true,
"sourcemap": false,
"map": { "map": {
"bootstrap.bundle.min.js": "bootstrap.bundle.min.js", "bootstrap.bundle.min.js": "bootstrap.bundle.min.js",
"bootstrap.min.css": "bootstrap.min.css" "bootstrap.min.css": "bootstrap.min.css"

@ -1,18 +1,5 @@
/** /**
* ACL plugin script * ACL plugin script
*
* @licstart The following is the entire license notice for the
* JavaScript code in this file.
*
* Copyright (c) The Roundcube Dev Team
*
* The JavaScript code in this page is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* @licend The above is the entire license notice
* for the JavaScript code in this file.
*/ */
if (window.rcmail) { if (window.rcmail) {
@ -202,7 +189,7 @@ rcube_webmail.prototype.acl_list_update = function(html)
// Returns names of users in selected rows // Returns names of users in selected rows
rcube_webmail.prototype.acl_get_usernames = function() rcube_webmail.prototype.acl_get_usernames = function()
{ {
var users = [], n, len, id, row, var users = [], n, len, cell, row,
list = this.acl_list, list = this.acl_list,
selection = list.get_selection(); selection = list.get_selection();
@ -210,8 +197,10 @@ rcube_webmail.prototype.acl_get_usernames = function()
if (this.env.acl_specials.length && $.inArray(selection[n], this.env.acl_specials) >= 0) { if (this.env.acl_specials.length && $.inArray(selection[n], this.env.acl_specials) >= 0) {
users.push(selection[n]); users.push(selection[n]);
} }
else if ((row = list.rows[selection[n]]) && (id = $(row.obj).data('userid'))) { else if (row = list.rows[selection[n]]) {
users.push(id); cell = $('td.user', row.obj);
if (cell.length == 1)
users.push(cell.text());
} }
} }
@ -255,14 +244,15 @@ rcube_webmail.prototype.acl_add_row = function(o, sel)
cl = items[cl]; cl = items[cl];
if (cl == 'user') if (cl == 'user')
td.addClass(cl).attr('title', o.title).append($('<a>').text(o.display)); td.addClass(cl).append($('<a>').text(o.username));
else else
td.addClass(this.className + ' ' + rcmail.acl_class(o.acl, cl)).html('<span/>'); td.addClass(this.className + ' ' + rcmail.acl_class(o.acl, cl)).html('<span/>');
$(this).replaceWith(td); $(this).replaceWith(td);
}); });
row = row.attr({id: 'rcmrow' + id, 'data-userid': o.username}).get(0); row.attr('id', 'rcmrow'+id);
row = row.get(0);
this.env.acl[id] = o.acl; this.env.acl[id] = o.acl;
@ -336,7 +326,7 @@ rcube_webmail.prototype.acl_init_form = function(id)
}); });
if (!this.env.acl_specials.length || $.inArray(id, this.env.acl_specials) < 0) if (!this.env.acl_specials.length || $.inArray(id, this.env.acl_specials) < 0)
val = $(row).data('userid'); val = $('td.user', row).text();
else else
type = id; type = id;
} }

@ -5,7 +5,7 @@
* *
* @author Aleksander Machniak <alec@alec.pl> * @author Aleksander Machniak <alec@alec.pl>
* *
* Copyright (C) Kolab Systems AG * Copyright (C) 2011-2012, Kolab Systems AG
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -407,10 +407,10 @@ class acl extends rcube_plugin
} }
else { else {
$items = array( $items = array(
'read' => 'lrs', 'read' => 'lrs',
'write' => 'wi', 'write' => 'wi',
'delete' => $deleteright, 'delete' => $deleteright,
'other' => preg_replace('/[lrswi'.$deleteright.']/', '', implode($supported)), 'other' => preg_replace('/[lrswi'.$deleteright.']/', '', implode($supported)),
); );
// give plugins the opportunity to adjust this list // give plugins the opportunity to adjust this list
@ -438,19 +438,14 @@ class acl extends rcube_plugin
// filter out virtual rights (c or d) the server may return // filter out virtual rights (c or d) the server may return
$userrights = array_intersect($rights, $supported); $userrights = array_intersect($rights, $supported);
$userid = rcube_utils::html_identifier($user); $userid = rcube_utils::html_identifier($user);
$title = null;
if (!empty($this->specials) && in_array($user, $this->specials)) { if (!empty($this->specials) && in_array($user, $this->specials)) {
$username = $this->gettext($user); $user = $this->gettext($user);
}
else {
$username = $this->resolve_acl_identifier($user, $title);
} }
$table->add_row(array('id' => 'rcmrow' . $userid, 'data-userid' => $user)); $table->add_row(array('id' => 'rcmrow'.$userid));
$table->add(array('class' => 'user text-nowrap', 'title' => $title), $table->add('user', html::a(array('id' => 'rcmlinkrow'.$userid), rcube::Q($user)));
html::a(array('id' => 'rcmlinkrow' . $userid), rcube::Q($username)));
foreach ($items as $key => $right) { foreach ($items as $key => $right) {
$in = $this->acl_compare($userrights, $right); $in = $this->acl_compare($userrights, $right);
@ -520,15 +515,9 @@ class acl extends rcube_plugin
if ($user != $_SESSION['username'] && $username != $_SESSION['username']) { if ($user != $_SESSION['username'] && $username != $_SESSION['username']) {
if ($this->rc->storage->set_acl($mbox, $user, $acl)) { if ($this->rc->storage->set_acl($mbox, $user, $acl)) {
$display = $this->resolve_acl_identifier($username, $title); $ret = array('id' => rcube_utils::html_identifier($user),
$this->rc->output->command('acl_update', array( 'username' => $username, 'acl' => implode($acl), 'old' => $oldid);
'id' => rcube_utils::html_identifier($user), $this->rc->output->command('acl_update', $ret);
'username' => $username,
'title' => $title,
'display' => $display,
'acl' => implode($acl),
'old' => $oldid
));
$result++; $result++;
} }
} }
@ -619,9 +608,8 @@ class acl extends rcube_plugin
} }
} }
if (count($list) == count($supported)) { if (count($list) == count($supported))
return rcube::Q($this->gettext('aclfull')); return rcube::Q($this->gettext('aclfull'));
}
return html::tag('ul', $attrib, implode("\n", $list)); return html::tag('ul', $attrib, implode("\n", $list));
} }
@ -648,15 +636,12 @@ class acl extends rcube_plugin
$cnt1 = count($res); $cnt1 = count($res);
$cnt2 = count($acl2); $cnt2 = count($acl2);
if ($cnt1 == $cnt2) { if ($cnt1 == $cnt2)
return 2; return 2;
} else if ($cnt1)
if ($cnt1) {
return 1; return 1;
} else
return 0;
return 0;
} }
/** /**
@ -802,51 +787,4 @@ class acl extends rcube_plugin
return $user; return $user;
} }
/**
* Resolve acl identifier to user/group name
*/
protected function resolve_acl_identifier($id, &$title = null)
{
if ($this->init_ldap()) {
$groups = $this->rc->config->get('acl_groups');
$prefix = $this->rc->config->get('acl_group_prefix');
$group_field = $this->rc->config->get('acl_group_field', 'name');
// Unfortunately this works only if group_field=name,
// list_groups() allows searching by group name only
if ($groups && $prefix && $group_field === 'name' && strpos($id, $prefix) === 0) {
$gid = substr($id, strlen($prefix));
$result = $this->ldap->list_groups($gid, rcube_addressbook::SEARCH_STRICT);
if (count($result) === 1 && ($record = $result[0])) {
if ($record[$group_field] === $gid) {
$display = $record['name'];
if ($display != $gid) {
$title = sprintf('%s (%s)', $display, $gid);
}
return $display;
}
}
return $id;
}
$this->ldap->set_pagesize('2');
// Note: 'uid' works here because we overwrite fieldmap in init_ldap() above
$result = $this->ldap->search('uid', $id, rcube_addressbook::SEARCH_STRICT);
if ($result->count === 1 && ($record = $result->first())) {
if ($record['uid'] === $id) {
$title = rcube_addressbook::compose_search_name($record);
$display = rcube_addressbook::compose_list_name($record);
return $display;
}
}
}
return $id;
}
} }

@ -3,7 +3,7 @@
"type": "roundcube-plugin", "type": "roundcube-plugin",
"description": "IMAP Folders Access Control Lists Management (RFC4314, RFC2086).", "description": "IMAP Folders Access Control Lists Management (RFC4314, RFC2086).",
"license": "GPLv3+", "license": "GPLv3+",
"version": "1.8", "version": "1.7",
"authors": [ "authors": [
{ {
"name": "Aleksander Machniak", "name": "Aleksander Machniak",

@ -2,20 +2,20 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['username'] = 'المستخدم :'; $labels['username'] = 'المستخدم :';
$labels['advanced'] = 'الوضع المتقدم';
$labels['add'] = 'إضافة'; $labels['add'] = 'إضافة';
$labels['acld'] = 'حذف الرسائل'; $labels['acld'] = 'حذف الرسائل';
$labels['aclt'] = 'حذف الرسائل'; $labels['aclt'] = 'حذف الرسائل';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'مشاركة'; $labels['sharing'] = 'مشاركة';
$labels['myrights'] = 'حقوق الوصول'; $labels['myrights'] = 'حقوق الوصول';
$labels['username'] = 'مستخدم:'; $labels['username'] = 'مستخدم:';
@ -38,7 +39,6 @@ $labels['aclt'] = 'حذف الرسائل';
$labels['acle'] = 'حُذف'; $labels['acle'] = 'حُذف';
$labels['aclx'] = 'حذف المجلد'; $labels['aclx'] = 'حذف المجلد';
$labels['acla'] = 'ادارة'; $labels['acla'] = 'ادارة';
$labels['acln'] = 'التعليق على الرسائل';
$labels['aclfull'] = 'تحكم كامل'; $labels['aclfull'] = 'تحكم كامل';
$labels['aclother'] = 'اخرى'; $labels['aclother'] = 'اخرى';
$labels['aclread'] = 'قراءة '; $labels['aclread'] = 'قراءة ';
@ -57,7 +57,6 @@ $labels['shortaclt'] = 'حذف';
$labels['shortacle'] = 'حُذف'; $labels['shortacle'] = 'حُذف';
$labels['shortaclx'] = 'حذف المجلد'; $labels['shortaclx'] = 'حذف المجلد';
$labels['shortacla'] = 'ادارة'; $labels['shortacla'] = 'ادارة';
$labels['shortacln'] = 'كتابة تعليق';
$labels['shortaclother'] = 'اخرى'; $labels['shortaclother'] = 'اخرى';
$labels['shortaclread'] = 'قراءة '; $labels['shortaclread'] = 'قراءة ';
$labels['shortaclwrite'] = 'كتابة'; $labels['shortaclwrite'] = 'كتابة';
@ -75,14 +74,10 @@ $labels['longaclt'] = 'حذف وسم الرسائل من الممكن تغيير
$labels['longacle'] = 'بالامكان شطب الرسائل'; $labels['longacle'] = 'بالامكان شطب الرسائل';
$labels['longaclx'] = 'هذا المجلد بالامكان حذفة او اعادة تسميته'; $labels['longaclx'] = 'هذا المجلد بالامكان حذفة او اعادة تسميته';
$labels['longacla'] = 'حقوق الوصول لهذا المجلد بالامكان تغييره'; $labels['longacla'] = 'حقوق الوصول لهذا المجلد بالامكان تغييره';
$labels['longacln'] = 'يمكن تغيير البيانات الوصفية (التعليقات) المشتركة بين الرسائل';
$labels['longaclfull'] = 'التحكم الكامل يتضمن ادارة المجلدات'; $labels['longaclfull'] = 'التحكم الكامل يتضمن ادارة المجلدات';
$labels['longaclread'] = 'من الممكن فتح المجلد للقراءة'; $labels['longaclread'] = 'من الممكن فتح المجلد للقراءة';
$labels['longaclwrite'] = 'لا يمكن وضع علامة على الرسائل, كتبت او نسخة الى هذا المجلد'; $labels['longaclwrite'] = 'لا يمكن وضع علامة على الرسائل, كتبت او نسخة الى هذا المجلد';
$labels['longacldelete'] = 'لا يمكن حذف الرسائل'; $labels['longacldelete'] = 'لا يمكن حذف الرسائل';
$labels['longaclother'] = 'حقوق الوصول الأخرى';
$labels['ariasummaryacltable'] = 'قائمة حقوق الوصول';
$labels['arialabelaclform'] = 'نموذج حقوق الوصول';
$messages['deleting'] = 'جاري حذف حقوق الوصول...'; $messages['deleting'] = 'جاري حذف حقوق الوصول...';
$messages['saving'] = 'جاري حفظ حقوق الوصول...'; $messages['saving'] = 'جاري حفظ حقوق الوصول...';
$messages['updatesuccess'] = 'تم تغيير حقوق الوصول بنجاح'; $messages['updatesuccess'] = 'تم تغيير حقوق الوصول بنجاح';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Compartición'; $labels['sharing'] = 'Compartición';
$labels['myrights'] = 'Drechos d\'accesu'; $labels['myrights'] = 'Drechos d\'accesu';
$labels['username'] = 'Usuariu:'; $labels['username'] = 'Usuariu:';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Paylaşma'; $labels['sharing'] = 'Paylaşma';
$labels['myrights'] = 'Giriş hüququ'; $labels['myrights'] = 'Giriş hüququ';
$labels['username'] = 'İstifadəçi:'; $labels['username'] = 'İstifadəçi:';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Сумесны доступ'; $labels['sharing'] = 'Сумесны доступ';
$labels['myrights'] = 'Правы доступу'; $labels['myrights'] = 'Правы доступу';
$labels['username'] = 'Карыстальнік:'; $labels['username'] = 'Карыстальнік:';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Споделяне'; $labels['sharing'] = 'Споделяне';
$labels['myrights'] = 'Права за достъп'; $labels['myrights'] = 'Права за достъп';
$labels['username'] = 'Потребител:'; $labels['username'] = 'Потребител:';

@ -2,19 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['aclread'] = 'পড়'; $labels['aclread'] = 'পড়';
$labels['acldelete'] = 'ফেলে দিন'; $labels['acldelete'] = 'ফেলে দিন';
$labels['shortaclr'] = 'পড়'; $labels['shortaclr'] = 'পড়';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Rannañ'; $labels['sharing'] = 'Rannañ';
$labels['myrights'] = 'Aotreoù mont e-barzh'; $labels['myrights'] = 'Aotreoù mont e-barzh';
$labels['username'] = 'Implijer:'; $labels['username'] = 'Implijer:';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Razmjena'; $labels['sharing'] = 'Razmjena';
$labels['myrights'] = 'Prava pristupa'; $labels['myrights'] = 'Prava pristupa';
$labels['username'] = 'Korisnik:'; $labels['username'] = 'Korisnik:';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Comparteix'; $labels['sharing'] = 'Comparteix';
$labels['myrights'] = 'Permisos d\'accés'; $labels['myrights'] = 'Permisos d\'accés';
$labels['username'] = 'Usuari:'; $labels['username'] = 'Usuari:';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Sdílení'; $labels['sharing'] = 'Sdílení';
$labels['myrights'] = 'Přístupová práva'; $labels['myrights'] = 'Přístupová práva';
$labels['username'] = 'Uživatel:'; $labels['username'] = 'Uživatel:';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Rhannu'; $labels['sharing'] = 'Rhannu';
$labels['myrights'] = 'Hawliau Mynediad'; $labels['myrights'] = 'Hawliau Mynediad';
$labels['username'] = 'Defnyddiwr:'; $labels['username'] = 'Defnyddiwr:';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Deling'; $labels['sharing'] = 'Deling';
$labels['myrights'] = 'Adgangrettigheder'; $labels['myrights'] = 'Adgangrettigheder';
$labels['username'] = 'Bruger:'; $labels['username'] = 'Bruger:';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Freigabe'; $labels['sharing'] = 'Freigabe';
$labels['myrights'] = 'Zugriffsrechte'; $labels['myrights'] = 'Zugriffsrechte';
$labels['username'] = 'Benutzer:'; $labels['username'] = 'Benutzer:';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Freigabe'; $labels['sharing'] = 'Freigabe';
$labels['myrights'] = 'Zugriffsrechte'; $labels['myrights'] = 'Zugriffsrechte';
$labels['username'] = 'Benutzer:'; $labels['username'] = 'Benutzer:';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Κοινή χρήση'; $labels['sharing'] = 'Κοινή χρήση';
$labels['myrights'] = 'Δικαιώματα Πρόσβασης '; $labels['myrights'] = 'Δικαιώματα Πρόσβασης ';
$labels['username'] = 'Χρήστης:'; $labels['username'] = 'Χρήστης:';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Sharing'; $labels['sharing'] = 'Sharing';
$labels['myrights'] = 'Access Rights'; $labels['myrights'] = 'Access Rights';
$labels['username'] = 'User:'; $labels['username'] = 'User:';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Sharing'; $labels['sharing'] = 'Sharing';
$labels['myrights'] = 'Access Rights'; $labels['myrights'] = 'Access Rights';
$labels['username'] = 'User:'; $labels['username'] = 'User:';

@ -2,13 +2,15 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Kunhavigado'; $labels['sharing'] = 'Kunhavigado';
$labels['myrights'] = 'Atingrajtoj'; $labels['myrights'] = 'Atingrajtoj';
$labels['username'] = 'Uzanto:'; $labels['username'] = 'Uzanto:';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Compartiendo'; $labels['sharing'] = 'Compartiendo';
$labels['myrights'] = 'Permisos de acceso'; $labels['myrights'] = 'Permisos de acceso';
$labels['username'] = 'Usuario:'; $labels['username'] = 'Usuario:';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Compartiendo'; $labels['sharing'] = 'Compartiendo';
$labels['myrights'] = 'Permisos de acceso'; $labels['myrights'] = 'Permisos de acceso';
$labels['username'] = 'Usuario:'; $labels['username'] = 'Usuario:';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Compartir'; $labels['sharing'] = 'Compartir';
$labels['myrights'] = 'Permisos de acceso'; $labels['myrights'] = 'Permisos de acceso';
$labels['username'] = 'Usuario:'; $labels['username'] = 'Usuario:';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Jagamine'; $labels['sharing'] = 'Jagamine';
$labels['myrights'] = 'Ligipääsuõigused'; $labels['myrights'] = 'Ligipääsuõigused';
$labels['username'] = 'Kasutaja:'; $labels['username'] = 'Kasutaja:';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Partekatzen'; $labels['sharing'] = 'Partekatzen';
$labels['myrights'] = 'Sarbide-eskubideak'; $labels['myrights'] = 'Sarbide-eskubideak';
$labels['username'] = 'Erabiltzailea:'; $labels['username'] = 'Erabiltzailea:';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'اشتراک گذاری'; $labels['sharing'] = 'اشتراک گذاری';
$labels['username'] = 'کاربر:'; $labels['username'] = 'کاربر:';
$labels['add'] = 'افزودن'; $labels['add'] = 'افزودن';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'اشتراک‌گذاری'; $labels['sharing'] = 'اشتراک‌گذاری';
$labels['myrights'] = 'حقوق دسترسی'; $labels['myrights'] = 'حقوق دسترسی';
$labels['username'] = 'کاربر:'; $labels['username'] = 'کاربر:';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Jakaminen'; $labels['sharing'] = 'Jakaminen';
$labels['myrights'] = 'Käyttöoikeudet'; $labels['myrights'] = 'Käyttöoikeudet';
$labels['username'] = 'Käyttäjä:'; $labels['username'] = 'Käyttäjä:';
@ -21,18 +22,14 @@ $labels['advanced'] = 'Edistynyt tila';
$labels['add'] = 'Lisää'; $labels['add'] = 'Lisää';
$labels['newuser'] = 'LIsää kohde'; $labels['newuser'] = 'LIsää kohde';
$labels['editperms'] = 'Muokkaa oikeuksia'; $labels['editperms'] = 'Muokkaa oikeuksia';
$labels['actions'] = 'Käyttöoikeuksien toiminnot...';
$labels['anyone'] = 'Kaikki käyttäjät (kuka tahansa)'; $labels['anyone'] = 'Kaikki käyttäjät (kuka tahansa)';
$labels['anonymous'] = 'Vieraat (anonyymit)'; $labels['anonymous'] = 'Vieraat (anonyymit)';
$labels['identifier'] = 'Tunniste';
$labels['aclr'] = 'Lue viestit'; $labels['aclr'] = 'Lue viestit';
$labels['aclc'] = 'Luo alikansioita'; $labels['aclc'] = 'Luo alikansioita';
$labels['aclk'] = 'Luo alikansioita'; $labels['aclk'] = 'Luo alikansioita';
$labels['acld'] = 'Poista viestejä'; $labels['acld'] = 'Poista viestejä';
$labels['aclt'] = 'Poista viestejä'; $labels['aclt'] = 'Poista viestejä';
$labels['acle'] = 'Tiivistä';
$labels['aclx'] = 'Poista kansio'; $labels['aclx'] = 'Poista kansio';
$labels['acla'] = 'Hallitse';
$labels['aclfull'] = 'Täydet käyttöoikeudet'; $labels['aclfull'] = 'Täydet käyttöoikeudet';
$labels['aclother'] = 'Muu'; $labels['aclother'] = 'Muu';
$labels['aclread'] = 'Luku'; $labels['aclread'] = 'Luku';
@ -46,24 +43,15 @@ $labels['shortaclc'] = 'Luo';
$labels['shortaclk'] = 'Luo'; $labels['shortaclk'] = 'Luo';
$labels['shortacld'] = 'Poista'; $labels['shortacld'] = 'Poista';
$labels['shortaclt'] = 'Poista'; $labels['shortaclt'] = 'Poista';
$labels['shortacle'] = 'Tiivistä';
$labels['shortaclx'] = 'Kansion poisto'; $labels['shortaclx'] = 'Kansion poisto';
$labels['shortacla'] = 'Hallitse';
$labels['shortaclother'] = 'Muu'; $labels['shortaclother'] = 'Muu';
$labels['shortaclread'] = 'Luku'; $labels['shortaclread'] = 'Luku';
$labels['shortaclwrite'] = 'Kirjoitus'; $labels['shortaclwrite'] = 'Kirjoitus';
$labels['shortacldelete'] = 'Poisto'; $labels['shortacldelete'] = 'Poisto';
$labels['longaclr'] = 'Kansion voi avata lukua varten'; $labels['longaclr'] = 'Kansion voi avata lukua varten';
$labels['longaclp'] = 'Viestejä voidaan lähettää tähän kansioon';
$labels['longaclc'] = 'Kansioita voidaan luoda (tai uudelleennimetä) suoraan tämän kansion alle';
$labels['longaclk'] = 'Kansioita voidaan luoda (tai uudelleennimetä) suoraan tämän kansion alle';
$labels['longacle'] = 'Viestit voidaan tiivistää';
$labels['longaclx'] = 'Kansio voidaan poistaa tai nimetä uudelleen'; $labels['longaclx'] = 'Kansio voidaan poistaa tai nimetä uudelleen';
$labels['longacla'] = 'Kansion käyttöoikeuksia voi muuttaa'; $labels['longacla'] = 'Kansion käyttöoikeuksia voi muuttaa';
$labels['longaclread'] = 'Kansion voi avata lukua varten'; $labels['longaclread'] = 'Kansion voi avata lukua varten';
$labels['longacldelete'] = 'Viestit voidaan poistaa';
$labels['longaclother'] = 'Muut käyttöoikeudet';
$labels['ariasummaryacltable'] = 'Lista käyttöoikeuksista';
$labels['arialabelaclactions'] = 'Listatoiminnot'; $labels['arialabelaclactions'] = 'Listatoiminnot';
$messages['deleting'] = 'Poistetaan käyttöoikeuksia...'; $messages['deleting'] = 'Poistetaan käyttöoikeuksia...';
$messages['saving'] = 'Tallennetaan käyttöoikeuksia...'; $messages['saving'] = 'Tallennetaan käyttöoikeuksia...';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Deiling'; $labels['sharing'] = 'Deiling';
$labels['myrights'] = 'Atgongdar-rættindi'; $labels['myrights'] = 'Atgongdar-rættindi';
$labels['username'] = 'Brúkari:'; $labels['username'] = 'Brúkari:';

@ -2,18 +2,19 @@
/* /*
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
| Localization file of the Roundcube Webmail ACL plugin | | plugins/acl/localization/<lang>.inc |
| | | |
| Copyright (C) The Roundcube Dev Team | | Localization file of the Roundcube Webmail ACL plugin |
| Copyright (C) 2012-2013, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. | | See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/ For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-acl/
*/ */
$labels['sharing'] = 'Partage'; $labels['sharing'] = 'Partage';
$labels['myrights'] = 'Droits daccès'; $labels['myrights'] = 'Droits daccès';
$labels['username'] = 'Utilisateur :'; $labels['username'] = 'Utilisateur :';
@ -21,7 +22,7 @@ $labels['advanced'] = 'Mode avancé';
$labels['add'] = 'Ajouter'; $labels['add'] = 'Ajouter';
$labels['newuser'] = 'Ajouter une entrée'; $labels['newuser'] = 'Ajouter une entrée';
$labels['editperms'] = 'Modifier les permissions'; $labels['editperms'] = 'Modifier les permissions';
$labels['actions'] = 'Actions des droits daccès'; $labels['actions'] = 'Actions des droits daccès...';
$labels['anyone'] = 'Tous les utilisateurs (nimporte qui)'; $labels['anyone'] = 'Tous les utilisateurs (nimporte qui)';
$labels['anonymous'] = 'Invités (anonyme)'; $labels['anonymous'] = 'Invités (anonyme)';
$labels['identifier'] = 'Identifiant'; $labels['identifier'] = 'Identifiant';
@ -82,7 +83,7 @@ $labels['longaclwrite'] = 'Les courriels peuvent-être marqués, écrits ou copi
$labels['longacldelete'] = 'Les courriels peuvent être supprimés'; $labels['longacldelete'] = 'Les courriels peuvent être supprimés';
$labels['longaclother'] = 'Autres droits daccès'; $labels['longaclother'] = 'Autres droits daccès';
$labels['ariasummaryacltable'] = 'Liste de droits daccès'; $labels['ariasummaryacltable'] = 'Liste de droits daccès';
$labels['arialabelaclactions'] = 'Actions de listage'; $labels['arialabelaclactions'] = 'Lister les actions';
$labels['arialabelaclform'] = 'Formulaire de droits daccès'; $labels['arialabelaclform'] = 'Formulaire de droits daccès';
$messages['deleting'] = 'Suppression des droits daccès…'; $messages['deleting'] = 'Suppression des droits daccès…';
$messages['saving'] = 'Enregistrement des droits daccès…'; $messages['saving'] = 'Enregistrement des droits daccès…';
@ -93,6 +94,6 @@ $messages['updateerror'] = 'Impossible de mettre à jour les droits daccès';
$messages['deleteerror'] = 'Impossible de supprimer les droits daccès'; $messages['deleteerror'] = 'Impossible de supprimer les droits daccès';
$messages['createerror'] = 'Impossible dajouter des droits daccès'; $messages['createerror'] = 'Impossible dajouter des droits daccès';
$messages['deleteconfirm'] = 'Êtes-vous certain de vouloir retirer les droits daccès des utilisateurs sélectionnés?'; $messages['deleteconfirm'] = 'Êtes-vous certain de vouloir retirer les droits daccès des utilisateurs sélectionnés?';
$messages['norights'] = 'Aucun droit na été indiqué'; $messages['norights'] = 'Aucun droit na été spécifié!';
$messages['nouser'] = 'Aucun nom dutilisateur na été indiqué'; $messages['nouser'] = 'Aucun nom dutilisateur na été spécifié!';
?> ?>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save