Re-design of caching (new database table added\!); some bugfixes; Postgres support

release-0.6
thomascube 19 years ago
parent 5bc8cb662f
commit 1cded85790

@ -1,6 +1,38 @@
CHANGELOG RoundCube Webmail
---------------------------
2005/12/03
----------
- Added Finnish, Romanian, Polish, Czech, British, Norwegian, Greek, Russian, Estonian and Chinese translation
- Get IMAP server capabilities in array
- Check for NAMESPACE capability before sending command
- Set default user language from config 'locale_string'
- Added sorting patch for message list
- Make default sort col/order configurable
- Fixed XSS in address book and identities
- Added more XSS protection (Bug #1308236)
- Added tab indexes for compose form
- Added 'changed' col to contacts table
- Support for 160-bit session hashes
- Added input check for contacts and identities (Patch #1346523)
- Added messages/warning to compose step (Patch #1323895)
- Added favicon to the default skin
- Fixed Bug #1334337 as far as possible
- Added Reply-To-All functionality (Request #1326395, Patch #1349777)
- Redesign of client side AJAX code (enable multi threading)
- Added keep-alive signal every minute
- Make logs dir configurable
- Added support for SMTPS
- Decode attachment file names
- Make delimiter for message headers configurable
- Add generic footer to sent messages
- Choose the rigt identity when replying
- Remove signature when replying (Request #1333167)
- Signatures for each identity
- Select charset when composing message
- Complete re-design of the caching mechanism
2005/08/11
----------
- Write list header to client even if list is empty
@ -14,16 +46,20 @@ CHANGELOG RoundCube Webmail
- Added German translation
2005/08/20
2005/10/20
----------
- Improved cacheing of mailbox messagecount
- Fixed javascript bug when creating a new message folder
- Fixed javascript bugs #1260990 and #1260992: folder selection
- Make Trash folder configurable
- Auto create folders Inbox, Sent and Trash (if configured)
- Support for IMAP root folder
- Added support fot text/enriched messages
- Make list of special mailboxes configurable
- Added Swedish, Latvian, Portuguese and Catalan translation
- Make SMTP auth method configurable
- Make mailboxlist scrollable (Bug #1326372)
- Fixed SSL support
- Improved support for Courier IMAP (root folder and delimiter issues)
- Moved taskbar from bottom to top
- Added 'session_lifetime' parameter
- Fixed wrong unread count when deleting message (Bug #1332434)
- Srip tags when creating a new folder (Bug #1332084)
- Translate HTML tags in message headers (Bug #1330134)
- Correction in German translation (Bug #1329434)
- Display folder names with special chars correctly (Bug #1330157)
2005/10/07
@ -44,46 +80,14 @@ CHANGELOG RoundCube Webmail
- Enable IMAPS by host
2005/10/20
----------
- Added Swedish, Latvian, Portuguese and Catalan translation
- Make SMTP auth method configurable
- Make mailboxlist scrollable (Bug #1326372)
- Fixed SSL support
- Improved support for Courier IMAP (root folder and delimiter issues)
- Moved taskbar from bottom to top
- Added 'session_lifetime' parameter
- Fixed wrong unread count when deleting message (Bug #1332434)
- Srip tags when creating a new folder (Bug #1332084)
- Translate HTML tags in message headers (Bug #1330134)
- Correction in German translation (Bug #1329434)
- Display folder names with special chars correctly (Bug #1330157)
2005/11/18
2005/08/20
----------
- Added Finnish, Romanian, Polish, Czech, British, Norwegian, Greek, Russian and Chinese translation
- Get IMAP server capabilities in array
- Check for NAMESPACE capability before sending command
- Set default user language from config 'locale_string'
- Added sorting patch for message list
- Make default sort col/order configurable
- Fixed XSS in address book and identities
- Added more XSS protection (Bug #1308236)
- Added tab indexes for compose form
- Added 'changed' col to contacts table
- Support for 160-bit session hashes
- Added input check for contacts and identities (Patch #1346523)
- Added messages/warning to compose step (Patch #1323895)
- Added favicon to the default skin
- Fixed Bug #1334337 as far as possible
- Added Reply-To-All functionality (Request #1326395, Patch #1349777)
- Redesign of client side AJAX code (enable multi threading)
- Added keep-alive signal every minute
- Make logs dir configurable
- Added support for SMTPS
- Decode attachment file names
- Make delimiter for message headers configurable
- Add generic footer to sent messages
- Improved cacheing of mailbox messagecount
- Fixed javascript bug when creating a new message folder
- Fixed javascript bugs #1260990 and #1260992: folder selection
- Make Trash folder configurable
- Auto create folders Inbox, Sent and Trash (if configured)
- Support for IMAP root folder
- Added support fot text/enriched messages
- Make list of special mailboxes configurable

@ -31,6 +31,7 @@ roundcube user. Here is an example of that procedure:
> quit
# mysql roundcubemail < SQL/mysql.initial.sql
* SQLite
--------
Sqlite requires specifically php5 (sqlite in php4 currently doesn't
@ -44,6 +45,25 @@ Make sure your configuration points to the sqlite.db file and that the
webserver can write to the file.
* PostgreSQL
------------
To use RoundCube with PostgreSQL support you have to follow the next
simple steps, which have to be done with the postgres system user (or
which ever is the database superuser):
$ createuser roundcubemail
$ createdb -O roundcubemail roundcubemail
$ psql roundcubemail
roundcubemail =# ALTER USER roundcube WITH PASSWORD 'the_new_password';
roundcubemail =# \c - roundcubemail
roundcubemail => \i SQL/postgres.initial.sql
All this has been tested with PostgreSQL 8.0.x and 7.4.x. Older
versions don't have a -O option for the createdb, so if you are
using that version you'll have to change ownership of the DB later.
UPGRADING
=========
If you already have a previous version of RoundCube installed,

@ -11,7 +11,7 @@
CREATE TABLE `cache` (
`cache_id` int(10) unsigned NOT NULL auto_increment,
`user_id` int(10) unsigned NOT NULL default '0',
`session_id` varchar(32) default NULL,
`session_id` varchar(40) default NULL,
`cache_key` varchar(128) NOT NULL default '',
`created` datetime NOT NULL default '0000-00-00 00:00:00',
`data` longtext NOT NULL,
@ -31,7 +31,7 @@ CREATE TABLE `contacts` (
`contact_id` int(10) unsigned NOT NULL auto_increment,
`user_id` int(10) unsigned NOT NULL default '0',
`changed` datetime NOT NULL default '0000-00-00 00:00:00',
`del` enum('0','1') NOT NULL default '0',
`del` tinyint(1) NOT NULL default '0',
`name` varchar(128) NOT NULL default '',
`email` varchar(128) NOT NULL default '',
`firstname` varchar(128) NOT NULL default '',
@ -50,8 +50,8 @@ CREATE TABLE `contacts` (
CREATE TABLE `identities` (
`identity_id` int(10) unsigned NOT NULL auto_increment,
`user_id` int(10) unsigned NOT NULL default '0',
`del` enum('0','1') NOT NULL default '0',
`default` enum('0','1') NOT NULL default '0',
`del` tinyint(1) NOT NULL default '0',
`standard` tinyint(1) NOT NULL default '0',
`name` varchar(128) NOT NULL default '',
`organization` varchar(128) NOT NULL default '',
`email` varchar(128) NOT NULL default '',
@ -94,3 +94,33 @@ CREATE TABLE `users` (
`preferences` text NOT NULL,
PRIMARY KEY (`user_id`)
) TYPE=MyISAM;
-- --------------------------------------------------------
--
-- Table structure for table `messages`
--
CREATE TABLE `messages` (
`message_id` int(11) unsigned NOT NULL auto_increment,
`user_id` int(11) unsigned NOT NULL default '0',
`del` tinyint(1) NOT NULL default '0',
`cache_key` varchar(128) NOT NULL default '',
`idx` int(11) unsigned NOT NULL default '0',
`uid` int(11) unsigned NOT NULL default '0',
`subject` varchar(255) NOT NULL default '',
`from` varchar(255) NOT NULL default '',
`to` varchar(255) NOT NULL default '',
`cc` varchar(255) NOT NULL default '',
`date` datetime NOT NULL default '0000-00-00 00:00:00',
`size` int(11) unsigned NOT NULL default '0',
`headers` text NOT NULL,
`body` longtext,
PRIMARY KEY (`message_id`),
KEY `user_id` (`user_id`),
KEY `cache_key` (`cache_key`),
KEY `idx` (`idx`),
KEY `uid` (`uid`)
) TYPE=MyISAM;

@ -11,4 +11,39 @@ ALTER TABLE users ADD alias VARCHAR(128) NOT NULL AFTER mail_host;
-- Version 0.1-20051021
ALTER TABLE `session` CHANGE `sess_id` `sess_id` VARCHAR(40) NOT NULL;
ALTER TABLE `contacts` CHANGE `del` `del` TINYINT(1) NOT NULL;
ALTER TABLE `contacts` ADD `changed` DATETIME NOT NULL AFTER `user_id`;
UPDATE `contacts` SET `del`=0 WHERE `del`=1;
UPDATE `contacts` SET `del`=1 WHERE `del`=2;
ALTER TABLE `identities` CHANGE `default` `standard` TINYINT(1) NOT NULL;
ALTER TABLE `identities` CHANGE `del` `del` TINYINT(1) NOT NULL;
UPDATE `identities` SET `del`=0 WHERE `del`=1;
UPDATE `identities` SET `del`=1 WHERE `del`=2;
UPDATE `identities` SET `standard`=0 WHERE `standard`=1;
UPDATE `identities` SET `standard`=1 WHERE `standard`=2;
CREATE TABLE `messages` (
`message_id` int(11) unsigned NOT NULL auto_increment,
`user_id` int(11) unsigned NOT NULL default '0',
`del` tinyint(1) NOT NULL default '0',
`cache_key` varchar(128) NOT NULL default '',
`idx` int(11) unsigned NOT NULL default '0',
`uid` int(11) unsigned NOT NULL default '0',
`subject` varchar(255) NOT NULL default '',
`from` varchar(255) NOT NULL default '',
`to` varchar(255) NOT NULL default '',
`cc` varchar(255) NOT NULL default '',
`date` datetime NOT NULL default '0000-00-00 00:00:00',
`size` int(11) unsigned NOT NULL default '0',
`headers` text NOT NULL,
`body` longtext,
PRIMARY KEY (`message_id`),
KEY `user_id` (`user_id`),
KEY `cache_key` (`cache_key`),
KEY `idx` (`idx`),
KEY `uid` (`uid`)
) TYPE=MyISAM;

@ -1,255 +1,223 @@
--
-- PostgreSQL database dump
--
SET client_encoding = 'UNICODE';
SET check_function_bodies = false;
SET search_path = public, pg_catalog;
ALTER TABLE ONLY public.identities DROP CONSTRAINT "$1";
ALTER TABLE ONLY public.contacts DROP CONSTRAINT "$1";
ALTER TABLE ONLY public."cache" DROP CONSTRAINT "$2";
ALTER TABLE ONLY public."cache" DROP CONSTRAINT "$1";
ALTER TABLE ONLY public.users DROP CONSTRAINT users_pkey;
ALTER TABLE ONLY public."session" DROP CONSTRAINT session_pkey;
ALTER TABLE ONLY public.identities DROP CONSTRAINT identities_pkey;
ALTER TABLE ONLY public.contacts DROP CONSTRAINT contacts_pkey;
ALTER TABLE ONLY public."cache" DROP CONSTRAINT cache_pkey;
DROP TABLE public.users;
DROP TABLE public."session";
DROP TABLE public.identities;
DROP TABLE public.contacts;
DROP TABLE public."cache";
DROP SEQUENCE public.user_ids;
DROP SEQUENCE public.identity_ids;
DROP SEQUENCE public.contact_ids;
DROP SEQUENCE public.cache_ids;
--
-- TOC entry 4 (OID 15282470)
-- Name: cache_ids; Type: SEQUENCE; Schema: public; Owner: postgres
-- Table "users"
-- Name: users; Type: TABLE; Schema: public; Owner: postgres
--
CREATE SEQUENCE cache_ids
INCREMENT BY 1
NO MAXVALUE
NO MINVALUE
CACHE 1;
--
-- TOC entry 5 (OID 15282472)
-- Name: contact_ids; Type: SEQUENCE; Schema: public; Owner: postgres
--
CREATE TABLE users (
user_id integer DEFAULT nextval('user_ids'::text) NOT NULL,
username character varying(128) DEFAULT ''::character varying NOT NULL,
mail_host character varying(128) DEFAULT ''::character varying NOT NULL,
alias character varying(128) DEFAULT ''::character varying NOT NULL,
created timestamp with time zone DEFAULT now() NOT NULL,
last_login timestamp with time zone DEFAULT now() NOT NULL,
"language" character varying(5) DEFAULT 'en'::character varying NOT NULL,
preferences text DEFAULT ''::text NOT NULL
);
CREATE SEQUENCE contact_ids
START WITH 1
INCREMENT BY 1
NO MAXVALUE
NO MINVALUE
CACHE 1;
--
-- TOC entry 6 (OID 15282474)
-- Name: identity_ids; Type: SEQUENCE; Schema: public; Owner: postgres
-- Table "session"
-- Name: session; Type: TABLE; Schema: public; Owner: postgres
--
CREATE SEQUENCE identity_ids
START WITH 1
INCREMENT BY 1
NO MAXVALUE
NO MINVALUE
CACHE 1;
--
-- TOC entry 7 (OID 15282476)
-- Name: user_ids; Type: SEQUENCE; Schema: public; Owner: postgres
--
CREATE TABLE "session" (
sess_id character varying(40) DEFAULT ''::character varying NOT NULL,
created timestamp with time zone DEFAULT now() NOT NULL,
changed timestamp with time zone DEFAULT now() NOT NULL,
ip character varying(16) NOT NULL,
vars text NOT NULL
);
CREATE SEQUENCE user_ids
INCREMENT BY 1
NO MAXVALUE
NO MINVALUE
CACHE 1;
--
-- TOC entry 8 (OID 15282478)
-- Name: cache; Type: TABLE; Schema: public; Owner: postgres
-- Table "identities"
-- Name: identities; Type: TABLE; Schema: public; Owner: postgres
--
CREATE TABLE "cache" (
cache_id integer DEFAULT nextval('cache_ids'::text) NOT NULL,
CREATE TABLE identities (
identity_id integer DEFAULT nextval('identity_ids'::text) NOT NULL,
user_id integer DEFAULT 0 NOT NULL,
session_id character varying(32),
cache_key character varying(128) DEFAULT ''::character varying NOT NULL,
created timestamp with time zone DEFAULT now() NOT NULL,
data text NOT NULL
del integer DEFAULT 0 NOT NULL,
standard integer DEFAULT 0 NOT NULL,
name character varying(128) NOT NULL,
organization character varying(128),
email character varying(128) NOT NULL,
"reply-to" character varying(128),
bcc character varying(128),
signature text
);
--
-- TOC entry 10 (OID 15282486)
-- Table "contacts"
-- Name: contacts; Type: TABLE; Schema: public; Owner: postgres
--
CREATE TABLE contacts (
contact_id integer DEFAULT nextval('contact_ids'::text) NOT NULL,
user_id integer DEFAULT 0 NOT NULL,
del boolean DEFAULT false NOT NULL,
changed timestamp with time zone DEFAULT now() NOT NULL,
del integer DEFAULT 0 NOT NULL,
name character varying(128) DEFAULT ''::character varying NOT NULL,
email character varying(128) DEFAULT ''::character varying NOT NULL,
firstname character varying(128) DEFAULT ''::character varying NOT NULL,
surname character varying(128) DEFAULT ''::character varying NOT NULL,
vcard text NOT NULL
vcard text
);
--
-- TOC entry 11 (OID 15282494)
-- Name: identities; Type: TABLE; Schema: public; Owner: postgres
--
CREATE TABLE identities (
identity_id integer DEFAULT nextval('identity_ids'::text) NOT NULL,
user_id integer DEFAULT 0 NOT NULL,
del boolean DEFAULT false NOT NULL,
"default" boolean DEFAULT false NOT NULL,
name character varying(128) NOT NULL,
organization character varying(128),
email character varying(128) NOT NULL,
"reply-to" character varying(128),
bcc character varying(128),
signature text
);
--
-- TOC entry 12 (OID 15282503)
-- Name: session; Type: TABLE; Schema: public; Owner: postgres
-- Table "cache"
-- Name: cache; Type: TABLE; Schema: public; Owner: postgres
--
CREATE TABLE "session" (
sess_id character varying(32) DEFAULT ''::character varying NOT NULL,
CREATE TABLE "cache" (
cache_id integer DEFAULT nextval('cache_ids'::text) NOT NULL,
user_id integer DEFAULT 0 NOT NULL,
session_id character varying(40),
cache_key character varying(128) DEFAULT ''::character varying NOT NULL,
created timestamp with time zone DEFAULT now() NOT NULL,
changed timestamp with time zone DEFAULT now() NOT NULL,
ip character varying(16) NOT NULL,
vars text NOT NULL
data text NOT NULL
);
--
-- TOC entry 13 (OID 15282510)
-- Name: users; Type: TABLE; Schema: public; Owner: postgres
-- Table "messages"
-- Name: messages; Type: TABLE; Schema: public; Owner: postgres
--
CREATE TABLE users (
user_id integer DEFAULT nextval('user_ids'::text) NOT NULL,
username character varying(128) DEFAULT ''::character varying NOT NULL,
mail_host character varying(128) DEFAULT ''::character varying NOT NULL,
alias character varying(128) DEFAULT ''::character varying NOT NULL,
created timestamp with time zone DEFAULT now() NOT NULL,
last_login timestamp with time zone DEFAULT now() NOT NULL,
"language" character varying(5) DEFAULT 'en'::character varying NOT NULL,
preferences text DEFAULT ''::text NOT NULL
CREATE TABLE "messages" (
message_id integer DEFAULT nextval('message_ids'::text) NOT NULL,
user_id integer DEFAULT 0 NOT NULL,
del integer DEFAULT 0 NOT NULL,
cache_key character varying(128) DEFAULT ''::character varying NOT NULL,
idx integer DEFAULT 0 NOT NULL,
uid integer DEFAULT 0 NOT NULL,
subject character varying(128) DEFAULT ''::character varying NOT NULL,
"from" character varying(128) DEFAULT ''::character varying NOT NULL,
"to" character varying(128) DEFAULT ''::character varying NOT NULL,
cc character varying(128) DEFAULT ''::character varying NOT NULL,
date timestamp with time zone NOT NULL,
size integer DEFAULT 0 NOT NULL,
headers text NOT NULL,
body text
);
--
-- TOC entry 14 (OID 15282518)
-- Name: cache_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
-- Add primary keys
--
ALTER TABLE ONLY "cache"
ADD CONSTRAINT cache_pkey PRIMARY KEY (cache_id);
--
-- TOC entry 15 (OID 15282520)
-- Name: contacts_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--
ALTER TABLE ONLY contacts
ALTER TABLE ONLY "contacts"
ADD CONSTRAINT contacts_pkey PRIMARY KEY (contact_id);
--
-- TOC entry 16 (OID 15282522)
-- Name: identities_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--
ALTER TABLE ONLY identities
ADD CONSTRAINT identities_pkey PRIMARY KEY (identity_id);
--
-- TOC entry 17 (OID 15282524)
-- Name: session_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--
ALTER TABLE ONLY "session"
ADD CONSTRAINT session_pkey PRIMARY KEY (sess_id);
--
-- TOC entry 18 (OID 15282526)
-- Name: users_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--
ALTER TABLE ONLY users
ALTER TABLE ONLY "users"
ADD CONSTRAINT users_pkey PRIMARY KEY (user_id);
ALTER TABLE ONLY "messages"
ADD CONSTRAINT messages_pkey PRIMARY KEY (message_id);
--
-- TOC entry 19 (OID 15282528)
-- Name: $1; Type: FK CONSTRAINT; Schema: public; Owner: postgres
-- Reference keys
--
ALTER TABLE ONLY "cache"
ADD CONSTRAINT "$1" FOREIGN KEY (user_id) REFERENCES users(user_id);
ALTER TABLE ONLY "cache"
ADD CONSTRAINT "$2" FOREIGN KEY (session_id) REFERENCES "session"(sess_id);
ALTER TABLE ONLY "contacts"
ADD CONSTRAINT "$1" FOREIGN KEY (user_id) REFERENCES users(user_id);
ALTER TABLE ONLY "identities"
ADD CONSTRAINT "$1" FOREIGN KEY (user_id) REFERENCES users(user_id);
ALTER TABLE ONLY "messages"
ADD CONSTRAINT "$1" FOREIGN KEY (user_id) REFERENCES users(user_id);
--
-- TOC entry 20 (OID 15282532)
-- Name: $2; Type: FK CONSTRAINT; Schema: public; Owner: postgres
-- Sequence "cache_ids"
-- Name: cache_ids; Type: SEQUENCE; Schema: public; Owner: postgres
--
ALTER TABLE ONLY "cache"
ADD CONSTRAINT "$2" FOREIGN KEY (session_id) REFERENCES "session"(sess_id);
CREATE SEQUENCE cache_ids
INCREMENT BY 1
NO MAXVALUE
NO MINVALUE
CACHE 1;
--
-- TOC entry 21 (OID 15282536)
-- Name: $1; Type: FK CONSTRAINT; Schema: public; Owner: postgres
-- Sequence "contact_ids"
-- Name: contact_ids; Type: SEQUENCE; Schema: public; Owner: postgres
--
ALTER TABLE ONLY contacts
ADD CONSTRAINT "$1" FOREIGN KEY (user_id) REFERENCES users(user_id);
CREATE SEQUENCE contact_ids
START WITH 1
INCREMENT BY 1
NO MAXVALUE
NO MINVALUE
CACHE 1;
--
-- TOC entry 22 (OID 15282540)
-- Name: $1; Type: FK CONSTRAINT; Schema: public; Owner: postgres
-- Sequence "identity_ids"
-- Name: identity_ids; Type: SEQUENCE; Schema: public; Owner: postgres
--
ALTER TABLE ONLY identities
ADD CONSTRAINT "$1" FOREIGN KEY (user_id) REFERENCES users(user_id);
CREATE SEQUENCE identity_ids
START WITH 1
INCREMENT BY 1
NO MAXVALUE
NO MINVALUE
CACHE 1;
SET SESSION AUTHORIZATION 'postgres';
--
-- TOC entry 3 (OID 15282469)
-- Name: SCHEMA public; Type: COMMENT; Schema: -; Owner: postgres
-- Sequence "user_ids"
-- Name: user_ids; Type: SEQUENCE; Schema: public; Owner: postgres
--
COMMENT ON SCHEMA public IS 'Standard public schema';
CREATE SEQUENCE user_ids
INCREMENT BY 1
NO MAXVALUE
NO MINVALUE
CACHE 1;
SET SESSION AUTHORIZATION 'postgres';
--
-- TOC entry 9 (OID 15282478)
-- Name: TABLE "cache"; Type: COMMENT; Schema: public; Owner: postgres
--
-- Sequence "message_ids"
-- Name: message_ids; Type: SEQUENCE; Schema: public; Owner: postgres
--
CREATE SEQUENCE message_ids
INCREMENT BY 1
NO MAXVALUE
NO MINVALUE
CACHE 1;

@ -11,7 +11,7 @@
CREATE TABLE cache (
cache_id integer NOT NULL PRIMARY KEY,
user_id integer NOT NULL default 0,
session_id varchar(32) default NULL,
session_id varchar(40) default NULL,
cache_key varchar(128) NOT NULL default '',
created datetime NOT NULL default '0000-00-00 00:00:00',
data longtext NOT NULL
@ -21,6 +21,7 @@ CREATE INDEX ix_cache_user_id ON cache(user_id);
CREATE INDEX ix_cache_cache_key ON cache(cache_key);
CREATE INDEX ix_cache_session_id ON cache(session_id);
-- --------------------------------------------------------
--
@ -30,7 +31,8 @@ CREATE INDEX ix_cache_session_id ON cache(session_id);
CREATE TABLE contacts (
contact_id integer NOT NULL PRIMARY KEY,
user_id integer NOT NULL default '0',
del integer NOT NULL default '0',
created datetime NOT NULL default '0000-00-00 00:00:00',
del tinyint NOT NULL default '0',
name varchar(128) NOT NULL default '',
email varchar(128) NOT NULL default '',
firstname varchar(128) NOT NULL default '',
@ -49,10 +51,10 @@ CREATE INDEX ix_contacts_user_id ON contacts(user_id);
CREATE TABLE identities (
identity_id integer NOT NULL PRIMARY KEY,
user_id integer NOT NULL default '0',
del integer NOT NULL default '0',
"default" integer NOT NULL default '0',
del tinyint NOT NULL default '0',
standard tinyint NOT NULL default '0',
name varchar(128) NOT NULL default '',
organization varchar(128) NOT NULL default '',
organization varchar(128) default '',
email varchar(128) NOT NULL default '',
"reply-to" varchar(128) NOT NULL default '',
bcc varchar(128) NOT NULL default '',
@ -78,3 +80,45 @@ CREATE TABLE users (
language varchar(5) NOT NULL default 'en',
preferences text NOT NULL default ''
);
-- --------------------------------------------------------
--
-- Table structure for table session
--
CREATE TABLE session (
sess_id varchar(40) NOT NULL PRIMARY KEY,
created datetime NOT NULL default '0000-00-00 00:00:00',
changed datetime NOT NULL default '0000-00-00 00:00:00',
ip varchar(15) NOT NULL default '',
vars text NOT NULL
);
-- --------------------------------------------------------
--
-- Table structure for table messages
--
CREATE TABLE messages (
message_id integer NOT NULL PRIMARY KEY,
user_id integer NOT NULL default '0',
del tinyint NOT NULL default '0',
cache_key varchar(128) NOT NULL default '',
idx integer NOT NULL default '0',
uid integer NOT NULL default '0',
subject varchar(255) NOT NULL default '',
"from" varchar(255) NOT NULL default '',
"to" varchar(255) NOT NULL default '',
cc varchar(255) NOT NULL default '',
date datetime NOT NULL default '0000-00-00 00:00:00',
size integer NOT NULL default '0',
headers text NOT NULL,
body text
);
CREATE INDEX ix_messages_user_id ON messages(user_id);
CREATE INDEX ix_messages_cache_key ON messages(cache_key);

@ -10,7 +10,7 @@ from versions 0.1-alpha and 0.1-20050811
- replace index.php
- replace all files in folder /program/
- replace all files in folder /skins/default/
- rund SQL queries in order to update the database
- run all commands in SQL/*.update.sql or re-initalize database with *.initial.sql
- add these line to /config/main.inc.php
$rcmail_config['trash_mbox'] = 'Trash';
$rcmail_config['default_imap_folders'] = array('INBOX', 'Drafts', 'Sent', 'Junk', 'Trash');
@ -22,9 +22,12 @@ from versions 0.1-alpha and 0.1-20050811
$rcmail_config['message_sort_col'] = 'date';
$rcmail_config['message_sort_order'] = 'DESC';
$rcmail_config['log_dir'] = 'logs/';
$rcmail_config['temp_dir'] = 'temp/';
- replace database properties (db_type, db_host, db_user, db_pass, $d_name)
in /config/db.inc.php with the following line:
$rcmail_config['db_dsnw'] = 'mysql://roundcube:pass@localhost/roundcubemail';
- add these lines to /config/db.inc.php
$rcmail_config['db_max_length'] = 512000;
from version 0.1-20050820
@ -32,7 +35,7 @@ from version 0.1-20050820
- replace index.php
- replace all files in folder /program/
- replace all files in folder /skins/default/
- rund SQL queries in order to update the database
- run all commands in SQL/*.update.sql or re-initalize database with *.initial.sql
- add these line to /config/main.inc.php
$rcmail_config['prettydate'] = TRUE;
$rcmail_config['smtp_port'] = 25;
@ -41,9 +44,12 @@ from version 0.1-20050820
$rcmail_config['message_sort_col'] = 'date';
$rcmail_config['message_sort_order'] = 'DESC';
$rcmail_config['log_dir'] = 'logs/';
$rcmail_config['temp_dir'] = 'temp/';
- replace database properties (db_type, db_host, db_user, db_pass, $d_name)
in /config/db.inc.php with the following line:
$rcmail_config['db_dsnw'] = 'mysql://roundcube:pass@localhost/roundcubemail';
- add these lines to /config/db.inc.php
$rcmail_config['db_max_length'] = 512000;
from version 0.1-20051007
@ -51,20 +57,38 @@ from version 0.1-20051007
- replace index.php
- replace all files in folder /program/
- replace all files in folder /skins/default/
- run all commands in SQL/*.update.sql or re-initalize database with *.initial.sql
- add these lines to /config/main.inc.php
$rcmail_config['smtp_auth_type'] = ''; // if you need to specify an auth method for SMTP
$rcmail_config['session_lifetime'] = 20; // to specify the session lifetime in minutes
$rcmail_config['message_sort_col'] = 'date';
$rcmail_config['message_sort_order'] = 'DESC';
$rcmail_config['log_dir'] = 'logs/';
$rcmail_config['temp_dir'] = 'temp/';
- add these lines to /config/db.inc.php
$rcmail_config['db_max_length'] = 512000;
$rcmail_config['db_sequence_user_ids'] = 'user_ids';
$rcmail_config['db_sequence_identity_ids'] = 'identity_ids';
$rcmail_config['db_sequence_contact_ids'] = 'contact_ids';
$rcmail_config['db_sequence_cache_ids'] = 'cache_ids';
$rcmail_config['db_sequence_message_ids'] = 'message_ids';
from version 0.1-20051021
----------------------------------------
- replace index.php
- replace all files in folder /program/
- replace all files in folder /skins/default/
- run all commands in SQL/*.update.sql or re-initalize database with *.initial.sql
- add these lines to /config/main.inc.php
$rcmail_config['message_sort_col'] = 'date';
$rcmail_config['message_sort_order'] = 'DESC';
$rcmail_config['log_dir'] = 'logs/';
$rcmail_config['temp_dir'] = 'temp/';
- add these lines to /config/db.inc.php
$rcmail_config['db_max_length'] = 512000;
$rcmail_config['db_sequence_user_ids'] = 'user_ids';
$rcmail_config['db_sequence_identity_ids'] = 'identity_ids';
$rcmail_config['db_sequence_contact_ids'] = 'contact_ids';
$rcmail_config['db_sequence_cache_ids'] = 'cache_ids';
$rcmail_config['db_sequence_message_ids'] = 'message_ids';

@ -19,6 +19,7 @@ $rcmail_config = array();
// currentyl suported db_providers: mysql, sqlite
$rcmail_config['db_dsnw'] = 'mysql://roundcube:pass@localhost/roundcubemail';
// postgres example: 'pgsql://roundcube:pass@localhost/roundcubemail';
// sqlite example: 'sqlite://./sqlite.db?mode=0646';
// PEAR database DSN for read only operations (if empty write database will be used)
@ -28,6 +29,9 @@ $rcmail_config['db_dsnr'] = '';
// database backend to use (only db or mdb2 are supported)
$rcmail_config['db_backend'] = 'db';
// maximum length of a query in bytes
$rcmail_config['db_max_length'] = 512000; // 500K
// you can define specific table names used to store webmail data
$rcmail_config['db_table_users'] = 'users';
@ -39,6 +43,20 @@ $rcmail_config['db_table_session'] = 'session';
$rcmail_config['db_table_cache'] = 'cache';
$rcmail_config['db_table_messages'] = 'messages';
// you can define specific sequence names used in PostgreSQL
$rcmail_config['db_sequence_users'] = 'user_ids';
$rcmail_config['db_sequence_identities'] = 'identity_ids';
$rcmail_config['db_sequence_contacts'] = 'contact_ids';
$rcmail_config['db_sequence_cache'] = 'cache_ids';
$rcmail_config['db_sequence_messages'] = 'message_ids';
// end db config file
?>

@ -88,7 +88,7 @@ $rcmail_config['date_short'] = 'D H:i';
$rcmail_config['date_long'] = 'd.m.Y H:i';
// add this user-agent to message headers when sending
$rcmail_config['useragent'] = 'RoundCube Webmail/0.1-20051021';
$rcmail_config['useragent'] = 'RoundCube Webmail/0.1b';
// only list folders within this path
$rcmail_config['imap_root'] = '';

@ -62,7 +62,7 @@ ini_set('error_reporting', E_ALL&~E_NOTICE);
// increase maximum execution time for php scripts
// (does not work in safe mode)
@set_time_limit('120');
@set_time_limit(120);
// include base files
require_once('include/rcube_shared.inc');
@ -199,6 +199,13 @@ if (!$_SESSION['user_id'])
}
// handle keep-alive signal
if ($_action=='keep-alive')
{
rcube_remote_response('');
exit;
}
// include task specific files
if ($_task=='mail')
@ -289,14 +296,6 @@ if ($_task=='settings')
}
// handle keep-alive signal
if ($_action=='keep-alive')
{
rcube_remote_response('');
exit;
}
// only allow these templates to be included
$valid_tasks = array('mail','settings','addressbook');

@ -43,8 +43,8 @@ function rcube_read_cache($key)
return $data;
}
function rcube_write_cache($key, $data, $session_cache=FALSE)
{
global $DB, $CACHE_KEYS, $sess_id;
@ -91,7 +91,6 @@ function rcube_write_cache($key, $data, $session_cache=FALSE)
}
function rcube_clear_cache($key)
{
global $DB;

@ -69,7 +69,7 @@ function rcmail_startup($task='mail')
// we can use the database for storing session data
// session queries do not work with MDB2
if ($CONFIG['db_backend']!='mdb2' && is_object($DB) && $DB->db_provider!='sqlite')
if ($CONFIG['db_backend']!='mdb2' && is_object($DB) /* && $DB->db_provider!='sqlite' */)
include_once('include/session.inc');
@ -143,9 +143,9 @@ function rcmail_auth_hash($sess_id, $ts)
// create IMAP object and connect to server
function rcmail_imap_init($connect=FALSE)
{
global $CONFIG, $IMAP;
global $CONFIG, $DB, $IMAP;
$IMAP = new rcube_imap();
$IMAP = new rcube_imap($DB);
// connect with stored session data
if ($connect)
@ -227,6 +227,22 @@ function get_table_name($table)
}
// return correct name for a specific database sequence
// (used for Postres only)
function get_sequence_name($sequence)
{
global $CONFIG;
// return table name if configured
$config_key = 'db_sequence_'.$sequence;
if (strlen($CONFIG[$config_key]))
return $CONFIG[$config_key];
return $table;
}
// init output object for GUI and add common scripts
function load_gui()
@ -380,15 +396,15 @@ function rcmail_create_user($user, $host)
$host,
$_SESSION['user_lang']);
if ($user_id = $DB->insert_id('user_ids'))
if ($user_id = $DB->insert_id(get_sequence_name('users')))
{
$user_email = strstr($user, '@') ? $user : sprintf('%s@%s', $user, $host);
$user_name = $user!=$user_email ? $user : '';
// also create a new identity record
$DB->query("INSERT INTO ".get_table_name('identities')."
(user_id, `default`, name, email)
VALUES (?, '1', ?, ?)",
(user_id, del, standard, name, email)
VALUES (?, 0, 1, ?, ?)",
$user_id,
$user_name,
$user_email);
@ -479,7 +495,6 @@ function decrypt_passwd($cypher)
function rcube_remote_response($js_code)
{
send_nocacheing_headers();
//header('Content-Type: text/javascript');
header('Content-Type: application/x-javascript');
print '/** remote response ['.date('d/M/Y h:i:s O')."] **/\n";
@ -530,6 +545,117 @@ function rcube_add_label()
}
// remove temp files of a session
function rcmail_clear_session_temp($sess_id)
{
global $CONFIG;
$temp_dir = $CONFIG['temp_dir'].(!eregi('\/$', $CONFIG['temp_dir']) ? '/' : '');
$cache_dir = $temp_dir.$sess_id;
if (is_dir($cache_dir))
{
clear_directory($cache_dir);
rmdir($cache_dir);
}
}
// replace specials characters to a specific encoding type
function rep_specialchars_output($str, $enctype='', $mode='', $newlines=TRUE)
{
global $OUTPUT_TYPE, $CHARSET;
static $html_encode_arr, $js_rep_table, $rtf_rep_table, $xml_rep_table;
if (!$enctype)
$enctype = $GLOBALS['OUTPUT_TYPE'];
// convert nbsps back to normal spaces if not html
if ($enctype!='html')
$str = str_replace(chr(160), ' ', $str);
// encode for plaintext
if ($enctype=='text')
return str_replace("\r\n", "\n", $mode=='remove' ? strip_tags($str) : $str);
// encode for HTML output
if ($enctype=='html')
{
if (!$html_encode_arr)
{
if ($CHARSET=='ISO-8859-1')
{
$html_encode_arr = get_html_translation_table(HTML_ENTITIES);
$html_encode_arr[chr(128)] = '&euro;';
}
else
$html_encode_arr = get_html_translation_table(HTML_SPECIALCHARS);
unset($html_encode_arr['?']);
unset($html_encode_arr['&']);
}
$ltpos = strpos($str, '<');
$encode_arr = $html_encode_arr;
// don't replace quotes and html tags
if (($mode=='show' || $mode=='') && $ltpos!==false && strpos($str, '>', $ltpos)!==false)
{
unset($encode_arr['"']);
unset($encode_arr['<']);
unset($encode_arr['>']);
}
else if ($mode=='remove')
$str = strip_tags($str);
$out = strtr($str, $encode_arr);
return $newlines ? nl2br($out) : $out;
}
if ($enctype=='url')
return rawurlencode($str);
// if the replace tables for RTF, XML and JS are not yet defined
if (!$js_rep_table)
{
$js_rep_table = $rtf_rep_table = $xml_rep_table = array();
for ($c=160; $c<256; $c++) // can be increased to support more charsets
{
$hex = dechex($c);
$rtf_rep_table[Chr($c)] = "\\'$hex";
$xml_rep_table[Chr($c)] = "&#$c;";
if ($CHARSET=='ISO-8859-1')
$js_rep_table[Chr($c)] = sprintf("\u%s%s", str_repeat('0', 4-strlen($hex)), $hex);
}
$js_rep_table['"'] = sprintf("\u%s%s", str_repeat('0', 4-strlen(dechex(34))), dechex(34));
$xml_rep_table['"'] = '&quot;';
}
// encode for RTF
if ($enctype=='xml')
return strtr($str, $xml_rep_table);
// encode for javascript use
if ($enctype=='js')
return preg_replace(array("/\r\n/", '/"/', "/([^\\\])'/"), array('\n', '\"', "$1\'"), strtr($str, $js_rep_table));
// encode for RTF
if ($enctype=='rtf')
return preg_replace("/\r\n/", "\par ", strtr($str, $rtf_rep_table));
// no encoding given -> return original string
return $str;
}
// ************** template parsing and gui functions **************
@ -653,104 +779,53 @@ function rcube_xml_command($command, $str_attrib, $a_attrib=NULL)
case 'object':
$object = strtolower($attrib['name']);
$object_handlers = array(
// MAIL
'mailboxlist' => 'rcmail_mailbox_list',
'messages' => 'rcmail_message_list',
'messagecountdisplay' => 'rcmail_messagecount_display',
'messageheaders' => 'rcmail_message_headers',
'messagebody' => 'rcmail_message_body',
'messageattachments' => 'rcmail_message_attachments',
'blockedobjects' => 'rcmail_remote_objects_msg',
'messagecontentframe' => 'rcmail_messagecontent_frame',
'messagepartframe' => 'rcmail_message_part_frame',
'messagepartcontrols' => 'rcmail_message_part_controls',
'composeheaders' => 'rcmail_compose_headers',
'composesubject' => 'rcmail_compose_subject',
'composebody' => 'rcmail_compose_body',
'composeattachmentlist' => 'rcmail_compose_attachment_list',
'composeattachmentform' => 'rcmail_compose_attachment_form',
'composeattachment' => 'rcmail_compose_attachment_field',
'priorityselector' => 'rcmail_priority_selector',
'charsetselector' => 'rcmail_charset_selector',
// ADDRESS BOOK
'addresslist' => 'rcmail_contacts_list',
'addressframe' => 'rcmail_contact_frame',
'recordscountdisplay' => 'rcmail_rowcount_display',
'contactdetails' => 'rcmail_contact_details',
'contacteditform' => 'rcmail_contact_editform',
// USER SETTINGS
'userprefs' => 'rcmail_user_prefs_form',
'itentitieslist' => 'rcmail_identities_list',
'identityframe' => 'rcmail_identity_frame',
'identityform' => 'rcube_identity_form',
'foldersubscription' => 'rcube_subscription_form',
'createfolder' => 'rcube_create_folder_form',
'composebody' => 'rcmail_compose_body'
);
if ($object=='loginform')
return rcmail_login_form($attrib);
else if ($object=='message')
return rcmail_message_container($attrib);
// MAIL
else if ($object=='mailboxlist' && function_exists('rcmail_mailbox_list'))
return rcmail_mailbox_list($attrib);
else if ($object=='messages' && function_exists('rcmail_message_list'))
return rcmail_message_list($attrib);
else if ($object=='messagecountdisplay' && function_exists('rcmail_messagecount_display'))
return rcmail_messagecount_display($attrib);
else if ($object=='messageheaders' && function_exists('rcmail_message_headers'))
return rcmail_message_headers($attrib);
else if ($object=='messageattachments' && function_exists('rcmail_message_attachments'))
return rcmail_message_attachments($attrib);
else if ($object=='messagebody' && function_exists('rcmail_message_body'))
return rcmail_message_body($attrib);
else if ($object=='blockedobjects' && function_exists('rcmail_remote_objects_msg'))
return rcmail_remote_objects_msg($attrib);
else if ($object=='messagecontentframe' && function_exists('rcmail_messagecontent_frame'))
return rcmail_messagecontent_frame($attrib);
else if ($object=='messagepartframe' && function_exists('rcmail_message_part_frame'))
return rcmail_message_part_frame($attrib);
else if ($object=='messagepartcontrols' && function_exists('rcmail_message_part_controls'))
return rcmail_message_part_controls($attrib);
else if ($object=='composeheaders' && function_exists('rcmail_compose_headers'))
return rcmail_compose_headers($attrib);
else if ($object=='composesubject' && function_exists('rcmail_compose_subject'))
return rcmail_compose_subject($attrib);
else if ($object=='composebody' && function_exists('rcmail_compose_body'))
return rcmail_compose_body($attrib);
else if ($object=='composeattachmentlist' && function_exists('rcmail_compose_attachment_list'))
return rcmail_compose_attachment_list($attrib);
else if ($object=='composeattachmentform' && function_exists('rcmail_compose_attachment_form'))
return rcmail_compose_attachment_form($attrib);
else if ($object=='composeattachment' && function_exists('rcmail_compose_attachment_field'))
return rcmail_compose_attachment_field($attrib);
else if ($object=='priorityselector' && function_exists('rcmail_priority_selector'))
return rcmail_priority_selector($attrib);
else if ($object=='priorityselector' && function_exists('rcmail_priority_selector'))
return rcmail_priority_selector($attrib);
// ADDRESS BOOK
else if ($object=='addresslist' && function_exists('rcmail_contacts_list'))
return rcmail_contacts_list($attrib);
else if ($object=='addressframe' && function_exists('rcmail_contact_frame'))
return rcmail_contact_frame($attrib);
else if ($object=='recordscountdisplay' && function_exists('rcmail_rowcount_display'))
return rcmail_rowcount_display($attrib);
else if ($object=='contactdetails' && function_exists('rcmail_contact_details'))
return rcmail_contact_details($attrib);
else if ($object=='contacteditform' && function_exists('rcmail_contact_editform'))
return rcmail_contact_editform($attrib);
// USER SETTINGS
else if ($object=='userprefs' && function_exists('rcmail_user_prefs_form'))
return rcmail_user_prefs_form($attrib);
else if ($object=='itentitieslist' && function_exists('rcmail_identities_list'))
return rcmail_identities_list($attrib);
else if ($object=='identityframe' && function_exists('rcmail_identity_frame'))
return rcmail_identity_frame($attrib);
else if ($object=='identityform' && function_exists('rcube_identity_form'))
return rcube_identity_form($attrib);
else if ($object=='foldersubscription' && function_exists('rcube_subscription_form'))
return rcube_subscription_form($attrib);
else if ($object=='createfolder' && function_exists('rcube_create_folder_form'))
return rcube_create_folder_form($attrib);
// execute object handler function
else if ($object_handlers[$object] && function_exists($object_handlers[$object]))
return call_user_func($object_handlers[$object], $attrib);
else if ($object=='pagetitle')
{
@ -878,7 +953,7 @@ function rcube_button($attrib)
// generate image tag
if ($attrib['type']=='image')
{
$attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'width', 'height', 'border', 'hspace', 'vspace', 'alt'));
$attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'width', 'height', 'border', 'hspace', 'vspace', 'align', 'alt'));
$img_tag = sprintf('<img src="%%s"%s />', $attrib_str);
$btn_content = sprintf($img_tag, $skin_path.$attrib['image']);
if ($attrib['label'])
@ -1161,4 +1236,39 @@ EOF;
}
function rcmail_charset_selector($attrib)
{
// pass the following attributes to the form class
$field_attrib = array('name' => '_charset');
foreach ($attrib as $attr => $value)
if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex')))
$field_attrib[$attr] = $value;
$charsets = array(
'US-ASCII' => 'ASCII (English)',
'X-EUC-JP' => 'EUC-JP (Japanese)',
'EUC-KR' => 'EUC-KR (Korean)',
'BIG5' => 'BIG5 (Chinese)',
'GB2312' => 'GB2312 (Chinese)',
'ISO-8859-1' => 'ISO-8859-1 (Latin-1)',
'ISO-8859-2' => 'ISO-8895-2 (Central European)',
'ISO-8859-7' => 'ISO-8859-7 (Greek)',
'ISO-8859-9' => 'ISO-8859-9 (Turkish)',
'Windows-1251' => 'Windows-1251 (Cyrillic)',
'Windows-1252' => 'Windows-1252 (Western)',
'Windows-1255' => 'Windows-1255 (Hebrew)',
'Windows-1256' => 'Windows-1256 (Arabic)',
'Windows-1257' => 'Windows-1257 (Baltic)',
'UTF-8' => 'UTF-8'
);
$select = new select($field_attrib);
$select->add(array_values($charsets), array_keys($charsets));
$set = $_POST['_charset'] ? $_POST['_charset'] : $GLOBALS['CHARSET'];
return $select->show($set);
}
?>

@ -23,299 +23,332 @@
require_once('DB.php');
class rcube_db
{
var $db_dsnw; // DSN for write operations
var $db_dsnr; // DSN for read operations
var $db_connected=false; // Already connected ?
var $db_mode=''; // Connection mode
var $db_handle=0; // Connection handle
var $a_query_results = array('dummy');
var $last_res_id = 0;
// PHP 5 constructor
function __construct($db_dsnw,$db_dsnr='')
{
var $db_dsnw; // DSN for write operations
var $db_dsnr; // DSN for read operations
var $db_connected = false; // Already connected ?
var $db_mode = ''; // Connection mode
var $db_handle = 0; // Connection handle
var $a_query_results = array('dummy');
var $last_res_id = 0;
// PHP 5 constructor
function __construct($db_dsnw,$db_dsnr='')
{
if ($db_dsnr=='') $db_dsnr=$db_dsnw;
if ($db_dsnr=='')
$db_dsnr=$db_dsnw;
$this->db_dsnw = $db_dsnw;
$this->db_dsnr = $db_dsnr;
$this->db_dsnw = $db_dsnw;
$this->db_dsnr = $db_dsnr;
$dsn_array = DB::parseDSN($db_dsnw);
$this->db_provider = $dsn_array['phptype'];
$dsn_array = DB::parseDSN($db_dsnw);
$this->db_provider = $dsn_array['phptype'];
}
// PHP 4 compatibility
function rcube_db($db_dsnw,$db_dsnr='')
// PHP 4 compatibility
function rcube_db($db_dsnw,$db_dsnr='')
{
$this->__construct($db_dsnw,$db_dsnr);
$this->__construct($db_dsnw,$db_dsnr);
}
// Connect to specific database
function dsn_connect($dsn)
// Connect to specific database
function dsn_connect($dsn)
{
// Use persistent connections if available
$dbh = DB::connect($dsn, array('persistent' => $true));
// Use persistent connections if available
$dbh = DB::connect($dsn, array('persistent' => TRUE));
if (DB::isError($dbh))
raise_error(array('code' => 500,
if (DB::isError($dbh))
raise_error(array('code' => 500,
'type' => 'db',
'line' => __LINE__,
'file' => __FILE__,
'message' => $dbh->getMessage()), TRUE, FALSE);
else if ($this->db_provider=='sqlite')
{
$dsn_array = DB::parseDSN($dsn);
if (!filesize($dsn_array['database']) && !empty($this->sqlite_initials))
$this->_sqlite_create_database($dbh, $this->sqlite_initials);
}
else if ($this->db_provider=='sqlite')
{
$dsn_array = DB::parseDSN($dsn);
if (!filesize($dsn_array['database']) && !empty($this->sqlite_initials))
$this->_sqlite_create_database($dbh, $this->sqlite_initials);
}
return $dbh;
return $dbh;
}
// Connect to appropiate databse
function db_connect ($mode)
{
$this->db_mode = $mode;
// Already connected
if ($this->db_connected)
{
// no replication, current connection is ok
if ($this->db_dsnw==$this->db_dsnr) return;
// Connect to appropiate databse
function db_connect ($mode)
{
$this->db_mode = $mode;
// Already connected
if ($this->db_connected)
{
// no replication, current connection is ok
if ($this->db_dsnw==$this->db_dsnr)
return;
// connected to master, current connection is ok
if ($this->db_mode=='w') return;
// Same mode, current connection is ok
if ($this->db_mode==$mode) return;
}
// connected to master, current connection is ok
if ($this->db_mode=='w')
return;
// Same mode, current connection is ok
if ($this->db_mode==$mode)
return;
}
if ($mode=='r')
$dsn=$this->db_dsnr;
else
$dsn=$this->db_dsnw;
if ($mode=='r')
$dsn = $this->db_dsnr;
else
$dsn = $this->db_dsnw;
$this->db_handle = $this->dsn_connect($dsn);
$this->db_connected = true;
$this->db_handle = $this->dsn_connect($dsn);
$this->db_connected = true;
}
// Query database
function query()
// Query database
function query()
{
$params = func_get_args();
$query = array_shift($params);
return $this->_query($query, 0, 0, $params);
$params = func_get_args();
$query = array_shift($params);
return $this->_query($query, 0, 0, $params);
}
function limitquery()
// Query with limits
function limitquery()
{
$params = func_get_args();
$query = array_shift($params);
$offset = array_shift($params);
$numrows = array_shift($params);
$params = func_get_args();
$query = array_shift($params);
$offset = array_shift($params);
$numrows = array_shift($params);
return $this->_query($query, $offset, $numrows, $params);
return $this->_query($query, $offset, $numrows, $params);
}
function _query($query, $offset, $numrows, $params)
function _query($query, $offset, $numrows, $params)
{
// Read or write ?
if (strtolower(trim(substr($query,0,6)))=='select')
$mode='r';
else
$mode='w';
// Read or write ?
if (strtolower(trim(substr($query,0,6)))=='select')
$mode='r';
else
$mode='w';
$this->db_connect($mode);
$this->db_connect($mode);
if ($this->db_provider == 'sqlite')
$query = $this->_sqlite_prepare_query($query);
if ($numrows || $offset)
{
$result = $this->db_handle->limitQuery($query,$offset,$numrows,$params);
}
else
$result = $this->db_handle->query($query, $params);
if ($this->db_provider == 'sqlite')
$this->_sqlite_prepare();
if (DB::isError($result))
{
raise_error(array('code' => 500,
'type' => 'db',
'line' => __LINE__,
'file' => __FILE__,
'message' => $result->getMessage().'; QUERY: '.$query), TRUE, FALSE);
return false;
}
return $this->_add_result($result, $query);
if ($numrows || $offset)
$result = $this->db_handle->limitQuery($query,$offset,$numrows,$params);
else
$result = $this->db_handle->query($query, $params);
// add result, even if it's an error
return $this->_add_result($result);
}
function num_rows($res_id=NULL)
function num_rows($res_id=NULL)
{
if (!$this->db_handle)
return FALSE;
if (!$this->db_handle)
return FALSE;
$result = $this->_get_result($res_id);
if ($result)
return $result->numRows();
else
return FALSE;
if ($result = $this->_get_result($res_id))
return $result->numRows();
else
return FALSE;
}
function affected_rows($res_id=NULL)
function affected_rows($res_id=NULL)
{
if (!$this->db_handle)
return FALSE;
return $this->db_handle->affectedRows();
if (!$this->db_handle)
return FALSE;
return $this->db_handle->affectedRows();
}
function insert_id($sequence = '')
function insert_id($sequence = '')
{
if (!$this->db_handle || $this->db_mode=='r')
return FALSE;
switch($this->db_provider)
{
case 'pgsql':
// PostgreSQL uses sequences
$result =& $this->db_handle->getOne("SELECT CURRVAL('$sequence')");
if (DB::isError($result)) {
raise_error( array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__,
'message' => $result->getMessage()), TRUE, TRUE);
}
return $result;
if (!$this->db_handle || $this->db_mode=='r')
return FALSE;
switch($this->db_provider)
{
case 'pgsql':
// PostgreSQL uses sequences
$result =& $this->db_handle->getOne("SELECT CURRVAL('$sequence')");
if (DB::isError($result))
raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__,
'message' => $result->getMessage()), TRUE, FALSE);
return $result;
case 'mysql': // This is unfortuneate
return mysql_insert_id($this->db_handle->connection);
case 'mysql': // This is unfortuneate
return mysql_insert_id($this->db_handle->connection);
case 'mysqli':
return mysqli_insert_id($this->db_handle->connection);
case 'mysqli':
return mysqli_insert_id($this->db_handle->connection);
case 'sqlite':
return sqlite_last_insert_rowid($this->db_handle->connection);
case 'sqlite':
return sqlite_last_insert_rowid($this->db_handle->connection);
default:
die("portability issue with this database, please have the developer fix");
}
default:
die("portability issue with this database, please have the developer fix");
}
}
function fetch_assoc($res_id=NULL)
function fetch_assoc($res_id=NULL)
{
$result = $this->_get_result($res_id);
if (DB::isError($result))
{
raise_error( array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__,
'message' => $this->db_link->getMessage()), TRUE, FALSE);
return FALSE;
}
$result = $this->_get_result($res_id);
if (DB::isError($result))
{
raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__,
'message' => $this->db_link->getMessage()), TRUE, FALSE);
return FALSE;
}
return $result->fetchRow(DB_FETCHMODE_ASSOC);
return $result->fetchRow(DB_FETCHMODE_ASSOC);
}
function quote($input, $type=null)
function quote($input, $type=null)
{
if (!$this->db_handle)
$this->db_connect('r');
if (!$this->db_handle)
$this->db_connect('r');
return $this->db_handle->quote($input);
return $this->db_handle->quote($input);
}
function quoteIdentifier($str)
function quoteIdentifier($str)
{
if (!$this->db_handle)
$this->db_connect('r');
if (!$this->db_handle)
$this->db_connect('r');
return $this->db_handle->quoteIdentifier($str);
}
function quote_identifier($str)
{
return $this->quoteIdentifier($str);
return $this->db_handle->quoteIdentifier($str);
}
function unixtimestamp($field)
{
switch($this->db_provider)
{
case 'pgsql':
return "EXTRACT (EPOCH FROM $field)";
break;
default:
return "UNIX_TIMESTAMP($field)";
}
}
function _add_result($res, $query)
function quote_identifier($str)
{
return $this->quoteIdentifier($str);
}
function unixtimestamp($field)
{
// sql error occured
if (DB::isError($res))
{
raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, 'message' => $res->getMessage() . " Query: " . substr(preg_replace('/[\r\n]+\s*/', ' ', $query), 0, 1024)), TRUE, FALSE);
return FALSE;
}
else
{
$res_id = sizeof($this->a_query_results);
$this->a_query_results[$res_id] = $res;
$this->last_res_id = $res_id;
return $res_id;
}
switch($this->db_provider)
{
case 'pgsql':
return "EXTRACT (EPOCH FROM $field)";
break;
default:
return "UNIX_TIMESTAMP($field)";
}
}
function _get_result($res_id)
function fromunixtime($timestamp)
{
if ($res_id==NULL)
$res_id = $this->last_res_id;
switch($this->db_provider)
{
case 'mysqli':
case 'mysql':
case 'sqlite':
return "FROM_UNIXTIME($timestamp)";
default:
return date("'Y-m-d H:i:s'", $timestamp);
}
}
function _add_result($res)
{
// sql error occured
if (DB::isError($res))
{
raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__,
'message' => $res->getMessage() . " Query: " . substr(preg_replace('/[\r\n]+\s*/', ' ', $res->userinfo), 0, 1024)), TRUE, FALSE);
return FALSE;
}
else
{
$res_id = sizeof($this->a_query_results);
$this->a_query_results[$res_id] = $res;
$this->last_res_id = $res_id;
return $res_id;
}
}
function _get_result($res_id)
{
if ($res_id==NULL)
$res_id = $this->last_res_id;
if ($res_id && isset($this->a_query_results[$res_id]))
return $this->a_query_results[$res_id];
else
return FALSE;
if ($res_id && isset($this->a_query_results[$res_id]))
return $this->a_query_results[$res_id];
else
return FALSE;
}
// create a sqlite database from a file
function _sqlite_create_database($dbh, $fileName)
// create a sqlite database from a file
function _sqlite_create_database($dbh, $fileName)
{
if (empty($fileName) || !is_string($fileName))
return ;
$data = '';
if ($fd = fopen($fileName, 'r'))
{
$data = fread($fd, filesize($fileName));
fclose($fd);
}
if (strlen($data))
sqlite_exec($dbh->connection, $data);
if (empty($fileName) || !is_string($fileName))
return ;
$data = '';
if ($fd = fopen($fileName, 'r'))
{
$data = fread($fd, filesize($fileName));
fclose($fd);
}
if (strlen($data))
sqlite_exec($dbh->connection, $data);
}
// transform a query so that it is sqlite2 compliant
function _sqlite_prepare_query($query)
function _sqlite_prepare()
{
if (!is_string($query))
return ($query);
$search = array('/NOW\(\)/i', '/`/');
$replace = array("datetime('now')", '"');
$query = preg_replace($search, $replace, $query);
include_once('include/rcube_sqlite.inc');
return ($query);
// we emulate via callback some missing MySQL function
sqlite_create_function($this->db_handle->connection, "from_unixtime", "rcube_sqlite_from_unixtime");
sqlite_create_function($this->db_handle->connection, "unix_timestamp", "rcube_sqlite_unix_timestamp");
sqlite_create_function($this->db_handle->connection, "now", "rcube_sqlite_now");
sqlite_create_function($this->db_handle->connection, "md5", "rcube_sqlite_md5");
}
}
/*
// transform a query so that it is sqlite2 compliant
function _sqlite_prepare_query($query)
{
if (!is_string($query))
return ($query);
$search = array('/NOW\(\)/i', '/`/');
$replace = array("datetime('now')", '"');
$query = preg_replace($search, $replace, $query);
return ($query);
}
*/
} // end class rcube_db
?>

@ -28,6 +28,7 @@ require_once('lib/utf7.inc');
class rcube_imap
{
var $db;
var $conn;
var $root_ns = '';
var $root_dir = '';
@ -38,21 +39,23 @@ class rcube_imap
var $caching_enabled = FALSE;
var $default_folders = array('inbox', 'drafts', 'sent', 'junk', 'trash');
var $cache = array();
var $cache_keys = array();
var $cache_changes = array();
var $uid_id_map = array();
var $msg_headers = array();
var $capabilities = array();
// PHP 5 constructor
function __construct()
function __construct($db_conn)
{
$this->db = $db_conn;
}
// PHP 4 compatibility
function rcube_imap()
function rcube_imap($db_conn)
{
$this->__construct();
$this->__construct($db_conn);
}
@ -95,6 +98,7 @@ class rcube_imap
// get account namespace
if ($this->conn)
{
$this->_parse_capability($this->conn->capability);
iil_C_NameSpace($this->conn);
if (!empty($this->conn->delimiter))
@ -185,6 +189,13 @@ class rcube_imap
}
function get_capability($cap)
{
$cap = strtoupper($cap);
return $this->capabilities[$cap];
}
function get_hierarchy_delimiter()
{
if ($this->conn && empty($this->delimiter))
@ -298,200 +309,131 @@ class rcube_imap
// private method for listing message header
// by DrSlump <drslump@drslump.biz>
function __list_headers($mailbox='', $page=NULL, $sort_field='date', $sort_order='DESC')
function _list_headers($mailbox='', $page=NULL, $sort_field='date', $sort_order='DESC')
{
$a_out = array();
$cached_count = 0;
if (!strlen($mailbox))
return $a_out;
return array();
$max = $this->_messagecount($mailbox);
$start_msg = ($this->list_page-1) * $this->page_size;
if ($page=='all')
{
$begin = 0;
$end = $max;
}
else if ($sort_order=='DESC')
{
$begin = $max - $this->page_size - $start_msg;
$end = $max - $start_msg;
}
else
{
$begin = $start_msg;
$end = $start_msg + $this->page_size;
}
$mbox_count = $this->_messagecount($mailbox /*, 'ALL', TRUE*/);
if ($begin < 0) $begin = 0;
if ($end < 0) $end = $max;
if ($end > $max) $end = $max;
$revalidate = false;
if ($mbox_count)
//console("fetch headers $start_msg to ".($start_msg+$this->page_size)." (msg $begin to $end)");
$headers_sorted = FALSE;
$cache_key = $mailbox.'.msg';
$cache_status = $this->check_cache_status($mailbox, $cache_key);
//console("Cache status = $cache_status");
// cache is OK, we can get all messages from local cache
if ($cache_status>0)
{
$a_msg_headers = $this->get_message_cache($cache_key, $start_msg, $start_msg+$this->page_size, $sort_field, $sort_order);
$headers_sorted = TRUE;
}
else
{
// get cached headers
$a_out = $this->get_cache($mailbox.'.msg');
$a_out = is_array($a_out) ? $a_out : array(); // make sure we get an array
$cached_count = count($a_out);
$a_new = array();
$revalidate = true; // revalidate by default
// if the cache count is greater then there have been changes for sure
if ($cached_count <= $mbox_count)
// retrieve headers from IMAP
if ($this->get_capability('sort') && ($msg_index = iil_C_Sort($this->conn, $mailbox, $sort_field)))
{
$from = $cached_count?$cached_count:1;
//get new headers (at least one is returned)
$a_temp = iil_C_FetchHeaders($this->conn, $mailbox, $from . ':' . $mbox_count);
$duplicated = $cached_count?true:false;
foreach ($a_temp as $hdr)
//console("$mailbox: ".count($msg_index));
$msgs = $msg_index[$begin];
for ($i=$begin; $i < $end; $i++)
{
//skip the first one if duplicated
if ($duplicated)
{
//check for changes using the UID
$lastCacheHdr = end($a_out);
if ($hdr->uid === $lastCacheHdr->uid)
$revalidate = false;
$duplicated = false;
continue;
}
//skip deleted ones
if (! $hdr->deleted)
$a_new[ $hdr->uid ] = $hdr;
if ($sort_order == 'DESC')
$msgs = $msg_index[$i].','.$msgs;
else
$msgs = $msgs.','.$msg_index[$i];
}
}
//revalidate cache if needed
$to = $mbox_count - count($a_new);
if ($revalidate && $to !== 0) //we'll need to reindex the array so we have to make a copy
$sorted = TRUE;
}
else
{
$a_dirty = $a_out;
$a_out = array();
$a_buffers = array();
$msgs = sprintf("%d:%d", $begin+1, $end);
$sorted = FALSE;
}
//fetch chunks of 20 headers
$step = 20;
$found = false;
//fetch headers in blocks starting from new to old
do {
$from = $to-$step;
if ($from < 1) $from = 1;
//store the block in a temporal buffer
$a_buffers[$from] = iil_C_FetchHeaders($this->conn, $mailbox, $from . ':' . $to);
// cache is dirty, sync it
if ($this->caching_enabled && $cache_status==-1)
{
$this->sync_header_index($mailbox);
return $this->_list_headers($mailbox, $page, $sort_field, $sort_order);
}
//compare the fetched headers with the ones in the cache
$idx = 0;
foreach ($a_buffers[$from] as $k=>$hdr)
// cache is incomplete
$cache_index = $this->get_message_cache_index($cache_key);
// fetch reuested headers from server
$a_header_index = iil_C_FetchHeaders($this->conn, $mailbox, $msgs);
$a_msg_headers = array();
if (!empty($a_header_index))
{
foreach ($a_header_index as $i => $headers)
{
if ($headers->deleted)
{
//if it's different the comparison ends
if (!isset($a_dirty[$hdr->uid]) || $a_dirty[$hdr->uid]->id !== $hdr->id)
break;
// delete from cache
if ($cache_index[$headers->id] && $cache_index[$headers->id] == $headers->uid)
$this->remove_message_cache($cache_key, $headers->id);
//if we arrive here then we know that the older messages in cache are ok
$found = $hdr->id;
$idx++;
continue;
}
//remove from the buffer the headers which are already cached
if ($found)
$a_buffers[$from] = array_splice($a_buffers[$from], 0, $idx );
$to = $from-1;
}
while ($found===false && $from > 1);
// add message to cache
if ($this->caching_enabled && $cache_index[$headers->id] != $headers->uid)
$this->add_message_cache($cache_key, $headers->id, $headers);
//just keep the headers we are certain that didn't change in the cache
if ($found !== false)
{
foreach ($a_dirty as $hdr)
{
if ($hdr->id > $found) break;
$a_out[$hdr->uid] = $hdr;
}
}
//we builded the block buffers from new to older, we process them in reverse order
ksort($a_buffers, SORT_NUMERIC);
foreach ($a_buffers as $a_buff)
{
foreach ($a_buff as $hdr)
{
if (! $hdr->deleted)
$a_out[$hdr->uid] = $hdr;
}
$a_msg_headers[$headers->uid] = $headers;
}
}
//array_merge() would reindex the keys, so we use this 'hack'
$a_out += $a_new;
}
//write headers list to cache if needed
if ($revalidate || count($a_out)!=$cached_count) {
$this->update_cache($mailbox.'.msg', $a_out);
}
//sort headers by a specific col
$a_out = iil_SortHeaders( $a_out, $sort_field, $sort_order );
// return complete list of messages
if (strtolower($page)=='all')
return $a_out;
$start_msg = ($this->list_page-1) * $this->page_size;
return array_slice($a_out, $start_msg, $this->page_size);
}
// delete cached messages with a higher index than $max
$this->clear_message_cache($cache_key, $max);
// original function; replaced 2005/10/18
// private method for listing message header
function _list_headers($mailbox='', $page=NULL, $sort_field='date', $sort_order='DESC')
{
$max = $this->_messagecount($mailbox);
if (!strlen($mailbox))
return array();
// get cached headers
$a_msg_headers = $this->get_cache($mailbox.'.msg');
// retrieve headers from IMAP
if (!is_array($a_msg_headers) || sizeof($a_msg_headers) != $max)
{
$a_header_index = iil_C_FetchHeaders($this->conn, $mailbox, "1:$max");
$a_msg_headers = array();
if (!empty($a_header_index))
foreach ($a_header_index as $i => $headers)
if (!$headers->deleted)
$a_msg_headers[$headers->uid] = $headers;
}
else
$headers_cached = TRUE;
if (!is_array($a_msg_headers))
return array();
// sort headers by a specific col
$a_headers = iil_SortHeaders($a_msg_headers, $sort_field, $sort_order);
$headers_count = count($a_headers);
// free memory
unset($a_msg_headers);
// write headers list to cache
if (!$headers_cached)
$this->update_cache($mailbox.'.msg', $a_headers);
// kick child process to sync cache
// update message count cache
$a_mailbox_cache = $this->get_cache('messagecount');
if (isset($a_mailbox_cache[$mailbox]['ALL']) && $a_mailbox_cache[$mailbox]['ALL'] != $headers_count)
{
$a_mailbox_cache[$mailbox]['ALL'] = (int)$headers_count;
$this->update_cache('messagecount', $a_mailbox_cache);
}
if (empty($a_headers))
// return empty array if no messages found
if (!is_array($a_msg_headers) || empty($a_msg_headers))
return array();
// return complete list of messages
if (strtolower($page)=='all')
return $a_headers;
$start_msg = ($this->list_page-1) * $this->page_size;
return array_slice($a_headers, $start_msg, $this->page_size);
// if not already sorted
if (!$headers_sorted)
$a_msg_headers = iil_SortHeaders($a_msg_headers, $sort_field, $sort_order);
return array_values($a_msg_headers);
}
// return sorted array of message UIDs
function message_index($mbox='', $sort_field='date', $sort_order='DESC')
@ -510,9 +452,54 @@ class rcube_imap
}
function sync_header_index($mbox=NULL)
function sync_header_index($mailbox)
{
$cache_key = $mailbox.'.msg';
$cache_index = $this->get_message_cache_index($cache_key);
$msg_count = $this->_messagecount($mailbox);
// fetch complete message index
$a_message_index = iil_C_FetchHeaderIndex($this->conn, $mailbox, "1:$msg_count", 'UID');
foreach ($a_message_index as $id => $uid)
{
// message in cache at correct position
if ($cache_index[$id] == $uid)
{
// console("$id / $uid: OK");
unset($cache_index[$id]);
continue;
}
// message in cache but in wrong position
if (in_array((string)$uid, $cache_index, TRUE))
{
// console("$id / $uid: Moved");
unset($cache_index[$id]);
}
// other message at this position
if (isset($cache_index[$id]))
{
// console("$id / $uid: Delete");
$this->remove_message_cache($cache_key, $id);
unset($cache_index[$id]);
}
// console("$id / $uid: Add");
// fetch complete headers and add to cache
$headers = iil_C_FetchHeader($this->conn, $mailbox, $id);
$this->add_message_cache($cache_key, $headers->id, $headers);
}
// those ids that are still in cache_index have been deleted
if (!empty($cache_index))
{
foreach ($cache_index as $id => $uid)
$this->remove_message_cache($cache_key, $id);
}
}
@ -527,22 +514,19 @@ class rcube_imap
function get_headers($uid, $mbox=NULL)
{
$mailbox = $mbox ? $this->_mod_mailbox($mbox) : $this->mailbox;
// get cached headers
$a_msg_headers = $this->get_cache($mailbox.'.msg');
// return cached header
if ($a_msg_headers[$uid])
return $a_msg_headers[$uid];
if ($headers = $this->get_cached_message($mailbox.'.msg', $uid))
return $headers;
$msg_id = $this->_uid2id($uid);
$header = iil_C_FetchHeader($this->conn, $mailbox, $msg_id);
$headers = iil_C_FetchHeader($this->conn, $mailbox, $msg_id);
// write headers cache
$a_msg_headers[$uid] = $header;
$this->update_cache($mailbox.'.msg', $a_msg_headers);
if ($headers)
$this->add_message_cache($mailbox.'.msg', $msg_id, $headers);
return $header;
return $headers;
}
@ -595,19 +579,20 @@ class rcube_imap
// reload message headers if cached
$cache_key = $this->mailbox.'.msg';
if ($this->caching_enabled && $result && ($a_cached_headers = $this->get_cache($cache_key)))
if ($this->caching_enabled)
{
// close and re-open connection
$this->reconnect();
foreach ($uids as $uid)
foreach ($msg_ids as $id)
{
if (isset($a_cached_headers[$uid]))
if ($cached_headers = $this->get_cached_message($cache_key, $id))
{
unset($this->cache[$cache_key][$uid]);
$this->get_headers($uid);
$this->remove_message_cache($cache_key, $id);
//$this->get_headers($uid);
}
}
// close and re-open connection
// this prevents connection problems with Courier
$this->reconnect();
}
// set nr of messages that were flaged
@ -633,7 +618,7 @@ class rcube_imap
// make shure mailbox exists
if (in_array($mailbox, $this->_list_mailboxes()))
$saved = iil_C_Append($this->conn, $mailbox, $message);
if ($saved)
{
// increase messagecount of the target mailbox
@ -672,20 +657,24 @@ class rcube_imap
// really deleted from the source mailbox
if ($moved)
{
$this->expunge($from_mbox, FALSE);
$this->clear_cache($to_mbox.'.msg');
$this->_expunge($from_mbox, FALSE);
$this->_clear_messagecount($from_mbox);
$this->_clear_messagecount($to_mbox);
}
// update cached message headers
$cache_key = $from_mbox.'.msg';
if ($moved && ($a_cached_headers = $this->get_cache($cache_key)))
if ($moved && ($a_cache_index = $this->get_message_cache_index($cache_key)))
{
$start_index = 100000;
foreach ($a_uids as $uid)
unset($a_cached_headers[$uid]);
{
$index = array_search($uid, $a_cache_index);
$start_index = min($index, $start_index);
}
$this->update_cache($cache_key, $a_cached_headers);
// clear cache from the lowest index on
$this->clear_message_cache($cache_key, $start_index);
}
return $moved;
@ -716,17 +705,23 @@ class rcube_imap
// really deleted from the mailbox
if ($deleted)
{
$this->expunge($mailbox, FALSE);
$this->_expunge($mailbox, FALSE);
$this->_clear_messagecount($mailbox);
}
// remove deleted messages from cache
if ($deleted && ($a_cached_headers = $this->get_cache($mailbox.'.msg')))
$cache_key = $mailbox.'.msg';
if ($deleted && ($a_cache_index = $this->get_message_cache_index($cache_key)))
{
$start_index = 100000;
foreach ($a_uids as $uid)
unset($a_cached_headers[$uid]);
{
$index = array_search($uid, $a_cache_index);
$start_index = min($index, $start_index);
}
$this->update_cache($mailbox.'.msg', $a_cached_headers);
// clear cache from the lowest index on
$this->clear_message_cache($cache_key, $start_index);
}
return $deleted;
@ -740,7 +735,10 @@ class rcube_imap
$msg_count = $this->_messagecount($mailbox, 'ALL');
if ($msg_count>0)
{
$this->clear_message_cache($mailbox.'.msg');
return iil_C_ClearFolder($this->conn, $mailbox);
}
else
return 0;
}
@ -750,12 +748,18 @@ class rcube_imap
function expunge($mbox='', $clear_cache=TRUE)
{
$mailbox = $mbox ? $this->_mod_mailbox($mbox) : $this->mailbox;
return $this->_expunge($mailbox, $clear_cache);
}
// send IMAP expunge command and clear cache
function _expunge($mailbox, $clear_cache=TRUE)
{
$result = iil_C_Expunge($this->conn, $mailbox);
if ($result>=0 && $clear_cache)
{
$this->clear_cache($mailbox.'.msg');
//$this->clear_message_cache($mailbox.'.msg');
$this->_clear_messagecount($mailbox);
}
@ -763,7 +767,6 @@ class rcube_imap
}
/* --------------------------------
* folder managment
* --------------------------------*/
@ -824,13 +827,18 @@ class rcube_imap
function create_mailbox($name, $subscribe=FALSE)
{
$result = FALSE;
// replace backslashes
$name = preg_replace('/[\\\]+/', '-', $name);
$name_enc = UTF7EncodeString($name);
// reduce mailbox name to 100 chars
$name_enc = substr($name_enc, 0, 100);
$abs_name = $this->_mod_mailbox($name_enc);
$a_mailbox_cache = $this->get_cache('mailboxes');
//if (strlen($this->root_ns))
// $abs_name = $this->root_ns.$abs_name;
if (strlen($abs_name) && (!is_array($a_mailbox_cache) || !in_array($abs_name, $a_mailbox_cache)))
$result = iil_C_CreateFolder($this->conn, $abs_name);
@ -875,37 +883,41 @@ class rcube_imap
// clear mailboxlist cache
if ($deleted)
{
$this->clear_message_cache($mailbox.'.msg');
$this->clear_cache('mailboxes');
}
return $updated;
return $deleted;
}
/* --------------------------------
* internal caching functions
* internal caching methods
* --------------------------------*/
function set_caching($set)
{
if ($set && function_exists('rcube_read_cache'))
if ($set && is_object($this->db))
$this->caching_enabled = TRUE;
else
$this->caching_enabled = FALSE;
}
function get_cache($key)
{
// read cache
if (!isset($this->cache[$key]) && $this->caching_enabled)
{
$cache_data = rcube_read_cache('IMAP.'.$key);
$cache_data = $this->_read_cache_record('IMAP.'.$key);
$this->cache[$key] = strlen($cache_data) ? unserialize($cache_data) : FALSE;
}
return $this->cache[$key];
return $this->cache[$key];
}
@ -924,7 +936,7 @@ class rcube_imap
foreach ($this->cache as $key => $data)
{
if ($this->cache_changes[$key])
rcube_write_cache('IMAP.'.$key, serialize($data));
$this->_write_cache_record('IMAP.'.$key, serialize($data));
}
}
}
@ -935,7 +947,7 @@ class rcube_imap
if ($key===NULL)
{
foreach ($this->cache as $key => $data)
rcube_clear_cache('IMAP.'.$key);
$this->_clear_cache_record('IMAP.'.$key);
$this->cache = array();
$this->cache_changed = FALSE;
@ -943,7 +955,7 @@ class rcube_imap
}
else
{
rcube_clear_cache('IMAP.'.$key);
$this->_clear_cache_record('IMAP.'.$key);
$this->cache_changes[$key] = FALSE;
unset($this->cache[$key]);
}
@ -951,8 +963,276 @@ class rcube_imap
function _read_cache_record($key)
{
$cache_data = FALSE;
if ($this->db)
{
// get cached data from DB
$sql_result = $this->db->query(
"SELECT cache_id, data
FROM ".get_table_name('cache')."
WHERE user_id=?
AND cache_key=?",
$_SESSION['user_id'],
$key);
if ($sql_arr = $this->db->fetch_assoc($sql_result))
{
$cache_data = $sql_arr['data'];
$this->cache_keys[$key] = $sql_arr['cache_id'];
}
}
return $cache_data;
}
function _write_cache_record($key, $data)
{
if (!$this->db)
return FALSE;
// check if we already have a cache entry for this key
if (!isset($this->cache_keys[$key]))
{
$sql_result = $this->db->query(
"SELECT cache_id
FROM ".get_table_name('cache')."
WHERE user_id=?
AND cache_key=?",
$_SESSION['user_id'],
$key);
if ($sql_arr = $this->db->fetch_assoc($sql_result))
$this->cache_keys[$key] = $sql_arr['cache_id'];
else
$this->cache_keys[$key] = FALSE;
}
// update existing cache record
if ($this->cache_keys[$key])
{
$this->db->query(
"UPDATE ".get_table_name('cache')."
SET created=now(),
data=?
WHERE user_id=?
AND cache_key=?",
$data,
$_SESSION['user_id'],
$key);
}
// add new cache record
else
{
$this->db->query(
"INSERT INTO ".get_table_name('cache')."
(created, user_id, cache_key, data)
VALUES (now(), ?, ?, ?)",
$_SESSION['user_id'],
$key,
$data);
}
}
function _clear_cache_record($key)
{
$this->db->query(
"DELETE FROM ".get_table_name('cache')."
WHERE user_id=?
AND cache_key=?",
$_SESSION['user_id'],
$key);
}
/* --------------------------------
* message caching methods
* --------------------------------*/
// checks if the cache is up-to-date
// return: -3 = off, -2 = incomplete, -1 = dirty
function check_cache_status($mailbox, $cache_key)
{
if (!$this->caching_enabled)
return -3;
$cache_index = $this->get_message_cache_index($cache_key, TRUE);
$msg_count = $this->_messagecount($mailbox);
$cache_count = count($cache_index);
// console("Cache check: $msg_count !== ".count($cache_index));
if ($cache_count==$msg_count)
{
// get highest index
$header = iil_C_FetchHeader($this->conn, $mailbox, "$msg_count");
$cache_uid = array_pop($cache_index);
// uids of highes message matches -> cache seems OK
if ($cache_uid == $header->uid)
return 1;
// cache is dirty
return -1;
}
// if cache count differs less that 10% report as dirty
else if (abs($msg_count - $cache_count) < $msg_count/10)
return -1;
else
return -2;
}
function get_message_cache($key, $from, $to, $sort_field, $sort_order)
{
$cache_key = "$key:$from:$to:$sort_field:$sort_order";
$db_header_fields = array('idx', 'uid', 'subject', 'from', 'to', 'cc', 'date', 'size');
if (!in_array($sort_field, $db_header_fields))
$sort_field = 'idx';
if ($this->caching_enabled && !isset($this->cache[$cache_key]))
{
$this->cache[$cache_key] = array();
$sql_result = $this->db->limitquery(
"SELECT idx, uid, headers
FROM ".get_table_name('messages')."
WHERE user_id=?
AND cache_key=?
ORDER BY ".$this->db->quoteIdentifier($sort_field)." ".
strtoupper($sort_order),
$from,
$to-$from,
$_SESSION['user_id'],
$key);
while ($sql_arr = $this->db->fetch_assoc($sql_result))
{
$uid = $sql_arr['uid'];
$this->cache[$cache_key][$uid] = unserialize($sql_arr['headers']);
}
}
return $this->cache[$cache_key];
}
function get_cached_message($key, $uid, $body=FALSE)
{
if (!$this->caching_enabled)
return FALSE;
$internal_key = '__single_msg';
if ($this->caching_enabled && (!isset($this->cache[$internal_key][$uid]) || $body))
{
$sql_select = "idx, uid, headers";
if ($body)
$sql_select .= ", body";
$sql_result = $this->db->query(
"SELECT $sql_select
FROM ".get_table_name('messages')."
WHERE user_id=?
AND cache_key=?
AND uid=?",
$_SESSION['user_id'],
$key,
$uid);
if ($sql_arr = $this->db->fetch_assoc($sql_result))
{
$headers = unserialize($sql_arr['headers']);
if (is_object($headers) && !empty($sql_arr['body']))
$headers->body = $sql_arr['body'];
$this->cache[$internal_key][$uid] = $headers;
}
}
return $this->cache[$internal_key][$uid];
}
function get_message_cache_index($key, $force=FALSE)
{
static $sa_message_index = array();
if (!empty($sa_message_index[$key]) && !$force)
return $sa_message_index[$key];
$sa_message_index[$key] = array();
$sql_result = $this->db->query(
"SELECT idx, uid
FROM ".get_table_name('messages')."
WHERE user_id=?
AND cache_key=?
ORDER BY idx ASC",
$_SESSION['user_id'],
$key);
while ($sql_arr = $this->db->fetch_assoc($sql_result))
$sa_message_index[$key][$sql_arr['idx']] = $sql_arr['uid'];
return $sa_message_index[$key];
}
function add_message_cache($key, $index, $headers)
{
$this->db->query(
"INSERT INTO ".get_table_name('messages')."
(user_id, del, cache_key, idx, uid, subject, ".$this->db->quoteIdentifier('from').", ".$this->db->quoteIdentifier('to').", cc, date, size, headers)
VALUES (?, 0, ?, ?, ?, ?, ?, ?, ?, ".$this->db->fromunixtime($headers->timestamp).", ?, ?)",
$_SESSION['user_id'],
$key,
$index,
$headers->uid,
$this->decode_header($headers->subject, TRUE),
$this->decode_header($headers->from, TRUE),
$this->decode_header($headers->to, TRUE),
$this->decode_header($headers->cc, TRUE),
$headers->size,
serialize($headers));
}
function remove_message_cache($key, $index)
{
$this->db->query(
"DELETE FROM ".get_table_name('messages')."
WHERE user_id=?
AND cache_key=?
AND idx=?",
$_SESSION['user_id'],
$key,
$index);
}
function clear_message_cache($key, $start_index=1)
{
$this->db->query(
"DELETE FROM ".get_table_name('messages')."
WHERE user_id=?
AND cache_key=?
AND idx>=?",
$_SESSION['user_id'],
$key,
$start_index);
}
/* --------------------------------
* encoding/decoding functions
* encoding/decoding methods
* --------------------------------*/
@ -986,9 +1266,15 @@ class rcube_imap
}
function decode_header($input)
function decode_header($input, $remove_quotes=FALSE)
{
return $this->decode_mime_string($input);
$str = $this->decode_mime_string($input);
if ($str{0}=='"' && $remove_quotes)
{
$str = str_replace('"', '', $str);
}
return $str;
}
@ -1094,6 +1380,7 @@ class rcube_imap
}
/* --------------------------------
* private methods
* --------------------------------*/
@ -1149,6 +1436,33 @@ class rcube_imap
}
// parse string or array of server capabilities and put them in internal array
function _parse_capability($caps)
{
if (!is_array($caps))
$cap_arr = explode(' ', $caps);
else
$cap_arr = $caps;
foreach ($cap_arr as $cap)
{
if ($cap=='CAPABILITY')
continue;
if (strpos($cap, '=')>0)
{
list($key, $value) = explode('=', $cap);
if (!is_array($this->capabilities[$key]))
$this->capabilities[$key] = array();
$this->capabilities[$key][] = $value;
}
else
$this->capabilities[$cap] = TRUE;
}
}
// subscribe/unsubscribe a list of mailboxes and update local cache
function _change_subscription($a_mboxes, $mode)
{

@ -238,6 +238,22 @@ class rcube_db
}
function format_date($timestamp)
{
switch($this->db_provider)
{
case 'mysqli':
case 'mysql':
return "FROM_UNIXTIME($timestamp)";
break;
case 'sqlite':
return "datetime('$timestamp')";
break;
default:
return date("Y-m-d H:i:s", $timestamp);
}
}
function _add_result($res, $query)
{
// sql error occured

@ -1185,99 +1185,6 @@ function send_future_expire_header()
}
// replace specials characters to a specific encoding type
function rep_specialchars_output($str, $enctype='', $mode='', $newlines=TRUE)
{
global $OUTPUT_TYPE, $CHARSET;
static $html_encode_arr, $js_rep_table, $rtf_rep_table, $xml_rep_table;
if (!$enctype)
$enctype = $GLOBALS['OUTPUT_TYPE'];
// convert nbsps back to normal spaces if not html
if ($enctype!='html')
$str = str_replace(chr(160), ' ', $str);
// encode for plaintext
if ($enctype=='text')
return str_replace("\r\n", "\n", $mode=='remove' ? strip_tags($str) : $str);
// encode for HTML output
if ($enctype=='html')
{
if (!$html_encode_arr)
{
if ($CHARSET=='ISO-8859-1')
{
$html_encode_arr = get_html_translation_table(HTML_ENTITIES);
$html_encode_arr[chr(128)] = '&euro;';
}
else
$html_encode_arr = get_html_translation_table(HTML_SPECIALCHARS);
unset($html_encode_arr['?']);
unset($html_encode_arr['&']);
}
$ltpos = strpos($str, '<');
$encode_arr = $html_encode_arr;
// don't replace quotes and html tags
if (($mode=='show' || $mode=='') && $ltpos!==false && strpos($str, '>', $ltpos)!==false)
{
unset($encode_arr['"']);
unset($encode_arr['<']);
unset($encode_arr['>']);
}
else if ($mode=='remove')
$str = strip_tags($str);
$out = strtr($str, $encode_arr);
return $newlines ? nl2br($out) : $out;
}
if ($enctype=='url')
return rawurlencode($str);
// if the replace tables for RTF, XML and JS are not yet defined
if (!$js_rep_table)
{
$js_rep_table = $rtf_rep_table = $xml_rep_table = array();
for ($c=160; $c<256; $c++) // can be increased to support more charsets
{
$hex = dechex($c);
$rtf_rep_table[Chr($c)] = "\\'$hex";
$xml_rep_table[Chr($c)] = "&#$c;";
if ($CHARSET=='ISO-8859-1')
$js_rep_table[Chr($c)] = sprintf("\u%s%s", str_repeat('0', 4-strlen($hex)), $hex);
}
$js_rep_table['"'] = sprintf("\u%s%s", str_repeat('0', 4-strlen(dechex(34))), dechex(34));
$xml_rep_table['"'] = '&quot;';
}
// encode for RTF
if ($enctype=='xml')
return strtr($str, $xml_rep_table);
// encode for javascript use
if ($enctype=='js')
return preg_replace(array("/\r\n/", '/"/', "/([^\\\])'/"), array('\n', '\"', "$1\'"), strtr($str, $js_rep_table));
// encode for RTF
if ($enctype=='rtf')
return preg_replace("/\r\n/", "\par ", strtr($str, $rtf_rep_table));
// no encoding given -> return original string
return $str;
}
function decode_specialchars($input, $charset='')
{
@ -1462,7 +1369,21 @@ function abbrevate_string($str, $maxlength, $place_holder='...')
return $str;
}
// delete all files within a folder
function clear_directory($dir_path)
{
$dir = @opendir($dir_path);
if(!$dir) return FALSE;
while ($file = readdir($dir))
if (strlen($file)>2)
unlink("$dir_path/$file");
closedir($dir);
return TRUE;
}
?>

@ -0,0 +1,71 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/include/rcube_sqlite.inc |
| |
| This file is part of the RoundCube Webmail client |
| Copyright (C) 2005, RoundCube Dev. - Switzerland |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Provide callback functions for sqlite that will emulate |
| sone MySQL functions |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
function rcube_sqlite_from_unixtime($timestamp)
{
$timestamp = trim($timestamp);
if (!preg_match("/^[0-9]+$/is", $timestamp))
$ret = strtotime($timestamp);
else
$ret = $timestamp;
$ret = date("Y-m-d H:i:s", $ret);
rcube_sqlite_debug("FROM_UNIXTIME ($timestamp) = $ret");
return $ret;
}
function rcube_sqlite_unix_timestamp($timestamp="")
{
$timestamp = trim($timestamp);
if (!$timestamp)
$ret = time();
else if (!preg_match("/^[0-9]+$/is", $timestamp))
$ret = strtotime($timestamp);
else
$ret = $timestamp;
rcube_sqlite_debug("UNIX_TIMESTAMP ($timestamp) = $ret");
return $ret;
}
function rcube_sqlite_now()
{
rcube_sqlite_debug("NOW() = ".date("Y-m-d H:i:s"));
return date("Y-m-d H:i:s");
}
function rcube_sqlite_md5($str)
{
return md5($str);
}
function rcube_sqlite_debug($str)
{
//console($str);
}
?>

@ -45,7 +45,7 @@ function sess_read($key)
if ($sql_arr = $DB->fetch_assoc($sql_result))
{
$SESS_CHANGED = $sql_arr['changed'];
$SESS_CHANGED = mktime(); //$sql_arr['changed'];
if (strlen($sql_arr['vars']))
return $sql_arr['vars'];
@ -59,7 +59,7 @@ function sess_read($key)
function sess_write($key, $vars)
{
global $DB;
$sql_result = $DB->query("SELECT 1
FROM ".get_table_name('session')."
WHERE sess_id=?",
@ -83,6 +83,8 @@ function sess_write($key, $vars)
$key,
$vars,
$_SERVER['REMOTE_ADDR']);
}
return TRUE;
@ -102,7 +104,9 @@ function sess_destroy($key)
$DB->query("DELETE FROM ".get_table_name('session')."
WHERE sess_id=?",
$key);
rcmail_clear_session_temp($key);
return TRUE;
}
@ -115,7 +119,7 @@ function sess_gc($maxlifetime)
// get all expired sessions
$sql_result = $DB->query("SELECT sess_id
FROM ".get_table_name('session')."
WHERE ".$DB->unixtimestamp('now()')."-".$DB->unixtimestamp('created')." > ?",
WHERE ".$DB->unixtimestamp('now()')."-".$DB->unixtimestamp('changed')." > ?",
$maxlifetime);
$a_exp_sessions = array();
@ -134,6 +138,10 @@ function sess_gc($maxlifetime)
WHERE sess_id IN ('".join("','", $a_exp_sessions)."')");
}
// remove session specific temp dirs
foreach ($a_exp_sessions as $key)
rcmail_clear_session_temp($key);
return TRUE;
}

@ -210,7 +210,7 @@ function rcube_webmail()
this.enable_command('logout', true);
// disable browser's contextmenus
//document.oncontextmenu = function(){ return false; }
// document.oncontextmenu = function(){ return false; }
// flag object as complete
this.loaded = true;
@ -286,6 +286,7 @@ function rcube_webmail()
return false;
//this.messageform = this.gui_objects.messageform;
var input_from = rcube_find_object('_from');
var input_to = rcube_find_object('_to');
var input_cc = rcube_find_object('_cc');
var input_bcc = rcube_find_object('_bcc');
@ -300,6 +301,10 @@ function rcube_webmail()
this.init_address_input_events(input_cc);
if (input_bcc)
this.init_address_input_events(input_bcc);
// add signature according to selected identity
if (input_from && input_from.type=='select-one')
this.change_identity(input_from);
if (input_to && input_to.value=='')
input_to.focus();
@ -461,9 +466,18 @@ function rcube_webmail()
// get the type of sorting
var a_sort = props.split('_');
var sort_col = a_sort[0];
var sort_order = a_sort[1].toUpperCase();
var sort_order = a_sort[1] ? a_sort[1].toUpperCase() : null;
var header;
// no sort order specified: toggle
if (sort_order==null)
{
if (this.env.sort_col==sort_col)
sort_order = this.env.sort_order=='ASC' ? 'DESC' : 'ASC';
else
sort_order = this.env.sort_order;
}
if (this.env.sort_col==sort_col && this.env.sort_order==sort_order)
break;
@ -478,7 +492,7 @@ function rcube_webmail()
this.env.sort_order = sort_order;
// reload message list
this.list_mailbox('', '', props);
this.list_mailbox('', '', sort_col+'_'+sort_order);
break;
case 'nextpage':
@ -805,7 +819,7 @@ function rcube_webmail()
break;
case 'delete-folder':
if (confirm('Do you really want to delete this folder?'))
if (confirm(this.get_label('deletefolderconfirm')))
this.delete_folder(props);
break;
@ -933,8 +947,8 @@ function rcube_webmail()
if (!this.in_selection_before)
{
var shift = this.check_shiftkey(e);
this.select(id, shift);
var ctrl = this.check_ctrlkey(e);
this.select(id, ctrl);
}
if (this.selection.length)
@ -951,7 +965,7 @@ function rcube_webmail()
// onmouseup-handler of message list row
this.click_row = function(e, id)
{
var shift = this.check_shiftkey(e);
var ctrl = this.check_ctrlkey(e);
// don't do anything (another action processed before)
if (this.dont_select)
@ -961,13 +975,13 @@ function rcube_webmail()
}
if (!this.drag_active && this.in_selection_before==id)
this.select(id, (shift && this.task!='settings'));
this.select(id, (ctrl && this.task!='settings'));
this.drag_start = false;
this.in_selection_before = false;
// row was double clicked
if (this.task=='mail' && this.list_rows && this.list_rows[id].clicked && !shift)
if (this.task=='mail' && this.list_rows && this.list_rows[id].clicked && !ctrl)
{
this.show_message(id);
return false;
@ -1332,6 +1346,38 @@ function rcube_webmail()
/*********************************************************/
/********* message compose methods *********/
/*********************************************************/
this.change_identity = function(obj)
{
if (!obj || !obj.options)
return false;
var id = obj.options[obj.selectedIndex].value;
var input_message = rcube_find_object('_message');
var message = input_message ? input_message.value : '';
// remove the 'old' signature
if (this.env.identity && this.env.signatures && this.env.signatures[this.env.identity])
{
var sig = this.env.signatures[this.env.identity];
if (p = message.lastIndexOf(sig))
message = message.substring(0, p-1) + message.substring(p+sig.length, message.length);
}
// add the new signature string
if (this.env.signatures && this.env.signatures[id])
{
var sig = this.env.signatures[id];
message += '\n'+sig;
}
if (input_message && message)
input_message.value = message;
this.env.identity = id;
};
this.show_attachment_form = function(a)
@ -1854,19 +1900,23 @@ function rcube_webmail()
{
if (folder)
{
for (var id in this.env.subscriptionrows)
if (this.env.subscriptionrows[id]==folder)
break;
var row;
if (id && (row = document.getElementById(id)))
row.style.display = 'none';
this.http_request('delete-folder', '_mboxes='+escape(folder));
}
};
this.remove_folder_row = function(folder)
{
for (var id in this.env.subscriptionrows)
if (this.env.subscriptionrows[id]==folder)
break;
var row;
if (id && (row = document.getElementById(id)))
row.style.display = 'none';
};
this.subscribe_folder = function(folder)
{
var form;
@ -2491,6 +2541,21 @@ function rcube_webmail()
return false;
}
// check if Shift-key is pressed on event
this.check_ctrlkey = function(e)
{
if(!e && window.event)
e = window.event;
if(bw.linux && bw.ns4 && e.modifiers)
return true;
else if (bw.mac)
return this.check_shiftkey(e);
else if((bw.ns4 && e.modifiers & Event.CTRL_MASK) || (e && e.ctrlKey))
return true;
else
return false;
}
this.get_mouse_pos = function(e)
{

@ -109,6 +109,7 @@ $labels['unread'] = 'Ungelesene';
$labels['compose'] = 'Neue Nachricht verfassen';
$labels['sendmessage'] = 'Nachricht jetzt senden';
$labels['addattachment'] = 'Datei anfügen';
$labels['charset'] = 'Zeichensatz';
$labels['attachments'] = 'Anhänge';
$labels['upload'] = 'Hochladen';
@ -121,7 +122,6 @@ $labels['high'] = 'Hoch';
$labels['highest'] = 'Höchste';
$labels['nosubject'] = '(kein Betreff)';
$labels['showimages'] = 'Bilder anzeigen';
@ -165,7 +165,7 @@ $labels['setdefault'] = 'Als Standard';
$labels['language'] = 'Sprache';
$labels['timezone'] = 'Zeitzone';
$labels['pagesize'] = 'Einträge pro Seite';
$labels['signature'] = 'Signatur';
$labels['folders'] = 'Ordner';
$labels['foldername'] = 'Ordnername';

@ -54,6 +54,8 @@ $messages['sendingfailed'] = 'Versand der Nachricht fehlgeschlagen';
$messages['errorsaving'] = 'Beim Speichern ist ein Fehler aufgetreten';
$messages['deletefolderconfirm'] = 'Wollen Sie diesen Ordner wirklich löschen?';
$messages['formincomplete'] = 'Das Formular wurde nicht vollständig ausgefüllt';
$messages['noemailwarning'] = 'Bitte geben Sie eine gültige E-Mail-Adresse ein';

@ -0,0 +1,182 @@
<?php
/*
+-----------------------------------------------------------------------+
| language/ee/labels.inc |
| |
| Language file of the RoundCube Webmail client |
| Copyright (C) 2005, RoundQube Dev. - Switzerland |
| Licensed under the GNU GPL |
| |
+-----------------------------------------------------------------------+
| Author: Üllar Pajus <yllar.pajus@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
$labels = array();
// login page
$labels['username'] = 'Kasutajanimi';
$labels['password'] = 'Parool';
$labels['server'] = 'Server';
$labels['login'] = 'Logi sisse';
// taskbar
$labels['logout'] = 'Logi välja';
$labels['mail'] = 'Postkast';
$labels['settings'] = 'Seaded';
$labels['addressbook'] = 'Aadressiraamat';
// mailbox names
$labels['inbox'] = 'Sissetulevad';
$labels['sent'] = 'Saadetud';
$labels['trash'] = 'Prügikast';
$labels['drafts'] = 'Ootel';
$labels['junk'] = 'Rämps';
// message listing
$labels['subject'] = 'Pealkiri';
$labels['from'] = 'Saatja';
$labels['to'] = 'Saaja';
$labels['cc'] = 'Koopia';
$labels['bcc'] = 'Bcc';
$labels['replyto'] = 'Vastus aadressile';
$labels['date'] = 'Kuupäev';
$labels['size'] = 'Suurus';
$labels['priority'] = 'Tähtsus';
$labels['organization'] = 'Organisatsioon';
// aliases
$labels['reply-to'] = $labels['replyto'];
$labels['mailboxlist'] = 'Kaustad';
$labels['messagesfromto'] = 'Kirjed $from kuni $to, kokku $count';
$labels['messagenrof'] = 'Kiri $nr, kokku $count';
$labels['moveto'] = 'liiguta kausta...';
$labels['download'] = 'lae arvutisse';
$labels['filename'] = 'Faili nimi';
$labels['filesize'] = 'Faili suurus';
$labels['preferhtml'] = 'Eelista HTMLi';
$labels['htmlmessage'] = 'HTML kirjad';
$labels['prettydate'] = 'Kenad kuupäevad';
$labels['addtoaddressbook'] = 'Lisa aadressiraamatusse';
// weekdays short
$labels['sun'] = 'P';
$labels['mon'] = 'E';
$labels['tue'] = 'T';
$labels['wed'] = 'K';
$labels['thu'] = 'N';
$labels['fri'] = 'R';
$labels['sat'] = 'L';
// weekdays long
$labels['sunday'] = 'Pühapäev';
$labels['monday'] = 'Esmaspäev';
$labels['tuesday'] = 'Teisipäev';
$labels['wednesday'] = 'Kolmapäev';
$labels['thursday'] = 'Neljapäev';
$labels['friday'] = 'Reede';
$labels['saturday'] = 'Laupäev';
$labels['today'] = 'Täna';
// toolbar buttons
$labels['writenewmessage'] = 'Kirjuta uus kiri';
$labels['replytomessage'] = 'Vasta kirjale';
$labels['replytoallmessage'] = 'Vasta saatjale ja teistele kirja saanutele';
$labels['forwardmessage'] = 'Edasta see kiri';
$labels['deletemessage'] = 'Liiguta kiri prügikasti';
$labels['printmessage'] = 'Trüki kiri';
$labels['previousmessages'] = 'Näita eelmisi kirju';
$labels['nextmessages'] = 'Näita järgmisi kirju';
$labels['backtolist'] = 'Tagasi kirjade nimekirja';
$labels['viewsource'] = 'Näita lähtekoodi';
$labels['select'] = 'Vali';
$labels['all'] = 'kõik';
$labels['none'] = 'mitte midagi';
$labels['unread'] = 'mitte loetud';
// message compose
$labels['compose'] = 'Koosta kiri';
$labels['sendmessage'] = 'Saada kiri kohe';
$labels['addattachment'] = 'Lisa fail';
$labels['attachments'] = 'Manused';
$labels['upload'] = 'Kinnita manus';
$labels['close'] = 'Sulge';
$labels['low'] = 'Madal';
$labels['lowest'] = 'Madalaim';
$labels['normal'] = 'Tavaline';
$labels['high'] = 'Kõrge';
$labels['highest'] = 'Kõrgeim';
$labels['nosubject'] = '(teema puudub)';
$labels['showimages'] = 'Näita pilte';
// address boook
$labels['name'] = 'Näidatav nimi';
$labels['firstname'] = 'Eesnimi';
$labels['surname'] = 'Perekonnanimi';
$labels['email'] = 'E-Mail';
$labels['addcontact'] = 'Lisa uus kontakt';
$labels['editcontact'] = 'Muuda kontakti';
$labels['edit'] = 'Muuda';
$labels['cancel'] = 'Katkesta';
$labels['save'] = 'Salvesta';
$labels['delete'] = 'Kustuta';
$labels['newcontact'] = 'Loo uus sissekanne';
$labels['deletecontact'] = 'Kustuta märgistatud kontaktid';
$labels['composeto'] = 'Kirjuta kiri';
$labels['contactsfromto'] = 'Kirjed $from kuni $to, kokku $count';
$labels['print'] = 'Trüki';
$labels['export'] = 'Ekspordi';
// settings
$labels['settingsfor'] = 'Kasutajaeelistused kontole';
$labels['preferences'] = 'Eelistused';
$labels['userpreferences'] = 'Kasutaja eelistused';
$labels['editpreferences'] = 'Muuda kasutaja eelistusi';
$labels['identities'] = 'Identiteedid';
$labels['manageidentities'] = 'Halda selle konto identiteete';
$labels['newidentity'] = 'Uus identiteet';
$labels['newitem'] = 'Uus sissekanne';
$labels['edititem'] = 'Muuda sissekannet';
$labels['setdefault'] = 'Muuda vaikeseadeks';
$labels['language'] = 'Keel';
$labels['timezone'] = 'Ajatsoon';
$labels['pagesize'] = 'Ridu lehe kohta';
$labels['folders'] = 'Kaustad';
$labels['foldername'] = 'Kausta nimi';
$labels['subscribed'] = 'Näitan';
$labels['create'] = 'Loo';
$labels['createfolder'] = 'Loo uus kaust';
$labels['deletefolder'] = 'Kustuta kaust';
$labels['managefolders'] = 'Manage folders';
$labels['sortby'] = 'Järjesta';
$labels['sortasc'] = 'Järjesta kasvavalt';
$labels['sortdesc'] = 'Järjesta kahanevalt';
?>

@ -0,0 +1,80 @@
<?php
/*
+-----------------------------------------------------------------------+
| language/ee/messages.inc |
| |
| Language file of the RoundCube Webmail client |
| Copyright (C) 2005, RoundCube Dev. - Switzerland |
| Licensed under the GNU GPL |
| |
+-----------------------------------------------------------------------+
| Author: Üllar Pajus <yllar.pajus@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
$messages = array();
$messages['loginfailed'] = 'Sisselogimine ebaõnnestus';
$messages['cookiesdisabled'] = 'Sinu veebilehitseja ei võta präänikuid vastu';
$messages['sessionerror'] = 'Sinu sessioon on aegunud või vigane';
$messages['imaperror'] = 'Ei õnnestunud IMAP serveriga ühendust luua';
$messages['nomessagesfound'] = 'Postkast paistab tühi olevat';
$messages['loggedout'] = 'Sinu sessioon on edukalt lõpetatud. Nägemiseni!';
$messages['mailboxempty'] = 'Postkast on tühi';
$messages['loading'] = 'Laen...';
$messages['loadingdata'] = 'Laen andmeid...';
$messages['sendingmessage'] = 'Saadan kirja...';
$messages['messagesent'] = 'Kiri edukalt saadetud';
$messages['successfullysaved'] = 'Edukalt salvestatud';
$messages['addedsuccessfully'] = 'Kontakt lisati edukalt aadressiraamatusse';
$messages['contactexists'] = 'Sama e-maili aadressiga kontakt on juba olemas';
$messages['blockedimages'] = 'Sinu privaatsuse kaitsmiseks on selles kirjas välised pildid blokeeritud.';
$messages['encryptedmessage'] = 'See on krüpteeritud kiri ja kahjuks pole seda võimalik näidata. Andestust!';
$messages['nocontactsfound'] = 'Ei leidnud ühtegi kontakti';
$messages['sendingfailed'] = 'Kirja saatmine ebaõnnestus';
$messages['errorsaving'] = 'Salvestamie ajal ilmnes viga';
$messages['errormoving'] = 'Ei suutnud seda kirja liigutada';
$messages['errordeleting'] = 'Ei suutnud seda kirja kustutada';
$messages['errordeleting'] = 'Ei suutnud seda kirja kustutada';
$messages['formincomplete'] = 'Vormi kõik väljad ei ole täidetud';
$messages['noemailwarning'] = 'Palun sisesta toimiv e-maili aadress';
$messages['nonamewarning'] = 'Palun sisesta nimi';
$messages['nopagesizewarning'] = 'Palun sisesta lehekülje suurus';
$messages['norecipientwarning'] = 'Palun sisesta vähemalt üks kirjasaaja';
$messages['nosubjectwarning'] = 'Väli "Pealkiri" on tühi. Soovid selle ära täita ?';
$messages['nobodywarning'] = 'Saadan selle kirja ilma tekstita ?';
?>

@ -109,6 +109,7 @@ $labels['unread'] = 'Unread';
$labels['compose'] = 'Compose a message';
$labels['sendmessage'] = 'Send the message now';
$labels['addattachment'] = 'Attach a file';
$labels['charset'] = 'Charset';
$labels['attachments'] = 'Attachments';
$labels['upload'] = 'Upload';
@ -121,7 +122,6 @@ $labels['high'] = 'High';
$labels['highest'] = 'Highest';
$labels['nosubject'] = '(no subject)';
$labels['showimages'] = 'Display images';
@ -165,7 +165,7 @@ $labels['setdefault'] = 'Set default';
$labels['language'] = 'Language';
$labels['timezone'] = 'Time zone';
$labels['pagesize'] = 'Rows per page';
$labels['signature'] = 'Signature';
$labels['folders'] = 'Folders';
$labels['foldername'] = 'Folder name';

@ -60,13 +60,13 @@ $messages['errormoving'] = 'Could not move the message';
$messages['errordeleting'] = 'Could not delete the message';
$messages['errordeleting'] = 'Could not delete the message';
$messages['deletefolderconfirm'] = 'Do you really want to delete this folder?';
$messages['formincomplete'] = 'The form was not completely filled out';
$messages['formincomplete'] = 'The form was not completely filled out';
$messages['noemailwarning'] = 'Please enter a valid email address';
$messages['noemailwarning'] = 'Please enter a valid email address';
$messages['nonamewarning'] = 'Please enter a name';
$messages['nonamewarning'] = 'Please enter a name';
$messages['nopagesizewarning'] = 'Please enter a page size';

@ -120,6 +120,7 @@ $labels['normal'] = 'Normal';
$labels['high'] = 'High';
$labels['highest'] = 'Highest';
$labels['nosubject'] = '(no subject)';
$labels['showimages'] = 'Display images';
@ -163,7 +164,7 @@ $labels['setdefault'] = 'Set default';
$labels['language'] = 'Language';
$labels['timezone'] = 'Time zone';
$labels['pagesize'] = 'Rows per page';
$labels['signature'] = 'Signature';
$labels['folders'] = 'Folders';
$labels['foldername'] = 'Folder name';

@ -32,6 +32,7 @@
'da' => 'Dansk',
'de' => 'Deutsch',
'es' => 'Espa&ntilde;ol',
'ee' => 'Estonian',
'fr' => 'Fran&ccedil;ais',
'ga' => 'Galician',
'el' => 'Greek',

@ -24,7 +24,7 @@ $REMOTE_REQUEST = TRUE;
if ($_GET['_cid'])
{
$DB->query("UPDATE ".get_table_name('contacts')."
SET del='1'
SET del=1
WHERE user_id=?
AND contact_id IN (".$_GET['_cid'].")",
$_SESSION['user_id']);
@ -40,7 +40,7 @@ if ($_GET['_cid'])
// count contacts for this user
$sql_result = $DB->query("SELECT COUNT(contact_id) AS rows
FROM ".get_table_name('contacts')."
WHERE del<>'1'
WHERE del<>1
AND user_id=?",
$_SESSION['user_id']);
@ -60,7 +60,7 @@ if ($_GET['_cid'])
// get contacts from DB
$sql_result = $DB->limitquery("SELECT * FROM ".get_table_name('contacts')."
WHERE del<>'1'
WHERE del<>1
AND user_id=?
ORDER BY name",
$start_row,

@ -26,7 +26,7 @@ if (($_GET['_cid'] || $_POST['_cid']) && $_action=='edit')
$DB->query("SELECT * FROM ".get_table_name('contacts')."
WHERE contact_id=?
AND user_id=?
AND del<>'1'",
AND del<>1",
$cid,
$_SESSION['user_id']);

@ -43,7 +43,7 @@ function rcmail_contacts_list($attrib)
// count contacts for this user
$sql_result = $DB->query("SELECT COUNT(contact_id) AS rows
FROM ".get_table_name('contacts')."
WHERE del<>'1'
WHERE del<>1
AND user_id=?",
$_SESSION['user_id']);
@ -56,7 +56,7 @@ function rcmail_contacts_list($attrib)
// get contacts from DB
$sql_result = $DB->limitquery("SELECT * FROM ".get_table_name('contacts')."
WHERE del<>'1'
WHERE del<>1
AND user_id= ?
ORDER BY name",
$start_row,
@ -173,7 +173,7 @@ function rcmail_get_rowcount_text($max=NULL)
if ($max===NULL)
{
$sql_result = $DB->query("SELECT 1 FROM ".get_table_name('contacts')."
WHERE del<>'1'
WHERE del<>1
AND user_id=?",
$_SESSION['user_id']);

@ -24,7 +24,7 @@ $REMOTE_REQUEST = TRUE;
// count contacts for this user
$sql_result = $DB->query("SELECT COUNT(contact_id) AS rows
FROM ".get_table_name('contacts')."
WHERE del<>'1'
WHERE del<>1
AND user_id=?",
$_SESSION['user_id']);
@ -40,7 +40,7 @@ $start_row = ($CONTACTS_LIST['page']-1) * $CONFIG['pagesize'];
// get contacts from DB
$sql_result = $DB->limitquery("SELECT * FROM ".get_table_name('contacts')."
WHERE del<>'1'
WHERE del<>1
AND user_id=?
ORDER BY name",
$start_row,

@ -52,7 +52,7 @@ if ($_POST['_cid'])
SET changed=now(), ".join(', ', $a_write_sql)."
WHERE contact_id=?
AND user_id=?
AND del<>'1'",
AND del<>1",
$_POST['_cid'],
$_SESSION['user_id']);
@ -73,7 +73,7 @@ if ($_POST['_cid'])
$sql_result = $DB->query("SELECT * FROM ".get_table_name('contacts')."
WHERE contact_id=?
AND user_id=?
AND del<>'1'",
AND del<>1",
$_POST['_cid'],
$_SESSION['user_id']);
@ -109,7 +109,7 @@ else
$sql_result = $DB->query("SELECT 1 FROM ".get_table_name('contacts')."
WHERE user_id=?
AND email=?
AND del<>'1'",
AND del<>1",
$_SESSION['user_id'],
$_POST['_email']);
@ -134,11 +134,11 @@ else
if (sizeof($a_insert_cols))
{
$DB->query("INSERT INTO ".get_table_name('contacts')."
(user_id, changed, ".join(', ', $a_insert_cols).")
VALUES (?, now(), ".join(', ', $a_insert_values).")",
(user_id, changed, del, ".join(', ', $a_insert_cols).")
VALUES (?, now(), 0, ".join(', ', $a_insert_values).")",
$_SESSION['user_id']);
$insert_id = $DB->insert_id();
$insert_id = $DB->insert_id(get_sequence_name('contacts'));
}
if ($insert_id)

@ -26,7 +26,7 @@ if ($_GET['_cid'] || $_POST['_cid'])
$DB->query("SELECT * FROM ".get_table_name('contacts')."
WHERE contact_id=?
AND user_id=?
AND del<>'1'",
AND del<>1",
$cid,
$_SESSION['user_id']);

@ -32,7 +32,7 @@ if ($_GET['_address'])
$sql_result = $DB->query("SELECT 1 FROM ".get_table_name('contacts')."
WHERE user_id=?
AND email=?
AND del<>'1'",
AND del<>1",
$_SESSION['user_id'],$contact['mailto']);
// contact entry with this mail address exists
@ -42,13 +42,13 @@ if ($_GET['_address'])
else if ($contact['mailto'])
{
$DB->query("INSERT INTO ".get_table_name('contacts')."
(user_id, changed, name, email)
VALUES (?, now(), ?, ?)",
(user_id, changed, del, name, email)
VALUES (?, now(), 0, ?, ?)",
$_SESSION['user_id'],
$contact['name'],
$contact['mailto']);
$added = $DB->insert_id();
$added = $DB->insert_id(get_sequence_name('contacts'));
}
}

@ -88,50 +88,20 @@ function rcmail_compose_headers($attrib)
switch ($part)
{
case 'from':
// pass the following attributes to the form class
$field_attrib = array('name' => '_from');
foreach ($attrib as $attr => $value)
if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex')))
$field_attrib[$attr] = $value;
// get this user's identities
$sql_result = $DB->query("SELECT identity_id, name, email
FROM ".get_table_name('identities')." WHERE user_id=?
AND del<>'1'
ORDER BY ".$DB->quoteIdentifier('default')." DESC, name ASC",
$_SESSION['user_id']);
if ($DB->num_rows($sql_result))
{
$select_from = new select($field_attrib);
while ($sql_arr = $DB->fetch_assoc($sql_result))
$select_from->add(format_email_recipient($sql_arr['email'], $sql_arr['name']), $sql_arr['identity_id']);
$out = $select_from->show($_POST['_from']);
}
else
{
$input_from = new textfield($field_attrib);
$out = $input_from->show($_POST['_from']);
}
if ($form_start)
$out = $form_start.$out;
return $out;
return rcmail_compose_header_from($attrib);
case 'to':
$fname = '_to';
$header = 'to';
// we have contact id's as get parameters
if (!empty($_GET['_to']) && preg_match('/[0-9]+,?/', $_GET['_to']))
if (!empty($_GET['_to']) && preg_match('/^([0-9]+,?)+$/', $_GET['_to']))
{
$a_recipients = array();
$sql_result = $DB->query("SELECT name, email
FROM ".get_table_name('contacts')." WHERE user_id=?
AND del<>'1'
FROM ".get_table_name('contacts')."
WHERE user_id=?
AND del<>1
AND contact_id IN (".$_GET['_to'].")",
$_SESSION['user_id']);
@ -229,71 +199,91 @@ function rcmail_compose_headers($attrib)
}
/*function rcube_compose_headers($attrib)
{
global $CONFIG, $OUTPUT;
list($form_start, $form_end) = get_form_tags($attrib);
// allow the following attributes to be added to the headers table
$attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border'));
$labels = array();
$labels['from'] = rcube_label('from');
$labels['to'] = rcube_label('to');
$labels['cc'] = rcube_label('cc');
$labels['bcc'] = rcube_label('bcc');
$labels['replyto'] = rcube_label('replyto');
$input_from = new textfield(array('name' => '_from', 'size' => 30));
$input_to = new textfield(array('name' => '_to', 'size' => 30));
$input_cc = new textfield(array('name' => '_cc', 'size' => 30));
$input_bcc = new textfield(array('name' => '_bcc', 'size' => 30));
$input_replyto = new textfield(array('name' => '_replyto', 'size' => 30));
$fields = array();
$fields['from'] = $input_from->show($_POST['_from']);
$fields['to'] = $input_to->show($_POST['_to']);
$fields['cc'] = $input_cc->show($_POST['_cc']);
$fields['bcc'] = $input_bcc->show($_POST['_bcc']);
$fields['replyto'] = $input_replyto->show($_POST['_replyto']);
$out = <<<EOF
$form_start
<table$attrib_str><tr>
<td class="title">$labels[from]</td>
<td>$fields[from]</td>
</tr><tr>
<td class="title">$labels[to]</td>
<td>$fields[to]</td>
</tr><tr>
function rcmail_compose_header_from($attrib)
{
global $IMAP, $REPLY_MESSAGE, $DB, $OUTPUT, $JS_OBJECT_NAME;
// pass the following attributes to the form class
$field_attrib = array('name' => '_from');
foreach ($attrib as $attr => $value)
if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex')))
$field_attrib[$attr] = $value;
// extract all recipients of the reply-message
$a_recipients = array();
if ($REPLY_MESSAGE && is_object($REPLY_MESSAGE['headers']))
{
$a_to = $IMAP->decode_address_list($REPLY_MESSAGE['headers']->to);
foreach ($a_to as $addr)
{
if (!empty($addr['mailto']))
$a_recipients[] = $addr['mailto'];
}
<td class="title">$labels[cc]</td>
<td>$fields[cc]</td>
if (!empty($REPLY_MESSAGE['headers']->cc))
{
$a_cc = $IMAP->decode_address_list($REPLY_MESSAGE['headers']->cc);
foreach ($a_cc as $addr)
{
if (!empty($addr['mailto']))
$a_recipients[] = $addr['mailto'];
}
}
}
</tr><tr>
// get this user's identities
$sql_result = $DB->query("SELECT identity_id, name, email, signature
FROM ".get_table_name('identities')."
WHERE user_id=?
AND del<>1
ORDER BY ".$DB->quoteIdentifier('standard')." DESC, name ASC",
$_SESSION['user_id']);
if ($DB->num_rows($sql_result))
{
$from_id = 0;
$a_signatures = array();
$field_attrib['onchange'] = "$JS_OBJECT_NAME.change_identity(this)";
$select_from = new select($field_attrib);
while ($sql_arr = $DB->fetch_assoc($sql_result))
{
$select_from->add(format_email_recipient($sql_arr['email'], $sql_arr['name']), $sql_arr['identity_id']);
<td class="title">$labels[bcc]</td>
<td>$fields[bcc]</td>
// add signature to array
if (!empty($sql_arr['signature']))
$a_signatures[$sql_arr['identity_id']] = $sql_arr['signature'];
// set identity if it's one of the reply-message recipients
if (in_array($sql_arr['email'], $a_recipients))
$from_id = $sql_arr['identity_id'];
}
</tr><tr>
// overwrite identity selection with post parameter
if (isset($_POST['_from']))
$from_id = $_POST['_from'];
<td class="title">$labels[replyto]</td>
<td>$fields[replyto]</td>
$out = $select_from->show($from_id);
</tr></table>
$form_end
EOF;
// add signatures to client
$OUTPUT->add_script(sprintf("%s.set_env('signatures', %s);", $JS_OBJECT_NAME, array2js($a_signatures)));
}
else
{
$input_from = new textfield($field_attrib);
$out = $input_from->show($_POST['_from']);
}
if ($form_start)
$out = $form_start.$out;
return $out;
return $out;
}
*/
function rcmail_compose_body($attrib)
{
@ -360,6 +350,14 @@ function rcmail_create_reply_body($body)
$pefix = sprintf("\n\n\nOn %s, %s wrote:\n",
$REPLY_MESSAGE['headers']->date,
$IMAP->decode_header($REPLY_MESSAGE['headers']->from));
// try to remove the signature
if ($sp = strrpos($body, '--'))
{
if ($body{$sp+3}==' ' || $body{$sp+3}=="\n" || $body{$sp+3}=="\r")
$body = substr($body, 0, $sp-1);
}
return $pefix.$body;
}
@ -596,7 +594,7 @@ function rcmail_charset_pulldown($selected='ISO-8859-1')
$sql_result = $DB->query("SELECT name, email
FROM ".get_table_name('contacts')." WHERE user_id=?
AND del<>'1'",$_SESSION['user_id']);
AND del<>1",$_SESSION['user_id']);
if ($DB->num_rows($sql_result))
{

@ -305,26 +305,41 @@ function rcmail_message_list($attrib)
// make sort links
$sort = '';
if (in_array($col, $a_sort_cols) && (!empty($attrib['sortdescbutton']) || !empty($attrib['sortascbutton'])))
if ($IMAP->get_capability('sort') && in_array($col, $a_sort_cols))
{
$sort = '&nbsp;&nbsp;';
// asc link
if (!empty($attrib['sortascbutton']))
// have buttons configured
if (!empty($attrib['sortdescbutton']) || !empty($attrib['sortascbutton']))
{
$sort .= rcube_button(array('command' => 'sort',
'prop' => $col.'_ASC',
'image' => $attrib['sortascbutton'],
'title' => 'sortasc'));
}
$sort = '&nbsp;&nbsp;';
// asc link
if (!empty($attrib['sortascbutton']))
{
$sort .= rcube_button(array('command' => 'sort',
'prop' => $col.'_ASC',
'image' => $attrib['sortascbutton'],
'align' => 'absmiddle',
'title' => 'sortasc'));
}
// desc link
if (!empty($attrib['sortdescbutton']))
// desc link
if (!empty($attrib['sortdescbutton']))
{
$sort .= rcube_button(array('command' => 'sort',
'prop' => $col.'_DESC',
'image' => $attrib['sortdescbutton'],
'align' => 'absmiddle',
'title' => 'sortdesc'));
}
}
// just add a link tag to the header
else
{
$sort .= rcube_button(array('command' => 'sort',
'prop' => $col.'_DESC',
'image' => $attrib['sortdescbutton'],
'title' => 'sortdesc'));
$col_name = sprintf('<a href="./#sort" onclick="return %s.command(\'sort\',\'%s\',this)" title="%s">%s</a>',
$JS_OBJECT_NAME,
$col,
rcube_label('sortby'),
$col_name);
}
}
@ -1128,20 +1143,76 @@ function rcmail_first_text_part($message_parts)
// get source code of a specific message and cache it
function rcmail_message_source($uid)
{
global $IMAP, $DB;
global $IMAP, $DB, $CONFIG;
// get message ID if uid is given
$cache_key = $IMAP->mailbox.'.msg';
$cached = $IMAP->get_cached_message($cache_key, $uid, FALSE);
// message is cached in database
if ($cached && !empty($cached->body))
return $cached->body;
if (!$cached)
$headers = $IMAP->get_headers($uid);
else
$headers = &$cached;
// get message ID if uid is given
$headers = $IMAP->get_headers($uid);
$message_id = $headers->messageID;
// get cached message source
$msg_source = rcube_read_cache($message_id);
$temp_dir = $CONFIG['temp_dir'].(!eregi('\/$', $CONFIG['temp_dir']) ? '/' : '');
$cache_dir = $temp_dir.$_SESSION['client_id'];
$cache_path = $cache_dir.'/'.$message_id;
// message is cached in temp dir
if (is_dir($cache_dir) && is_file($cache_path))
{
if ($fp = fopen($cache_path, 'r'))
{
$msg_source = fread($fp, filesize($cache_path));
fclose($fp);
return $msg_source;
}
}
// get message from server
$msg_source = $IMAP->get_raw_body($uid);
// let's cache the message body within the database
if ($CONFIG['enable_caching'] && $cached && ($CONFIG['db_max_length'] -300) > $headers->size)
{
$DB->query("UPDATE ".get_table_name('messages')."
SET body=?
WHERE user_id=?
AND cache_key=?
AND uid=?",
$msg_source,
$_SESSION['user_id'],
$cache_key,
$uid);
return $msg_source;
}
// create dir for caching
if (!is_dir($cache_dir))
$dir = mkdir($cache_dir);
else
$dir = true;
// get message from server and cache it
if (!$msg_source)
// attempt to write a file with the message body
if ($dir && ($fp = fopen($cache_path, 'w')))
{
fwrite($fp, $msg_source);
fclose($fp);
}
else
{
$msg_source = $IMAP->get_raw_body($uid);
rcube_write_cache($message_id, $msg_source, TRUE);
raise_error(array('code' => 403, 'type' => 'php', 'line' => __LINE__, 'file' => __FILE__,
'message' => "Failed to write to temp dir"), TRUE, FALSE);
}
return $msg_source;

@ -46,7 +46,7 @@ function rcmail_get_identity($id)
FROM ".get_table_name('identities')."
WHERE identity_id=?
AND user_id=?
AND del<>'1'",
AND del<>1",
$id,$_SESSION['user_id']);
if ($DB->num_rows($sql_result))
@ -78,8 +78,8 @@ if (empty($CHARSET))
$CHARSET = 'ISO-8859-1';
$mailto_regexp = array('/,\s*[\r\n]+/', '/[\r\n]+/', '/,\s*$/m');
$mailto_replace = array(' ', ', ', '');
$mailto_regexp = array('/[,;]\s*[\r\n]+/', '/[\r\n]+/', '/[,;]\s*$/m');
$mailto_replace = array(', ', ', ', '');
// repalce new lines and strip ending ', '
$mailto = preg_replace($mailto_regexp, $mailto_replace, stripslashes($_POST['_to']));
@ -175,13 +175,16 @@ if (is_array($_FILES['_attachments']['tmp_name']))
foreach ($_FILES['_attachments']['tmp_name'] as $i => $filepath)
$MAIL_MIME->addAttachment($filepath, $files['type'][$i], $files['name'][$i], TRUE);
$message_charset = isset($_POST['_charset']) ? $_POST['_charset'] : $CHARSET;
// encoding settings for mail composing
$message_param = array('text_encoding' => '7bit',
'html_encoding' => 'quoted-printable',
'head_encoding' => 'quoted-printable',
'head_charset' => $CHARSET,
'html_charset' => $CHARSET,
'text_charset' => $CHARSET);
'head_charset' => $message_charset,
'html_charset' => $message_charset,
'text_charset' => $message_charset);
// compose message body and get headers
$msg_body = $MAIL_MIME->get($message_param);

@ -24,7 +24,7 @@ $REMOTE_REQUEST = $_GET['_remote'] ? TRUE : FALSE;
if ($_GET['_iid'])
{
$DB->query("UPDATE ".get_table_name('identities')."
SET del='1'
SET del=1
WHERE user_id=?
AND identity_id IN (".$_GET['_iid'].")",
$_SESSION['user_id']);

@ -25,7 +25,7 @@ if (($_GET['_iid'] || $_POST['_iid']) && $_action=='edit-identity')
$DB->query("SELECT * FROM ".get_table_name('identities')."
WHERE identity_id=?
AND user_id=?
AND del<>'1'",
AND del<>1",
$id,
$_SESSION['user_id']);
@ -63,7 +63,8 @@ function rcube_identity_form($attrib)
'organization' => array('type' => 'text'),
'reply-to' => array('type' => 'text', 'label' => 'replyto'),
'bcc' => array('type' => 'text'),
'default' => array('type' => 'checkbox', 'label' => 'setdefault'));
'signature' => array('type' => 'textarea'),
'standard' => array('type' => 'checkbox', 'label' => 'setdefault'));
// a specific part is requested

@ -146,9 +146,9 @@ function rcmail_identities_list($attrib)
// get contacts from DB
$sql_result = $DB->query("SELECT * FROM ".get_table_name('identities')."
WHERE del<>'1'
WHERE del<>1
AND user_id=?
ORDER BY ".$DB->quoteIdentifier('default')." DESC, name ASC",
ORDER BY standard DESC, name ASC",
$_SESSION['user_id']);

@ -69,10 +69,15 @@ else if ($_action=='create-folder')
else if ($_action=='delete-folder')
{
if (strlen($_GET['_mboxes']))
$IMAP->delete_mailbox(explode(',', $_GET['_mboxes']));
$deleted = $IMAP->delete_mailbox(explode(',', $_GET['_mboxes']));
if ($_GET['_remote'])
rcube_remote_response('// deleted');
if ($_GET['_remote'] && $deleted)
rcube_remote_response(sprintf("this.remove_folder_row('%s')", rep_specialchars_output($_GET['_mboxes'], 'js')));
else if ($_GET['_remote'])
{
$commands = show_message('errorsaving', 'error');
rcube_remote_response($commands);
}
}
@ -174,5 +179,9 @@ function rcube_create_folder_form($attrib)
}
// add some labels to client
rcube_add_label('deletefolderconfirm');
parse_template('managefolders');
?>

@ -19,7 +19,7 @@
*/
$a_save_cols = array('name', 'email', 'organization', 'reply-to', 'bcc', 'default');
$a_save_cols = array('name', 'email', 'organization', 'reply-to', 'bcc', 'standard', 'signature');
// check input
@ -51,7 +51,7 @@ if ($_POST['_iid'])
SET ".join(', ', $a_write_sql)."
WHERE identity_id=?
AND user_id=?
AND del<>'1'",
AND del<>1",
$_POST['_iid'],
$_SESSION['user_id']);
@ -64,10 +64,10 @@ if ($_POST['_iid'])
// mark all other identities as 'not-default'
$DB->query("UPDATE ".get_table_name('identities')."
SET ".$DB->quoteIdentifier('default')."='0'
SET ".$DB->quoteIdentifier('standard')."='0'
WHERE user_id=?
AND identity_id<>?
AND del<>'1'",
AND del<>1",
$_SESSION['user_id'],
$_POST['_iid']);
@ -106,8 +106,8 @@ else
(user_id, ".join(', ', $a_insert_cols).")
VALUES (?, ".join(', ', $a_insert_values).")",
$_SESSION['user_id']);
$insert_id = $DB->insert_id();
$insert_id = $DB->insert_id(get_sequence_name('identities'));
}
if ($insert_id)

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 B

@ -75,9 +75,10 @@
position: absolute;
top: 60px;
right: 40px;
width: 200px;
width: 220px;
height: 20px;
text-align: right;
white-space: nowrap;
}
#messagecountbar span
@ -332,6 +333,26 @@ body.messagelist
background-image: url(images/listheader_dark.gif);
}
#messagelist thead tr td.sortedASC a
{
background: url(images/sort_asc.gif) top right no-repeat;
}
#messagelist thead tr td.sortedDESC a
{
background: url(images/sort_desc.gif) top right no-repeat;
}
#messagelist thead tr td a,
#messagelist thead tr td a:hover
{
display: block;
width: auto !important;
width: 100%;
color: #333333;
text-decoration: none;
}
#messagelist tbody tr td
{
height: 16px !important;
@ -645,9 +666,10 @@ div.message-part pre
#compose-body
{
margin-top: 10px;
margin-bottom: 5px;
width: 99% !important;
width: 95%;
height: 95%;
height: 90%;
min-height: 300px;
font-size: 9pt;
font-family: "Courier New", Courier, monospace;
@ -702,4 +724,3 @@ div.message-part pre
margin-top: 8px;
}

@ -40,7 +40,7 @@ function fixImage() {
element.src = blankSrc;
// set filter
element.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" +
src + "',sizingMethod='scale')";
src + "',sizingMethod='crop')";
}
else {
// remove filter

@ -87,8 +87,9 @@ function rcmail_toggle_display(id)
</tr><tr>
<td style="width:100%; height:100%; vertical-align:top;">
<roundcube:object name="composeBody" id="compose-body" form="form" cols="80" rows="20" warp="virtual" tabindex="7" />
<td style="width:100%; height:95%; vertical-align:top;">
<roundcube:object name="composeBody" id="compose-body" form="form" cols="80" rows="20" warp="virtual" tabindex="7" /><br />
<roundcube:label name="charset" />:&nbsp;<roundcube:object name="charsetSelector" tabindex="8" />
</td>
</tr></table>

@ -37,9 +37,7 @@
messageIcon="/images/icons/dot.png"
unreadIcon="/images/icons/unread.png"
repliedIcon="/images/icons/replied.png"
attachmentIcon="/images/icons/attachment.png"
sortDescButton="/images/buttons/up_arrow.png"
sortAscButton="/images/buttons/down_arrow.png" />
attachmentIcon="/images/icons/attachment.png" />
</div>
<div id="listcontrols">

Loading…
Cancel
Save