Changeset 1cded85 in github
- Timestamp:
- Dec 3, 2005 11:54:12 AM (7 years ago)
- Branches:
- master, HEAD, courier-fix, dev-browser-capabilities, pdo, release-0.6, release-0.7, release-0.8
- Children:
- 31b2cee
- Parents:
- 5bc8cb66
- Files:
-
- 5 added
- 43 edited
-
CHANGELOG (modified) (2 diffs)
-
INSTALL (modified) (2 diffs)
-
SQL/mysql.initial.sql (modified) (4 diffs)
-
SQL/mysql.update.sql (modified) (1 diff)
-
SQL/postgres.initial.sql (modified) (5 diffs)
-
SQL/sqlite.initial.sql (modified) (5 diffs)
-
UPGRADING (modified) (7 diffs)
-
config/db.inc.php.dist (modified) (3 diffs)
-
config/main.inc.php.dist (modified) (1 diff)
-
index.php (modified) (3 diffs)
-
program/include/cache.inc (modified) (2 diffs)
-
program/include/main.inc (modified) (11 diffs)
-
program/include/rcube_db.inc (modified) (2 diffs)
-
program/include/rcube_imap.inc (modified) (28 diffs)
-
program/include/rcube_mdb2.inc (modified) (1 diff)
-
program/include/rcube_shared.inc (modified) (2 diffs)
-
program/include/rcube_sqlite.inc (added)
-
program/include/session.inc (modified) (6 diffs)
-
program/js/app.js (modified) (13 diffs)
-
program/localization/de/labels.inc (modified) (3 diffs)
-
program/localization/de/messages.inc (modified) (1 diff)
-
program/localization/ee/labels.inc (added)
-
program/localization/ee/messages.inc (added)
-
program/localization/en/labels.inc (modified) (3 diffs)
-
program/localization/en/messages.inc (modified) (1 diff)
-
program/localization/en_GB/labels.inc (modified) (2 diffs)
-
program/localization/index.inc (modified) (1 diff)
-
program/steps/addressbook/delete.inc (modified) (3 diffs)
-
program/steps/addressbook/edit.inc (modified) (1 diff)
-
program/steps/addressbook/func.inc (modified) (3 diffs)
-
program/steps/addressbook/list.inc (modified) (2 diffs)
-
program/steps/addressbook/save.inc (modified) (4 diffs)
-
program/steps/addressbook/show.inc (modified) (1 diff)
-
program/steps/mail/addcontact.inc (modified) (2 diffs)
-
program/steps/mail/compose.inc (modified) (4 diffs)
-
program/steps/mail/func.inc (modified) (2 diffs)
-
program/steps/mail/sendmail.inc (modified) (3 diffs)
-
program/steps/settings/delete_identity.inc (modified) (1 diff)
-
program/steps/settings/edit_identity.inc (modified) (2 diffs)
-
program/steps/settings/func.inc (modified) (1 diff)
-
program/steps/settings/manage_folders.inc (modified) (2 diffs)
-
program/steps/settings/save_identity.inc (modified) (4 diffs)
-
skins/default/images/sort_asc.gif (added)
-
skins/default/images/sort_desc.gif (added)
-
skins/default/mail.css (modified) (4 diffs)
-
skins/default/pngbehavior.htc (modified) (1 diff)
-
skins/default/templates/compose.html (modified) (1 diff)
-
skins/default/templates/mail.html (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
CHANGELOG
r4b0f65a r1cded85 2 2 --------------------------- 3 3 4 2005/ 08/114 2005/12/03 5 5 ---------- 6 - Write list header to client even if list is empty 7 - Add functions "select all", "select none" to message list 8 - Improved filter for HTML messages to remove potentially malicious tags (script, iframe, object) and event handlers. 9 - Buttons for next/previous message in view mode 10 - Add new created contact to list and show confirmation status 11 - Added folder management (subscribe/create/delete) 12 - Log message sending (SMTP log) 13 - Grant access for Camino browser 14 - Added German translation 15 16 17 2005/08/20 18 ---------- 19 - Improved cacheing of mailbox messagecount 20 - Fixed javascript bug when creating a new message folder 21 - Fixed javascript bugs #1260990 and #1260992: folder selection 22 - Make Trash folder configurable 23 - Auto create folders Inbox, Sent and Trash (if configured) 24 - Support for IMAP root folder 25 - Added support fot text/enriched messages 26 - Make list of special mailboxes configurable 27 28 29 2005/10/07 30 ---------- 31 - Added French, Italian, Spanish, Danish, Dutch translation 32 - Clarified license (Bug #1305966) 33 - Fixed PHP warnings (Bug #1299403) 34 - Fixed english translation (Bug #1295406) 35 - Fixed bug #1290833: Last character of email not seen 36 - Fixed bug #1292199 when creating new user 37 - Allow more browsers (Bug #1285101) 38 - Added setting for showing pretty dates 39 - Added support for SQLite database 40 - Make use of message caching configurable 41 - Also add attachments when forwarding a message 42 - Long folder names will not flow over message list (Bug #1267232) 43 - Show nested mailboxes hieracically 44 - Enable IMAPS by host 45 46 47 2005/10/20 48 ---------- 49 - Added Swedish, Latvian, Portuguese and Catalan translation 50 - Make SMTP auth method configurable 51 - Make mailboxlist scrollable (Bug #1326372) 52 - Fixed SSL support 53 - Improved support for Courier IMAP (root folder and delimiter issues) 54 - Moved taskbar from bottom to top 55 - Added 'session_lifetime' parameter 56 - Fixed wrong unread count when deleting message (Bug #1332434) 57 - Srip tags when creating a new folder (Bug #1332084) 58 - Translate HTML tags in message headers (Bug #1330134) 59 - Correction in German translation (Bug #1329434) 60 - Display folder names with special chars correctly (Bug #1330157) 61 62 63 2005/11/18 64 ---------- 65 - Added Finnish, Romanian, Polish, Czech, British, Norwegian, Greek, Russian and Chinese translation 6 - Added Finnish, Romanian, Polish, Czech, British, Norwegian, Greek, Russian, Estonian and Chinese translation 66 7 - Get IMAP server capabilities in array 67 8 - Check for NAMESPACE capability before sending command … … 86 27 - Make delimiter for message headers configurable 87 28 - Add generic footer to sent messages 29 - Choose the rigt identity when replying 30 - Remove signature when replying (Request #1333167) 31 - Signatures for each identity 32 - Select charset when composing message 33 - Complete re-design of the caching mechanism 88 34 89 35 36 2005/08/11 37 ---------- 38 - Write list header to client even if list is empty 39 - Add functions "select all", "select none" to message list 40 - Improved filter for HTML messages to remove potentially malicious tags (script, iframe, object) and event handlers. 41 - Buttons for next/previous message in view mode 42 - Add new created contact to list and show confirmation status 43 - Added folder management (subscribe/create/delete) 44 - Log message sending (SMTP log) 45 - Grant access for Camino browser 46 - Added German translation 47 48 49 2005/10/20 50 ---------- 51 - Added Swedish, Latvian, Portuguese and Catalan translation 52 - Make SMTP auth method configurable 53 - Make mailboxlist scrollable (Bug #1326372) 54 - Fixed SSL support 55 - Improved support for Courier IMAP (root folder and delimiter issues) 56 - Moved taskbar from bottom to top 57 - Added 'session_lifetime' parameter 58 - Fixed wrong unread count when deleting message (Bug #1332434) 59 - Srip tags when creating a new folder (Bug #1332084) 60 - Translate HTML tags in message headers (Bug #1330134) 61 - Correction in German translation (Bug #1329434) 62 - Display folder names with special chars correctly (Bug #1330157) 63 64 65 2005/10/07 66 ---------- 67 - Added French, Italian, Spanish, Danish, Dutch translation 68 - Clarified license (Bug #1305966) 69 - Fixed PHP warnings (Bug #1299403) 70 - Fixed english translation (Bug #1295406) 71 - Fixed bug #1290833: Last character of email not seen 72 - Fixed bug #1292199 when creating new user 73 - Allow more browsers (Bug #1285101) 74 - Added setting for showing pretty dates 75 - Added support for SQLite database 76 - Make use of message caching configurable 77 - Also add attachments when forwarding a message 78 - Long folder names will not flow over message list (Bug #1267232) 79 - Show nested mailboxes hieracically 80 - Enable IMAPS by host 81 82 83 2005/08/20 84 ---------- 85 - Improved cacheing of mailbox messagecount 86 - Fixed javascript bug when creating a new message folder 87 - Fixed javascript bugs #1260990 and #1260992: folder selection 88 - Make Trash folder configurable 89 - Auto create folders Inbox, Sent and Trash (if configured) 90 - Support for IMAP root folder 91 - Added support fot text/enriched messages 92 - Make list of special mailboxes configurable 93 -
INSTALL
r10a69975 r1cded85 32 32 # mysql roundcubemail < SQL/mysql.initial.sql 33 33 34 34 35 * SQLite 35 36 -------- … … 43 44 Make sure your configuration points to the sqlite.db file and that the 44 45 webserver can write to the file. 46 47 48 * PostgreSQL 49 ------------ 50 To use RoundCube with PostgreSQL support you have to follow the next 51 simple steps, which have to be done with the postgres system user (or 52 which ever is the database superuser): 53 54 $ createuser roundcubemail 55 $ createdb -O roundcubemail roundcubemail 56 $ psql roundcubemail 57 58 roundcubemail =# ALTER USER roundcube WITH PASSWORD 'the_new_password'; 59 roundcubemail =# \c - roundcubemail 60 roundcubemail => \i SQL/postgres.initial.sql 61 62 All this has been tested with PostgreSQL 8.0.x and 7.4.x. Older 63 versions don't have a -O option for the createdb, so if you are 64 using that version you'll have to change ownership of the DB later. 45 65 46 66 -
SQL/mysql.initial.sql
re447cb0 r1cded85 12 12 `cache_id` int(10) unsigned NOT NULL auto_increment, 13 13 `user_id` int(10) unsigned NOT NULL default '0', 14 `session_id` varchar( 32) default NULL,14 `session_id` varchar(40) default NULL, 15 15 `cache_key` varchar(128) NOT NULL default '', 16 16 `created` datetime NOT NULL default '0000-00-00 00:00:00', … … 32 32 `user_id` int(10) unsigned NOT NULL default '0', 33 33 `changed` datetime NOT NULL default '0000-00-00 00:00:00', 34 `del` enum('0','1') NOT NULL default '0',34 `del` tinyint(1) NOT NULL default '0', 35 35 `name` varchar(128) NOT NULL default '', 36 36 `email` varchar(128) NOT NULL default '', … … 51 51 `identity_id` int(10) unsigned NOT NULL auto_increment, 52 52 `user_id` int(10) unsigned NOT NULL default '0', 53 `del` enum('0','1') NOT NULL default '0',54 ` default` enum('0','1') NOT NULL default '0',53 `del` tinyint(1) NOT NULL default '0', 54 `standard` tinyint(1) NOT NULL default '0', 55 55 `name` varchar(128) NOT NULL default '', 56 56 `organization` varchar(128) NOT NULL default '', … … 95 95 PRIMARY KEY (`user_id`) 96 96 ) TYPE=MyISAM; 97 98 -- -------------------------------------------------------- 99 100 -- 101 -- Table structure for table `messages` 102 -- 103 104 CREATE TABLE `messages` ( 105 `message_id` int(11) unsigned NOT NULL auto_increment, 106 `user_id` int(11) unsigned NOT NULL default '0', 107 `del` tinyint(1) NOT NULL default '0', 108 `cache_key` varchar(128) NOT NULL default '', 109 `idx` int(11) unsigned NOT NULL default '0', 110 `uid` int(11) unsigned NOT NULL default '0', 111 `subject` varchar(255) NOT NULL default '', 112 `from` varchar(255) NOT NULL default '', 113 `to` varchar(255) NOT NULL default '', 114 `cc` varchar(255) NOT NULL default '', 115 `date` datetime NOT NULL default '0000-00-00 00:00:00', 116 `size` int(11) unsigned NOT NULL default '0', 117 `headers` text NOT NULL, 118 `body` longtext, 119 PRIMARY KEY (`message_id`), 120 KEY `user_id` (`user_id`), 121 KEY `cache_key` (`cache_key`), 122 KEY `idx` (`idx`), 123 KEY `uid` (`uid`) 124 ) TYPE=MyISAM; 125 126 -
SQL/mysql.update.sql
re0ddd4e r1cded85 12 12 13 13 ALTER TABLE `session` CHANGE `sess_id` `sess_id` VARCHAR(40) NOT NULL; 14 15 ALTER TABLE `contacts` CHANGE `del` `del` TINYINT(1) NOT NULL; 14 16 ALTER TABLE `contacts` ADD `changed` DATETIME NOT NULL AFTER `user_id`; 17 18 UPDATE `contacts` SET `del`=0 WHERE `del`=1; 19 UPDATE `contacts` SET `del`=1 WHERE `del`=2; 20 21 ALTER TABLE `identities` CHANGE `default` `standard` TINYINT(1) NOT NULL; 22 ALTER TABLE `identities` CHANGE `del` `del` TINYINT(1) NOT NULL; 23 24 UPDATE `identities` SET `del`=0 WHERE `del`=1; 25 UPDATE `identities` SET `del`=1 WHERE `del`=2; 26 UPDATE `identities` SET `standard`=0 WHERE `standard`=1; 27 UPDATE `identities` SET `standard`=1 WHERE `standard`=2; 28 29 CREATE TABLE `messages` ( 30 `message_id` int(11) unsigned NOT NULL auto_increment, 31 `user_id` int(11) unsigned NOT NULL default '0', 32 `del` tinyint(1) NOT NULL default '0', 33 `cache_key` varchar(128) NOT NULL default '', 34 `idx` int(11) unsigned NOT NULL default '0', 35 `uid` int(11) unsigned NOT NULL default '0', 36 `subject` varchar(255) NOT NULL default '', 37 `from` varchar(255) NOT NULL default '', 38 `to` varchar(255) NOT NULL default '', 39 `cc` varchar(255) NOT NULL default '', 40 `date` datetime NOT NULL default '0000-00-00 00:00:00', 41 `size` int(11) unsigned NOT NULL default '0', 42 `headers` text NOT NULL, 43 `body` longtext, 44 PRIMARY KEY (`message_id`), 45 KEY `user_id` (`user_id`), 46 KEY `cache_key` (`cache_key`), 47 KEY `idx` (`idx`), 48 KEY `uid` (`uid`) 49 ) TYPE=MyISAM; -
SQL/postgres.initial.sql
rd7cb774 r1cded85 1 1 -- 2 -- PostgreSQL database dump 3 -- 4 5 SET client_encoding = 'UNICODE'; 6 SET check_function_bodies = false; 7 SET search_path = public, pg_catalog; 8 9 ALTER TABLE ONLY public.identities DROP CONSTRAINT "$1"; 10 ALTER TABLE ONLY public.contacts DROP CONSTRAINT "$1"; 11 ALTER TABLE ONLY public."cache" DROP CONSTRAINT "$2"; 12 ALTER TABLE ONLY public."cache" DROP CONSTRAINT "$1"; 13 ALTER TABLE ONLY public.users DROP CONSTRAINT users_pkey; 14 ALTER TABLE ONLY public."session" DROP CONSTRAINT session_pkey; 15 ALTER TABLE ONLY public.identities DROP CONSTRAINT identities_pkey; 16 ALTER TABLE ONLY public.contacts DROP CONSTRAINT contacts_pkey; 17 ALTER TABLE ONLY public."cache" DROP CONSTRAINT cache_pkey; 18 DROP TABLE public.users; 19 DROP TABLE public."session"; 20 DROP TABLE public.identities; 21 DROP TABLE public.contacts; 22 DROP TABLE public."cache"; 23 DROP SEQUENCE public.user_ids; 24 DROP SEQUENCE public.identity_ids; 25 DROP SEQUENCE public.contact_ids; 26 DROP SEQUENCE public.cache_ids; 27 -- 28 -- TOC entry 4 (OID 15282470) 29 -- Name: cache_ids; Type: SEQUENCE; Schema: public; Owner: postgres 30 -- 31 32 CREATE SEQUENCE cache_ids 33 INCREMENT BY 1 34 NO MAXVALUE 35 NO MINVALUE 36 CACHE 1; 37 38 39 -- 40 -- TOC entry 5 (OID 15282472) 41 -- Name: contact_ids; Type: SEQUENCE; Schema: public; Owner: postgres 42 -- 43 44 CREATE SEQUENCE contact_ids 45 START WITH 1 46 INCREMENT BY 1 47 NO MAXVALUE 48 NO MINVALUE 49 CACHE 1; 50 51 52 -- 53 -- TOC entry 6 (OID 15282474) 54 -- Name: identity_ids; Type: SEQUENCE; Schema: public; Owner: postgres 55 -- 56 57 CREATE SEQUENCE identity_ids 58 START WITH 1 59 INCREMENT BY 1 60 NO MAXVALUE 61 NO MINVALUE 62 CACHE 1; 63 64 65 -- 66 -- TOC entry 7 (OID 15282476) 67 -- Name: user_ids; Type: SEQUENCE; Schema: public; Owner: postgres 68 -- 69 70 CREATE SEQUENCE user_ids 71 INCREMENT BY 1 72 NO MAXVALUE 73 NO MINVALUE 74 CACHE 1; 75 76 77 -- 78 -- TOC entry 8 (OID 15282478) 79 -- Name: cache; Type: TABLE; Schema: public; Owner: postgres 80 -- 81 82 CREATE TABLE "cache" ( 83 cache_id integer DEFAULT nextval('cache_ids'::text) NOT NULL, 84 user_id integer DEFAULT 0 NOT NULL, 85 session_id character varying(32), 86 cache_key character varying(128) DEFAULT ''::character varying NOT NULL, 87 created timestamp with time zone DEFAULT now() NOT NULL, 88 data text NOT NULL 89 ); 90 91 92 -- 93 -- TOC entry 10 (OID 15282486) 94 -- Name: contacts; Type: TABLE; Schema: public; Owner: postgres 95 -- 96 97 CREATE TABLE contacts ( 98 contact_id integer DEFAULT nextval('contact_ids'::text) NOT NULL, 99 user_id integer DEFAULT 0 NOT NULL, 100 del boolean DEFAULT false NOT NULL, 101 name character varying(128) DEFAULT ''::character varying NOT NULL, 102 email character varying(128) DEFAULT ''::character varying NOT NULL, 103 firstname character varying(128) DEFAULT ''::character varying NOT NULL, 104 surname character varying(128) DEFAULT ''::character varying NOT NULL, 105 vcard text NOT NULL 106 ); 107 108 109 -- 110 -- TOC entry 11 (OID 15282494) 111 -- Name: identities; Type: TABLE; Schema: public; Owner: postgres 112 -- 113 114 CREATE TABLE identities ( 115 identity_id integer DEFAULT nextval('identity_ids'::text) NOT NULL, 116 user_id integer DEFAULT 0 NOT NULL, 117 del boolean DEFAULT false NOT NULL, 118 "default" boolean DEFAULT false NOT NULL, 119 name character varying(128) NOT NULL, 120 organization character varying(128), 121 email character varying(128) NOT NULL, 122 "reply-to" character varying(128), 123 bcc character varying(128), 124 signature text 125 ); 126 127 128 -- 129 -- TOC entry 12 (OID 15282503) 130 -- Name: session; Type: TABLE; Schema: public; Owner: postgres 131 -- 132 133 CREATE TABLE "session" ( 134 sess_id character varying(32) DEFAULT ''::character varying NOT NULL, 135 created timestamp with time zone DEFAULT now() NOT NULL, 136 changed timestamp with time zone DEFAULT now() NOT NULL, 137 ip character varying(16) NOT NULL, 138 vars text NOT NULL 139 ); 140 141 142 -- 143 -- TOC entry 13 (OID 15282510) 2 -- Table "users" 144 3 -- Name: users; Type: TABLE; Schema: public; Owner: postgres 145 4 -- … … 157 16 158 17 159 -- 160 -- TOC entry 14 (OID 15282518) 161 -- Name: cache_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres 18 19 -- 20 -- Table "session" 21 -- Name: session; Type: TABLE; Schema: public; Owner: postgres 22 -- 23 24 CREATE TABLE "session" ( 25 sess_id character varying(40) DEFAULT ''::character varying NOT NULL, 26 created timestamp with time zone DEFAULT now() NOT NULL, 27 changed timestamp with time zone DEFAULT now() NOT NULL, 28 ip character varying(16) NOT NULL, 29 vars text NOT NULL 30 ); 31 32 33 34 -- 35 -- Table "identities" 36 -- Name: identities; Type: TABLE; Schema: public; Owner: postgres 37 -- 38 39 CREATE TABLE identities ( 40 identity_id integer DEFAULT nextval('identity_ids'::text) NOT NULL, 41 user_id integer DEFAULT 0 NOT NULL, 42 del integer DEFAULT 0 NOT NULL, 43 standard integer DEFAULT 0 NOT NULL, 44 name character varying(128) NOT NULL, 45 organization character varying(128), 46 email character varying(128) NOT NULL, 47 "reply-to" character varying(128), 48 bcc character varying(128), 49 signature text 50 ); 51 52 53 -- 54 -- Table "contacts" 55 -- Name: contacts; Type: TABLE; Schema: public; Owner: postgres 56 -- 57 58 CREATE TABLE contacts ( 59 contact_id integer DEFAULT nextval('contact_ids'::text) NOT NULL, 60 user_id integer DEFAULT 0 NOT NULL, 61 changed timestamp with time zone DEFAULT now() NOT NULL, 62 del integer DEFAULT 0 NOT NULL, 63 name character varying(128) DEFAULT ''::character varying NOT NULL, 64 email character varying(128) DEFAULT ''::character varying NOT NULL, 65 firstname character varying(128) DEFAULT ''::character varying NOT NULL, 66 surname character varying(128) DEFAULT ''::character varying NOT NULL, 67 vcard text 68 ); 69 70 71 72 -- 73 -- Table "cache" 74 -- Name: cache; Type: TABLE; Schema: public; Owner: postgres 75 -- 76 77 CREATE TABLE "cache" ( 78 cache_id integer DEFAULT nextval('cache_ids'::text) NOT NULL, 79 user_id integer DEFAULT 0 NOT NULL, 80 session_id character varying(40), 81 cache_key character varying(128) DEFAULT ''::character varying NOT NULL, 82 created timestamp with time zone DEFAULT now() NOT NULL, 83 data text NOT NULL 84 ); 85 86 87 88 -- 89 -- Table "messages" 90 -- Name: messages; Type: TABLE; Schema: public; Owner: postgres 91 -- 92 93 CREATE TABLE "messages" ( 94 message_id integer DEFAULT nextval('message_ids'::text) NOT NULL, 95 user_id integer DEFAULT 0 NOT NULL, 96 del integer DEFAULT 0 NOT NULL, 97 cache_key character varying(128) DEFAULT ''::character varying NOT NULL, 98 idx integer DEFAULT 0 NOT NULL, 99 uid integer DEFAULT 0 NOT NULL, 100 subject character varying(128) DEFAULT ''::character varying NOT NULL, 101 "from" character varying(128) DEFAULT ''::character varying NOT NULL, 102 "to" character varying(128) DEFAULT ''::character varying NOT NULL, 103 cc character varying(128) DEFAULT ''::character varying NOT NULL, 104 date timestamp with time zone NOT NULL, 105 size integer DEFAULT 0 NOT NULL, 106 headers text NOT NULL, 107 body text 108 ); 109 110 111 112 -- 113 -- Add primary keys 162 114 -- 163 115 … … 166 118 167 119 168 -- 169 -- TOC entry 15 (OID 15282520) 170 -- Name: contacts_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres 171 -- 172 173 ALTER TABLE ONLY contacts 120 ALTER TABLE ONLY "contacts" 174 121 ADD CONSTRAINT contacts_pkey PRIMARY KEY (contact_id); 175 122 176 177 --178 -- TOC entry 16 (OID 15282522)179 -- Name: identities_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres180 --181 123 182 124 ALTER TABLE ONLY identities … … 184 126 185 127 186 --187 -- TOC entry 17 (OID 15282524)188 -- Name: session_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres189 --190 191 128 ALTER TABLE ONLY "session" 192 129 ADD CONSTRAINT session_pkey PRIMARY KEY (sess_id); 193 130 194 131 195 -- 196 -- TOC entry 18 (OID 15282526) 197 -- Name: users_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres 198 -- 199 200 ALTER TABLE ONLY users 132 ALTER TABLE ONLY "users" 201 133 ADD CONSTRAINT users_pkey PRIMARY KEY (user_id); 202 134 203 135 204 -- 205 -- TOC entry 19 (OID 15282528) 206 -- Name: $1; Type: FK CONSTRAINT; Schema: public; Owner: postgres 136 ALTER TABLE ONLY "messages" 137 ADD CONSTRAINT messages_pkey PRIMARY KEY (message_id); 138 139 140 -- 141 -- Reference keys 207 142 -- 208 143 209 144 ALTER TABLE ONLY "cache" 210 145 ADD CONSTRAINT "$1" FOREIGN KEY (user_id) REFERENCES users(user_id); 211 212 213 --214 -- TOC entry 20 (OID 15282532)215 -- Name: $2; Type: FK CONSTRAINT; Schema: public; Owner: postgres216 --217 146 218 147 ALTER TABLE ONLY "cache" … … 220 149 221 150 222 -- 223 -- TOC entry 21 (OID 15282536) 224 -- Name: $1; Type: FK CONSTRAINT; Schema: public; Owner: postgres 225 -- 226 227 ALTER TABLE ONLY contacts 228 ADD CONSTRAINT "$1" FOREIGN KEY (user_id) REFERENCES users(user_id); 229 230 231 -- 232 -- TOC entry 22 (OID 15282540) 233 -- Name: $1; Type: FK CONSTRAINT; Schema: public; Owner: postgres 234 -- 235 236 ALTER TABLE ONLY identities 237 ADD CONSTRAINT "$1" FOREIGN KEY (user_id) REFERENCES users(user_id); 238 239 240 SET SESSION AUTHORIZATION 'postgres'; 241 242 -- 243 -- TOC entry 3 (OID 15282469) 244 -- Name: SCHEMA public; Type: COMMENT; Schema: -; Owner: postgres 245 -- 246 247 COMMENT ON SCHEMA public IS 'Standard public schema'; 248 249 250 SET SESSION AUTHORIZATION 'postgres'; 251 252 -- 253 -- TOC entry 9 (OID 15282478) 254 -- Name: TABLE "cache"; Type: COMMENT; Schema: public; Owner: postgres 255 -- 151 ALTER TABLE ONLY "contacts" 152 ADD CONSTRAINT "$1" FOREIGN KEY (user_id) REFERENCES users(user_id); 153 154 155 ALTER TABLE ONLY "identities" 156 ADD CONSTRAINT "$1" FOREIGN KEY (user_id) REFERENCES users(user_id); 157 158 159 ALTER TABLE ONLY "messages" 160 ADD CONSTRAINT "$1" FOREIGN KEY (user_id) REFERENCES users(user_id); 161 162 163 -- 164 -- Sequence "cache_ids" 165 -- Name: cache_ids; Type: SEQUENCE; Schema: public; Owner: postgres 166 -- 167 168 CREATE SEQUENCE cache_ids 169 INCREMENT BY 1 170 NO MAXVALUE 171 NO MINVALUE 172 CACHE 1; 173 174 175 -- 176 -- Sequence "contact_ids" 177 -- Name: contact_ids; Type: SEQUENCE; Schema: public; Owner: postgres 178 -- 179 180 CREATE SEQUENCE contact_ids 181 START WITH 1 182 INCREMENT BY 1 183 NO MAXVALUE 184 NO MINVALUE 185 CACHE 1; 186 187 188 -- 189 -- Sequence "identity_ids" 190 -- Name: identity_ids; Type: SEQUENCE; Schema: public; Owner: postgres 191 -- 192 193 CREATE SEQUENCE identity_ids 194 START WITH 1 195 INCREMENT BY 1 196 NO MAXVALUE 197 NO MINVALUE 198 CACHE 1; 199 200 201 -- 202 -- Sequence "user_ids" 203 -- Name: user_ids; Type: SEQUENCE; Schema: public; Owner: postgres 204 -- 205 206 CREATE SEQUENCE user_ids 207 INCREMENT BY 1 208 NO MAXVALUE 209 NO MINVALUE 210 CACHE 1; 211 212 213 -- 214 -- Sequence "message_ids" 215 -- Name: message_ids; Type: SEQUENCE; Schema: public; Owner: postgres 216 -- 217 218 CREATE SEQUENCE message_ids 219 INCREMENT BY 1 220 NO MAXVALUE 221 NO MINVALUE 222 CACHE 1; 223 -
SQL/sqlite.initial.sql
r79fe17f r1cded85 12 12 cache_id integer NOT NULL PRIMARY KEY, 13 13 user_id integer NOT NULL default 0, 14 session_id varchar( 32) default NULL,14 session_id varchar(40) default NULL, 15 15 cache_key varchar(128) NOT NULL default '', 16 16 created datetime NOT NULL default '0000-00-00 00:00:00', … … 21 21 CREATE INDEX ix_cache_cache_key ON cache(cache_key); 22 22 CREATE INDEX ix_cache_session_id ON cache(session_id); 23 23 24 24 25 -- -------------------------------------------------------- … … 31 32 contact_id integer NOT NULL PRIMARY KEY, 32 33 user_id integer NOT NULL default '0', 33 del integer NOT NULL default '0', 34 created datetime NOT NULL default '0000-00-00 00:00:00', 35 del tinyint NOT NULL default '0', 34 36 name varchar(128) NOT NULL default '', 35 37 email varchar(128) NOT NULL default '', … … 50 52 identity_id integer NOT NULL PRIMARY KEY, 51 53 user_id integer NOT NULL default '0', 52 del integerNOT NULL default '0',53 "default" integerNOT NULL default '0',54 del tinyint NOT NULL default '0', 55 standard tinyint NOT NULL default '0', 54 56 name varchar(128) NOT NULL default '', 55 organization varchar(128) NOT NULLdefault '',57 organization varchar(128) default '', 56 58 email varchar(128) NOT NULL default '', 57 59 "reply-to" varchar(128) NOT NULL default '', … … 79 81 preferences text NOT NULL default '' 80 82 ); 83 84 85 -- -------------------------------------------------------- 86 87 -- 88 -- Table structure for table session 89 -- 90 91 CREATE TABLE session ( 92 sess_id varchar(40) NOT NULL PRIMARY KEY, 93 created datetime NOT NULL default '0000-00-00 00:00:00', 94 changed datetime NOT NULL default '0000-00-00 00:00:00', 95 ip varchar(15) NOT NULL default '', 96 vars text NOT NULL 97 ); 98 99 100 -- -------------------------------------------------------- 101 102 -- 103 -- Table structure for table messages 104 -- 105 106 CREATE TABLE messages ( 107 message_id integer NOT NULL PRIMARY KEY, 108 user_id integer NOT NULL default '0', 109 del tinyint NOT NULL default '0', 110 cache_key varchar(128) NOT NULL default '', 111 idx integer NOT NULL default '0', 112 uid integer NOT NULL default '0', 113 subject varchar(255) NOT NULL default '', 114 "from" varchar(255) NOT NULL default '', 115 "to" varchar(255) NOT NULL default '', 116 cc varchar(255) NOT NULL default '', 117 date datetime NOT NULL default '0000-00-00 00:00:00', 118 size integer NOT NULL default '0', 119 headers text NOT NULL, 120 body text 121 ); 122 123 CREATE INDEX ix_messages_user_id ON messages(user_id); 124 CREATE INDEX ix_messages_cache_key ON messages(cache_key); -
UPGRADING
r0cbc094 r1cded85 11 11 - replace all files in folder /program/ 12 12 - replace all files in folder /skins/default/ 13 - run d SQL queries in order to update the database13 - run all commands in SQL/*.update.sql or re-initalize database with *.initial.sql 14 14 - add these line to /config/main.inc.php 15 15 $rcmail_config['trash_mbox'] = 'Trash'; … … 23 23 $rcmail_config['message_sort_order'] = 'DESC'; 24 24 $rcmail_config['log_dir'] = 'logs/'; 25 $rcmail_config['temp_dir'] = 'temp/'; 25 26 - replace database properties (db_type, db_host, db_user, db_pass, $d_name) 26 27 in /config/db.inc.php with the following line: 27 28 $rcmail_config['db_dsnw'] = 'mysql://roundcube:pass@localhost/roundcubemail'; 29 - add these lines to /config/db.inc.php 30 $rcmail_config['db_max_length'] = 512000; 28 31 29 32 … … 33 36 - replace all files in folder /program/ 34 37 - replace all files in folder /skins/default/ 35 - run d SQL queries in order to update the database38 - run all commands in SQL/*.update.sql or re-initalize database with *.initial.sql 36 39 - add these line to /config/main.inc.php 37 40 $rcmail_config['prettydate'] = TRUE; … … 42 45 $rcmail_config['message_sort_order'] = 'DESC'; 43 46 $rcmail_config['log_dir'] = 'logs/'; 47 $rcmail_config['temp_dir'] = 'temp/'; 44 48 - replace database properties (db_type, db_host, db_user, db_pass, $d_name) 45 49 in /config/db.inc.php with the following line: 46 50 $rcmail_config['db_dsnw'] = 'mysql://roundcube:pass@localhost/roundcubemail'; 51 - add these lines to /config/db.inc.php 52 $rcmail_config['db_max_length'] = 512000; 47 53 48 54 … … 52 58 - replace all files in folder /program/ 53 59 - replace all files in folder /skins/default/ 60 - run all commands in SQL/*.update.sql or re-initalize database with *.initial.sql 54 61 - add these lines to /config/main.inc.php 55 62 $rcmail_config['smtp_auth_type'] = ''; // if you need to specify an auth method for SMTP … … 58 65 $rcmail_config['message_sort_order'] = 'DESC'; 59 66 $rcmail_config['log_dir'] = 'logs/'; 60 67 $rcmail_config['temp_dir'] = 'temp/'; 68 - add these lines to /config/db.inc.php 69 $rcmail_config['db_max_length'] = 512000; 70 $rcmail_config['db_sequence_user_ids'] = 'user_ids'; 71 $rcmail_config['db_sequence_identity_ids'] = 'identity_ids'; 72 $rcmail_config['db_sequence_contact_ids'] = 'contact_ids'; 73 $rcmail_config['db_sequence_cache_ids'] = 'cache_ids'; 74 $rcmail_config['db_sequence_message_ids'] = 'message_ids'; 75 61 76 62 77 from version 0.1-20051021 … … 65 80 - replace all files in folder /program/ 66 81 - replace all files in folder /skins/default/ 82 - run all commands in SQL/*.update.sql or re-initalize database with *.initial.sql 67 83 - add these lines to /config/main.inc.php 68 84 $rcmail_config['message_sort_col'] = 'date'; 69 85 $rcmail_config['message_sort_order'] = 'DESC'; 70 86 $rcmail_config['log_dir'] = 'logs/'; 87 $rcmail_config['temp_dir'] = 'temp/'; 88 - add these lines to /config/db.inc.php 89 $rcmail_config['db_max_length'] = 512000; 90 $rcmail_config['db_sequence_user_ids'] = 'user_ids'; 91 $rcmail_config['db_sequence_identity_ids'] = 'identity_ids'; 92 $rcmail_config['db_sequence_contact_ids'] = 'contact_ids'; 93 $rcmail_config['db_sequence_cache_ids'] = 'cache_ids'; 94 $rcmail_config['db_sequence_message_ids'] = 'message_ids'; -
config/db.inc.php.dist
r7cc38e0 r1cded85 20 20 21 21 $rcmail_config['db_dsnw'] = 'mysql://roundcube:pass@localhost/roundcubemail'; 22 // postgres example: 'pgsql://roundcube:pass@localhost/roundcubemail'; 22 23 // sqlite example: 'sqlite://./sqlite.db?mode=0646'; 23 24 … … 28 29 // database backend to use (only db or mdb2 are supported) 29 30 $rcmail_config['db_backend'] = 'db'; 31 32 // maximum length of a query in bytes 33 $rcmail_config['db_max_length'] = 512000; // 500K 30 34 31 35 // you can define specific table names used to store webmail data … … 40 44 $rcmail_config['db_table_cache'] = 'cache'; 41 45 46 $rcmail_config['db_table_messages'] = 'messages'; 47 48 49 // you can define specific sequence names used in PostgreSQL 50 $rcmail_config['db_sequence_users'] = 'user_ids'; 51 52 $rcmail_config['db_sequence_identities'] = 'identity_ids'; 53 54 $rcmail_config['db_sequence_contacts'] = 'contact_ids'; 55 56 $rcmail_config['db_sequence_cache'] = 'cache_ids'; 57 58 $rcmail_config['db_sequence_messages'] = 'message_ids'; 59 42 60 43 61 // end db config file -
config/main.inc.php.dist
r4b0f65a r1cded85 89 89 90 90 // add this user-agent to message headers when sending 91 $rcmail_config['useragent'] = 'RoundCube Webmail/0.1 -20051021';91 $rcmail_config['useragent'] = 'RoundCube Webmail/0.1b'; 92 92 93 93 // only list folders within this path -
index.php
recf7590 r1cded85 63 63 // increase maximum execution time for php scripts 64 64 // (does not work in safe mode) 65 @set_time_limit( '120');65 @set_time_limit(120); 66 66 67 67 // include base files … … 200 200 201 201 202 // handle keep-alive signal 203 if ($_action=='keep-alive') 204 { 205 rcube_remote_response(''); 206 exit; 207 } 208 202 209 203 210 // include task specific files … … 287 294 include('program/steps/settings/manage_folders.inc'); 288 295 289 }290 291 292 // handle keep-alive signal293 if ($_action=='keep-alive')294 {295 rcube_remote_response('');296 exit;297 296 } 298 297 -
program/include/cache.inc
r6677378 r1cded85 44 44 return $data; 45 45 } 46 47 46 47 48 48 function rcube_write_cache($key, $data, $session_cache=FALSE) 49 49 { … … 92 92 93 93 94 95 94 function rcube_clear_cache($key) 96 95 { -
program/include/main.inc
r5bc8cb66 r1cded85 70 70 // we can use the database for storing session data 71 71 // session queries do not work with MDB2 72 if ($CONFIG['db_backend']!='mdb2' && is_object($DB) && $DB->db_provider!='sqlite')72 if ($CONFIG['db_backend']!='mdb2' && is_object($DB) /* && $DB->db_provider!='sqlite' */) 73 73 include_once('include/session.inc'); 74 74 … … 144 144 function rcmail_imap_init($connect=FALSE) 145 145 { 146 global $CONFIG, $ IMAP;147 148 $IMAP = new rcube_imap( );146 global $CONFIG, $DB, $IMAP; 147 148 $IMAP = new rcube_imap($DB); 149 149 150 150 // connect with stored session data … … 228 228 229 229 230 // return correct name for a specific database sequence 231 // (used for Postres only) 232 function get_sequence_name($sequence) 233 { 234 global $CONFIG; 235 236 // return table name if configured 237 $config_key = 'db_sequence_'.$sequence; 238 239 if (strlen($CONFIG[$config_key])) 240 return $CONFIG[$config_key]; 241 242 return $table; 243 } 244 245 230 246 231 247 // init output object for GUI and add common scripts … … 381 397 $_SESSION['user_lang']); 382 398 383 if ($user_id = $DB->insert_id( 'user_ids'))399 if ($user_id = $DB->insert_id(get_sequence_name('users'))) 384 400 { 385 401 $user_email = strstr($user, '@') ? $user : sprintf('%s@%s', $user, $host); … … 388 404 // also create a new identity record 389 405 $DB->query("INSERT INTO ".get_table_name('identities')." 390 (user_id, `default`, name, email)391 VALUES (?, '1', ?, ?)",406 (user_id, del, standard, name, email) 407 VALUES (?, 0, 1, ?, ?)", 392 408 $user_id, 393 409 $user_name, … … 480 496 { 481 497 send_nocacheing_headers(); 482 //header('Content-Type: text/javascript');483 498 header('Content-Type: application/x-javascript'); 484 499 … … 528 543 $name, 529 544 rep_specialchars_output(rcube_label($name), 'js'))); 545 } 546 547 548 // remove temp files of a session 549 function rcmail_clear_session_temp($sess_id) 550 { 551 global $CONFIG; 552 553 $temp_dir = $CONFIG['temp_dir'].(!eregi('\/$', $CONFIG['temp_dir']) ? '/' : ''); 554 $cache_dir = $temp_dir.$sess_id; 555 556 if (is_dir($cache_dir)) 557 { 558 clear_directory($cache_dir); 559 rmdir($cache_dir); 560 } 561 } 562 563 564 565 // replace specials characters to a specific encoding type 566 function rep_specialchars_output($str, $enctype='', $mode='', $newlines=TRUE) 567 { 568 global $OUTPUT_TYPE, $CHARSET; 569 static $html_encode_arr, $js_rep_table, $rtf_rep_table, $xml_rep_table; 570 571 if (!$enctype) 572 $enctype = $GLOBALS['OUTPUT_TYPE']; 573 574 // convert nbsps back to normal spaces if not html 575 if ($enctype!='html') 576 $str = str_replace(chr(160), ' ', $str); 577 578 579 // encode for plaintext 580 if ($enctype=='text') 581 return str_replace("\r\n", "\n", $mode=='remove' ? strip_tags($str) : $str); 582 583 // encode for HTML output 584 if ($enctype=='html') 585 { 586 if (!$html_encode_arr) 587 { 588 if ($CHARSET=='ISO-8859-1') 589 { 590 $html_encode_arr = get_html_translation_table(HTML_ENTITIES); 591 $html_encode_arr[chr(128)] = '€'; 592 } 593 else 594 $html_encode_arr = get_html_translation_table(HTML_SPECIALCHARS); 595 596 unset($html_encode_arr['?']); 597 unset($html_encode_arr['&']); 598 } 599 600 $ltpos = strpos($str, '<'); 601 $encode_arr = $html_encode_arr; 602 603 // don't replace quotes and html tags 604 if (($mode=='show' || $mode=='') && $ltpos!==false && strpos($str, '>', $ltpos)!==false) 605 { 606 unset($encode_arr['"']); 607 unset($encode_arr['<']); 608 unset($encode_arr['>']); 609 } 610 else if ($mode=='remove') 611 $str = strip_tags($str); 612 613 $out = strtr($str, $encode_arr); 614 615 return $newlines ? nl2br($out) : $out; 616 } 617 618 619 if ($enctype=='url') 620 return rawurlencode($str); 621 622 623 // if the replace tables for RTF, XML and JS are not yet defined 624 if (!$js_rep_table) 625 { 626 $js_rep_table = $rtf_rep_table = $xml_rep_table = array(); 627 628 for ($c=160; $c<256; $c++) // can be increased to support more charsets 629 { 630 $hex = dechex($c); 631 $rtf_rep_table[Chr($c)] = "\\'$hex"; 632 $xml_rep_table[Chr($c)] = "&#$c;"; 633 634 if ($CHARSET=='ISO-8859-1') 635 $js_rep_table[Chr($c)] = sprintf("\u%s%s", str_repeat('0', 4-strlen($hex)), $hex); 636 } 637 638 $js_rep_table['"'] = sprintf("\u%s%s", str_repeat('0', 4-strlen(dechex(34))), dechex(34)); 639 $xml_rep_table['"'] = '"'; 640 } 641 642 // encode for RTF 643 if ($enctype=='xml') 644 return strtr($str, $xml_rep_table); 645 646 // encode for javascript use 647 if ($enctype=='js') 648 return preg_replace(array("/\r\n/", '/"/', "/([^\\\])'/"), array('\n', '\"', "$1\'"), strtr($str, $js_rep_table)); 649 650 // encode for RTF 651 if ($enctype=='rtf') 652 return preg_replace("/\r\n/", "\par ", strtr($str, $rtf_rep_table)); 653 654 // no encoding given -> return original string 655 return $str; 530 656 } 531 657 … … 654 780 $object = strtolower($attrib['name']); 655 781 782 $object_handlers = array( 783 // MAIL 784 'mailboxlist' => 'rcmail_mailbox_list', 785 'messages' => 'rcmail_message_list', 786 'messagecountdisplay' => 'rcmail_messagecount_display', 787 'messageheaders' => 'rcmail_message_headers', 788 'messagebody' => 'rcmail_message_body', 789 'messageattachments' => 'rcmail_message_attachments', 790 'blockedobjects' => 'rcmail_remote_objects_msg', 791 'messagecontentframe' => 'rcmail_messagecontent_frame', 792 'messagepartframe' => 'rcmail_message_part_frame', 793 'messagepartcontrols' => 'rcmail_message_part_controls', 794 'composeheaders' => 'rcmail_compose_headers', 795 'composesubject' => 'rcmail_compose_subject', 796 'composebody' => 'rcmail_compose_body', 797 'composeattachmentlist' => 'rcmail_compose_attachment_list', 798 'composeattachmentform' => 'rcmail_compose_attachment_form', 799 'composeattachment' => 'rcmail_compose_attachment_field', 800 'priorityselector' => 'rcmail_priority_selector', 801 'charsetselector' => 'rcmail_charset_selector', 802 803 // ADDRESS BOOK 804 'addresslist' => 'rcmail_contacts_list', 805 'addressframe' => 'rcmail_contact_frame', 806 'recordscountdisplay' => 'rcmail_rowcount_display', 807 'contactdetails' => 'rcmail_contact_details', 808 'contacteditform' => 'rcmail_contact_editform', 809 810 // USER SETTINGS 811 'userprefs' => 'rcmail_user_prefs_form', 812 'itentitieslist' => 'rcmail_identities_list', 813 'identityframe' => 'rcmail_identity_frame', 814 'identityform' => 'rcube_identity_form', 815 'foldersubscription' => 'rcube_subscription_form', 816 'createfolder' => 'rcube_create_folder_form', 817 'composebody' => 'rcmail_compose_body' 818 ); 819 656 820 if ($object=='loginform') 657 821 return rcmail_login_form($attrib); … … 659 823 else if ($object=='message') 660 824 return rcmail_message_container($attrib); 661 662 // MAIL 663 else if ($object=='mailboxlist' && function_exists('rcmail_mailbox_list')) 664 return rcmail_mailbox_list($attrib); 665 666 else if ($object=='messages' && function_exists('rcmail_message_list')) 667 return rcmail_message_list($attrib); 668 669 else if ($object=='messagecountdisplay' && function_exists('rcmail_messagecount_display')) 670 return rcmail_messagecount_display($attrib); 671 672 else if ($object=='messageheaders' && function_exists('rcmail_message_headers')) 673 return rcmail_message_headers($attrib); 674 675 else if ($object=='messageattachments' && function_exists('rcmail_message_attachments')) 676 return rcmail_message_attachments($attrib); 677 678 else if ($object=='messagebody' && function_exists('rcmail_message_body')) 679 return rcmail_message_body($attrib); 680 681 else if ($object=='blockedobjects' && function_exists('rcmail_remote_objects_msg')) 682 return rcmail_remote_objects_msg($attrib); 683 684 else if ($object=='messagecontentframe' && function_exists('rcmail_messagecontent_frame')) 685 return rcmail_messagecontent_frame($attrib); 686 687 else if ($object=='messagepartframe' && function_exists('rcmail_message_part_frame')) 688 return rcmail_message_part_frame($attrib); 689 690 else if ($object=='messagepartcontrols' && function_exists('rcmail_message_part_controls')) 691 return rcmail_message_part_controls($attrib); 692 693 else if ($object=='composeheaders' && function_exists('rcmail_compose_headers')) 694 return rcmail_compose_headers($attrib); 695 696 else if ($object=='composesubject' && function_exists('rcmail_compose_subject')) 697 return rcmail_compose_subject($attrib); 698 699 else if ($object=='composebody' && function_exists('rcmail_compose_body')) 700 return rcmail_compose_body($attrib); 701 702 else if ($object=='composeattachmentlist' && function_exists('rcmail_compose_attachment_list')) 703 return rcmail_compose_attachment_list($attrib); 704 705 else if ($object=='composeattachmentform' && function_exists('rcmail_compose_attachment_form')) 706 return rcmail_compose_attachment_form($attrib); 707 708 else if ($object=='composeattachment' && function_exists('rcmail_compose_attachment_field')) 709 return rcmail_compose_attachment_field($attrib); 710 711 else if ($object=='priorityselector' && function_exists('rcmail_priority_selector')) 712 return rcmail_priority_selector($attrib); 713 714 else if ($object=='priorityselector' && function_exists('rcmail_priority_selector')) 715 return rcmail_priority_selector($attrib); 716 717 718 // ADDRESS BOOK 719 else if ($object=='addresslist' && function_exists('rcmail_contacts_list')) 720 return rcmail_contacts_list($attrib); 721 722 else if ($object=='addressframe' && function_exists('rcmail_contact_frame')) 723 return rcmail_contact_frame($attrib); 724 725 else if ($object=='recordscountdisplay' && function_exists('rcmail_rowcount_display')) 726 return rcmail_rowcount_display($attrib); 727 728 else if ($object=='contactdetails' && function_exists('rcmail_contact_details')) 729 return rcmail_contact_details($attrib); 730 731 else if ($object=='contacteditform' && function_exists('rcmail_contact_editform')) 732 return rcmail_contact_editform($attrib); 733 734 735 // USER SETTINGS 736 else if ($object=='userprefs' && function_exists('rcmail_user_prefs_form')) 737 return rcmail_user_prefs_form($attrib); 738 739 else if ($object=='itentitieslist' && function_exists('rcmail_identities_list')) 740 return rcmail_identities_list($attrib); 741 742 else if ($object=='identityframe' && function_exists('rcmail_identity_frame')) 743 return rcmail_identity_frame($attrib); 744 745 else if ($object=='identityform' && function_exists('rcube_identity_form')) 746 return rcube_identity_form($attrib); 747 748 else if ($object=='foldersubscription' && function_exists('rcube_subscription_form')) 749 return rcube_subscription_form($attrib); 750 751 else if ($object=='createfolder' && function_exists('rcube_create_folder_form')) 752 return rcube_create_folder_form($attrib); 753 825 826 // execute object handler function 827 else if ($object_handlers[$object] && function_exists($object_handlers[$object])) 828 return call_user_func($object_handlers[$object], $attrib); 754 829 755 830 else if ($object=='pagetitle') … … 879 954 if ($attrib['type']=='image') 880 955 { 881 $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'width', 'height', 'border', 'hspace', 'vspace', 'al t'));956 $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'width', 'height', 'border', 'hspace', 'vspace', 'align', 'alt')); 882 957 $img_tag = sprintf('<img src="%%s"%s />', $attrib_str); 883 958 $btn_content = sprintf($img_tag, $skin_path.$attrib['image']); … … 1162 1237 1163 1238 1239 1240 function rcmail_charset_selector($attrib) 1241 { 1242 // pass the following attributes to the form class 1243 $field_attrib = array('name' => '_charset'); 1244 foreach ($attrib as $attr => $value) 1245 if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex'))) 1246 $field_attrib[$attr] = $value; 1247 1248 $charsets = array( 1249 'US-ASCII' => 'ASCII (English)', 1250 'X-EUC-JP' => 'EUC-JP (Japanese)', 1251 'EUC-KR' => 'EUC-KR (Korean)', 1252 'BIG5' => 'BIG5 (Chinese)', 1253 'GB2312' => 'GB2312 (Chinese)', 1254 'ISO-8859-1' => 'ISO-8859-1 (Latin-1)', 1255 'ISO-8859-2' => 'ISO-8895-2 (Central European)', 1256 'ISO-8859-7' => 'ISO-8859-7 (Greek)', 1257 'ISO-8859-9' => 'ISO-8859-9 (Turkish)', 1258 'Windows-1251' => 'Windows-1251 (Cyrillic)', 1259 'Windows-1252' => 'Windows-1252 (Western)', 1260 'Windows-1255' => 'Windows-1255 (Hebrew)', 1261 'Windows-1256' => 'Windows-1256 (Arabic)', 1262 'Windows-1257' => 'Windows-1257 (Baltic)', 1263 'UTF-8' => 'UTF-8' 1264 ); 1265 1266 $select = new select($field_attrib); 1267 $select->add(array_values($charsets), array_keys($charsets)); 1268 1269 $set = $_POST['_charset'] ? $_POST['_charset'] : $GLOBALS['CHARSET']; 1270 return $select->show($set); 1271 } 1272 1273 1164 1274 ?> -
program/include/rcube_db.inc
r10a69975 r1cded85 24 24 25 25 class rcube_db 26 { 27 var $db_dsnw; // DSN for write operations 28 var $db_dsnr; // DSN for read operations 29 var $db_connected=false; // Already connected ? 30 var $db_mode=''; // Connection mode 31 var $db_handle=0; // Connection handle 32 33 var $a_query_results = array('dummy'); 34 var $last_res_id = 0; 35 36 // PHP 5 constructor 37 function __construct($db_dsnw,$db_dsnr='') 38 { 39 if ($db_dsnr=='') $db_dsnr=$db_dsnw; 40 41 $this->db_dsnw = $db_dsnw; 42 $this->db_dsnr = $db_dsnr; 43 44 $dsn_array = DB::parseDSN($db_dsnw); 45 $this->db_provider = $dsn_array['phptype']; 46 } 47 48 // PHP 4 compatibility 49 function rcube_db($db_dsnw,$db_dsnr='') 50 { 51 $this->__construct($db_dsnw,$db_dsnr); 52 } 53 54 // Connect to specific database 55 function dsn_connect($dsn) 56 { 57 // Use persistent connections if available 58 $dbh = DB::connect($dsn, array('persistent' => $true)); 59 60 if (DB::isError($dbh)) 61 raise_error(array('code' => 500, 26 { 27 var $db_dsnw; // DSN for write operations 28 var $db_dsnr; // DSN for read operations 29 var $db_connected = false; // Already connected ? 30 var $db_mode = ''; // Connection mode 31 var $db_handle = 0; // Connection handle 32 33 var $a_query_results = array('dummy'); 34 var $last_res_id = 0; 35 36 37 // PHP 5 constructor 38 function __construct($db_dsnw,$db_dsnr='') 39 { 40 if ($db_dsnr=='') 41 $db_dsnr=$db_dsnw; 42 43 $this->db_dsnw = $db_dsnw; 44 $this->db_dsnr = $db_dsnr; 45 46 $dsn_array = DB::parseDSN($db_dsnw); 47 $this->db_provider = $dsn_array['phptype']; 48 } 49 50 51 // PHP 4 compatibility 52 function rcube_db($db_dsnw,$db_dsnr='') 53 { 54 $this->__construct($db_dsnw,$db_dsnr); 55 } 56 57 58 // Connect to specific database 59 function dsn_connect($dsn) 60 { 61 // Use persistent connections if available 62 $dbh = DB::connect($dsn, array('persistent' => TRUE)); 63 64 if (DB::isError($dbh)) 65 raise_error(array('code' => 500, 62 66 'type' => 'db', 63 67 'line' => __LINE__, … … 65 69 'message' => $dbh->getMessage()), TRUE, FALSE); 66 70 67 else if ($this->db_provider=='sqlite') 68 { 69 $dsn_array = DB::parseDSN($dsn); 70 if (!filesize($dsn_array['database']) && !empty($this->sqlite_initials)) 71 $this->_sqlite_create_database($dbh, $this->sqlite_initials); 72 } 73 74 return $dbh; 75 } 76 77 // Connect to appropiate databse 78 function db_connect ($mode) 79 { 80 $this->db_mode = $mode; 81 82 // Already connected 83 if ($this->db_connected) 84 { 85 // no replication, current connection is ok 86 if ($this->db_dsnw==$this->db_dsnr) return; 71 else if ($this->db_provider=='sqlite') 72 { 73 $dsn_array = DB::parseDSN($dsn); 74 if (!filesize($dsn_array['database']) && !empty($this->sqlite_initials)) 75 $this->_sqlite_create_database($dbh, $this->sqlite_initials); 76 } 77 78 return $dbh; 79 } 80 81 82 // Connect to appropiate databse 83 function db_connect ($mode) 84 { 85 $this->db_mode = $mode; 86 87 // Already connected 88 if ($this->db_connected) 89 { 90 // no replication, current connection is ok 91 if ($this->db_dsnw==$this->db_dsnr) 92 return; 87 93 88 // connected to master, current connection is ok 89 if ($this->db_mode=='w') return; 90 91 // Same mode, current connection is ok 92 if ($this->db_mode==$mode) return; 93 } 94 // connected to master, current connection is ok 95 if ($this->db_mode=='w') 96 return; 97 98 // Same mode, current connection is ok 99 if ($this->db_mode==$mode) 100 return; 101 } 94 102 95 if ($mode=='r') 96 $dsn=$this->db_dsnr; 97 else 98 $dsn=$this->db_dsnw; 99 100 $this->db_handle = $this->dsn_connect($dsn); 101 $this->db_connected = true; 102 } 103 104 // Query database 103 if ($mode=='r') 104 $dsn = $this->db_dsnr; 105 else 106 $dsn = $this->db_dsnw; 107 108 $this->db_handle = $this->dsn_connect($dsn); 109 $this->db_connected = true; 110 } 111 112 113 // Query database 114 function query() 115 { 116 $params = func_get_args(); 117 $query = array_shift($params); 118 119 return $this->_query($query, 0, 0, $params); 120 } 121 122 123 // Query with limits 124 function limitquery() 125 { 126 $params = func_get_args(); 127 $query = array_shift($params); 128 $offset = array_shift($params); 129 $numrows = array_shift($params); 130 131 return $this->_query($query, $offset, $numrows, $params); 132 } 133 134 135 function _query($query, $offset, $numrows, $params) 136 { 137 // Read or write ? 138 if (strtolower(trim(substr($query,0,6)))=='select') 139 $mode='r'; 140 else 141 $mode='w'; 142 143 $this->db_connect($mode); 144 145 if ($this->db_provider == 'sqlite') 146 $this->_sqlite_prepare(); 147 148 if ($numrows || $offset) 149 $result = $this->db_handle->limitQuery($query,$offset,$numrows,$params); 150 else 151 $result = $this->db_handle->query($query, $params); 152 153 // add result, even if it's an error 154 return $this->_add_result($result); 155 } 156 157 158 function num_rows($res_id=NULL) 159 { 160 if (!$this->db_handle) 161 return FALSE; 162 163 if ($result = $this->_get_result($res_id)) 164 return $result->numRows(); 165 else 166 return FALSE; 167 } 168 169 170 function affected_rows($res_id=NULL) 171 { 172 if (!$this->db_handle) 173 return FALSE; 174 175 return $this->db_handle->affectedRows(); 176 } 177 178 179 function insert_id($sequence = '') 180 { 181 if (!$this->db_handle || $this->db_mode=='r') 182 return FALSE; 183 184 switch($this->db_provider) 185 { 186 case 'pgsql': 187 // PostgreSQL uses sequences 188 $result =& $this->db_handle->getOne("SELECT CURRVAL('$sequence')"); 189 if (DB::isError($result)) 190 raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, 191 'message' => $result->getMessage()), TRUE, FALSE); 192 193 return $result; 194 195 case 'mysql': // This is unfortuneate 196 return mysql_insert_id($this->db_handle->connection); 197 198 case 'mysqli': 199 return mysqli_insert_id($this->db_handle->connection); 200 201 case 'sqlite': 202 return sqlite_last_insert_rowid($this->db_handle->connection); 203 204 default: 205 die("portability issue with this database, please have the developer fix"); 206 } 207 } 208 209 210 function fetch_assoc($res_id=NULL) 211 { 212 $result = $this->_get_result($res_id); 213 214 if (DB::isError($result)) 215 { 216 raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, 217 'message' => $this->db_link->getMessage()), TRUE, FALSE); 218 return FALSE; 219 } 220 221 return $result->fetchRow(DB_FETCHMODE_ASSOC); 222 } 223 224 225 function quote($input, $type=null) 226 { 227 if (!$this->db_handle) 228 $this->db_connect('r'); 229 230 return $this->db_handle->quote($input); 231 } 105 232 106 function query() 107 { 108 $params = func_get_args(); 109 $query = array_shift($params); 110 111 return $this->_query($query, 0, 0, $params); 112 } 113 114 function limitquery() 115 { 116 $params = func_get_args(); 117 $query = array_shift($params); 118 $offset = array_shift($params); 119 $numrows = array_shift($params); 120 121 return $this->_query($query, $offset, $numrows, $params); 122 } 233 234 function quoteIdentifier($str) 235 { 236 if (!$this->db_handle) 237 $this->db_connect('r'); 238 239 return $this->db_handle->quoteIdentifier($str); 240 } 241 242 243 function quote_identifier($str) 244 { 245 return $this->quoteIdentifier($str); 246 } 247 248 249 function unixtimestamp($field) 250 { 251 switch($this->db_provider) 252 { 253 case 'pgsql': 254 return "EXTRACT (EPOCH FROM $field)"; 255 break; 256 257 default: 258 return "UNIX_TIMESTAMP($field)"; 259 } 260 } 261 262 263 function fromunixtime($timestamp) 264 { 265 switch($this->db_provider) 266 { 267 case 'mysqli': 268 case 'mysql': 269 case 'sqlite': 270 return "FROM_UNIXTIME($timestamp)"; 271 272 default: 273 return date("'Y-m-d H:i:s'", $timestamp); 274 } 275 } 276 277 278 function _add_result($res) 279 { 280 // sql error occured 281 if (DB::isError($res)) 282 { 283 raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, 284 'message' => $res->getMessage() . " Query: " . substr(preg_replace('/[\r\n]+\s*/', ' ', $res->userinfo), 0, 1024)), TRUE, FALSE); 285 return FALSE; 286 } 287 else 288 { 289 $res_id = sizeof($this->a_query_results); 290 $this->a_query_results[$res_id] = $res; 291 $this->last_res_id = $res_id; 292 return $res_id; 293 } 294 } 295 296 297 function _get_result($res_id) 298 { 299 if ($res_id==NULL) 300 $res_id = $this->last_res_id; 123 301 124 function _query($query, $offset, $numrows, $params) 125 { 126 // Read or write ? 127 if (strtolower(trim(substr($query,0,6)))=='select') 128 $mode='r'; 129 else 130 $mode='w'; 131 132 $this->db_connect($mode); 133 134 if ($this->db_provider == 'sqlite') 135 $query = $this->_sqlite_prepare_query($query); 136 137 if ($numrows || $offset) 138 { 139 $result = $this->db_handle->limitQuery($query,$offset,$numrows,$params); 140 } 141 else 142 $result = $this->db_handle->query($query, $params); 143 144 if (DB::isError($result)) 145 { 146 raise_error(array('code' => 500, 147 'type' => 'db', 148 'line' => __LINE__, 149 'file' => __FILE__, 150 'message' => $result->getMessage().'; QUERY: '.$query), TRUE, FALSE); 151 return false; 152 } 153 154 return $this->_add_result($result, $query); 155 } 156 157 function num_rows($res_id=NULL) 158 { 159 if (!$this->db_handle) 160 return FALSE; 161 162 $result = $this->_get_result($res_id); 163 164 if ($result) 165 return $result->numRows(); 166 else 167 return FALSE; 168 } 169 170 function affected_rows($res_id=NULL) 171 { 172 if (!$this->db_handle) 173 return FALSE; 174 175 return $this->db_handle->affectedRows(); 176 } 177 178 function insert_id($sequence = '') 179 { 180 if (!$this->db_handle || $this->db_mode=='r') 181 return FALSE; 182 183 switch($this->db_provider) 184 { 185 case 'pgsql': 186 // PostgreSQL uses sequences 187 $result =& $this->db_handle->getOne("SELECT CURRVAL('$sequence')"); 188 if (DB::isError($result)) { 189 raise_error( array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, 190 'message' => $result->getMessage()), TRUE, TRUE); 191 } 192 return $result; 193 194 case 'mysql': // This is unfortuneate 195 return mysql_insert_id($this->db_handle->connection); 196 197 case 'mysqli': 198 return mysqli_insert_id($this->db_handle->connection); 199 200 case 'sqlite': 201 return sqlite_last_insert_rowid($this->db_handle->connection); 202 203 default: 204 die("portability issue with this database, please have the developer fix"); 205 } 206 } 207 208 209 function fetch_assoc($res_id=NULL) 210 { 211 $result = $this->_get_result($res_id); 212 213 if (DB::isError($result)) 214 { 215 raise_error( array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, 216 'message' => $this->db_link->getMessage()), TRUE, FALSE); 217 return FALSE; 218 } 219 220 return $result->fetchRow(DB_FETCHMODE_ASSOC); 221 } 222 223 224 function quote($input, $type=null) 225 { 226 if (!$this->db_handle) 227 $this->db_connect('r'); 228 229 return $this->db_handle->quote($input); 230 } 231 232 233 function quoteIdentifier($str) 234 { 235 if (!$this->db_handle) 236 $this->db_connect('r'); 237 238 return $this->db_handle->quoteIdentifier($str); 239 } 240 241 function quote_identifier($str) 242 { 243 return $this->quoteIdentifier($str); 244 } 245 246 247 function unixtimestamp($field) 248 { 249 switch($this->db_provider) 250 { 251 case 'pgsql': 252 return "EXTRACT (EPOCH FROM $field)"; 253 break; 254 default: 255 return "UNIX_TIMESTAMP($field)"; 256 } 257 } 258 259 function _add_result($res, $query) 260 { 261 // sql error occured 262 if (DB::isError($res)) 263 { 264 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); 265 return FALSE; 266 } 267 else 268 { 269 $res_id = sizeof($this->a_query_results); 270 $this->a_query_results[$res_id] = $res; 271 $this->last_res_id = $res_id; 272 return $res_id; 273 } 274 } 275 276 277 function _get_result($res_id) 278 { 279 if ($res_id==NULL) 280 $res_id = $this->last_res_id; 281 282 if ($res_id && isset($this->a_query_results[$res_id])) 283 return $this->a_query_results[$res_id]; 284 else 285 return FALSE; 286 } 287 288 289 // create a sqlite database from a file 290 function _sqlite_create_database($dbh, $fileName) 291 { 292 if (empty($fileName) || !is_string($fileName)) 293 return ; 294 295 $data = ''; 296 if ($fd = fopen($fileName, 'r')) 297 { 298 $data = fread($fd, filesize($fileName)); 299 fclose($fd); 300 } 301 302 if (strlen($data)) 303 sqlite_exec($dbh->connection, $data); 304 } 305 306 // transform a query so that it is sqlite2 compliant 307 function _sqlite_prepare_query($query) 308 { 309 if (!is_string($query)) 310 return ($query); 311 312 $search = array('/NOW\(\)/i', '/`/'); 313 $replace = array("datetime('now')", '"'); 314 $query = preg_replace($search, $replace, $query); 315 316 return ($query); 317 } 318 319 } 302 if ($res_id && isset($this->a_query_results[$res_id])) 303 return $this->a_query_results[$res_id]; 304 else 305 return FALSE; 306 } 307 308 309 // create a sqlite database from a file 310 function _sqlite_create_database($dbh, $fileName) 311 { 312 if (empty($fileName) || !is_string($fileName)) 313 return ; 314 315 $data = ''; 316 if ($fd = fopen($fileName, 'r')) 317 { 318 $data = fread($fd, filesize($fileName)); 319 fclose($fd); 320 } 321 322 if (strlen($data)) 323 sqlite_exec($dbh->connection, $data); 324 } 325 326 function _sqlite_prepare() 327 { 328 include_once('include/rcube_sqlite.inc'); 329 330 // we emulate via callback some missing MySQL function 331 sqlite_create_function($this->db_handle->connection, "from_unixtime", "rcube_sqlite_from_unixtime"); 332 sqlite_create_function($this->db_handle->connection, "unix_timestamp", "rcube_sqlite_unix_timestamp"); 333 sqlite_create_function($this->db_handle->connection, "now", "rcube_sqlite_now"); 334 sqlite_create_function($this->db_handle->connection, "md5", "rcube_sqlite_md5"); 335 } 336 337 /* 338 // transform a query so that it is sqlite2 compliant 339 function _sqlite_prepare_query($query) 340 { 341 if (!is_string($query)) 342 return ($query); 343 344 345 $search = array('/NOW\(\)/i', '/`/'); 346 $replace = array("datetime('now')", '"'); 347 $query = preg_replace($search, $replace, $query); 348 349 return ($query); 350 } 351 */ 352 } // end class rcube_db 320 353 321 354 ?> -
program/include/rcube_imap.inc
r4b0f65a r1cded85 29 29 class rcube_imap 30 30 { 31 var $db; 31 32 var $conn; 32 33 var $root_ns = ''; … … 39 40 var $default_folders = array('inbox', 'drafts', 'sent', 'junk', 'trash'); 40 41 var $cache = array(); 42 var $cache_keys = array(); 41 43 var $cache_changes = array(); 42 44 var $uid_id_map = array(); 43 45 var $msg_headers = array(); 46 var $capabilities = array(); 44 47 45 48 46 49 // PHP 5 constructor 47 function __construct( )48 { 49 50 function __construct($db_conn) 51 { 52 $this->db = $db_conn; 50 53 } 51 54 52 55 // PHP 4 compatibility 53 function rcube_imap( )54 { 55 $this->__construct( );56 function rcube_imap($db_conn) 57 { 58 $this->__construct($db_conn); 56 59 } 57 60 … … 96 99 if ($this->conn) 97 100 { 101 $this->_parse_capability($this->conn->capability); 98 102 iil_C_NameSpace($this->conn); 99 103 … … 183 187 { 184 188 return $this->conn ? $this->_mod_mailbox($this->mailbox, 'out') : ''; 189 } 190 191 192 function get_capability($cap) 193 { 194 $cap = strtoupper($cap); 195 return $this->capabilities[$cap]; 185 196 } 186 197 … … 299 310 300 311 // private method for listing message header 301 // by DrSlump <drslump@drslump.biz> 302 function __list_headers($mailbox='', $page=NULL, $sort_field='date', $sort_order='DESC') 303 { 304 $a_out = array(); 305 $cached_count = 0; 306 312 function _list_headers($mailbox='', $page=NULL, $sort_field='date', $sort_order='DESC') 313 { 307 314 if (!strlen($mailbox)) 308 return $a_out; 309 310 $mbox_count = $this->_messagecount($mailbox /*, 'ALL', TRUE*/); 311 312 $revalidate = false; 313 if ($mbox_count) 314 { 315 // get cached headers 316 $a_out = $this->get_cache($mailbox.'.msg'); 317 $a_out = is_array($a_out) ? $a_out : array(); // make sure we get an array 318 319 $cached_count = count($a_out); 320 $a_new = array(); 321 $revalidate = true; // revalidate by default 322 323 // if the cache count is greater then there have been changes for sure 324 if ($cached_count <= $mbox_count) 325 { 326 $from = $cached_count?$cached_count:1; 327 328 //get new headers (at least one is returned) 329 $a_temp = iil_C_FetchHeaders($this->conn, $mailbox, $from . ':' . $mbox_count); 330 $duplicated = $cached_count?true:false; 331 332 foreach ($a_temp as $hdr) 315 return array(); 316 317 $max = $this->_messagecount($mailbox); 318 $start_msg = ($this->list_page-1) * $this->page_size; 319 320 if ($page=='all') 321 { 322 $begin = 0; 323 $end = $max; 324 } 325 else if ($sort_order=='DESC') 326 { 327 $begin = $max - $this->page_size - $start_msg; 328 $end = $max - $start_msg; 329 } 330 else 331 { 332 $begin = $start_msg; 333 $end = $start_msg + $this->page_size; 334 } 335 336 if ($begin < 0) $begin = 0; 337 if ($end < 0) $end = $max; 338 if ($end > $max) $end = $max; 339 340 //console("fetch headers $start_msg to ".($start_msg+$this->page_size)." (msg $begin to $end)"); 341 342 $headers_sorted = FALSE; 343 $cache_key = $mailbox.'.msg'; 344 $cache_status = $this->check_cache_status($mailbox, $cache_key); 345 346 //console("Cache status = $cache_status"); 347 348 // cache is OK, we can get all messages from local cache 349 if ($cache_status>0) 350 { 351 $a_msg_headers = $this->get_message_cache($cache_key, $start_msg, $start_msg+$this->page_size, $sort_field, $sort_order); 352 $headers_sorted = TRUE; 353 } 354 else 355 { 356 // retrieve headers from IMAP 357 if ($this->get_capability('sort') && ($msg_index = iil_C_Sort($this->conn, $mailbox, $sort_field))) 358 { 359 //console("$mailbox: ".count($msg_index)); 360 361 $msgs = $msg_index[$begin]; 362 for ($i=$begin; $i < $end; $i++) 333 363 { 334 //skip the first one if duplicated 335 if ($duplicated) 364 if ($sort_order == 'DESC') 365 $msgs = $msg_index[$i].','.$msgs; 366 else 367 $msgs = $msgs.','.$msg_index[$i]; 368 } 369 370 $sorted = TRUE; 371 } 372 else 373 { 374 $msgs = sprintf("%d:%d", $begin+1, $end); 375 $sorted = FALSE; 376 } 377 378 379 // cache is dirty, sync it 380 if ($this->caching_enabled && $cache_status==-1) 381 { 382 $this->sync_header_index($mailbox); 383 return $this->_list_headers($mailbox, $page, $sort_field, $sort_order); 384 } 385 386 387 // cache is incomplete 388 $cache_index = $this->get_message_cache_index($cache_key); 389 390 // fetch reuested headers from server 391 $a_header_index = iil_C_FetchHeaders($this->conn, $mailbox, $msgs); 392 $a_msg_headers = array(); 393 394 395 if (!empty($a_header_index)) 396 { 397 foreach ($a_header_index as $i => $headers) 398 { 399 if ($headers->deleted) 336 400 { 337 //check for changes using the UID 338 $lastCacheHdr = end($a_out); 339 if ($hdr->uid === $lastCacheHdr->uid) 340 $revalidate = false; 341 342 $duplicated = false; 401 // delete from cache 402 if ($cache_index[$headers->id] && $cache_index[$headers->id] == $headers->uid) 403 $this->remove_message_cache($cache_key, $headers->id); 404 343 405 continue; 344 406 } 345 346 //skip deleted ones 347 if (! $hdr->deleted) 348 $a_new[ $hdr->uid ] = $hdr; 407 408 // add message to cache 409 if ($this->caching_enabled && $cache_index[$headers->id] != $headers->uid) 410 $this->add_message_cache($cache_key, $headers->id, $headers); 411 412 $a_msg_headers[$headers->uid] = $headers; 349 413 } 350 414 } 351 415 352 //revalidate cache if needed 353 $to = $mbox_count - count($a_new); 354 if ($revalidate && $to !== 0) //we'll need to reindex the array so we have to make a copy 355 { 356 $a_dirty = $a_out; 357 $a_out = array(); 358 $a_buffers = array(); 359 360 //fetch chunks of 20 headers 361 $step = 20; 362 $found = false; 363 364 //fetch headers in blocks starting from new to old 365 do { 366 $from = $to-$step; 367 if ($from < 1) $from = 1; 368 369 //store the block in a temporal buffer 370 $a_buffers[$from] = iil_C_FetchHeaders($this->conn, $mailbox, $from . ':' . $to); 371 372 //compare the fetched headers with the ones in the cache 373 $idx = 0; 374 foreach ($a_buffers[$from] as $k=>$hdr) 375 { 376 //if it's different the comparison ends 377 if (!isset($a_dirty[$hdr->uid]) || $a_dirty[$hdr->uid]->id !== $hdr->id) 378 break; 379 380 //if we arrive here then we know that the older messages in cache are ok 381 $found = $hdr->id; 382 $idx++; 383 } 384 385 //remove from the buffer the headers which are already cached 386 if ($found) 387 $a_buffers[$from] = array_splice($a_buffers[$from], 0, $idx ); 388 389 $to = $from-1; 390 } 391 while ($found===false && $from > 1); 392 393 //just keep the headers we are certain that didn't change in the cache 394 if ($found !== false) 395 { 396 foreach ($a_dirty as $hdr) 397 { 398 if ($hdr->id > $found) break; 399 $a_out[$hdr->uid] = $hdr; 400 } 401 } 402 403 //we builded the block buffers from new to older, we process them in reverse order 404 ksort($a_buffers, SORT_NUMERIC); 405 foreach ($a_buffers as $a_buff) 406 { 407 foreach ($a_buff as $hdr) 408 { 409 if (! $hdr->deleted) 410 $a_out[$hdr->uid] = $hdr; 411 } 412 } 413 } 414 415 //array_merge() would reindex the keys, so we use this 'hack' 416 $a_out += $a_new; 417 } 418 419 //write headers list to cache if needed 420 if ($revalidate || count($a_out)!=$cached_count) { 421 $this->update_cache($mailbox.'.msg', $a_out); 422 } 423 424 //sort headers by a specific col 425 $a_out = iil_SortHeaders( $a_out, $sort_field, $sort_order ); 426 427 // return complete list of messages 428 if (strtolower($page)=='all') 429 return $a_out; 430 431 $start_msg = ($this->list_page-1) * $this->page_size; 432 return array_slice($a_out, $start_msg, $this->page_size); 433 } 434 435 436 // original function; replaced 2005/10/18 437 // private method for listing message header 438 function _list_headers($mailbox='', $page=NULL, $sort_field='date', $sort_order='DESC') 439 { 440 $max = $this->_messagecount($mailbox); 441 442 if (!strlen($mailbox)) 443 return array(); 444 445 // get cached headers 446 $a_msg_headers = $this->get_cache($mailbox.'.msg'); 447 448 // retrieve headers from IMAP 449 if (!is_array($a_msg_headers) || sizeof($a_msg_headers) != $max) 450 { 451 $a_header_index = iil_C_FetchHeaders($this->conn, $mailbox, "1:$max"); 452 $a_msg_headers = array(); 453 454 if (!empty($a_header_index)) 455 foreach ($a_header_index as $i => $headers) 456 if (!$headers->deleted) 457 $a_msg_headers[$headers->uid] = $headers; 458 } 459 else 460 $headers_cached = TRUE; 461 462 if (!is_array($a_msg_headers)) 416 // delete cached messages with a higher index than $max 417 $this->clear_message_cache($cache_key, $max); 418 419 420 // kick child process to sync cache 421 422 } 423 424 425 // return empty array if no messages found 426 if (!is_array($a_msg_headers) || empty($a_msg_headers)) 463 427 return array(); 464 465 // sort headers by a specific col 466 $a_headers = iil_SortHeaders($a_msg_headers, $sort_field, $sort_order); 467 $headers_count = count($a_headers); 468 469 // free memory 470 unset($a_msg_headers); 471 472 // write headers list to cache 473 if (!$headers_cached) 474 $this->update_cache($mailbox.'.msg', $a_headers); 475 476 // update message count cache 477 $a_mailbox_cache = $this->get_cache('messagecount'); 478 if (isset($a_mailbox_cache[$mailbox]['ALL']) && $a_mailbox_cache[$mailbox]['ALL'] != $headers_count) 479 { 480 $a_mailbox_cache[$mailbox]['ALL'] = (int)$headers_count; 481 $this->update_cache('messagecount', $a_mailbox_cache); 482 } 483 484 if (empty($a_headers)) 485 return array(); 486 487 // return complete list of messages 488 if (strtolower($page)=='all') 489 return $a_headers; 490 491 $start_msg = ($this->list_page-1) * $this->page_size; 492 return array_slice($a_headers, $start_msg, $this->page_size); 493 } 494 428 429 430 // if not already sorted 431 if (!$headers_sorted) 432 $a_msg_headers = iil_SortHeaders($a_msg_headers, $sort_field, $sort_order); 433 434 return array_values($a_msg_headers); 435 } 436 495 437 496 438 // return sorted array of message UIDs … … 511 453 512 454 513 function sync_header_index($mbox=NULL) 514 { 515 455 function sync_header_index($mailbox) 456 { 457 $cache_key = $mailbox.'.msg'; 458 $cache_index = $this->get_message_cache_index($cache_key); 459 $msg_count = $this->_messagecount($mailbox); 460 461 // fetch complete message index 462 $a_message_index = iil_C_FetchHeaderIndex($this->conn, $mailbox, "1:$msg_count", 'UID'); 463 464 foreach ($a_message_index as $id => $uid) 465 { 466 // message in cache at correct position 467 if ($cache_index[$id] == $uid) 468 { 469 // console("$id / $uid: OK"); 470 unset($cache_index[$id]); 471 continue; 472 } 473 474 // message in cache but in wrong position 475 if (in_array((string)$uid, $cache_index, TRUE)) 476 { 477 // console("$id / $uid: Moved"); 478 unset($cache_index[$id]); 479 } 480 481 // other message at this position 482 if (isset($cache_index[$id])) 483 { 484 // console("$id / $uid: Delete"); 485 $this->remove_message_cache($cache_key, $id); 486 unset($cache_index[$id]); 487 } 488 489 490 // console("$id / $uid: Add"); 491 492 // fetch complete headers and add to cache 493 $headers = iil_C_FetchHeader($this->conn, $mailbox, $id); 494 $this->add_message_cache($cache_key, $headers->id, $headers); 495 } 496 497 // those ids that are still in cache_index have been deleted 498 if (!empty($cache_index)) 499 { 500 foreach ($cache_index as $id => $uid) 501 $this->remove_message_cache($cache_key, $id); 502 } 516 503 } 517 504 … … 528 515 { 529 516 $mailbox = $mbox ? $this->_mod_mailbox($mbox) : $this->mailbox; 530 517 531 518 // get cached headers 532 $a_msg_headers = $this->get_cache($mailbox.'.msg'); 533 534 // return cached header 535 if ($a_msg_headers[$uid]) 536 return $a_msg_headers[$uid]; 519 if ($headers = $this->get_cached_message($mailbox.'.msg', $uid)) 520 return $headers; 537 521 538 522 $msg_id = $this->_uid2id($uid); 539 $header = iil_C_FetchHeader($this->conn, $mailbox, $msg_id);523 $headers = iil_C_FetchHeader($this->conn, $mailbox, $msg_id); 540 524 541 525 // write headers cache 542 $a_msg_headers[$uid] = $header;543 $this->update_cache($mailbox.'.msg', $a_msg_headers);544 545 return $header ;526 if ($headers) 527 $this->add_message_cache($mailbox.'.msg', $msg_id, $headers); 528 529 return $headers; 546 530 } 547 531 … … 596 580 // reload message headers if cached 597 581 $cache_key = $this->mailbox.'.msg'; 598 if ($this->caching_enabled && $result && ($a_cached_headers = $this->get_cache($cache_key))) 599 { 582 if ($this->caching_enabled) 583 { 584 foreach ($msg_ids as $id) 585 { 586 if ($cached_headers = $this->get_cached_message($cache_key, $id)) 587 { 588 $this->remove_message_cache($cache_key, $id); 589 //$this->get_headers($uid); 590 } 591 } 592 600 593 // close and re-open connection 594 // this prevents connection problems with Courier 601 595 $this->reconnect(); 602 603 foreach ($uids as $uid)604 {605 if (isset($a_cached_headers[$uid]))606 {607 unset($this->cache[$cache_key][$uid]);608 $this->get_headers($uid);609 }610 }611 596 } 612 597 … … 634 619 if (in_array($mailbox, $this->_list_mailboxes())) 635 620 $saved = iil_C_Append($this->conn, $mailbox, $message); 636 621 637 622 if ($saved) 638 623 { … … 673 658 if ($moved) 674 659 { 675 $this->expunge($from_mbox, FALSE); 676 $this->clear_cache($to_mbox.'.msg'); 660 $this->_expunge($from_mbox, FALSE); 677 661 $this->_clear_messagecount($from_mbox); 678 662 $this->_clear_messagecount($to_mbox); … … 681 665 // update cached message headers 682 666 $cache_key = $from_mbox.'.msg'; 683 if ($moved && ($a_cached_headers = $this->get_cache($cache_key))) 684 { 667 if ($moved && ($a_cache_index = $this->get_message_cache_index($cache_key))) 668 { 669 $start_index = 100000; 685 670 foreach ($a_uids as $uid) 686 unset($a_cached_headers[$uid]); 687 688 $this->update_cache($cache_key, $a_cached_headers); 671 { 672 $index = array_search($uid, $a_cache_index); 673 $start_index = min($index, $start_index); 674 } 675 676 // clear cache from the lowest index on 677 $this->clear_message_cache($cache_key, $start_index); 689 678 } 690 679 … … 717 706 if ($deleted) 718 707 { 719 $this-> expunge($mailbox, FALSE);708 $this->_expunge($mailbox, FALSE); 720 709 $this->_clear_messagecount($mailbox); 721 710 } 722 711 723 712 // remove deleted messages from cache 724 if ($deleted && ($a_cached_headers = $this->get_cache($mailbox.'.msg'))) 725 { 713 $cache_key = $mailbox.'.msg'; 714 if ($deleted && ($a_cache_index = $this->get_message_cache_index($cache_key))) 715 { 716 $start_index = 100000; 726 717 foreach ($a_uids as $uid) 727 unset($a_cached_headers[$uid]); 728 729 $this->update_cache($mailbox.'.msg', $a_cached_headers); 718 { 719 $index = array_search($uid, $a_cache_index); 720 $start_index = min($index, $start_index); 721 } 722 723 // clear cache from the lowest index on 724 $this->clear_message_cache($cache_key, $start_index); 730 725 } 731 726 … … 741 736 742 737 if ($msg_count>0) 738 { 739 $this->clear_message_cache($mailbox.'.msg'); 743 740 return iil_C_ClearFolder($this->conn, $mailbox); 741 } 744 742 else 745 743 return 0; … … 751 749 { 752 750 $mailbox = $mbox ? $this->_mod_mailbox($mbox) : $this->mailbox; 753 751 return $this->_expunge($mailbox, $clear_cache); 752 } 753 754 755 // send IMAP expunge command and clear cache 756 function _expunge($mailbox, $clear_cache=TRUE) 757 { 754 758 $result = iil_C_Expunge($this->conn, $mailbox); 755 759 756 760 if ($result>=0 && $clear_cache) 757 761 { 758 $this->clear_cache($mailbox.'.msg');762 //$this->clear_message_cache($mailbox.'.msg'); 759 763 $this->_clear_messagecount($mailbox); 760 764 } … … 762 766 return $result; 763 767 } 764 765 768 766 769 … … 825 828 { 826 829 $result = FALSE; 830 831 // replace backslashes 832 $name = preg_replace('/[\\\]+/', '-', $name); 833 827 834 $name_enc = UTF7EncodeString($name); 835 836 // reduce mailbox name to 100 chars 837 $name_enc = substr($name_enc, 0, 100); 838 828 839 $abs_name = $this->_mod_mailbox($name_enc); 829 840 $a_mailbox_cache = $this->get_cache('mailboxes'); 830 831 //if (strlen($this->root_ns)) 832 // $abs_name = $this->root_ns.$abs_name; 833 841 834 842 if (strlen($abs_name) && (!is_array($a_mailbox_cache) || !in_array($abs_name, $a_mailbox_cache))) 835 843 $result = iil_C_CreateFolder($this->conn, $abs_name); … … 876 884 // clear mailboxlist cache 877 885 if ($deleted) 886 { 887 $this->clear_message_cache($mailbox.'.msg'); 878 888 $this->clear_cache('mailboxes'); 879 880 return $updated; 889 } 890 891 return $deleted; 881 892 } 882 893 … … 885 896 886 897 /* -------------------------------- 887 * internal caching functions898 * internal caching methods 888 899 * --------------------------------*/ 889 900 … … 891 902 function set_caching($set) 892 903 { 893 if ($set && function_exists('rcube_read_cache'))904 if ($set && is_object($this->db)) 894 905 $this->caching_enabled = TRUE; 895 906 else … … 897 908 } 898 909 910 899 911 function get_cache($key) 900 912 { … … 902 914 if (!isset($this->cache[$key]) && $this->caching_enabled) 903 915 { 904 $cache_data = rcube_read_cache('IMAP.'.$key);916 $cache_data = $this->_read_cache_record('IMAP.'.$key); 905 917 $this->cache[$key] = strlen($cache_data) ? unserialize($cache_data) : FALSE; 906 918 } 907 919 908 return $this->cache[$key]; 920 return $this->cache[$key]; 909 921 } 910 922 … … 925 937 { 926 938 if ($this->cache_changes[$key]) 927 rcube_write_cache('IMAP.'.$key, serialize($data));939 $this->_write_cache_record('IMAP.'.$key, serialize($data)); 928 940 } 929 941 } … … 936 948 { 937 949 foreach ($this->cache as $key => $data) 938 rcube_clear_cache('IMAP.'.$key);950 $this->_clear_cache_record('IMAP.'.$key); 939 951 940 952 $this->cache = array(); … … 944 956 else 945 957 { 946 rcube_clear_cache('IMAP.'.$key);958 $this->_clear_cache_record('IMAP.'.$key); 947 959 $this->cache_changes[$key] = FALSE; 948 960 unset($this->cache[$key]); … … 952 964 953 965 966 function _read_cache_record($key) 967 { 968 $cache_data = FALSE; 969 970 if ($this->db) 971 { 972 // get cached data from DB 973 $sql_result = $this->db->query( 974 "SELECT cache_id, data 975 FROM ".get_table_name('cache')." 976 WHERE user_id=? 977 AND cache_key=?", 978 $_SESSION['user_id'], 979 $key); 980 981 if ($sql_arr = $this->db->fetch_assoc($sql_result)) 982 { 983 $cache_data = $sql_arr['data']; 984 $this->cache_keys[$key] = $sql_arr['cache_id']; 985 } 986 } 987 988 return $cache_data; 989 } 990 991 992 function _write_cache_record($key, $data) 993 { 994 if (!$this->db) 995 return FALSE; 996 997 // check if we already have a cache entry for this key 998 if (!isset($this->cache_keys[$key])) 999 { 1000 $sql_result = $this->db->query( 1001 "SELECT cache_id 1002 FROM ".get_table_name('cache')." 1003 WHERE user_id=? 1004 AND cache_key=?", 1005 $_SESSION['user_id'], 1006 $key); 1007 1008 if ($sql_arr = $this->db->fetch_assoc($sql_result)) 1009 $this->cache_keys[$key] = $sql_arr['cache_id']; 1010 else 1011 $this->cache_keys[$key] = FALSE; 1012 } 1013 1014 // update existing cache record 1015 if ($this->cache_keys[$key]) 1016 { 1017 $this->db->query( 1018 "UPDATE ".get_table_name('cache')." 1019 SET created=now(), 1020 data=? 1021 WHERE user_id=? 1022 AND cache_key=?", 1023 $data, 1024 $_SESSION['user_id'], 1025 $key); 1026 } 1027 // add new cache record 1028 else 1029 { 1030 $this->db->query( 1031 "INSERT INTO ".get_table_name('cache')." 1032 (created, user_id, cache_key, data) 1033 VALUES (now(), ?, ?, ?)", 1034 $_SESSION['user_id'], 1035 $key, 1036 $data); 1037 } 1038 } 1039 1040 1041 function _clear_cache_record($key) 1042 { 1043 $this->db->query( 1044 "DELETE FROM ".get_table_name('cache')." 1045 WHERE user_id=? 1046 AND cache_key=?", 1047 $_SESSION['user_id'], 1048 $key); 1049 } 1050 1051 1052 954 1053 /* -------------------------------- 955 * encoding/decoding functions 1054 * message caching methods 1055 * --------------------------------*/ 1056 1057 1058 // checks if the cache is up-to-date 1059 // return: -3 = off, -2 = incomplete, -1 = dirty 1060 function check_cache_status($mailbox, $cache_key) 1061 { 1062 if (!$this->caching_enabled) 1063 return -3; 1064 1065 $cache_index = $this->get_message_cache_index($cache_key, TRUE); 1066 $msg_count = $this->_messagecount($mailbox); 1067 $cache_count = count($cache_index); 1068 1069 // console("Cache check: $msg_count !== ".count($cache_index)); 1070 1071 if ($cache_count==$msg_count) 1072 { 1073 // get highest index 1074 $header = iil_C_FetchHeader($this->conn, $mailbox, "$msg_count"); 1075 $cache_uid = array_pop($cache_index); 1076 1077 // uids of highes message matches -> cache seems OK 1078 if ($cache_uid == $header->uid) 1079 return 1; 1080 1081 // cache is dirty 1082 return -1; 1083 } 1084 // if cache count differs less that 10% report as dirty 1085 else if (abs($msg_count - $cache_count) < $msg_count/10) 1086 return -1; 1087 else 1088 return -2; 1089 } 1090 1091 1092 1093 function get_message_cache($key, $from, $to, $sort_field, $sort_order) 1094 { 1095 $cache_key = "$key:$from:$to:$sort_field:$sort_order"; 1096 $db_header_fields = array('idx', 'uid', 'subject', 'from', 'to', 'cc', 'date', 'size'); 1097 1098 if (!in_array($sort_field, $db_header_fields)) 1099 $sort_field = 'idx'; 1100 1101 if ($this->caching_enabled && !isset($this->cache[$cache_key])) 1102 { 1103 $this->cache[$cache_key] = array(); 1104 $sql_result = $this->db->limitquery( 1105 "SELECT idx, uid, headers 1106 FROM ".get_table_name('messages')." 1107 WHERE user_id=? 1108 AND cache_key=? 1109 ORDER BY ".$this->db->quoteIdentifier($sort_field)." ". 1110 strtoupper($sort_order), 1111 $from, 1112 $to-$from, 1113 $_SESSION['user_id'], 1114 $key); 1115 1116 while ($sql_arr = $this->db->fetch_assoc($sql_result)) 1117 { 1118 $uid = $sql_arr['uid']; 1119 $this->cache[$cache_key][$uid] = unserialize($sql_arr['headers']); 1120 } 1121 } 1122 1123 return $this->cache[$cache_key]; 1124 } 1125 1126 1127 function get_cached_message($key, $uid, $body=FALSE) 1128 { 1129 if (!$this->caching_enabled) 1130 return FALSE; 1131 1132 $internal_key = '__single_msg'; 1133 if ($this->caching_enabled && (!isset($this->cache[$internal_key][$uid]) || $body)) 1134 { 1135 $sql_select = "idx, uid, headers"; 1136 if ($body) 1137 $sql_select .= ", body"; 1138 1139 $sql_result = $this->db->query( 1140 "SELECT $sql_select 1141 FROM ".get_table_name('messages')." 1142 WHERE user_id=? 1143 AND cache_key=? 1144 AND uid=?", 1145 $_SESSION['user_id'], 1146 $key, 1147 $uid); 1148 1149 if ($sql_arr = $this->db->fetch_assoc($sql_result)) 1150 { 1151 $headers = unserialize($sql_arr['headers']); 1152 if (is_object($headers) && !empty($sql_arr['body'])) 1153 $headers->body = $sql_arr['body']; 1154 1155 $this->cache[$internal_key][$uid] = $headers; 1156 } 1157 } 1158 1159 return $this->cache[$internal_key][$uid]; 1160 } 1161 1162 1163 function get_message_cache_index($key, $force=FALSE) 1164 { 1165 static $sa_message_index = array(); 1166 1167 if (!empty($sa_message_index[$key]) && !$force) 1168 return $sa_message_index[$key]; 1169 1170 $sa_message_index[$key] = array(); 1171 $sql_result = $this->db->query( 1172 "SELECT idx, uid 1173 FROM ".get_table_name('messages')." 1174 WHERE user_id=? 1175 AND cache_key=? 1176 ORDER BY idx ASC", 1177 $_SESSION['user_id'], 1178 $key); 1179 1180 while ($sql_arr = $this->db->fetch_assoc($sql_result)) 1181 $sa_message_index[$key][$sql_arr['idx']] = $sql_arr['uid']; 1182 1183 return $sa_message_index[$key]; 1184 } 1185 1186 1187 function add_message_cache($key, $index, $headers) 1188 { 1189 $this->db->query( 1190 "INSERT INTO ".get_table_name('messages')." 1191 (user_id, del, cache_key, idx, uid, subject, ".$this->db->quoteIdentifier('from').", ".$this->db->quoteIdentifier('to').", cc, date, size, headers) 1192 VALUES (?, 0, ?, ?, ?, ?, ?, ?, ?, ".$this->db->fromunixtime($headers->timestamp).", ?, ?)", 1193 $_SESSION['user_id'], 1194 $key, 1195 $index, 1196 $headers->uid, 1197 $this->decode_header($headers->subject, TRUE), 1198 $this->decode_header($headers->from, TRUE), 1199 $this->decode_header($headers->to, TRUE), 1200 $this->decode_header($headers->cc, TRUE), 1201 $headers->size, 1202 serialize($headers)); 1203 } 1204 1205 1206 function remove_message_cache($key, $index) 1207 { 1208 $this->db->query( 1209 "DELETE FROM ".get_table_name('messages')." 1210 WHERE user_id=? 1211 AND cache_key=? 1212 AND idx=?", 1213 $_SESSION['user_id'], 1214 $key, 1215 $index); 1216 } 1217 1218 1219 function clear_message_cache($key, $start_index=1) 1220 { 1221 $this->db->query( 1222 "DELETE FROM ".get_table_name('messages')." 1223 WHERE user_id=? 1224 AND cache_key=? 1225 AND idx>=?", 1226 $_SESSION['user_id'], 1227 $key, 1228 $start_index); 1229 } 1230 1231 1232 1233 1234 /* -------------------------------- 1235 * encoding/decoding methods 956 1236 * --------------------------------*/ 957 1237 … … 987 1267 988 1268 989 function decode_header($input) 990 { 991 return $this->decode_mime_string($input); 1269 function decode_header($input, $remove_quotes=FALSE) 1270 { 1271 $str = $this->decode_mime_string($input); 1272 if ($str{0}=='"' && $remove_quotes) 1273 { 1274 $str = str_replace('"', '', $str); 1275 } 1276 1277 return $str; 992 1278 } 993 1279 … … 1095 1381 1096 1382 1383 1097 1384 /* -------------------------------- 1098 1385 * private methods … … 1147 1434 1148 1435 return $this->uid_id_map[$mbox][$uid]; 1436 } 1437 1438 1439 // parse string or array of server capabilities and put them in internal array 1440 function _parse_capability($caps) 1441 { 1442 if (!is_array($caps)) 1443 $cap_arr = explode(' ', $caps); 1444 else 1445 $cap_arr = $caps; 1446 1447 foreach ($cap_arr as $cap) 1448 { 1449 if ($cap=='CAPABILITY') 1450 continue; 1451 1452 if (strpos($cap, '=')>0) 1453 { 1454 list($key, $value) = explode('=', $cap); 1455 if (!is_array($this->capabilities[$key])) 1456 $this->capabilities[$key] = array(); 1457 1458 $this->capabilities[$key][] = $value; 1459 } 1460 else 1461 $this->capabilities[$cap] = TRUE; 1462 } 1149 1463 } 1150 1464 -
program/include/rcube_mdb2.inc
r10a69975 r1cded85 239 239 240 240 241 function format_date($timestamp) 242 { 243 switch($this->db_provider) 244 { 245 case 'mysqli': 246 case 'mysql': 247 return "FROM_UNIXTIME($timestamp)"; 248 break; 249 case 'sqlite': 250 return "datetime('$timestamp')"; 251 break; 252 default: 253 return date("Y-m-d H:i:s", $timestamp); 254 } 255 } 256 241 257 function _add_result($res, $query) 242 258 { -
program/include/rcube_shared.inc
r4b0f65a r1cded85 1186 1186 1187 1187 1188 // replace specials characters to a specific encoding type1189 function rep_specialchars_output($str, $enctype='', $mode='', $newlines=TRUE)1190 {1191 global $OUTPUT_TYPE, $CHARSET;1192 static $html_encode_arr, $js_rep_table, $rtf_rep_table, $xml_rep_table;1193 1194 if (!$enctype)1195 $enctype = $GLOBALS['OUTPUT_TYPE'];1196 1197 // convert nbsps back to normal spaces if not html1198 if ($enctype!='html')1199 $str = str_replace(chr(160), ' ', $str);1200 1201 1202 // encode for plaintext1203 if ($enctype=='text')1204 return str_replace("\r\n", "\n", $mode=='remove' ? strip_tags($str) : $str);1205 1206 // encode for HTML output1207 if ($enctype=='html')1208 {1209 if (!$html_encode_arr)1210 {1211 if ($CHARSET=='ISO-8859-1')1212 {1213 $html_encode_arr = get_html_translation_table(HTML_ENTITIES);1214 $html_encode_arr[chr(128)] = '€';1215 }1216 else1217 $html_encode_arr = get_html_translation_table(HTML_SPECIALCHARS);1218 1219 unset($html_encode_arr['?']);1220 unset($html_encode_arr['&']);1221 }1222 1223 $ltpos = strpos($str, '<');1224 $encode_arr = $html_encode_arr;1225 1226 // don't replace quotes and html tags1227 if (($mode=='show' || $mode=='') && $ltpos!==false && strpos($str, '>', $ltpos)!==false)1228 {1229 unset($encode_arr['"']);1230 unset($encode_arr['<']);1231 unset($encode_arr['>']);1232 }1233 else if ($mode=='remove')1234 $str = strip_tags($str);1235 1236 $out = strtr($str, $encode_arr);1237 1238 return $newlines ? nl2br($out) : $out;1239 }1240 1241 1242 if ($enctype=='url')1243 return rawurlencode($str);1244 1245 1246 // if the replace tables for RTF, XML and JS are not yet defined1247 if (!$js_rep_table)1248 {1249 $js_rep_table = $rtf_rep_table = $xml_rep_table = array();1250 1251 for ($c=160; $c<256; $c++) // can be increased to support more charsets1252 {1253 $hex = dechex($c);1254 $rtf_rep_table[Chr($c)] = "\\'$hex";1255 $xml_rep_table[Chr($c)] = "&#$c;";1256 1257 if ($CHARSET=='ISO-8859-1')1258 $js_rep_table[Chr($c)] = sprintf("\u%s%s", str_repeat('0', 4-strlen($hex)), $hex);1259 }1260 1261 $js_rep_table['"'] = sprintf("\u%s%s", str_repeat('0', 4-strlen(dechex(34))), dechex(34));1262 $xml_rep_table['"'] = '"';1263 }1264 1265 // encode for RTF1266 if ($enctype=='xml')1267 return strtr($str, $xml_rep_table);1268 1269 // encode for javascript use1270 if ($enctype=='js')1271 return preg_replace(array("/\r\n/", '/"/', "/([^\\\])'/"), array('\n', '\"', "$1\'"), strtr($str, $js_rep_table));1272 1273 // encode for RTF1274 if ($enctype=='rtf')1275 return preg_replace("/\r\n/", "\par ", strtr($str, $rtf_rep_table));1276 1277 // no encoding given -> return original string1278 return $str;1279 }1280 1281 1188 1282 1189 function decode_specialchars($input, $charset='') … … 1463 1370 return $str; 1464 1371 } 1465 1372 1373 1374 // delete all files within a folder 1375 function clear_directory($dir_path) 1376 { 1377 $dir = @opendir($dir_path); 1378 if(!$dir) return FALSE; 1379 1380 while ($file = readdir($dir)) 1381 if (strlen($file)>2) 1382 unlink("$dir_path/$file"); 1383 1384 closedir($dir); 1385 return TRUE; 1386 } 1466 1387 1467 1388 -
program/include/session.inc
r6677378 r1cded85 46 46 if ($sql_arr = $DB->fetch_assoc($sql_result)) 47 47 { 48 $SESS_CHANGED = $sql_arr['changed'];48 $SESS_CHANGED = mktime(); //$sql_arr['changed']; 49 49 50 50 if (strlen($sql_arr['vars'])) … … 60 60 { 61 61 global $DB; 62 62 63 63 $sql_result = $DB->query("SELECT 1 64 64 FROM ".get_table_name('session')." … … 84 84 $vars, 85 85 $_SERVER['REMOTE_ADDR']); 86 87 86 88 } 87 89 … … 103 105 WHERE sess_id=?", 104 106 $key); 105 107 108 rcmail_clear_session_temp($key); 109 106 110 return TRUE; 107 111 } … … 116 120 $sql_result = $DB->query("SELECT sess_id 117 121 FROM ".get_table_name('session')." 118 WHERE ".$DB->unixtimestamp('now()')."-".$DB->unixtimestamp('c reated')." > ?",122 WHERE ".$DB->unixtimestamp('now()')."-".$DB->unixtimestamp('changed')." > ?", 119 123 $maxlifetime); 120 124 … … 135 139 } 136 140 141 // remove session specific temp dirs 142 foreach ($a_exp_sessions as $key) 143 rcmail_clear_session_temp($key); 144 137 145 return TRUE; 138 146 } -
program/js/app.js
recf7590 r1cded85 211 211 212 212 // disable browser's contextmenus 213 // document.oncontextmenu = function(){ return false; }213 // document.oncontextmenu = function(){ return false; } 214 214 215 215 // flag object as complete … … 287 287 288 288 //this.messageform = this.gui_objects.messageform; 289 var input_from = rcube_find_object('_from'); 289 290 var input_to = rcube_find_object('_to'); 290 291 var input_cc = rcube_find_object('_cc'); … … 301 302 if (input_bcc) 302 303 this.init_address_input_events(input_bcc); 304 305 // add signature according to selected identity 306 if (input_from && input_from.type=='select-one') 307 this.change_identity(input_from); 303 308 304 309 if (input_to && input_to.value=='') … … 462 467 var a_sort = props.split('_'); 463 468 var sort_col = a_sort[0]; 464 var sort_order = a_sort[1] .toUpperCase();469 var sort_order = a_sort[1] ? a_sort[1].toUpperCase() : null; 465 470 var header; 471 472 // no sort order specified: toggle 473 if (sort_order==null) 474 { 475 if (this.env.sort_col==sort_col) 476 sort_order = this.env.sort_order=='ASC' ? 'DESC' : 'ASC'; 477 else 478 sort_order = this.env.sort_order; 479 } 466 480 467 481 if (this.env.sort_col==sort_col && this.env.sort_order==sort_order) … … 479 493 480 494 // reload message list 481 this.list_mailbox('', '', props);495 this.list_mailbox('', '', sort_col+'_'+sort_order); 482 496 break; 483 497 … … 806 820 807 821 case 'delete-folder': 808 if (confirm( 'Do you really want to delete this folder?'))822 if (confirm(this.get_label('deletefolderconfirm'))) 809 823 this.delete_folder(props); 810 824 break; … … 934 948 if (!this.in_selection_before) 935 949 { 936 var shift = this.check_shiftkey(e);937 this.select(id, shift);950 var ctrl = this.check_ctrlkey(e); 951 this.select(id, ctrl); 938 952 } 939 953 … … 952 966 this.click_row = function(e, id) 953 967 { 954 var shift = this.check_shiftkey(e);968 var ctrl = this.check_ctrlkey(e); 955 969 956 970 // don't do anything (another action processed before) … … 962 976 963 977 if (!this.drag_active && this.in_selection_before==id) 964 this.select(id, ( shift&& this.task!='settings'));978 this.select(id, (ctrl && this.task!='settings')); 965 979 966 980 this.drag_start = false; … … 968 982 969 983 // row was double clicked 970 if (this.task=='mail' && this.list_rows && this.list_rows[id].clicked && ! shift)984 if (this.task=='mail' && this.list_rows && this.list_rows[id].clicked && !ctrl) 971 985 { 972 986 this.show_message(id); … … 1333 1347 /********* message compose methods *********/ 1334 1348 /*********************************************************/ 1349 1350 1351 this.change_identity = function(obj) 1352 { 1353 if (!obj || !obj.options) 1354 return false; 1355 1356 var id = obj.options[obj.selectedIndex].value; 1357 var input_message = rcube_find_object('_message'); 1358 var message = input_message ? input_message.value : ''; 1359 1360 // remove the 'old' signature 1361 if (this.env.identity && this.env.signatures && this.env.signatures[this.env.identity]) 1362 { 1363 var sig = this.env.signatures[this.env.identity]; 1364 1365 if (p = message.lastIndexOf(sig)) 1366 message = message.substring(0, p-1) + message.substring(p+sig.length, message.length); 1367 } 1368 1369 // add the new signature string 1370 if (this.env.signatures && this.env.signatures[id]) 1371 { 1372 var sig = this.env.signatures[id]; 1373 message += '\n'+sig; 1374 } 1375 1376 if (input_message && message) 1377 input_message.value = message; 1378 1379 this.env.identity = id; 1380 }; 1335 1381 1336 1382 … … 1855 1901 if (folder) 1856 1902 { 1857 for (var id in this.env.subscriptionrows)1858 if (this.env.subscriptionrows[id]==folder)1859 break;1860 1861 var row;1862 if (id && (row = document.getElementById(id)))1863 row.style.display = 'none';1864 1865 1903 this.http_request('delete-folder', '_mboxes='+escape(folder)); 1866 1904 } 1905 }; 1906 1907 1908 this.remove_folder_row = function(folder) 1909 { 1910 for (var id in this.env.subscriptionrows) 1911 if (this.env.subscriptionrows[id]==folder) 1912 break; 1913 1914 var row; 1915 if (id && (row = document.getElementById(id))) 1916 row.style.display = 'none'; 1867 1917 }; 1868 1918 … … 2492 2542 } 2493 2543 2544 // check if Shift-key is pressed on event 2545 this.check_ctrlkey = function(e) 2546 { 2547 if(!e && window.event) 2548 e = window.event; 2549 2550 if(bw.linux && bw.ns4 && e.modifiers) 2551 return true; 2552 else if (bw.mac) 2553 return this.check_shiftkey(e); 2554 else if((bw.ns4 && e.modifiers & Event.CTRL_MASK) || (e && e.ctrlKey)) 2555 return true; 2556 else 2557 return false; 2558 } 2494 2559 2495 2560 this.get_mouse_pos = function(e) -
program/localization/de/labels.inc
r583f1c8 r1cded85 110 110 $labels['sendmessage'] = 'Nachricht jetzt senden'; 111 111 $labels['addattachment'] = 'Datei anfügen'; 112 $labels['charset'] = 'Zeichensatz'; 112 113 113 114 $labels['attachments'] = 'Anhänge'; … … 122 123 123 124 $labels['nosubject'] = '(kein Betreff)'; 124 125 125 $labels['showimages'] = 'Bilder anzeigen'; 126 126 … … 166 166 $labels['timezone'] = 'Zeitzone'; 167 167 $labels['pagesize'] = 'Einträge pro Seite'; 168 168 $labels['signature'] = 'Signatur'; 169 169 170 170 $labels['folders'] = 'Ordner'; -
program/localization/de/messages.inc
r10a69975 r1cded85 55 55 $messages['errorsaving'] = 'Beim Speichern ist ein Fehler aufgetreten'; 56 56 57 $messages['deletefolderconfirm'] = 'Wollen Sie diesen Ordner wirklich löschen?'; 58 57 59 $messages['formincomplete'] = 'Das Formular wurde nicht vollständig ausgefüllt'; 58 60 -
program/localization/en/labels.inc
r583f1c8 r1cded85 110 110 $labels['sendmessage'] = 'Send the message now'; 111 111 $labels['addattachment'] = 'Attach a file'; 112 $labels['charset'] = 'Charset'; 112 113 113 114 $labels['attachments'] = 'Attachments'; … … 122 123 123 124 $labels['nosubject'] = '(no subject)'; 124 125 125 $labels['showimages'] = 'Display images'; 126 126 … … 166 166 $labels['timezone'] = 'Time zone'; 167 167 $labels['pagesize'] = 'Rows per page'; 168 168 $labels['signature'] = 'Signature'; 169 169 170 170 $labels['folders'] = 'Folders'; -
program/localization/en/messages.inc
r10a69975 r1cded85 61 61 $messages['errordeleting'] = 'Could not delete the message'; 62 62 63 $messages[' errordeleting'] = 'Could not delete the message';63 $messages['deletefolderconfirm'] = 'Do you really want to delete this folder?'; 64 64 65 $messages['formincomplete'] = 'The form was not completely filled out';65 $messages['formincomplete'] = 'The form was not completely filled out'; 66 66 67 $messages['noemailwarning'] = 'Please enter a valid email address';67 $messages['noemailwarning'] = 'Please enter a valid email address'; 68 68 69 $messages['nonamewarning'] = 'Please enter a name';69 $messages['nonamewarning'] = 'Please enter a name'; 70 70 71 71 $messages['nopagesizewarning'] = 'Please enter a page size'; -
program/localization/en_GB/labels.inc
r583f1c8 r1cded85 121 121 $labels['highest'] = 'Highest'; 122 122 123 $labels['nosubject'] = '(no subject)'; 123 124 $labels['showimages'] = 'Display images'; 124 125 … … 164 165 $labels['timezone'] = 'Time zone'; 165 166 $labels['pagesize'] = 'Rows per page'; 166 167 $labels['signature'] = 'Signature'; 167 168 168 169 $labels['folders'] = 'Folders'; -
program/localization/index.inc
r4b0f65a r1cded85 33 33 'de' => 'Deutsch', 34 34 'es' => 'Español', 35 'ee' => 'Estonian', 35 36 'fr' => 'Français', 36 37 'ga' => 'Galician', -
program/steps/addressbook/delete.inc
rd7cb774 r1cded85 25 25 { 26 26 $DB->query("UPDATE ".get_table_name('contacts')." 27 SET del= '1'27 SET del=1 28 28 WHERE user_id=? 29 29 AND contact_id IN (".$_GET['_cid'].")", … … 41 41 $sql_result = $DB->query("SELECT COUNT(contact_id) AS rows 42 42 FROM ".get_table_name('contacts')." 43 WHERE del<> '1'43 WHERE del<>1 44 44 AND user_id=?", 45 45 $_SESSION['user_id']); … … 61 61 // get contacts from DB 62 62 $sql_result = $DB->limitquery("SELECT * FROM ".get_table_name('contacts')." 63 WHERE del<> '1'63 WHERE del<>1 64 64 AND user_id=? 65 65 ORDER BY name", -
program/steps/addressbook/edit.inc
r10a69975 r1cded85 27 27 WHERE contact_id=? 28 28 AND user_id=? 29 AND del<> '1'",29 AND del<>1", 30 30 $cid, 31 31 $_SESSION['user_id']); -
program/steps/addressbook/func.inc
rd7cb774 r1cded85 44 44 $sql_result = $DB->query("SELECT COUNT(contact_id) AS rows 45 45 FROM ".get_table_name('contacts')." 46 WHERE del<> '1'46 WHERE del<>1 47 47 AND user_id=?", 48 48 $_SESSION['user_id']); … … 57 57 // get contacts from DB 58 58 $sql_result = $DB->limitquery("SELECT * FROM ".get_table_name('contacts')." 59 WHERE del<> '1'59 WHERE del<>1 60 60 AND user_id= ? 61 61 ORDER BY name", … … 174 174 { 175 175 $sql_result = $DB->query("SELECT 1 FROM ".get_table_name('contacts')." 176 WHERE del<> '1'176 WHERE del<>1 177 177 AND user_id=?", 178 178 $_SESSION['user_id']); -
program/steps/addressbook/list.inc
rd7cb774 r1cded85 25 25 $sql_result = $DB->query("SELECT COUNT(contact_id) AS rows 26 26 FROM ".get_table_name('contacts')." 27 WHERE del<> '1'27 WHERE del<>1 28 28 AND user_id=?", 29 29 $_SESSION['user_id']); … … 41 41 // get contacts from DB 42 42 $sql_result = $DB->limitquery("SELECT * FROM ".get_table_name('contacts')." 43 WHERE del<> '1'43 WHERE del<>1 44 44 AND user_id=? 45 45 ORDER BY name", -
program/steps/addressbook/save.inc
r10a69975 r1cded85 53 53 WHERE contact_id=? 54 54 AND user_id=? 55 AND del<> '1'",55 AND del<>1", 56 56 $_POST['_cid'], 57 57 $_SESSION['user_id']); … … 74 74 WHERE contact_id=? 75 75 AND user_id=? 76 AND del<> '1'",76 AND del<>1", 77 77 $_POST['_cid'], 78 78 $_SESSION['user_id']); … … 110 110 WHERE user_id=? 111 111 AND email=? 112 AND del<> '1'",112 AND del<>1", 113 113 $_SESSION['user_id'], 114 114 $_POST['_email']); … … 135 135 { 136 136 $DB->query("INSERT INTO ".get_table_name('contacts')." 137 (user_id, changed, ".join(', ', $a_insert_cols).")138 VALUES (?, now(), ".join(', ', $a_insert_values).")",137 (user_id, changed, del, ".join(', ', $a_insert_cols).") 138 VALUES (?, now(), 0, ".join(', ', $a_insert_values).")", 139 139 $_SESSION['user_id']); 140 140 141 $insert_id = $DB->insert_id( );141 $insert_id = $DB->insert_id(get_sequence_name('contacts')); 142 142 } 143 143 -
program/steps/addressbook/show.inc
rd7cb774 r1cded85 27 27 WHERE contact_id=? 28 28 AND user_id=? 29 AND del<> '1'",29 AND del<>1", 30 30 $cid, 31 31 $_SESSION['user_id']); -
program/steps/mail/addcontact.inc
re0ddd4e r1cded85 33 33 WHERE user_id=? 34 34 AND email=? 35 AND del<> '1'",35 AND del<>1", 36 36 $_SESSION['user_id'],$contact['mailto']); 37 37 … … 43 43 { 44 44 $DB->query("INSERT INTO ".get_table_name('contacts')." 45 (user_id, changed, name, email)46 VALUES (?, now(), ?, ?)",45 (user_id, changed, del, name, email) 46 VALUES (?, now(), 0, ?, ?)", 47 47 $_SESSION['user_id'], 48 48 $contact['name'], 49 49 $contact['mailto']); 50 50 51 $added = $DB->insert_id( );51 $added = $DB->insert_id(get_sequence_name('contacts')); 52 52 } 53 53 } -
program/steps/mail/compose.inc
rfd8c506 r1cded85 89 89 { 90 90 case 'from': 91 // pass the following attributes to the form class 92 $field_attrib = array('name' => '_from'); 93 foreach ($attrib as $attr => $value) 94 if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex'))) 95 $field_attrib[$attr] = $value; 96 97 // get this user's identities 98 $sql_result = $DB->query("SELECT identity_id, name, email 99 FROM ".get_table_name('identities')." WHERE user_id=? 100 AND del<>'1' 101 ORDER BY ".$DB->quoteIdentifier('default')." DESC, name ASC", 102 $_SESSION['user_id']); 103 104 if ($DB->num_rows($sql_result)) 105 { 106 $select_from = new select($field_attrib); 107 while ($sql_arr = $DB->fetch_assoc($sql_result)) 108 $select_from->add(format_email_recipient($sql_arr['email'], $sql_arr['name']), $sql_arr['identity_id']); 109 110 $out = $select_from->show($_POST['_from']); 111 } 112 else 113 { 114 $input_from = new textfield($field_attrib); 115 $out = $input_from->show($_POST['_from']); 116 } 117 118 if ($form_start) 119 $out = $form_start.$out; 120 121 return $out; 122 91 return rcmail_compose_header_from($attrib); 123 92 124 93 case 'to': 125 94 $fname = '_to'; 126 95 $header = 'to'; 127 96 128 97 // we have contact id's as get parameters 129 if (!empty($_GET['_to']) && preg_match('/ [0-9]+,?/', $_GET['_to']))98 if (!empty($_GET['_to']) && preg_match('/^([0-9]+,?)+$/', $_GET['_to'])) 130 99 { 131 100 $a_recipients = array(); 132 101 $sql_result = $DB->query("SELECT name, email 133 FROM ".get_table_name('contacts')." WHERE user_id=? 134 AND del<>'1' 102 FROM ".get_table_name('contacts')." 103 WHERE user_id=? 104 AND del<>1 135 105 AND contact_id IN (".$_GET['_to'].")", 136 106 $_SESSION['user_id']); … … 230 200 231 201 232 /*function rcube_compose_headers($attrib) 233 { 234 global $CONFIG, $OUTPUT; 235 236 list($form_start, $form_end) = get_form_tags($attrib); 237 238 // allow the following attributes to be added to the headers table 239 $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border')); 240 241 $labels = array(); 242 $labels['from'] = rcube_label('from'); 243 $labels['to'] = rcube_label('to'); 244 $labels['cc'] = rcube_label('cc'); 245 $labels['bcc'] = rcube_label('bcc'); 246 $labels['replyto'] = rcube_label('replyto'); 247 248 $input_from = new textfield(array('name' => '_from', 'size' => 30)); 249 $input_to = new textfield(array('name' => '_to', 'size' => 30)); 250 $input_cc = new textfield(array('name' => '_cc', 'size' => 30)); 251 $input_bcc = new textfield(array('name' => '_bcc', 'size' => 30)); 252 $input_replyto = new textfield(array('name' => '_replyto', 'size' => 30)); 253 254 $fields = array(); 255 $fields['from'] = $input_from->show($_POST['_from']); 256 $fields['to'] = $input_to->show($_POST['_to']); 257 $fields['cc'] = $input_cc->show($_POST['_cc']); 258 $fields['bcc'] = $input_bcc->show($_POST['_bcc']); 259 $fields['replyto'] = $input_replyto->show($_POST['_replyto']); 260 261 262 $out = <<<EOF 263 $form_start 264 <table$attrib_str><tr> 265 266 <td class="title">$labels[from]</td> 267 <td>$fields[from]</td> 268 269 </tr><tr> 270 271 <td class="title">$labels[to]</td> 272 <td>$fields[to]</td> 273 274 </tr><tr> 275 276 <td class="title">$labels[cc]</td> 277 <td>$fields[cc]</td> 278 279 </tr><tr> 280 281 <td class="title">$labels[bcc]</td> 282 <td>$fields[bcc]</td> 283 284 </tr><tr> 285 286 <td class="title">$labels[replyto]</td> 287 <td>$fields[replyto]</td> 288 289 </tr></table> 290 $form_end 291 EOF; 292 293 return $out; 294 } 295 */ 296 202 203 function rcmail_compose_header_from($attrib) 204 { 205 global $IMAP, $REPLY_MESSAGE, $DB, $OUTPUT, $JS_OBJECT_NAME; 206 207 // pass the following attributes to the form class 208 $field_attrib = array('name' => '_from'); 209 foreach ($attrib as $attr => $value) 210 if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex'))) 211 $field_attrib[$attr] = $value; 212 213 // extract all recipients of the reply-message 214 $a_recipients = array(); 215 if ($REPLY_MESSAGE && is_object($REPLY_MESSAGE['headers'])) 216 { 217 $a_to = $IMAP->decode_address_list($REPLY_MESSAGE['headers']->to); 218 foreach ($a_to as $addr) 219 { 220 if (!empty($addr['mailto'])) 221 $a_recipients[] = $addr['mailto']; 222 } 223 224 if (!empty($REPLY_MESSAGE['headers']->cc)) 225 { 226 $a_cc = $IMAP->decode_address_list($REPLY_MESSAGE['headers']->cc); 227 foreach ($a_cc as $addr) 228 { 229 if (!empty($addr['mailto'])) 230 $a_recipients[] = $addr['mailto']; 231 } 232 } 233 } 234 235 // get this user's identities 236 $sql_result = $DB->query("SELECT identity_id, name, email, signature 237 FROM ".get_table_name('identities')." 238 WHERE user_id=? 239 AND del<>1 240 ORDER BY ".$DB->quoteIdentifier('standard')." DESC, name ASC", 241 $_SESSION['user_id']); 242 243 if ($DB->num_rows($sql_result)) 244 { 245 $from_id = 0; 246 $a_signatures = array(); 247 248 $field_attrib['onchange'] = "$JS_OBJECT_NAME.change_identity(this)"; 249 $select_from = new select($field_attrib); 250 251 while ($sql_arr = $DB->fetch_assoc($sql_result)) 252 { 253 $select_from->add(format_email_recipient($sql_arr['email'], $sql_arr['name']), $sql_arr['identity_id']); 254 255 // add signature to array 256 if (!empty($sql_arr['signature'])) 257 $a_signatures[$sql_arr['identity_id']] = $sql_arr['signature']; 258 259 // set identity if it's one of the reply-message recipients 260 if (in_array($sql_arr['email'], $a_recipients)) 261 $from_id = $sql_arr['identity_id']; 262 } 263 264 // overwrite identity selection with post parameter 265 if (isset($_POST['_from'])) 266 $from_id = $_POST['_from']; 267 268 $out = $select_from->show($from_id); 269 270 271 // add signatures to client 272 $OUTPUT->add_script(sprintf("%s.set_env('signatures', %s);", $JS_OBJECT_NAME, array2js($a_signatures))); 273 } 274 else 275 { 276 $input_from = new textfield($field_attrib); 277 $out = $input_from->show($_POST['_from']); 278 } 279 280 if ($form_start) 281 $out = $form_start.$out; 282 283 return $out; 284 } 285 286 297 287 298 288 function rcmail_compose_body($attrib) … … 361 351 $REPLY_MESSAGE['headers']->date, 362 352 $IMAP->decode_header($REPLY_MESSAGE['headers']->from)); 353 354 355 // try to remove the signature 356 if ($sp = strrpos($body, '--')) 357 { 358 if ($body{$sp+3}==' ' || $body{$sp+3}=="\n" || $body{$sp+3}=="\r") 359 $body = substr($body, 0, $sp-1); 360 } 363 361 364 362 return $pefix.$body; … … 597 595 $sql_result = $DB->query("SELECT name, email 598 596 FROM ".get_table_name('contacts')." WHERE user_id=? 599 AND del<> '1'",$_SESSION['user_id']);597 AND del<>1",$_SESSION['user_id']); 600 598 601 599 if ($DB->num_rows($sql_result)) -
program/steps/mail/func.inc
r4b0f65a r1cded85 306 306 // make sort links 307 307 $sort = ''; 308 if (in_array($col, $a_sort_cols) && (!empty($attrib['sortdescbutton']) || !empty($attrib['sortascbutton']))) 309 { 310 $sort = ' '; 311 312 // asc link 313 if (!empty($attrib['sortascbutton'])) 308 if ($IMAP->get_capability('sort') && in_array($col, $a_sort_cols)) 309 { 310 // have buttons configured 311 if (!empty($attrib['sortdescbutton']) || !empty($attrib['sortascbutton'])) 314 312 { 315 $sort .= rcube_button(array('command' => 'sort', 316 'prop' => $col.'_ASC', 317 'image' => $attrib['sortascbutton'], 318 'title' => 'sortasc')); 319 } 313 $sort = ' '; 314 315 // asc link 316 if (!empty($attrib['sortascbutton'])) 317 { 318 $sort .= rcube_button(array('command' => 'sort', 319 'prop' => $col.'_ASC', 320 'image' => $attrib['sortascbutton'], 321 'align' => 'absmiddle', 322 'title' => 'sortasc')); 323 } 320 324 321 // desc link 322 if (!empty($attrib['sortdescbutton'])) 325 // desc link 326 if (!empty($attrib['sortdescbutton'])) 327 { 328 $sort .= rcube_button(array('command' => 'sort', 329 'prop' => $col.'_DESC', 330 'image' => $attrib['sortdescbutton'], 331 'align' => 'absmiddle', 332 'title' => 'sortdesc')); 333 } 334 } 335 // just add a link tag to the header 336 else 323 337 { 324 $sort .= rcube_button(array('command' => 'sort', 325 'prop' => $col.'_DESC', 326 'image' => $attrib['sortdescbutton'], 327 'title' => 'sortdesc')); 338 $col_name = sprintf('<a href="./#sort" onclick="return %s.command(\'sort\',\'%s\',this)" title="%s">%s</a>', 339 $JS_OBJECT_NAME, 340 $col, 341 rcube_label('sortby'), 342 $col_name); 328 343 } 329 344 } … … 1129 1144 function rcmail_message_source($uid) 1130 1145 { 1131 global $IMAP, $DB; 1132 1133 // get message ID if uid is given 1134 $headers = $IMAP->get_headers($uid); 1146 global $IMAP, $DB, $CONFIG; 1147 1148 // get message ID if uid is given 1149 $cache_key = $IMAP->mailbox.'.msg'; 1150 $cached = $IMAP->get_cached_message($cache_key, $uid, FALSE); 1151 1152 // message is cached in database 1153 if ($cached && !empty($cached->body)) 1154 return $cached->body; 1155 1156 if (!$cached) 1157 $headers = $IMAP->get_headers($uid); 1158 else 1159 $headers = &$cached; 1160 1161 1135 1162 $message_id = $headers->messageID; 1136 1163 1137 // get cached message source 1138 $msg_source = rcube_read_cache($message_id); 1139 1140 // get message from server and cache it 1141 if (!$msg_source) 1142 { 1143 $msg_source = $IMAP->get_raw_body($uid); 1144 rcube_write_cache($message_id, $msg_source, TRUE); 1164 $temp_dir = $CONFIG['temp_dir'].(!eregi('\/$', $CONFIG['temp_dir']) ? '/' : ''); 1165 $cache_dir = $temp_dir.$_SESSION['client_id']; 1166 $cache_path = $cache_dir.'/'.$message_id; 1167 1168 // message is cached in temp dir 1169 if (is_dir($cache_dir) && is_file($cache_path)) 1170 { 1171 if ($fp = fopen($cache_path, 'r')) 1172 { 1173 $msg_source = fread($fp, filesize($cache_path)); 1174 fclose($fp); 1175 return $msg_source; 1176 } 1177 } 1178 1179 1180 // get message from server 1181 $msg_source = $IMAP->get_raw_body($uid); 1182 1183 // let's cache the message body within the database 1184 if ($CONFIG['enable_caching'] && $cached && ($CONFIG['db_max_length'] -300) > $headers->size) 1185 { 1186 $DB->query("UPDATE ".get_table_name('messages')." 1187 SET body=? 1188 WHERE user_id=? 1189 AND cache_key=? 1190 AND uid=?", 1191 $msg_source, 1192 $_SESSION['user_id'], 1193 $cache_key, 1194 $uid); 1195 1196 return $msg_source; 1197 } 1198 1199 1200 // create dir for caching 1201 if (!is_dir($cache_dir)) 1202 $dir = mkdir($cache_dir); 1203 else 1204 $dir = true; 1205 1206 // attempt to write a file with the message body 1207 if ($dir && ($fp = fopen($cache_path, 'w'))) 1208 { 1209 fwrite($fp, $msg_source); 1210 fclose($fp); 1211 } 1212 else 1213 { 1214 raise_error(array('code' => 403, 'type' => 'php', 'line' => __LINE__, 'file' => __FILE__, 1215 'message' => "Failed to write to temp dir"), TRUE, FALSE); 1145 1216 } 1146 1217 -
program/steps/mail/sendmail.inc
r5bc8cb66 r1cded85 47 47 WHERE identity_id=? 48 48 AND user_id=? 49 AND del<> '1'",49 AND del<>1", 50 50 $id,$_SESSION['user_id']); 51 51 … … 79 79 80 80 81 $mailto_regexp = array('/ ,\s*[\r\n]+/', '/[\r\n]+/', '/,\s*$/m');82 $mailto_replace = array(' ', ', ', '');81 $mailto_regexp = array('/[,;]\s*[\r\n]+/', '/[\r\n]+/', '/[,;]\s*$/m'); 82 $mailto_replace = array(', ', ', ', ''); 83 83 84 84 // repalce new lines and strip ending ', ' … … 176 176 $MAIL_MIME->addAttachment($filepath, $files['type'][$i], $files['name'][$i], TRUE); 177 177 178 179 $message_charset = isset($_POST['_charset']) ? $_POST['_charset'] : $CHARSET; 180 178 181 // encoding settings for mail composing 179 182 $message_param = array('text_encoding' => '7bit', 180 183 'html_encoding' => 'quoted-printable', 181 184 'head_encoding' => 'quoted-printable', 182 'head_charset' => $ CHARSET,183 'html_charset' => $ CHARSET,184 'text_charset' => $ CHARSET);185 'head_charset' => $message_charset, 186 'html_charset' => $message_charset, 187 'text_charset' => $message_charset); 185 188 186 189 // compose message body and get headers -
program/steps/settings/delete_identity.inc
rd7cb774 r1cded85 25 25 { 26 26 $DB->query("UPDATE ".get_table_name('identities')." 27 SET del= '1'27 SET del=1 28 28 WHERE user_id=? 29 29 AND identity_id IN (".$_GET['_iid'].")", -
program/steps/settings/edit_identity.inc
r10a69975 r1cded85 26 26 WHERE identity_id=? 27 27 AND user_id=? 28 AND del<> '1'",28 AND del<>1", 29 29 $id, 30 30 $_SESSION['user_id']); … … 64 64 'reply-to' => array('type' => 'text', 'label' => 'replyto'), 65 65 'bcc' => array('type' => 'text'), 66 'default' => array('type' => 'checkbox', 'label' => 'setdefault')); 66 'signature' => array('type' => 'textarea'), 67 'standard' => array('type' => 'checkbox', 'label' => 'setdefault')); 67 68 68 69 -
program/steps/settings/func.inc
r10a69975 r1cded85 147 147 // get contacts from DB 148 148 $sql_result = $DB->query("SELECT * FROM ".get_table_name('identities')." 149 WHERE del<> '1'149 WHERE del<>1 150 150 AND user_id=? 151 ORDER BY ".$DB->quoteIdentifier('default')."DESC, name ASC",151 ORDER BY standard DESC, name ASC", 152 152 $_SESSION['user_id']); 153 153 -
program/steps/settings/manage_folders.inc
ra95e0e1 r1cded85 70 70 { 71 71 if (strlen($_GET['_mboxes'])) 72 $ IMAP->delete_mailbox(explode(',', $_GET['_mboxes']));72 $deleted = $IMAP->delete_mailbox(explode(',', $_GET['_mboxes'])); 73 73 74 if ($_GET['_remote']) 75 rcube_remote_response('// deleted'); 74 if ($_GET['_remote'] && $deleted) 75 rcube_remote_response(sprintf("this.remove_folder_row('%s')", rep_specialchars_output($_GET['_mboxes'], 'js'))); 76 else if ($_GET['_remote']) 77 { 78 $commands = show_message('errorsaving', 'error'); 79 rcube_remote_response($commands); 80 } 76 81 } 77 82 … … 175 180 176 181 182 // add some labels to client 183 rcube_add_label('deletefolderconfirm'); 184 185 177 186 parse_template('managefolders'); 178 187 ?> -
program/steps/settings/save_identity.inc
r10a69975 r1cded85 20 20 */ 21 21 22 $a_save_cols = array('name', 'email', 'organization', 'reply-to', 'bcc', ' default');22 $a_save_cols = array('name', 'email', 'organization', 'reply-to', 'bcc', 'standard', 'signature'); 23 23 24 24 … … 52 52 WHERE identity_id=? 53 53 AND user_id=? 54 AND del<> '1'",54 AND del<>1", 55 55 $_POST['_iid'], 56 56 $_SESSION['user_id']); … … 65 65 // mark all other identities as 'not-default' 66 66 $DB->query("UPDATE ".get_table_name('identities')." 67 SET ".$DB->quoteIdentifier(' default')."='0'67 SET ".$DB->quoteIdentifier('standard')."='0' 68 68 WHERE user_id=? 69 69 AND identity_id<>? 70 AND del<> '1'",70 AND del<>1", 71 71 $_SESSION['user_id'], 72 72 $_POST['_iid']); … … 107 107 VALUES (?, ".join(', ', $a_insert_values).")", 108 108 $_SESSION['user_id']); 109 110 $insert_id = $DB->insert_id( );109 110 $insert_id = $DB->insert_id(get_sequence_name('identities')); 111 111 } 112 112 -
skins/default/mail.css
r4b0f65a r1cded85 76 76 top: 60px; 77 77 right: 40px; 78 width: 2 00px;78 width: 220px; 79 79 height: 20px; 80 80 text-align: right; 81 white-space: nowrap; 81 82 } 82 83 … … 331 332 { 332 333 background-image: url(images/listheader_dark.gif); 334 } 335 336 #messagelist thead tr td.sortedASC a 337 { 338 background: url(images/sort_asc.gif) top right no-repeat; 339 } 340 341 #messagelist thead tr td.sortedDESC a 342 { 343 background: url(images/sort_desc.gif) top right no-repeat; 344 } 345 346 #messagelist thead tr td a, 347 #messagelist thead tr td a:hover 348 { 349 display: block; 350 width: auto !important; 351 width: 100%; 352 color: #333333; 353 text-decoration: none; 333 354 } 334 355 … … 646 667 { 647 668 margin-top: 10px; 669 margin-bottom: 5px; 648 670 width: 99% !important; 649 671 width: 95%; 650 height: 9 5%;672 height: 90%; 651 673 min-height: 300px; 652 674 font-size: 9pt; … … 703 725 } 704 726 705 -
skins/default/pngbehavior.htc
r4e17e6c r1cded85 41 41 // set filter 42 42 element.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + 43 src + "',sizingMethod=' scale')";43 src + "',sizingMethod='crop')"; 44 44 } 45 45 else { -
skins/default/templates/compose.html
r583f1c8 r1cded85 88 88 </tr><tr> 89 89 90 <td style="width:100%; height:100%; vertical-align:top;"> 91 <roundcube:object name="composeBody" id="compose-body" form="form" cols="80" rows="20" warp="virtual" tabindex="7" /> 90 <td style="width:100%; height:95%; vertical-align:top;"> 91 <roundcube:object name="composeBody" id="compose-body" form="form" cols="80" rows="20" warp="virtual" tabindex="7" /><br /> 92 <roundcube:label name="charset" />: <roundcube:object name="charsetSelector" tabindex="8" /> 92 93 </td> 93 94 -
skins/default/templates/mail.html
r583f1c8 r1cded85 38 38 unreadIcon="/images/icons/unread.png" 39 39 repliedIcon="/images/icons/replied.png" 40 attachmentIcon="/images/icons/attachment.png" 41 sortDescButton="/images/buttons/up_arrow.png" 42 sortAscButton="/images/buttons/down_arrow.png" /> 40 attachmentIcon="/images/icons/attachment.png" /> 43 41 </div> 44 42
Note: See TracChangeset
for help on using the changeset viewer.
