作者 邓超

init

正在显示 100 个修改的文件 包含 3636 行增加0 行删除

要显示太多修改。

为保证性能只显示 100 of 100+ 个文件。

  1 +.idea
  2 +composer.lock
  3 +.user.ini
  4 +temp/*
  5 +logs/*
  1 +<!doctype html>
  2 +<html>
  3 +<head>
  4 +<meta charset="utf-8">
  5 +<meta http-equiv="X-UA-Compatible" content="IE=edge">
  6 +<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  7 +<title>404</title>
  8 +<style>
  9 + body{
  10 + background-color:#444;
  11 + font-size:14px;
  12 + }
  13 + h3{
  14 + font-size:60px;
  15 + color:#eee;
  16 + text-align:center;
  17 + padding-top:30px;
  18 + font-weight:normal;
  19 + }
  20 +</style>
  21 +</head>
  22 +
  23 +<body>
  24 +<h3>404,您请求的文件不存在!</h3>
  25 +</body>
  26 +</html>
此 diff 太大无法显示。
  1 +INTRODUCTION
  2 +============
  3 +
  4 +This file describes the basic steps to install Roundcube Webmail on your
  5 +web server. For additional information, please also consult the project's
  6 +wiki page at https://github.com/roundcube/roundcubemail/wiki
  7 +
  8 +
  9 +REQUIREMENTS
  10 +============
  11 +
  12 +* An IMAP, HTTP and SMTP server
  13 +* .htaccess support allowing overrides for DirectoryIndex
  14 +* PHP Version 5.5 or greater including:
  15 + - PCRE, DOM, JSON, Session, Sockets, OpenSSL, Mbstring, Filter, Ctype, Intl (required)
  16 + - PHP PDO with driver for either MySQL, PostgreSQL, SQL Server, Oracle or SQLite (required)
  17 + - Iconv, Zip, Fileinfo, Exif (recommended)
  18 + - LDAP for LDAP addressbook support (optional)
  19 + - GD, Imagick (optional thumbnails generation, QR-code)
  20 +* PEAR and PEAR packages distributed with Roundcube or external.
  21 + See composer.json-dist for the list of required packages.
  22 +* php.ini options:
  23 + - error_reporting E_ALL & ~E_NOTICE & ~E_STRICT
  24 + - memory_limit > 16MB
  25 + - file_uploads enabled (for uploading attachments and import files)
  26 + - session.auto_start disabled
  27 + - suhosin.session.encrypt disabled
  28 + - mbstring.func_overload disabled
  29 + - pcre.backtrack_limit >= 100000
  30 +* A MySQL, PostgreSQL, MS SQL Server (2005 or newer), Oracle database
  31 + or SQLite v3 support in PHP - with permission to create tables
  32 +* Composer installed either locally or globally (https://getcomposer.org)
  33 +
  34 +
  35 +INSTALLATION
  36 +============
  37 +
  38 +1. Decompress and put this folder somewhere inside your document root.
  39 + Note: Make sure files have proper owner/group for your setup. If you use
  40 + tar command `--no-same-owner` option might be helpful.
  41 +2. In case you don't use the so-called "complete" release package,
  42 + you have to install PHP and javascript dependencies.
  43 + 2.1. Install PHP dependencies using composer:
  44 + - get composer from https://getcomposer.org/download/
  45 + - rename the composer.json-dist file into composer.json
  46 + - if you want to use LDAP address books, enable the LDAP libraries in your
  47 + composer.json file by moving the items from "suggest" to the "require"
  48 + section (remove the explanation texts after the version!).
  49 + - run `php composer.phar install --no-dev`
  50 + 2.2. Install Javascript dependencies by executing `bin/install-jsdeps.sh` script.
  51 +3. Make sure that the following directories (and the files within)
  52 + are writable by the webserver
  53 + - /temp
  54 + - /logs
  55 +4. Create a new database and a database user for Roundcube (see DATABASE SETUP)
  56 +5. Point your browser to http://url-to-roundcube/installer/
  57 +6. Follow the instructions of the install script (or see MANUAL CONFIGURATION)
  58 +7. After creating and testing the configuration, remove the installer directory
  59 + ------------------------------------------
  60 + IMPORTANT: REMOVE THE INSTALLER DIRECTORY!
  61 + ------------------------------------------
  62 +8. If you use git sources compile css files for the Elastic skin (required
  63 + lessc >= 2.5.2):
  64 + $ cd skins/elastic
  65 + $ lessc --clean-css="--s1 --advanced" styles/styles.less > styles/styles.min.css
  66 + $ lessc --clean-css="--s1 --advanced" styles/print.less > styles/print.min.css
  67 + $ lessc --clean-css="--s1 --advanced" styles/embed.less > styles/embed.min.css
  68 +9. Check Known Issues section of this file
  69 +
  70 +
  71 +CONFIGURATION HINTS
  72 +===================
  73 +
  74 +IMPORTANT! Read all comments in defaults.inc.php, understand them
  75 +and configure your installation to be not surprised by default behaviour.
  76 +
  77 +Roundcube writes internal errors to the 'errors.log' log file located in the logs
  78 +directory which can be configured in config/config.inc.php. If you want ordinary
  79 +PHP errors to be logged there as well, set error_log in php.ini or .htaccess file.
  80 +
  81 +Roundcube forces display_errors=Off and log_errors=On.
  82 +
  83 +By default the session cookie settings of PHP are not modified by Roundcube.
  84 +However if you want to limit the session cookies to the directory where
  85 +Roundcube resides you can set session.cookie_path in the php.ini or .htaccess file.
  86 +
  87 +More about PHP settings: https://github.com/roundcube/roundcubemail/wiki/Installation#php-configuration
  88 +
  89 +
  90 +DATABASE SETUP
  91 +==============
  92 +
  93 +Note: Database for Roundcube must use UTF-8 character set.
  94 +Note: See defaults.inc.php file for examples of DSN configuration.
  95 +
  96 +* MySQL
  97 +-------
  98 +Setting up the mysql database can be done by creating an empty database,
  99 +importing the table layout and granting the proper permissions to the
  100 +roundcube user. Here is an example of that procedure:
  101 +
  102 +# mysql
  103 +> CREATE DATABASE roundcubemail CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  104 +> CREATE USER roundcube@localhost IDENTIFIED BY 'password';
  105 +> GRANT ALL PRIVILEGES ON roundcubemail.* TO roundcube@localhost;
  106 +> quit
  107 +
  108 +Note 1: 'password' is the master password for the roundcube user. It is strongly
  109 +recommended you replace this with a more secure password. Please keep in
  110 +mind that you must specify this password later in 'config/config.inc.php'.
  111 +
  112 +Note 2: When using MySQL < 5.7.7 or MariaDB < 10.2.2 it is required to configure
  113 +the database engine with:
  114 + innodb_large_prefix=1
  115 + innodb_file_per_table=1
  116 + innodb_file_format=Barracuda
  117 +
  118 +Now you can run the Installer or configure the database access options in
  119 +'config/config.inc.php' and run: `bin/initdb.sh --dir=SQL`.
  120 +
  121 +
  122 +* SQLite
  123 +--------
  124 +Versions of sqlite database engine older than 3.0 aren't supported.
  125 +Database file and structure is created automatically by Roundcube.
  126 +Make sure your configuration points to some file location and that the
  127 +webserver can write to the file and the directory containing the file.
  128 +
  129 +
  130 +* PostgreSQL
  131 +------------
  132 +To use Roundcube with PostgreSQL support you have to follow these
  133 +simple steps, which have to be done as the postgres system user (or
  134 +which ever is the database superuser):
  135 +
  136 +$ createuser -P roundcube
  137 +$ createdb -O roundcube -E UNICODE roundcubemail
  138 +
  139 +Note: in some system configurations you might need to add '-U postgres' to
  140 +createuser and createdb commands.
  141 +
  142 +Now you can run the Installer or configure the database access options in
  143 +'config/config.inc.php' and run: `bin/initdb.sh --dir=SQL`.
  144 +
  145 +
  146 +* Microsoft SQL Server
  147 +----------------------
  148 +Language/locale of the database must be set to us_english (1033). More info
  149 +on this at https://github.com/roundcube/roundcubemail/issues/4078.
  150 +
  151 +
  152 +Database cleaning
  153 +-----------------
  154 +To keep your database slick and clean we recommend to periodically execute
  155 +bin/cleandb.sh which finally removes all records that are marked as deleted.
  156 +Best solution is to install a cronjob running this script daily.
  157 +
  158 +
  159 +MANUAL CONFIGURATION
  160 +====================
  161 +
  162 +First of all, copy the sample configuration file config/config.inc.php.sample
  163 +to config/config.inc.php and make the necessary adjustments according to your
  164 +environment and your needs. More configuration options can be copied from the
  165 +config/defaults.inc.php file into your local config.inc.php file as needed.
  166 +Read the comments above the individual configuration options to find out what
  167 +they do or read https://github.com/roundcube/roundcubemail/wiki/Installation
  168 +for even more guidance.
  169 +
  170 +The maximum size of email attachments and other file uploads is controlled by
  171 +PHP settings: upload_max_filesize and post_max_size. Read more about PHP
  172 +settings at https://github.com/roundcube/roundcubemail/wiki/Installation#php-configuration.
  173 +
  174 +
  175 +SECURE YOUR INSTALLATION
  176 +========================
  177 +
  178 +Access through the webserver to the following directories should be denied:
  179 +
  180 + /config
  181 + /temp
  182 + /logs
  183 +
  184 +Roundcube uses .htaccess files to protect these directories, so be sure to
  185 +allow override of the Limit directives to get them taken into account. The
  186 +package also ships a .htaccess file in the root directory which defines some
  187 +rewrite rules. In order to properly secure your installation, please enable
  188 +mod_rewrite for Apache webserver and double check access to the above listed
  189 +directories and their contents is denied.
  190 +
  191 +NOTE: In Apache 2.4, support for .htaccess files has been disabled by
  192 +default. Therefore you first need to enable this in your Apache main or
  193 +virtual host config by with:
  194 +
  195 + AllowOverride all
  196 +
  197 +For non-apache web servers add equivalent configuration parameters to deny
  198 +direct access to these private resources.
  199 +
  200 +It is also recommended to change the document root to <install path>/public_html
  201 +after installation if Roundcube runs at root of a dedicated virtual host. This
  202 +will automatically keep sensitive files out of reach for http requests.
  203 +
  204 +
  205 +UPGRADING
  206 +=========
  207 +
  208 +If you already have a previous version of Roundcube installed,
  209 +please refer to the instructions in UPGRADING guide.
  210 +
  211 +
  212 +OPTIMISING
  213 +==========
  214 +
  215 +There are two forms of optimization here, compression and caching, both aimed
  216 +at increasing an end user's experience using Roundcube Webmail. Compression
  217 +allows the static web pages to be delivered with less bandwidth. The index.php
  218 +of Roundcube Webmail already enables compression on its output. The settings
  219 +below allow compression to occur for all static files. Caching sets HTTP
  220 +response headers that enable a user's web client to understand what is static
  221 +and how to cache it.
  222 +
  223 +The caching directives used are:
  224 + * Etags - sets at tag so the client can request is the page has changed
  225 + * Cache-control - defines the age of the page and that the page is 'public'
  226 + This enables clients to cache javascript files that don't have private
  227 + information between sessions even if using HTTPS. It also allows proxies
  228 + to share the same cached page between users.
  229 + * Expires - provides another hint to increase the lifetime of static pages.
  230 +
  231 +For more information refer to RFC 2616.
  232 +
  233 +Side effects:
  234 +-------------
  235 +These directives are designed for production use. If you are using this in
  236 +a development environment you may get horribly confused if your webclient
  237 +is caching stuff that you changed on the server. Disabling the expires
  238 +parts below should save you some grief.
  239 +
  240 +If you are changing the skins, it is recommended that you copy content to
  241 +a different directory apart from 'default'.
  242 +
  243 +Apache:
  244 +-------
  245 +To enable these features in apache the following modules need to be enabled:
  246 + * mod_deflate
  247 + * mod_expires
  248 + * mod_headers
  249 +
  250 +The optimization is already included in the .htaccess file in the top
  251 +directory of your installation.
  252 +
  253 +Lighttpd:
  254 +---------
  255 +With Lighttpd the addition of Expire: tags by mod_expire is incompatible with
  256 +the addition of "Cache-control: public". Using Cache-control 'public' is
  257 +used below as it is assumed to give a better caching result.
  258 +
  259 +Enable modules in server.modules:
  260 + "mod_setenv"
  261 + "mod_compress"
  262 +
  263 +Mod_compress is a server side cache of compressed files to improve its performance.
  264 +
  265 +$HTTP["host"] == "www.example.com" {
  266 +
  267 + static-file.etags = "enable"
  268 + # http://redmine.lighttpd.net/projects/lighttpd/wiki/Etag.use-mtimeDetails
  269 + etag.use-mtime = "enable"
  270 +
  271 + # http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:ModSetEnv
  272 + $HTTP["url"] =~ "^/roundcubemail/(plugins|skins|program)" {
  273 + setenv.add-response-header = ( "Cache-Control" => "public, max-age=2592000")
  274 + }
  275 +
  276 + # http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:ModCompress
  277 + # set compress.cache-dir to somewhere outside the docroot.
  278 + compress.cache-dir = var.statedir + "/cache/compress"
  279 +
  280 + compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png")
  281 +}
  282 +
  283 +
  284 +KNOWN ISSUES
  285 +============
  286 +
  287 +Installations with uw-imap server should set imap_disabled_caps = array('ESEARCH')
  288 +in main configuration file. ESEARCH implementation in this server is broken (#1489184).
  289 +
  290 +PHP >= 5.6 validates the ssl certificates by default. It means that
  291 +if IMAP/SMTP certificates are self-signed or use wrong host name you'll get
  292 +connection errors. A solution in such cases is to set imap_conn_options,
  293 +smtp_conn_options and managesieve_conn_options in a way described in config/defaults.inc.php.
  294 +
  295 +If you have problems with temp files or non-working logs make sure temp and logs folders
  296 +are writeable to the user used by http server. Access to them may also be blocked by
  297 +SELINUX. Here's some sample commands for SELINUX:
  298 +
  299 + $ semanage fcontext -a -t httpd_sys_rw_content_t "/path_to_roundcube/logs(/.*)?"
  300 + $ semanage fcontext -a -t httpd_sys_rw_content_t "/path_to_roundcube/temp(/.*)?"
  301 + $ restorecon -Rv /path_to_roundcube/
  302 +
  303 +Microsoft IIS Server by default does not support WOFF fonts used in Elastic skin. It might be
  304 +needed to add following MIME Types definitions (via web.config or IIS Manager):
  305 +
  306 + .woff application/font-woff
  307 + .woff2 application/font-woff2
  308 +
  309 +When installing on Windows be aware we're using symbolic links which may need an additional
  310 +attention. See https://github.com/roundcube/roundcubemail/issues/7151.
  1 + GNU GENERAL PUBLIC LICENSE
  2 + Version 3, 29 June 2007
  3 +
  4 + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
  5 + Everyone is permitted to copy and distribute verbatim copies
  6 + of this license document, but changing it is not allowed.
  7 +
  8 + Preamble
  9 +
  10 + The GNU General Public License is a free, copyleft license for
  11 +software and other kinds of works.
  12 +
  13 + The licenses for most software and other practical works are designed
  14 +to take away your freedom to share and change the works. By contrast,
  15 +the GNU General Public License is intended to guarantee your freedom to
  16 +share and change all versions of a program--to make sure it remains free
  17 +software for all its users. We, the Free Software Foundation, use the
  18 +GNU General Public License for most of our software; it applies also to
  19 +any other work released this way by its authors. You can apply it to
  20 +your programs, too.
  21 +
  22 + When we speak of free software, we are referring to freedom, not
  23 +price. Our General Public Licenses are designed to make sure that you
  24 +have the freedom to distribute copies of free software (and charge for
  25 +them if you wish), that you receive source code or can get it if you
  26 +want it, that you can change the software or use pieces of it in new
  27 +free programs, and that you know you can do these things.
  28 +
  29 + To protect your rights, we need to prevent others from denying you
  30 +these rights or asking you to surrender the rights. Therefore, you have
  31 +certain responsibilities if you distribute copies of the software, or if
  32 +you modify it: responsibilities to respect the freedom of others.
  33 +
  34 + For example, if you distribute copies of such a program, whether
  35 +gratis or for a fee, you must pass on to the recipients the same
  36 +freedoms that you received. You must make sure that they, too, receive
  37 +or can get the source code. And you must show them these terms so they
  38 +know their rights.
  39 +
  40 + Developers that use the GNU GPL protect your rights with two steps:
  41 +(1) assert copyright on the software, and (2) offer you this License
  42 +giving you legal permission to copy, distribute and/or modify it.
  43 +
  44 + For the developers' and authors' protection, the GPL clearly explains
  45 +that there is no warranty for this free software. For both users' and
  46 +authors' sake, the GPL requires that modified versions be marked as
  47 +changed, so that their problems will not be attributed erroneously to
  48 +authors of previous versions.
  49 +
  50 + Some devices are designed to deny users access to install or run
  51 +modified versions of the software inside them, although the manufacturer
  52 +can do so. This is fundamentally incompatible with the aim of
  53 +protecting users' freedom to change the software. The systematic
  54 +pattern of such abuse occurs in the area of products for individuals to
  55 +use, which is precisely where it is most unacceptable. Therefore, we
  56 +have designed this version of the GPL to prohibit the practice for those
  57 +products. If such problems arise substantially in other domains, we
  58 +stand ready to extend this provision to those domains in future versions
  59 +of the GPL, as needed to protect the freedom of users.
  60 +
  61 + Finally, every program is threatened constantly by software patents.
  62 +States should not allow patents to restrict development and use of
  63 +software on general-purpose computers, but in those that do, we wish to
  64 +avoid the special danger that patents applied to a free program could
  65 +make it effectively proprietary. To prevent this, the GPL assures that
  66 +patents cannot be used to render the program non-free.
  67 +
  68 + The precise terms and conditions for copying, distribution and
  69 +modification follow.
  70 +
  71 + TERMS AND CONDITIONS
  72 +
  73 + 0. Definitions.
  74 +
  75 + "This License" refers to version 3 of the GNU General Public License.
  76 +
  77 + "Copyright" also means copyright-like laws that apply to other kinds of
  78 +works, such as semiconductor masks.
  79 +
  80 + "The Program" refers to any copyrightable work licensed under this
  81 +License. Each licensee is addressed as "you". "Licensees" and
  82 +"recipients" may be individuals or organizations.
  83 +
  84 + To "modify" a work means to copy from or adapt all or part of the work
  85 +in a fashion requiring copyright permission, other than the making of an
  86 +exact copy. The resulting work is called a "modified version" of the
  87 +earlier work or a work "based on" the earlier work.
  88 +
  89 + A "covered work" means either the unmodified Program or a work based
  90 +on the Program.
  91 +
  92 + To "propagate" a work means to do anything with it that, without
  93 +permission, would make you directly or secondarily liable for
  94 +infringement under applicable copyright law, except executing it on a
  95 +computer or modifying a private copy. Propagation includes copying,
  96 +distribution (with or without modification), making available to the
  97 +public, and in some countries other activities as well.
  98 +
  99 + To "convey" a work means any kind of propagation that enables other
  100 +parties to make or receive copies. Mere interaction with a user through
  101 +a computer network, with no transfer of a copy, is not conveying.
  102 +
  103 + An interactive user interface displays "Appropriate Legal Notices"
  104 +to the extent that it includes a convenient and prominently visible
  105 +feature that (1) displays an appropriate copyright notice, and (2)
  106 +tells the user that there is no warranty for the work (except to the
  107 +extent that warranties are provided), that licensees may convey the
  108 +work under this License, and how to view a copy of this License. If
  109 +the interface presents a list of user commands or options, such as a
  110 +menu, a prominent item in the list meets this criterion.
  111 +
  112 + 1. Source Code.
  113 +
  114 + The "source code" for a work means the preferred form of the work
  115 +for making modifications to it. "Object code" means any non-source
  116 +form of a work.
  117 +
  118 + A "Standard Interface" means an interface that either is an official
  119 +standard defined by a recognized standards body, or, in the case of
  120 +interfaces specified for a particular programming language, one that
  121 +is widely used among developers working in that language.
  122 +
  123 + The "System Libraries" of an executable work include anything, other
  124 +than the work as a whole, that (a) is included in the normal form of
  125 +packaging a Major Component, but which is not part of that Major
  126 +Component, and (b) serves only to enable use of the work with that
  127 +Major Component, or to implement a Standard Interface for which an
  128 +implementation is available to the public in source code form. A
  129 +"Major Component", in this context, means a major essential component
  130 +(kernel, window system, and so on) of the specific operating system
  131 +(if any) on which the executable work runs, or a compiler used to
  132 +produce the work, or an object code interpreter used to run it.
  133 +
  134 + The "Corresponding Source" for a work in object code form means all
  135 +the source code needed to generate, install, and (for an executable
  136 +work) run the object code and to modify the work, including scripts to
  137 +control those activities. However, it does not include the work's
  138 +System Libraries, or general-purpose tools or generally available free
  139 +programs which are used unmodified in performing those activities but
  140 +which are not part of the work. For example, Corresponding Source
  141 +includes interface definition files associated with source files for
  142 +the work, and the source code for shared libraries and dynamically
  143 +linked subprograms that the work is specifically designed to require,
  144 +such as by intimate data communication or control flow between those
  145 +subprograms and other parts of the work.
  146 +
  147 + The Corresponding Source need not include anything that users
  148 +can regenerate automatically from other parts of the Corresponding
  149 +Source.
  150 +
  151 + The Corresponding Source for a work in source code form is that
  152 +same work.
  153 +
  154 + 2. Basic Permissions.
  155 +
  156 + All rights granted under this License are granted for the term of
  157 +copyright on the Program, and are irrevocable provided the stated
  158 +conditions are met. This License explicitly affirms your unlimited
  159 +permission to run the unmodified Program. The output from running a
  160 +covered work is covered by this License only if the output, given its
  161 +content, constitutes a covered work. This License acknowledges your
  162 +rights of fair use or other equivalent, as provided by copyright law.
  163 +
  164 + You may make, run and propagate covered works that you do not
  165 +convey, without conditions so long as your license otherwise remains
  166 +in force. You may convey covered works to others for the sole purpose
  167 +of having them make modifications exclusively for you, or provide you
  168 +with facilities for running those works, provided that you comply with
  169 +the terms of this License in conveying all material for which you do
  170 +not control copyright. Those thus making or running the covered works
  171 +for you must do so exclusively on your behalf, under your direction
  172 +and control, on terms that prohibit them from making any copies of
  173 +your copyrighted material outside their relationship with you.
  174 +
  175 + Conveying under any other circumstances is permitted solely under
  176 +the conditions stated below. Sublicensing is not allowed; section 10
  177 +makes it unnecessary.
  178 +
  179 + 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
  180 +
  181 + No covered work shall be deemed part of an effective technological
  182 +measure under any applicable law fulfilling obligations under article
  183 +11 of the WIPO copyright treaty adopted on 20 December 1996, or
  184 +similar laws prohibiting or restricting circumvention of such
  185 +measures.
  186 +
  187 + When you convey a covered work, you waive any legal power to forbid
  188 +circumvention of technological measures to the extent such circumvention
  189 +is effected by exercising rights under this License with respect to
  190 +the covered work, and you disclaim any intention to limit operation or
  191 +modification of the work as a means of enforcing, against the work's
  192 +users, your or third parties' legal rights to forbid circumvention of
  193 +technological measures.
  194 +
  195 + 4. Conveying Verbatim Copies.
  196 +
  197 + You may convey verbatim copies of the Program's source code as you
  198 +receive it, in any medium, provided that you conspicuously and
  199 +appropriately publish on each copy an appropriate copyright notice;
  200 +keep intact all notices stating that this License and any
  201 +non-permissive terms added in accord with section 7 apply to the code;
  202 +keep intact all notices of the absence of any warranty; and give all
  203 +recipients a copy of this License along with the Program.
  204 +
  205 + You may charge any price or no price for each copy that you convey,
  206 +and you may offer support or warranty protection for a fee.
  207 +
  208 + 5. Conveying Modified Source Versions.
  209 +
  210 + You may convey a work based on the Program, or the modifications to
  211 +produce it from the Program, in the form of source code under the
  212 +terms of section 4, provided that you also meet all of these conditions:
  213 +
  214 + a) The work must carry prominent notices stating that you modified
  215 + it, and giving a relevant date.
  216 +
  217 + b) The work must carry prominent notices stating that it is
  218 + released under this License and any conditions added under section
  219 + 7. This requirement modifies the requirement in section 4 to
  220 + "keep intact all notices".
  221 +
  222 + c) You must license the entire work, as a whole, under this
  223 + License to anyone who comes into possession of a copy. This
  224 + License will therefore apply, along with any applicable section 7
  225 + additional terms, to the whole of the work, and all its parts,
  226 + regardless of how they are packaged. This License gives no
  227 + permission to license the work in any other way, but it does not
  228 + invalidate such permission if you have separately received it.
  229 +
  230 + d) If the work has interactive user interfaces, each must display
  231 + Appropriate Legal Notices; however, if the Program has interactive
  232 + interfaces that do not display Appropriate Legal Notices, your
  233 + work need not make them do so.
  234 +
  235 + A compilation of a covered work with other separate and independent
  236 +works, which are not by their nature extensions of the covered work,
  237 +and which are not combined with it such as to form a larger program,
  238 +in or on a volume of a storage or distribution medium, is called an
  239 +"aggregate" if the compilation and its resulting copyright are not
  240 +used to limit the access or legal rights of the compilation's users
  241 +beyond what the individual works permit. Inclusion of a covered work
  242 +in an aggregate does not cause this License to apply to the other
  243 +parts of the aggregate.
  244 +
  245 + 6. Conveying Non-Source Forms.
  246 +
  247 + You may convey a covered work in object code form under the terms
  248 +of sections 4 and 5, provided that you also convey the
  249 +machine-readable Corresponding Source under the terms of this License,
  250 +in one of these ways:
  251 +
  252 + a) Convey the object code in, or embodied in, a physical product
  253 + (including a physical distribution medium), accompanied by the
  254 + Corresponding Source fixed on a durable physical medium
  255 + customarily used for software interchange.
  256 +
  257 + b) Convey the object code in, or embodied in, a physical product
  258 + (including a physical distribution medium), accompanied by a
  259 + written offer, valid for at least three years and valid for as
  260 + long as you offer spare parts or customer support for that product
  261 + model, to give anyone who possesses the object code either (1) a
  262 + copy of the Corresponding Source for all the software in the
  263 + product that is covered by this License, on a durable physical
  264 + medium customarily used for software interchange, for a price no
  265 + more than your reasonable cost of physically performing this
  266 + conveying of source, or (2) access to copy the
  267 + Corresponding Source from a network server at no charge.
  268 +
  269 + c) Convey individual copies of the object code with a copy of the
  270 + written offer to provide the Corresponding Source. This
  271 + alternative is allowed only occasionally and noncommercially, and
  272 + only if you received the object code with such an offer, in accord
  273 + with subsection 6b.
  274 +
  275 + d) Convey the object code by offering access from a designated
  276 + place (gratis or for a charge), and offer equivalent access to the
  277 + Corresponding Source in the same way through the same place at no
  278 + further charge. You need not require recipients to copy the
  279 + Corresponding Source along with the object code. If the place to
  280 + copy the object code is a network server, the Corresponding Source
  281 + may be on a different server (operated by you or a third party)
  282 + that supports equivalent copying facilities, provided you maintain
  283 + clear directions next to the object code saying where to find the
  284 + Corresponding Source. Regardless of what server hosts the
  285 + Corresponding Source, you remain obligated to ensure that it is
  286 + available for as long as needed to satisfy these requirements.
  287 +
  288 + e) Convey the object code using peer-to-peer transmission, provided
  289 + you inform other peers where the object code and Corresponding
  290 + Source of the work are being offered to the general public at no
  291 + charge under subsection 6d.
  292 +
  293 + A separable portion of the object code, whose source code is excluded
  294 +from the Corresponding Source as a System Library, need not be
  295 +included in conveying the object code work.
  296 +
  297 + A "User Product" is either (1) a "consumer product", which means any
  298 +tangible personal property which is normally used for personal, family,
  299 +or household purposes, or (2) anything designed or sold for incorporation
  300 +into a dwelling. In determining whether a product is a consumer product,
  301 +doubtful cases shall be resolved in favor of coverage. For a particular
  302 +product received by a particular user, "normally used" refers to a
  303 +typical or common use of that class of product, regardless of the status
  304 +of the particular user or of the way in which the particular user
  305 +actually uses, or expects or is expected to use, the product. A product
  306 +is a consumer product regardless of whether the product has substantial
  307 +commercial, industrial or non-consumer uses, unless such uses represent
  308 +the only significant mode of use of the product.
  309 +
  310 + "Installation Information" for a User Product means any methods,
  311 +procedures, authorization keys, or other information required to install
  312 +and execute modified versions of a covered work in that User Product from
  313 +a modified version of its Corresponding Source. The information must
  314 +suffice to ensure that the continued functioning of the modified object
  315 +code is in no case prevented or interfered with solely because
  316 +modification has been made.
  317 +
  318 + If you convey an object code work under this section in, or with, or
  319 +specifically for use in, a User Product, and the conveying occurs as
  320 +part of a transaction in which the right of possession and use of the
  321 +User Product is transferred to the recipient in perpetuity or for a
  322 +fixed term (regardless of how the transaction is characterized), the
  323 +Corresponding Source conveyed under this section must be accompanied
  324 +by the Installation Information. But this requirement does not apply
  325 +if neither you nor any third party retains the ability to install
  326 +modified object code on the User Product (for example, the work has
  327 +been installed in ROM).
  328 +
  329 + The requirement to provide Installation Information does not include a
  330 +requirement to continue to provide support service, warranty, or updates
  331 +for a work that has been modified or installed by the recipient, or for
  332 +the User Product in which it has been modified or installed. Access to a
  333 +network may be denied when the modification itself materially and
  334 +adversely affects the operation of the network or violates the rules and
  335 +protocols for communication across the network.
  336 +
  337 + Corresponding Source conveyed, and Installation Information provided,
  338 +in accord with this section must be in a format that is publicly
  339 +documented (and with an implementation available to the public in
  340 +source code form), and must require no special password or key for
  341 +unpacking, reading or copying.
  342 +
  343 + 7. Additional Terms.
  344 +
  345 + "Additional permissions" are terms that supplement the terms of this
  346 +License by making exceptions from one or more of its conditions.
  347 +Additional permissions that are applicable to the entire Program shall
  348 +be treated as though they were included in this License, to the extent
  349 +that they are valid under applicable law. If additional permissions
  350 +apply only to part of the Program, that part may be used separately
  351 +under those permissions, but the entire Program remains governed by
  352 +this License without regard to the additional permissions.
  353 +
  354 + When you convey a copy of a covered work, you may at your option
  355 +remove any additional permissions from that copy, or from any part of
  356 +it. (Additional permissions may be written to require their own
  357 +removal in certain cases when you modify the work.) You may place
  358 +additional permissions on material, added by you to a covered work,
  359 +for which you have or can give appropriate copyright permission.
  360 +
  361 + Notwithstanding any other provision of this License, for material you
  362 +add to a covered work, you may (if authorized by the copyright holders of
  363 +that material) supplement the terms of this License with terms:
  364 +
  365 + a) Disclaiming warranty or limiting liability differently from the
  366 + terms of sections 15 and 16 of this License; or
  367 +
  368 + b) Requiring preservation of specified reasonable legal notices or
  369 + author attributions in that material or in the Appropriate Legal
  370 + Notices displayed by works containing it; or
  371 +
  372 + c) Prohibiting misrepresentation of the origin of that material, or
  373 + requiring that modified versions of such material be marked in
  374 + reasonable ways as different from the original version; or
  375 +
  376 + d) Limiting the use for publicity purposes of names of licensors or
  377 + authors of the material; or
  378 +
  379 + e) Declining to grant rights under trademark law for use of some
  380 + trade names, trademarks, or service marks; or
  381 +
  382 + f) Requiring indemnification of licensors and authors of that
  383 + material by anyone who conveys the material (or modified versions of
  384 + it) with contractual assumptions of liability to the recipient, for
  385 + any liability that these contractual assumptions directly impose on
  386 + those licensors and authors.
  387 +
  388 + All other non-permissive additional terms are considered "further
  389 +restrictions" within the meaning of section 10. If the Program as you
  390 +received it, or any part of it, contains a notice stating that it is
  391 +governed by this License along with a term that is a further
  392 +restriction, you may remove that term. If a license document contains
  393 +a further restriction but permits relicensing or conveying under this
  394 +License, you may add to a covered work material governed by the terms
  395 +of that license document, provided that the further restriction does
  396 +not survive such relicensing or conveying.
  397 +
  398 + If you add terms to a covered work in accord with this section, you
  399 +must place, in the relevant source files, a statement of the
  400 +additional terms that apply to those files, or a notice indicating
  401 +where to find the applicable terms.
  402 +
  403 + Additional terms, permissive or non-permissive, may be stated in the
  404 +form of a separately written license, or stated as exceptions;
  405 +the above requirements apply either way.
  406 +
  407 + 8. Termination.
  408 +
  409 + You may not propagate or modify a covered work except as expressly
  410 +provided under this License. Any attempt otherwise to propagate or
  411 +modify it is void, and will automatically terminate your rights under
  412 +this License (including any patent licenses granted under the third
  413 +paragraph of section 11).
  414 +
  415 + However, if you cease all violation of this License, then your
  416 +license from a particular copyright holder is reinstated (a)
  417 +provisionally, unless and until the copyright holder explicitly and
  418 +finally terminates your license, and (b) permanently, if the copyright
  419 +holder fails to notify you of the violation by some reasonable means
  420 +prior to 60 days after the cessation.
  421 +
  422 + Moreover, your license from a particular copyright holder is
  423 +reinstated permanently if the copyright holder notifies you of the
  424 +violation by some reasonable means, this is the first time you have
  425 +received notice of violation of this License (for any work) from that
  426 +copyright holder, and you cure the violation prior to 30 days after
  427 +your receipt of the notice.
  428 +
  429 + Termination of your rights under this section does not terminate the
  430 +licenses of parties who have received copies or rights from you under
  431 +this License. If your rights have been terminated and not permanently
  432 +reinstated, you do not qualify to receive new licenses for the same
  433 +material under section 10.
  434 +
  435 + 9. Acceptance Not Required for Having Copies.
  436 +
  437 + You are not required to accept this License in order to receive or
  438 +run a copy of the Program. Ancillary propagation of a covered work
  439 +occurring solely as a consequence of using peer-to-peer transmission
  440 +to receive a copy likewise does not require acceptance. However,
  441 +nothing other than this License grants you permission to propagate or
  442 +modify any covered work. These actions infringe copyright if you do
  443 +not accept this License. Therefore, by modifying or propagating a
  444 +covered work, you indicate your acceptance of this License to do so.
  445 +
  446 + 10. Automatic Licensing of Downstream Recipients.
  447 +
  448 + Each time you convey a covered work, the recipient automatically
  449 +receives a license from the original licensors, to run, modify and
  450 +propagate that work, subject to this License. You are not responsible
  451 +for enforcing compliance by third parties with this License.
  452 +
  453 + An "entity transaction" is a transaction transferring control of an
  454 +organization, or substantially all assets of one, or subdividing an
  455 +organization, or merging organizations. If propagation of a covered
  456 +work results from an entity transaction, each party to that
  457 +transaction who receives a copy of the work also receives whatever
  458 +licenses to the work the party's predecessor in interest had or could
  459 +give under the previous paragraph, plus a right to possession of the
  460 +Corresponding Source of the work from the predecessor in interest, if
  461 +the predecessor has it or can get it with reasonable efforts.
  462 +
  463 + You may not impose any further restrictions on the exercise of the
  464 +rights granted or affirmed under this License. For example, you may
  465 +not impose a license fee, royalty, or other charge for exercise of
  466 +rights granted under this License, and you may not initiate litigation
  467 +(including a cross-claim or counterclaim in a lawsuit) alleging that
  468 +any patent claim is infringed by making, using, selling, offering for
  469 +sale, or importing the Program or any portion of it.
  470 +
  471 + 11. Patents.
  472 +
  473 + A "contributor" is a copyright holder who authorizes use under this
  474 +License of the Program or a work on which the Program is based. The
  475 +work thus licensed is called the contributor's "contributor version".
  476 +
  477 + A contributor's "essential patent claims" are all patent claims
  478 +owned or controlled by the contributor, whether already acquired or
  479 +hereafter acquired, that would be infringed by some manner, permitted
  480 +by this License, of making, using, or selling its contributor version,
  481 +but do not include claims that would be infringed only as a
  482 +consequence of further modification of the contributor version. For
  483 +purposes of this definition, "control" includes the right to grant
  484 +patent sublicenses in a manner consistent with the requirements of
  485 +this License.
  486 +
  487 + Each contributor grants you a non-exclusive, worldwide, royalty-free
  488 +patent license under the contributor's essential patent claims, to
  489 +make, use, sell, offer for sale, import and otherwise run, modify and
  490 +propagate the contents of its contributor version.
  491 +
  492 + In the following three paragraphs, a "patent license" is any express
  493 +agreement or commitment, however denominated, not to enforce a patent
  494 +(such as an express permission to practice a patent or covenant not to
  495 +sue for patent infringement). To "grant" such a patent license to a
  496 +party means to make such an agreement or commitment not to enforce a
  497 +patent against the party.
  498 +
  499 + If you convey a covered work, knowingly relying on a patent license,
  500 +and the Corresponding Source of the work is not available for anyone
  501 +to copy, free of charge and under the terms of this License, through a
  502 +publicly available network server or other readily accessible means,
  503 +then you must either (1) cause the Corresponding Source to be so
  504 +available, or (2) arrange to deprive yourself of the benefit of the
  505 +patent license for this particular work, or (3) arrange, in a manner
  506 +consistent with the requirements of this License, to extend the patent
  507 +license to downstream recipients. "Knowingly relying" means you have
  508 +actual knowledge that, but for the patent license, your conveying the
  509 +covered work in a country, or your recipient's use of the covered work
  510 +in a country, would infringe one or more identifiable patents in that
  511 +country that you have reason to believe are valid.
  512 +
  513 + If, pursuant to or in connection with a single transaction or
  514 +arrangement, you convey, or propagate by procuring conveyance of, a
  515 +covered work, and grant a patent license to some of the parties
  516 +receiving the covered work authorizing them to use, propagate, modify
  517 +or convey a specific copy of the covered work, then the patent license
  518 +you grant is automatically extended to all recipients of the covered
  519 +work and works based on it.
  520 +
  521 + A patent license is "discriminatory" if it does not include within
  522 +the scope of its coverage, prohibits the exercise of, or is
  523 +conditioned on the non-exercise of one or more of the rights that are
  524 +specifically granted under this License. You may not convey a covered
  525 +work if you are a party to an arrangement with a third party that is
  526 +in the business of distributing software, under which you make payment
  527 +to the third party based on the extent of your activity of conveying
  528 +the work, and under which the third party grants, to any of the
  529 +parties who would receive the covered work from you, a discriminatory
  530 +patent license (a) in connection with copies of the covered work
  531 +conveyed by you (or copies made from those copies), or (b) primarily
  532 +for and in connection with specific products or compilations that
  533 +contain the covered work, unless you entered into that arrangement,
  534 +or that patent license was granted, prior to 28 March 2007.
  535 +
  536 + Nothing in this License shall be construed as excluding or limiting
  537 +any implied license or other defenses to infringement that may
  538 +otherwise be available to you under applicable patent law.
  539 +
  540 + 12. No Surrender of Others' Freedom.
  541 +
  542 + If conditions are imposed on you (whether by court order, agreement or
  543 +otherwise) that contradict the conditions of this License, they do not
  544 +excuse you from the conditions of this License. If you cannot convey a
  545 +covered work so as to satisfy simultaneously your obligations under this
  546 +License and any other pertinent obligations, then as a consequence you may
  547 +not convey it at all. For example, if you agree to terms that obligate you
  548 +to collect a royalty for further conveying from those to whom you convey
  549 +the Program, the only way you could satisfy both those terms and this
  550 +License would be to refrain entirely from conveying the Program.
  551 +
  552 + 13. Use with the GNU Affero General Public License.
  553 +
  554 + Notwithstanding any other provision of this License, you have
  555 +permission to link or combine any covered work with a work licensed
  556 +under version 3 of the GNU Affero General Public License into a single
  557 +combined work, and to convey the resulting work. The terms of this
  558 +License will continue to apply to the part which is the covered work,
  559 +but the special requirements of the GNU Affero General Public License,
  560 +section 13, concerning interaction through a network will apply to the
  561 +combination as such.
  562 +
  563 + 14. Revised Versions of this License.
  564 +
  565 + The Free Software Foundation may publish revised and/or new versions of
  566 +the GNU General Public License from time to time. Such new versions will
  567 +be similar in spirit to the present version, but may differ in detail to
  568 +address new problems or concerns.
  569 +
  570 + Each version is given a distinguishing version number. If the
  571 +Program specifies that a certain numbered version of the GNU General
  572 +Public License "or any later version" applies to it, you have the
  573 +option of following the terms and conditions either of that numbered
  574 +version or of any later version published by the Free Software
  575 +Foundation. If the Program does not specify a version number of the
  576 +GNU General Public License, you may choose any version ever published
  577 +by the Free Software Foundation.
  578 +
  579 + If the Program specifies that a proxy can decide which future
  580 +versions of the GNU General Public License can be used, that proxy's
  581 +public statement of acceptance of a version permanently authorizes you
  582 +to choose that version for the Program.
  583 +
  584 + Later license versions may give you additional or different
  585 +permissions. However, no additional obligations are imposed on any
  586 +author or copyright holder as a result of your choosing to follow a
  587 +later version.
  588 +
  589 + 15. Disclaimer of Warranty.
  590 +
  591 + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
  592 +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
  593 +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
  594 +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
  595 +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  596 +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
  597 +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
  598 +ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  599 +
  600 + 16. Limitation of Liability.
  601 +
  602 + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
  603 +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
  604 +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
  605 +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
  606 +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
  607 +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
  608 +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
  609 +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
  610 +SUCH DAMAGES.
  611 +
  612 + 17. Interpretation of Sections 15 and 16.
  613 +
  614 + If the disclaimer of warranty and limitation of liability provided
  615 +above cannot be given local legal effect according to their terms,
  616 +reviewing courts shall apply local law that most closely approximates
  617 +an absolute waiver of all civil liability in connection with the
  618 +Program, unless a warranty or assumption of liability accompanies a
  619 +copy of the Program in return for a fee.
  620 +
  621 + END OF TERMS AND CONDITIONS
  622 +
  623 + How to Apply These Terms to Your New Programs
  624 +
  625 + If you develop a new program, and you want it to be of the greatest
  626 +possible use to the public, the best way to achieve this is to make it
  627 +free software which everyone can redistribute and change under these terms.
  628 +
  629 + To do so, attach the following notices to the program. It is safest
  630 +to attach them to the start of each source file to most effectively
  631 +state the exclusion of warranty; and each file should have at least
  632 +the "copyright" line and a pointer to where the full notice is found.
  633 +
  634 + <one line to give the program's name and a brief idea of what it does.>
  635 + Copyright (C) <year> <name of author>
  636 +
  637 + This program is free software: you can redistribute it and/or modify
  638 + it under the terms of the GNU General Public License as published by
  639 + the Free Software Foundation, either version 3 of the License, or
  640 + (at your option) any later version.
  641 +
  642 + This program is distributed in the hope that it will be useful,
  643 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  644 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  645 + GNU General Public License for more details.
  646 +
  647 + You should have received a copy of the GNU General Public License
  648 + along with this program. If not, see <http://www.gnu.org/licenses/>.
  649 +
  650 +Also add information on how to contact you by electronic and paper mail.
  651 +
  652 + If the program does terminal interaction, make it output a short
  653 +notice like this when it starts in an interactive mode:
  654 +
  655 + <program> Copyright (C) <year> <name of author>
  656 + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
  657 + This is free software, and you are welcome to redistribute it
  658 + under certain conditions; type `show c' for details.
  659 +
  660 +The hypothetical commands `show w' and `show c' should show the appropriate
  661 +parts of the General Public License. Of course, your program's commands
  662 +might be different; for a GUI interface, you would use an "about box".
  663 +
  664 + You should also get your employer (if you work as a programmer) or school,
  665 +if any, to sign a "copyright disclaimer" for the program, if necessary.
  666 +For more information on this, and how to apply and follow the GNU GPL, see
  667 +<http://www.gnu.org/licenses/>.
  668 +
  669 + The GNU General Public License does not permit incorporating your program
  670 +into proprietary programs. If your program is a subroutine library, you
  671 +may consider it more useful to permit linking proprietary applications with
  672 +the library. If this is what you want to do, use the GNU Lesser General
  673 +Public License instead of this License. But first, please read
  674 +<http://www.gnu.org/philosophy/why-not-lgpl.html>.
  1 +Roundcube Webmail
  2 +=================
  3 +[roundcube.net](https://roundcube.net)
  4 +
  5 +[![Tests Status](https://github.com/roundcube/roundcubemail/actions/workflows/tests.yml/badge.svg?branch=master)](https://github.com/roundcube/roundcubemail/actions/workflows/tests.yml)
  6 +
  7 +INTRODUCTION
  8 +------------
  9 +Roundcube Webmail is a browser-based multilingual IMAP client with an
  10 +application-like user interface. It provides full functionality you expect
  11 +from an email client, including MIME support, address book, folder management,
  12 +message searching and spell checking. Roundcube Webmail is written in PHP and
  13 +requires the MySQL, PostgreSQL or SQLite database. With its plugin API it is
  14 +easily extendable and the user interface is fully customizable using skins.
  15 +
  16 +The code designed to run on a webserver is mainly written in PHP and Javascript.
  17 +It includes a custom framework with an IMAP library derived from [IlohaMail][iloha]
  18 +and requires a set of external libraries (see composer.json and jsdeps.json files).
  19 +
  20 +
  21 +INSTALLATION
  22 +------------
  23 +For detailed instructions on how to install Roundcube webmail on your server,
  24 +please refer to the INSTALL document in the same directory as this document.
  25 +
  26 +If you're updating an older version of Roundcube please follow the steps
  27 +described in the UPGRADING file.
  28 +
  29 +
  30 +BROWSER SUPPORT
  31 +---------------
  32 +Roundcube uses jQuery 3.x (and other libs) for its client and therefore
  33 +inherits the browser support from there. This currently includes:
  34 +
  35 +- Chrome: (Current - 1) and Current
  36 +- Edge: (Current - 1) and Current
  37 +- Firefox: (Current - 1) and Current, ESR
  38 +- Internet Explorer: 11+
  39 +- Safari: (Current - 1) and Current
  40 +- Opera: Current
  41 +
  42 +
  43 +LICENSE
  44 +-------
  45 +This program is free software: you can redistribute it and/or modify
  46 +it under the terms of the GNU General Public License (**with exceptions
  47 +for skins & plugins**) as published by the Free Software Foundation,
  48 +either version 3 of the License, or (at your option) any later version.
  49 +
  50 +This program is distributed in the hope that it will be useful,
  51 +but WITHOUT ANY WARRANTY; without even the implied warranty of
  52 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  53 +GNU General Public License for more details.
  54 +
  55 +You should have received a copy of the GNU General Public License
  56 +along with this program. If not, see [www.gnu.org/licenses/][gpl].
  57 +
  58 +This file forms part of the Roundcube Webmail Software for which the
  59 +following exception is added: Plugins and Skins which merely make
  60 +function calls to the Roundcube Webmail Software, and for that purpose
  61 +include it by reference shall not be considered modifications of
  62 +the software.
  63 +
  64 +If you wish to use this file in another project or create a modified
  65 +version that will not be part of the Roundcube Webmail Software, you
  66 +may remove the exception above and use this source code under the
  67 +original version of the license.
  68 +
  69 +For more details about licensing and the exceptions for skins and plugins
  70 +see [roundcube.net/license][license]
  71 +
  72 +
  73 +CONTRIBUTION
  74 +------------
  75 +Want to help make Roundcube the best webmail solution ever?
  76 +Roundcube is open source software. Our developers and contributors all
  77 +are volunteers and we're always looking for new additions and resources.
  78 +For more information visit [roundcube.net/contribute][contrib]
  79 +
  80 +
  81 +CONTACT
  82 +-------
  83 +For bug reports or feature requests please refer to the tracking system
  84 +at [Github][githubissues] or subscribe to our mailing list.
  85 +See [roundcube.net/support][support] for details.
  86 +
  87 +You're always welcome to send a message to the project admin:
  88 +hello(at)roundcube(dot)net
  89 +
  90 +
  91 +[iloha]: https://sourceforge.net/projects/ilohamail/
  92 +[gpl]: https://www.gnu.org/licenses/
  93 +[license]: https://roundcube.net/license
  94 +[contrib]: https://roundcube.net/contribute
  95 +[support]: https://roundcube.net/support
  96 +[githubissues]: https://github.com/roundcube/roundcubemail/issues
  1 +# Security Policy
  2 +
  3 +## Supported Versions
  4 +
  5 +Check our website's [download page](https://roundcube.net/download/) to see which versions are still supported and will receive security updates.
  6 +
  7 +## Reporting a Vulnerability
  8 +
  9 +If you found a security issue or vulnerability of the software, please report with direct and encrypted email to *thomas[at]roundcube.net*
  10 +and *alec[at]alec.pl*. You can find the according PGP public keys on the major public keyservers like [pgp.key-server.io](https://pgp.key-server.io).
  11 +
  12 +Your report should include clear steps for reproduction and a classification of the found vulnerability.
  13 +
  14 +## Publishing and Credits
  15 +
  16 +We're dedicated to analyze and fix the reported issues as fast a possible. Usually within days we'll have an update ready.
  17 +Together with the reporter we plan the releasing and the disclosure of the found and fixed vulnerability.
  18 +Credits to the reporter are granted and can be included in all public communication if desired.
  1 +CREATE TABLE [dbo].[cache] (
  2 + [user_id] [int] NOT NULL ,
  3 + [cache_key] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL ,
  4 + [expires] [datetime] NULL ,
  5 + [data] [text] COLLATE Latin1_General_CI_AI NOT NULL
  6 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  7 +GO
  8 +
  9 +CREATE TABLE [dbo].[cache_shared] (
  10 + [cache_key] [varchar] (255) COLLATE Latin1_General_CS_AS NOT NULL ,
  11 + [expires] [datetime] NULL ,
  12 + [data] [text] COLLATE Latin1_General_CI_AI NOT NULL
  13 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  14 +GO
  15 +
  16 +CREATE TABLE [dbo].[cache_index] (
  17 + [user_id] [int] NOT NULL ,
  18 + [mailbox] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL ,
  19 + [expires] [datetime] NULL ,
  20 + [valid] [char] (1) COLLATE Latin1_General_CI_AI NOT NULL ,
  21 + [data] [text] COLLATE Latin1_General_CI_AI NOT NULL
  22 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  23 +GO
  24 +
  25 +CREATE TABLE [dbo].[cache_thread] (
  26 + [user_id] [int] NOT NULL ,
  27 + [mailbox] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL ,
  28 + [expires] [datetime] NULL ,
  29 + [data] [text] COLLATE Latin1_General_CI_AI NOT NULL
  30 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  31 +GO
  32 +
  33 +CREATE TABLE [dbo].[cache_messages] (
  34 + [user_id] [int] NOT NULL ,
  35 + [mailbox] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL ,
  36 + [uid] [int] NOT NULL ,
  37 + [expires] [datetime] NULL ,
  38 + [data] [text] COLLATE Latin1_General_CI_AI NOT NULL ,
  39 + [flags] [int] NOT NULL
  40 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  41 +GO
  42 +
  43 +CREATE TABLE [dbo].[collected_addresses] (
  44 + [address_id] [int] IDENTITY (1, 1) NOT NULL ,
  45 + [user_id] [int] NOT NULL ,
  46 + [changed] [datetime] NOT NULL ,
  47 + [name] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL ,
  48 + [email] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL ,
  49 + [type] [int] NOT NULL
  50 +) ON [PRIMARY]
  51 +GO
  52 +
  53 +CREATE TABLE [dbo].[contacts] (
  54 + [contact_id] [int] IDENTITY (1, 1) NOT NULL ,
  55 + [user_id] [int] NOT NULL ,
  56 + [changed] [datetime] NOT NULL ,
  57 + [del] [char] (1) COLLATE Latin1_General_CI_AI NOT NULL ,
  58 + [name] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
  59 + [email] [varchar] (8000) COLLATE Latin1_General_CI_AI NOT NULL ,
  60 + [firstname] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
  61 + [surname] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
  62 + [vcard] [text] COLLATE Latin1_General_CI_AI NULL ,
  63 + [words] [text] COLLATE Latin1_General_CI_AI NULL
  64 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  65 +GO
  66 +
  67 +CREATE TABLE [dbo].[contactgroups] (
  68 + [contactgroup_id] [int] IDENTITY (1, 1) NOT NULL ,
  69 + [user_id] [int] NOT NULL ,
  70 + [changed] [datetime] NOT NULL ,
  71 + [del] [char] (1) COLLATE Latin1_General_CI_AI NOT NULL ,
  72 + [name] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL
  73 +) ON [PRIMARY]
  74 +GO
  75 +
  76 +CREATE TABLE [dbo].[contactgroupmembers] (
  77 + [contactgroup_id] [int] NOT NULL ,
  78 + [contact_id] [int] NOT NULL ,
  79 + [created] [datetime] NOT NULL
  80 +) ON [PRIMARY]
  81 +GO
  82 +
  83 +CREATE TABLE [dbo].[identities] (
  84 + [identity_id] [int] IDENTITY (1, 1) NOT NULL ,
  85 + [user_id] [int] NOT NULL ,
  86 + [changed] [datetime] NOT NULL ,
  87 + [del] [char] (1) COLLATE Latin1_General_CI_AI NOT NULL ,
  88 + [standard] [char] (1) COLLATE Latin1_General_CI_AI NOT NULL ,
  89 + [name] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
  90 + [organization] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
  91 + [email] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
  92 + [reply-to] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
  93 + [bcc] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
  94 + [signature] [text] COLLATE Latin1_General_CI_AI NULL,
  95 + [html_signature] [char] (1) COLLATE Latin1_General_CI_AI NOT NULL
  96 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  97 +GO
  98 +
  99 +CREATE TABLE [dbo].[session] (
  100 + [sess_id] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
  101 + [changed] [datetime] NULL ,
  102 + [ip] [varchar] (40) COLLATE Latin1_General_CI_AI NOT NULL ,
  103 + [vars] [text] COLLATE Latin1_General_CI_AI NOT NULL
  104 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  105 +GO
  106 +
  107 +CREATE TABLE [dbo].[users] (
  108 + [user_id] [int] IDENTITY (1, 1) NOT NULL ,
  109 + [username] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL ,
  110 + [mail_host] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
  111 + [created] [datetime] NOT NULL ,
  112 + [last_login] [datetime] NULL ,
  113 + [failed_login] [datetime] NULL ,
  114 + [failed_login_counter] [int] NULL ,
  115 + [language] [varchar] (16) COLLATE Latin1_General_CI_AI NULL ,
  116 + [preferences] [text] COLLATE Latin1_General_CI_AI NULL
  117 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  118 +GO
  119 +
  120 +CREATE TABLE [dbo].[dictionary] (
  121 + [user_id] [int] ,
  122 + [language] [varchar] (16) COLLATE Latin1_General_CI_AI NOT NULL ,
  123 + [data] [text] COLLATE Latin1_General_CI_AI NOT NULL
  124 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  125 +GO
  126 +
  127 +CREATE TABLE [dbo].[searches] (
  128 + [search_id] [int] IDENTITY (1, 1) NOT NULL ,
  129 + [user_id] [int] NOT NULL ,
  130 + [type] [tinyint] NOT NULL ,
  131 + [name] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
  132 + [data] [text] COLLATE Latin1_General_CI_AI NOT NULL
  133 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  134 +GO
  135 +
  136 +CREATE TABLE [dbo].[filestore] (
  137 + [file_id] [int] IDENTITY (1, 1) NOT NULL ,
  138 + [user_id] [int] NOT NULL ,
  139 + [context] [varchar] (32) COLLATE Latin1_General_CI_AI NOT NULL ,
  140 + [filename] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
  141 + [mtime] [int] NOT NULL ,
  142 + [data] [text] COLLATE Latin1_General_CI_AI NULL ,
  143 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  144 +GO
  145 +
  146 +CREATE TABLE [dbo].[system] (
  147 + [name] [varchar] (64) COLLATE Latin1_General_CI_AI NOT NULL ,
  148 + [value] [text] COLLATE Latin1_General_CI_AI NOT NULL
  149 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  150 +GO
  151 +
  152 +ALTER TABLE [dbo].[cache] WITH NOCHECK ADD
  153 + PRIMARY KEY CLUSTERED
  154 + (
  155 + [user_id],[cache_key]
  156 + ) ON [PRIMARY]
  157 +GO
  158 +
  159 +ALTER TABLE [dbo].[cache_shared] WITH NOCHECK ADD
  160 + PRIMARY KEY CLUSTERED
  161 + (
  162 + [cache_key]
  163 + ) ON [PRIMARY]
  164 +GO
  165 +
  166 +ALTER TABLE [dbo].[cache_index] WITH NOCHECK ADD
  167 + PRIMARY KEY CLUSTERED
  168 + (
  169 + [user_id],[mailbox]
  170 + ) ON [PRIMARY]
  171 +GO
  172 +
  173 +ALTER TABLE [dbo].[cache_thread] WITH NOCHECK ADD
  174 + PRIMARY KEY CLUSTERED
  175 + (
  176 + [user_id],[mailbox]
  177 + ) ON [PRIMARY]
  178 +GO
  179 +
  180 +ALTER TABLE [dbo].[cache_messages] WITH NOCHECK ADD
  181 + PRIMARY KEY CLUSTERED
  182 + (
  183 + [user_id],[mailbox],[uid]
  184 + ) ON [PRIMARY]
  185 +GO
  186 +
  187 +ALTER TABLE [dbo].[collected_addresses] WITH NOCHECK ADD
  188 + CONSTRAINT [PK_collected_addresses_address_id] PRIMARY KEY CLUSTERED
  189 + (
  190 + [address_id]
  191 + ) ON [PRIMARY]
  192 +GO
  193 +
  194 +ALTER TABLE [dbo].[contacts] WITH NOCHECK ADD
  195 + CONSTRAINT [PK_contacts_contact_id] PRIMARY KEY CLUSTERED
  196 + (
  197 + [contact_id]
  198 + ) ON [PRIMARY]
  199 +GO
  200 +
  201 +ALTER TABLE [dbo].[contactgroups] WITH NOCHECK ADD
  202 + CONSTRAINT [PK_contactgroups_contactgroup_id] PRIMARY KEY CLUSTERED
  203 + (
  204 + [contactgroup_id]
  205 + ) ON [PRIMARY]
  206 +GO
  207 +
  208 +ALTER TABLE [dbo].[contactgroupmembers] WITH NOCHECK ADD
  209 + CONSTRAINT [PK_contactgroupmembers_id] PRIMARY KEY CLUSTERED
  210 + (
  211 + [contactgroup_id], [contact_id]
  212 + ) ON [PRIMARY]
  213 +GO
  214 +
  215 +ALTER TABLE [dbo].[identities] WITH NOCHECK ADD
  216 + PRIMARY KEY CLUSTERED
  217 + (
  218 + [identity_id]
  219 + ) ON [PRIMARY]
  220 +GO
  221 +
  222 +ALTER TABLE [dbo].[session] WITH NOCHECK ADD
  223 + CONSTRAINT [PK_session_sess_id] PRIMARY KEY CLUSTERED
  224 + (
  225 + [sess_id]
  226 + ) ON [PRIMARY]
  227 +GO
  228 +
  229 +ALTER TABLE [dbo].[users] WITH NOCHECK ADD
  230 + CONSTRAINT [PK_users_user_id] PRIMARY KEY CLUSTERED
  231 + (
  232 + [user_id]
  233 + ) ON [PRIMARY]
  234 +GO
  235 +
  236 +ALTER TABLE [dbo].[searches] WITH NOCHECK ADD
  237 + CONSTRAINT [PK_searches_search_id] PRIMARY KEY CLUSTERED
  238 + (
  239 + [search_id]
  240 + ) ON [PRIMARY]
  241 +GO
  242 +
  243 +ALTER TABLE [dbo].[filestore] WITH NOCHECK ADD
  244 + CONSTRAINT [PK_filestore_file_id] PRIMARY KEY CLUSTERED
  245 + (
  246 + [file_id]
  247 + ) ON [PRIMARY]
  248 +GO
  249 +
  250 +ALTER TABLE [dbo].[system] WITH NOCHECK ADD
  251 + CONSTRAINT [PK_system_name] PRIMARY KEY CLUSTERED
  252 + (
  253 + [name]
  254 + ) ON [PRIMARY]
  255 +GO
  256 +
  257 +ALTER TABLE [dbo].[cache] ADD
  258 + CONSTRAINT [DF_cache_user_id] DEFAULT ('0') FOR [user_id],
  259 + CONSTRAINT [DF_cache_cache_key] DEFAULT ('') FOR [cache_key]
  260 +GO
  261 +
  262 +ALTER TABLE [dbo].[cache_index] ADD
  263 + CONSTRAINT [DF_cache_index_valid] DEFAULT ('0') FOR [valid]
  264 +GO
  265 +
  266 +ALTER TABLE [dbo].[cache_messages] ADD
  267 + CONSTRAINT [DF_cache_messages_flags] DEFAULT (0) FOR [flags]
  268 +GO
  269 +
  270 +CREATE INDEX [IX_cache_shared_cache_key] ON [dbo].[cache_shared]([cache_key]) ON [PRIMARY]
  271 +GO
  272 +
  273 +CREATE INDEX [IX_cache_index_user_id] ON [dbo].[cache_index]([user_id]) ON [PRIMARY]
  274 +GO
  275 +
  276 +CREATE INDEX [IX_cache_thread_user_id] ON [dbo].[cache_thread]([user_id]) ON [PRIMARY]
  277 +GO
  278 +
  279 +CREATE INDEX [IX_cache_messages_user_id] ON [dbo].[cache_messages]([user_id]) ON [PRIMARY]
  280 +GO
  281 +
  282 +CREATE INDEX [IX_cache_expires] ON [dbo].[cache]([expires]) ON [PRIMARY]
  283 +GO
  284 +
  285 +CREATE INDEX [IX_cache_shared_expires] ON [dbo].[cache_shared]([expires]) ON [PRIMARY]
  286 +GO
  287 +
  288 +CREATE INDEX [IX_cache_index_expires] ON [dbo].[cache_index]([expires]) ON [PRIMARY]
  289 +GO
  290 +
  291 +CREATE INDEX [IX_cache_thread_expires] ON [dbo].[cache_thread]([expires]) ON [PRIMARY]
  292 +GO
  293 +
  294 +CREATE INDEX [IX_cache_messages_expires] ON [dbo].[cache_messages]([expires]) ON [PRIMARY]
  295 +GO
  296 +
  297 +ALTER TABLE [dbo].[collected_addresses] ADD
  298 + CONSTRAINT [DF_collected_addresses_user_id] DEFAULT (0) FOR [user_id],
  299 + CONSTRAINT [DF_collected_addresses_changed] DEFAULT (getdate()) FOR [changed],
  300 + CONSTRAINT [DF_collected_addresses_name] DEFAULT ('') FOR [name]
  301 +GO
  302 +
  303 +CREATE UNIQUE INDEX [IX_collected_addresses_user_id] ON [dbo].[collected_addresses]([user_id],[type],[email]) ON [PRIMARY]
  304 +GO
  305 +
  306 +ALTER TABLE [dbo].[contacts] ADD
  307 + CONSTRAINT [DF_contacts_user_id] DEFAULT (0) FOR [user_id],
  308 + CONSTRAINT [DF_contacts_changed] DEFAULT (getdate()) FOR [changed],
  309 + CONSTRAINT [DF_contacts_del] DEFAULT ('0') FOR [del],
  310 + CONSTRAINT [DF_contacts_name] DEFAULT ('') FOR [name],
  311 + CONSTRAINT [DF_contacts_email] DEFAULT ('') FOR [email],
  312 + CONSTRAINT [DF_contacts_firstname] DEFAULT ('') FOR [firstname],
  313 + CONSTRAINT [DF_contacts_surname] DEFAULT ('') FOR [surname],
  314 + CONSTRAINT [CK_contacts_del] CHECK ([del] = '1' or [del] = '0')
  315 +GO
  316 +
  317 +CREATE INDEX [IX_contacts_user_id] ON [dbo].[contacts]([user_id]) ON [PRIMARY]
  318 +GO
  319 +
  320 +ALTER TABLE [dbo].[contactgroups] ADD
  321 + CONSTRAINT [DF_contactgroups_user_id] DEFAULT (0) FOR [user_id],
  322 + CONSTRAINT [DF_contactgroups_changed] DEFAULT (getdate()) FOR [changed],
  323 + CONSTRAINT [DF_contactgroups_del] DEFAULT ('0') FOR [del],
  324 + CONSTRAINT [DF_contactgroups_name] DEFAULT ('') FOR [name],
  325 + CONSTRAINT [CK_contactgroups_del] CHECK ([del] = '1' or [del] = '0')
  326 +GO
  327 +
  328 +CREATE INDEX [IX_contactgroups_user_id] ON [dbo].[contactgroups]([user_id]) ON [PRIMARY]
  329 +GO
  330 +
  331 +ALTER TABLE [dbo].[contactgroupmembers] ADD
  332 + CONSTRAINT [DF_contactgroupmembers_contactgroup_id] DEFAULT (0) FOR [contactgroup_id],
  333 + CONSTRAINT [DF_contactgroupmembers_contact_id] DEFAULT (0) FOR [contact_id],
  334 + CONSTRAINT [DF_contactgroupmembers_created] DEFAULT (getdate()) FOR [created]
  335 +GO
  336 +
  337 +CREATE INDEX [IX_contactgroupmembers_contact_id] ON [dbo].[contactgroupmembers]([contact_id]) ON [PRIMARY]
  338 +GO
  339 +
  340 +ALTER TABLE [dbo].[identities] ADD
  341 + CONSTRAINT [DF_identities_user] DEFAULT ('0') FOR [user_id],
  342 + CONSTRAINT [DF_identities_del] DEFAULT ('0') FOR [del],
  343 + CONSTRAINT [DF_identities_standard] DEFAULT ('0') FOR [standard],
  344 + CONSTRAINT [DF_identities_name] DEFAULT ('') FOR [name],
  345 + CONSTRAINT [DF_identities_organization] DEFAULT ('') FOR [organization],
  346 + CONSTRAINT [DF_identities_email] DEFAULT ('') FOR [email],
  347 + CONSTRAINT [DF_identities_reply] DEFAULT ('') FOR [reply-to],
  348 + CONSTRAINT [DF_identities_bcc] DEFAULT ('') FOR [bcc],
  349 + CONSTRAINT [DF_identities_html_signature] DEFAULT ('0') FOR [html_signature],
  350 + CHECK ([standard] = '1' or [standard] = '0'),
  351 + CHECK ([del] = '1' or [del] = '0')
  352 +GO
  353 +
  354 +CREATE INDEX [IX_identities_user_id] ON [dbo].[identities]([user_id]) ON [PRIMARY]
  355 +GO
  356 +CREATE INDEX [IX_identities_email] ON [dbo].[identities]([email],[del]) ON [PRIMARY]
  357 +GO
  358 +
  359 +ALTER TABLE [dbo].[session] ADD
  360 + CONSTRAINT [DF_session_sess_id] DEFAULT ('') FOR [sess_id],
  361 + CONSTRAINT [DF_session_ip] DEFAULT ('') FOR [ip]
  362 +GO
  363 +
  364 +CREATE INDEX [IX_session_changed] ON [dbo].[session]([changed]) ON [PRIMARY]
  365 +GO
  366 +
  367 +CREATE INDEX [IX_filestore_user_id] ON [dbo].[filestore]([user_id]) ON [PRIMARY]
  368 +GO
  369 +
  370 +ALTER TABLE [dbo].[users] ADD
  371 + CONSTRAINT [DF_users_username] DEFAULT ('') FOR [username],
  372 + CONSTRAINT [DF_users_mail_host] DEFAULT ('') FOR [mail_host],
  373 + CONSTRAINT [DF_users_created] DEFAULT (getdate()) FOR [created]
  374 +GO
  375 +
  376 +CREATE UNIQUE INDEX [IX_users_username] ON [dbo].[users]([username],[mail_host]) ON [PRIMARY]
  377 +GO
  378 +
  379 +CREATE UNIQUE INDEX [IX_dictionary_user_language] ON [dbo].[dictionary]([user_id],[language]) ON [PRIMARY]
  380 +GO
  381 +
  382 +ALTER TABLE [dbo].[searches] ADD
  383 + CONSTRAINT [DF_searches_user] DEFAULT (0) FOR [user_id],
  384 + CONSTRAINT [DF_searches_type] DEFAULT (0) FOR [type]
  385 +GO
  386 +
  387 +CREATE UNIQUE INDEX [IX_searches_user_type_name] ON [dbo].[searches]([user_id],[type],[name]) ON [PRIMARY]
  388 +GO
  389 +
  390 +CREATE UNIQUE INDEX [IX_filestore_user_id_context_filename] ON [dbo].[filestore]([user_id],[context],[filename]) ON [PRIMARY]
  391 +GO
  392 +
  393 +ALTER TABLE [dbo].[identities] ADD CONSTRAINT [FK_identities_user_id]
  394 + FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
  395 + ON DELETE CASCADE ON UPDATE CASCADE
  396 +GO
  397 +
  398 +ALTER TABLE [dbo].[collected_addresses] ADD CONSTRAINT [FK_collected_addresses_user_id]
  399 + FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
  400 + ON DELETE CASCADE ON UPDATE CASCADE
  401 +GO
  402 +
  403 +ALTER TABLE [dbo].[contacts] ADD CONSTRAINT [FK_contacts_user_id]
  404 + FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
  405 + ON DELETE CASCADE ON UPDATE CASCADE
  406 +GO
  407 +
  408 +ALTER TABLE [dbo].[contactgroups] ADD CONSTRAINT [FK_contactgroups_user_id]
  409 + FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
  410 + ON DELETE CASCADE ON UPDATE CASCADE
  411 +GO
  412 +
  413 +ALTER TABLE [dbo].[cache] ADD CONSTRAINT [FK_cache_user_id]
  414 + FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
  415 + ON DELETE CASCADE ON UPDATE CASCADE
  416 +GO
  417 +
  418 +ALTER TABLE [dbo].[cache_index] ADD CONSTRAINT [FK_cache_index_user_id]
  419 + FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
  420 + ON DELETE CASCADE ON UPDATE CASCADE
  421 +GO
  422 +
  423 +ALTER TABLE [dbo].[cache_thread] ADD CONSTRAINT [FK_cache_thread_user_id]
  424 + FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
  425 + ON DELETE CASCADE ON UPDATE CASCADE
  426 +GO
  427 +
  428 +ALTER TABLE [dbo].[cache_messages] ADD CONSTRAINT [FK_cache_messages_user_id]
  429 + FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
  430 + ON DELETE CASCADE ON UPDATE CASCADE
  431 +GO
  432 +
  433 +ALTER TABLE [dbo].[contactgroupmembers] ADD CONSTRAINT [FK_contactgroupmembers_contactgroup_id]
  434 + FOREIGN KEY ([contactgroup_id]) REFERENCES [dbo].[contactgroups] ([contactgroup_id])
  435 + ON DELETE CASCADE ON UPDATE CASCADE
  436 +GO
  437 +
  438 +ALTER TABLE [dbo].[searches] ADD CONSTRAINT [FK_searches_user_id]
  439 + FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
  440 + ON DELETE CASCADE ON UPDATE CASCADE
  441 +GO
  442 +
  443 +ALTER TABLE [dbo].[filestore] ADD CONSTRAINT [FK_filestore_user_id]
  444 + FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
  445 + ON DELETE CASCADE ON UPDATE CASCADE
  446 +GO
  447 +
  448 +-- Use trigger instead of foreign key (#1487112)
  449 +-- "Introducing FOREIGN KEY constraint ... may cause cycles or multiple cascade paths."
  450 +CREATE TRIGGER [contact_delete_member] ON [dbo].[contacts]
  451 + AFTER DELETE AS
  452 + DELETE FROM [dbo].[contactgroupmembers]
  453 + WHERE [contact_id] IN (SELECT [contact_id] FROM deleted)
  454 +GO
  455 +
  456 +INSERT INTO [dbo].[system] ([name], [value]) VALUES ('roundcube-version', '2020122900')
  457 +GO
  458 +
  1 +-- Updates from version 0.3.1
  2 +
  3 +ALTER TABLE [dbo].[messages] ADD CONSTRAINT [FK_messages_user_id]
  4 + FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
  5 + ON DELETE CASCADE ON UPDATE CASCADE
  6 +GO
  7 +
  8 +ALTER TABLE [dbo].[cache] ADD CONSTRAINT [FK_cache_user_id]
  9 + FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
  10 + ON DELETE CASCADE ON UPDATE CASCADE
  11 +GO
  12 +
  13 +ALTER TABLE [dbo].[contacts] ADD CONSTRAINT [FK_contacts_user_id]
  14 + FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
  15 + ON DELETE CASCADE ON UPDATE CASCADE
  16 +GO
  17 +
  18 +ALTER TABLE [dbo].[identities] ADD CONSTRAINT [FK_identities_user_id]
  19 + FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
  20 + ON DELETE CASCADE ON UPDATE CASCADE
  21 +GO
  22 +
  23 +ALTER TABLE [dbo].[identities] ADD [changed] [datetime] NULL
  24 +GO
  25 +
  26 +CREATE TABLE [dbo].[contactgroups] (
  27 + [contactgroup_id] [int] IDENTITY (1, 1) NOT NULL ,
  28 + [user_id] [int] NOT NULL ,
  29 + [changed] [datetime] NOT NULL ,
  30 + [del] [char] (1) COLLATE Latin1_General_CI_AI NOT NULL ,
  31 + [name] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL
  32 +) ON [PRIMARY]
  33 +GO
  34 +
  35 +CREATE TABLE [dbo].[contactgroupmembers] (
  36 + [contactgroup_id] [int] NOT NULL ,
  37 + [contact_id] [int] NOT NULL ,
  38 + [created] [datetime] NOT NULL
  39 +) ON [PRIMARY]
  40 +GO
  41 +
  42 +ALTER TABLE [dbo].[contactgroups] WITH NOCHECK ADD
  43 + CONSTRAINT [PK_contactgroups_contactgroup_id] PRIMARY KEY CLUSTERED
  44 + (
  45 + [contactgroup_id]
  46 + ) ON [PRIMARY]
  47 +GO
  48 +
  49 +ALTER TABLE [dbo].[contactgroupmembers] WITH NOCHECK ADD
  50 + CONSTRAINT [PK_contactgroupmembers_id] PRIMARY KEY CLUSTERED
  51 + (
  52 + [contactgroup_id], [contact_id]
  53 + ) ON [PRIMARY]
  54 +GO
  55 +
  56 +ALTER TABLE [dbo].[contactgroups] ADD
  57 + CONSTRAINT [DF_contactgroups_user_id] DEFAULT (0) FOR [user_id],
  58 + CONSTRAINT [DF_contactgroups_changed] DEFAULT (getdate()) FOR [changed],
  59 + CONSTRAINT [DF_contactgroups_del] DEFAULT ('0') FOR [del],
  60 + CONSTRAINT [DF_contactgroups_name] DEFAULT ('') FOR [name],
  61 + CONSTRAINT [CK_contactgroups_del] CHECK ([del] = '1' or [del] = '0')
  62 +GO
  63 +
  64 +CREATE INDEX [IX_contactgroups_user_id] ON [dbo].[contacts]([user_id]) ON [PRIMARY]
  65 +GO
  66 +
  67 +ALTER TABLE [dbo].[contactgroupmembers] ADD
  68 + CONSTRAINT [DF_contactgroupmembers_contactgroup_id] DEFAULT (0) FOR [contactgroup_id],
  69 + CONSTRAINT [DF_contactgroupmembers_contact_id] DEFAULT (0) FOR [contact_id],
  70 + CONSTRAINT [DF_contactgroupmembers_created] DEFAULT (getdate()) FOR [created]
  71 +GO
  72 +
  73 +ALTER TABLE [dbo].[contactgroupmembers] ADD CONSTRAINT [FK_contactgroupmembers_contactgroup_id]
  74 + FOREIGN KEY ([contactgroup_id]) REFERENCES [dbo].[contactgroups] ([contactgroup_id])
  75 + ON DELETE CASCADE ON UPDATE CASCADE
  76 +GO
  77 +
  78 +CREATE TRIGGER [contact_delete_member] ON [dbo].[contacts]
  79 + AFTER DELETE AS
  80 + DELETE FROM [dbo].[contactgroupmembers]
  81 + WHERE [contact_id] IN (SELECT [contact_id] FROM deleted)
  82 +GO
  83 +
  84 +ALTER TABLE [dbo].[contactgroups] ADD CONSTRAINT [FK_contactgroups_user_id]
  85 + FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
  86 + ON DELETE CASCADE ON UPDATE CASCADE
  87 +GO
  1 +-- Updates from version 0.4.2
  2 +
  3 +DROP INDEX [IX_users_username]
  4 +GO
  5 +CREATE UNIQUE INDEX [IX_users_username] ON [dbo].[users]([username],[mail_host]) ON [PRIMARY]
  6 +GO
  7 +ALTER TABLE [dbo].[contacts] ALTER COLUMN [email] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL
  8 +GO
  9 +
  1 +-- Updates from version 0.5.x
  2 +
  3 +ALTER TABLE [dbo].[contacts] ADD [words] [text] COLLATE Latin1_General_CI_AI NULL
  4 +GO
  5 +CREATE INDEX [IX_contactgroupmembers_contact_id] ON [dbo].[contactgroupmembers]([contact_id]) ON [PRIMARY]
  6 +GO
  7 +DELETE FROM [dbo].[messages]
  8 +GO
  9 +DELETE FROM [dbo].[cache]
  10 +GO
  1 +-- Updates from version 0.6
  2 +
  3 +CREATE TABLE [dbo].[dictionary] (
  4 + [user_id] [int] ,
  5 + [language] [varchar] (5) COLLATE Latin1_General_CI_AI NOT NULL ,
  6 + [data] [text] COLLATE Latin1_General_CI_AI NOT NULL
  7 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  8 +GO
  9 +CREATE UNIQUE INDEX [IX_dictionary_user_language] ON [dbo].[dictionary]([user_id],[language]) ON [PRIMARY]
  10 +GO
  11 +
  12 +CREATE TABLE [dbo].[searches] (
  13 + [search_id] [int] IDENTITY (1, 1) NOT NULL ,
  14 + [user_id] [int] NOT NULL ,
  15 + [type] [tinyint] NOT NULL ,
  16 + [name] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
  17 + [data] [text] COLLATE Latin1_General_CI_AI NOT NULL
  18 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  19 +GO
  20 +
  21 +ALTER TABLE [dbo].[searches] WITH NOCHECK ADD
  22 + CONSTRAINT [PK_searches_search_id] PRIMARY KEY CLUSTERED
  23 + (
  24 + [search_id]
  25 + ) ON [PRIMARY]
  26 +GO
  27 +
  28 +ALTER TABLE [dbo].[searches] ADD
  29 + CONSTRAINT [DF_searches_user] DEFAULT (0) FOR [user_id],
  30 + CONSTRAINT [DF_searches_type] DEFAULT (0) FOR [type],
  31 +GO
  32 +
  33 +CREATE UNIQUE INDEX [IX_searches_user_type_name] ON [dbo].[searches]([user_id],[type],[name]) ON [PRIMARY]
  34 +GO
  35 +
  36 +ALTER TABLE [dbo].[searches] ADD CONSTRAINT [FK_searches_user_id]
  37 + FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
  38 + ON DELETE CASCADE ON UPDATE CASCADE
  39 +GO
  40 +
  41 +DROP TABLE [dbo].[messages]
  42 +GO
  43 +CREATE TABLE [dbo].[cache_index] (
  44 + [user_id] [int] NOT NULL ,
  45 + [mailbox] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
  46 + [changed] [datetime] NOT NULL ,
  47 + [valid] [char] (1) COLLATE Latin1_General_CI_AI NOT NULL ,
  48 + [data] [text] COLLATE Latin1_General_CI_AI NOT NULL
  49 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  50 +GO
  51 +
  52 +CREATE TABLE [dbo].[cache_thread] (
  53 + [user_id] [int] NOT NULL ,
  54 + [mailbox] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
  55 + [changed] [datetime] NOT NULL ,
  56 + [data] [text] COLLATE Latin1_General_CI_AI NOT NULL
  57 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  58 +GO
  59 +
  60 +CREATE TABLE [dbo].[cache_messages] (
  61 + [user_id] [int] NOT NULL ,
  62 + [mailbox] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
  63 + [uid] [int] NOT NULL ,
  64 + [changed] [datetime] NOT NULL ,
  65 + [data] [text] COLLATE Latin1_General_CI_AI NOT NULL ,
  66 + [flags] [int] NOT NULL
  67 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  68 +GO
  69 +
  70 +ALTER TABLE [dbo].[cache_index] WITH NOCHECK ADD
  71 + PRIMARY KEY CLUSTERED
  72 + (
  73 + [user_id],[mailbox]
  74 + ) ON [PRIMARY]
  75 +GO
  76 +
  77 +ALTER TABLE [dbo].[cache_thread] WITH NOCHECK ADD
  78 + PRIMARY KEY CLUSTERED
  79 + (
  80 + [user_id],[mailbox]
  81 + ) ON [PRIMARY]
  82 +GO
  83 +
  84 +ALTER TABLE [dbo].[cache_messages] WITH NOCHECK ADD
  85 + PRIMARY KEY CLUSTERED
  86 + (
  87 + [user_id],[mailbox],[uid]
  88 + ) ON [PRIMARY]
  89 +GO
  90 +
  91 +ALTER TABLE [dbo].[cache_index] ADD
  92 + CONSTRAINT [DF_cache_index_changed] DEFAULT (getdate()) FOR [changed],
  93 + CONSTRAINT [DF_cache_index_valid] DEFAULT ('0') FOR [valid]
  94 +GO
  95 +
  96 +CREATE INDEX [IX_cache_index_user_id] ON [dbo].[cache_index]([user_id]) ON [PRIMARY]
  97 +GO
  98 +
  99 +ALTER TABLE [dbo].[cache_thread] ADD
  100 + CONSTRAINT [DF_cache_thread_changed] DEFAULT (getdate()) FOR [changed]
  101 +GO
  102 +
  103 +CREATE INDEX [IX_cache_thread_user_id] ON [dbo].[cache_thread]([user_id]) ON [PRIMARY]
  104 +GO
  105 +
  106 +ALTER TABLE [dbo].[cache_messages] ADD
  107 + CONSTRAINT [DF_cache_messages_changed] DEFAULT (getdate()) FOR [changed],
  108 + CONSTRAINT [DF_cache_messages_flags] DEFAULT (0) FOR [flags]
  109 +GO
  110 +
  111 +CREATE INDEX [IX_cache_messages_user_id] ON [dbo].[cache_messages]([user_id]) ON [PRIMARY]
  112 +GO
  113 +
  114 +ALTER TABLE [dbo].[cache_index] ADD CONSTRAINT [FK_cache_index_user_id]
  115 + FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
  116 + ON DELETE CASCADE ON UPDATE CASCADE
  117 +GO
  118 +
  119 +ALTER TABLE [dbo].[cache_thread] ADD CONSTRAINT [FK_cache_thread_user_id]
  120 + FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
  121 + ON DELETE CASCADE ON UPDATE CASCADE
  122 +GO
  123 +
  124 +ALTER TABLE [dbo].[cache_messages] ADD CONSTRAINT [FK_cache_messages_user_id]
  125 + FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
  126 + ON DELETE CASCADE ON UPDATE CASCADE
  127 +GO
  1 +-- Updates from version 0.7-beta
  2 +
  3 +ALTER TABLE [dbo].[session] ALTER COLUMN [sess_id] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL
  4 +GO
  1 +-- Updates from version 0.7
  2 +
  3 +ALTER TABLE [dbo].[contacts] DROP CONSTRAINT [DF_contacts_email]
  4 +GO
  5 +ALTER TABLE [dbo].[contacts] ALTER COLUMN [email] [text] COLLATE Latin1_General_CI_AI NOT NULL
  6 +GO
  7 +ALTER TABLE [dbo].[contacts] ADD CONSTRAINT [DF_contacts_email] DEFAULT ('') FOR [email]
  8 +GO
  9 +
  1 +-- Updates from version 0.8-rc
  2 +
  3 +ALTER TABLE [dbo].[contacts] DROP CONSTRAINT [DF_contacts_email]
  4 +GO
  5 +ALTER TABLE [dbo].[contacts] ALTER COLUMN [email] [varchar] (8000) COLLATE Latin1_General_CI_AI NOT NULL
  6 +GO
  7 +ALTER TABLE [dbo].[contacts] ADD CONSTRAINT [DF_contacts_email] DEFAULT ('') FOR [email]
  8 +GO
  9 +
  10 +-- Updates from version 0.8
  11 +
  12 +ALTER TABLE [dbo].[cache] DROP COLUMN [cache_id]
  13 +GO
  14 +ALTER TABLE [dbo].[users] DROP COLUMN [alias]
  15 +GO
  16 +CREATE INDEX [IX_identities_email] ON [dbo].[identities]([email],[del]) ON [PRIMARY]
  17 +GO
  18 +
  1 +-- Updates from version 0.8
  2 +
  3 +ALTER TABLE [dbo].[cache] DROP COLUMN [cache_id]
  4 +GO
  5 +ALTER TABLE [dbo].[users] DROP COLUMN [alias]
  6 +GO
  7 +CREATE INDEX [IX_identities_email] ON [dbo].[identities]([email],[del]) ON [PRIMARY]
  8 +GO
  1 +-- Upgrades from 0.9-beta
  2 +
  3 +CREATE TABLE [dbo].[system] (
  4 + [name] [varchar] (64) COLLATE Latin1_General_CI_AI NOT NULL ,
  5 + [value] [text] COLLATE Latin1_General_CI_AI
  6 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  7 +GO
  8 +
  9 +ALTER TABLE [dbo].[system] WITH NOCHECK ADD
  10 + CONSTRAINT [PK_system_name] PRIMARY KEY CLUSTERED
  11 + (
  12 + [name]
  13 + ) ON [PRIMARY]
  14 +GO
  1 +CREATE TABLE [dbo].[cache_shared] (
  2 + [cache_key] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL ,
  3 + [created] [datetime] NOT NULL ,
  4 + [data] [text] COLLATE Latin1_General_CI_AI NOT NULL
  5 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  6 +GO
  7 +
  8 +ALTER TABLE [dbo].[cache_shared] ADD
  9 + CONSTRAINT [DF_cache_shared_created] DEFAULT (getdate()) FOR [created]
  10 +GO
  11 +
  12 +CREATE INDEX [IX_cache_shared_cache_key] ON [dbo].[cache_shared]([cache_key]) ON [PRIMARY]
  13 +GO
  14 +
  15 +CREATE INDEX [IX_cache_shared_created] ON [dbo].[cache_shared]([created]) ON [PRIMARY]
  16 +GO
  17 +
  1 +ALTER TABLE [dbo].[cache] ADD [expires] [datetime] NULL
  2 +GO
  3 +ALTER TABLE [dbo].[cache_shared] ADD [expires] [datetime] NULL
  4 +GO
  5 +ALTER TABLE [dbo].[cache_index] ADD [expires] [datetime] NULL
  6 +GO
  7 +ALTER TABLE [dbo].[cache_thread] ADD [expires] [datetime] NULL
  8 +GO
  9 +ALTER TABLE [dbo].[cache_messages] ADD [expires] [datetime] NULL
  10 +GO
  11 +
  12 +UPDATE [dbo].[cache] SET [expires] = DATEADD(second, 604800, [created])
  13 +GO
  14 +UPDATE [dbo].[cache_shared] SET [expires] = DATEADD(second, 604800, [created])
  15 +GO
  16 +UPDATE [dbo].[cache_index] SET [expires] = DATEADD(second, 604800, [changed])
  17 +GO
  18 +UPDATE [dbo].[cache_thread] SET [expires] = DATEADD(second, 604800, [changed])
  19 +GO
  20 +UPDATE [dbo].[cache_messages] SET [expires] = DATEADD(second, 604800, [changed])
  21 +GO
  22 +
  23 +DROP INDEX [IX_cache_created]
  24 +GO
  25 +DROP INDEX [IX_cache_shared_created]
  26 +GO
  27 +ALTER TABLE [dbo].[cache_index] DROP COLUMN [changed]
  28 +GO
  29 +ALTER TABLE [dbo].[cache_thread] DROP COLUMN [changed]
  30 +GO
  31 +ALTER TABLE [dbo].[cache_messages] DROP COLUMN [changed]
  32 +GO
  33 +
  34 +CREATE INDEX [IX_cache_expires] ON [dbo].[cache]([expires]) ON [PRIMARY]
  35 +GO
  36 +CREATE INDEX [IX_cache_shared_expires] ON [dbo].[cache_shared]([expires]) ON [PRIMARY]
  37 +GO
  38 +CREATE INDEX [IX_cache_index_expires] ON [dbo].[cache_index]([expires]) ON [PRIMARY]
  39 +GO
  40 +CREATE INDEX [IX_cache_thread_expires] ON [dbo].[cache_thread]([expires]) ON [PRIMARY]
  41 +GO
  42 +CREATE INDEX [IX_cache_messages_expires] ON [dbo].[cache_messages]([expires]) ON [PRIMARY]
  43 +GO
  44 +
  1 +ALTER TABLE [dbo].[users] ADD [failed_login] [datetime] NULL
  2 +GO
  3 +ALTER TABLE [dbo].[users] ADD [failed_login_counter] [int] NULL
  4 +GO
  1 +ALTER TABLE [dbo].[session] DROP CONSTRAINT [DF_session_created]
  2 +GO
  3 +
  4 +ALTER TABLE [dbo].[session] DROP COLUMN [created]
  5 +GO
  1 +ALTER TABLE [dbo].[session] ALTER COLUMN [ip] [varchar] (40) COLLATE Latin1_General_CI_AI NOT NULL
  2 +GO
  1 +DROP TABLE [dbo].[cache]
  2 +GO
  3 +DROP TABLE [dbo].[cache_shared]
  4 +GO
  5 +
  6 +CREATE TABLE [dbo].[cache] (
  7 + [user_id] [int] NOT NULL ,
  8 + [cache_key] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
  9 + [expires] [datetime] NULL ,
  10 + [data] [text] COLLATE Latin1_General_CI_AI NOT NULL
  11 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  12 +GO
  13 +CREATE TABLE [dbo].[cache_shared] (
  14 + [cache_key] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL ,
  15 + [expires] [datetime] NULL ,
  16 + [data] [text] COLLATE Latin1_General_CI_AI NOT NULL
  17 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  18 +GO
  19 +ALTER TABLE [dbo].[cache] ADD
  20 + CONSTRAINT [DF_cache_user_id] DEFAULT ('0') FOR [user_id],
  21 + CONSTRAINT [DF_cache_cache_key] DEFAULT ('') FOR [cache_key]
  22 +GO
  23 +CREATE INDEX [IX_cache_expires] ON [dbo].[cache]([expires]) ON [PRIMARY]
  24 +GO
  25 +CREATE INDEX [IX_cache_shared_expires] ON [dbo].[cache_shared]([expires]) ON [PRIMARY]
  26 +GO
  27 +ALTER TABLE [dbo].[cache] WITH NOCHECK ADD
  28 + PRIMARY KEY CLUSTERED (
  29 + [user_id],[cache_key]
  30 + ) ON [PRIMARY]
  31 +GO
  32 +ALTER TABLE [dbo].[cache_shared] WITH NOCHECK ADD
  33 + PRIMARY KEY CLUSTERED (
  34 + [cache_key]
  35 + ) ON [PRIMARY]
  36 +GO
  1 +CREATE TABLE [dbo].[filestore] (
  2 + [file_id] [int] IDENTITY (1, 1) NOT NULL ,
  3 + [user_id] [int] NOT NULL ,
  4 + [filename] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
  5 + [mtime] [int] NOT NULL ,
  6 + [data] [text] COLLATE Latin1_General_CI_AI NULL ,
  7 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  8 +GO
  9 +
  10 +ALTER TABLE [dbo].[filestore] WITH NOCHECK ADD
  11 + CONSTRAINT [PK_filestore_file_id] PRIMARY KEY CLUSTERED
  12 + (
  13 + [file_id]
  14 + ) ON [PRIMARY]
  15 +GO
  16 +
  17 +CREATE INDEX [IX_filestore_user_id] ON [dbo].[filestore]([user_id]) ON [PRIMARY]
  18 +GO
  19 +
  20 +ALTER TABLE [dbo].[filestore] ADD CONSTRAINT [FK_filestore_user_id]
  21 + FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
  22 + ON DELETE CASCADE ON UPDATE CASCADE
  23 +GO
  24 +
  1 +ALTER TABLE [dbo].[filestore] ADD [context] varchar(32) COLLATE Latin1_General_CI_AI NOT NULL
  2 +GO
  3 +
  4 +UPDATE [dbo].[filestore] SET [context] = 'enigma'
  5 +GO
  6 +
  7 +CREATE UNIQUE INDEX [IX_filestore_user_id_context_filename] ON [dbo].[filestore]([user_id],[context],[filename]) ON [PRIMARY]
  8 +GO
  9 +
  1 +ALTER TABLE [dbo].[cache] ALTER COLUMN
  2 + [cache_key] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL
  3 +GO
  4 +ALTER TABLE [dbo].[cache_shared] ALTER COLUMN
  5 + [cache_key] [varchar] (255) COLLATE Latin1_General_CS_AS NOT NULL
  6 +GO
  7 +ALTER TABLE [dbo].[cache_index] ALTER COLUMN
  8 + [mailbox] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL
  9 +GO
  10 +ALTER TABLE [dbo].[cache_messages] ALTER COLUMN
  11 + [mailbox] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL
  12 +GO
  13 +ALTER TABLE [dbo].[cache_thread] ALTER COLUMN
  14 + [mailbox] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL
  15 +GO
  16 +ALTER TABLE [dbo].[users] ALTER COLUMN
  17 + [username] [varchar] (128) COLLATE Latin1_General_CS_AS NOT NULL
  18 +GO
  1 +ALTER TABLE [dbo].[users] ALTER COLUMN [language] [varchar] (16) COLLATE Latin1_General_CI_AI NULL
  2 +GO
  3 +ALTER TABLE [dbo].[dictionary] ALTER COLUMN [language] [varchar] (16) COLLATE Latin1_General_CI_AI NOT NULL
  4 +GO
  1 +CREATE TABLE [dbo].[collected_addresses] (
  2 + [address_id] [int] IDENTITY (1, 1) NOT NULL ,
  3 + [user_id] [int] NOT NULL ,
  4 + [changed] [datetime] NOT NULL ,
  5 + [name] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL ,
  6 + [email] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL ,
  7 + [type] [int] NOT NULL
  8 +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  9 +GO
  10 +
  11 +ALTER TABLE [dbo].[collected_addresses] WITH NOCHECK ADD
  12 + CONSTRAINT [PK_collected_addresses_address_id] PRIMARY KEY CLUSTERED
  13 + (
  14 + [address_id]
  15 + ) ON [PRIMARY]
  16 +GO
  17 +
  18 +ALTER TABLE [dbo].[collected_addresses] ADD
  19 + CONSTRAINT [DF_collected_addresses_user_id] DEFAULT (0) FOR [user_id],
  20 + CONSTRAINT [DF_collected_addresses_changed] DEFAULT (getdate()) FOR [changed],
  21 + CONSTRAINT [DF_collected_addresses_name] DEFAULT ('') FOR [name],
  22 +GO
  23 +
  24 +CREATE UNIQUE INDEX [IX_collected_addresses_user_id] ON [dbo].[collected_addresses]([user_id],[type],[email]) ON [PRIMARY]
  25 +GO
  26 +
  27 +ALTER TABLE [dbo].[collected_addresses] ADD CONSTRAINT [FK_collected_addresses_user_id]
  28 + FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([user_id])
  29 + ON DELETE CASCADE ON UPDATE CASCADE
  30 +GO
  31 +
  1 +-- Roundcube Webmail initial database structure
  2 +
  3 +
  4 +SET FOREIGN_KEY_CHECKS=0;
  5 +
  6 +-- Table structure for table `session`
  7 +
  8 +CREATE TABLE `session` (
  9 + `sess_id` varchar(128) NOT NULL,
  10 + `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
  11 + `ip` varchar(40) NOT NULL,
  12 + `vars` mediumtext NOT NULL,
  13 + PRIMARY KEY(`sess_id`),
  14 + INDEX `changed_index` (`changed`)
  15 +) ROW_FORMAT=DYNAMIC ENGINE=INNODB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  16 +
  17 +
  18 +-- Table structure for table `users`
  19 +
  20 +CREATE TABLE `users` (
  21 + `user_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  22 + `username` varchar(128) BINARY NOT NULL,
  23 + `mail_host` varchar(128) NOT NULL,
  24 + `created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
  25 + `last_login` datetime DEFAULT NULL,
  26 + `failed_login` datetime DEFAULT NULL,
  27 + `failed_login_counter` int(10) UNSIGNED DEFAULT NULL,
  28 + `language` varchar(16),
  29 + `preferences` longtext,
  30 + PRIMARY KEY(`user_id`),
  31 + UNIQUE `username` (`username`, `mail_host`)
  32 +) ROW_FORMAT=DYNAMIC ENGINE=INNODB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  33 +
  34 +
  35 +-- Table structure for table `cache`
  36 +
  37 +CREATE TABLE `cache` (
  38 + `user_id` int(10) UNSIGNED NOT NULL,
  39 + `cache_key` varchar(128) BINARY NOT NULL,
  40 + `expires` datetime DEFAULT NULL,
  41 + `data` longtext NOT NULL,
  42 + PRIMARY KEY (`user_id`, `cache_key`),
  43 + CONSTRAINT `user_id_fk_cache` FOREIGN KEY (`user_id`)
  44 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  45 + INDEX `expires_index` (`expires`)
  46 +) ROW_FORMAT=DYNAMIC ENGINE=INNODB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  47 +
  48 +
  49 +-- Table structure for table `cache_shared`
  50 +
  51 +CREATE TABLE `cache_shared` (
  52 + `cache_key` varchar(64) BINARY NOT NULL,
  53 + `expires` datetime DEFAULT NULL,
  54 + `data` longtext NOT NULL,
  55 + PRIMARY KEY (`cache_key`),
  56 + INDEX `expires_index` (`expires`)
  57 +) ROW_FORMAT=DYNAMIC ENGINE=INNODB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  58 +
  59 +
  60 +-- Table structure for table `cache_index`
  61 +
  62 +CREATE TABLE `cache_index` (
  63 + `user_id` int(10) UNSIGNED NOT NULL,
  64 + `mailbox` varchar(64) BINARY NOT NULL,
  65 + `expires` datetime DEFAULT NULL,
  66 + `valid` tinyint(1) NOT NULL DEFAULT '0',
  67 + `data` longtext NOT NULL,
  68 + CONSTRAINT `user_id_fk_cache_index` FOREIGN KEY (`user_id`)
  69 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  70 + INDEX `expires_index` (`expires`),
  71 + PRIMARY KEY (`user_id`, `mailbox`)
  72 +) ROW_FORMAT=DYNAMIC ENGINE=INNODB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  73 +
  74 +
  75 +-- Table structure for table `cache_thread`
  76 +
  77 +CREATE TABLE `cache_thread` (
  78 + `user_id` int(10) UNSIGNED NOT NULL,
  79 + `mailbox` varchar(64) BINARY NOT NULL,
  80 + `expires` datetime DEFAULT NULL,
  81 + `data` longtext NOT NULL,
  82 + CONSTRAINT `user_id_fk_cache_thread` FOREIGN KEY (`user_id`)
  83 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  84 + INDEX `expires_index` (`expires`),
  85 + PRIMARY KEY (`user_id`, `mailbox`)
  86 +) ROW_FORMAT=DYNAMIC ENGINE=INNODB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  87 +
  88 +
  89 +-- Table structure for table `cache_messages`
  90 +
  91 +CREATE TABLE `cache_messages` (
  92 + `user_id` int(10) UNSIGNED NOT NULL,
  93 + `mailbox` varchar(64) BINARY NOT NULL,
  94 + `uid` int(11) UNSIGNED NOT NULL DEFAULT '0',
  95 + `expires` datetime DEFAULT NULL,
  96 + `data` longtext NOT NULL,
  97 + `flags` int(11) NOT NULL DEFAULT '0',
  98 + CONSTRAINT `user_id_fk_cache_messages` FOREIGN KEY (`user_id`)
  99 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  100 + INDEX `expires_index` (`expires`),
  101 + PRIMARY KEY (`user_id`, `mailbox`, `uid`)
  102 +) ROW_FORMAT=DYNAMIC ENGINE=INNODB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  103 +
  104 +
  105 +-- Table structure for table `collected_addresses`
  106 +
  107 +CREATE TABLE `collected_addresses` (
  108 + `address_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  109 + `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
  110 + `name` varchar(255) NOT NULL DEFAULT '',
  111 + `email` varchar(64) NOT NULL,
  112 + `user_id` int(10) UNSIGNED NOT NULL,
  113 + `type` int(10) UNSIGNED NOT NULL,
  114 + PRIMARY KEY(`address_id`),
  115 + CONSTRAINT `user_id_fk_collected_addresses` FOREIGN KEY (`user_id`)
  116 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  117 + UNIQUE INDEX `user_email_collected_addresses_index` (`user_id`, `type`, `email`)
  118 +) ROW_FORMAT=DYNAMIC ENGINE=INNODB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  119 +
  120 +
  121 +-- Table structure for table `contacts`
  122 +
  123 +CREATE TABLE `contacts` (
  124 + `contact_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  125 + `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
  126 + `del` tinyint(1) NOT NULL DEFAULT '0',
  127 + `name` varchar(128) NOT NULL DEFAULT '',
  128 + `email` text NOT NULL,
  129 + `firstname` varchar(128) NOT NULL DEFAULT '',
  130 + `surname` varchar(128) NOT NULL DEFAULT '',
  131 + `vcard` longtext NULL,
  132 + `words` text NULL,
  133 + `user_id` int(10) UNSIGNED NOT NULL,
  134 + PRIMARY KEY(`contact_id`),
  135 + CONSTRAINT `user_id_fk_contacts` FOREIGN KEY (`user_id`)
  136 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  137 + INDEX `user_contacts_index` (`user_id`,`del`)
  138 +) ROW_FORMAT=DYNAMIC ENGINE=INNODB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  139 +
  140 +
  141 +-- Table structure for table `contactgroups`
  142 +
  143 +CREATE TABLE `contactgroups` (
  144 + `contactgroup_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  145 + `user_id` int(10) UNSIGNED NOT NULL,
  146 + `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
  147 + `del` tinyint(1) NOT NULL DEFAULT '0',
  148 + `name` varchar(128) NOT NULL DEFAULT '',
  149 + PRIMARY KEY(`contactgroup_id`),
  150 + CONSTRAINT `user_id_fk_contactgroups` FOREIGN KEY (`user_id`)
  151 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  152 + INDEX `contactgroups_user_index` (`user_id`,`del`)
  153 +) ROW_FORMAT=DYNAMIC ENGINE=INNODB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  154 +
  155 +
  156 +-- Table structure for table `contactgroupmembers`
  157 +
  158 +CREATE TABLE `contactgroupmembers` (
  159 + `contactgroup_id` int(10) UNSIGNED NOT NULL,
  160 + `contact_id` int(10) UNSIGNED NOT NULL,
  161 + `created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
  162 + PRIMARY KEY (`contactgroup_id`, `contact_id`),
  163 + CONSTRAINT `contactgroup_id_fk_contactgroups` FOREIGN KEY (`contactgroup_id`)
  164 + REFERENCES `contactgroups`(`contactgroup_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  165 + CONSTRAINT `contact_id_fk_contacts` FOREIGN KEY (`contact_id`)
  166 + REFERENCES `contacts`(`contact_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  167 + INDEX `contactgroupmembers_contact_index` (`contact_id`)
  168 +) ROW_FORMAT=DYNAMIC ENGINE=INNODB;
  169 +
  170 +
  171 +-- Table structure for table `identities`
  172 +
  173 +CREATE TABLE `identities` (
  174 + `identity_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  175 + `user_id` int(10) UNSIGNED NOT NULL,
  176 + `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
  177 + `del` tinyint(1) NOT NULL DEFAULT '0',
  178 + `standard` tinyint(1) NOT NULL DEFAULT '0',
  179 + `name` varchar(128) NOT NULL,
  180 + `organization` varchar(128) NOT NULL DEFAULT '',
  181 + `email` varchar(128) NOT NULL,
  182 + `reply-to` varchar(128) NOT NULL DEFAULT '',
  183 + `bcc` varchar(128) NOT NULL DEFAULT '',
  184 + `signature` longtext,
  185 + `html_signature` tinyint(1) NOT NULL DEFAULT '0',
  186 + PRIMARY KEY(`identity_id`),
  187 + CONSTRAINT `user_id_fk_identities` FOREIGN KEY (`user_id`)
  188 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  189 + INDEX `user_identities_index` (`user_id`, `del`),
  190 + INDEX `email_identities_index` (`email`, `del`)
  191 +) ROW_FORMAT=DYNAMIC ENGINE=INNODB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  192 +
  193 +
  194 +-- Table structure for table `dictionary`
  195 +
  196 +CREATE TABLE `dictionary` (
  197 + `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, -- redundant, for compat. with Galera Cluster
  198 + `user_id` int(10) UNSIGNED DEFAULT NULL, -- NULL here is for "shared dictionaries"
  199 + `language` varchar(16) NOT NULL,
  200 + `data` longtext NOT NULL,
  201 + CONSTRAINT `user_id_fk_dictionary` FOREIGN KEY (`user_id`)
  202 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  203 + UNIQUE `uniqueness` (`user_id`, `language`)
  204 +) ROW_FORMAT=DYNAMIC ENGINE=INNODB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  205 +
  206 +
  207 +-- Table structure for table `searches`
  208 +
  209 +CREATE TABLE `searches` (
  210 + `search_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  211 + `user_id` int(10) UNSIGNED NOT NULL,
  212 + `type` int(3) NOT NULL DEFAULT '0',
  213 + `name` varchar(128) NOT NULL,
  214 + `data` text,
  215 + PRIMARY KEY(`search_id`),
  216 + CONSTRAINT `user_id_fk_searches` FOREIGN KEY (`user_id`)
  217 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  218 + UNIQUE `uniqueness` (`user_id`, `type`, `name`)
  219 +) ROW_FORMAT=DYNAMIC ENGINE=INNODB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  220 +
  221 +-- Table structure for table `filestore`
  222 +
  223 +CREATE TABLE `filestore` (
  224 + `file_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  225 + `user_id` int(10) UNSIGNED NOT NULL,
  226 + `context` varchar(32) NOT NULL,
  227 + `filename` varchar(128) NOT NULL,
  228 + `mtime` int(10) NOT NULL,
  229 + `data` longtext NOT NULL,
  230 + PRIMARY KEY (`file_id`),
  231 + CONSTRAINT `user_id_fk_filestore` FOREIGN KEY (`user_id`)
  232 + REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  233 + UNIQUE `uniqueness` (`user_id`, `context`, `filename`)
  234 +) ROW_FORMAT=DYNAMIC ENGINE=INNODB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  235 +
  236 +-- Table structure for table `system`
  237 +
  238 +CREATE TABLE `system` (
  239 + `name` varchar(64) NOT NULL,
  240 + `value` mediumtext,
  241 + PRIMARY KEY(`name`)
  242 +) ROW_FORMAT=DYNAMIC ENGINE=INNODB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  243 +
  244 +SET FOREIGN_KEY_CHECKS=1;
  245 +
  246 +INSERT INTO `system` (`name`, `value`) VALUES ('roundcube-version', '2020122900');
  1 +-- Updates from version 0.1-stable
  2 +
  3 +TRUNCATE TABLE `messages`;
  4 +
  5 +ALTER TABLE `messages`
  6 + DROP INDEX `idx`,
  7 + DROP INDEX `uid`;
  8 +
  9 +ALTER TABLE `cache`
  10 + DROP INDEX `cache_key`,
  11 + DROP INDEX `session_id`,
  12 + ADD INDEX `user_cache_index` (`user_id`,`cache_key`);
  13 +
  14 +ALTER TABLE `users`
  15 + ADD INDEX `username_index` (`username`),
  16 + ADD INDEX `alias_index` (`alias`);
  1 +-- Updates from version 0.1.1
  2 +
  3 +ALTER TABLE `identities`
  4 + MODIFY `signature` text,
  5 + MODIFY `bcc` varchar(128) NOT NULL DEFAULT '',
  6 + MODIFY `reply-to` varchar(128) NOT NULL DEFAULT '',
  7 + MODIFY `organization` varchar(128) NOT NULL DEFAULT '',
  8 + MODIFY `name` varchar(128) NOT NULL,
  9 + MODIFY `email` varchar(128) NOT NULL;
  1 +-- Updates from version 0.2-alpha
  2 +
  3 +ALTER TABLE `messages`
  4 + ADD INDEX `created_index` (`created`);
  1 +-- Updates from version 0.2-beta (InnoDB required)
  2 +
  3 +ALTER TABLE `cache`
  4 + DROP `session_id`;
  5 +
  6 +ALTER TABLE `session`
  7 + ADD INDEX `changed_index` (`changed`);
  8 +
  9 +ALTER TABLE `cache`
  10 + ADD INDEX `created_index` (`created`);
  11 +
  12 +ALTER TABLE `users`
  13 + CHANGE `language` `language` varchar(5);
  14 +
  15 +ALTER TABLE `cache` ENGINE=InnoDB;
  16 +ALTER TABLE `session` ENGINE=InnoDB;
  17 +ALTER TABLE `messages` ENGINE=InnoDB;
  18 +ALTER TABLE `users` ENGINE=InnoDB;
  19 +ALTER TABLE `contacts` ENGINE=InnoDB;
  20 +ALTER TABLE `identities` ENGINE=InnoDB;
  1 +-- Updates from version 0.3-stable
  2 +
  3 +TRUNCATE `messages`;
  4 +
  5 +ALTER TABLE `messages`
  6 + ADD INDEX `index_index` (`user_id`, `cache_key`, `idx`);
  7 +
  8 +ALTER TABLE `session`
  9 + CHANGE `vars` `vars` MEDIUMTEXT NOT NULL;
  10 +
  11 +ALTER TABLE `contacts`
  12 + ADD INDEX `user_contacts_index` (`user_id`,`email`);
  1 +-- Updates from version 0.3.1
  2 +-- WARNING: Make sure that all tables are using InnoDB engine!!!
  3 +-- If not, use: ALTER TABLE xxx ENGINE=InnoDB;
  4 +
  5 +/* MySQL bug workaround: http://bugs.mysql.com/bug.php?id=46293 */
  6 +/*!40014 SET FOREIGN_KEY_CHECKS=0 */;
  7 +
  8 +ALTER TABLE `messages` DROP FOREIGN KEY `user_id_fk_messages`;
  9 +ALTER TABLE `cache` DROP FOREIGN KEY `user_id_fk_cache`;
  10 +ALTER TABLE `contacts` DROP FOREIGN KEY `user_id_fk_contacts`;
  11 +ALTER TABLE `identities` DROP FOREIGN KEY `user_id_fk_identities`;
  12 +
  13 +ALTER TABLE `messages` ADD CONSTRAINT `user_id_fk_messages` FOREIGN KEY (`user_id`)
  14 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;
  15 +ALTER TABLE `cache` ADD CONSTRAINT `user_id_fk_cache` FOREIGN KEY (`user_id`)
  16 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;
  17 +ALTER TABLE `contacts` ADD CONSTRAINT `user_id_fk_contacts` FOREIGN KEY (`user_id`)
  18 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;
  19 +ALTER TABLE `identities` ADD CONSTRAINT `user_id_fk_identities` FOREIGN KEY (`user_id`)
  20 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;
  21 +
  22 +ALTER TABLE `contacts` ALTER `name` SET DEFAULT '';
  23 +ALTER TABLE `contacts` ALTER `firstname` SET DEFAULT '';
  24 +ALTER TABLE `contacts` ALTER `surname` SET DEFAULT '';
  25 +
  26 +ALTER TABLE `identities` ADD INDEX `user_identities_index` (`user_id`, `del`);
  27 +ALTER TABLE `identities` ADD `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00' AFTER `user_id`;
  28 +
  29 +CREATE TABLE `contactgroups` (
  30 + `contactgroup_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  31 + `user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
  32 + `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
  33 + `del` tinyint(1) NOT NULL DEFAULT '0',
  34 + `name` varchar(128) NOT NULL DEFAULT '',
  35 + PRIMARY KEY(`contactgroup_id`),
  36 + CONSTRAINT `user_id_fk_contactgroups` FOREIGN KEY (`user_id`)
  37 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  38 + INDEX `contactgroups_user_index` (`user_id`,`del`)
  39 +) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
  40 +
  41 +CREATE TABLE `contactgroupmembers` (
  42 + `contactgroup_id` int(10) UNSIGNED NOT NULL,
  43 + `contact_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
  44 + `created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
  45 + PRIMARY KEY (`contactgroup_id`, `contact_id`),
  46 + CONSTRAINT `contactgroup_id_fk_contactgroups` FOREIGN KEY (`contactgroup_id`)
  47 + REFERENCES `contactgroups`(`contactgroup_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  48 + CONSTRAINT `contact_id_fk_contacts` FOREIGN KEY (`contact_id`)
  49 + REFERENCES `contacts`(`contact_id`) ON DELETE CASCADE ON UPDATE CASCADE
  50 +) /*!40000 ENGINE=INNODB */;
  51 +
  52 +/*!40014 SET FOREIGN_KEY_CHECKS=1 */;
  1 +-- Updates from version 0.4-beta
  2 +
  3 +ALTER TABLE `users` CHANGE `last_login` `last_login` datetime DEFAULT NULL;
  4 +UPDATE `users` SET `last_login` = NULL WHERE `last_login` = '1000-01-01 00:00:00';
  1 +-- Updates from version 0.4.2
  2 +
  3 +ALTER TABLE `users` DROP INDEX `username_index`;
  4 +ALTER TABLE `users` ADD UNIQUE `username` (`username`, `mail_host`);
  5 +
  6 +ALTER TABLE `contacts` MODIFY `email` varchar(255) NOT NULL;
  7 +
  8 +TRUNCATE TABLE `messages`;
  1 +-- Updates from version 0.5.x
  2 +
  3 +ALTER TABLE `contacts` ADD `words` TEXT NULL AFTER `vcard`;
  4 +ALTER TABLE `contacts` CHANGE `vcard` `vcard` LONGTEXT /*!40101 CHARACTER SET utf8 */ NULL DEFAULT NULL;
  5 +ALTER TABLE `contactgroupmembers` ADD INDEX `contactgroupmembers_contact_index` (`contact_id`);
  6 +
  7 +TRUNCATE TABLE `messages`;
  8 +TRUNCATE TABLE `cache`;
  1 +-- Updates from version 0.6
  2 +
  3 +/*!40014 SET FOREIGN_KEY_CHECKS=0 */;
  4 +
  5 +ALTER TABLE `users` CHANGE `alias` `alias` varchar(128) BINARY NOT NULL;
  6 +ALTER TABLE `users` CHANGE `username` `username` varchar(128) BINARY NOT NULL;
  7 +
  8 +CREATE TABLE `dictionary` (
  9 + `user_id` int(10) UNSIGNED DEFAULT NULL,
  10 + `language` varchar(5) NOT NULL,
  11 + `data` longtext NOT NULL,
  12 + CONSTRAINT `user_id_fk_dictionary` FOREIGN KEY (`user_id`)
  13 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  14 + UNIQUE `uniqueness` (`user_id`, `language`)
  15 +) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
  16 +
  17 +CREATE TABLE `searches` (
  18 + `search_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  19 + `user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
  20 + `type` int(3) NOT NULL DEFAULT '0',
  21 + `name` varchar(128) NOT NULL,
  22 + `data` text,
  23 + PRIMARY KEY(`search_id`),
  24 + CONSTRAINT `user_id_fk_searches` FOREIGN KEY (`user_id`)
  25 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  26 + UNIQUE `uniqueness` (`user_id`, `type`, `name`)
  27 +) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
  28 +
  29 +DROP TABLE `messages`;
  30 +
  31 +CREATE TABLE `cache_index` (
  32 + `user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
  33 + `mailbox` varchar(255) BINARY NOT NULL,
  34 + `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
  35 + `valid` tinyint(1) NOT NULL DEFAULT '0',
  36 + `data` longtext NOT NULL,
  37 + CONSTRAINT `user_id_fk_cache_index` FOREIGN KEY (`user_id`)
  38 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  39 + INDEX `changed_index` (`changed`),
  40 + PRIMARY KEY (`user_id`, `mailbox`)
  41 +) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
  42 +
  43 +CREATE TABLE `cache_thread` (
  44 + `user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
  45 + `mailbox` varchar(255) BINARY NOT NULL,
  46 + `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
  47 + `data` longtext NOT NULL,
  48 + CONSTRAINT `user_id_fk_cache_thread` FOREIGN KEY (`user_id`)
  49 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  50 + INDEX `changed_index` (`changed`),
  51 + PRIMARY KEY (`user_id`, `mailbox`)
  52 +) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
  53 +
  54 +CREATE TABLE `cache_messages` (
  55 + `user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
  56 + `mailbox` varchar(255) BINARY NOT NULL,
  57 + `uid` int(11) UNSIGNED NOT NULL DEFAULT '0',
  58 + `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
  59 + `data` longtext NOT NULL,
  60 + `flags` int(11) NOT NULL DEFAULT '0',
  61 + CONSTRAINT `user_id_fk_cache_messages` FOREIGN KEY (`user_id`)
  62 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  63 + INDEX `changed_index` (`changed`),
  64 + PRIMARY KEY (`user_id`, `mailbox`, `uid`)
  65 +) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
  66 +
  67 +/*!40014 SET FOREIGN_KEY_CHECKS=1 */;
  1 +-- Updates from version 0.7-beta
  2 +
  3 +ALTER TABLE `session` CHANGE `sess_id` `sess_id` varchar(128) NOT NULL;
  1 +-- Updates from version 0.7
  2 +
  3 +/*!40014 SET FOREIGN_KEY_CHECKS=0 */;
  4 +
  5 +ALTER TABLE `contacts` DROP FOREIGN KEY `user_id_fk_contacts`;
  6 +ALTER TABLE `contacts` DROP INDEX `user_contacts_index`;
  7 +ALTER TABLE `contacts` MODIFY `email` text NOT NULL;
  8 +ALTER TABLE `contacts` ADD INDEX `user_contacts_index` (`user_id`,`del`);
  9 +ALTER TABLE `contacts` ADD CONSTRAINT `user_id_fk_contacts` FOREIGN KEY (`user_id`)
  10 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;
  11 +
  12 +ALTER TABLE `cache` ALTER `user_id` DROP DEFAULT;
  13 +ALTER TABLE `cache_index` ALTER `user_id` DROP DEFAULT;
  14 +ALTER TABLE `cache_thread` ALTER `user_id` DROP DEFAULT;
  15 +ALTER TABLE `cache_messages` ALTER `user_id` DROP DEFAULT;
  16 +ALTER TABLE `contacts` ALTER `user_id` DROP DEFAULT;
  17 +ALTER TABLE `contactgroups` ALTER `user_id` DROP DEFAULT;
  18 +ALTER TABLE `contactgroupmembers` ALTER `contact_id` DROP DEFAULT;
  19 +ALTER TABLE `identities` ALTER `user_id` DROP DEFAULT;
  20 +ALTER TABLE `searches` ALTER `user_id` DROP DEFAULT;
  21 +
  22 +/*!40014 SET FOREIGN_KEY_CHECKS=1 */;
  1 +-- Updates from version 0.8
  2 +
  3 +ALTER TABLE `cache` DROP COLUMN `cache_id`;
  4 +ALTER TABLE `users` DROP COLUMN `alias`;
  5 +ALTER TABLE `identities` ADD INDEX `email_identities_index` (`email`, `del`);
  1 +-- Upgrade from 0.9-beta
  2 +
  3 +CREATE TABLE IF NOT EXISTS `system` (
  4 + `name` varchar(64) NOT NULL,
  5 + `value` mediumtext,
  6 + PRIMARY KEY(`name`)
  7 +) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
  1 +CREATE TABLE `cache_shared` (
  2 + `cache_key` varchar(255) /*!40101 CHARACTER SET ascii COLLATE ascii_general_ci */ NOT NULL,
  3 + `created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
  4 + `data` longtext NOT NULL,
  5 + INDEX `created_index` (`created`),
  6 + INDEX `cache_key_index` (`cache_key`)
  7 +) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
  1 +ALTER TABLE `cache` ADD `expires` datetime DEFAULT NULL;
  2 +ALTER TABLE `cache_shared` ADD `expires` datetime DEFAULT NULL;
  3 +ALTER TABLE `cache_index` ADD `expires` datetime DEFAULT NULL;
  4 +ALTER TABLE `cache_thread` ADD `expires` datetime DEFAULT NULL;
  5 +ALTER TABLE `cache_messages` ADD `expires` datetime DEFAULT NULL;
  6 +
  7 +-- initialize expires column with created/changed date + 7days
  8 +UPDATE `cache` SET `expires` = `created` + interval 604800 second;
  9 +UPDATE `cache_shared` SET `expires` = `created` + interval 604800 second;
  10 +UPDATE `cache_index` SET `expires` = `changed` + interval 604800 second;
  11 +UPDATE `cache_thread` SET `expires` = `changed` + interval 604800 second;
  12 +UPDATE `cache_messages` SET `expires` = `changed` + interval 604800 second;
  13 +
  14 +ALTER TABLE `cache` DROP INDEX `created_index`;
  15 +ALTER TABLE `cache_shared` DROP INDEX `created_index`;
  16 +ALTER TABLE `cache_index` DROP `changed`;
  17 +ALTER TABLE `cache_thread` DROP `changed`;
  18 +ALTER TABLE `cache_messages` DROP `changed`;
  19 +
  20 +ALTER TABLE `cache` ADD INDEX `expires_index` (`expires`);
  21 +ALTER TABLE `cache_shared` ADD INDEX `expires_index` (`expires`);
  22 +ALTER TABLE `cache_index` ADD INDEX `expires_index` (`expires`);
  23 +ALTER TABLE `cache_thread` ADD INDEX `expires_index` (`expires`);
  24 +ALTER TABLE `cache_messages` ADD INDEX `expires_index` (`expires`);
  1 +ALTER TABLE `users` CHANGE `preferences` `preferences` longtext;
  1 +ALTER TABLE `identities` CHANGE `signature` `signature` longtext;
  1 +ALTER TABLE `users`
  2 + ADD `failed_login` datetime DEFAULT NULL,
  3 + ADD `failed_login_counter` int(10) UNSIGNED DEFAULT NULL;
  1 +ALTER TABLE `session` DROP COLUMN `created`;
  1 +ALTER TABLE `session` MODIFY `ip` varchar(40) NOT NULL;
  1 +ALTER TABLE `dictionary` ADD COLUMN `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST; -- redundant, for compat. with Galera Cluster
  2 +
  3 +DROP TABLE `cache`;
  4 +DROP TABLE `cache_shared`;
  5 +
  6 +CREATE TABLE `cache` (
  7 + `user_id` int(10) UNSIGNED NOT NULL,
  8 + `cache_key` varchar(128) /*!40101 CHARACTER SET ascii COLLATE ascii_general_ci */ NOT NULL,
  9 + `expires` datetime DEFAULT NULL,
  10 + `data` longtext NOT NULL,
  11 + PRIMARY KEY (`user_id`, `cache_key`),
  12 + CONSTRAINT `user_id_fk_cache` FOREIGN KEY (`user_id`)
  13 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  14 + INDEX `expires_index` (`expires`)
  15 +) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
  16 +
  17 +
  18 +CREATE TABLE `cache_shared` (
  19 + `cache_key` varchar(255) /*!40101 CHARACTER SET ascii COLLATE ascii_general_ci */ NOT NULL,
  20 + `expires` datetime DEFAULT NULL,
  21 + `data` longtext NOT NULL,
  22 + PRIMARY KEY (`cache_key`),
  23 + INDEX `expires_index` (`expires`)
  24 +) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
  1 +CREATE TABLE `filestore` (
  2 + `file_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  3 + `user_id` int(10) UNSIGNED NOT NULL,
  4 + `filename` varchar(128) NOT NULL,
  5 + `mtime` int(10) NOT NULL,
  6 + `data` longtext NOT NULL,
  7 + PRIMARY KEY (`file_id`),
  8 + CONSTRAINT `user_id_fk_filestore` FOREIGN KEY (`user_id`)
  9 + REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  10 + UNIQUE `uniqueness` (`user_id`, `filename`)
  11 +) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
  1 +ALTER TABLE `filestore` ADD COLUMN `context` varchar(32) NOT NULL;
  2 +UPDATE `filestore` SET `context` = 'enigma';
  3 +ALTER TABLE `filestore` DROP FOREIGN KEY `user_id_fk_filestore`;
  4 +ALTER TABLE `filestore` DROP INDEX `uniqueness`;
  5 +ALTER TABLE `filestore` ADD UNIQUE INDEX `uniqueness` (`user_id`, `context`, `filename`);
  6 +ALTER TABLE `filestore` ADD CONSTRAINT `user_id_fk_filestore` FOREIGN KEY (`user_id`)
  7 + REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;
  1 +ALTER TABLE `cache` CHANGE `cache_key` `cache_key` varchar(128) BINARY NOT NULL;
  2 +ALTER TABLE `cache_shared` CHANGE `cache_key` `cache_key` varchar(255) BINARY NOT NULL;
  1 +ALTER TABLE `users` MODIFY `language` varchar(16);
  2 +ALTER TABLE `dictionary` MODIFY `language` varchar(16) NOT NULL;
  1 +-- Dropping foreign keys and changing table format is needed for some versions of MySQL (#7277)
  2 +ALTER TABLE `cache` DROP FOREIGN KEY `user_id_fk_cache`;
  3 +ALTER TABLE `cache_index` DROP FOREIGN KEY `user_id_fk_cache_index`;
  4 +ALTER TABLE `cache_thread` DROP FOREIGN KEY `user_id_fk_cache_thread`;
  5 +ALTER TABLE `cache_messages` DROP FOREIGN KEY `user_id_fk_cache_messages`;
  6 +ALTER TABLE `contactgroups` DROP FOREIGN KEY `user_id_fk_contactgroups`;
  7 +ALTER TABLE `contacts` DROP FOREIGN KEY `user_id_fk_contacts`;
  8 +ALTER TABLE `dictionary` DROP FOREIGN KEY `user_id_fk_dictionary`;
  9 +ALTER TABLE `filestore` DROP FOREIGN KEY `user_id_fk_filestore`;
  10 +ALTER TABLE `identities` DROP FOREIGN KEY `user_id_fk_identities`;
  11 +ALTER TABLE `searches` DROP FOREIGN KEY `user_id_fk_searches`;
  12 +
  13 +ALTER TABLE `session` ROW_FORMAT=DYNAMIC;
  14 +ALTER TABLE `users` ROW_FORMAT=DYNAMIC;
  15 +ALTER TABLE `cache` ROW_FORMAT=DYNAMIC;
  16 +ALTER TABLE `cache_shared` ROW_FORMAT=DYNAMIC;
  17 +ALTER TABLE `cache_index` ROW_FORMAT=DYNAMIC;
  18 +ALTER TABLE `cache_thread` ROW_FORMAT=DYNAMIC;
  19 +ALTER TABLE `cache_messages` ROW_FORMAT=DYNAMIC;
  20 +ALTER TABLE `contacts` ROW_FORMAT=DYNAMIC;
  21 +ALTER TABLE `contactgroups` ROW_FORMAT=DYNAMIC;
  22 +ALTER TABLE `contactgroupmembers` ROW_FORMAT=DYNAMIC;
  23 +ALTER TABLE `identities` ROW_FORMAT=DYNAMIC;
  24 +ALTER TABLE `dictionary` ROW_FORMAT=DYNAMIC;
  25 +ALTER TABLE `searches` ROW_FORMAT=DYNAMIC;
  26 +ALTER TABLE `filestore` ROW_FORMAT=DYNAMIC;
  27 +ALTER TABLE `system` ROW_FORMAT=DYNAMIC;
  28 +
  29 +ALTER TABLE `session` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  30 +ALTER TABLE `users` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  31 +ALTER TABLE `cache` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  32 +ALTER TABLE `cache_shared` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  33 +ALTER TABLE `cache_index` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  34 +ALTER TABLE `cache_thread` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  35 +ALTER TABLE `cache_messages` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  36 +ALTER TABLE `contacts` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  37 +ALTER TABLE `contactgroups` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  38 +ALTER TABLE `identities` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  39 +ALTER TABLE `dictionary` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  40 +ALTER TABLE `searches` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  41 +ALTER TABLE `filestore` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  42 +ALTER TABLE `system` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  43 +
  44 +ALTER TABLE `users` CHANGE `username` `username` varchar(128) BINARY NOT NULL;
  45 +ALTER TABLE `cache` CHANGE `cache_key` `cache_key` varchar(128) BINARY NOT NULL;
  46 +ALTER TABLE `cache_shared` CHANGE `cache_key` `cache_key` varchar(255) BINARY NOT NULL;
  47 +ALTER TABLE `cache_index` CHANGE `mailbox` `mailbox` varchar(255) BINARY NOT NULL;
  48 +ALTER TABLE `cache_thread` CHANGE `mailbox` `mailbox` varchar(255) BINARY NOT NULL;
  49 +ALTER TABLE `cache_messages` CHANGE `mailbox` `mailbox` varchar(255) BINARY NOT NULL;
  50 +
  51 +ALTER TABLE `cache`
  52 + ADD CONSTRAINT `user_id_fk_cache` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;
  53 +ALTER TABLE `cache_index`
  54 + ADD CONSTRAINT `user_id_fk_cache_index` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;
  55 +ALTER TABLE `cache_thread`
  56 + ADD CONSTRAINT `user_id_fk_cache_thread` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;
  57 +ALTER TABLE `cache_messages`
  58 + ADD CONSTRAINT `user_id_fk_cache_messages` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;
  59 +ALTER TABLE `contactgroups`
  60 + ADD CONSTRAINT `user_id_fk_contactgroups` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;
  61 +ALTER TABLE `contacts`
  62 + ADD CONSTRAINT `user_id_fk_contacts` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;
  63 +ALTER TABLE `dictionary`
  64 + ADD CONSTRAINT `user_id_fk_dictionary` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;
  65 +ALTER TABLE `filestore`
  66 + ADD CONSTRAINT `user_id_fk_filestore` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;
  67 +ALTER TABLE `identities`
  68 + ADD CONSTRAINT `user_id_fk_identities` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;
  69 +ALTER TABLE `searches`
  70 + ADD CONSTRAINT `user_id_fk_searches` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;
  1 +CREATE TABLE `collected_addresses` (
  2 + `address_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  3 + `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
  4 + `name` varchar(255) NOT NULL DEFAULT '',
  5 + `email` varchar(255) NOT NULL,
  6 + `user_id` int(10) UNSIGNED NOT NULL,
  7 + `type` int(10) UNSIGNED NOT NULL,
  8 + PRIMARY KEY(`address_id`),
  9 + CONSTRAINT `user_id_fk_collected_addresses` FOREIGN KEY (`user_id`)
  10 + REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  11 + UNIQUE INDEX `user_email_collected_addresses_index` (`user_id`, `type`, `email`)
  12 +) ROW_FORMAT=DYNAMIC ENGINE=INNODB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  1 +-- Roundcube Webmail initial database structure
  2 +-- This was tested with Oracle 11g
  3 +
  4 +CREATE TABLE "users" (
  5 + "user_id" integer PRIMARY KEY,
  6 + "username" varchar(128) NOT NULL,
  7 + "mail_host" varchar(128) NOT NULL,
  8 + "created" timestamp with time zone DEFAULT current_timestamp NOT NULL,
  9 + "last_login" timestamp with time zone DEFAULT NULL,
  10 + "failed_login" timestamp with time zone DEFAULT NULL,
  11 + "failed_login_counter" integer DEFAULT NULL,
  12 + "language" varchar(16),
  13 + "preferences" long DEFAULT NULL,
  14 + CONSTRAINT "users_username_key" UNIQUE ("username", "mail_host")
  15 +);
  16 +
  17 +CREATE SEQUENCE "users_seq"
  18 + START WITH 1 INCREMENT BY 1 NOMAXVALUE;
  19 +
  20 +CREATE TRIGGER "users_seq_trig"
  21 +BEFORE INSERT ON "users" FOR EACH ROW
  22 +BEGIN
  23 + :NEW."user_id" := "users_seq".nextval;
  24 +END;
  25 +/
  26 +
  27 +CREATE TABLE "session" (
  28 + "sess_id" varchar(128) NOT NULL PRIMARY KEY,
  29 + "changed" timestamp with time zone DEFAULT current_timestamp NOT NULL,
  30 + "ip" varchar(41) NOT NULL,
  31 + "vars" long NOT NULL
  32 +);
  33 +
  34 +CREATE INDEX "session_changed_idx" ON "session" ("changed");
  35 +
  36 +
  37 +CREATE TABLE "identities" (
  38 + "identity_id" integer PRIMARY KEY,
  39 + "user_id" integer NOT NULL
  40 + REFERENCES "users" ("user_id") ON DELETE CASCADE,
  41 + "changed" timestamp with time zone DEFAULT current_timestamp NOT NULL,
  42 + "del" smallint DEFAULT 0 NOT NULL,
  43 + "standard" smallint DEFAULT 0 NOT NULL,
  44 + "name" varchar(128) NOT NULL,
  45 + "organization" varchar(128),
  46 + "email" varchar(128) NOT NULL,
  47 + "reply-to" varchar(128),
  48 + "bcc" varchar(128),
  49 + "signature" long,
  50 + "html_signature" integer DEFAULT 0 NOT NULL
  51 +);
  52 +
  53 +CREATE INDEX "identities_user_id_idx" ON "identities" ("user_id", "del");
  54 +CREATE INDEX "identities_email_idx" ON "identities" ("email", "del");
  55 +
  56 +CREATE SEQUENCE "identities_seq"
  57 + START WITH 1 INCREMENT BY 1 NOMAXVALUE;
  58 +
  59 +CREATE TRIGGER "identities_seq_trig"
  60 +BEFORE INSERT ON "identities" FOR EACH ROW
  61 +BEGIN
  62 + :NEW."identity_id" := "identities_seq".nextval;
  63 +END;
  64 +/
  65 +
  66 +CREATE TABLE "collected_addresses" (
  67 + "address_id" integer PRIMARY KEY,
  68 + "user_id" integer NOT NULL
  69 + REFERENCES "users" ("user_id") ON DELETE CASCADE,
  70 + "changed" timestamp with time zone DEFAULT current_timestamp NOT NULL,
  71 + "name" varchar(255) DEFAULT NULL,
  72 + "email" varchar(255) DEFAULT NULL,
  73 + "type" integer NOT NULL
  74 +);
  75 +
  76 +CREATE UNIQUE INDEX "collected_addresses_user_id_idx" ON "collected_addresses" ("user_id", "type", "email");
  77 +
  78 +CREATE SEQUENCE "collected_addresses_seq"
  79 + START WITH 1 INCREMENT BY 1 NOMAXVALUE;
  80 +
  81 +CREATE TRIGGER "collected_addresses_seq_trig"
  82 +BEFORE INSERT ON "collected_addresses" FOR EACH ROW
  83 +BEGIN
  84 + :NEW."address_id" := "collected_addresses_seq".nextval;
  85 +END;
  86 +/
  87 +
  88 +CREATE TABLE "contacts" (
  89 + "contact_id" integer PRIMARY KEY,
  90 + "user_id" integer NOT NULL
  91 + REFERENCES "users" ("user_id") ON DELETE CASCADE,
  92 + "changed" timestamp with time zone DEFAULT current_timestamp NOT NULL,
  93 + "del" smallint DEFAULT 0 NOT NULL,
  94 + "name" varchar(128) DEFAULT NULL,
  95 + "email" varchar(4000) DEFAULT NULL,
  96 + "firstname" varchar(128) DEFAULT NULL,
  97 + "surname" varchar(128) DEFAULT NULL,
  98 + "vcard" long,
  99 + "words" varchar(4000)
  100 +);
  101 +
  102 +CREATE INDEX "contacts_user_id_idx" ON "contacts" ("user_id", "del");
  103 +
  104 +CREATE SEQUENCE "contacts_seq"
  105 + START WITH 1 INCREMENT BY 1 NOMAXVALUE;
  106 +
  107 +CREATE TRIGGER "contacts_seq_trig"
  108 +BEFORE INSERT ON "contacts" FOR EACH ROW
  109 +BEGIN
  110 + :NEW."contact_id" := "contacts_seq".nextval;
  111 +END;
  112 +/
  113 +
  114 +CREATE TABLE "contactgroups" (
  115 + "contactgroup_id" integer PRIMARY KEY,
  116 + "user_id" integer NOT NULL
  117 + REFERENCES "users" ("user_id") ON DELETE CASCADE,
  118 + "changed" timestamp with time zone DEFAULT current_timestamp NOT NULL,
  119 + "del" smallint DEFAULT 0 NOT NULL,
  120 + "name" varchar(128) NOT NULL
  121 +);
  122 +
  123 +CREATE INDEX "contactgroups_user_id_idx" ON "contactgroups" ("user_id", "del");
  124 +
  125 +CREATE SEQUENCE "contactgroups_seq"
  126 + START WITH 1 INCREMENT BY 1 NOMAXVALUE;
  127 +
  128 +CREATE TRIGGER "contactgroups_seq_trig"
  129 +BEFORE INSERT ON "contactgroups" FOR EACH ROW
  130 +BEGIN
  131 + :NEW."contactgroup_id" := "contactgroups_seq".nextval;
  132 +END;
  133 +/
  134 +
  135 +CREATE TABLE "contactgroupmembers" (
  136 + "contactgroup_id" integer NOT NULL
  137 + REFERENCES "contactgroups" ("contactgroup_id") ON DELETE CASCADE,
  138 + "contact_id" integer NOT NULL
  139 + REFERENCES "contacts" ("contact_id") ON DELETE CASCADE,
  140 + "created" timestamp with time zone DEFAULT current_timestamp NOT NULL,
  141 + PRIMARY KEY ("contactgroup_id", "contact_id")
  142 +);
  143 +
  144 +CREATE INDEX "contactgroupmembers_idx" ON "contactgroupmembers" ("contact_id");
  145 +
  146 +
  147 +CREATE TABLE "cache" (
  148 + "user_id" integer NOT NULL
  149 + REFERENCES "users" ("user_id") ON DELETE CASCADE,
  150 + "cache_key" varchar(128) NOT NULL,
  151 + "expires" timestamp with time zone DEFAULT NULL,
  152 + "data" long NOT NULL,
  153 + PRIMARY KEY ("user_id", "cache_key")
  154 +);
  155 +
  156 +CREATE INDEX "cache_expires_idx" ON "cache" ("expires");
  157 +
  158 +
  159 +CREATE TABLE "cache_shared" (
  160 + "cache_key" varchar(255) NOT NULL,
  161 + "expires" timestamp with time zone DEFAULT NULL,
  162 + "data" long NOT NULL,
  163 + PRIMARY KEY ("cache_key")
  164 +);
  165 +
  166 +CREATE INDEX "cache_shared_expires_idx" ON "cache_shared" ("expires");
  167 +
  168 +
  169 +CREATE TABLE "cache_index" (
  170 + "user_id" integer NOT NULL
  171 + REFERENCES "users" ("user_id") ON DELETE CASCADE,
  172 + "mailbox" varchar(255) NOT NULL,
  173 + "expires" timestamp with time zone DEFAULT NULL,
  174 + "valid" smallint DEFAULT 0 NOT NULL,
  175 + "data" long NOT NULL,
  176 + PRIMARY KEY ("user_id", "mailbox")
  177 +);
  178 +
  179 +CREATE INDEX "cache_index_expires_idx" ON "cache_index" ("expires");
  180 +
  181 +
  182 +CREATE TABLE "cache_thread" (
  183 + "user_id" integer NOT NULL
  184 + REFERENCES "users" ("user_id") ON DELETE CASCADE,
  185 + "mailbox" varchar(255) NOT NULL,
  186 + "expires" timestamp with time zone DEFAULT NULL,
  187 + "data" long NOT NULL,
  188 + PRIMARY KEY ("user_id", "mailbox")
  189 +);
  190 +
  191 +CREATE INDEX "cache_thread_expires_idx" ON "cache_thread" ("expires");
  192 +
  193 +
  194 +CREATE TABLE "cache_messages" (
  195 + "user_id" integer NOT NULL
  196 + REFERENCES "users" ("user_id") ON DELETE CASCADE,
  197 + "mailbox" varchar(255) NOT NULL,
  198 + "uid" integer NOT NULL,
  199 + "expires" timestamp with time zone DEFAULT NULL,
  200 + "data" long NOT NULL,
  201 + "flags" integer DEFAULT 0 NOT NULL,
  202 + PRIMARY KEY ("user_id", "mailbox", "uid")
  203 +);
  204 +
  205 +CREATE INDEX "cache_messages_expires_idx" ON "cache_messages" ("expires");
  206 +
  207 +
  208 +CREATE TABLE "dictionary" (
  209 + "user_id" integer DEFAULT NULL
  210 + REFERENCES "users" ("user_id") ON DELETE CASCADE,
  211 + "language" varchar(16) NOT NULL,
  212 + "data" long DEFAULT NULL,
  213 + CONSTRAINT "dictionary_user_id_lang_key" UNIQUE ("user_id", "language")
  214 +);
  215 +
  216 +
  217 +CREATE TABLE "searches" (
  218 + "search_id" integer PRIMARY KEY,
  219 + "user_id" integer NOT NULL
  220 + REFERENCES "users" ("user_id") ON DELETE CASCADE,
  221 + "type" smallint DEFAULT 0 NOT NULL,
  222 + "name" varchar(128) NOT NULL,
  223 + "data" long NOT NULL,
  224 + CONSTRAINT "searches_user_id_key" UNIQUE ("user_id", "type", "name")
  225 +);
  226 +
  227 +CREATE SEQUENCE "searches_seq"
  228 + START WITH 1 INCREMENT BY 1 NOMAXVALUE;
  229 +
  230 +CREATE TRIGGER "searches_seq_trig"
  231 +BEFORE INSERT ON "searches" FOR EACH ROW
  232 +BEGIN
  233 + :NEW."search_id" := "searches_seq".nextval;
  234 +END;
  235 +/
  236 +
  237 +CREATE TABLE "filestore" (
  238 + "file_id" integer PRIMARY KEY,
  239 + "user_id" integer NOT NULL
  240 + REFERENCES "users" ("user_id") ON DELETE CASCADE ON UPDATE CASCADE,
  241 + "context" varchar(32) NOT NULL,
  242 + "filename" varchar(128) NOT NULL,
  243 + "mtime" integer NOT NULL,
  244 + "data" long,
  245 + CONSTRAINT "filestore_user_id_key" UNIQUE ("user_id", "context", "filename")
  246 +);
  247 +
  248 +CREATE SEQUENCE "filestore_seq"
  249 + START WITH 1 INCREMENT BY 1 NOMAXVALUE;
  250 +
  251 +CREATE TRIGGER "filestore_seq_trig"
  252 +BEFORE INSERT ON "filestore" FOR EACH ROW
  253 +BEGIN
  254 + :NEW."user_id" := "filestore_seq".nextval;
  255 +END;
  256 +/
  257 +
  258 +CREATE TABLE "system" (
  259 + "name" varchar(64) NOT NULL PRIMARY KEY,
  260 + "value" long
  261 +);
  262 +
  263 +INSERT INTO "system" ("name", "value") VALUES ('roundcube-version', '2020122900');
  1 +ALTER TABLE "users" ADD "failed_login" timestamp with time zone DEFAULT NULL;
  2 +ALTER TABLE "users" ADD "failed_login_counter" integer DEFAULT NULL;
  1 +ALTER TABLE "session" DROP COLUMN "created";
  1 +ALTER TABLE "session" MODIFY "ip" varchar(41) NOT NULL;
  1 +DROP TABLE "cache";
  2 +DROP TABLE "cache_shared";
  3 +
  4 +CREATE TABLE "cache" (
  5 + "user_id" integer NOT NULL
  6 + REFERENCES "users" ("user_id") ON DELETE CASCADE,
  7 + "cache_key" varchar(128) NOT NULL,
  8 + "expires" timestamp with time zone DEFAULT NULL,
  9 + "data" long NOT NULL,
  10 + PRIMARY KEY ("user_id", "cache_key")
  11 +);
  12 +
  13 +CREATE INDEX "cache_expires_idx" ON "cache" ("expires");
  14 +
  15 +
  16 +CREATE TABLE "cache_shared" (
  17 + "cache_key" varchar(255) NOT NULL,
  18 + "expires" timestamp with time zone DEFAULT NULL,
  19 + "data" long NOT NULL,
  20 + PRIMARY KEY ("cache_key")
  21 +);
  22 +
  23 +CREATE INDEX "cache_shared_expires_idx" ON "cache_shared" ("expires");
  1 +CREATE TABLE "filestore" (
  2 + "file_id" integer PRIMARY KEY,
  3 + "user_id" integer NOT NULL
  4 + REFERENCES "users" ("user_id") ON DELETE CASCADE ON UPDATE CASCADE,
  5 + "filename" varchar(128) NOT NULL,
  6 + "mtime" integer NOT NULL,
  7 + "data" long,
  8 + CONSTRAINT "filestore_user_id_key" UNIQUE ("user_id", "filename")
  9 +);
  10 +
  11 +CREATE SEQUENCE "filestore_seq"
  12 + START WITH 1 INCREMENT BY 1 NOMAXVALUE;
  13 +
  14 +CREATE TRIGGER "filestore_seq_trig"
  15 +BEFORE INSERT ON "filestore" FOR EACH ROW
  16 +BEGIN
  17 + :NEW."user_id" := "filestore_seq".nextval;
  18 +END;
  19 +/
  1 +ALTER TABLE "filestore" ADD COLUMN "context" varchar(32) NOT NULL;
  2 +UPDATE "filestore" SET "context" = 'enigma';
  3 +ALTER TABLE "filestore" DROP CONSTRAINT "filestore_user_id_key";
  4 +ALTER TABLE "filestore" ADD CONSTRAINT "filestore_user_id_key" UNIQUE ("user_id", "context", "filename");
  1 +ALTER TABLE "users" MODIFY "language" varchar(16) NOT NULL;
  2 +ALTER TABLE "dictionary" MODIFY "language" varchar(16);
  1 +CREATE TABLE "collected_addresses" (
  2 + "address_id" integer PRIMARY KEY,
  3 + "user_id" integer NOT NULL
  4 + REFERENCES "users" ("user_id") ON DELETE CASCADE,
  5 + "changed" timestamp with time zone DEFAULT current_timestamp NOT NULL,
  6 + "name" varchar(255) DEFAULT NULL,
  7 + "email" varchar(255) DEFAULT NULL,
  8 + "type" integer NOT NULL
  9 +);
  10 +
  11 +CREATE UNIQUE INDEX "collected_addresses_user_id_idx" ON "collected_addresses" ("user_id", "type", "email");
  12 +
  13 +CREATE SEQUENCE "collected_addresses_seq"
  14 + START WITH 1 INCREMENT BY 1 NOMAXVALUE;
  15 +
  16 +CREATE TRIGGER "collected_addresses_seq_trig"
  17 +BEFORE INSERT ON "collected_addresses" FOR EACH ROW
  18 +BEGIN
  19 + :NEW."address_id" := "collected_addresses_seq".nextval;
  20 +END;
  21 +/
  1 +-- Roundcube Webmail initial database structure
  2 +
  3 +--
  4 +-- Sequence "users_seq"
  5 +-- Name: users_seq; Type: SEQUENCE; Schema: public; Owner: postgres
  6 +--
  7 +
  8 +CREATE SEQUENCE users_seq
  9 + INCREMENT BY 1
  10 + NO MAXVALUE
  11 + NO MINVALUE
  12 + CACHE 1;
  13 +
  14 +--
  15 +-- Table "users"
  16 +-- Name: users; Type: TABLE; Schema: public; Owner: postgres
  17 +--
  18 +
  19 +CREATE TABLE users (
  20 + user_id integer DEFAULT nextval('users_seq'::text) PRIMARY KEY,
  21 + username varchar(128) DEFAULT '' NOT NULL,
  22 + mail_host varchar(128) DEFAULT '' NOT NULL,
  23 + created timestamp with time zone DEFAULT now() NOT NULL,
  24 + last_login timestamp with time zone DEFAULT NULL,
  25 + failed_login timestamp with time zone DEFAULT NULL,
  26 + failed_login_counter integer DEFAULT NULL,
  27 + "language" varchar(16),
  28 + preferences text DEFAULT NULL,
  29 + CONSTRAINT users_username_key UNIQUE (username, mail_host)
  30 +);
  31 +
  32 +
  33 +--
  34 +-- Table "session"
  35 +-- Name: session; Type: TABLE; Schema: public; Owner: postgres
  36 +--
  37 +
  38 +CREATE TABLE "session" (
  39 + sess_id varchar(128) DEFAULT '' PRIMARY KEY,
  40 + changed timestamp with time zone DEFAULT now() NOT NULL,
  41 + ip varchar(41) NOT NULL,
  42 + vars text NOT NULL
  43 +);
  44 +
  45 +CREATE INDEX session_changed_idx ON session (changed);
  46 +
  47 +
  48 +--
  49 +-- Sequence "identities_seq"
  50 +-- Name: identities_seq; Type: SEQUENCE; Schema: public; Owner: postgres
  51 +--
  52 +
  53 +CREATE SEQUENCE identities_seq
  54 + START WITH 1
  55 + INCREMENT BY 1
  56 + NO MAXVALUE
  57 + NO MINVALUE
  58 + CACHE 1;
  59 +
  60 +--
  61 +-- Table "identities"
  62 +-- Name: identities; Type: TABLE; Schema: public; Owner: postgres
  63 +--
  64 +
  65 +CREATE TABLE identities (
  66 + identity_id integer DEFAULT nextval('identities_seq'::text) PRIMARY KEY,
  67 + user_id integer NOT NULL
  68 + REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
  69 + changed timestamp with time zone DEFAULT now() NOT NULL,
  70 + del smallint DEFAULT 0 NOT NULL,
  71 + standard smallint DEFAULT 0 NOT NULL,
  72 + name varchar(128) NOT NULL,
  73 + organization varchar(128),
  74 + email varchar(128) NOT NULL,
  75 + "reply-to" varchar(128),
  76 + bcc varchar(128),
  77 + signature text,
  78 + html_signature integer DEFAULT 0 NOT NULL
  79 +);
  80 +
  81 +CREATE INDEX identities_user_id_idx ON identities (user_id, del);
  82 +CREATE INDEX identities_email_idx ON identities (email, del);
  83 +
  84 +--
  85 +-- Sequence "collected_addresses_seq"
  86 +-- Name: collected_addresses_seq; Type: SEQUENCE; Schema: public; Owner: postgres
  87 +--
  88 +
  89 +CREATE SEQUENCE collected_addresses_seq
  90 + START WITH 1
  91 + INCREMENT BY 1
  92 + NO MAXVALUE
  93 + NO MINVALUE
  94 + CACHE 1;
  95 +
  96 +--
  97 +-- Table "collected_addresses"
  98 +-- Name: collected_addresses; Type: TABLE; Schema: public; Owner: postgres
  99 +--
  100 +
  101 +CREATE TABLE collected_addresses (
  102 + address_id integer DEFAULT nextval('collected_addresses_seq'::text) PRIMARY KEY,
  103 + user_id integer NOT NULL
  104 + REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
  105 + changed timestamp with time zone DEFAULT now() NOT NULL,
  106 + name varchar(255) DEFAULT '' NOT NULL,
  107 + email varchar(255) NOT NULL,
  108 + "type" integer NOT NULL
  109 +);
  110 +
  111 +CREATE UNIQUE INDEX collected_addresses_user_id_idx ON collected_addresses (user_id, "type", email);
  112 +
  113 +
  114 +--
  115 +-- Sequence "contacts_seq"
  116 +-- Name: contacts_seq; Type: SEQUENCE; Schema: public; Owner: postgres
  117 +--
  118 +
  119 +CREATE SEQUENCE contacts_seq
  120 + START WITH 1
  121 + INCREMENT BY 1
  122 + NO MAXVALUE
  123 + NO MINVALUE
  124 + CACHE 1;
  125 +
  126 +--
  127 +-- Table "contacts"
  128 +-- Name: contacts; Type: TABLE; Schema: public; Owner: postgres
  129 +--
  130 +
  131 +CREATE TABLE contacts (
  132 + contact_id integer DEFAULT nextval('contacts_seq'::text) PRIMARY KEY,
  133 + user_id integer NOT NULL
  134 + REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
  135 + changed timestamp with time zone DEFAULT now() NOT NULL,
  136 + del smallint DEFAULT 0 NOT NULL,
  137 + name varchar(128) DEFAULT '' NOT NULL,
  138 + email text DEFAULT '' NOT NULL,
  139 + firstname varchar(128) DEFAULT '' NOT NULL,
  140 + surname varchar(128) DEFAULT '' NOT NULL,
  141 + vcard text,
  142 + words text
  143 +);
  144 +
  145 +CREATE INDEX contacts_user_id_idx ON contacts (user_id, del);
  146 +
  147 +--
  148 +-- Sequence "contactgroups_seq"
  149 +-- Name: contactgroups_seq; Type: SEQUENCE; Schema: public; Owner: postgres
  150 +--
  151 +
  152 +CREATE SEQUENCE contactgroups_seq
  153 + INCREMENT BY 1
  154 + NO MAXVALUE
  155 + NO MINVALUE
  156 + CACHE 1;
  157 +
  158 +--
  159 +-- Table "contactgroups"
  160 +-- Name: contactgroups; Type: TABLE; Schema: public; Owner: postgres
  161 +--
  162 +
  163 +CREATE TABLE contactgroups (
  164 + contactgroup_id integer DEFAULT nextval('contactgroups_seq'::text) PRIMARY KEY,
  165 + user_id integer NOT NULL
  166 + REFERENCES users(user_id) ON DELETE CASCADE ON UPDATE CASCADE,
  167 + changed timestamp with time zone DEFAULT now() NOT NULL,
  168 + del smallint NOT NULL DEFAULT 0,
  169 + name varchar(128) NOT NULL DEFAULT ''
  170 +);
  171 +
  172 +CREATE INDEX contactgroups_user_id_idx ON contactgroups (user_id, del);
  173 +
  174 +--
  175 +-- Table "contactgroupmembers"
  176 +-- Name: contactgroupmembers; Type: TABLE; Schema: public; Owner: postgres
  177 +--
  178 +
  179 +CREATE TABLE contactgroupmembers (
  180 + contactgroup_id integer NOT NULL
  181 + REFERENCES contactgroups(contactgroup_id) ON DELETE CASCADE ON UPDATE CASCADE,
  182 + contact_id integer NOT NULL
  183 + REFERENCES contacts(contact_id) ON DELETE CASCADE ON UPDATE CASCADE,
  184 + created timestamp with time zone DEFAULT now() NOT NULL,
  185 + PRIMARY KEY (contactgroup_id, contact_id)
  186 +);
  187 +
  188 +CREATE INDEX contactgroupmembers_contact_id_idx ON contactgroupmembers (contact_id);
  189 +
  190 +--
  191 +-- Table "cache"
  192 +-- Name: cache; Type: TABLE; Schema: public; Owner: postgres
  193 +--
  194 +
  195 +CREATE TABLE "cache" (
  196 + user_id integer NOT NULL
  197 + REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
  198 + cache_key varchar(128) DEFAULT '' NOT NULL,
  199 + expires timestamp with time zone DEFAULT NULL,
  200 + data text NOT NULL,
  201 + PRIMARY KEY (user_id, cache_key)
  202 +);
  203 +
  204 +CREATE INDEX cache_expires_idx ON "cache" (expires);
  205 +
  206 +--
  207 +-- Table "cache_shared"
  208 +-- Name: cache_shared; Type: TABLE; Schema: public; Owner: postgres
  209 +--
  210 +
  211 +CREATE TABLE "cache_shared" (
  212 + cache_key varchar(255) NOT NULL PRIMARY KEY,
  213 + expires timestamp with time zone DEFAULT NULL,
  214 + data text NOT NULL
  215 +);
  216 +
  217 +CREATE INDEX cache_shared_expires_idx ON "cache_shared" (expires);
  218 +
  219 +--
  220 +-- Table "cache_index"
  221 +-- Name: cache_index; Type: TABLE; Schema: public; Owner: postgres
  222 +--
  223 +
  224 +CREATE TABLE cache_index (
  225 + user_id integer NOT NULL
  226 + REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
  227 + mailbox varchar(255) NOT NULL,
  228 + expires timestamp with time zone DEFAULT NULL,
  229 + valid smallint NOT NULL DEFAULT 0,
  230 + data text NOT NULL,
  231 + PRIMARY KEY (user_id, mailbox)
  232 +);
  233 +
  234 +CREATE INDEX cache_index_expires_idx ON cache_index (expires);
  235 +
  236 +--
  237 +-- Table "cache_thread"
  238 +-- Name: cache_thread; Type: TABLE; Schema: public; Owner: postgres
  239 +--
  240 +
  241 +CREATE TABLE cache_thread (
  242 + user_id integer NOT NULL
  243 + REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
  244 + mailbox varchar(255) NOT NULL,
  245 + expires timestamp with time zone DEFAULT NULL,
  246 + data text NOT NULL,
  247 + PRIMARY KEY (user_id, mailbox)
  248 +);
  249 +
  250 +CREATE INDEX cache_thread_expires_idx ON cache_thread (expires);
  251 +
  252 +--
  253 +-- Table "cache_messages"
  254 +-- Name: cache_messages; Type: TABLE; Schema: public; Owner: postgres
  255 +--
  256 +
  257 +CREATE TABLE cache_messages (
  258 + user_id integer NOT NULL
  259 + REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
  260 + mailbox varchar(255) NOT NULL,
  261 + uid integer NOT NULL,
  262 + expires timestamp with time zone DEFAULT NULL,
  263 + data text NOT NULL,
  264 + flags integer NOT NULL DEFAULT 0,
  265 + PRIMARY KEY (user_id, mailbox, uid)
  266 +);
  267 +
  268 +CREATE INDEX cache_messages_expires_idx ON cache_messages (expires);
  269 +
  270 +--
  271 +-- Table "dictionary"
  272 +-- Name: dictionary; Type: TABLE; Schema: public; Owner: postgres
  273 +--
  274 +
  275 +CREATE TABLE dictionary (
  276 + user_id integer DEFAULT NULL
  277 + REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
  278 + "language" varchar(16) NOT NULL,
  279 + data text NOT NULL,
  280 + CONSTRAINT dictionary_user_id_language_key UNIQUE (user_id, "language")
  281 +);
  282 +
  283 +--
  284 +-- Sequence "searches_seq"
  285 +-- Name: searches_seq; Type: SEQUENCE; Schema: public; Owner: postgres
  286 +--
  287 +
  288 +CREATE SEQUENCE searches_seq
  289 + INCREMENT BY 1
  290 + NO MAXVALUE
  291 + NO MINVALUE
  292 + CACHE 1;
  293 +
  294 +--
  295 +-- Table "searches"
  296 +-- Name: searches; Type: TABLE; Schema: public; Owner: postgres
  297 +--
  298 +
  299 +CREATE TABLE searches (
  300 + search_id integer DEFAULT nextval('searches_seq'::text) PRIMARY KEY,
  301 + user_id integer NOT NULL
  302 + REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
  303 + "type" smallint DEFAULT 0 NOT NULL,
  304 + name varchar(128) NOT NULL,
  305 + data text NOT NULL,
  306 + CONSTRAINT searches_user_id_key UNIQUE (user_id, "type", name)
  307 +);
  308 +
  309 +--
  310 +-- Sequence "filestore_seq"
  311 +-- Name: filestore_seq; Type: SEQUENCE; Schema: public; Owner: postgres
  312 +--
  313 +
  314 +CREATE SEQUENCE "filestore_seq"
  315 + INCREMENT BY 1
  316 + NO MAXVALUE
  317 + NO MINVALUE
  318 + CACHE 1;
  319 +
  320 +--
  321 +-- Table "filestore"
  322 +-- Name: filestore; Type: TABLE; Schema: public; Owner: postgres
  323 +--
  324 +
  325 +CREATE TABLE "filestore" (
  326 + file_id integer DEFAULT nextval('filestore_seq'::text) PRIMARY KEY,
  327 + user_id integer NOT NULL
  328 + REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
  329 + context varchar(32) NOT NULL,
  330 + filename varchar(128) NOT NULL,
  331 + mtime integer NOT NULL,
  332 + data text NOT NULL,
  333 + CONSTRAINT filestore_user_id_filename UNIQUE (user_id, context, filename)
  334 +);
  335 +
  336 +--
  337 +-- Table "system"
  338 +-- Name: system; Type: TABLE; Schema: public; Owner: postgres
  339 +--
  340 +
  341 +CREATE TABLE "system" (
  342 + name varchar(64) NOT NULL PRIMARY KEY,
  343 + value text
  344 +);
  345 +
  346 +INSERT INTO "system" (name, value) VALUES ('roundcube-version', '2020122900');
  1 +-- Updates from version 0.1-stable to 0.1.1
  2 +
  3 +CREATE INDEX cache_user_id_idx ON cache (user_id, cache_key);
  4 +CREATE INDEX contacts_user_id_idx ON contacts (user_id);
  5 +CREATE INDEX identities_user_id_idx ON identities (user_id);
  6 +
  7 +CREATE INDEX users_username_id_idx ON users (username);
  8 +CREATE INDEX users_alias_id_idx ON users (alias);
  9 +
  10 +-- added ON DELETE/UPDATE actions
  11 +ALTER TABLE messages DROP CONSTRAINT messages_user_id_fkey;
  12 +ALTER TABLE messages ADD FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE ON UPDATE CASCADE;
  13 +ALTER TABLE identities DROP CONSTRAINT identities_user_id_fkey;
  14 +ALTER TABLE identities ADD FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE ON UPDATE CASCADE;
  15 +ALTER TABLE contacts DROP CONSTRAINT contacts_user_id_fkey;
  16 +ALTER TABLE contacts ADD FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE ON UPDATE CASCADE;
  17 +ALTER TABLE cache DROP CONSTRAINT cache_user_id_fkey;
  18 +ALTER TABLE cache ADD FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE ON UPDATE CASCADE;
  1 +-- Updates from version 0.2-alpha
  2 +
  3 +CREATE INDEX messages_created_idx ON messages (created);
  1 +-- Updates from version 0.2-beta
  2 +
  3 +ALTER TABLE cache DROP session_id;
  4 +
  5 +CREATE INDEX session_changed_idx ON session (changed);
  6 +CREATE INDEX cache_created_idx ON "cache" (created);
  7 +
  8 +ALTER TABLE users ALTER "language" DROP NOT NULL;
  9 +ALTER TABLE users ALTER "language" DROP DEFAULT;
  10 +
  11 +ALTER TABLE identities ALTER del TYPE smallint;
  12 +ALTER TABLE identities ALTER standard TYPE smallint;
  13 +ALTER TABLE contacts ALTER del TYPE smallint;
  14 +ALTER TABLE messages ALTER del TYPE smallint;
  1 +-- Updates from version 0.3-stable
  2 +
  3 +TRUNCATE messages;
  4 +CREATE INDEX messages_index_idx ON messages (user_id, cache_key, idx);
  5 +DROP INDEX contacts_user_id_idx;
  6 +CREATE INDEX contacts_user_id_idx ON contacts (user_id, email);
  1 +-- Updates from version 0.3.1
  2 +
  3 +DROP INDEX identities_user_id_idx;
  4 +CREATE INDEX identities_user_id_idx ON identities (user_id, del);
  5 +
  6 +ALTER TABLE identities ADD changed timestamp with time zone DEFAULT now() NOT NULL;
  7 +
  8 +CREATE SEQUENCE contactgroups_ids
  9 + INCREMENT BY 1
  10 + NO MAXVALUE
  11 + NO MINVALUE
  12 + CACHE 1;
  13 +
  14 +CREATE TABLE contactgroups (
  15 + contactgroup_id integer DEFAULT nextval('contactgroups_ids'::text) PRIMARY KEY,
  16 + user_id integer NOT NULL
  17 + REFERENCES users(user_id) ON DELETE CASCADE ON UPDATE CASCADE,
  18 + changed timestamp with time zone DEFAULT now() NOT NULL,
  19 + del smallint NOT NULL DEFAULT 0,
  20 + name varchar(128) NOT NULL DEFAULT ''
  21 +);
  22 +
  23 +CREATE INDEX contactgroups_user_id_idx ON contactgroups (user_id, del);
  24 +
  25 +CREATE TABLE contactgroupmembers (
  26 + contactgroup_id integer NOT NULL
  27 + REFERENCES contactgroups(contactgroup_id) ON DELETE CASCADE ON UPDATE CASCADE,
  28 + contact_id integer NOT NULL
  29 + REFERENCES contacts(contact_id) ON DELETE CASCADE ON UPDATE CASCADE,
  30 + created timestamp with time zone DEFAULT now() NOT NULL,
  31 + PRIMARY KEY (contactgroup_id, contact_id)
  32 +);
  1 +-- Updates from version 0.4-beta
  2 +
  3 +ALTER TABLE users ALTER last_login DROP NOT NULL;
  4 +ALTER TABLE users ALTER last_login SET DEFAULT NULL;
  1 +-- Updates from version 0.4.2
  2 +
  3 +DROP INDEX users_username_id_idx;
  4 +ALTER TABLE users ADD CONSTRAINT users_username_key UNIQUE (username, mail_host);
  5 +ALTER TABLE contacts ALTER email TYPE varchar(255);
  6 +
  7 +TRUNCATE messages;
  1 +-- Updates from version 0.5.x
  2 +
  3 +ALTER TABLE contacts ADD words TEXT NULL;
  4 +CREATE INDEX contactgroupmembers_contact_id_idx ON contactgroupmembers (contact_id);
  5 +
  6 +TRUNCATE messages;
  7 +TRUNCATE cache;
  1 +-- Updates from version 0.6
  2 +
  3 +CREATE TABLE dictionary (
  4 + user_id integer DEFAULT NULL
  5 + REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
  6 + "language" varchar(5) NOT NULL,
  7 + data text NOT NULL,
  8 + CONSTRAINT dictionary_user_id_language_key UNIQUE (user_id, "language")
  9 +);
  10 +
  11 +CREATE SEQUENCE search_ids
  12 + INCREMENT BY 1
  13 + NO MAXVALUE
  14 + NO MINVALUE
  15 + CACHE 1;
  16 +
  17 +CREATE TABLE searches (
  18 + search_id integer DEFAULT nextval('search_ids'::text) PRIMARY KEY,
  19 + user_id integer NOT NULL
  20 + REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
  21 + "type" smallint DEFAULT 0 NOT NULL,
  22 + name varchar(128) NOT NULL,
  23 + data text NOT NULL,
  24 + CONSTRAINT searches_user_id_key UNIQUE (user_id, "type", name)
  25 +);
  26 +
  27 +DROP SEQUENCE message_ids;
  28 +DROP TABLE messages;
  29 +
  30 +CREATE TABLE cache_index (
  31 + user_id integer NOT NULL
  32 + REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
  33 + mailbox varchar(255) NOT NULL,
  34 + changed timestamp with time zone DEFAULT now() NOT NULL,
  35 + valid smallint NOT NULL DEFAULT 0,
  36 + data text NOT NULL,
  37 + PRIMARY KEY (user_id, mailbox)
  38 +);
  39 +
  40 +CREATE INDEX cache_index_changed_idx ON cache_index (changed);
  41 +
  42 +CREATE TABLE cache_thread (
  43 + user_id integer NOT NULL
  44 + REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
  45 + mailbox varchar(255) NOT NULL,
  46 + changed timestamp with time zone DEFAULT now() NOT NULL,
  47 + data text NOT NULL,
  48 + PRIMARY KEY (user_id, mailbox)
  49 +);
  50 +
  51 +CREATE INDEX cache_thread_changed_idx ON cache_thread (changed);
  52 +
  53 +CREATE TABLE cache_messages (
  54 + user_id integer NOT NULL
  55 + REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
  56 + mailbox varchar(255) NOT NULL,
  57 + uid integer NOT NULL,
  58 + changed timestamp with time zone DEFAULT now() NOT NULL,
  59 + data text NOT NULL,
  60 + flags integer NOT NULL DEFAULT 0,
  61 + PRIMARY KEY (user_id, mailbox, uid)
  62 +);
  63 +
  64 +CREATE INDEX cache_messages_changed_idx ON cache_messages (changed);
  1 +-- Updates from version 0.7-beta
  2 +
  3 +ALTER TABLE "session" ALTER sess_id TYPE varchar(128);
  1 +-- Updates from version 0.7
  2 +
  3 +DROP INDEX contacts_user_id_idx;
  4 +CREATE INDEX contacts_user_id_idx ON contacts USING btree (user_id, del);
  5 +ALTER TABLE contacts ALTER email TYPE text;
  1 +-- Updates from version 0.8
  2 +
  3 +ALTER TABLE cache DROP COLUMN cache_id;
  4 +DROP SEQUENCE cache_ids;
  5 +
  6 +ALTER TABLE users DROP COLUMN alias;
  7 +CREATE INDEX identities_email_idx ON identities (email, del);
  1 +CREATE TABLE "system" (
  2 + name varchar(64) NOT NULL PRIMARY KEY,
  3 + value text
  4 +);
  1 +ALTER SEQUENCE user_ids RENAME TO users_seq;
  2 +ALTER TABLE users ALTER COLUMN user_id SET DEFAULT nextval('users_seq'::text);
  3 +
  4 +ALTER SEQUENCE identity_ids RENAME TO identities_seq;
  5 +ALTER TABLE identities ALTER COLUMN identity_id SET DEFAULT nextval('identities_seq'::text);
  6 +
  7 +ALTER SEQUENCE contact_ids RENAME TO contacts_seq;
  8 +ALTER TABLE contacts ALTER COLUMN contact_id SET DEFAULT nextval('contacts_seq'::text);
  9 +
  10 +ALTER SEQUENCE contactgroups_ids RENAME TO contactgroups_seq;
  11 +ALTER TABLE contactgroups ALTER COLUMN contactgroup_id SET DEFAULT nextval('contactgroups_seq'::text);
  12 +
  13 +ALTER SEQUENCE search_ids RENAME TO searches_seq;
  14 +ALTER TABLE searches ALTER COLUMN search_id SET DEFAULT nextval('searches_seq'::text);
  1 +CREATE TABLE "cache_shared" (
  2 + cache_key varchar(255) NOT NULL,
  3 + created timestamp with time zone DEFAULT now() NOT NULL,
  4 + data text NOT NULL
  5 +);
  6 +
  7 +CREATE INDEX cache_shared_cache_key_idx ON "cache_shared" (cache_key);
  8 +CREATE INDEX cache_shared_created_idx ON "cache_shared" (created);
  1 +ALTER TABLE "cache" ADD expires timestamp with time zone DEFAULT NULL;
  2 +ALTER TABLE "cache_shared" ADD expires timestamp with time zone DEFAULT NULL;
  3 +ALTER TABLE "cache_index" ADD expires timestamp with time zone DEFAULT NULL;
  4 +ALTER TABLE "cache_thread" ADD expires timestamp with time zone DEFAULT NULL;
  5 +ALTER TABLE "cache_messages" ADD expires timestamp with time zone DEFAULT NULL;
  6 +
  7 +-- initialize expires column with created/changed date + 7days
  8 +UPDATE "cache" SET expires = created + interval '604800 seconds';
  9 +UPDATE "cache_shared" SET expires = created + interval '604800 seconds';
  10 +UPDATE "cache_index" SET expires = changed + interval '604800 seconds';
  11 +UPDATE "cache_thread" SET expires = changed + interval '604800 seconds';
  12 +UPDATE "cache_messages" SET expires = changed + interval '604800 seconds';
  13 +
  14 +DROP INDEX cache_created_idx;
  15 +DROP INDEX cache_shared_created_idx;
  16 +ALTER TABLE "cache_index" DROP "changed";
  17 +ALTER TABLE "cache_thread" DROP "changed";
  18 +ALTER TABLE "cache_messages" DROP "changed";
  19 +
  20 +CREATE INDEX cache_expires_idx ON "cache" (expires);
  21 +CREATE INDEX cache_shared_expires_idx ON "cache_shared" (expires);
  22 +CREATE INDEX cache_index_expires_idx ON "cache_index" (expires);
  23 +CREATE INDEX cache_thread_expires_idx ON "cache_thread" (expires);
  24 +CREATE INDEX cache_messages_expires_idx ON "cache_messages" (expires);
  1 +ALTER TABLE "users" ADD failed_login timestamp with time zone DEFAULT NULL;
  2 +ALTER TABLE "users" ADD failed_login_counter integer DEFAULT NULL;
  1 +ALTER TABLE "session" DROP COLUMN created;
  1 +ALTER TABLE session ALTER COLUMN ip TYPE character varying(41);