- Applied fixes from trunk up to r5711

release-0.7
alecpl 13 years ago
parent 896b2204e8
commit a33118fd0f

@ -1,6 +1,9 @@
CHANGELOG Roundcube Webmail
===========================
- Fix SQL Error when saving a contact with many email addresses (#1488286)
- Fix strict email address searching if contact has more than one address
- Remove duplicated 'organization' label (#1488287)
- Fix so editor selector is hidden when 'htmleditor' is listed in 'dont_override'
- Fix wrong (long) label usage (#1488283)
- Fix handling of INBOX's subfolders in special folders config (#1488279)

@ -40,7 +40,7 @@ CREATE TABLE [dbo].[contacts] (
[changed] [datetime] NOT NULL ,
[del] [char] (1) COLLATE Latin1_General_CI_AI NOT NULL ,
[name] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
[email] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL ,
[email] [text] COLLATE Latin1_General_CI_AI NOT NULL ,
[firstname] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
[surname] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL ,
[vcard] [text] COLLATE Latin1_General_CI_AI NULL ,

@ -244,3 +244,8 @@ GO
ALTER TABLE [dbo].[session] ALTER COLUMN [sess_id] [varchar] (128) COLLATE Latin1_General_CI_AI NOT NULL
GO
-- Updates from version 0.7
ALTER TABLE [dbo].[contacts] ALTER COLUMN [email] [text] COLLATE Latin1_General_CI_AI NOT NULL
GO

@ -40,7 +40,7 @@ CREATE TABLE `cache` (
`cache_key` varchar(128) /*!40101 CHARACTER SET ascii COLLATE ascii_general_ci */ NOT NULL ,
`created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`data` longtext NOT NULL,
`user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
`user_id` int(10) UNSIGNED NOT NULL,
PRIMARY KEY(`cache_id`),
CONSTRAINT `user_id_fk_cache` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
@ -52,7 +52,7 @@ CREATE TABLE `cache` (
-- Table structure for table `cache_index`
CREATE TABLE `cache_index` (
`user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
`user_id` int(10) UNSIGNED NOT NULL,
`mailbox` varchar(255) BINARY NOT NULL,
`changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`valid` tinyint(1) NOT NULL DEFAULT '0',
@ -67,7 +67,7 @@ CREATE TABLE `cache_index` (
-- Table structure for table `cache_thread`
CREATE TABLE `cache_thread` (
`user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
`user_id` int(10) UNSIGNED NOT NULL,
`mailbox` varchar(255) BINARY NOT NULL,
`changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`data` longtext NOT NULL,
@ -81,7 +81,7 @@ CREATE TABLE `cache_thread` (
-- Table structure for table `cache_messages`
CREATE TABLE `cache_messages` (
`user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
`user_id` int(10) UNSIGNED NOT NULL,
`mailbox` varchar(255) BINARY NOT NULL,
`uid` int(11) UNSIGNED NOT NULL DEFAULT '0',
`changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
@ -101,23 +101,23 @@ CREATE TABLE `contacts` (
`changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`del` tinyint(1) NOT NULL DEFAULT '0',
`name` varchar(128) NOT NULL DEFAULT '',
`email` varchar(255) NOT NULL,
`email` text NOT NULL DEFAULT '',
`firstname` varchar(128) NOT NULL DEFAULT '',
`surname` varchar(128) NOT NULL DEFAULT '',
`vcard` longtext NULL,
`words` text NULL,
`user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
`user_id` int(10) UNSIGNED NOT NULL,
PRIMARY KEY(`contact_id`),
CONSTRAINT `user_id_fk_contacts` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
INDEX `user_contacts_index` (`user_id`,`email`)
INDEX `user_contacts_index` (`user_id`,`del`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
-- Table structure for table `contactgroups`
CREATE TABLE `contactgroups` (
`contactgroup_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
`user_id` int(10) UNSIGNED NOT NULL,
`changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`del` tinyint(1) NOT NULL DEFAULT '0',
`name` varchar(128) NOT NULL DEFAULT '',
@ -129,7 +129,7 @@ CREATE TABLE `contactgroups` (
CREATE TABLE `contactgroupmembers` (
`contactgroup_id` int(10) UNSIGNED NOT NULL,
`contact_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
`contact_id` int(10) UNSIGNED NOT NULL,
`created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
PRIMARY KEY (`contactgroup_id`, `contact_id`),
CONSTRAINT `contactgroup_id_fk_contactgroups` FOREIGN KEY (`contactgroup_id`)
@ -144,7 +144,7 @@ CREATE TABLE `contactgroupmembers` (
CREATE TABLE `identities` (
`identity_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
`user_id` int(10) UNSIGNED NOT NULL,
`changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`del` tinyint(1) NOT NULL DEFAULT '0',
`standard` tinyint(1) NOT NULL DEFAULT '0',
@ -178,7 +178,7 @@ CREATE TABLE `dictionary` (
CREATE TABLE `searches` (
`search_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
`user_id` int(10) UNSIGNED NOT NULL,
`type` int(3) NOT NULL DEFAULT '0',
`name` varchar(128) NOT NULL,
`data` text,

@ -212,3 +212,22 @@ CREATE TABLE `cache_messages` (
-- Updates from version 0.7-beta
ALTER TABLE `session` CHANGE `sess_id` `sess_id` varchar(128) NOT NULL;
-- Updates from version 0.7
ALTER TABLE `contacts` DROP FOREIGN KEY `user_id_fk_contacts`;
ALTER TABLE `contacts` DROP INDEX `user_contacts_index`;
ALTER TABLE `contacts` MODIFY `email` text NOT NULL DEFAULT '';
ALTER TABLE `contacts` ADD INDEX `user_contacts_index` (`user_id`,`del`);
ALTER TABLE `contacts` ADD CONSTRAINT `user_id_fk_contacts` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE `cache` ALTER `user_id` DROP DEFAULT;
ALTER TABLE `cache_index` ALTER `user_id` DROP DEFAULT;
ALTER TABLE `cache_thread` ALTER `user_id` DROP DEFAULT;
ALTER TABLE `cache_messages` ALTER `user_id` DROP DEFAULT;
ALTER TABLE `contacts` ALTER `user_id` DROP DEFAULT;
ALTER TABLE `contactgroups` ALTER `user_id` DROP DEFAULT;
ALTER TABLE `contactgroupmembers` ALTER `contact_id` DROP DEFAULT;
ALTER TABLE `identities` ALTER `user_id` DROP DEFAULT;
ALTER TABLE `searches` ALTER `user_id` DROP DEFAULT;

@ -107,14 +107,14 @@ CREATE TABLE contacts (
changed timestamp with time zone DEFAULT now() NOT NULL,
del smallint DEFAULT 0 NOT NULL,
name varchar(128) DEFAULT '' NOT NULL,
email varchar(255) DEFAULT '' NOT NULL,
email text DEFAULT '' NOT NULL,
firstname varchar(128) DEFAULT '' NOT NULL,
surname varchar(128) DEFAULT '' NOT NULL,
vcard text,
words text
);
CREATE INDEX contacts_user_id_idx ON contacts (user_id, email);
CREATE INDEX contacts_user_id_idx ON contacts (user_id, del);
--
-- Sequence "contactgroups_ids"

@ -169,3 +169,9 @@ CREATE INDEX cache_messages_changed_idx ON cache_messages (changed);
-- Updates from version 0.7-beta
ALTER TABLE "session" ALTER sess_id TYPE varchar(128);
-- Updates from version 0.7
DROP INDEX contacts_user_id_idx;
CREATE INDEX contacts_user_id_idx ON contacts USING btree (user_id, del);
ALTER TABLE contacts ALTER email TYPE text;

@ -24,18 +24,18 @@ CREATE INDEX ix_cache_created ON cache(created);
CREATE TABLE contacts (
contact_id integer NOT NULL PRIMARY KEY,
user_id integer NOT NULL default '0',
user_id integer NOT NULL,
changed datetime NOT NULL default '0000-00-00 00:00:00',
del tinyint NOT NULL default '0',
name varchar(128) NOT NULL default '',
email varchar(255) NOT NULL default '',
email text NOT NULL default '',
firstname varchar(128) NOT NULL default '',
surname varchar(128) NOT NULL default '',
vcard text NOT NULL default '',
words text NOT NULL default ''
);
CREATE INDEX ix_contacts_user_id ON contacts(user_id, email);
CREATE INDEX ix_contacts_user_id ON contacts(user_id, del);
CREATE TABLE contactgroups (

@ -293,5 +293,43 @@ CREATE TABLE session (
ip varchar(40) NOT NULL default '',
vars text NOT NULL
);
CREATE INDEX ix_session_changed ON session (changed);
-- Updates from version 0.7
CREATE TABLE contacts_tmp (
contact_id integer NOT NULL PRIMARY KEY,
user_id integer NOT NULL,
changed datetime NOT NULL default '0000-00-00 00:00:00',
del tinyint NOT NULL default '0',
name varchar(128) NOT NULL default '',
email text NOT NULL default '',
firstname varchar(128) NOT NULL default '',
surname varchar(128) NOT NULL default '',
vcard text NOT NULL default '',
words text NOT NULL default ''
);
INSERT INTO contacts_tmp (contact_id, user_id, changed, del, name, email, firstname, surname, vcard, words)
SELECT contact_id, user_id, changed, del, name, email, firstname, surname, vcard, words FROM contacts;
DROP TABLE contacts;
CREATE TABLE contacts (
contact_id integer NOT NULL PRIMARY KEY,
user_id integer NOT NULL,
changed datetime NOT NULL default '0000-00-00 00:00:00',
del tinyint NOT NULL default '0',
name varchar(128) NOT NULL default '',
email text NOT NULL default '',
firstname varchar(128) NOT NULL default '',
surname varchar(128) NOT NULL default '',
vcard text NOT NULL default '',
words text NOT NULL default ''
);
INSERT INTO contacts (contact_id, user_id, changed, del, name, email, firstname, surname, vcard, words)
SELECT contact_id, user_id, changed, del, name, email, firstname, surname, vcard, words FROM contacts_tmp;
CREATE INDEX ix_contacts_user_id ON contacts(user_id, del);
DROP TABLE contacts_tmp;

@ -1,5 +1,6 @@
- Fixed setting test type to :is when none is specified
- Fixed javascript error in IE8
- Fix possible ID duplication when adding filter rules very fast (#1488288)
* version 5.0-rc1 [2011-11-17]
-----------------------------------------------------------

@ -1542,7 +1542,7 @@ class managesieve extends rcube_plugin
private function genid()
{
$result = intval(rcube_timer());
$result = preg_replace('/[^0-9]/', '', microtime(true));
return $result;
}

@ -62,6 +62,8 @@ class rcube_contacts extends rcube_addressbook
'gender', 'maidenname', 'spouse', 'email', 'phone', 'address',
'birthday', 'anniversary', 'website', 'im', 'notes', 'photo');
const SEPARATOR = ',';
/**
* Object constructor
@ -232,8 +234,10 @@ class rcube_contacts extends rcube_addressbook
if ($read_vcard)
$sql_arr = $this->convert_db_data($sql_arr);
else
$sql_arr['email'] = preg_split('/,\s*/', $sql_arr['email']);
else {
$sql_arr['email'] = explode(self::SEPARATOR, $sql_arr['email']);
$sql_arr['email'] = array_map('trim', $sql_arr['email']);
}
// make sure we have a name to display
if (empty($sql_arr['name'])) {
@ -287,11 +291,13 @@ class rcube_contacts extends rcube_addressbook
$where = $and_where = array();
$mode = intval($mode);
$WS = ' ';
$AS = self::SEPARATOR;
foreach ($fields as $idx => $col) {
// direct ID search
if ($col == 'ID' || $col == $this->primary_key) {
$ids = !is_array($value) ? explode(',', $value) : $value;
$ids = !is_array($value) ? explode(self::SEPARATOR, $value) : $value;
$ids = $this->db->array2list($ids, 'integer');
$where[] = 'c.' . $this->primary_key.' IN ('.$ids.')';
continue;
@ -299,19 +305,19 @@ class rcube_contacts extends rcube_addressbook
// fulltext search in all fields
else if ($col == '*') {
$words = array();
foreach (explode(" ", self::normalize_string($value)) as $word) {
foreach (explode($WS, self::normalize_string($value)) as $word) {
switch ($mode) {
case 1: // strict
$words[] = '(' . $this->db->ilike('words', $word.' %')
. ' OR ' . $this->db->ilike('words', '% '.$word.' %')
. ' OR ' . $this->db->ilike('words', '% '.$word) . ')';
$words[] = '(' . $this->db->ilike('words', $word . '%')
. ' OR ' . $this->db->ilike('words', '%' . $WS . $word . $WS . '%')
. ' OR ' . $this->db->ilike('words', '%' . $WS . $word) . ')';
break;
case 2: // prefix
$words[] = '(' . $this->db->ilike('words', $word.'%')
. ' OR ' . $this->db->ilike('words', '% '.$word.'%') . ')';
$words[] = '(' . $this->db->ilike('words', $word . '%')
. ' OR ' . $this->db->ilike('words', '%' . $WS . $word . '%') . ')';
break;
default: // partial
$words[] = $this->db->ilike('words', '%'.$word.'%');
$words[] = $this->db->ilike('words', '%' . $word . '%');
}
}
$where[] = '(' . join(' AND ', $words) . ')';
@ -322,13 +328,17 @@ class rcube_contacts extends rcube_addressbook
if (in_array($col, $this->table_cols)) {
switch ($mode) {
case 1: // strict
$where[] = $this->db->quoteIdentifier($col).' = '.$this->db->quote($val);
$where[] = '(' . $this->db->quoteIdentifier($col) . ' = ' . $this->db->quote($val)
. ' OR ' . $this->db->ilike($col, $val . $AS . '%')
. ' OR ' . $this->db->ilike($col, '%' . $AS . $val . $AS . '%')
. ' OR ' . $this->db->ilike($col, '%' . $AS . $val) . ')';
break;
case 2: // prefix
$where[] = $this->db->ilike($col, $val.'%');
$where[] = '(' . $this->db->ilike($col, $val . '%')
. ' OR ' . $this->db->ilike($col, $AS . $val . '%') . ')';
break;
default: // partial
$where[] = $this->db->ilike($col, '%'.$val.'%');
$where[] = $this->db->ilike($col, '%' . $val . '%');
}
}
// vCard field
@ -337,16 +347,16 @@ class rcube_contacts extends rcube_addressbook
foreach (explode(" ", self::normalize_string($val)) as $word) {
switch ($mode) {
case 1: // strict
$words[] = '(' . $this->db->ilike('words', $word.' %')
. ' OR ' . $this->db->ilike('words', '% '.$word.' %')
. ' OR ' . $this->db->ilike('words', '% '.$word) . ')';
$words[] = '(' . $this->db->ilike('words', $word . $WS . '%')
. ' OR ' . $this->db->ilike('words', '%' . $AS . $word . $WS .'%')
. ' OR ' . $this->db->ilike('words', '%' . $AS . $word) . ')';
break;
case 2: // prefix
$words[] = '(' . $this->db->ilike('words', $word.'%')
. ' OR ' . $this->db->ilike('words', ' '.$word.'%') . ')';
$words[] = '(' . $this->db->ilike('words', $word . '%')
. ' OR ' . $this->db->ilike('words', $AS . $word . '%') . ')';
break;
default: // partial
$words[] = $this->db->ilike('words', '%'.$word.'%');
$words[] = $this->db->ilike('words', '%' . $word . '%');
}
}
$where[] = '(' . join(' AND ', $words) . ')';
@ -687,7 +697,8 @@ class rcube_contacts extends rcube_addressbook
}
else {
$record += $sql_arr;
$record['email'] = preg_split('/,\s*/', $record['email']);
$record['email'] = explode(self::SEPARATOR, $record['email']);
$record['email'] = array_map('trim', $record['email']);
}
return $record;
@ -720,12 +731,16 @@ class rcube_contacts extends rcube_addressbook
$key = $col;
if (!isset($save_data[$key]))
$key .= ':home';
if (isset($save_data[$key]))
$out[$col] = is_array($save_data[$key]) ? join(',', $save_data[$key]) : $save_data[$key];
if (isset($save_data[$key])) {
if (is_array($save_data[$key]))
$out[$col] = join(self::SEPARATOR, $save_data[$key]);
else
$out[$col] = $save_data[$key];
}
}
// save all e-mails in database column
$out['email'] = join(", ", $vcard->email);
$out['email'] = join(self::SEPARATOR, $vcard->email);
// join words for fulltext search
$out['words'] = join(" ", array_unique(explode(" ", $words)));
@ -743,7 +758,7 @@ class rcube_contacts extends rcube_addressbook
function delete($ids, $force=true)
{
if (!is_array($ids))
$ids = explode(',', $ids);
$ids = explode(self::SEPARATOR, $ids);
$ids = $this->db->array2list($ids, 'integer');
@ -770,7 +785,7 @@ class rcube_contacts extends rcube_addressbook
function undelete($ids)
{
if (!is_array($ids))
$ids = explode(',', $ids);
$ids = explode(self::SEPARATOR, $ids);
$ids = $this->db->array2list($ids, 'integer');
@ -887,7 +902,7 @@ class rcube_contacts extends rcube_addressbook
function add_to_group($group_id, $ids)
{
if (!is_array($ids))
$ids = explode(',', $ids);
$ids = explode(self::SEPARATOR, $ids);
$added = 0;
$exists = array();
@ -932,7 +947,7 @@ class rcube_contacts extends rcube_addressbook
function remove_from_group($group_id, $ids)
{
if (!is_array($ids))
$ids = explode(',', $ids);
$ids = explode(self::SEPARATOR, $ids);
$ids = $this->db->array2list($ids, 'integer');

@ -81,8 +81,8 @@ if (empty($a_record['name'])) {
// do input checks (delegated to $CONTACTS instance)
if (!$CONTACTS->validate($a_record)) {
$err = (array)$CONTACTS->get_error() + array('message' => 'formincomplete', 'type' => 'warning');
$OUTPUT->show_message($err['message'], $err['type']);
$err = (array)$CONTACTS->get_error();
$OUTPUT->show_message($err['message'] ? $err['message'] : 'formincomplete', 'warning');
$GLOBALS['EDIT_RECORD'] = $a_record; // store submitted data to be used in edit form
rcmail_overwrite_action($return_action);
return;

Loading…
Cancel
Save