Compare commits

..

354 Commits

Author SHA1 Message Date
Thomas 4af76d20ca Bump version 11 years ago
Aleksander Machniak 8d5832fe96 Fix failing vCard import when email address field contains spaces (#1489386) 11 years ago
Thomas 9f0bbeb7e7 Change default spell-check URI after Google suspended their spell service 11 years ago
Aleksander Machniak 4109bb26ce Fix vulnerability in handling _session argument of utils/save-prefs (#1489382) 11 years ago
Aleksander Machniak f2d4e40f09 Do not add css files to the page when body is empty, e.g. upload iframes 11 years ago
Aleksander Machniak 5aa6f6203d Fix iframe onload for upload errors handling (#1489379) 11 years ago
Aleksander Machniak acbf6eede6 Fix address matching in Return-Path header on identity selection (#1489374)
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak 571aa9b04e Fix text wrapping issue with long unwrappable lines (#1489371)
Conflicts:

	CHANGELOG
11 years ago
Thomas 42173df79e Updated Ukrainian translation as submitted by Vladislav 11 years ago
Aleksander Machniak 68f4b54ccf Update changelog 11 years ago
Aleksander Machniak 57b44d2339 Fix typo: occured -> occurred (#1489366)
Conflicts:

	CHANGELOG
	installer/rcube_install.php
11 years ago
Aleksander Machniak bdc515d35c Fixed issues where HTML comments inside style tag would hang Internet Explorer
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak 9919c2e68c Update changelog 11 years ago
Aleksander Machniak 065fdbaa65 Fix setting domain in virtualmin password driver (#1489332) 11 years ago
Aleksander Machniak 62fe7203e6 Hide Delivery Status Notification option when smtp_server is unset (#1489336)
Conflicts:

	CHANGELOG
	config/main.inc.php.dist
11 years ago
Aleksander Machniak 7f1218caea Display full attachment name using title attribute when name is too long to display (#1489320)
Conflicts:

	CHANGELOG
	program/steps/mail/show.inc
11 years ago
Aleksander Machniak 256d5b7216 In password virtualmin driver removed support for username in format based on user alias (#1489332)
Conflicts:

	plugins/password/config.inc.php.dist
11 years ago
Aleksander Machniak b8c2554f1f Update releases list 11 years ago
Aleksander Machniak b403ede321 Fix attachment icon issue when rare font/language is used (#1489326)
Conflicts:

	CHANGELOG
	skins/larry/styles.css
11 years ago
Aleksander Machniak e02bfe0831 Fix expanded thread root message styling after refreshing messages list (#1489327) 11 years ago
Aleksander Machniak 63ec68b026 Fix de_DE localization of "About" label in Help plugin (#1489325) 11 years ago
Aleksander Machniak 6632d42717 Fix issue where From address was removed from Cc and Bcc fields when editing a draft (#1489319)
Conflicts:

	CHANGELOG
11 years ago
Thomas B. d499f06613 Remove unstable warning 11 years ago
Aleksander Machniak 6a76f22759 Fix error_reporting directive check (#1489323)
Conflicts:

	CHANGELOG
	program/lib/Roundcube/bootstrap.php
11 years ago
Thomas Bruederli 4b125969ae Move these two fixes to the 0.9.4 release 11 years ago
Aleksander Machniak 93adce7abf Make identities matching case insensitive (#1485480) 11 years ago
Aleksander Machniak 262f485538 Fix issue where too big message data was stored in cache causing sql errors (#1489316)
Conflicts:

	CHANGELOG
11 years ago
Thomas Bruederli 183c7ffd32 Bump version and update Changelog 11 years ago
Thomas Bruederli d3cceb4882 Fix iframe scrollbars on webkit browsers (#1489306) 11 years ago
Aleksander Machniak 74adada93c Fix issue where legacy config was overriden by default config (#1489288)
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak c9e1e386e1 Fix newmail_notifier issue where favicon wasn't changed back to default (#1489313) 11 years ago
Aleksander Machniak c1a0b07242 Fix setting of Junk and NonJunk flags by markasjunk plugin (#1489285)
Added possibility to register flag mappings by a plugin.

Conflicts:

	plugins/markasjunk/markasjunk.php
	program/lib/Roundcube/rcube_imap_generic.php
11 years ago
Aleksander Machniak 5df7179b32 Fix lack of Reply-To address in header of forwarded message body (#1489298) 11 years ago
Aleksander Machniak 4fbbd81b9b Fix bugs when invoking contact creation form when read-only addressbook is selected (#1489296) 11 years ago
Aleksander Machniak 652577d1fe Fix wrong close tag in /template/mail.html (#1489295) 11 years ago
Aleksander Machniak 3d0003dbdf Fixed variable name (changed unintentionally in last backporting commit) 11 years ago
Aleksander Machniak 5fd90b9a6b Fix identity selection on reply (#1489291) 11 years ago
Aleksander Machniak 70eac89a5c Fix so additional headers are added to all messages sent (#1489284)
Conflicts:

	plugins/additional_message_headers/additional_message_headers.php
	program/lib/Roundcube/rcube.php
11 years ago
Aleksander Machniak eae2a1e684 Fix display issue after moving folder in Folder Manager (#1489293)
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak e15869a979 Fix small style glitch on first toolbar button in recent Firefox 11 years ago
Aleksander Machniak 4db26a430b Fix handling of non-default date formats (#1489294)
- remove ambiguous m/d/Y format from default config

Conflicts:

	CHANGELOG
	config/main.inc.php.dist
	program/lib/Roundcube/rcube_utils.php
	tests/Framework/Utils.php
11 years ago
Aleksander Machniak 6e14fcf9bf Fix Junk folder icon alignment when it's nested in inbox folder (#1489292)
- reverted commit 856ec447fa which shouldn't
  be cherry-picked from master
11 years ago
Aleksander Machniak 06efad1ac8 Fix last commit conflict 11 years ago
Aleksander Machniak e9c5b9f096 Fix unquoted path in PREG expression on Windows (#1489290)
Conflicts:

	CHANGELOG
	program/lib/Roundcube/bootstrap.php
11 years ago
Thomas Bruederli a6f5a68880 Include last fix in 0.9.3 release 11 years ago
Aleksander Machniak 896aa0d604 - Fix setting refresh_interval to "Never" in Preferences (#1489286)
Conflicts:

	CHANGELOG
11 years ago
Thomas Bruederli 0e3f0ad9c9 Fix touch check when IE doesn't specify the event object 11 years ago
Thomas Bruederli 5a3eb6fdeb Bump version for next release 11 years ago
Thomas Bruederli debd0f8515 Let the framework adjust the include_path if necessary 11 years ago
Thomas Bruederli c9192c1c73 Make session auth cookie name configurable 11 years ago
Thomas Bruederli d1c40bbd87 Distinguish mobile/tablet/touch devices 11 years ago
Thomas Bruederli 680d0ec072 Update changelog 11 years ago
Thomas Bruederli ed478cf064 Fix scrolling in iframes on touch devices 11 years ago
Thomas Bruederli cf89e87eff Updated changelog 11 years ago
Thomas Bruederli 341fa8b9a6 Merge branch 'release-0.9' of github.com:roundcube/roundcubemail into release-0.9 11 years ago
Thomas Bruederli 96c4b9098b Optimize list events for touch devices 11 years ago
Thomas Bruederli deacf16bee Make thread toggles work on touch devices 11 years ago
Aleksander Machniak f4ba655a41 Fix purge action in folder manager (#1489280)
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak 216fdb891a Fix base URL resolving on attribute values with no quotes (#1489275) 11 years ago
Aleksander Machniak 17f11330f8 Fix wrong handling of links with '|' character (#1489276)
Conflicts:

	CHANGELOG
	tests/Framework/StringReplacer.php
11 years ago
Aleksander Machniak 6d26369021 Fix XSS vulnerability when saving HTML signatures (#1489251)
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak 5591a63d70 Fix colorspace issue on image conversion using ImageMagick (#1489270) - s/RGB/sRGB/ 11 years ago
Aleksander Machniak 254af68cd8 Fix broken (in 93b0a30c1c) text/plain body of a message when using "edit as new" 11 years ago
Aleksander Machniak f2d12f4363 Fix fatal error when opening non-existing message in compose window 11 years ago
Aleksander Machniak 276ea5fcae Fix XSS vulnerability when editing a message "as new" or draft (#1489251) - added HTML content "washing"
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak a67ad15d2f Support special Return-Path form used on some (PEAR) mailing list (#1489241) 11 years ago
Aleksander Machniak dfaf8c5b8c - Fix rewrite rule in .htaccess (#1489240) 11 years ago
Aleksander Machniak addbb83521 Fixed some StringReplacer tests 11 years ago
Aleksander Machniak 7adcd62f62 - Fix detecting Turkish language in ISO-8859-9 encoding (#1489252) 11 years ago
Thomas Bruederli cd0633cf52 Updated changelog 11 years ago
Thomas Bruederli ccce3cce3a Fix identity-selection using Return-Path headers (#1489241) 11 years ago
Thomas Bruederli 08f5bbd26b Updated Changelog 11 years ago
Thomas Bruederli 8f14c5e1eb Fix parsing of links with ... in URL (#1489192) 11 years ago
Thomas Bruederli 7df4db0b4f Better check for priority header 11 years ago
Thomas Bruederli 0d1f9ebe6a Fix priority selector when open in new window (#1489257) 11 years ago
Thomas Bruederli 8b31b0b6b4 Avoid session timeouts with memcache backend as proposed by D. Carter via users mailing list 11 years ago
Aleksander Machniak fc5ce4758d Fix identity selection when opening extwindow from compose window 11 years ago
Aleksander Machniak 39d14ee22b Fix bug where signature wasn't changed on identity selection when editing a draft (#1489229)
Conflicts:

	program/js/app.js
11 years ago
Aleksander Machniak 0cf43e310c Fix IMAP SETMETADATA parameters quoting (#1489231)
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak 00c2a90f69 Fix "could not load message" error on valid empty message body (#1489228)
Conflicts:

	CHANGELOG
11 years ago
Thomas Bruederli e6a7be8b1f Don't add filters for required fields which are already in search filter 11 years ago
Aleksander Machniak c3fe8a0b7a Fix conflicts in last commit 11 years ago
Aleksander Machniak e6b6925b67 Fix handling of message/rfc822 attachments on message forward and edit (#1489214)
Conflicts:

	CHANGELOG
	program/steps/mail/compose.inc
11 years ago
Aleksander Machniak dc33646971 Remove sqlite 2.x requirement 11 years ago
Aleksander Machniak 88e49b37f7 Fix parsing of square bracket characters in IMAP response strings (#1489223)
Conflicts:

	program/lib/Roundcube/rcube_imap_generic.php
11 years ago
Thomas Bruederli 440b58b476 Fix binary data upload with jQuery.ajax() 11 years ago
Aleksander Machniak c78a652746 Don't clear References and in-Reply-To when a message is "edited as new" (#1489216)
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak 6913c0ae86 Fix message list sort with THREADS=REFS and sort column other than "None" or "Sent date" 11 years ago
Aleksander Machniak d2fa254d90 Fix messages list sorting with THREAD=REFS
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak 357dc97228 Fix handling of &, <, > characters in scripts/filter names (#1489208) 11 years ago
Aleksander Machniak daa131395e Remove deprecated (in PHP 5.5) PREG /e modifier usage (#1489174) 11 years ago
Aleksander Machniak 2f98161392 Fix empty messages list when register_globals is enabled (#1489157)
Conflicts:

	CHANGELOG
11 years ago
Victor Benincasa 856ec447fa Fix Junk folder alignment when it's nested in inbox folder. 11 years ago
Aleksander Machniak e221786bbe Remove confusing note about closing ?> tag and no characters after it.
We currently do not require closing tag in config file, we also
correctly handle characters after the closing tag (#1489179)
11 years ago
Aleksander Machniak 738c446078 Fix so valid and set date.timezone is not required by installer checks (#1489180) 11 years ago
Thomas Bruederli 6376aaff0c Remove unfinished development plugin from release branch 11 years ago
Aleksander Machniak b96be346de Canonize boolean ini_get() results (#1489189)
Conflicts:

	CHANGELOG
	program/lib/Roundcube/rcube.php
11 years ago
Aleksander Machniak 2bc814eed5 Add note about possible connection errors when using ssl with smtp_timeout>0 (#1489187) 11 years ago
Aleksander Machniak 8b81c61396 Fix so install do not fail when one of DB driver checks fails but other drivers exist (#1489178) 11 years ago
Aleksander Machniak dd12eec622 Fix so exported vCard specifies encoding in v3-compatible format (#1489183)
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak 85f756737f Fix messages list column dragging after changing column/sort settings 11 years ago
Thomas Bruederli 73c702c4d1 Display '(empty subject)' in message view if subject header is missing (#1489108) 11 years ago
Aleksander Machniak 70ef48c2f3 Remove old enable_caching option from Installer 11 years ago
Aleksander Machniak 853d0ab2a4 Fix version selector - do not list versions newer than 0.9.0, use
"0.9 or newer" instead.

Conflicts:

	installer/rcube_install.php
11 years ago
Thomas Bruederli 1f5557817f Update changelog + bump version number 11 years ago
Thomas Bruederli b5c6850732 Updated translations from Transifex 11 years ago
Thomas Bruederli 50d0a12933 Add styles for image thumbnails in print mode (#1489134) 11 years ago
Thomas Bruederli 63049afbfe Set minimum height for message headers block (#1489108) 11 years ago
Aleksander Machniak 36d5e8a7c3 Fix timeout issue on drag&drop uploads (#1489170)
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak 35b0a75f72 Fix default sorting of threaded list when THREAD=REFS isn't supported.
The result need to be re-sorted even if sort column is not set. This fixes
the issue when new messages aren't displayed on top of the list.
11 years ago
Aleksander Machniak 04f841e900 Fix list mode switch to 'List' after saving list settings in Larry skin (#1489164) 11 years ago
Aleksander Machniak acb4b71ce5 Fix error when there's no writeable addressbook source (#1489162)
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak b9139f9f98 Fix parse error in broken last commit 11 years ago
Aleksander Machniak 057b9e3e7f Fix zipdownload plugin issue with filenames charset (#1489156)
Conflicts:

	CHANGELOG
	plugins/zipdownload/zipdownload.php
11 years ago
Aleksander Machniak aafc0a3d24 Fix so non-inline images aren't skipped on forward (#1489150)
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak 55e60c6d85 Fix legacy options handling
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak 4257444957 Fix "null" instead of empty string on messages list in IE10 (#1489145) 11 years ago
Aleksander Machniak 0a7df4a32e Fix so bounces addresses in Sender headers are skipped on Reply-All (#1489011) 11 years ago
Aleksander Machniak ab05ee25c1 Fix backward copat. with cached values serialized but not base64-encoded (#1489142) 11 years ago
Aleksander Machniak 72c8504b99 Fix bug where serialized strings were truncated in PDO::quote() (#1489142)
Conflicts:

	CHANGELOG
	program/lib/Roundcube/rcube_cache_shared.php
11 years ago
Aleksander Machniak 6213c6a6e1 Fix removing flags from serialized object before saving it in DB 11 years ago
Aleksander Machniak 1fe7d6ad75 Fix displaying messages with invalid self-closing HTML tags (#1489137) 11 years ago
Aleksander Machniak f5fac810dd Fix PHP warning when responding to a message with many Return-Path headers (#1489136)
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak e12ac4e9b5 Backport popup windows size fixes from master 11 years ago
Aleksander Machniak ecbc8770c6 Fix unintentional compose window resize (#1489114)
Conflicts:

	program/js/app.js
11 years ago
Aleksander Machniak f031cb6c5e Fix performance regression in text wrapping function (#1489133) - don't use iconv here 11 years ago
Aleksander Machniak 983308e8b3 Fix connection to posgtres db using unix socket (#1489132)
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak 7b81cdb8e3 Fix washtml test after "unsupported node type" fix 11 years ago
Aleksander Machniak 40d1f99cb2 Fix handling of comma when adding contact from contacts widget (#1489107) 11 years ago
Aleksander Machniak 1a9d466ef3 Fix bug where a message was opened in both preview pane and new window on double-click (#1489122) 11 years ago
Aleksander Machniak f1c0c05223 Fix fatal error when xdebug.max_nesting_level was exceeded in rcube_washtml (#1489110) 11 years ago
Aleksander Machniak ace518fa6e Fix PHP warning in html_table::set_row_attribs() in PHP 5.4 (#1489094) 11 years ago
Aleksander Machniak 62766c9665 Print nicer error message when too old PHP version found - required by mysql driver (#1489099) 11 years ago
Aleksander Machniak 2f39634b0a Fix invalid option selected in default_font selector when font is unset (#1489112) 11 years ago
Aleksander Machniak e3cbe5dd62 Fix displaying contact with ID divisible by 100 in sql addressbook (#1489121) 11 years ago
Aleksander Machniak c79a7b734e Fix browser warnings on PDF plugin detection (#1489118) 11 years ago
Aleksander Machniak 9312ba2cb6 Fix fatal error when parsing UUencoded messages (#1489119)
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak 20df06be5d Fix another text wrapping issue (wrong handling of long unwrappable lines) 11 years ago
Aleksander Machniak 656005f056 Catch warning on is_readable() failure (open_basedir restriction) 11 years ago
Aleksander Machniak d16f90a1e2 Add 0.9.1 to releases list 11 years ago
Thomas Bruederli e68942c65b Better German labels for from/to headers to avoid conflicts with 'sender' (#1489084) 11 years ago
Aleksander Machniak 193d385f00 Small fix to the printed debug message 11 years ago
Aleksander Machniak 6b6209b587 Bump version number here too 11 years ago
Thomas Bruederli 57323253f7 Update localizations from Transifex 11 years ago
Thomas Bruederli cd9801234b Add composer.json template in preparation for the new plugin repository 11 years ago
Thomas Bruederli 917f5e9eb1 Bump version for next release 11 years ago
Aleksander Machniak 05b5f969d5 Fix problem where security warning was displayed for valid images with image/jpg type (#1489097) 11 years ago
Aleksander Machniak bde85428d6 Fix handling of invalid email addresses in headers (#1489092)
Conflicts:

	CHANGELOG
	program/steps/mail/func.inc
11 years ago
Aleksander Machniak 71ec1b6063 Fix format=flowed text re-wrapping for display 11 years ago
Aleksander Machniak c8f5588c8a Fix IMAP connection issue with default_socket_timeout < 0 and imap_timeout < 0 (#1489090) 11 years ago
Aleksander Machniak 187cf5e1cd Fix various PHP code bugs found using static analysis (#1489086)
Conflicts:

	plugins/enigma/enigma.php
	plugins/enigma/lib/enigma_engine.php
11 years ago
Aleksander Machniak 78c270c9f2 Fix bugs caught by static analysis 11 years ago
Aleksander Machniak e4f288c3fe Fix backslash character handling on vCard import (#1489085) 11 years ago
Aleksander Machniak ac2df4e658 Fix csv import from Thunderbird with French localization (#1489059) 11 years ago
Zou Guangxian 13a77deef4 * fixed: modsecurity warning: AppDefect: Cache-Control Response Header Missing 'no-store' flag. http://websecuritytool.codeplex.com/wikipage?title=Checks#http-cache-control-header-no-store 11 years ago
Aleksander Machniak af4185be64 Implemented updatecss.sh script for background images cache issues fix (#1489047) 11 years ago
Aleksander Machniak 2f5495763b Fix messages list focus issue in Opera and Webkit (#1489058)A
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak 56aeedd9cd Fix bug where multi-level quoting was replaced with one-level quoted text after format=flowed wrapping 11 years ago
Aleksander Machniak c067bb55df Fix another text wrap issue (added test case) 11 years ago
Aleksander Machniak fedbd431c2 Remove changelog entry of reverted change
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak b7770e69fd Revert fix for #1489058 because it opened another IE8 focus issue 11 years ago
Thomas Bruederli 2d6dca4714 Escape user input values when used in eval() 11 years ago
Aleksander Machniak 283ac97852 Fix Reply-To header handling in Reply-All action (#1489037) 11 years ago
Aleksander Machniak 9b82062f5a Fix so Sender: address is added to Cc: field on reply to all (#1489011) 11 years ago
Aleksander Machniak 62fe548e08 Fix so addressbook_search_mode works also for group search (#1489079) 11 years ago
Aleksander Machniak 54c6d6a943 Fix removal of a contact from a group in LDAP addressbook (#1489081)
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak 410a4c663e Inlcude SQL query in the log on SQL error (#1489064) 11 years ago
Aleksander Machniak 9712d2240a Fix handling untagged responses in IMAP FETCH - "could not load message" error (#1489074) 11 years ago
Aleksander Machniak 6c3e466c74 Update changelog 11 years ago
Thomas Bruederli 5bc49fa22a Remove moveTo() call which causes problems in Chrome and has no real effect in other browsers (#1488931) 11 years ago
Aleksander Machniak fb2f066370 Catch possible "Permission denied" error on iframe elements in IE 11 years ago
Aleksander Machniak af98eb046f Fix list page reset when viewing a message in Larry skin (#1489076) 11 years ago
Aleksander Machniak 8eb66e38c9 Fix min_refresh_interval handling on preferences save (#1489073) 11 years ago
Aleksander Machniak 967860765c Fix PDF support detection for Firefox PDF.js (#1488972) 11 years ago
Aleksander Machniak cf3f125784 Fix messages list focus issue in Internet Explorer (#1489058)
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak ecc1b3bd5e Fix possible collision in generated thumbnail cache key (#1489069) 11 years ago
Aleksander Machniak b542f8800e Fix exit code on bootsrap errors in CLI mode (#1489044) 11 years ago
Aleksander Machniak ae0c133d45 Fix error handling in CLI mode, use STDERR and non-empty exit code (#1489043)
Conflicts:

	program/lib/Roundcube/rcube.php
11 years ago
Thomas Bruederli 23ea51e98d Extend fetched header block to 32K, require one of subjct, from or to headers 11 years ago
Aleksander Machniak 4571305398 Fix error when using check_referer=true 11 years ago
Aleksander Machniak 32229952ed Add note about required MSSQL database language settings 11 years ago
Aleksander Machniak 17fb6ee986 Fix incorrect handling of some specific links (#1489060)
Conflicts:

	program/lib/Roundcube/rcube_string_replacer.php
11 years ago
Aleksander Machniak a2446d9296 Fix another text wrapping issue 11 years ago
Aleksander Machniak 102b08c6a2 Fix incorrect handling of leading spaces in text wrapping 11 years ago
Aleksander Machniak f55bfe096d Fix unintentional messages list jumps on click in Internet Explorer (#1489056) 11 years ago
Aleksander Machniak 037f4c27c2 Fix a typo 11 years ago
Aleksander Machniak dbb86df538 Add 0.9.0 to releases list 11 years ago
Aleksander Machniak 2bed05d60a Fix list of required configuration options (#1489055). Removed support_url, and db_table_* 11 years ago
Aleksander Machniak 59997a3030 Fix DB error when creating a new contact and a group is selected (#1489051) 11 years ago
Aleksander Machniak 8b8462018a Fix handling of deprecated boolean value of reply_mode option (#1489052)
Conflicts:

	CHANGELOG
11 years ago
Victor Benincasa 9824e212cc Fix typos
Allows the new_user_dialog plugin to work properly
11 years ago
Aleksander Machniak 51f52b525b Add rcube_db::escape() method, fix escapeSimple() to use escape instead of quote() 11 years ago
Aleksander Machniak 7af32a95bb Fix typo simpleEscape -> escapeSimple 11 years ago
Aleksander Machniak 82f1c77847 Fix links to PHP PDO drivers manual 11 years ago
Aleksander Machniak fa04e19be3 CS fixes (converted tabs to spaces) 11 years ago
Aleksander Machniak d8752c9839 Add rcube_db::escapeSimple() method for backward compat. 11 years ago
Aleksander Machniak ebaf850afa Remove redundant ini checks 11 years ago
Thomas Bruederli a7db8f93ef Bump version to 0.9-stable 11 years ago
Aleksander Machniak d83e12a620 Fix display of HTML entities in protected folder name (#1489042) 11 years ago
Thomas Bruederli 8289923552 Fix ticket reference 11 years ago
Thomas Bruederli a32682f3db Updated changelog 11 years ago
Thomas Bruederli 2741d8eced Set minimal permissions to temp files (#148899) 11 years ago
Thomas Bruederli 706d3f472f Skip filename suffix check for embedded images; return blocked.gif instead of HTML warning when embedded (#1489029) 11 years ago
Aleksander Machniak 6f4b50abea Fix handling of invalid characters in message headers and output (#1489032)
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak 9404f4a7a6 Fix selecting collapsed rows when using selection with Shift/Ctrl key 11 years ago
Aleksander Machniak 84243db8c7 Fix selecting collapsed rows on select-all (#1489036)
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak d2d8d498c6 Fix copying messages to a folder with "empty" name e.g. "0", better error handling 11 years ago
Thomas Bruederli e152227571 Update changelog 11 years ago
Thomas Bruederli b2c66d0331 Hack to reset PDO statement iterators after counting 11 years ago
Thomas Bruederli bd723e565d Fix typo 11 years ago
Thomas Bruederli 8d7f8c8c79 Check for exact matching session keys before splitting into path segments. Adds backwards-compatibility after commit f0a7159c 11 years ago
Thomas Bruederli d6cbdea04d Add methods to append certain nodes to session data in order to avoid session saving race conditions. Fixes #1488422 11 years ago
Aleksander Machniak ea002b6d76 Fix possible header duplicates when using additional headers (#1489033) 11 years ago
Aleksander Machniak 334784a051 Skip message/rfc822 attachments only in reply mode 11 years ago
Aleksander Machniak d74b410697 Fix session issues with use_https=true (#1488986) 11 years ago
Aleksander Machniak f3739dc729 Fix empbedded warning icon 11 years ago
Aleksander Machniak 4dd9bb4671 Fix blockquote width in sent mail (#1489031) 11 years ago
Aleksander Machniak d22ef3f480 Update releases list 11 years ago
Aleksander Machniak 60fd3c8b5f Fix keyboard events on list widgets in Internet Explorer (#1489025) - It was a regression in fix for #1489008 11 years ago
Aleksander Machniak bb13a88054 Remove unwanted horizontal scrollbar on addressbook in Internet Explorer 11 years ago
Thomas Bruederli 64808edbc8 Add 'if not exists' to system table creation. Just in case some previous db update routine was aborted or failed 11 years ago
Thomas Bruederli 357485e7e1 Skip some irrelevant ini checks in CLI mode 11 years ago
Thomas Bruederli 0032911784 Sanity check the file path for generic message footer before adding it 11 years ago
Aleksander Machniak 285b1ceb1c Update changelog 11 years ago
Aleksander Machniak e6d376236e Whitelist configuration options (user preferences) that can be changed using save-pref command 11 years ago
Aleksander Machniak 8320af552c Fix errors in IE8 when opening compose page in new window 11 years ago
Aleksander Machniak 099d2b9fd4 Remove sig_above configuration option, use reply_mode only (#1489001) 11 years ago
Aleksander Machniak 321d8b06fb Refresh current folder in opener window after draft save or message sent (#1488997) 11 years ago
Aleksander Machniak aa30cf8f3c Better fix for "saving draft just after entering compose window (#1489012)" 11 years ago
Aleksander Machniak d608088a64 Fix saving draft just after entering compose window (#1489012)
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak ae0821f1dd Be less restrictive on vCard import, do not require FN when N exists 11 years ago
Aleksander Machniak 1f8fbf9455 Fix vcard folding when outputing already generated vcard 11 years ago
Thomas Bruederli 73be4b5296 Match regex on multi-line sql statements 11 years ago
Thomas Bruederli 551ebd46de Ensure backwards compatibility by considering old-style skin_path attribute for <roundcube:include ...> tags 11 years ago
Aleksander Machniak e5a3e61052 Add some extension/mimetype aliases to fix some quirks in attachment type validation (#1488891) 11 years ago
Thomas Bruederli 57d1b12f2e Remove composer template because the new plugin system isn't ready yet 11 years ago
Aleksander Machniak ad5cefeefc Better fix for IE9 issue with document.activeElement error (#1489008) 11 years ago
Aleksander Machniak 73f094ff3c Fix javascript error in IE9 when loading form with placeholders into an iframe (#1489008) 11 years ago
Aleksander Machniak 71cae613f0 Added two tests for HTML comments handling in rcube_washtml class 11 years ago
Aleksander Machniak da595a5027 Fix handling of some conditional comment tags in HTML message (#1489004)
Conflicts:

	CHANGELOG
11 years ago
Thomas Bruederli ffa0c53236 Consider alternative table names from config when running DB updates 11 years ago
Aleksander Machniak 15963b7165 Workaround for some versions/systems where finfo_open() with second
argument doesn't do the same as with no 2nd argument as it should
11 years ago
Aleksander Machniak a15a595158 Make mime.types common locations list OS-aware 11 years ago
Aleksander Machniak 1d719e43fb Fix so forward as attachment works if additional attachment is added by message_compose hook (#1489000)
Prevent from re-adding the same forward attachment on compose page refresh

Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak ec27006ebe Fix wrapping of text lines with the same length as specified length limit 11 years ago
Aleksander Machniak 2c8afa8ac2 Fix javascript error when window name (for window.open()) in IE8 contains a dot
Conflicts:

	program/js/app.js
11 years ago
Aleksander Machniak c60f58f9fd Fix "rcmail is undefined" error in HTML attachment preview - regression
from commit d30460ad2f, small improvements
11 years ago
Aleksander Machniak 4c0c248dd9 Fix storing 'safe' flag on a message. The key for session value should include
folder name. A message with the same UID may exist in another folder.
11 years ago
Thomas Bruederli 713259002f Re-implement rcube_db::num_rows() to ensure backwards compatibility 11 years ago
Aleksander Machniak 5b82ed62dc Better handling of session errors in ajax requests - do page reload
on 403 Forbidden response (#1488960)
11 years ago
Aleksander Machniak 58993ffcbb Fix HTML part detection for some specific message structures (#1488992) 11 years ago
Aleksander Machniak 097c544d98 Don't show fake address - phishing prevention (#1488981) 11 years ago
Aleksander Machniak 2bbbca39ff Fix forward as attachment bug with editormode != 1 (#1488991) 11 years ago
Aleksander Machniak 5410eff830 Fix handling of empty $uids argument in change_flag() 11 years ago
Aleksander Machniak c4ff57c75f Fix LIMIT/OFFSET queries handling on MS SQL Server (#1488984) - require version 2005+
Conflicts:

	CHANGELOG
	program/lib/Roundcube/rcube_db_mssql.php
11 years ago
Thomas Bruederli 5aa77efcbe Trigger 'refresh' hook in mail view 11 years ago
Aleksander Machniak 527e7d4509 Fix javascript errors when working in a page opened with taget="_blank" 11 years ago
Aleksander Machniak 91deac7c91 Move spellcheck options section below signature options section 11 years ago
Aleksander Machniak acced81bba Add 0.9-rc to releases list 11 years ago
Aleksander Machniak 6e3f2b4294 Mention SQLite database format change in UPGRADING file (#1488983) 11 years ago
Aleksander Machniak 4999702e1e Increase maxlength to 254 chars for email input fields in addressbook (#1488987)
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak 9eb6d9e46a Add type 'ident' in quote() so we can quote identifiers (eg. column names) there.
Using array2list() for list of identifiers is now possible.
11 years ago
Aleksander Machniak 0ae20f6b9c Fix so full filename is used for title attribute 11 years ago
Aleksander Machniak dedf138795 Fix thumbnail size when GD extension is used for image resize (#1488985)
Conflicts:

	CHANGELOG
11 years ago
Aleksander Machniak 7797005999 Update changelog 11 years ago
Aleksander Machniak fddb9ff383 Display notice that message is encrypted also for application/pkcs7-mime messages (#1488526) 11 years ago
Aleksander Machniak ec2453866b Add 0.9-rc section 11 years ago
Thomas Bruederli 6c8ea96a56 Update copyright in about pages 11 years ago
Aleksander Machniak f5584cbfeb Fixed ACL edition in advanced mode 11 years ago
Thomas Bruederli 91a4864231 Merge branch 'release-0.9' of github.com:roundcube/roundcubemail into release-0.9 11 years ago
Thomas Bruederli 22819a3081 Don't skip message/* attachments when opening a draft. Restore check as it was before [fa57c988] 11 years ago
Thomas Bruederli e3eda60a60 Localization updates from Transifex 11 years ago
Aleksander Machniak ccc2e358f2 Fix plain text spellchecker icorrect highlighting in non-ASCII text (#1488973) 11 years ago
Thomas Bruederli f5533cf722 Synced localizations with Transifex 11 years ago
Aleksander Machniak e68d2a15f5 Don't try to print file extension in a warning message if it's not available 11 years ago
Aleksander Machniak bdf5656026 If version is not provided assume RCMAIL_VERSION (#1488933) 11 years ago
Aleksander Machniak fd777a8627 Add workaround for invalid message charset detection by IMAP servers (#1488968) 11 years ago
Aleksander Machniak 0ffb1a7af3 Fix typo in DB version strings (there should be no .sql suffix) 11 years ago
Aleksander Machniak 203251838b Fix NUL characters in content-type of ms-tnef attachment (#1488964) 11 years ago
Aleksander Machniak 60dabb35ae - Fix regression in handling LDAP contact identifiers (#1488959) 11 years ago
Aleksander Machniak a7e1b93109 Bump version number up to 6.2 11 years ago
Aleksander Machniak ee393929a6 Don't trim whitespace in folder names (#1488955)
Conflicts:

	plugins/managesieve/Changelog
11 years ago
Aleksander Machniak 8b08ec158b Make cleanup() method public 11 years ago
Thomas Bruederli cbb695a6de Correctly quote spell text contents inside the xml container 11 years ago
Thomas Bruederli 4279dd18ee Bump version to 0.9-rc 11 years ago
Thomas Bruederli 6b5e31f0af Import all translations from Transifex 11 years ago
Thomas Bruederli b2932cb614 Updated changelog 11 years ago
Thomas Bruederli df22967745 Let some env variables survive reset(); don't show taskbar and top line in framed error pages (#1488938) 11 years ago
Thomas Bruederli 0016cde2fe Fix rewrite rule to actually prevent access to bin/ and SQL/ directories 11 years ago
Thomas Bruederli a33717b230 Properly quote form validation error messages 11 years ago
Aleksander Machniak e55fc1458e Fix filenames charset handling (#1488946)
Conflicts:

	plugins/zipdownload/zipdownload.php
11 years ago
Aleksander Machniak 8514ab48d4 Fix reference to non-existing class rcube_output_html (#1488948) 11 years ago
Thomas Bruederli 24d7cc5dd1 Ignore file extension difference for text/plain attachments (#1488891) 11 years ago
Aleksander Machniak 334d37eda0 Fix contacts-table position when there's more than one addressbook 11 years ago
Aleksander Machniak 4003dbe988 Add 0.8.5 to releases list 11 years ago
Aleksander Machniak 0be1804c00 Lowercase username if 'login_lc' is set (#1488943) 11 years ago
Aleksander Machniak d3b18e6fc9 Slightly improve database driver chack 11 years ago
Thomas Bruederli 8c6ef8f05b Only trigger timers when dragging is active 11 years ago
Aleksander Machniak f2b4b8f3eb Fix spellcheck button menu in IE8 (change z-index and move the button to the right) 11 years ago
Aleksander Machniak 43aeb195c1 Fix handling link href attribute value with (valid) newline characters (#1488940) 11 years ago
Aleksander Machniak 85c972a4f7 Make get_instance() a static method 12 years ago
Aleksander Machniak 03ce0e12b8 Fix typo 12 years ago
Aleksander Machniak 6d5ad417d6 Fix "empty" ACL entry when there's "User, " in user input field 12 years ago
Thomas Bruederli 6782fe1fd7 Merge branch 'release-0.9' of github.com:roundcube/roundcubemail into release-0.9 12 years ago
Thomas Bruederli b4a30ac84f Catch connection timeouts on message sending form submissions 12 years ago
Aleksander Machniak 0f4022d54f Small fixes for Opera 12 years ago
Aleksander Machniak a188a9a305 Fix PHP Warning: Missing argument 2 for rcmail_output_html::get_skin_file() 12 years ago
Aleksander Machniak b0cc5519d7 Small fix to initial splitter position 12 years ago
Aleksander Machniak b3bbb28100 Add addressbook widget on compose page in classic skin 12 years ago
Thomas Bruederli 2a6472b2c2 Bring back lost text braking width adjustment when quoting blockquote parts 12 years ago
Thomas Bruederli a8fd895263 Make searchbox properly scale to 100% using box-sizing trick (#1488381) 12 years ago
Thomas Bruederli a2c2cb64e1 Refactored blockquote quotion routine in html2text conversion: it now correctly converts multiple and/or nested blockquotes 12 years ago
Thomas Bruederli 4901199761 Add search box to compose address book widget (#1488381) 12 years ago
Thomas Bruederli 5a0875ecb6 Define generic .searchbox styles 12 years ago
Thomas Bruederli c4a1d3fe5d Move rcmail_contact_key() to rcube_addressbook::compose_contact_key() 12 years ago
Aleksander Machniak 7f693b6565 Send LOGOUT only when closing connection in logged state (#1487784) 12 years ago
Aleksander Machniak cba8df5e1b Fix new browser window size in Chrome (#1488931), make new windows smaller 12 years ago
Aleksander Machniak ab0eb04f8c Added embed.css for classic skin, improved/unified warnings style (button is still different), cleanup 12 years ago
Thomas Bruederli 39bb93d9ae Load a default stylesheet (embed.css) from skin in plain html pages (e.g. attachment warnings and html messages) 12 years ago
Thomas Bruederli a7cec740ad Add file type icons for pgp/pks7 signatures and attached email messages 12 years ago
Thomas Bruederli f6404d1288 Save some vertical space in message part view 12 years ago
Thomas Bruederli f2c0e7a9c0 Allow to shrink any file passed as argument 12 years ago
Aleksander Machniak 01f1afbccc Fix login in case when default_host is an array with one element (#1488928) 12 years ago
Thomas Bruederli aefb924082 Updated changelog 12 years ago
Thomas Bruederli 2b2f34d354 Use LDAP fallback hosts on connect + bind because with OpenLDAP 2.x ldap_connect() always succeeds but ldap_bind() will fail if host isn't reachable.
Add option for LDAP bind timeout (sets LDAP_OPT_NETWORK_TIMEOUT on PHP > 5.3.0)
12 years ago
Thomas Bruederli 6984ab64f7 Use the right variable for IPv6 check 12 years ago
Aleksander Machniak a2181ee625 Submit Addressbook advanced search form with Enter key (#1488568) 12 years ago
Aleksander Machniak 68fb9e63f0 Rtrim() quoted lines on conversion to flowed format (according to RFC2646) 12 years ago
Aleksander Machniak 9deb663f94 More improvements to format=flowed handling + fix in wordwrap() used internally by format_flowed() 12 years ago
Aleksander Machniak 1aca4cb3ae Improve format=flowed text unfolding, add test for signature separator handling 12 years ago
Thomas Bruederli 24607ceb80 Also block remote images in HTML part view (#1488827) 12 years ago
Thomas Bruederli 8c293e2f28 Fix format=flowed unfolding on quoted lines; added tests for rcube_mime::format_flowed() and rcube_mime::unfold_flowed() 12 years ago
Aleksander Machniak 2c195e0365 Add basic tests for plugins 12 years ago
Aleksander Machniak cc2ee75ea4 Bump version number in *.initial.sql 12 years ago
Aleksander Machniak 55459c7576 Drop tmp_users table (#1488910) 12 years ago
Aleksander Machniak 5a2453703a Update changelog
Conflicts:

	CHANGELOG
12 years ago
Aleksander Machniak f5c7df4c32 Merge branch 'schema_upgrades' into release-0.9 12 years ago
Aleksander Machniak a03c28a22f Make sure mimetypes is an array not object in a better way 12 years ago
Thomas Bruederli 2080feca93 Select 8 KB of message part for headers (to make sure we get them all) 12 years ago
Thomas Bruederli ba36369638 Better check for 'real' links on shift/ctrl clicks 12 years ago
Thomas Bruederli a3e341cb29 Merge branch 'release-0.9' of github.com:roundcube/roundcubemail into release-0.9 12 years ago
Thomas Bruederli 7cc1d3ae17 Fix opener check in extwin (avoid JS errors in IE when opener is gone); always close extwin, even if opener isn't available anymore 12 years ago
Aleksander Machniak 536d45d3a2 Support more Thunderbird CSV fields, added zh_TW localization for csv2vcard map (#1488901) 12 years ago
Thomas Bruederli 9d318f5347 Fix logo display in IE8 (#1488889) 12 years ago
Thomas Bruederli 25a31031b0 Mark mime_magic option with old default value as obsolete 12 years ago
Thomas Bruederli d9f061b558 Avoid direct execution of installer includes (#1488895) 12 years ago
Thomas Bruederli a0eb4aef29 Merge branch 'release-0.9' of github.com:roundcube/roundcubemail into release-0.9 12 years ago
Thomas Bruederli b33f21867f Adjust searchbox position 12 years ago
Thomas Bruederli 0938f6622b Fix /this/ paths from plugin templates in extended skins 12 years ago
Aleksander Machniak 941fa51836 Add 0.9-beta to list of releases 12 years ago
Aleksander Machniak fd88a22eff Force autocommit mode in mysql database driver (#1488902) 12 years ago
Aleksander Machniak 942cbb6581 Don't convert to link a text with < and > characters 12 years ago
Thomas Bruederli 6fdc35e13e Remove development stuff and prepare for release 12 years ago
Thomas Bruederli 2c6aea9b8e Bump versions for 0.9 release branch 12 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

8
.gitignore vendored

@ -13,11 +13,3 @@ composer.json
composer.phar
composer.lock
vendor
# javascript dependencies
plugins/enigma/openpgp.min.js
plugins/managesieve/codemirror/
program/js/jquery.min.js
program/js/jstz.min.js
program/js/publickey.js
program/js/tinymce/

@ -1,24 +1,49 @@
# This is a sample with suggested security and performance options
# AddDefaultCharset UTF-8
AddType text/x-component .htc
<IfModule mod_php5.c>
php_flag display_errors Off
php_flag log_errors On
# php_value error_log logs/errors
php_value upload_max_filesize 5M
php_value post_max_size 6M
php_value memory_limit 64M
php_flag zlib.output_compression Off
php_flag magic_quotes_gpc Off
php_flag magic_quotes_runtime Off
php_flag zend.ze1_compatibility_mode Off
php_flag suhosin.session.encrypt Off
#php_value session.cookie_path /
php_flag session.auto_start Off
php_value session.gc_maxlifetime 21600
php_value session.gc_divisor 500
php_value session.gc_probability 1
# http://bugs.php.net/bug.php?id=30766
php_value mbstring.func_overload 0
</IfModule>
<IfModule mod_rewrite.c>
Options +SymLinksIfOwnerMatch
RewriteEngine On
RewriteRule ^favicon\.ico$ skins/larry/images/favicon.ico
# security rules:
# - deny access to files not containing a dot or starting with a dot
# in all locations except installer directory
RewriteRule ^(?!installer|\.well-known\/|[a-zA-Z0-9]{16})(\.?[^\.]+)$ - [F]
# - deny access to some locations
RewriteRule ^/?(\.git|\.tx|SQL|bin|config|logs|temp|tests|vendor|program\/(include|lib|localization|steps)) - [F]
# - deny access to some documentation files
RewriteRule /?(README.*|meta\.json|composer\..*|jsdeps.json)$ - [F]
# security rules
RewriteRule \.git - [F]
RewriteRule ^/?(README(.md)?|INSTALL|LICENSE|CHANGELOG|UPGRADING)$ - [F]
RewriteRule ^/?(SQL|bin) - [F]
</IfModule>
<IfModule mod_deflate.c>
SetOutputFilter DEFLATE
</IfModule>
<IfModule mod_headers.c>
# replace 'append' with 'merge' for Apache version 2.2.9 and later
#Header append Cache-Control public env=!NO_CACHE
</IfModule>
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 month"
@ -28,42 +53,4 @@ FileETag MTime Size
<IfModule mod_autoindex.c>
Options -Indexes
</IfModule>
<IfModule mod_headers.c>
# Disable page indexing
Header set X-Robots-Tag "noindex, nofollow"
# replace 'merge' with 'append' for Apache < 2.2.9
#Header merge Cache-Control public env=!NO_CACHE
# Optional security headers
# Only provides increased security if the browser supports those features
# Be careful! Testing is required! They should be adjusted to your installation / user environment
# HSTS - HTTP Strict Transport Security
#Header always set Strict-Transport-Security "max-age=31536000; preload" env=HTTPS
# HPKP - HTTP Public Key Pinning
# Only template - fill with your values
#Header always set Public-Key-Pins "max-age=3600; report-uri=\"\"; pin-sha256=\"\"; pin-sha256=\"\"" env=HTTPS
# X-Xss-Protection
# This header is used to configure the built in reflective XSS protection found in Internet Explorer, Chrome and Safari (Webkit).
#Header set X-XSS-Protection "1; mode=block"
# X-Frame-Options
# The X-Frame-Options header (RFC), or XFO header, protects your visitors against clickjacking attacks
# Already set by php code! Do not activate both options
#Header set X-Frame-Options SAMEORIGIN
# X-Content-Type-Options
# It prevents Google Chrome and Internet Explorer from trying to mime-sniff the content-type of a response away from the one being declared by the server.
#Header set X-Content-Type-Options: "nosniff"
# CSP - Content Security Policy
# for better privacy/security ask browsers to not set the Referer
# more flags for script, stylesheets and images available, read RFC for more information
# Note: "Referrer-Policy: same-origin" is already set by php code.
#Header set Content-Security-Policy "referrer no-referrer"
</IfModule>
</ifModule>

@ -1,37 +0,0 @@
language: php
dist: trusty #
sudo: false
matrix:
fast_finish: true
include:
- php: 5.4
- php: 5.5
- php: 5.6
- php: 7.0
- php: 7.1
env: CODE_COVERAGE=1
- php: 7.2
- 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:
directories:
- $HOME/.composer
install:
- .ci/install.sh
script:
- .ci/run.sh
notifications:
email: false

@ -1,99 +0,0 @@
[main]
host = https://www.transifex.com
lang_map = be: be_BE, sr: sr_CS, fa: fa_AF, lb: lb_LU, fr: fr_FR
type = PHP_ALT_ARRAY
[roundcube-webmail.labels]
file_filter = program/localization/<lang>/labels.inc
source_file = program/localization/en_US/labels.inc
source_lang = en_US
[roundcube-webmail.messages]
file_filter = program/localization/<lang>/messages.inc
source_file = program/localization/en_US/messages.inc
source_lang = en_US
[roundcube-webmail.timezones]
file_filter = program/localization/<lang>/timezones.inc
source_file = program/localization/en_US/timezones.inc
source_lang = en_US
[roundcube-webmail.plugin-acl]
file_filter = plugins/acl/localization/<lang>.inc
source_file = plugins/acl/localization/en_US.inc
source_lang = en_US
[roundcube-webmail.plugin-archive]
file_filter = plugins/archive/localization/<lang>.inc
source_file = plugins/archive/localization/en_US.inc
source_lang = en_US
[roundcube-webmail.plugin-attachment_reminder]
file_filter = plugins/attachment_reminder/localization/<lang>.inc
source_file = plugins/attachment_reminder/localization/en_US.inc
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]
file_filter = plugins/enigma/localization/<lang>.inc
source_file = plugins/enigma/localization/en_US.inc
source_lang = en_US
[roundcube-webmail.plugin-help]
file_filter = plugins/help/localization/<lang>.inc
source_file = plugins/help/localization/en_US.inc
source_lang = en_US
[roundcube-webmail.plugin-hide_blockquote]
file_filter = plugins/hide_blockquote/localization/<lang>.inc
source_file = plugins/hide_blockquote/localization/en_US.inc
source_lang = en_US
[roundcube-webmail.plugin-managesieve]
file_filter = plugins/managesieve/localization/<lang>.inc
source_file = plugins/managesieve/localization/en_US.inc
source_lang = en_US
[roundcube-webmail.plugin-markasjunk]
file_filter = plugins/markasjunk/localization/<lang>.inc
source_file = plugins/markasjunk/localization/en_US.inc
source_lang = en_US
[roundcube-webmail.plugin-new_user_dialog]
file_filter = plugins/new_user_dialog/localization/<lang>.inc
source_file = plugins/new_user_dialog/localization/en_US.inc
source_lang = en_US
[roundcube-webmail.plugin-newmail_notifier]
file_filter = plugins/newmail_notifier/localization/<lang>.inc
source_file = plugins/newmail_notifier/localization/en_US.inc
source_lang = en_US
[roundcube-webmail.plugin-password]
file_filter = plugins/password/localization/<lang>.inc
source_file = plugins/password/localization/en_US.inc
source_lang = en_US
[roundcube-webmail.plugin-subscriptions_option]
file_filter = plugins/subscriptions_option/localization/<lang>.inc
source_file = plugins/subscriptions_option/localization/en_US.inc
source_lang = en_US
[roundcube-webmail.plugin-userinfo]
file_filter = plugins/userinfo/localization/<lang>.inc
source_file = plugins/userinfo/localization/en_US.inc
source_lang = en_US
[roundcube-webmail.plugin-vcard_attachments]
file_filter = plugins/vcard_attachments/localization/<lang>.inc
source_file = plugins/vcard_attachments/localization/en_US.inc
source_lang = en_US
[roundcube-webmail.plugin-zipdownload]
file_filter = plugins/zipdownload/localization/<lang>.inc
source_file = plugins/zipdownload/localization/en_US.inc
source_lang = en_US

File diff suppressed because it is too large Load Diff

@ -3,104 +3,76 @@ INTRODUCTION
This file describes the basic steps to install Roundcube Webmail on your
web server. For additional information, please also consult the project's
wiki page at https://github.com/roundcube/roundcubemail/wiki
wiki page at http://trac.roundcube.net/wiki
REQUIREMENTS
============
* An IMAP, HTTP and SMTP server
* The Apache, Lighttpd, Cherokee or Hiawatha web server
* .htaccess support allowing overrides for DirectoryIndex
* PHP Version 5.4 or greater including:
- PCRE, DOM, JSON, Session, Sockets, OpenSSL, Mbstring, Filter, Ctype (required)
- PHP PDO with driver for either MySQL, PostgreSQL, SQL Server, Oracle or SQLite (required)
- Zip, Fileinfo, Intl, Exif (recommended)
- LDAP for LDAP addressbook support (optional)
- GD, Imagick (optional thumbnails generation, QR-code)
* PEAR and PEAR packages distributed with Roundcube or external:
- Mail_Mime 1.10.0 or newer
- Net_SMTP 1.8.1 or newer
- Net_Socket 1.0.12 or newer
* PHP Version 5.2.1 or greater including
- PCRE, DOM, JSON, XML, Session, Sockets (required)
- PHP Data Objects (PDO) with driver for either MySQL, PostgreSQL or SQLite (required)
Note: MySQL database driver requires PHP 5.3 or newer.
- Libiconv, Zip (recommended)
- Fileinfo, Mcrypt, mbstring (optional)
* PEAR packages distributed with Roundcube or external:
- Mail_Mime 1.8.1 or newer
- Mail_mimeDecode 1.5.5 or newer
- Net_SMTP (latest from https://github.com/pear/Net_SMTP/)
- Net_IDNA2 0.1.1 or newer
- Auth_SASL 1.0.6 or newer
- Net_Sieve 1.4.3 or newer (for managesieve plugin)
- Crypt_GPG 1.6.3 or newer (for enigma plugin)
- 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:
- error_reporting E_ALL & ~E_NOTICE & ~E_STRICT
- memory_limit > 16MB
- file_uploads enabled (for uploading attachments and import files)
* php.ini options (see .htaccess file):
- error_reporting E_ALL & ~E_NOTICE (or lower)
- memory_limit > 16MB (increase as suitable to support large attachments)
- file_uploads enabled (for attachment upload features)
- session.auto_start disabled
- zend.ze1_compatibility_mode disabled
- suhosin.session.encrypt disabled
- mbstring.func_overload disabled
- pcre.backtrack_limit >= 100000
* A MySQL, PostgreSQL, MS SQL Server (2005 or newer), Oracle database
or SQLite support in PHP - with permission to create tables
* Composer installed either locally or globally (https://getcomposer.org)
- magic_quotes_runtime disabled
- magic_quotes_sybase disabled
* PHP compiled with OpenSSL to connect to IMAPS and to use the spell checker
* A MySQL (4.0.8 or newer), PostgreSQL, MS SQL Server (2005 or newer) database engine
or SQLite support in PHP
* One of the above databases with permission to create tables
* An SMTP server (recommended) or PHP configured for mail delivery
INSTALLATION
============
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,
you have to install PHP and javascript dependencies.
2.1. Install PHP dependencies using composer:
- get composer from https://getcomposer.org/download/
- rename the composer.json-dist file into composer.json
- if you want to use LDAP address books, enable the LDAP libraries in your
composer.json file by moving the items from "suggest" to the "require"
section (remove the explanation texts after the version!).
- run `php composer.phar install --no-dev`
2.2. Install Javascript dependencies by executing `bin/install-jsdeps.sh` script.
3. Make sure that the following directories (and the files within)
1. Decompress and put this folder somewhere inside your document root
2. Make sure that the following directories (and the files within)
are writable by the webserver
- /temp
- /logs
4. Create a new database and a database user for Roundcube (see DATABASE SETUP)
5. Point your browser to http://url-to-roundcube/installer/
6. Follow the instructions of the install script (or see MANUAL CONFIGURATION)
7. After creating and testing the configuration, remove the installer directory
------------------------------------------
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
$ lessc -x styles/styles.less > styles/styles.css
$ lessc -x styles/print.less > styles/print.css
$ lessc -x styles/embed.less > styles/embed.css
9. Check Known Issues section of this file
3. Create a new database and a database user for Roundcube (see DATABASE SETUP)
4. Point your browser to http://url-to-roundcube/installer/
5. Follow the instructions of the install script (or see MANUAL CONFIGURATION)
6. After creating and testing the configuration, remove the installer directory
7. Done!
CONFIGURATION HINTS
===================
IMPORTANT! Read all comments in defaults.inc.php, understand them
and configure your installation to be not surprised by default behaviour.
Roundcube writes internal errors to the 'errors' log file located in the logs
directory which can be configured in config/main.inc.php. If you want ordinary
PHP errors to be logged there as well, enable the 'php_value error_log' line
in the .htaccess file and set the path to the log file accordingly.
Roundcube writes internal errors to the 'errors.log' log file located in the logs
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.
Roundcube forces display_errors=Off and log_errors=On.
By default the session cookie settings of PHP are not modified by Roundcube.
By default the session_path settings of PHP are not modified by Roundcube.
However if you want to limit the session cookies to the directory where
Roundcube resides you can set session.cookie_path in the php.ini or .htaccess file.
More about PHP settings: https://github.com/roundcube/roundcubemail/wiki/Installation#php-configuration
Roundcube resides you can uncomment and configure the according line
in the .htaccess file.
DATABASE SETUP
==============
Note: Database for Roundcube must use UTF-8 character set.
Note: See defaults.inc.php file for examples of DSN configuration.
* MySQL
-------
@ -109,9 +81,9 @@ importing the table layout and granting the proper permissions to the
roundcube user. Here is an example of that procedure:
# mysql
> CREATE DATABASE roundcubemail CHARACTER SET utf8 COLLATE utf8_general_ci;
> CREATE USER roundcube@localhost IDENTIFIED BY 'password';
> GRANT ALL PRIVILEGES ON roundcubemail.* TO roundcube@localhost;
> CREATE DATABASE roundcubemail /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
> GRANT ALL PRIVILEGES ON roundcubemail.* TO roundcube@localhost
IDENTIFIED BY 'password';
> quit
# mysql roundcubemail < SQL/mysql.initial.sql
@ -120,11 +92,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
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
--------
@ -140,18 +107,23 @@ To use Roundcube with PostgreSQL support you have to follow these
simple steps, which have to be done as the postgres system user (or
which ever is the database superuser):
$ createuser -P roundcube
$ createuser roundcube
$ createdb -O roundcube -E UNICODE roundcubemail
$ psql -U roundcube -f SQL/postgres.initial.sql roundcubemail
$ psql roundcubemail
Note: in some system configurations you might need to add '-U postgres' to
createuser and createdb commands.
roundcubemail =# ALTER USER roundcube WITH PASSWORD 'the_new_password';
roundcubemail =# \c - roundcube
roundcubemail => \i SQL/postgres.initial.sql
All this has been tested with PostgreSQL 8.x and 7.4.x. Older
versions don't have a -O option for the createdb, so if you are
using that version you'll have to change ownership of the DB later.
* Microsoft SQL Server
----------------------
Language/locale of the database must be set to us_english (1033). More info
on this at https://github.com/roundcube/roundcubemail/issues/4078.
on this at http://trac.roundcube.net/ticket/1488918.
Database cleaning
@ -161,50 +133,18 @@ bin/cleandb.sh which finally removes all records that are marked as deleted.
Best solution is to install a cronjob running this script daily.
MANUAL CONFIGURATION
====================
First of all, copy the sample configuration file config/config.inc.php.sample
to config/config.inc.php and make the necessary adjustments according to your
environment and your needs. More configuration options can be copied from the
config/defaults.inc.php file into your local config.inc.php file as needed.
Read the comments above the individual configuration options to find out what
they do or read https://github.com/roundcube/roundcubemail/wiki/Installation
for even more guidance.
The maximum size of email attachments and other file uploads is controlled by
PHP settings: upload_max_filesize and post_max_size. Read more about PHP
settings at https://github.com/roundcube/roundcubemail/wiki/Installation#php-configuration.
SECURE YOUR INSTALLATION
========================
Access through the webserver to the following directories should be denied:
/config
/temp
/logs
Roundcube uses .htaccess files to protect these directories, so be sure to
allow override of the Limit directives to get them taken into account. The
package also ships a .htaccess file in the root directory which defines some
rewrite rules. In order to properly secure your installation, please enable
mod_rewrite for Apache webserver and double check access to the above listed
directories and their contents is denied.
NOTE: In Apache 2.4, support for .htaccess files has been disabled by
default. Therefore you first need to enable this in your Apache main or
virtual host config by with:
First of all, rename the files config/*.inc.php.dist to config/*.inc.php.
You can then change these files according to your environment and your needs.
Details about the config parameters can be found in the config files.
See http://trac.roundcube.net/wiki/Howto_Install for even more guidance.
AllowOverride all
For non-apache web servers add equivalent configuration parameters to deny
direct access to these private resources.
It is also recommended to change the document root to <install path>/public_html
after installation if Roundcube runs at root of a dedicated virtual host. This
will automatically keep sensitive files out of reach for http requests.
You can also modify the default .htaccess file. This is necessary to
increase the allowed size of file attachments, for example:
php_value upload_max_filesize 2M
UPGRADING
@ -255,6 +195,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
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:
---------
With Lightty the addition of Expire: tags by mod_expire is incompatible with
@ -284,32 +229,3 @@ $HTTP["host"] == "www.example.com" {
compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png")
}
KNOWN ISSUES
============
Installations with uw-imap server should set imap_disabled_caps = array('ESEARCH')
in main configuration file. ESEARCH implementation in this server is broken (#1489184).
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
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.
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.

@ -1,15 +1,6 @@
Roundcube Webmail
=================
[roundcube.net](https://roundcube.net)
[![Build Status](https://api.travis-ci.org/roundcube/roundcubemail.svg?branch=master)](https://travis-ci.org/roundcube/roundcubemail)
ATTENTION
---------
This is just a snapshot from the GIT repository and is **NOT A STABLE
version of Roundcube**. It's not recommended to replace an existing installation
of Roundcube with this version. Also using a separate database for this
installation is highly recommended.
[roundcube.net](http://roundcube.net)
INTRODUCTION
@ -19,11 +10,17 @@ application-like user interface. It provides full functionality you expect
from an email client, including MIME support, address book, folder management,
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
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 is mainly written in PHP and is designed to run on a webserver.
It includes other open-source classes/libraries from [PEAR][pear],
an IMAP library derived from [IlohaMail][iloha] the [TinyMCE][tinymce] rich
text editor, [Googiespell][googiespell] library for spell checking or
the [WASHTML][washtml] sanitizer by Frederic Motte.
The code designed to run on a webserver is mainly written in PHP and Javascript.
It includes a custom framework with an IMAP library derived from [IlohaMail][iloha]
and requires a set of external libraries (see composer.json and jsdeps.json files).
The current default skin uses icons designed by Stephen Horlander and [Kevin
Gerich][kmgerich] for Mozilla.org.
INSTALLATION
@ -35,19 +32,6 @@ If you're updating an older version of Roundcube please follow the steps
described in the UPGRADING file.
BROWSER SUPPORT
---------------
Roundcube uses jQuery 3.x for its client and therefore inherits the browser
support from there. This currently includes:
- Chrome: (Current - 1) and Current
- Edge: (Current - 1) and Current
- Firefox: (Current - 1) and Current, ESR
- Internet Explorer: 9+ (11+ for the Elastic skin)
- Safari: (Current - 1) and Current
- Opera: Current
LICENSE
-------
This program is free software: you can redistribute it and/or modify
@ -88,17 +72,22 @@ For more information visit [roundcube.net/contribute][contrib]
CONTACT
-------
For bug reports or feature requests please refer to the tracking system
at [Github][githubissues] or subscribe to our mailing list.
For any bug reports or feature requests please refer to the tracking system
at [trac.roundcube.net][tracreport] or subscribe to our mailing list.
See [roundcube.net/support][support] for details.
You're always welcome to send a message to the project admin:
hello(at)roundcube(dot)net
[iloha]: https://sourceforge.net/projects/ilohamail/
[gpl]: https://www.gnu.org/licenses/
[license]: https://roundcube.net/license
[contrib]: https://roundcube.net/contribute
[support]: https://roundcube.net/support
[githubissues]: https://github.com/roundcube/roundcubemail/issues
[pear]: http://pear.php.net
[iloha]: http://sourceforge.net/projects/ilohamail/
[tinymce]: http://www.tinymce.com/
[googiespell]: http://orangoo.com/labs/GoogieSpell/
[washtml]: http://www.ubixis.com/washtml/
[kmgerich]: http://kmgerich.com/
[gpl]: http://www.gnu.org/licenses/
[license]: http://roundcube.net/license
[contrib]: http://roundcube.net/contribute
[support]: http://roundcube.net/support
[tracreport]: http://trac.roundcube.net/wiki/Howto_ReportIssues

@ -1,22 +1,15 @@
CREATE TABLE [dbo].[cache] (
[user_id] [int] NOT NULL ,
[cache_key] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL ,
[expires] [datetime] NULL ,
[data] [text] COLLATE Latin1_General_CI_AI NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE TABLE [dbo].[cache_shared] (
[cache_key] [varchar] (255) COLLATE Latin1_General_CS_AS NOT NULL ,
[expires] [datetime] NULL ,
[cache_key] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
[created] [datetime] NOT NULL ,
[data] [text] COLLATE Latin1_General_CI_AI NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE TABLE [dbo].[cache_index] (
[user_id] [int] NOT NULL ,
[mailbox] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL ,
[expires] [datetime] NULL ,
[mailbox] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
[changed] [datetime] NOT NULL ,
[valid] [char] (1) COLLATE Latin1_General_CI_AI NOT NULL ,
[data] [text] COLLATE Latin1_General_CI_AI NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
@ -24,17 +17,17 @@ GO
CREATE TABLE [dbo].[cache_thread] (
[user_id] [int] NOT NULL ,
[mailbox] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL ,
[expires] [datetime] NULL ,
[mailbox] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
[changed] [datetime] NOT NULL ,
[data] [text] COLLATE Latin1_General_CI_AI NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE TABLE [dbo].[cache_messages] (
[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 ,
[expires] [datetime] NULL ,
[changed] [datetime] NOT NULL ,
[data] [text] COLLATE Latin1_General_CI_AI NOT NULL ,
[flags] [int] NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
@ -88,6 +81,7 @@ GO
CREATE TABLE [dbo].[session] (
[sess_id] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
[created] [datetime] NOT NULL ,
[changed] [datetime] NULL ,
[ip] [varchar] (40) COLLATE Latin1_General_CI_AI NOT NULL ,
[vars] [text] COLLATE Latin1_General_CI_AI NOT NULL
@ -96,20 +90,18 @@ GO
CREATE TABLE [dbo].[users] (
[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 ,
[created] [datetime] NOT NULL ,
[last_login] [datetime] NULL ,
[failed_login] [datetime] 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
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE TABLE [dbo].[dictionary] (
[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
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
@ -123,36 +115,12 @@ CREATE TABLE [dbo].[searches] (
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE TABLE [dbo].[filestore] (
[file_id] [int] IDENTITY (1, 1) NOT NULL ,
[user_id] [int] NOT NULL ,
[context] [varchar] (32) COLLATE Latin1_General_CI_AI NOT NULL ,
[filename] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
[mtime] [int] NOT NULL ,
[data] [text] COLLATE Latin1_General_CI_AI NULL ,
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE TABLE [dbo].[system] (
[name] [varchar] (64) COLLATE Latin1_General_CI_AI NOT NULL ,
[value] [text] COLLATE Latin1_General_CI_AI NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[cache] WITH NOCHECK ADD
PRIMARY KEY CLUSTERED
(
[user_id],[cache_key]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[cache_shared] WITH NOCHECK ADD
PRIMARY KEY CLUSTERED
(
[cache_key]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[cache_index] WITH NOCHECK ADD
PRIMARY KEY CLUSTERED
(
@ -178,42 +146,42 @@ ALTER TABLE [dbo].[contacts] WITH NOCHECK ADD
CONSTRAINT [PK_contacts_contact_id] PRIMARY KEY CLUSTERED
(
[contact_id]
) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[contactgroups] WITH NOCHECK ADD
CONSTRAINT [PK_contactgroups_contactgroup_id] PRIMARY KEY CLUSTERED
(
[contactgroup_id]
) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[contactgroupmembers] WITH NOCHECK ADD
CONSTRAINT [PK_contactgroupmembers_id] PRIMARY KEY CLUSTERED
(
[contactgroup_id], [contact_id]
) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[identities] WITH NOCHECK ADD
PRIMARY KEY CLUSTERED
(
[identity_id]
) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[session] WITH NOCHECK ADD
CONSTRAINT [PK_session_sess_id] PRIMARY KEY CLUSTERED
(
[sess_id]
) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[users] WITH NOCHECK ADD
CONSTRAINT [PK_users_user_id] PRIMARY KEY CLUSTERED
(
[user_id]
) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[searches] WITH NOCHECK ADD
@ -223,13 +191,6 @@ ALTER TABLE [dbo].[searches] WITH NOCHECK ADD
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[filestore] WITH NOCHECK ADD
CONSTRAINT [PK_filestore_file_id] PRIMARY KEY CLUSTERED
(
[file_id]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[system] WITH NOCHECK ADD
CONSTRAINT [PK_system_name] PRIMARY KEY CLUSTERED
(
@ -239,42 +200,40 @@ GO
ALTER TABLE [dbo].[cache] ADD
CONSTRAINT [DF_cache_user_id] DEFAULT ('0') FOR [user_id],
CONSTRAINT [DF_cache_cache_key] DEFAULT ('') FOR [cache_key]
GO
ALTER TABLE [dbo].[cache_index] ADD
CONSTRAINT [DF_cache_index_valid] DEFAULT ('0') FOR [valid]
GO
ALTER TABLE [dbo].[cache_messages] ADD
CONSTRAINT [DF_cache_messages_flags] DEFAULT (0) FOR [flags]
CONSTRAINT [DF_cache_cache_key] DEFAULT ('') FOR [cache_key],
CONSTRAINT [DF_cache_created] DEFAULT (getdate()) FOR [created]
GO
CREATE INDEX [IX_cache_shared_cache_key] ON [dbo].[cache_shared]([cache_key]) ON [PRIMARY]
CREATE INDEX [IX_cache_user_id] ON [dbo].[cache]([user_id]) ON [PRIMARY]
GO
CREATE INDEX [IX_cache_index_user_id] ON [dbo].[cache_index]([user_id]) ON [PRIMARY]
CREATE INDEX [IX_cache_cache_key] ON [dbo].[cache]([cache_key]) ON [PRIMARY]
GO
CREATE INDEX [IX_cache_thread_user_id] ON [dbo].[cache_thread]([user_id]) ON [PRIMARY]
CREATE INDEX [IX_cache_created] ON [dbo].[cache]([created]) ON [PRIMARY]
GO
CREATE INDEX [IX_cache_messages_user_id] ON [dbo].[cache_messages]([user_id]) ON [PRIMARY]
ALTER TABLE [dbo].[cache_index] ADD
CONSTRAINT [DF_cache_index_changed] DEFAULT (getdate()) FOR [changed],
CONSTRAINT [DF_cache_index_valid] DEFAULT ('0') FOR [valid]
GO
CREATE INDEX [IX_cache_expires] ON [dbo].[cache]([expires]) ON [PRIMARY]
CREATE INDEX [IX_cache_index_user_id] ON [dbo].[cache_index]([user_id]) ON [PRIMARY]
GO
CREATE INDEX [IX_cache_shared_expires] ON [dbo].[cache_shared]([expires]) ON [PRIMARY]
ALTER TABLE [dbo].[cache_thread] ADD
CONSTRAINT [DF_cache_thread_changed] DEFAULT (getdate()) FOR [changed]
GO
CREATE INDEX [IX_cache_index_expires] ON [dbo].[cache_index]([expires]) ON [PRIMARY]
CREATE INDEX [IX_cache_thread_user_id] ON [dbo].[cache_thread]([user_id]) ON [PRIMARY]
GO
CREATE INDEX [IX_cache_thread_expires] ON [dbo].[cache_thread]([expires]) ON [PRIMARY]
ALTER TABLE [dbo].[cache_messages] ADD
CONSTRAINT [DF_cache_messages_changed] DEFAULT (getdate()) FOR [changed],
CONSTRAINT [DF_cache_messages_flags] DEFAULT (0) FOR [flags]
GO
CREATE INDEX [IX_cache_messages_expires] ON [dbo].[cache_messages]([expires]) ON [PRIMARY]
CREATE INDEX [IX_cache_messages_user_id] ON [dbo].[cache_messages]([user_id]) ON [PRIMARY]
GO
ALTER TABLE [dbo].[contacts] ADD
@ -288,7 +247,7 @@ ALTER TABLE [dbo].[contacts] ADD
CONSTRAINT [CK_contacts_del] CHECK ([del] = '1' or [del] = '0')
GO
CREATE INDEX [IX_contacts_user_id] ON [dbo].[contacts]([user_id]) ON [PRIMARY]
CREATE INDEX [IX_contacts_user_id] ON [dbo].[contacts]([user_id]) ON [PRIMARY]
GO
ALTER TABLE [dbo].[contactgroups] ADD
@ -299,7 +258,7 @@ ALTER TABLE [dbo].[contactgroups] ADD
CONSTRAINT [CK_contactgroups_del] CHECK ([del] = '1' or [del] = '0')
GO
CREATE INDEX [IX_contactgroups_user_id] ON [dbo].[contactgroups]([user_id]) ON [PRIMARY]
CREATE INDEX [IX_contactgroups_user_id] ON [dbo].[contacts]([user_id]) ON [PRIMARY]
GO
ALTER TABLE [dbo].[contactgroupmembers] ADD
@ -308,7 +267,7 @@ ALTER TABLE [dbo].[contactgroupmembers] ADD
CONSTRAINT [DF_contactgroupmembers_created] DEFAULT (getdate()) FOR [created]
GO
CREATE INDEX [IX_contactgroupmembers_contact_id] ON [dbo].[contactgroupmembers]([contact_id]) ON [PRIMARY]
CREATE INDEX [IX_contactgroupmembers_contact_id] ON [dbo].[contactgroupmembers]([contact_id]) ON [PRIMARY]
GO
ALTER TABLE [dbo].[identities] ADD
@ -321,24 +280,22 @@ ALTER TABLE [dbo].[identities] ADD
CONSTRAINT [DF_identities_reply] DEFAULT ('') FOR [reply-to],
CONSTRAINT [DF_identities_bcc] DEFAULT ('') FOR [bcc],
CONSTRAINT [DF_identities_html_signature] DEFAULT ('0') FOR [html_signature],
CHECK ([standard] = '1' or [standard] = '0'),
CHECK ([del] = '1' or [del] = '0')
CHECK ([standard] = '1' or [standard] = '0'),
CHECK ([del] = '1' or [del] = '0')
GO
CREATE INDEX [IX_identities_user_id] ON [dbo].[identities]([user_id]) ON [PRIMARY]
CREATE INDEX [IX_identities_user_id] ON [dbo].[identities]([user_id]) ON [PRIMARY]
GO
CREATE INDEX [IX_identities_email] ON [dbo].[identities]([email],[del]) ON [PRIMARY]
CREATE INDEX [IX_identities_email] ON [dbo].[identities]([email],[del]) ON [PRIMARY]
GO
ALTER TABLE [dbo].[session] ADD
CONSTRAINT [DF_session_sess_id] DEFAULT ('') FOR [sess_id],
CONSTRAINT [DF_session_created] DEFAULT (getdate()) FOR [created],
CONSTRAINT [DF_session_ip] DEFAULT ('') FOR [ip]
GO
CREATE INDEX [IX_session_changed] ON [dbo].[session]([changed]) ON [PRIMARY]
GO
CREATE INDEX [IX_filestore_user_id] ON [dbo].[filestore]([user_id]) ON [PRIMARY]
CREATE INDEX [IX_session_changed] ON [dbo].[session]([changed]) ON [PRIMARY]
GO
ALTER TABLE [dbo].[users] ADD
@ -347,10 +304,10 @@ ALTER TABLE [dbo].[users] ADD
CONSTRAINT [DF_users_created] DEFAULT (getdate()) FOR [created]
GO
CREATE UNIQUE INDEX [IX_users_username] ON [dbo].[users]([username],[mail_host]) ON [PRIMARY]
CREATE UNIQUE INDEX [IX_users_username] ON [dbo].[users]([username],[mail_host]) ON [PRIMARY]
GO
CREATE UNIQUE INDEX [IX_dictionary_user_language] ON [dbo].[dictionary]([user_id],[language]) ON [PRIMARY]
CREATE UNIQUE INDEX [IX_dictionary_user_language] ON [dbo].[dictionary]([user_id],[language]) ON [PRIMARY]
GO
ALTER TABLE [dbo].[searches] ADD
@ -361,9 +318,6 @@ GO
CREATE UNIQUE INDEX [IX_searches_user_type_name] ON [dbo].[searches]([user_id],[type],[name]) ON [PRIMARY]
GO
CREATE UNIQUE INDEX [IX_filestore_user_id_context_filename] ON [dbo].[filestore]([user_id],[context],[filename]) ON [PRIMARY]
GO
ALTER TABLE [dbo].[identities] ADD CONSTRAINT [FK_identities_user_id]
FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
ON DELETE CASCADE ON UPDATE CASCADE
@ -409,11 +363,6 @@ ALTER TABLE [dbo].[searches] ADD CONSTRAINT [FK_searches_user_id]
ON DELETE CASCADE ON UPDATE CASCADE
GO
ALTER TABLE [dbo].[filestore] ADD CONSTRAINT [FK_filestore_user_id]
FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
ON DELETE CASCADE ON UPDATE CASCADE
GO
-- Use trigger instead of foreign key (#1487112)
-- "Introducing FOREIGN KEY constraint ... may cause cycles or multiple cascade paths."
CREATE TRIGGER [contact_delete_member] ON [dbo].[contacts]
@ -422,6 +371,6 @@ CREATE TRIGGER [contact_delete_member] ON [dbo].[contacts]
WHERE [contact_id] IN (SELECT [contact_id] FROM deleted)
GO
INSERT INTO [dbo].[system] ([name], [value]) VALUES ('roundcube-version', '2020020101')
INSERT INTO [dbo].[system] ([name], [value]) VALUES ('roundcube-version', '2013011700')
GO

@ -1,17 +0,0 @@
CREATE TABLE [dbo].[cache_shared] (
[cache_key] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL ,
[created] [datetime] NOT NULL ,
[data] [text] COLLATE Latin1_General_CI_AI NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[cache_shared] ADD
CONSTRAINT [DF_cache_shared_created] DEFAULT (getdate()) FOR [created]
GO
CREATE INDEX [IX_cache_shared_cache_key] ON [dbo].[cache_shared]([cache_key]) ON [PRIMARY]
GO
CREATE INDEX [IX_cache_shared_created] ON [dbo].[cache_shared]([created]) ON [PRIMARY]
GO

@ -1,44 +0,0 @@
ALTER TABLE [dbo].[cache] ADD [expires] [datetime] NULL
GO
ALTER TABLE [dbo].[cache_shared] ADD [expires] [datetime] NULL
GO
ALTER TABLE [dbo].[cache_index] ADD [expires] [datetime] NULL
GO
ALTER TABLE [dbo].[cache_thread] ADD [expires] [datetime] NULL
GO
ALTER TABLE [dbo].[cache_messages] ADD [expires] [datetime] NULL
GO
UPDATE [dbo].[cache] SET [expires] = DATEADD(second, 604800, [created])
GO
UPDATE [dbo].[cache_shared] SET [expires] = DATEADD(second, 604800, [created])
GO
UPDATE [dbo].[cache_index] SET [expires] = DATEADD(second, 604800, [changed])
GO
UPDATE [dbo].[cache_thread] SET [expires] = DATEADD(second, 604800, [changed])
GO
UPDATE [dbo].[cache_messages] SET [expires] = DATEADD(second, 604800, [changed])
GO
DROP INDEX [IX_cache_created]
GO
DROP INDEX [IX_cache_shared_created]
GO
ALTER TABLE [dbo].[cache_index] DROP COLUMN [changed]
GO
ALTER TABLE [dbo].[cache_thread] DROP COLUMN [changed]
GO
ALTER TABLE [dbo].[cache_messages] DROP COLUMN [changed]
GO
CREATE INDEX [IX_cache_expires] ON [dbo].[cache]([expires]) ON [PRIMARY]
GO
CREATE INDEX [IX_cache_shared_expires] ON [dbo].[cache_shared]([expires]) ON [PRIMARY]
GO
CREATE INDEX [IX_cache_index_expires] ON [dbo].[cache_index]([expires]) ON [PRIMARY]
GO
CREATE INDEX [IX_cache_thread_expires] ON [dbo].[cache_thread]([expires]) ON [PRIMARY]
GO
CREATE INDEX [IX_cache_messages_expires] ON [dbo].[cache_messages]([expires]) ON [PRIMARY]
GO

@ -1,4 +0,0 @@
ALTER TABLE [dbo].[users] ADD [failed_login] [datetime] NULL
GO
ALTER TABLE [dbo].[users] ADD [failed_login_counter] [int] NULL
GO

@ -1,2 +0,0 @@
ALTER TABLE [dbo].[session] DROP COLUMN [created]
GO

@ -1,2 +0,0 @@
ALTER TABLE [dbo].[session] ALTER COLUMN [ip] [varchar] (40) COLLATE Latin1_General_CI_AI NOT NULL
GO

@ -1,36 +0,0 @@
DROP TABLE [dbo].[cache]
GO
DROP TABLE [dbo].[cache_shared]
GO
CREATE TABLE [dbo].[cache] (
[user_id] [int] NOT NULL ,
[cache_key] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
[expires] [datetime] NULL ,
[data] [text] COLLATE Latin1_General_CI_AI NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE TABLE [dbo].[cache_shared] (
[cache_key] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL ,
[expires] [datetime] NULL ,
[data] [text] COLLATE Latin1_General_CI_AI NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[cache] ADD
CONSTRAINT [DF_cache_user_id] DEFAULT ('0') FOR [user_id],
CONSTRAINT [DF_cache_cache_key] DEFAULT ('') FOR [cache_key],
GO
CREATE INDEX [IX_cache_expires] ON [dbo].[cache]([expires]) ON [PRIMARY]
GO
CREATE INDEX [IX_cache_shared_expires] ON [dbo].[cache_shared]([expires]) ON [PRIMARY]
GO
ALTER TABLE [dbo].[cache] WITH NOCHECK ADD
PRIMARY KEY CLUSTERED (
[user_id],[cache_key]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[cache_shared] WITH NOCHECK ADD
PRIMARY KEY CLUSTERED (
[cache_key]
) ON [PRIMARY]
GO

@ -1,24 +0,0 @@
CREATE TABLE [dbo].[filestore] (
[file_id] [int] IDENTITY (1, 1) NOT NULL ,
[user_id] [int] NOT NULL ,
[filename] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
[mtime] [int] NOT NULL ,
[data] [text] COLLATE Latin1_General_CI_AI NULL ,
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[filestore] WITH NOCHECK ADD
CONSTRAINT [PK_filestore_file_id] PRIMARY KEY CLUSTERED
(
[file_id]
) ON [PRIMARY]
GO
CREATE INDEX [IX_filestore_user_id] ON [dbo].[filestore]([user_id]) ON [PRIMARY]
GO
ALTER TABLE [dbo].[filestore] ADD CONSTRAINT [FK_filestore_user_id]
FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
ON DELETE CASCADE ON UPDATE CASCADE
GO

@ -1,9 +0,0 @@
ALTER TABLE [dbo].[filestore] ADD COLUMN [context] [varchar] (32) COLLATE Latin1_General_CI_AI NOT NULL
GO
UPDATE [dbo].[filestore] SET [dbo].[context] = 'enigma'
GO
CREATE UNIQUE INDEX [IX_filestore_user_id_context_filename] ON [dbo].[filestore]([user_id],[context],[filename]) ON [PRIMARY]
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

@ -7,12 +7,13 @@
CREATE TABLE `session` (
`sess_id` varchar(128) NOT NULL,
`created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`ip` varchar(40) NOT NULL,
`vars` mediumtext NOT NULL,
PRIMARY KEY(`sess_id`),
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`
@ -23,38 +24,25 @@ CREATE TABLE `users` (
`mail_host` varchar(128) NOT NULL,
`created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`last_login` datetime DEFAULT NULL,
`failed_login` datetime DEFAULT NULL,
`failed_login_counter` int(10) UNSIGNED DEFAULT NULL,
`language` varchar(16),
`preferences` longtext,
`language` varchar(5),
`preferences` text,
PRIMARY KEY(`user_id`),
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`
CREATE TABLE `cache` (
`user_id` int(10) UNSIGNED NOT NULL,
`cache_key` varchar(128) BINARY NOT NULL,
`expires` datetime DEFAULT NULL,
`cache_key` varchar(128) /*!40101 CHARACTER SET ascii COLLATE ascii_general_ci */ NOT NULL ,
`created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`data` longtext NOT NULL,
PRIMARY KEY (`user_id`, `cache_key`),
CONSTRAINT `user_id_fk_cache` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
INDEX `expires_index` (`expires`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */;
-- Table structure for table `cache_shared`
CREATE TABLE `cache_shared` (
`cache_key` varchar(255) BINARY NOT NULL,
`expires` datetime DEFAULT NULL,
`data` longtext NOT NULL,
PRIMARY KEY (`cache_key`),
INDEX `expires_index` (`expires`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */;
INDEX `created_index` (`created`),
INDEX `user_cache_index` (`user_id`,`cache_key`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
-- Table structure for table `cache_index`
@ -62,14 +50,14 @@ CREATE TABLE `cache_shared` (
CREATE TABLE `cache_index` (
`user_id` int(10) UNSIGNED NOT NULL,
`mailbox` varchar(255) BINARY NOT NULL,
`expires` datetime DEFAULT NULL,
`changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`valid` tinyint(1) NOT NULL DEFAULT '0',
`data` longtext NOT NULL,
CONSTRAINT `user_id_fk_cache_index` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
INDEX `expires_index` (`expires`),
INDEX `changed_index` (`changed`),
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`
@ -77,13 +65,13 @@ CREATE TABLE `cache_index` (
CREATE TABLE `cache_thread` (
`user_id` int(10) UNSIGNED NOT NULL,
`mailbox` varchar(255) BINARY NOT NULL,
`expires` datetime DEFAULT NULL,
`changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`data` longtext NOT NULL,
CONSTRAINT `user_id_fk_cache_thread` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
INDEX `expires_index` (`expires`),
INDEX `changed_index` (`changed`),
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`
@ -92,14 +80,14 @@ CREATE TABLE `cache_messages` (
`user_id` int(10) UNSIGNED NOT NULL,
`mailbox` varchar(255) BINARY NOT NULL,
`uid` int(11) UNSIGNED NOT NULL DEFAULT '0',
`expires` datetime DEFAULT NULL,
`changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`data` longtext NOT NULL,
`flags` int(11) NOT NULL DEFAULT '0',
CONSTRAINT `user_id_fk_cache_messages` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
INDEX `expires_index` (`expires`),
INDEX `changed_index` (`changed`),
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`
@ -119,7 +107,7 @@ CREATE TABLE `contacts` (
CONSTRAINT `user_id_fk_contacts` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
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`
@ -133,7 +121,7 @@ CREATE TABLE `contactgroups` (
CONSTRAINT `user_id_fk_contactgroups` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
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` (
`contactgroup_id` int(10) UNSIGNED NOT NULL,
@ -161,27 +149,26 @@ CREATE TABLE `identities` (
`email` varchar(128) NOT NULL,
`reply-to` varchar(128) NOT NULL DEFAULT '',
`bcc` varchar(128) NOT NULL DEFAULT '',
`signature` longtext,
`signature` text,
`html_signature` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY(`identity_id`),
CONSTRAINT `user_id_fk_identities` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
INDEX `user_identities_index` (`user_id`, `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`
CREATE TABLE `dictionary` (
`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"
`language` varchar(16) NOT NULL,
`user_id` int(10) UNSIGNED DEFAULT NULL,
`language` varchar(5) NOT NULL,
`data` longtext NOT NULL,
CONSTRAINT `user_id_fk_dictionary` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
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`
@ -196,22 +183,8 @@ CREATE TABLE `searches` (
CONSTRAINT `user_id_fk_searches` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
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`
CREATE TABLE `filestore` (
`file_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` int(10) UNSIGNED NOT NULL,
`context` varchar(32) NOT NULL,
`filename` varchar(128) NOT NULL,
`mtime` int(10) NOT NULL,
`data` longtext NOT NULL,
PRIMARY KEY (`file_id`),
CONSTRAINT `user_id_fk_filestore` FOREIGN KEY (`user_id`)
REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
UNIQUE `uniqueness` (`user_id`, `context`, `filename`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */;
-- Table structure for table `system`
@ -219,8 +192,8 @@ CREATE TABLE `system` (
`name` varchar(64) NOT NULL,
`value` mediumtext,
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 */;
INSERT INTO `system` (`name`, `value`) VALUES ('roundcube-version', '2020020101');
INSERT INTO system (name, value) VALUES ('roundcube-version', '2013011700');

@ -1,7 +0,0 @@
CREATE TABLE `cache_shared` (
`cache_key` varchar(255) /*!40101 CHARACTER SET ascii COLLATE ascii_general_ci */ NOT NULL,
`created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`data` longtext NOT NULL,
INDEX `created_index` (`created`),
INDEX `cache_key_index` (`cache_key`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;

@ -1,24 +0,0 @@
ALTER TABLE `cache` ADD `expires` datetime DEFAULT NULL;
ALTER TABLE `cache_shared` ADD `expires` datetime DEFAULT NULL;
ALTER TABLE `cache_index` ADD `expires` datetime DEFAULT NULL;
ALTER TABLE `cache_thread` ADD `expires` datetime DEFAULT NULL;
ALTER TABLE `cache_messages` ADD `expires` datetime DEFAULT NULL;
-- initialize expires column with created/changed date + 7days
UPDATE `cache` SET `expires` = `created` + interval 604800 second;
UPDATE `cache_shared` SET `expires` = `created` + interval 604800 second;
UPDATE `cache_index` SET `expires` = `changed` + interval 604800 second;
UPDATE `cache_thread` SET `expires` = `changed` + interval 604800 second;
UPDATE `cache_messages` SET `expires` = `changed` + interval 604800 second;
ALTER TABLE `cache` DROP INDEX `created_index`;
ALTER TABLE `cache_shared` DROP INDEX `created_index`;
ALTER TABLE `cache_index` DROP `changed`;
ALTER TABLE `cache_thread` DROP `changed`;
ALTER TABLE `cache_messages` DROP `changed`;
ALTER TABLE `cache` ADD INDEX `expires_index` (`expires`);
ALTER TABLE `cache_shared` ADD INDEX `expires_index` (`expires`);
ALTER TABLE `cache_index` ADD INDEX `expires_index` (`expires`);
ALTER TABLE `cache_thread` ADD INDEX `expires_index` (`expires`);
ALTER TABLE `cache_messages` ADD INDEX `expires_index` (`expires`);

@ -1 +0,0 @@
ALTER TABLE `users` CHANGE `preferences` `preferences` longtext;

@ -1 +0,0 @@
ALTER TABLE `identities` CHANGE `signature` `signature` longtext;

@ -1,3 +0,0 @@
ALTER TABLE `users`
ADD `failed_login` datetime DEFAULT NULL,
ADD `failed_login_counter` int(10) UNSIGNED DEFAULT NULL;

@ -1 +0,0 @@
ALTER TABLE `session` DROP COLUMN `created`;

@ -1 +0,0 @@
ALTER TABLE `session` MODIFY `ip` varchar(40) NOT NULL;

@ -1,24 +0,0 @@
ALTER TABLE `dictionary` ADD COLUMN `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST; -- redundant, for compat. with Galera Cluster
DROP TABLE `cache`;
DROP TABLE `cache_shared`;
CREATE TABLE `cache` (
`user_id` int(10) UNSIGNED NOT NULL,
`cache_key` varchar(128) /*!40101 CHARACTER SET ascii COLLATE ascii_general_ci */ NOT NULL,
`expires` datetime DEFAULT NULL,
`data` longtext NOT NULL,
PRIMARY KEY (`user_id`, `cache_key`),
CONSTRAINT `user_id_fk_cache` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
INDEX `expires_index` (`expires`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
CREATE TABLE `cache_shared` (
`cache_key` varchar(255) /*!40101 CHARACTER SET ascii COLLATE ascii_general_ci */ NOT NULL,
`expires` datetime DEFAULT NULL,
`data` longtext NOT NULL,
PRIMARY KEY (`cache_key`),
INDEX `expires_index` (`expires`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;

@ -1,11 +0,0 @@
CREATE TABLE `filestore` (
`file_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` int(10) UNSIGNED NOT NULL,
`filename` varchar(128) NOT NULL,
`mtime` int(10) NOT NULL,
`data` longtext NOT NULL,
PRIMARY KEY (`file_id`),
CONSTRAINT `user_id_fk_filestore` FOREIGN KEY (`user_id`)
REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
UNIQUE `uniqueness` (`user_id`, `filename`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;

@ -1,7 +0,0 @@
ALTER TABLE `filestore` ADD COLUMN `context` varchar(32) NOT NULL;
UPDATE `filestore` SET `context` = 'enigma';
ALTER TABLE `filestore` DROP FOREIGN KEY `user_id_fk_filestore`;
ALTER TABLE `filestore` DROP INDEX `uniqueness`;
ALTER TABLE `filestore` ADD UNIQUE INDEX `uniqueness` (`user_id`, `context`, `filename`);
ALTER TABLE `filestore` ADD CONSTRAINT `user_id_fk_filestore` FOREIGN KEY (`user_id`)
REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;

@ -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;

@ -1,241 +0,0 @@
-- Roundcube Webmail initial database structure
-- This was tested with Oracle 11g
CREATE TABLE "users" (
"user_id" integer PRIMARY KEY,
"username" varchar(128) NOT NULL,
"mail_host" varchar(128) NOT NULL,
"created" timestamp with time zone DEFAULT current_timestamp NOT NULL,
"last_login" timestamp with time zone DEFAULT NULL,
"failed_login" timestamp with time zone DEFAULT NULL,
"failed_login_counter" integer DEFAULT NULL,
"language" varchar(16),
"preferences" long DEFAULT NULL,
CONSTRAINT "users_username_key" UNIQUE ("username", "mail_host")
);
CREATE SEQUENCE "users_seq"
START WITH 1 INCREMENT BY 1 NOMAXVALUE;
CREATE TRIGGER "users_seq_trig"
BEFORE INSERT ON "users" FOR EACH ROW
BEGIN
:NEW."user_id" := "users_seq".nextval;
END;
/
CREATE TABLE "session" (
"sess_id" varchar(128) NOT NULL PRIMARY KEY,
"changed" timestamp with time zone DEFAULT current_timestamp NOT NULL,
"ip" varchar(41) NOT NULL,
"vars" long NOT NULL
);
CREATE INDEX "session_changed_idx" ON "session" ("changed");
CREATE TABLE "identities" (
"identity_id" integer PRIMARY KEY,
"user_id" integer NOT NULL
REFERENCES "users" ("user_id") ON DELETE CASCADE,
"changed" timestamp with time zone DEFAULT current_timestamp NOT NULL,
"del" smallint DEFAULT 0 NOT NULL,
"standard" smallint DEFAULT 0 NOT NULL,
"name" varchar(128) NOT NULL,
"organization" varchar(128),
"email" varchar(128) NOT NULL,
"reply-to" varchar(128),
"bcc" varchar(128),
"signature" long,
"html_signature" integer DEFAULT 0 NOT NULL
);
CREATE INDEX "identities_user_id_idx" ON "identities" ("user_id", "del");
CREATE INDEX "identities_email_idx" ON "identities" ("email", "del");
CREATE SEQUENCE "identities_seq"
START WITH 1 INCREMENT BY 1 NOMAXVALUE;
CREATE TRIGGER "identities_seq_trig"
BEFORE INSERT ON "identities" FOR EACH ROW
BEGIN
:NEW."identity_id" := "identities_seq".nextval;
END;
/
CREATE TABLE "contacts" (
"contact_id" integer PRIMARY KEY,
"user_id" integer NOT NULL
REFERENCES "users" ("user_id") ON DELETE CASCADE,
"changed" timestamp with time zone DEFAULT current_timestamp NOT NULL,
"del" smallint DEFAULT 0 NOT NULL,
"name" varchar(128) DEFAULT NULL,
"email" varchar(4000) DEFAULT NULL,
"firstname" varchar(128) DEFAULT NULL,
"surname" varchar(128) DEFAULT NULL,
"vcard" long,
"words" varchar(4000)
);
CREATE INDEX "contacts_user_id_idx" ON "contacts" ("user_id", "del");
CREATE SEQUENCE "contacts_seq"
START WITH 1 INCREMENT BY 1 NOMAXVALUE;
CREATE TRIGGER "contacts_seq_trig"
BEFORE INSERT ON "contacts" FOR EACH ROW
BEGIN
:NEW."contact_id" := "contacts_seq".nextval;
END;
/
CREATE TABLE "contactgroups" (
"contactgroup_id" integer PRIMARY KEY,
"user_id" integer NOT NULL
REFERENCES "users" ("user_id") ON DELETE CASCADE,
"changed" timestamp with time zone DEFAULT current_timestamp NOT NULL,
"del" smallint DEFAULT 0 NOT NULL,
"name" varchar(128) NOT NULL
);
CREATE INDEX "contactgroups_user_id_idx" ON "contactgroups" ("user_id", "del");
CREATE SEQUENCE "contactgroups_seq"
START WITH 1 INCREMENT BY 1 NOMAXVALUE;
CREATE TRIGGER "contactgroups_seq_trig"
BEFORE INSERT ON "contactgroups" FOR EACH ROW
BEGIN
:NEW."contactgroup_id" := "contactgroups_seq".nextval;
END;
/
CREATE TABLE "contactgroupmembers" (
"contactgroup_id" integer NOT NULL
REFERENCES "contactgroups" ("contactgroup_id") ON DELETE CASCADE,
"contact_id" integer NOT NULL
REFERENCES "contacts" ("contact_id") ON DELETE CASCADE,
"created" timestamp with time zone DEFAULT current_timestamp NOT NULL,
PRIMARY KEY ("contactgroup_id", "contact_id")
);
CREATE INDEX "contactgroupmembers_idx" ON "contactgroupmembers" ("contact_id");
CREATE TABLE "cache" (
"user_id" integer NOT NULL
REFERENCES "users" ("user_id") ON DELETE CASCADE,
"cache_key" varchar(128) NOT NULL,
"expires" timestamp with time zone DEFAULT NULL,
"data" long NOT NULL,
PRIMARY KEY ("user_id", "cache_key")
);
CREATE INDEX "cache_expires_idx" ON "cache" ("expires");
CREATE TABLE "cache_shared" (
"cache_key" varchar(255) NOT NULL,
"expires" timestamp with time zone DEFAULT NULL,
"data" long NOT NULL,
PRIMARY KEY ("cache_key")
);
CREATE INDEX "cache_shared_expires_idx" ON "cache_shared" ("expires");
CREATE TABLE "cache_index" (
"user_id" integer NOT NULL
REFERENCES "users" ("user_id") ON DELETE CASCADE,
"mailbox" varchar(255) NOT NULL,
"expires" timestamp with time zone DEFAULT NULL,
"valid" smallint DEFAULT 0 NOT NULL,
"data" long NOT NULL,
PRIMARY KEY ("user_id", "mailbox")
);
CREATE INDEX "cache_index_expires_idx" ON "cache_index" ("expires");
CREATE TABLE "cache_thread" (
"user_id" integer NOT NULL
REFERENCES "users" ("user_id") ON DELETE CASCADE,
"mailbox" varchar(255) NOT NULL,
"expires" timestamp with time zone DEFAULT NULL,
"data" long NOT NULL,
PRIMARY KEY ("user_id", "mailbox")
);
CREATE INDEX "cache_thread_expires_idx" ON "cache_thread" ("expires");
CREATE TABLE "cache_messages" (
"user_id" integer NOT NULL
REFERENCES "users" ("user_id") ON DELETE CASCADE,
"mailbox" varchar(255) NOT NULL,
"uid" integer NOT NULL,
"expires" timestamp with time zone DEFAULT NULL,
"data" long NOT NULL,
"flags" integer DEFAULT 0 NOT NULL,
PRIMARY KEY ("user_id", "mailbox", "uid")
);
CREATE INDEX "cache_messages_expires_idx" ON "cache_messages" ("expires");
CREATE TABLE "dictionary" (
"user_id" integer DEFAULT NULL
REFERENCES "users" ("user_id") ON DELETE CASCADE,
"language" varchar(16) NOT NULL,
"data" long DEFAULT NULL,
CONSTRAINT "dictionary_user_id_lang_key" UNIQUE ("user_id", "language")
);
CREATE TABLE "searches" (
"search_id" integer PRIMARY KEY,
"user_id" integer NOT NULL
REFERENCES "users" ("user_id") ON DELETE CASCADE,
"type" smallint DEFAULT 0 NOT NULL,
"name" varchar(128) NOT NULL,
"data" long NOT NULL,
CONSTRAINT "searches_user_id_key" UNIQUE ("user_id", "type", "name")
);
CREATE SEQUENCE "searches_seq"
START WITH 1 INCREMENT BY 1 NOMAXVALUE;
CREATE TRIGGER "searches_seq_trig"
BEFORE INSERT ON "searches" FOR EACH ROW
BEGIN
:NEW."search_id" := "searches_seq".nextval;
END;
/
CREATE TABLE "filestore" (
"file_id" integer PRIMARY KEY,
"user_id" integer NOT NULL
REFERENCES "users" ("user_id") ON DELETE CASCADE ON UPDATE CASCADE,
"context" varchar(32) NOT NULL,
"filename" varchar(128) NOT NULL,
"mtime" integer NOT NULL,
"data" long,
CONSTRAINT "filestore_user_id_key" UNIQUE ("user_id", "context", "filename")
);
CREATE SEQUENCE "filestore_seq"
START WITH 1 INCREMENT BY 1 NOMAXVALUE;
CREATE TRIGGER "filestore_seq_trig"
BEFORE INSERT ON "filestore" FOR EACH ROW
BEGIN
:NEW."user_id" := "filestore_seq".nextval;
END;
/
CREATE TABLE "system" (
"name" varchar(64) NOT NULL PRIMARY KEY,
"value" long
);
INSERT INTO "system" ("name", "value") VALUES ('roundcube-version', '2020020101');

@ -1,2 +0,0 @@
ALTER TABLE "users" ADD "failed_login" timestamp with time zone DEFAULT NULL;
ALTER TABLE "users" ADD "failed_login_counter" integer DEFAULT NULL;

@ -1 +0,0 @@
ALTER TABLE "session" DROP COLUMN "created";

@ -1 +0,0 @@
ALTER TABLE "session" MODIFY "ip" varchar(41) NOT NULL;

@ -1,23 +0,0 @@
DROP TABLE "cache";
DROP TABLE "cache_shared";
CREATE TABLE "cache" (
"user_id" integer NOT NULL
REFERENCES "users" ("user_id") ON DELETE CASCADE,
"cache_key" varchar(128) NOT NULL,
"expires" timestamp with time zone DEFAULT NULL,
"data" long NOT NULL,
PRIMARY KEY ("user_id", "cache_key")
);
CREATE INDEX "cache_expires_idx" ON "cache" ("expires");
CREATE TABLE "cache_shared" (
"cache_key" varchar(255) NOT NULL,
"expires" timestamp with time zone DEFAULT NULL,
"data" long NOT NULL,
PRIMARY KEY ("cache_key")
);
CREATE INDEX "cache_shared_expires_idx" ON "cache_shared" ("expires");

@ -1,19 +0,0 @@
CREATE TABLE "filestore" (
"file_id" integer PRIMARY KEY,
"user_id" integer NOT NULL
REFERENCES "users" ("user_id") ON DELETE CASCADE ON UPDATE CASCADE,
"filename" varchar(128) NOT NULL,
"mtime" integer NOT NULL,
"data" long,
CONSTRAINT "filestore_user_id_key" UNIQUE ("user_id", "filename")
);
CREATE SEQUENCE "filestore_seq"
START WITH 1 INCREMENT BY 1 NOMAXVALUE;
CREATE TRIGGER "filestore_seq_trig"
BEFORE INSERT ON "filestore" FOR EACH ROW
BEGIN
:NEW."user_id" := "filestore_seq".nextval;
END;
/

@ -1,4 +0,0 @@
ALTER TABLE "filestore" ADD COLUMN "context" varchar(32) NOT NULL;
UPDATE "filestore" SET "context" = 'enigma';
ALTER TABLE "filestore" DROP CONSTRAINT "filestore_user_id_key";
ALTER TABLE "filestore" ADD CONSTRAINT "filestore_user_id_key" UNIQUE ("user_id", "context", "filename");

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

@ -1,11 +1,11 @@
-- Roundcube Webmail initial database structure
--
-- Sequence "users_seq"
-- Name: users_seq; Type: SEQUENCE; Schema: public; Owner: postgres
-- Sequence "user_ids"
-- Name: user_ids; Type: SEQUENCE; Schema: public; Owner: postgres
--
CREATE SEQUENCE users_seq
CREATE SEQUENCE user_ids
INCREMENT BY 1
NO MAXVALUE
NO MINVALUE
@ -17,14 +17,12 @@ CREATE SEQUENCE users_seq
--
CREATE TABLE users (
user_id integer DEFAULT nextval('users_seq'::text) PRIMARY KEY,
user_id integer DEFAULT nextval('user_ids'::text) PRIMARY KEY,
username varchar(128) DEFAULT '' NOT NULL,
mail_host varchar(128) DEFAULT '' NOT NULL,
created timestamp with time zone DEFAULT now() NOT NULL,
last_login timestamp with time zone DEFAULT NULL,
failed_login timestamp with time zone DEFAULT NULL,
failed_login_counter integer DEFAULT NULL,
"language" varchar(16),
"language" varchar(5),
preferences text DEFAULT ''::text NOT NULL,
CONSTRAINT users_username_key UNIQUE (username, mail_host)
);
@ -37,6 +35,7 @@ CREATE TABLE users (
CREATE TABLE "session" (
sess_id varchar(128) DEFAULT '' PRIMARY KEY,
created timestamp with time zone DEFAULT now() NOT NULL,
changed timestamp with time zone DEFAULT now() NOT NULL,
ip varchar(41) NOT NULL,
vars text NOT NULL
@ -46,11 +45,11 @@ CREATE INDEX session_changed_idx ON session (changed);
--
-- Sequence "identities_seq"
-- Name: identities_seq; Type: SEQUENCE; Schema: public; Owner: postgres
-- Sequence "identity_ids"
-- Name: identity_ids; Type: SEQUENCE; Schema: public; Owner: postgres
--
CREATE SEQUENCE identities_seq
CREATE SEQUENCE identity_ids
START WITH 1
INCREMENT BY 1
NO MAXVALUE
@ -63,7 +62,7 @@ CREATE SEQUENCE identities_seq
--
CREATE TABLE identities (
identity_id integer DEFAULT nextval('identities_seq'::text) PRIMARY KEY,
identity_id integer DEFAULT nextval('identity_ids'::text) PRIMARY KEY,
user_id integer NOT NULL
REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
changed timestamp with time zone DEFAULT now() NOT NULL,
@ -83,11 +82,11 @@ CREATE INDEX identities_email_idx ON identities (email, del);
--
-- Sequence "contacts_seq"
-- Name: contacts_seq; Type: SEQUENCE; Schema: public; Owner: postgres
-- Sequence "contact_ids"
-- Name: contact_ids; Type: SEQUENCE; Schema: public; Owner: postgres
--
CREATE SEQUENCE contacts_seq
CREATE SEQUENCE contact_ids
START WITH 1
INCREMENT BY 1
NO MAXVALUE
@ -100,7 +99,7 @@ CREATE SEQUENCE contacts_seq
--
CREATE TABLE contacts (
contact_id integer DEFAULT nextval('contacts_seq'::text) PRIMARY KEY,
contact_id integer DEFAULT nextval('contact_ids'::text) PRIMARY KEY,
user_id integer NOT NULL
REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
changed timestamp with time zone DEFAULT now() NOT NULL,
@ -116,11 +115,11 @@ CREATE TABLE contacts (
CREATE INDEX contacts_user_id_idx ON contacts (user_id, del);
--
-- Sequence "contactgroups_seq"
-- Name: contactgroups_seq; Type: SEQUENCE; Schema: public; Owner: postgres
-- Sequence "contactgroups_ids"
-- Name: contactgroups_ids; Type: SEQUENCE; Schema: public; Owner: postgres
--
CREATE SEQUENCE contactgroups_seq
CREATE SEQUENCE contactgroups_ids
INCREMENT BY 1
NO MAXVALUE
NO MINVALUE
@ -132,7 +131,7 @@ CREATE SEQUENCE contactgroups_seq
--
CREATE TABLE contactgroups (
contactgroup_id integer DEFAULT nextval('contactgroups_seq'::text) PRIMARY KEY,
contactgroup_id integer DEFAULT nextval('contactgroups_ids'::text) PRIMARY KEY,
user_id integer NOT NULL
REFERENCES users(user_id) ON DELETE CASCADE ON UPDATE CASCADE,
changed timestamp with time zone DEFAULT now() NOT NULL,
@ -165,27 +164,14 @@ CREATE INDEX contactgroupmembers_contact_id_idx ON contactgroupmembers (contact_
CREATE TABLE "cache" (
user_id integer NOT NULL
REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
cache_key varchar(128) DEFAULT '' NOT NULL,
expires timestamp with time zone DEFAULT NULL,
data text NOT NULL,
PRIMARY KEY (user_id, cache_key)
);
CREATE INDEX cache_expires_idx ON "cache" (expires);
--
-- Table "cache_shared"
-- Name: cache_shared; Type: TABLE; Schema: public; Owner: postgres
--
CREATE TABLE "cache_shared" (
cache_key varchar(255) NOT NULL PRIMARY KEY,
expires timestamp with time zone DEFAULT NULL,
created timestamp with time zone DEFAULT now() NOT NULL,
data text NOT NULL
);
CREATE INDEX cache_shared_expires_idx ON "cache_shared" (expires);
CREATE INDEX cache_user_id_idx ON "cache" (user_id, cache_key);
CREATE INDEX cache_created_idx ON "cache" (created);
--
-- Table "cache_index"
@ -194,15 +180,15 @@ CREATE INDEX cache_shared_expires_idx ON "cache_shared" (expires);
CREATE TABLE cache_index (
user_id integer NOT NULL
REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
mailbox varchar(255) NOT NULL,
expires timestamp with time zone DEFAULT NULL,
changed timestamp with time zone DEFAULT now() NOT NULL,
valid smallint NOT NULL DEFAULT 0,
data text NOT NULL,
PRIMARY KEY (user_id, mailbox)
);
CREATE INDEX cache_index_expires_idx ON cache_index (expires);
CREATE INDEX cache_index_changed_idx ON cache_index (changed);
--
-- Table "cache_thread"
@ -211,14 +197,14 @@ CREATE INDEX cache_index_expires_idx ON cache_index (expires);
CREATE TABLE cache_thread (
user_id integer NOT NULL
REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
mailbox varchar(255) NOT NULL,
expires timestamp with time zone DEFAULT NULL,
changed timestamp with time zone DEFAULT now() NOT NULL,
data text NOT NULL,
PRIMARY KEY (user_id, mailbox)
);
CREATE INDEX cache_thread_expires_idx ON cache_thread (expires);
CREATE INDEX cache_thread_changed_idx ON cache_thread (changed);
--
-- Table "cache_messages"
@ -227,16 +213,16 @@ CREATE INDEX cache_thread_expires_idx ON cache_thread (expires);
CREATE TABLE cache_messages (
user_id integer NOT NULL
REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
mailbox varchar(255) NOT NULL,
uid integer NOT NULL,
expires timestamp with time zone DEFAULT NULL,
changed timestamp with time zone DEFAULT now() NOT NULL,
data text NOT NULL,
flags integer NOT NULL DEFAULT 0,
PRIMARY KEY (user_id, mailbox, uid)
);
CREATE INDEX cache_messages_expires_idx ON cache_messages (expires);
CREATE INDEX cache_messages_changed_idx ON cache_messages (changed);
--
-- Table "dictionary"
@ -245,18 +231,18 @@ CREATE INDEX cache_messages_expires_idx ON cache_messages (expires);
CREATE TABLE dictionary (
user_id integer DEFAULT NULL
REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
"language" varchar(16) NOT NULL,
REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
"language" varchar(5) NOT NULL,
data text NOT NULL,
CONSTRAINT dictionary_user_id_language_key UNIQUE (user_id, "language")
);
--
-- Sequence "searches_seq"
-- Name: searches_seq; Type: SEQUENCE; Schema: public; Owner: postgres
-- Sequence "searches_ids"
-- Name: searches_ids; Type: SEQUENCE; Schema: public; Owner: postgres
--
CREATE SEQUENCE searches_seq
CREATE SEQUENCE search_ids
INCREMENT BY 1
NO MAXVALUE
NO MINVALUE
@ -268,7 +254,7 @@ CREATE SEQUENCE searches_seq
--
CREATE TABLE searches (
search_id integer DEFAULT nextval('searches_seq'::text) PRIMARY KEY,
search_id integer DEFAULT nextval('search_ids'::text) PRIMARY KEY,
user_id integer NOT NULL
REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
"type" smallint DEFAULT 0 NOT NULL,
@ -277,32 +263,6 @@ CREATE TABLE searches (
CONSTRAINT searches_user_id_key UNIQUE (user_id, "type", name)
);
--
-- Sequence "filestore_seq"
-- Name: filestore_seq; Type: SEQUENCE; Schema: public; Owner: postgres
--
CREATE SEQUENCE "filestore_seq"
INCREMENT BY 1
NO MAXVALUE
NO MINVALUE
CACHE 1;
--
-- Table "filestore"
-- Name: filestore; Type: TABLE; Schema: public; Owner: postgres
--
CREATE TABLE "filestore" (
file_id integer DEFAULT nextval('filestore_seq'::text) PRIMARY KEY,
user_id integer NOT NULL
REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
context varchar(32) NOT NULL,
filename varchar(128) NOT NULL,
mtime integer NOT NULL,
data text NOT NULL,
CONSTRAINT filestore_user_id_filename UNIQUE (user_id, context, filename)
);
--
-- Table "system"
@ -314,4 +274,4 @@ CREATE TABLE "system" (
value text
);
INSERT INTO "system" (name, value) VALUES ('roundcube-version', '2020020101');
INSERT INTO system (name, value) VALUES ('roundcube-version', '2013011700');

@ -1,14 +0,0 @@
ALTER SEQUENCE user_ids RENAME TO users_seq;
ALTER TABLE users ALTER COLUMN user_id SET DEFAULT nextval('users_seq'::text);
ALTER SEQUENCE identity_ids RENAME TO identities_seq;
ALTER TABLE identities ALTER COLUMN identity_id SET DEFAULT nextval('identities_seq'::text);
ALTER SEQUENCE contact_ids RENAME TO contacts_seq;
ALTER TABLE contacts ALTER COLUMN contact_id SET DEFAULT nextval('contacts_seq'::text);
ALTER SEQUENCE contactgroups_ids RENAME TO contactgroups_seq;
ALTER TABLE contactgroups ALTER COLUMN contactgroup_id SET DEFAULT nextval('contactgroups_seq'::text);
ALTER SEQUENCE search_ids RENAME TO searches_seq;
ALTER TABLE searches ALTER COLUMN search_id SET DEFAULT nextval('searches_seq'::text);

@ -1,8 +0,0 @@
CREATE TABLE "cache_shared" (
cache_key varchar(255) NOT NULL,
created timestamp with time zone DEFAULT now() NOT NULL,
data text NOT NULL
);
CREATE INDEX cache_shared_cache_key_idx ON "cache_shared" (cache_key);
CREATE INDEX cache_shared_created_idx ON "cache_shared" (created);

@ -1,24 +0,0 @@
ALTER TABLE "cache" ADD expires timestamp with time zone DEFAULT NULL;
ALTER TABLE "cache_shared" ADD expires timestamp with time zone DEFAULT NULL;
ALTER TABLE "cache_index" ADD expires timestamp with time zone DEFAULT NULL;
ALTER TABLE "cache_thread" ADD expires timestamp with time zone DEFAULT NULL;
ALTER TABLE "cache_messages" ADD expires timestamp with time zone DEFAULT NULL;
-- initialize expires column with created/changed date + 7days
UPDATE "cache" SET expires = created + interval '604800 seconds';
UPDATE "cache_shared" SET expires = created + interval '604800 seconds';
UPDATE "cache_index" SET expires = changed + interval '604800 seconds';
UPDATE "cache_thread" SET expires = changed + interval '604800 seconds';
UPDATE "cache_messages" SET expires = changed + interval '604800 seconds';
DROP INDEX cache_created_idx;
DROP INDEX cache_shared_created_idx;
ALTER TABLE "cache_index" DROP "changed";
ALTER TABLE "cache_thread" DROP "changed";
ALTER TABLE "cache_messages" DROP "changed";
CREATE INDEX cache_expires_idx ON "cache" (expires);
CREATE INDEX cache_shared_expires_idx ON "cache_shared" (expires);
CREATE INDEX cache_index_expires_idx ON "cache_index" (expires);
CREATE INDEX cache_thread_expires_idx ON "cache_thread" (expires);
CREATE INDEX cache_messages_expires_idx ON "cache_messages" (expires);

@ -1,2 +0,0 @@
ALTER TABLE "users" ADD failed_login timestamp with time zone DEFAULT NULL;
ALTER TABLE "users" ADD failed_login_counter integer DEFAULT NULL;

@ -1 +0,0 @@
ALTER TABLE "session" DROP COLUMN created;

@ -1 +0,0 @@
ALTER TABLE session ALTER COLUMN ip TYPE character varying(41);

@ -1,21 +0,0 @@
DROP TABLE "cache";
DROP TABLE "cache_shared";
CREATE TABLE "cache" (
user_id integer NOT NULL
REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
cache_key varchar(128) DEFAULT '' NOT NULL,
expires timestamp with time zone DEFAULT NULL,
data text NOT NULL,
PRIMARY KEY (user_id, cache_key)
);
CREATE INDEX cache_expires_idx ON "cache" (expires);
CREATE TABLE "cache_shared" (
cache_key varchar(255) NOT NULL PRIMARY KEY,
expires timestamp with time zone DEFAULT NULL,
data text NOT NULL
);
CREATE INDEX cache_shared_expires_idx ON "cache_shared" (expires);

@ -1,15 +0,0 @@
CREATE SEQUENCE "filestore_seq"
INCREMENT BY 1
NO MAXVALUE
NO MINVALUE
CACHE 1;
CREATE TABLE "filestore" (
file_id integer DEFAULT nextval('filestore_seq'::text) PRIMARY KEY,
user_id integer NOT NULL
REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
filename varchar(128) NOT NULL,
mtime integer NOT NULL,
data text NOT NULL,
CONSTRAINT filestore_user_id_filename UNIQUE (user_id, filename)
);

@ -1,4 +0,0 @@
ALTER TABLE "filestore" ADD COLUMN context varchar(32) NOT NULL;
UPDATE "filestore" SET context = 'enigma';
ALTER TABLE "filestore" DROP CONSTRAINT "filestore_user_id_filename";
ALTER TABLE "filestore" ADD CONSTRAINT "filestore_user_id_context_filename" UNIQUE (user_id, context, filename);

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

@ -1,5 +1,22 @@
-- Roundcube Webmail initial database structure
--
-- Table structure for table cache
--
CREATE TABLE cache (
user_id integer NOT NULL default 0,
cache_key varchar(128) NOT NULL default '',
created datetime NOT NULL default '0000-00-00 00:00:00',
data text NOT NULL
);
CREATE INDEX ix_cache_user_cache_key ON cache(user_id, cache_key);
CREATE INDEX ix_cache_created ON cache(created);
-- --------------------------------------------------------
--
-- Table structure for table contacts and related
--
@ -40,6 +57,9 @@ CREATE TABLE contactgroupmembers (
CREATE INDEX ix_contactgroupmembers_contact_id ON contactgroupmembers (contact_id);
-- --------------------------------------------------------
--
-- Table structure for table identities
--
@ -62,6 +82,9 @@ CREATE TABLE identities (
CREATE INDEX ix_identities_user_id ON identities(user_id, del);
CREATE INDEX ix_identities_email ON identities(email, del);
-- --------------------------------------------------------
--
-- Table structure for table users
--
@ -72,20 +95,21 @@ CREATE TABLE users (
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),
language varchar(5),
preferences text NOT NULL default ''
);
CREATE UNIQUE INDEX ix_users_username ON users(username, mail_host);
-- --------------------------------------------------------
--
-- Table structure for table session
--
CREATE TABLE session (
sess_id varchar(128) NOT NULL PRIMARY KEY,
created datetime NOT NULL default '0000-00-00 00:00:00',
changed datetime NOT NULL default '0000-00-00 00:00:00',
ip varchar(40) NOT NULL default '',
vars text NOT NULL
@ -93,17 +117,21 @@ CREATE TABLE session (
CREATE INDEX ix_session_changed ON session (changed);
-- --------------------------------------------------------
--
-- Table structure for table dictionary
--
CREATE TABLE dictionary (
user_id integer DEFAULT NULL,
language varchar(16) NOT NULL,
"language" varchar(5) 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
@ -119,32 +147,7 @@ CREATE TABLE searches (
CREATE UNIQUE INDEX ix_searches_user_type_name ON searches (user_id, type, name);
--
-- Table structure for table cache
--
CREATE TABLE cache (
user_id integer NOT NULL default 0,
cache_key varchar(128) NOT NULL default '',
expires datetime DEFAULT NULL,
data text NOT NULL,
PRIMARY KEY (user_id, cache_key)
);
CREATE INDEX ix_cache_expires ON cache(expires);
--
-- Table structure for table cache_shared
--
CREATE TABLE cache_shared (
cache_key varchar(255) NOT NULL,
expires datetime DEFAULT NULL,
data text NOT NULL,
PRIMARY KEY (cache_key)
);
CREATE INDEX ix_cache_shared_expires ON cache_shared(expires);
-- --------------------------------------------------------
--
-- Table structure for table cache_index
@ -153,13 +156,15 @@ CREATE INDEX ix_cache_shared_expires ON cache_shared(expires);
CREATE TABLE cache_index (
user_id integer NOT NULL,
mailbox varchar(255) NOT NULL,
expires datetime DEFAULT NULL,
changed datetime NOT NULL default '0000-00-00 00:00:00',
valid smallint NOT NULL DEFAULT '0',
data text NOT NULL,
PRIMARY KEY (user_id, mailbox)
);
CREATE INDEX ix_cache_index_expires ON cache_index (expires);
CREATE INDEX ix_cache_index_changed ON cache_index (changed);
-- --------------------------------------------------------
--
-- Table structure for table cache_thread
@ -168,12 +173,14 @@ CREATE INDEX ix_cache_index_expires ON cache_index (expires);
CREATE TABLE cache_thread (
user_id integer NOT NULL,
mailbox varchar(255) NOT NULL,
expires datetime DEFAULT NULL,
changed datetime NOT NULL default '0000-00-00 00:00:00',
data text NOT NULL,
PRIMARY KEY (user_id, mailbox)
);
CREATE INDEX ix_cache_thread_expires ON cache_thread (expires);
CREATE INDEX ix_cache_thread_changed ON cache_thread (changed);
-- --------------------------------------------------------
--
-- Table structure for table cache_messages
@ -183,28 +190,15 @@ CREATE TABLE cache_messages (
user_id integer NOT NULL,
mailbox varchar(255) NOT NULL,
uid integer NOT NULL,
expires datetime DEFAULT NULL,
changed datetime NOT NULL default '0000-00-00 00:00:00',
data text NOT NULL,
flags integer NOT NULL DEFAULT '0',
PRIMARY KEY (user_id, mailbox, uid)
);
CREATE INDEX ix_cache_messages_expires ON cache_messages (expires);
--
-- Table structure for table filestore
--
CREATE TABLE filestore (
file_id integer NOT NULL PRIMARY KEY,
user_id integer NOT NULL,
context varchar(32) NOT NULL,
filename varchar(128) NOT NULL,
mtime integer NOT NULL,
data text NOT NULL
);
CREATE INDEX ix_cache_messages_changed ON cache_messages (changed);
CREATE UNIQUE INDEX ix_filestore_user_id ON filestore(user_id, context, filename);
-- --------------------------------------------------------
--
-- Table structure for table system
@ -215,4 +209,4 @@ CREATE TABLE system (
value text NOT NULL
);
INSERT INTO system (name, value) VALUES ('roundcube-version', '2020020101');
INSERT INTO system (name, value) VALUES ('roundcube-version', '2013011700');

@ -1,8 +0,0 @@
CREATE TABLE cache_shared (
cache_key varchar(255) NOT NULL,
created datetime NOT NULL default '0000-00-00 00:00:00',
data text NOT NULL
);
CREATE INDEX ix_cache_shared_cache_key ON cache_shared(cache_key);
CREATE INDEX ix_cache_shared_created ON cache_shared(created);

@ -1,48 +0,0 @@
DROP TABLE cache_index;
DROP TABLE cache_thread;
DROP TABLE cache_messages;
ALTER TABLE cache ADD expires datetime DEFAULT NULL;
DROP INDEX ix_cache_created;
ALTER TABLE cache_shared ADD expires datetime DEFAULT NULL;
DROP INDEX ix_cache_shared_created;
UPDATE cache SET expires = datetime(created, '+604800 seconds');
UPDATE cache_shared SET expires = datetime(created, '+604800 seconds');
CREATE INDEX ix_cache_expires ON cache(expires);
CREATE INDEX ix_cache_shared_expires ON cache_shared(expires);
CREATE TABLE cache_index (
user_id integer NOT NULL,
mailbox varchar(255) NOT NULL,
expires datetime DEFAULT NULL,
valid smallint NOT NULL DEFAULT '0',
data text NOT NULL,
PRIMARY KEY (user_id, mailbox)
);
CREATE INDEX ix_cache_index_expires ON cache_index (expires);
CREATE TABLE cache_thread (
user_id integer NOT NULL,
mailbox varchar(255) NOT NULL,
expires datetime DEFAULT NULL,
data text NOT NULL,
PRIMARY KEY (user_id, mailbox)
);
CREATE INDEX ix_cache_thread_expires ON cache_thread (expires);
CREATE TABLE cache_messages (
user_id integer NOT NULL,
mailbox varchar(255) NOT NULL,
uid integer NOT NULL,
expires datetime DEFAULT NULL,
data text NOT NULL,
flags integer NOT NULL DEFAULT '0',
PRIMARY KEY (user_id, mailbox, uid)
);
CREATE INDEX ix_cache_messages_expires ON cache_messages (expires);

@ -1,35 +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(5),
preferences text NOT NULL default ''
);
INSERT INTO tmp_users (user_id, username, mail_host, created, last_login, language, preferences)
SELECT user_id, username, mail_host, created, last_login, 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(5),
preferences text NOT NULL default ''
);
INSERT INTO users (user_id, username, mail_host, created, last_login, language, preferences)
SELECT user_id, username, mail_host, created, last_login, language, preferences FROM tmp_users;
CREATE UNIQUE INDEX ix_users_username ON users(username, mail_host);
DROP TABLE tmp_users;

@ -1,9 +0,0 @@
DROP TABLE session;
CREATE TABLE session (
sess_id varchar(128) NOT NULL PRIMARY KEY,
changed datetime NOT NULL default '0000-00-00 00:00:00',
ip varchar(40) NOT NULL default '',
vars text NOT NULL
);
CREATE INDEX ix_session_changed ON session (changed);

@ -1,21 +0,0 @@
DROP TABLE cache;
DROP TABLE cache_shared;
CREATE TABLE cache (
user_id integer NOT NULL default 0,
cache_key varchar(128) NOT NULL default '',
expires datetime DEFAULT NULL,
data text NOT NULL,
PRIMARY KEY (user_id, cache_key)
);
CREATE INDEX ix_cache_expires ON cache(expires);
CREATE TABLE cache_shared (
cache_key varchar(255) NOT NULL,
expires datetime DEFAULT NULL,
data text NOT NULL,
PRIMARY KEY (cache_key)
);
CREATE INDEX ix_cache_shared_expires ON cache_shared(expires);

@ -1,9 +0,0 @@
CREATE TABLE filestore (
file_id integer PRIMARY KEY,
user_id integer NOT NULL,
filename varchar(128) NOT NULL,
mtime integer NOT NULL,
data text NOT NULL
);
CREATE UNIQUE INDEX ix_filestore_user_id ON filestore(user_id, filename);

@ -1,29 +0,0 @@
CREATE TABLE tmp_filestore (
file_id integer PRIMARY KEY,
user_id integer NOT NULL,
filename varchar(128) NOT NULL,
mtime integer NOT NULL,
data text NOT NULL
);
INSERT INTO tmp_filestore (file_id, user_id, filename, mtime, data)
SELECT file_id, user_id, filename, mtime, data FROM filestore;
DROP TABLE filestore;
CREATE TABLE filestore (
file_id integer NOT NULL PRIMARY KEY,
user_id integer NOT NULL,
context varchar(32) NOT NULL,
filename varchar(128) NOT NULL,
mtime integer NOT NULL,
data text NOT NULL
);
INSERT INTO filestore (file_id, user_id, filename, mtime, data, context)
SELECT file_id, user_id, filename, mtime, data, 'enigma' FROM tmp_filestore;
CREATE UNIQUE INDEX ix_filestore_user_id ON filestore(user_id, context, filename);
DROP TABLE tmp_filestore;

@ -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;

@ -14,77 +14,47 @@ and cd into that directory. From there, run the following command in a shell:
./bin/installto.sh <TARGET-FOLDER>
For <TARGET-FOLDER> you specify the path to the Roundcube installation
which should be updated. The update script will then copy all new files to the
For <TARGET-FOLDER> you specify the path to the Roundcube installation
which should be updated. The update script will then copy all new files to the
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.
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: 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
-----------------
If you don't have shell access to the Roundcube installation or if not running
If you don't have shell access to the Roundcube installation or if not running
it on a unix system, you need to do the following operations by hand:
1. Replace index.php and all files in
- ./bin/
- ./SQL/
- ./program/
- ./installer/
2. Replace the configuration defaults files:
- config/defaults.inc.php
- config/mimetypes.php
3. rsync the contents of the following folders from your installation
2. rsync the contents of the following folders from your installation
directory into the target folder:
./skins/
./plugins/
./vendor/
4. Update dependencies:
4a. If you previously installed plugins through composer, update dependencies
by running `php composer.phar update --no-dev`.
4b. Install/update dependencies using composer:
- get composer from https://getcomposer.org/download/
- rename the composer.json-dist file into composer.json
- if you want to use LDAP address books, enable the LDAP libraries in your
composer.json file by moving the items from "suggest" to the "require"
section (remove the explanation texts after the version!).
- run `php composer.phar install --no-dev`.
4c. If you use git sources or the release package without dependencies
update javascript dependencies by executing `bin/install-jsdeps.sh` script.
4d. If you use git sources compile css files for the Elastic skin (required
lessc >= 1.5.0):
$ cd skins/elastic
$ lessc -x styles/styles.less > styles/styles.css
$ lessc -x styles/print.less > styles/print.css
$ lessc -x styles/embed.less > styles/embed.css
5. Run `./bin/update.sh` from the commandline OR
3. Run ./bin/update.sh from the commandline OR
open http://url-to-roundcube/installer/ in a browser and choose "3 Test config".
To enable the latter one, you have to temporary set 'enable_installer'
to true in your local config/config.inc.php file.
to true in your local config/main.inc.php file.
WARNING: See SQLite database upgrade below.
6. Let the update script/installer check your configuration and
4. Let the update script/installer check your configuration and
update your config files and database schema as suggested by the updater.
7. Make sure 'enable_installer' is set to false again.
8. See Post-Upgrade Activities section.
5. Make sure 'enable_installer' is set to false again.
6. See Post-Upgrade Activities section.
Post-Upgrade Activities
-----------------------
1. Check system requirements in INSTALL file.
1. Check .htaccess settings (some php settings could become required)
2. If you're using build-in addressbook, run indexing script /bin/indexcontacts.sh.
3. When upgrading from version older than 0.6-beta you should make sure
your folder settings contain namespace prefix. For example Courier users
should add INBOX. prefix to folder names in main configuration file.
4. When upgrading from version older than 1.4.0 make sure old files
in configured temp_dir are removed. Since this version we use constant filename
prefix and do not remove files not starting with "RCMTEMP".
4. Check system requirements in INSTALL file.
SQLite database upgrade
-----------------------

@ -2,9 +2,10 @@
<?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, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
@ -12,18 +13,66 @@
| |
| PURPOSE: |
| Finally remove all db records marked as deleted some time ago |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
define('INSTALL_PATH', realpath(dirname(__FILE__) . '/..') . '/' );
require INSTALL_PATH.'program/include/clisetup.php';
// mapping for table name => primary key
$primary_keys = array(
'contacts' => "contact_id",
'contactgroups' => "contactgroup_id",
);
// connect to DB
$RCMAIL = rcmail::get_instance();
$db = $RCMAIL->get_dbh();
$db->db_connect('w');
if (!$db->is_connected() || $db->is_error()) {
rcube::raise_error("No DB connection", false, true);
}
if (!empty($_SERVER['argv'][1]))
$days = intval($_SERVER['argv'][1]);
else
$days = 7;
rcmail_utils::db_clean($days);
// remove all deleted records older than two days
$threshold = date('Y-m-d 00:00:00', time() - $days * 86400);
foreach (array('contacts','contactgroups','identities') as $table) {
$sqltable = get_table_name($table);
// also delete linked records
// could be skipped for databases which respect foreign key constraints
if ($db->db_provider == 'sqlite'
&& ($table == 'contacts' || $table == 'contactgroups')
) {
$pk = $primary_keys[$table];
$memberstable = get_table_name('contactgroupmembers');
$db->query(
"DELETE FROM $memberstable".
" WHERE $pk IN (".
"SELECT $pk FROM $sqltable".
" WHERE del=1 AND changed < ?".
")",
$threshold);
echo $db->affected_rows() . " records deleted from '$memberstable'\n";
}
// delete outdated records
$db->query("DELETE FROM $sqltable WHERE del=1 AND changed < ?", $threshold);
echo $db->affected_rows() . " records deleted from '$table'\n";
}
?>

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

@ -2,9 +2,10 @@
<?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 |
| any later version with exceptions for skins & plugins. |
@ -12,6 +13,7 @@
| |
| PURPOSE: |
| Decrypt the encrypted parts of the HTTP Received: headers |
| |
+-----------------------------------------------------------------------+
| Author: Tomas Tevesz <ice@extreme.hu> |
+-----------------------------------------------------------------------+
@ -50,16 +52,16 @@
* - you are dealing with counterfeit header data.
*/
define('INSTALL_PATH', realpath(__DIR__ .'/..') . '/');
define('INSTALL_PATH', realpath(dirname(__FILE__).'/..') . '/');
require INSTALL_PATH . 'program/include/clisetup.php';
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 = rcmail::get_instance();
for ($i = 1; $i < $argc; $i++) {
printf("%s\n", $RCMAIL->decrypt($argv[$i]));
printf("%s\n", $RCMAIL->decrypt($argv[$i]));
};

@ -1,144 +0,0 @@
#!/usr/bin/env 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. |
| |
| PURPOSE: |
| Utility script to remove all data related to a certain user |
| from the local database. |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <thomas@roundcube.net> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
require_once INSTALL_PATH . 'program/include/clisetup.php';
function print_usage()
{
print "Usage: deluser.sh [--host=HOST][--age=DAYS][--dry-run] [username]\n";
print "--host=HOST The IMAP hostname or IP the given user is related to\n";
print "--age=DAYS Delete all users who have not logged in for more than X days\n";
print "--dry-run List users but do not delete them (for use with --age)\n";
}
function _die($msg, $usage=false)
{
fwrite(STDERR, $msg . "\n");
if ($usage) print_usage();
exit(1);
}
$rcmail = rcube::get_instance();
// get arguments
$args = rcube_utils::get_opt(array('h' => 'host', 'a' => 'age', 'd' => 'dry-run:bool'));
if (!empty($args['age']) && ($age = intval($args['age']))) {
$db = $rcmail->get_dbh();
$db->db_connect('r');
$query = $db->query("SELECT `username`, `mail_host` FROM " . $db->table_name('users', true)
. " WHERE `last_login` < " . $db->now($age * -1 * 86400)
. ($args['host'] ? " AND `mail_host` = " . $db->quote($args['host']) : '')
);
while ($user = $db->fetch_assoc($query)) {
if (!empty($args['dry-run'])) {
printf("%s (%s)\n", $user['username'], $user['mail_host']);
continue;
}
system(sprintf("php %s/deluser.sh --host=%s %s", INSTALL_PATH . 'bin', $user['mail_host'], $user['username']));
}
exit(1);
}
$username = trim($args[0]);
if (empty($username)) {
_die("Missing required parameters", true);
}
if (empty($args['host'])) {
$hosts = $rcmail->config->get('default_host', '');
if (is_string($hosts)) {
$args['host'] = $hosts;
}
else if (is_array($hosts) && count($hosts) == 1) {
$args['host'] = reset($hosts);
}
else {
_die("Specify a host name", true);
}
// host can be a URL like tls://192.168.12.44
$host_url = parse_url($args['host']);
if ($host_url['host']) {
$args['host'] = $host_url['host'];
}
}
// connect to DB
$db = $rcmail->get_dbh();
$db->db_connect('w');
$transaction = false;
if (!$db->is_connected() || $db->is_error()) {
_die("No DB connection\n" . $db->is_error());
}
// find user in local database
$user = rcube_user::query($username, $args['host']);
if (!$user) {
die("User not found.\n");
}
// inform plugins about approaching user deletion
$plugin = $rcmail->plugins->exec_hook('user_delete_prepare', array('user' => $user, 'username' => $username, 'host' => $args['host']));
// let plugins cleanup their own user-related data
if (!$plugin['abort']) {
$transaction = $db->startTransaction();
$plugin = $rcmail->plugins->exec_hook('user_delete', $plugin);
}
if ($plugin['abort']) {
if ($transaction) {
$db->rollbackTransaction();
}
_die("User deletion aborted by plugin");
}
// deleting the user record should be sufficient due to ON DELETE CASCADE foreign key references
// but not all database backends actually support this so let's do it by hand
foreach (array('identities','contacts','contactgroups','dictionary','cache','cache_index','cache_messages','cache_thread','searches','users') as $table) {
$db->query('DELETE FROM ' . $db->table_name($table, true) . ' WHERE `user_id` = ?', $user->ID);
}
if ($db->is_error()) {
$rcmail->plugins->exec_hook('user_delete_rollback', $plugin);
_die("DB error occurred: " . $db->is_error());
}
else {
// inform plugins about executed user deletion
$plugin = $rcmail->plugins->exec_hook('user_delete_commit', $plugin);
if ($plugin['abort']) {
unset($plugin['abort']);
$db->rollbackTransaction();
$rcmail->plugins->exec_hook('user_delete_rollback', $plugin);
}
else {
$db->endTransaction();
echo "Successfully deleted user $user->ID\n";
}
}

@ -1,37 +0,0 @@
#!/usr/bin/env 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. |
| |
| PURPOSE: |
| Trigger garbage collecting routines manually (e.g. via cronjob) |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
require INSTALL_PATH.'program/include/clisetup.php';
$rcmail = rcube::get_instance();
$session_driver = $rcmail->config->get('session_storage', 'db');
$session_lifetime = $rcmail->config->get('session_lifetime', 0) * 60 * 2;
// Clean expired SQL sessions
if ($session_driver == 'db' && $session_lifetime) {
$db = $rcmail->get_dbh();
$db->query("DELETE FROM " . $db->table_name('session')
. " WHERE changed < " . $db->now(-$session_lifetime));
}
// Clean caches and temp directory
$rcmail->gc();

@ -2,9 +2,10 @@
<?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 |
| any later version with exceptions for skins & plugins. |
@ -18,9 +19,36 @@
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
define('INSTALL_PATH', realpath(dirname(__FILE__) . '/..') . '/' );
require_once INSTALL_PATH.'program/include/clisetup.php';
ini_set('memory_limit', -1);
rcmail_utils::indexcontacts();
// connect to DB
$RCMAIL = rcmail::get_instance();
$db = $RCMAIL->get_dbh();
$db->db_connect('w');
if (!$db->is_connected() || $db->is_error()) {
rcube::raise_error("No DB connection", false, true);
}
// iterate over all users
$sql_result = $db->query("SELECT user_id FROM " . $RCMAIL->config->get('db_table_users', 'users')." WHERE 1=1");
while ($sql_result && ($sql_arr = $db->fetch_assoc($sql_result))) {
echo "Indexing contacts for user " . $sql_arr['user_id'] . "...";
$contacts = new rcube_contacts($db, $sql_arr['user_id']);
$contacts->set_pagesize(9999);
$result = $contacts->list_records();
while ($result->count && ($row = $result->next())) {
unset($row['words']);
$contacts->update($row['ID'], $row);
}
echo "done.\n";
}
?>

@ -1,39 +0,0 @@
#!/usr/bin/env php
<?php
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| Copyright (C) Kolab Systems AG |
| |
| 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: |
| Create database schema |
+-----------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
require_once INSTALL_PATH . 'program/include/clisetup.php';
// get arguments
$opts = rcube_utils::get_opt(array(
'd' => 'dir',
));
if (empty($opts['dir'])) {
rcube::raise_error("Database schema directory not specified (--dir).", false, true);
}
// Check if directory exists
if (!file_exists($opts['dir'])) {
rcube::raise_error("Specified database schema directory doesn't exist.", false, true);
}
rcmail_utils::db_init($opts['dir']);

@ -1,385 +0,0 @@
#!/usr/bin/env 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. |
| |
| PURPOSE: |
| Utility script to fetch and install all 3rd party javascript |
| libraries used in Roundcube from source. |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <thomas@roundcube.net> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
require_once INSTALL_PATH . 'program/include/clisetup.php';
if (!function_exists('exec')) {
rcube::raise_error("PHP exec() function is required. Check disable_functions in php.ini.", false, true);
}
$cfgfile = INSTALL_PATH . 'jsdeps.json';
$SOURCES = json_decode(file_get_contents($cfgfile), true);
if (empty($SOURCES['dependencies'])) {
rcube::raise_error("Failed to read dependencies list from $cfgfile", false, true);
}
$CURL = trim(`which curl`);
$WGET = trim(`which wget`);
$UNZIP = trim(`which unzip`);
if (($CACHEDIR = getenv("CACHEDIR")) && is_writeable($CACHEDIR)) {
// use $CACHEDIR
}
else if (is_writeable(INSTALL_PATH . 'temp/js_cache') || @mkdir(INSTALL_PATH . 'temp/js_cache', 0774, true)) {
$CACHEDIR = INSTALL_PATH . 'temp/js_cache';
}
else {
$CACHEDIR = sys_get_temp_dir();
}
//////////////// License definitions
$LICENSES = array();
$LICENSES['MIT'] = <<<EOM
* Licensed under the MIT licenses
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
EOM;
$LICENSES['GPLv3'] = <<<EOG
* 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 (GNU GPL) as published by the Free Software
* Foundation, either version 3 of the License, or (at your option)
* any later version. The code is distributed WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
*
* As additional permission under GNU GPL version 3 section 7, you
* may distribute non-source (e.g., minimized or compacted) forms of
* that code without the copy of the GNU GPL normally required by
* section 4, provided you include this license notice and a URL
* through which recipients can access the Corresponding Source.
EOG;
$LICENSES['LGPL'] = <<<EOL
* The JavaScript code in this page is free software: you can
* redistribute it and/or modify it under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option)
* any later version.
EOL;
//////////////// Functions
/**
* Fetch package file from source
*/
function fetch_from_source($package, $useCache = true, &$filetype = null)
{
global $CURL, $WGET;
$cache_file = extract_filetype($package, $filetype);
if (!is_readable($cache_file) || !$useCache) {
if (empty($CURL) && empty($WGET)) {
rcube::raise_error("Required 'wget' or 'curl' program not found.", false, true);
}
$url = str_replace('$v', $package['version'], $package['url']);
echo "Fetching $url\n";
if ($CURL)
exec(sprintf('%s -L -s %s -o %s', $CURL, escapeshellarg($url), $cache_file), $out, $retval);
else
exec(sprintf('%s -q %s -O %s', $WGET, escapeshellarg($url), $cache_file), $out, $retval);
// Try Github API as a fallback (#6248)
if ($retval !== 0 && $package['api_url']) {
$url = str_replace('$v', $package['version'], $package['api_url']);
$header = 'Accept:application/vnd.github.v3.raw';
rcube::raise_error("Fetching failed. Using Github API on $url");
if ($CURL)
exec(sprintf('%s -L -H %s -s %s -o %s', $CURL, escapeshellarg($header), escapeshellarg($url), $cache_file), $out, $retval);
else
exec(sprintf('%s --header %s -q %s -O %s', $WGET, escapeshellarg($header), escapeshellarg($url), $cache_file), $out, $retval);
}
if ($retval !== 0) {
rcube::raise_error("Failed to download source file from $url", false, true);
}
}
return $cache_file;
}
/**
* Returns package source file location and type
*/
function extract_filetype($package, &$filetype = null)
{
global $CACHEDIR;
$filetype = pathinfo($package['url'], PATHINFO_EXTENSION) ?: 'tmp';
$cache_file = $CACHEDIR . '/' . $package['lib'] . '-' . $package['version'] . '.' . $filetype;
// Make sure it is a zip file
if (file_exists($cache_file)) {
$magic = file_get_contents($cache_file, false, null, 0, 4);
if ($magic === "PK\003\004") {
$filetype = 'zip';
}
}
return $cache_file;
}
/**
* Create a destination javascript file with copyright and license header
*/
function compose_destfile($package, $srcfile)
{
global $LICENSES;
$header = sprintf("/**\n * %s - v%s\n *\n", $package['name'], $package['version']);
if (!empty($package['source'])) {
$header .= " * @source " . str_replace('$v', $package['version'], $package['source']) . "\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";
}
$header .= $LICENSES[$package['license']];
$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))) {
echo "Wrote file " . INSTALL_PATH . $package['dest'] . "\n";
}
else {
rcube::raise_error("Failed to write destination file " . INSTALL_PATH . $package['dest'], false, true);
}
}
/**
* Extract a Zip archive into the destination specified by the package config
*/
function extract_zipfile($package, $srcfile)
{
global $UNZIP, $CACHEDIR;
if (empty($UNZIP)) {
rcube::raise_error("Required 'unzip' program not found.", false, true);
}
$destdir = INSTALL_PATH . $package['dest'];
if (!is_dir($destdir)) {
mkdir($destdir, 0775, true);
}
if (!is_writeable($destdir)) {
rcube::raise_error("Cannot write to destination directory: $destdir", false, true);
}
// 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) {
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';
exec(sprintf($zip_command, $UNZIP, escapeshellarg($srcfile), $extract), $out, $retval);
// 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
exec('rm -rf ' . $extract);
}
// 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) {
rcube::raise_error("Failed to unzip $srcfile; " . implode('; ' . $out));
}
}
// remove some files from the destination
if (!empty($package['omit'])) {
foreach ((array)$package['omit'] as $glob) {
exec(sprintf('rm -rf %s/%s', $destdir, escapeshellarg($glob)));
}
}
// 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);
}
}
}
/**
* Delete the package destination file/dir
*/
function delete_destfile($package)
{
$destdir = INSTALL_PATH . ($package['rm'] ?: $package['dest']);
if (file_exists($destdir)) {
if (PHP_OS === 'Windows') {
exec(sprintf("rd /s /q %s", escapeshellarg($destdir)));
}
else {
exec(sprintf("rm -rf %s", escapeshellarg($destdir)));
}
}
}
//////////////// Execution
$args = rcube_utils::get_opt(array('f' => 'force:bool', 'd' => 'delete:bool', 'g' => 'get:bool', 'e' => 'extract:bool'))
+ array('force' => false, 'delete' => false, 'get' => false, 'extract' => false);
$WHAT = $args[0];
$useCache = !$args['force'] && !$args['get'];
if (!$args['get'] && !$args['extract'] && !$args['delete']) {
$args['get'] = $args['extract'] = 1;
}
foreach ($SOURCES['dependencies'] as $package) {
if (!isset($package['name'])) {
$package['name'] = $package['lib'];
}
if ($WHAT && $package['lib'] !== $WHAT) {
continue;
}
if ($args['delete']) {
delete_destfile($package);
continue;
}
if ($args['get']) {
$srcfile = fetch_from_source($package, $useCache, $filetype);
}
else {
$srcfile = extract_filetype($package, $filetype);
}
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 "Installing {$package['name']}...\n";
if ($filetype === 'zip') {
extract_zipfile($package, $srcfile);
}
else {
compose_destfile($package, $srcfile);
}
echo "Done.\n";
}
}

@ -2,9 +2,10 @@
<?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) 2012, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
@ -18,131 +19,63 @@
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
define('INSTALL_PATH', realpath(dirname(__FILE__) . '/..') . '/' );
require_once INSTALL_PATH . 'program/include/clisetup.php';
if (!function_exists('system')) {
rcube::raise_error("PHP system() function is required. Check disable_functions in php.ini.", false, true);
}
$target_dir = unslashify(end($_SERVER['argv']));
$accept = in_array('-y', $_SERVER['argv']) ? 'y' : null;
$target_dir = unslashify($_SERVER['argv'][1]);
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
$iniset = @file_get_contents($target_dir . '/program/include/iniset.php');
if (!preg_match('/define\(.RCMAIL_VERSION.,\s*.([0-9.]+[a-z0-9-]*)/', $iniset, $m))
rcube::raise_error("No valid Roundcube installation found at $target_dir", false, true);
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);
$oldversion = $m[1];
if (version_compare(version_parse($oldversion), version_parse(RCMAIL_VERSION), '>'))
rcube::raise_error("Target installation already in version $oldversion.", false, true);
if (version_compare(version_parse($oldversion), version_parse(RCMAIL_VERSION), '>='))
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') {
echo "Copying files to target location...";
$adds = array();
$dirs = array('bin','SQL','plugins','skins','program');
if (is_dir(INSTALL_PATH . 'vendor') && !is_file("$target_dir/composer.json")) {
$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);
}
}
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";
if (file_exists(INSTALL_PATH . $file) && (system($command, $ret) === false || $ret > 0)) {
rcube::raise_error("Failed to execute command: $command", false, true);
}
$err = false;
echo "Copying files to target location...";
foreach (array('program','installer','bin','SQL','plugins','skins') as $dir) {
if (!system("rsync -avC " . INSTALL_PATH . "$dir/* $target_dir/$dir/")) {
$err = true;
break;
}
// Copy .htaccess or .user.ini if needed
foreach (array('.htaccess','.user.ini') as $file) {
if (file_exists(INSTALL_PATH . $file)) {
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.";
}
}
}
}
// remove old (<1.0) .htaccess file
@unlink("$target_dir/program/.htaccess");
echo "done.\n\n";
if (is_dir("$target_dir/skins/default")) {
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");
}
}
echo "done.\n\n";
}
// Warn about situation when using "complete" package to update "custom" installation (#7087)
// Note: "Complete" package do not include jsdeps.json nor install-jsdeps.sh
if (file_exists("$target_dir/jsdeps.json") && !file_exists(INSTALL_PATH . "jsdeps.json")) {
$adds[] = "WARNING: JavaScript dependencies update skipped.";
}
// check if js-deps are up-to-date
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];
$dest_file = $target_dir . '/' . $package->dest;
if (!file_exists($dest_file) || sha1_file($dest_file) !== $package->sha1) {
echo "Installing JavaScript dependencies...";
system("cd $target_dir && bin/install-jsdeps.sh");
echo "done.\n\n";
}
}
foreach (array('index.php','.htaccess','config/main.inc.php.dist','config/db.inc.php.dist','CHANGELOG','README.md','UPGRADING','LICENSE') as $file) {
if (!system("rsync -av " . INSTALL_PATH . "$file $target_dir/$file")) {
$err = true;
break;
}
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 "done.\n\n";
if (is_dir("$target_dir/skins/default")) {
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");
}
echo "done.\n\n";
}
if (!$err) {
echo "Running update script at target...\n";
system("cd $target_dir && php bin/update.sh --version=$oldversion" . ($accept ? ' -y' : ''));
system("cd $target_dir && bin/update.sh --version=$oldversion");
echo "All done.\n";
}
}
else {
echo "Update cancelled. See ya!\n";
}
else
echo "Update cancelled. See ya!\n";
?>

@ -1,75 +1,67 @@
#!/bin/sh
PWD=`dirname "$0"`
JS_DIR="$PWD/../program/js"
JS_DIR=`dirname "$0"`/../program/js
JAR_DIR='/tmp'
LANG_IN='ECMASCRIPT5'
CLOSURE_COMPILER_URL='http://dl.google.com/closure-compiler/compiler-latest.zip'
LANG_IN='ECMASCRIPT3'
CLOSURE_COMPILER_URL='http://closure-compiler.googlecode.com/files/compiler-latest.zip'
do_shrink() {
rm -f "$2"
# copy the first comment block with license information for LibreJS
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
rm -f "$2"
java -jar $JAR_DIR/compiler.jar --compilation_level=SIMPLE_OPTIMIZATIONS --js="$1" --js_output_file="$2" --language_in="$3"
}
if [ ! -d "$JS_DIR" ]; then
echo "Directory $JS_DIR not found."
exit 1
echo "Directory $JS_DIR not found."
exit 1
fi
if [ ! -w "$JAR_DIR" ]; then
JAR_DIR=$PWD
JAR_DIR=`dirname "$0"`
fi
if java -version >/dev/null 2>&1; then
:
:
else
echo "Java not found. Please ensure that the 'java' program is in your PATH."
exit 1
echo "Java not found. Please ensure that the 'java' program is in your PATH."
exit 1
fi
if [ ! -r "$JAR_DIR/compiler.jar" ]; then
if which wget >/dev/null 2>&1 && which unzip >/dev/null 2>&1; then
wget "$CLOSURE_COMPILER_URL" -O "/tmp/$$.zip"
elif which curl >/dev/null 2>&1 && which unzip >/dev/null 2>&1; then
curl "$CLOSURE_COMPILER_URL" -o "/tmp/$$.zip"
else
echo "Please download $CLOSURE_COMPILER_URL and extract compiler.jar to $JAR_DIR/."
exit 1
fi
unzip -p "/tmp/$$.zip" "*.jar" > "$JAR_DIR/compiler.jar"
rm -f "/tmp/$$.zip"
if which wget >/dev/null 2>&1 && which unzip >/dev/null 2>&1; then
wget "$CLOSURE_COMPILER_URL" -O "/tmp/$$.zip"
elif which curl >/dev/null 2>&1 && which unzip >/dev/null 2>&1; then
curl "$CLOSURE_COMPILER_URL" -o "/tmp/$$.zip"
else
echo "Please download $CLOSURE_COMPILER_URL and extract compiler.jar to $JAR_DIR/."
exit 1
fi
(cd $JAR_DIR && unzip "/tmp/$$.zip" "compiler.jar")
rm -f "/tmp/$$.zip"
fi
# compress single file from argument
if [ $# -gt 0 ]; then
JS_DIR=`dirname "$1"`
JS_FILE="$1"
JS_DIR=`dirname "$1"`
JS_FILE="$1"
if [ $# -gt 1 ]; then
LANG_IN="$2"
fi
if [ $# -gt 1 ]; then
LANG_IN="$2"
fi
echo "Shrinking $JS_FILE"
minfile=`echo $JS_FILE | sed -e 's/\.js$/\.min\.js/'`
do_shrink "$JS_FILE" "$minfile" "$LANG_IN"
exit
if [ ! -r "${JS_FILE}.src" ]; then
mv "$JS_FILE" "${JS_FILE}.src"
fi
echo "Shrinking $JS_FILE"
do_shrink "${JS_FILE}.src" "$JS_FILE" "$LANG_IN"
exit
fi
DIRS="$PWD/../program/js $PWD/../skins/* $PWD/../plugins/* $PWD/../plugins/*/skins/* $PWD/../plugins/managesieve/codemirror/lib"
# default: compress application scripts
for dir in $DIRS; do
for file in $dir/*.js; do
echo "$file" | grep -e '.min.js$' >/dev/null
if [ $? -eq 0 ]; then
continue
fi
if [ ! -f "$file" ]; then
continue
fi
echo "Shrinking $file"
minfile=`echo $file | sed -e 's/\.js$/\.min\.js/'`
do_shrink "$file" "$minfile" "$LANG_IN"
done
for fn in app common googiespell list; do
if [ -r "$JS_DIR/${fn}.js.src" ]; then
echo "$JS_DIR/${fn}.js.src already exists, not overwriting"
else
mv "$JS_DIR/${fn}.js" "$JS_DIR/${fn}.js.src"
fi
echo "Shrinking $JS_DIR/${fn}.js"
do_shrink "$JS_DIR/${fn}.js.src" "$JS_DIR/${fn}.js" "$LANG_IN"
done

@ -0,0 +1,14 @@
#!/bin/sh
JS_DIR=`dirname "$0"`/../program/js
if [ ! -d "$JS_DIR" ]; then
echo "Directory $JS_DIR not found."
exit 1
fi
for fn in app common googiespell list; do
if [ -r "$JS_DIR/${fn}.js.src" ]; then
mv "$JS_DIR/${fn}.js.src" "$JS_DIR/${fn}.js"
echo "Reverted $JS_DIR/${fn}.js"
fi
done

@ -1,23 +0,0 @@
#!/bin/sh
TITLE="Roundcube Webmail"
PACKAGES="Webmail"
INSTALL_PATH="`dirname $0`/.."
PATH_PROJECT=$INSTALL_PATH/program/include
PATH_FRAMEWORK=$INSTALL_PATH/program/lib/Roundcube
PATH_DOCS=$INSTALL_PATH/doc/phpdoc
BIN_PHPDOC="`/usr/bin/which phpdoc`"
if [ ! -x "$BIN_PHPDOC" ]
then
echo "phpdoc not found: $BIN_PHPDOC"
exit 1
fi
OUTPUTFORMAT=HTML
TEMPLATE=responsive-twig
# make documentation
$BIN_PHPDOC -d $PATH_PROJECT,$PATH_FRAMEWORK -t $PATH_DOCS --title "$TITLE" \
--defaultpackagename $PACKAGES --template=$TEMPLATE

@ -2,9 +2,10 @@
<?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, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
@ -17,49 +18,65 @@
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
define('INSTALL_PATH', realpath(dirname(__FILE__) . '/..') . '/' );
require_once INSTALL_PATH.'program/include/clisetup.php';
function print_usage()
{
print "Usage: moduserprefs.sh [options] pref-name [pref-value]\n";
print "Options:\n";
print " --user=user-id User ID in local database\n";
print " --config=path Location of additional configuration file\n";
print " --delete Unset the given preference\n";
print " --type=type Pref-value type: int, bool, string\n";
print "Usage: moduserprefs.sh [--user=user-id] pref-name [pref-value|--delete]\n";
print "--user User ID in local database\n";
print "--delete Unset the given preference\n";
}
// get arguments
$args = rcube_utils::get_opt(array(
'u' => 'user',
'd' => 'delete:bool',
't' => 'type',
'c' => 'config',
));
$args = rcube_utils::get_opt(array('u' => 'user', 'd' => 'delete'));
if ($_SERVER['argv'][1] == 'help') {
print_usage();
exit;
print_usage();
exit;
}
else if (empty($args[0]) || (empty($args[1]) && empty($args['delete']))) {
print "Missing required parameters.\n";
print_usage();
exit;
else if (empty($args[0]) || (!isset($args[1]) && !$args['delete'])) {
print "Missing required parameters.\n";
print_usage();
exit;
}
$pref_name = trim($args[0]);
$pref_value = $args['delete'] ? null : trim($args[1]);
if ($pref_value === null) {
$args['type'] = null;
}
// connect to DB
$rcmail = rcmail::get_instance();
$db = $rcmail->get_dbh();
$db->db_connect('w');
if (!$db->is_connected() || $db->is_error())
die("No DB connection\n" . $db->is_error());
$query = '1=1';
if ($args['user'])
$query = 'user_id=' . intval($args['user']);
// iterate over all users
$sql_result = $db->query("SELECT * FROM " . $rcmail->config->get('db_table_users', 'users')." WHERE $query");
while ($sql_result && ($sql_arr = $db->fetch_assoc($sql_result))) {
echo "Updating prefs for user " . $sql_arr['user_id'] . "...";
$user = new rcube_user($sql_arr['user_id'], $sql_arr);
$prefs = $old_prefs = $user->get_prefs();
$prefs[$pref_name] = $pref_value;
if ($args['config']) {
$rcube = rcube::get_instance();
$rcube->config->load_from_file($args['config']);
if ($prefs != $old_prefs) {
$user->save_prefs($prefs);
echo "saved.\n";
}
else {
echo "nothing changed.\n";
}
}
rcmail_utils::mod_pref($pref_name, $pref_value, $args['user'], $args['type']);
?>

@ -1,104 +1,96 @@
#!/usr/bin/env 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(dirname(__FILE__) . '/..') . '/' );
ini_set('memory_limit', -1);
require_once INSTALL_PATH.'program/include/clisetup.php';
function print_usage()
{
print "Usage: msgexport -h imap-host -u user-name -m mailbox name\n";
print "--host IMAP host\n";
print "--user IMAP user name\n";
print "--mbox Folder name, set to '*' for all\n";
print "--file Output file\n";
print "Usage: msgexport -h imap-host -u user-name -m mailbox name\n";
print "--host IMAP host\n";
print "--user IMAP user name\n";
print "--mbox Folder name, set to '*' for all\n";
print "--file Output file\n";
}
function vputs($str)
{
$out = $GLOBALS['args']['file'] ? STDOUT : STDERR;
fwrite($out, $str);
$out = $GLOBALS['args']['file'] ? STDOUT : STDERR;
fwrite($out, $str);
}
function progress_update($pos, $max)
{
$percent = round(100 * $pos / $max);
vputs(sprintf("%3d%% [%-51s] %d/%d\033[K\r", $percent, @str_repeat('=', $percent / 2) . '>', $pos, $max));
$percent = round(100 * $pos / $max);
vputs(sprintf("%3d%% [%-51s] %d/%d\033[K\r", $percent, @str_repeat('=', $percent / 2) . '>', $pos, $max));
}
function export_mailbox($mbox, $filename)
{
global $IMAP;
global $IMAP;
$IMAP->set_folder($mbox);
$IMAP->set_folder($mbox);
$index = $IMAP->index($mbox, null, 'ASC');
$count = $index->count();
$index = $index->get();
vputs("Getting message list of {$mbox}...");
vputs("$count messages\n");
if ($filename) {
if (!($out = fopen($filename, 'w'))) {
vputs("Cannot write to output file\n");
return;
}
vputs("Writing to $filename\n");
}
else {
$out = STDOUT;
}
for ($i = 0; $i < $count; $i++) {
$headers = $IMAP->get_message_headers($index[$i]);
$from = current(rcube_mime::decode_address_list($headers->from, 1, false));
fwrite($out, sprintf("From %s %s UID %d\n", $from['mailto'], $headers->date, $headers->uid));
$IMAP->get_raw_body($headers->uid, $out);
fwrite($out, "\n\n\n");
progress_update($i+1, $count);
}
vputs("\ncomplete.\n");
if ($filename) {
fclose($out);
}
vputs("Getting message list of {$mbox}...");
vputs("$count messages\n");
if ($filename)
{
if (!($out = fopen($filename, 'w')))
{
vputs("Cannot write to output file\n");
return;
}
vputs("Writing to $filename\n");
}
else
$out = STDOUT;
for ($i = 0; $i < $count; $i++)
{
$headers = $IMAP->get_message_headers($index[$i]);
$from = current(rcube_mime::decode_address_list($headers->from, 1, false));
fwrite($out, sprintf("From %s %s UID %d\n", $from['mailto'], $headers->date, $headers->uid));
fwrite($out, $IMAP->print_raw_body($headers->uid));
fwrite($out, "\n\n\n");
progress_update($i+1, $count);
}
vputs("\ncomplete.\n");
if ($filename)
fclose($out);
}
// get arguments
$opts = array('h' => 'host', 'u' => 'user', 'p' => 'pass', 'm' => 'mbox', 'f' => 'file');
$args = rcube_utils::get_opt($opts) + array('host' => 'localhost', 'mbox' => 'INBOX');
if ($_SERVER['argv'][1] == 'help') {
print_usage();
exit;
if ($_SERVER['argv'][1] == 'help')
{
print_usage();
exit;
}
else if (!$args['host']) {
vputs("Missing required parameters.\n");
print_usage();
exit;
else if (!$args['host'])
{
vputs("Missing required parameters.\n");
print_usage();
exit;
}
// prompt for username if not set
if (empty($args['user'])) {
vputs("IMAP user: ");
$args['user'] = trim(fgets(STDIN));
if (empty($args['user']))
{
vputs("IMAP user: ");
$args['user'] = trim(fgets(STDIN));
}
// prompt for password
@ -107,39 +99,45 @@ $args['pass'] = rcube_utils::prompt_silent("Password: ");
// parse $host URL
$a_host = parse_url($args['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;
$imap_port = isset($a_host['port']) ? $a_host['port'] : ($imap_ssl ? 993 : 143);
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;
$imap_port = isset($a_host['port']) ? $a_host['port'] : ($imap_ssl ? 993 : 143);
}
else {
$host = $args['host'];
$imap_port = 143;
else
{
$host = $args['host'];
$imap_port = 143;
}
// instantiate IMAP class
$IMAP = new rcube_imap(null);
// try to connect to IMAP server
if ($IMAP->connect($host, $args['user'], $args['pass'], $imap_port, $imap_ssl)) {
vputs("IMAP login successful.\n");
if ($IMAP->connect($host, $args['user'], $args['pass'], $imap_port, $imap_ssl))
{
vputs("IMAP login successful.\n");
$filename = null;
$mailboxes = $args['mbox'] == '*' ? $IMAP->list_folders(null) : array($args['mbox']);
$filename = null;
$mailboxes = $args['mbox'] == '*' ? $IMAP->list_folders(null) : array($args['mbox']);
foreach ($mailboxes as $mbox) {
if ($args['file'])
$filename = preg_replace('/\.[a-z0-9]{3,4}$/i', '', $args['file']) . asciiwords($mbox) . '.mbox';
else if ($args['mbox'] == '*')
$filename = asciiwords($mbox) . '.mbox';
foreach ($mailboxes as $mbox)
{
if ($args['file'])
$filename = preg_replace('/\.[a-z0-9]{3,4}$/i', '', $args['file']) . asciiwords($mbox) . '.mbox';
else if ($args['mbox'] == '*')
$filename = asciiwords($mbox) . '.mbox';
if ($args['mbox'] == '*' && in_array(strtolower($mbox), array('junk','spam','trash'))) {
continue;
}
if ($args['mbox'] == '*' && in_array(strtolower($mbox), array('junk','spam','trash')))
continue;
export_mailbox($mbox, $filename);
}
export_mailbox($mbox, $filename);
}
}
else {
vputs("IMAP login failed.\n");
else
{
vputs("IMAP login failed.\n");
}
?>

@ -1,31 +1,18 @@
#!/usr/bin/env 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(dirname(__FILE__) . '/..') . '/' );
ini_set('memory_limit', -1);
require_once INSTALL_PATH.'program/include/clisetup.php';
function print_usage()
{
print "Usage: msgimport -h imap-host -u user-name -m mailbox -f message-file\n";
print "--host IMAP host\n";
print "--user IMAP user name\n";
print "--mbox Target mailbox\n";
print "--file Message file to upload\n";
print "Usage: msgimport -h imap-host -u user-name -m mailbox -f message-file\n";
print "--host IMAP host\n";
print "--user IMAP user name\n";
print "--mbox Target mailbox\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');
$args = rcube_utils::get_opt($opts) + array('host' => 'localhost', 'mbox' => 'INBOX');
if ($_SERVER['argv'][1] == 'help') {
print_usage();
exit;
if ($_SERVER['argv'][1] == 'help')
{
print_usage();
exit;
}
else if (!($args['host'] && $args['file'])) {
print "Missing required parameters.\n";
print_usage();
exit;
else if (!($args['host'] && $args['file']))
{
print "Missing required parameters.\n";
print_usage();
exit;
}
else if (!is_file($args['file'])) {
rcube::raise_error("Cannot read message file.", false, true);
else if (!is_file($args['file']))
{
rcube::raise_error("Cannot read message file.", false, true);
}
// prompt for username if not set
if (empty($args['user'])) {
//fwrite(STDOUT, "Please enter your name\n");
echo "IMAP user: ";
$args['user'] = trim(fgets(STDIN));
if (empty($args['user']))
{
//fwrite(STDOUT, "Please enter your name\n");
echo "IMAP user: ";
$args['user'] = trim(fgets(STDIN));
}
// prompt for password
if (empty($args['pass'])) {
$args['pass'] = rcube_utils::prompt_silent("Password: ");
if (empty($args['pass']))
{
$args['pass'] = rcube_utils::prompt_silent("Password: ");
}
// parse $host URL
$a_host = parse_url($args['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;
$imap_port = isset($a_host['port']) ? $a_host['port'] : ($imap_ssl ? 993 : 143);
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;
$imap_port = isset($a_host['port']) ? $a_host['port'] : ($imap_ssl ? 993 : 143);
}
else {
$host = $args['host'];
$imap_port = 143;
else
{
$host = $args['host'];
$imap_port = 143;
}
// instantiate IMAP class
$IMAP = new rcube_imap(null);
// try to connect to IMAP server
if ($IMAP->connect($host, $args['user'], $args['pass'], $imap_port, $imap_ssl)) {
print "IMAP login successful.\n";
print "Uploading messages...\n";
$count = 0;
$message = $lastline = '';
$fp = fopen($args['file'], 'r');
while (($line = fgets($fp)) !== false) {
if (preg_match('/^From\s+-/', $line) && $lastline == '') {
if (!empty($message)) {
if ($IMAP->save_message($args['mbox'], rtrim($message)))
$count++;
else
rcube::raise_error("Failed to save message to {$args['mbox']}", false, true);
$message = '';
}
continue;
}
$message .= $line;
$lastline = rtrim($line);
}
if (!empty($message) && $IMAP->save_message($args['mbox'], rtrim($message)))
$count++;
// upload message from file
if ($count)
print "$count messages successfully added to {$args['mbox']}.\n";
else
print "Adding messages failed!\n";
if ($IMAP->connect($host, $args['user'], $args['pass'], $imap_port, $imap_ssl))
{
print "IMAP login successful.\n";
print "Uploading messages...\n";
$count = 0;
$message = $lastline = '';
$fp = fopen($args['file'], 'r');
while (($line = fgets($fp)) !== false)
{
if (preg_match('/^From\s+-/', $line) && $lastline == '')
{
if (!empty($message))
{
if ($IMAP->save_message($args['mbox'], rtrim($message)))
$count++;
else
rcube::raise_error("Failed to save message to {$args['mbox']}", false, true);
$message = '';
}
continue;
}
$message .= $line;
$lastline = rtrim($line);
}
if (!empty($message) && $IMAP->save_message($args['mbox'], rtrim($message)))
$count++;
// upload message from file
if ($count)
print "$count messages successfully added to {$args['mbox']}.\n";
else
print "Adding messages failed!\n";
}
else {
rcube::raise_error("IMAP login failed.", false, true);
else
{
rcube::raise_error("IMAP login failed.", false, true);
}
?>

@ -1,106 +0,0 @@
#!/usr/bin/env 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. |
| |
| PURPOSE: |
| Convert a plugin's package.xml file into a composer.json description |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <thomas@roundcube.net> |
+-----------------------------------------------------------------------+
*/
ini_set('error_reporting', E_ALL & ~E_NOTICE);
list(, $filename, $vendor) = $_SERVER['argv'];
if (!$filename || !is_readable($filename)) {
die("Invalid input file name!\nUsage: " . $_SERVER['argv'][0] . " XMLFILE VENDOR\n");
}
if (!$vendor) {
$vendor = 'anonymous';
}
$package = new SimpleXMLElement(file_get_contents($filename));
$data = array(
'name' => $vendor . '/' . strval($package->name),
'type' => 'roundcube-plugin',
'description' => trim(strval($package->description), '- ') ? trim(strval($package->description)) : trim(strval($package->summary)),
'homepage' => strval($package->uri),
'license' => 'GPLv3+',
'version' => strval($package->version->release),
'authors' => array(),
'repositories' => array(
array('type' => 'composer', 'url' => 'https://plugins.roundcube.net'),
),
'require' => array(
'php' => '>=5.3.0',
'roundcube/plugin-installer' => '>=0.1.3',
),
);
if ($package->license) {
$data['license'] = strval($package->license);
}
if ($package->lead) {
foreach ($package->lead as $lead) {
if (strval($lead->active) == 'no') {
continue;
}
$data['authors'][] = array(
'name' => strval($lead->name),
'email' => strval($lead->email),
'role' => 'Lead',
);
}
}
if ($devs = $package->developer) {
foreach ($package->developer as $dev) {
$data['authors'][] = array(
'name' => strval($dev->name),
'email' => strval($dev->email),
'role' => 'Developer',
);
}
}
if ($package->dependencies->required->extension) {
foreach ($package->dependencies->required->extension as $ext) {
$data['require']['ext-' . strval($ext->name)] = '*';
}
}
// remove empty values
$data = array_filter($data);
// use the JSON encoder from the Composer package
if (is_file('composer.phar')) {
include 'phar://composer.phar/src/Composer/Json/JsonFile.php';
echo \Composer\Json\JsonFile::encode($data);
}
// PHP 5.4's json_encode() does the job, too
else if (defined('JSON_PRETTY_PRINT')) {
$flags = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT & JSON_UNESCAPED_SLASHES : 0;
echo json_encode($data, $flags);
}
else {
fwrite(STDERR,
"FAILED! composer.phar not found in current directory.
Please download it from http://getcomposer.org/download/ or with
curl -s http://getcomposer.org/installer | php
");
}
echo "\n";

@ -1,44 +0,0 @@
#!/bin/sh
# In 'translator' mode files will contain empty translated texts
# where translation is not available, we'll remove these later
# Note: there's a bug in txclib, so if the command below doesn't
# work see https://github.com/transifex/transifex-client/commit/a80320735973dd608b48520bf3b89ad53e2b088b
tx --debug pull -a -f --mode translator
PWD=`dirname "$0"`
do_clean()
{
# do not cleanup en_US files
echo "$1" | grep -v en_US > /dev/null || return
echo "Cleaning $1"
# remove untranslated/empty texts
perl -pi -e "s/^\\\$(labels|messages)\[[^]]+\]\s+=\s+'';\n//" $1
perl -pi -e "s/^\\\$(labels|messages)\[[^]]+\]\s+=\s+\"\";\n//" $1
# remove variable initialization
perl -pi -e "s/^\\\$(labels|messages)\s*=\s*array\(\);\n//" $1
# remove (one-line) comments
perl -pi -e "s/^\\/\\/.*//" $1
# remove empty lines (but not in file header)
perl -ne 'print if ($. < 18 || length($_) > 1)' $1 > $1.tmp
mv $1.tmp $1
}
# clean up translation files
for file in $PWD/../program/localization/*/*.inc; do
do_clean $file
done
for file in $PWD/../plugins/*/localization/*.inc; do
do_clean $file
done
# remove empty localization files
for file in $PWD/../program/localization/*/labels.inc; do grep -q -E '\$labels' $file || rm $file; done
for file in $PWD/../program/localization/*/timezones.inc; do grep -q -E '\$labels' $file || rm $file; done
for file in $PWD/../program/localization/*/messages.inc; do grep -q -E '\$messages' $file || rm $file; done
for file in $PWD/../plugins/*/localization/*.inc; do grep -q -E '\$(labels|messages)' $file || rm $file; done

@ -2,9 +2,10 @@
<?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-2011, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
@ -18,276 +19,152 @@
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
define('INSTALL_PATH', realpath(dirname(__FILE__) . '/..') . '/' );
require_once INSTALL_PATH . 'program/include/clisetup.php';
require_once INSTALL_PATH . 'installer/rcube_install.php';
// get arguments
$opts = rcube_utils::get_opt(array('v' => 'version', 'y' => 'accept:bool'));
$opts = rcube_utils::get_opt(array('v' => 'version'));
// ask user if no version is specified
if (!$opts['version']) {
echo "What version are you upgrading from? Type '?' if you don't know.\n";
if (($input = trim(fgets(STDIN))) && preg_match('/^[0-9.]+[a-z0-9-]*$/', $input)) {
$opts['version'] = $input;
}
else {
$opts['version'] = RCMAIL_VERSION;
}
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))
$opts['version'] = $input;
else
$opts['version'] = RCMAIL_VERSION;
}
$RCI = rcmail_install::get_instance();
$RCI->load_config();
if ($RCI->configured) {
$success = true;
if (($messages = $RCI->check_config($opts['version'])) || $RCI->legacy_config) {
$success = false;
$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++;
}
}
// list obsolete config options (just a notice)
if (is_array($messages['obsolete'])) {
echo "NOTICE: Obsolete config options:\n";
echo "(You still have some obsolete or inexistent properties set."
. " This isn't a problem but should be noticed)\n";
foreach ($messages['obsolete'] as $msg) {
echo "- '" . $msg['prop'] . ($msg['name'] ? "': " . $msg['name'] : "'") . "\n";
$err++;
}
}
if (!$err && $RCI->legacy_config) {
echo "WARNING: Your configuration needs to be migrated!\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";
$err++;
}
// ask user to update config files
if ($err) {
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
if ($opts['accept'] || strtolower($input) == 'y') {
$error = $written = false;
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 (!empty($messages['defaults'])) {
echo "WARNING: Changed defaults (These config options have new default values):\n";
if ($opts['version'] && version_compare(version_parse($opts['version']), version_parse(RCMAIL_VERSION), '>='))
die("Nothing to be done here. Bye!\n");
foreach ($messages['defaults'] as $opt) {
echo "- '{$opt}'\n";
}
}
// check dependencies based on the current configuration
if (is_array($messages['dependencies'])) {
echo "WARNING: Dependency check failed!\n";
echo "(Some of your configuration settings require other options to be configured "
. "or additional PHP modules to be installed)\n";
foreach ($messages['dependencies'] as $msg) {
echo "- " . $msg['prop'] . ': ' . $msg['explain'] . "\n";
}
$RCI = rcube_install::get_instance();
$RCI->load_config();
echo "Please fix your config files and run this script again!\n";
echo "See ya.\n";
}
if ($RCI->configured) {
$success = true;
if ($messages = $RCI->check_config()) {
$success = false;
$err = 0;
// list missing config options
if (is_array($messages['missing'])) {
echo "WARNING: Missing config options:\n";
echo "(These config options should be present in the current configuration)\n";
foreach ($messages['missing'] as $msg) {
echo "- '" . $msg['prop'] . ($msg['name'] ? "': " . $msg['name'] : "'") . "\n";
$err++;
}
echo "\n";
}
// check file type detection
if ($RCI->check_mime_detection()) {
echo "WARNING: File type detection doesn't work properly!\n";
echo "Please check the 'mime_magic' config option or the finfo functions of PHP and run this script again.\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";
}
// 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";
// check database schema
if ($RCI->config['db_dsnw']) {
echo "Executing database schema update.\n";
$success = rcmail_utils::db_update(INSTALL_PATH . 'SQL', 'roundcube', $opts['version'],
array('errors' => true));
foreach ($messages['replaced'] as $msg) {
echo "- '" . $msg['prop'] . "' was replaced by '" . $msg['replacement'] . "'\n";
$err++;
}
echo "\n";
}
// update composer dependencies
if (is_file(INSTALL_PATH . 'composer.json') && is_readable(INSTALL_PATH . 'composer.json-dist')) {
$composer_data = json_decode(file_get_contents(INSTALL_PATH . 'composer.json'), true);
$composer_template = json_decode(file_get_contents(INSTALL_PATH . 'composer.json-dist'), true);
$comsposer_json = null;
// update the require section with the new dependencies
if (is_array($composer_data['require']) && is_array($composer_template['require'])) {
$composer_data['require'] = array_merge($composer_data['require'], $composer_template['require']);
// remove obsolete packages
$old_packages = array(
'pear-pear.php.net/net_socket',
'pear-pear.php.net/auth_sasl',
'pear-pear.php.net/net_idna2',
'pear-pear.php.net/mail_mime',
'pear-pear.php.net/net_smtp',
'pear-pear.php.net/crypt_gpg',
'pear-pear.php.net/net_sieve',
'pear/mail_mime-decode',
'roundcube/net_sieve',
'endroid/qrcode',
);
foreach ($old_packages as $pkg) {
if (array_key_exists($pkg, $composer_data['require'])) {
unset($composer_data['require'][$pkg]);
}
}
}
// update the repositories section with the new dependencies
if (is_array($composer_template['repositories'])) {
if (!is_array($composer_data['repositories'])) {
$composer_data['repositories'] = array();
}
foreach ($composer_template['repositories'] as $repo) {
$rkey = $repo['type'] . preg_replace('/^https?:/', '', $repo['url']) . $repo['package']['name'];
$existing = false;
foreach ($composer_data['repositories'] as $k => $_repo) {
if ($rkey == $_repo['type'] . preg_replace('/^https?:/', '', $_repo['url']) . $_repo['package']['name']) {
// switch to https://
if (isset($_repo['url']) && strpos($_repo['url'], 'http://') === 0) {
$composer_data['repositories'][$k]['url'] = 'https:' . substr($_repo['url'], 5);
}
// list obsolete config options (just a notice)
if (is_array($messages['obsolete'])) {
echo "NOTICE: Obsolete config options:\n";
echo "(You still have some obsolete or inexistent properties set. This isn't a problem but should be noticed)\n";
$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']);
}
foreach ($messages['obsolete'] as $msg) {
echo "- '" . $msg['prop'] . ($msg['name'] ? "': " . $msg['name'] : "'") . "\n";
$err++;
}
echo "\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);
// ask user to update config files
if ($err) {
echo "Do you want me to fix your local configuration? (y/N)\n";
$input = trim(fgets(STDIN));
// positive: let's merge the local config with the defaults
if (strtolower($input) == 'y') {
$copy1 = $copy2 = $write1 = $write2 = false;
// backup current config
echo ". backing up the current config files...\n";
$copy1 = copy(RCMAIL_CONFIG_DIR . '/main.inc.php', RCMAIL_CONFIG_DIR . '/main.old.php');
$copy2 = copy(RCMAIL_CONFIG_DIR . '/db.inc.php', RCMAIL_CONFIG_DIR . '/db.old.php');
if ($copy1 && $copy2) {
$RCI->merge_config();
echo ". writing " . RCMAIL_CONFIG_DIR . "/main.inc.php...\n";
$write1 = file_put_contents(RCMAIL_CONFIG_DIR . '/main.inc.php', $RCI->create_config('main', true));
echo ". writing " . RCMAIL_CONFIG_DIR . "/main.db.php...\n";
$write2 = file_put_contents(RCMAIL_CONFIG_DIR . '/db.inc.php', $RCI->create_config('db', true));
}
// 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);
// Success!
if ($write1 && $write2) {
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";
}
}
else {
$success = false;
$comsposer_json = null;
echo "Failed to write config files!\n";
echo "Grant write privileges to the current user or update the files manually according to the above messages.\n";
}
// write updated composer.json back to disk
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 = '';
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";
}
else {
echo "Please update your config files manually according to the above messages.\n";
}
}
// index contacts for fulltext searching
if ($opts['version'] && version_compare(version_parse($opts['version']), '0.6.0', '<')) {
rcmail_utils::indexcontacts();
}
// check dependencies based on the current configuration
if (is_array($messages['dependencies'])) {
echo "WARNING: Dependency check failed!\n";
echo "(Some of your configuration settings require other options to be configured or additional PHP modules to be installed)\n";
if ($success) {
echo "This instance of Roundcube is up-to-date.\n";
echo "Have fun!\n";
foreach ($messages['dependencies'] as $msg) {
echo "- " . $msg['prop'] . ': ' . $msg['explain'] . "\n";
}
echo "Please fix your config files and run this script again!\n";
echo "See ya.\n";
}
}
// check database schema
if ($RCI->config['db_dsnw']) {
echo "Executing database schema update.\n";
system(INSTALL_PATH . "bin/updatedb.sh --package=roundcube --version=" . $opts['version']
. " --dir=" . INSTALL_PATH . DIRECTORY_SEPARATOR . "SQL", $res);
$success = !$res;
}
// index contacts for fulltext searching
if (version_compare(version_parse($opts['version']), '0.6.0', '<')) {
system(INSTALL_PATH . 'bin/indexcontacts.sh');
}
if ($success) {
echo "This instance of Roundcube is up-to-date.\n";
echo "Have fun!\n";
}
}
else {
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 "This instance of Roundcube is not yet configured!\n";
echo "Open http://url-to-roundcube/installer/ in your browser and follow the instuctions.\n";
}
?>

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

Loading…
Cancel
Save