Projects
Kolab:3.4
cyrus-imapd
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 52
View file
cyrus-imapd.spec
Changed
@@ -57,14 +57,16 @@ ## ## Patches ## -Patch0001: cyrus-imapd-2.5-autoconf-2.63.patch -Patch0002: cyrus-imapd-2.5-lt-prereq.patch -Patch0003: cyrus-imapd-2.5-with-dav-ifdefs.patch -Patch0004: cyrus-imapd-2.5-return-0-to-make-function-nonvoid.patch -Patch0005: cyrus-imapd-2.5-shared-folder-deletion.patch -Patch1000: cyrus-imapd-2.5-disable-user-parameter-notifyd.patch -Patch1001: cyrus-imapd-2.5-acl-change-notifications.patch +Patch0001: 0001-There-is-no-actual-prerequisite-for-libtool-of-2.2.6.patch +Patch0002: 0002-A-non-void-function-should-return-something-so-retur.patch +Patch0003: 0003-Disable-user-parameter-check-to-notify-external.patch +Patch0004: 0004-Fix-display-of-deleted-shared-folders.patch +Patch0005: 0005-Apply-ifdefs-for-building-without-DAV-and-without-re.patch +Patch0006: 0006-Add-ACL-change-notifications.patch +Patch0007: 0007-Correct-location-of-ifdef-endif.patch +Patch0008: 0008-Extend-ifdefs-endifs-for-WITH_DAV.patch +Patch0009: 0009-Keep-the-same-order-between-.c-and-.h-perhaps.patch BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) @@ -241,14 +243,15 @@ %prep %setup -q -n %{_name}-%{real_version}%{?dot_snapshot_version} -#%patch0001 -p1 +%patch0001 -p1 %patch0002 -p1 %patch0003 -p1 %patch0004 -p1 %patch0005 -p1 - -%patch1000 -p1 -%patch1001 -p1 +%patch0006 -p1 +%patch0007 -p1 +%patch0008 -p1 +%patch0009 -p1 # only to update config.* files aclocal -I cmulocal
View file
0001-There-is-no-actual-prerequisite-for-libtool-of-2.2.6.patch
Added
@@ -0,0 +1,25 @@ +From 18c6d1d15047ce5e92b9892aeaf73e955e2b57f0 Mon Sep 17 00:00:00 2001 +From: "Jeroen van Meeuwen (Kolab Systems)" <vanmeeuwen@kolabsys.com> +Date: Sat, 8 Mar 2014 23:48:30 +0100 +Subject: [PATCH 1/6] There is no actual prerequisite for libtool of >= 2.2.6 + and it is incompatible with autoconf 2.63 + +--- + configure.ac | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 3c29680..61073e2 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -127,7 +127,6 @@ AH_BOTTOM([#if HAVE_VISIBILITY + #define HIDDEN + #endif]) + +-LT_PREREQ([2.2.6]) + LT_INIT([disable-static]) + AC_SUBST([LIBTOOL_DEPS]) + +-- +1.8.3.1 +
View file
0002-A-non-void-function-should-return-something-so-retur.patch
Added
@@ -0,0 +1,24 @@ +From 49a177f85e57c4a3c2613bf72ae492bc4b855caf Mon Sep 17 00:00:00 2001 +From: "Jeroen van Meeuwen (Kolab Systems)" <vanmeeuwen@kolabsys.com> +Date: Sat, 8 Mar 2014 23:49:04 +0100 +Subject: [PATCH 2/6] A non void function should return something, so return 0 + +--- + imap/xapian_wrap.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/imap/xapian_wrap.cpp b/imap/xapian_wrap.cpp +index 47d904f..ea96b87 100644 +--- a/imap/xapian_wrap.cpp ++++ b/imap/xapian_wrap.cpp +@@ -291,6 +291,7 @@ xapian_query_t *xapian_query_new_match(const xapian_db_t *db, const char *prefix + catch (const Xapian::Error &err) { + syslog(LOG_ERR, "IOERROR: Xapian: caught exception: %s: %s", + err.get_context().c_str(), err.get_description().c_str()); ++ return 0; + } + } + +-- +1.8.3.1 +
View file
0003-Disable-user-parameter-check-to-notify-external.patch
Added
@@ -0,0 +1,38 @@ +From 7e8b0d9ecee648e854bc90f674f61e44f8d42c05 Mon Sep 17 00:00:00 2001 +From: "Jeroen van Meeuwen (Kolab Systems)" <vanmeeuwen@kolabsys.com> +Date: Sat, 8 Mar 2014 23:49:27 +0100 +Subject: [PATCH 3/6] Disable user parameter check to notify external + +--- + notifyd/notify_external.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/notifyd/notify_external.c b/notifyd/notify_external.c +index 5a2d680..964d1ee 100644 +--- a/notifyd/notify_external.c ++++ b/notifyd/notify_external.c +@@ -71,15 +71,15 @@ char* notify_external(const char *class, const char *priority, + + /* check/parse options */ + if (!(notify = config_getstring(IMAPOPT_NOTIFY_EXTERNAL))) { +- syslog(LOG_ERR, "ERROR: recipient not specified"); +- return strdup("NO external recipient not specified"); ++ syslog(LOG_ERR, "ERROR: external recipient (program) not specified"); ++ return strdup("NO external recipient (program) not specified"); + } + +- if (!*user) { +- syslog(LOG_ERR, "ERROR: recipient not specified"); +- return strdup("NO external recipient not specified"); ++/* if (!*user) { ++ syslog(LOG_ERR, "ERROR: external recipient user not specified"); ++ return strdup("NO external recipient user not specified"); + } +- ++*/ + buf[0] = notify; + buf[1] = "-c"; + buf[2] = class; +-- +1.8.3.1 +
View file
0004-Fix-display-of-deleted-shared-folders.patch
Added
@@ -0,0 +1,32 @@ +From f931a6f37054f6f9f7638d71147c1b7367242557 Mon Sep 17 00:00:00 2001 +From: "Jeroen van Meeuwen (Kolab Systems)" <vanmeeuwen@kolabsys.com> +Date: Sat, 8 Mar 2014 23:49:50 +0100 +Subject: [PATCH 4/6] Fix display of deleted shared folders + +--- + imap/mboxname.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/imap/mboxname.c b/imap/mboxname.c +index 86a755f..f3634c0 100644 +--- a/imap/mboxname.c ++++ b/imap/mboxname.c +@@ -576,7 +576,15 @@ static int mboxname_toexternal(struct namespace *namespace, const char *mboxname + + if (mbparts.box) + strcat(result, "."); ++ } else { ++ /* shared mailbox */ ++ if (mbparts.is_deleted) { ++ const char *dp = config_getstring(IMAPOPT_DELETEDPREFIX); ++ sprintf(result, "%s.", dp); ++ } + } ++ ++ + if (mbparts.box) + strcat(result, mbparts.box); + +-- +1.8.3.1 +
View file
0005-Apply-ifdefs-for-building-without-DAV-and-without-re.patch
Added
@@ -0,0 +1,281 @@ +From af772395dc3f45dbc2347fc3611606c7242059b5 Mon Sep 17 00:00:00 2001 +From: "Jeroen van Meeuwen (Kolab Systems)" <vanmeeuwen@kolabsys.com> +Date: Sat, 8 Mar 2014 23:50:55 +0100 +Subject: [PATCH 5/6] Apply ifdefs for building without DAV and without + requiring DAV-related software during build + +--- + Makefile.am | 19 ++++++++++++++----- + imap/mailbox.c | 10 ++++++++++ + imap/mailbox.h | 2 ++ + imap/mboxevent.c | 13 ++++++++++++- + imap/mboxevent.h | 2 ++ + imap/sync_server.c | 6 ++++++ + 6 files changed, 46 insertions(+), 6 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index b1790a5..48d0e8e 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -1190,7 +1190,6 @@ dist_man_MANS = \ + man/deliver.8 \ + man/fetchnews.8 \ + man/fud.8 \ +- man/httpd.8 \ + man/idled.8 \ + man/imapd.8 \ + man/ipurge.8 \ +@@ -1206,17 +1205,27 @@ dist_man_MANS = \ + man/rmnews.8 \ + man/smmapd.8 \ + man/syncnews.8 \ +- man/sync_client.8 \ +- man/sync_reset.8 \ +- man/sync_server.8 \ + man/timsieved.8 \ + man/tls_prune.8 \ + man/unexpunge.8 +-if USE_SQUAT ++ ++if SQUATTER + dist_man_MANS += \ + man/squatter.8 + endif + ++if HTTPD ++dist_man_MANS += \ ++ man/httpd.8 ++endif ++ ++if REPLICATION ++dist_man_MANS += \ ++ man/sync_client.8 \ ++ man/sync_reset.8 \ ++ man/sync_server.8 ++endif ++ + master_master_SOURCES = \ + master/cyrusMasterMIB.c \ + master/cyrusMasterMIB.h \ +diff --git a/imap/mailbox.c b/imap/mailbox.c +index 43d8f79..cc457df 100644 +--- a/imap/mailbox.c ++++ b/imap/mailbox.c +@@ -51,7 +51,9 @@ + #elif defined(HAVE_STDINT_H) + # include <stdint.h> + #endif ++#ifdef WITH_DAV + #include <libical/vcc.h> ++#endif + #include <stdio.h> + #include <stdlib.h> + #include <string.h> +@@ -81,8 +83,10 @@ + + #include "annotate.h" + #include "assert.h" ++#ifdef WITH_DAV + #include "caldav_db.h" + #include "carddav_db.h" ++#endif + #include "crc32.h" + #include "md5.h" + #include "exitcodes.h" +@@ -2660,6 +2664,7 @@ out: + return r; + } + ++#ifdef WITH_DAV + static int mailbox_update_carddav(struct mailbox *mailbox, + struct index_record *old, + struct index_record *new) +@@ -2880,6 +2885,7 @@ static int mailbox_update_dav(struct mailbox *mailbox, + return mailbox_update_caldav(mailbox, old, new); + return 0; + } ++#endif //WITH_DAV + + EXPORTED int mailbox_update_conversations(struct mailbox *mailbox, + struct index_record *old, +@@ -3106,8 +3112,10 @@ static int mailbox_update_indexes(struct mailbox *mailbox, + { + int r = 0; + ++#ifdef WITH_DAV + r = mailbox_update_dav(mailbox, old, new); + if (r) return r; ++#endif + + r = mailbox_update_conversations(mailbox, old, new); + if (r) return r; +@@ -4231,6 +4239,7 @@ static int chkchildren(char *name, + return r; + } + ++#ifdef WITH_DAV + EXPORTED int mailbox_add_dav(struct mailbox *mailbox) + { + struct index_record record; +@@ -4250,6 +4259,7 @@ EXPORTED int mailbox_add_dav(struct mailbox *mailbox) + + return 0; + } ++#endif + + EXPORTED int mailbox_add_conversations(struct mailbox *mailbox) + { +diff --git a/imap/mailbox.h b/imap/mailbox.h +index cdcf878..f6174c6 100644 +--- a/imap/mailbox.h ++++ b/imap/mailbox.h +@@ -577,7 +577,9 @@ extern int mailbox_get_annotate_state(struct mailbox *mailbox, + uint32_t mailbox_sync_crc(struct mailbox *mailbox, unsigned vers, int recalc); + unsigned mailbox_best_crcvers(unsigned minvers, unsigned maxvers); + ++#ifdef WITH_DAV + extern int mailbox_add_dav(struct mailbox *mailbox); ++#endif + + /* Rename a CID. Note - this is just one mailbox! */ + extern int mailbox_cid_rename(struct mailbox *mailbox, +diff --git a/imap/mboxevent.c b/imap/mboxevent.c +index 97882a5..0f0d298 100644 +--- a/imap/mboxevent.c ++++ b/imap/mboxevent.c +@@ -53,8 +53,10 @@ + + #include "annotate.h" + #include "assert.h" ++#ifdef WITH_DAV + #include "caldav_db.h" + #include "carddav_db.h" ++#endif + #include "exitcodes.h" + #include "imapurl.h" + #include "libconfig.h" +@@ -131,9 +133,11 @@ static struct mboxevent event_template = + { EVENT_PID, "pid", EVENT_PARAM_INT, 0, 0 }, + { EVENT_USER, "user", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_MESSAGE_SIZE, "messageSize", EVENT_PARAM_INT, 0, 0 }, ++#ifdef WITH_DAV + { EVENT_MBTYPE, "vnd.cmu.mbtype", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_DAV_FILENAME, "vnd.cmu.davFilename", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_DAV_UID, "vnd.cmu.davUid", EVENT_PARAM_STRING, 0, 0 }, ++#endif + { EVENT_MESSAGE_CID, "vnd.fastmail.cid", EVENT_PARAM_STRING, 0, 0 }, + /* always at end to let the parser to easily truncate this part */ + { EVENT_ENVELOPE, "vnd.cmu.envelope", EVENT_PARAM_STRING, 0, 0 }, +@@ -378,8 +382,10 @@ static int mboxevent_expected_param(enum event_type type, enum event_param param + return extra_params & IMAP_ENUM_EVENT_EXTRA_PARAMS_VND_FASTMAIL_SESSIONID; + case EVENT_MAILBOX_ID: + return (type & MAILBOX_EVENTS); ++#ifdef WITH_DAV + case EVENT_MBTYPE: + return (type & MAILBOX_EVENTS); ++#endif + case EVENT_MAX_MESSAGES: + return type & QUOTA_EVENTS; + case EVENT_MESSAGE_CONTENT: +@@ -388,12 +394,14 @@ static int mboxevent_expected_param(enum event_type type, enum event_param param + case EVENT_MESSAGE_SIZE: + return (extra_params & IMAP_ENUM_EVENT_EXTRA_PARAMS_MESSAGESIZE) && + (type & (EVENT_MESSAGE_APPEND|EVENT_MESSAGE_NEW)); ++#ifdef WITH_DAV + case EVENT_DAV_FILENAME: + return (extra_params & IMAP_ENUM_EVENT_EXTRA_PARAMS_VND_CMU_DAVFILENAME) && + (type & EVENT_CALENDAR); + case EVENT_DAV_UID: + return (extra_params & IMAP_ENUM_EVENT_EXTRA_PARAMS_VND_CMU_DAVUID) && + (type & EVENT_CALENDAR); ++#endif + case EVENT_MESSAGE_CID: + return (extra_params & IMAP_ENUM_EVENT_EXTRA_PARAMS_VND_FASTMAIL_CID) && + (type & (EVENT_MESSAGE_APPEND|EVENT_MESSAGE_NEW)); +@@ -743,6 +751,7 @@ EXPORTED void mboxevent_extract_record(struct mboxevent *event, struct mailbox * + cacheitem_size(record, CACHE_BODYSTRUCTURE))); + } + ++#ifdef WITH_DAV
View file
0006-Add-ACL-change-notifications.patch
Added
@@ -0,0 +1,162 @@ +From 62103a35b782aad0d94efe21657b82eeab7d27df Mon Sep 17 00:00:00 2001 +From: "Jeroen van Meeuwen (Kolab Systems)" <vanmeeuwen@kolabsys.com> +Date: Sat, 8 Mar 2014 23:52:02 +0100 +Subject: [PATCH 6/6] Add ACL change notifications + +--- + imap/mboxevent.c | 34 ++++++++++++++++++++++++++++++---- + imap/mboxevent.h | 12 +++++++++++- + imap/mboxlist.c | 9 +++++++++ + 3 files changed, 50 insertions(+), 5 deletions(-) + +diff --git a/imap/mboxevent.c b/imap/mboxevent.c +index 0f0d298..9a60b0a 100644 +--- a/imap/mboxevent.c ++++ b/imap/mboxevent.c +@@ -78,7 +78,7 @@ + EVENT_MESSAGE_TRASH) + + #define MAILBOX_EVENTS (EVENT_MAILBOX_CREATE|EVENT_MAILBOX_DELETE|\ +- EVENT_MAILBOX_RENAME) ++ EVENT_MAILBOX_RENAME|EVENT_ACL_CHANGE) + + #define SUBS_EVENTS (EVENT_MAILBOX_SUBSCRIBE|EVENT_MAILBOX_UNSUBSCRIBE) + +@@ -122,6 +122,8 @@ static struct mboxevent event_template = + { EVENT_DISK_QUOTA, "diskQuota", EVENT_PARAM_INT, 0, 0 }, + { EVENT_DISK_USED, "diskUsed", EVENT_PARAM_INT, 0, 0 }, + { EVENT_MAX_MESSAGES, "maxMessages", EVENT_PARAM_INT, 0, 0 }, ++ { EVENT_ACL_SUBJECT, "aclSubject", EVENT_PARAM_STRING, 0, 0 }, ++ { EVENT_ACL_RIGHTS, "aclRights", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_MESSAGES, "messages", EVENT_PARAM_INT, 0, 0 }, + { EVENT_UNSEEN_MESSAGES, "vnd.cmu.unseenMessages", EVENT_PARAM_INT, 0, 0 }, + { EVENT_CONVEXISTS, "vnd.fastmail.convExists", EVENT_PARAM_INT, 0, 0 }, +@@ -191,7 +193,7 @@ EXPORTED void mboxevent_init(void) + enabled_events |= FLAGS_EVENTS; + + if (groups & IMAP_ENUM_EVENT_GROUPS_ACCESS) +- enabled_events |= (EVENT_LOGIN|EVENT_LOGOUT); ++ enabled_events |= (EVENT_LOGIN|EVENT_LOGOUT|EVENT_ACL_CHANGE); + + if (groups & IMAP_ENUM_EVENT_GROUPS_SUBSCRIPTION) + enabled_events |= SUBS_EVENTS; +@@ -423,6 +425,10 @@ static int mboxevent_expected_param(enum event_type type, enum event_param param + return extra_params & IMAP_ENUM_EVENT_EXTRA_PARAMS_SERVICE; + case EVENT_TIMESTAMP: + return extra_params & IMAP_ENUM_EVENT_EXTRA_PARAMS_TIMESTAMP; ++ case EVENT_ACL_SUBJECT: ++ return type & EVENT_ACL_CHANGE; ++ case EVENT_ACL_RIGHTS: ++ return type & EVENT_ACL_CHANGE; + case EVENT_UIDNEXT: + if (!(extra_params & IMAP_ENUM_EVENT_EXTRA_PARAMS_UIDNEXT)) + return 0; +@@ -679,12 +685,24 @@ EXPORTED void mboxevent_set_access(struct mboxevent *event, + if (userid && mboxevent_expected_param(event->type, EVENT_USER)) { + /* translate any separators in user */ + char *user = xstrdup(userid); +- mboxname_hiersep_toexternal(&namespace, user, +- config_virtdomains ? strcspn(user, "@") : 0); ++ if (user) { ++ mboxname_hiersep_toexternal(&namespace, user, ++ config_virtdomains ? strcspn(user, "@") : 0); ++ } + FILL_STRING_PARAM(event, EVENT_USER, user); + } + } + ++EXPORTED void mboxevent_set_acl(struct mboxevent *event, const char *identifier, ++ const char *rights) ++{ ++ if (!event) ++ return; ++ ++ FILL_STRING_PARAM(event, EVENT_ACL_SUBJECT, xstrdup(identifier)); ++ FILL_STRING_PARAM(event, EVENT_ACL_RIGHTS, xstrdup(rights)); ++} ++ + EXPORTED void mboxevent_extract_record(struct mboxevent *event, struct mailbox *mailbox, + struct index_record *record) + { +@@ -1132,6 +1150,8 @@ static const char *event_to_name(enum event_type type) + return "MailboxSubscribe"; + case EVENT_MAILBOX_UNSUBSCRIBE: + return "MailboxUnSubscribe"; ++ case EVENT_ACL_CHANGE: ++ return "AclChange"; + default: + fatal("Unknown message event", EC_SOFTWARE); + } +@@ -1335,6 +1355,12 @@ EXPORTED void mboxevent_set_access(struct mboxevent *event __attribute__((unused + { + } + ++EXPORTED void mboxevent_set_acl(struct mboxevent *event __attribute__((unused)), ++ const char *identifier __attribute__((unused)), ++>.......>.......>.......>.......const char *rights __attribute__((unused))) ++{ ++} ++ + EXPORTED void mboxevent_extract_record(struct mboxevent *event __attribute__((unused)), + struct mailbox *mailbox __attribute__((unused)), + struct index_record *record __attribute__((unused))) +diff --git a/imap/mboxevent.h b/imap/mboxevent.h +index 4e111c7..6106505 100644 +--- a/imap/mboxevent.h ++++ b/imap/mboxevent.h +@@ -80,7 +80,8 @@ enum event_type { + EVENT_MAILBOX_RENAME = (1<<17), + EVENT_MAILBOX_SUBSCRIBE = (1<<18), + EVENT_MAILBOX_UNSUBSCRIBE = (1<<19), +- EVENT_CALENDAR = (1<<20) ++ EVENT_CALENDAR = (1<<20), ++ EVENT_ACL_CHANGE = (1<<21) + }; + + /* +@@ -110,6 +111,8 @@ enum event_param { + EVENT_MIDSET, + EVENT_FLAG_NAMES, + EVENT_PID, ++ EVENT_ACL_SUBJECT, ++ EVENT_ACL_RIGHTS, + EVENT_USER, + EVENT_MESSAGE_SIZE, + #ifdef WITH_DAV +@@ -221,6 +224,13 @@ void mboxevent_add_flag(struct mboxevent *event, const char *flag); + void mboxevent_set_access(struct mboxevent *event, + const char *serveraddr, const char *clientaddr, + const char *userid, const char *mailboxname); ++ ++/* ++ * Shortcut to setting event notification parameters ++ */ ++void mboxevent_set_acl(struct mboxevent *event, const char *identifier, ++ const char *rights); ++ + /* + * Extract data from the given record to fill these event parameters : + * - uidset from UID +diff --git a/imap/mboxlist.c b/imap/mboxlist.c +index 2e4b7ee..c313ba7 100644 +--- a/imap/mboxlist.c ++++ b/imap/mboxlist.c +@@ -1854,6 +1854,15 @@ EXPORTED int mboxlist_setacl(struct namespace *namespace, const char *name, + name, cyrusdb_strerror(r)); + r = IMAP_IOERROR; + } ++ ++ /* send a AclChange event notification */ ++ struct mboxevent *mboxevent = mboxevent_new(EVENT_ACL_CHANGE); ++ mboxevent_extract_mailbox(mboxevent, mailbox); ++ mboxevent_set_acl(mboxevent, identifier, rights); ++ ++ mboxevent_notify(mboxevent); ++ mboxevent_free(&mboxevent); ++ + } + + /* 4. Change backup copy (cyrus.header) */ +-- +1.8.3.1 +
View file
0007-Correct-location-of-ifdef-endif.patch
Added
@@ -0,0 +1,27 @@ +From a5446f731ca691d8cd5eecc5ec21d81e70f5a688 Mon Sep 17 00:00:00 2001 +From: "Jeroen van Meeuwen (Kolab Systems)" <vanmeeuwen@kolabsys.com> +Date: Sat, 8 Mar 2014 23:56:42 +0100 +Subject: [PATCH 7/7] Correct location of ifdef/endif + +--- + imap/mboxevent.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/imap/mboxevent.c b/imap/mboxevent.c +index 9a60b0a..feac0fd 100644 +--- a/imap/mboxevent.c ++++ b/imap/mboxevent.c +@@ -809,8 +809,9 @@ EXPORTED void mboxevent_extract_record(struct mboxevent *event, struct mailbox * + } + } + } +-} + #endif //WITH_DAV ++} ++ + void mboxevent_extract_copied_record(struct mboxevent *event, + const struct mailbox *mailbox, uint32_t uid) + { +-- +1.8.3.1 +
View file
0008-Extend-ifdefs-endifs-for-WITH_DAV.patch
Added
@@ -0,0 +1,47 @@ +From 46eb1fa3ba446dbfdb31277fb0499785394a4d72 Mon Sep 17 00:00:00 2001 +From: "Jeroen van Meeuwen (Kolab Systems)" <vanmeeuwen@kolabsys.com> +Date: Sun, 9 Mar 2014 00:00:30 +0100 +Subject: [PATCH 8/8] Extend ifdefs/endifs for WITH_DAV + +--- + imap/mbdump.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/imap/mbdump.c b/imap/mbdump.c +index acabb95..352ed24 100644 +--- a/imap/mbdump.c ++++ b/imap/mbdump.c +@@ -630,6 +630,7 @@ EXPORTED int dump_mailbox(const char *tag, struct mailbox *mailbox, uint32_t uid + fname = mboxkey_getpath(userid); + ftag = "MBOXKEY"; + break; ++#ifdef WITH_DAV + case DAV_DB: { + struct buf dav_file = BUF_INITIALIZER; + +@@ -638,6 +639,7 @@ EXPORTED int dump_mailbox(const char *tag, struct mailbox *mailbox, uint32_t uid + ftag = "DAV"; + break; + } ++#endif // WITH_DAV + default: + fatal("unknown user data file", EC_OSFILE); + } +@@ -1072,12 +1074,14 @@ EXPORTED int undump_mailbox(const char *mbname, + char *s = user_hash_subs(userid); + strlcpy(fnamebuf, s, sizeof(fnamebuf)); + free(s); ++#ifdef WITHDAV + } else if (userid && !strcmp(file.s, "DAV")) { + /* overwriting this outright is absolutely what we want to do */ + struct buf dav_file = BUF_INITIALIZER; + dav_getpath_byuserid(&dav_file, userid); + strlcpy(fnamebuf, buf_cstring(&dav_file), sizeof(fnamebuf)); + buf_free(&dav_file); ++#endif // WITH_DAV + } else if (userid && !strcmp(file.s, "SEEN")) { + seen_file = seen_getpath(userid); + +-- +1.8.3.1 +
View file
0009-Keep-the-same-order-between-.c-and-.h-perhaps.patch
Added
@@ -0,0 +1,34 @@ +From c70ef68f50b32bbdad04ba4d80b9f9a8bddf8817 Mon Sep 17 00:00:00 2001 +From: "Jeroen van Meeuwen (Kolab Systems)" <vanmeeuwen@kolabsys.com> +Date: Sun, 9 Mar 2014 00:26:18 +0100 +Subject: [PATCH 9/9] Keep the same order between .c and .h perhaps? + +--- + imap/mboxevent.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/imap/mboxevent.c b/imap/mboxevent.c +index feac0fd..4fdf6a5 100644 +--- a/imap/mboxevent.c ++++ b/imap/mboxevent.c +@@ -122,8 +122,6 @@ static struct mboxevent event_template = + { EVENT_DISK_QUOTA, "diskQuota", EVENT_PARAM_INT, 0, 0 }, + { EVENT_DISK_USED, "diskUsed", EVENT_PARAM_INT, 0, 0 }, + { EVENT_MAX_MESSAGES, "maxMessages", EVENT_PARAM_INT, 0, 0 }, +- { EVENT_ACL_SUBJECT, "aclSubject", EVENT_PARAM_STRING, 0, 0 }, +- { EVENT_ACL_RIGHTS, "aclRights", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_MESSAGES, "messages", EVENT_PARAM_INT, 0, 0 }, + { EVENT_UNSEEN_MESSAGES, "vnd.cmu.unseenMessages", EVENT_PARAM_INT, 0, 0 }, + { EVENT_CONVEXISTS, "vnd.fastmail.convExists", EVENT_PARAM_INT, 0, 0 }, +@@ -133,6 +131,8 @@ static struct mboxevent event_template = + { EVENT_MIDSET, "vnd.cmu.midset", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_FLAG_NAMES, "flagNames", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_PID, "pid", EVENT_PARAM_INT, 0, 0 }, ++ { EVENT_ACL_SUBJECT, "aclSubject", EVENT_PARAM_STRING, 0, 0 }, ++ { EVENT_ACL_RIGHTS, "aclRights", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_USER, "user", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_MESSAGE_SIZE, "messageSize", EVENT_PARAM_INT, 0, 0 }, + #ifdef WITH_DAV +-- +1.8.3.1 +
View file
cyrus-imapd-2.5.tar.gz/Makefile.am
Changed
@@ -161,12 +161,15 @@ imap/http_dblookup.c \ imap/http_ischedule.c \ imap/http_rss.c \ + imap/http_timezone.c \ + imap/zoneinfo_db.c \ imap/caldav_db.c \ imap/proxy.c \ imap/smtpclient.c \ imap/spool.c \ imap/carddav_db.c \ imap/dav_db.c \ + imap/dav_util.c \ imap/jcal.c \ imap/xcal.c \ imap/httpd.c @@ -951,9 +954,12 @@ imap/http_dav.c \ imap/http_dblookup.c \ imap/dav_db.c \ + imap/dav_util.c \ imap/http_ischedule.c \ imap/http_carddav.c \ imap/http_caldav.c \ + imap/http_timezone.c \ + imap/zoneinfo_db.c \ imap/smtpclient.c \ imap/xcal.c \ imap/jcal.c \
View file
cyrus-imapd-2.5.tar.gz/cunit/annotate.testc
Changed
@@ -5,6 +5,7 @@ #include "assert.h" #include "xmalloc.h" #include "retry.h" +#include "util.h" #include "imap/global.h" #include "libcyr_cfg.h" #include "imap/annotate.h"
View file
cyrus-imapd-2.5.tar.gz/cunit/buf.testc
Changed
@@ -5,6 +5,7 @@ #include "util.h" #include "retry.h" #include "map.h" +#include "util.h" #include <sys/mman.h> static void test_simple(void) @@ -1223,7 +1224,6 @@ { static const char DATA0[] = "cardigan umami"; struct buf b = BUF_INITIALIZER; - const char *s; CU_ASSERT_EQUAL(b.len, 0); CU_ASSERT(b.alloc >= b.len); @@ -1236,14 +1236,6 @@ CU_ASSERT_EQUAL(buf_len(&b), b.len); CU_ASSERT_PTR_EQUAL(b.s, (char *)DATA0); - s = buf_cstring(&b); - CU_ASSERT_PTR_NOT_NULL(s); - CU_ASSERT_PTR_EQUAL(s, (char *)DATA0); - CU_ASSERT_EQUAL(b.len, sizeof(DATA0)-1); - CU_ASSERT_EQUAL(b.alloc, 0); - CU_ASSERT_EQUAL(buf_len(&b), b.len); - CU_ASSERT_PTR_EQUAL(b.s, (char *)DATA0); - buf_putc(&b, 'X'); CU_ASSERT_EQUAL(b.len, sizeof(DATA0)-1+1); CU_ASSERT(b.alloc >= b.len);
View file
cyrus-imapd-2.5.tar.gz/cunit/dlist.testc
Changed
@@ -380,4 +380,31 @@ buf_free(&b2); } +static void test_deepstructure(void) +{ + struct dlist *dl = NULL; + struct dlist *di = NULL; + struct buf b = BUF_INITIALIZER; + struct buf b2 = BUF_INITIALIZER; + int r; + + buf_setcstr(&b, "%(toplevel %(sub thing) ANOTHER (value is %(list with interesting things) (in it)) ExTrA ExTrA READ \"all about it\" INCLUDING 123456)"); + + r = dlist_parsemap(&dl, 0, b.s, b.len); + + CU_ASSERT_EQUAL(r, 0); + CU_ASSERT_PTR_NOT_NULL(dl); + + di = dlist_getchild(dl, "INCLUDING"); + CU_ASSERT_EQUAL(dlist_num(di), 123456); + + dlist_printbuf(dl, 0, &b2); + + CU_ASSERT_STRING_EQUAL(buf_cstring(&b2), buf_cstring(&b)); + + dlist_free(&dl); + buf_free(&b); + buf_free(&b2); +} + /* vim: set ft=c: */
View file
cyrus-imapd-2.5.tar.gz/cunit/message.testc
Changed
@@ -3,6 +3,7 @@ #endif #include "cunit/cunit.h" #include "parseaddr.h" +#include "util.h" #include "imap/message.h" static void test_parse_trivial(void)
View file
cyrus-imapd-2.5.tar.gz/cunit/sieve.testc
Changed
@@ -16,6 +16,7 @@ #include "retry.h" #include "imap/spool.h" #include "map.h" +#include "util.h" #include "cyrusdb.h" #include "libcyr_cfg.h" #include "libconfig.h"
View file
cyrus-imapd-2.5.tar.gz/doc/changes.html
Changed
@@ -8,11 +8,41 @@ </head> <body> +<h1>Changes to the Cyrus IMAP Server since 2.4.17-caldav-beta9</h1> +<ul> +<li>Split merging of scheduling object resources from + sched_deliver_local() into deliver_merge_request() and + deliver_merge_reply().</li> +</ul> + +<h1>Changes to the Cyrus IMAP Server since 2.4.17-caldav-beta8</h1> +<ul> +<li>Fixed bug in parsing of Accept header (now accepts <tt>*/*</tt> + and <tt>type/*</tt>).</li> +<li>Fixed telemetry logging bug (old garbage appearing in log).</li> +<li>Added a workaround for the DELETE bug in MacOS X 10.9.0 Calendar + client.</li> +</ul> + <h1>Changes to the Cyrus IMAP Server since 2.4.17-caldav-beta7</h1> <ul> -<li>Added support for returning jCal data in GET/PROPFIND/REPORT - response.</li> -<li>Added support for accepting jCal data in PUT request.</li> +<li>Added Timzone Service module along with associated admin tools + (ctl_zoneinfo, vzic).</li> +<li>Added support for accepting/returning jCal (requires Jansson) and + xCal data wherever iCalendar data is allowed.</li> +<li>Proxied responses (including chunked) are now piped to client + rather than being buffered and forwarded.</li> +<li>Better handling of COPY/MOVE between backends (including + LOCKs).</li> +<li>Fixed "annotation truncation" bug where the largest allowed + annotation value was slightly less than 4k (solves problem reading + CalDavZAP settings).</li> +<li>GET on ./well-known now returns a list of /.well-known/ URLs on + the server.</li> +<li>Added support for X-HTTP-Method-Override header in POST requests.</li> +<li>Added replacement functions for those not present in libxml2 < + v2.8.0</li> +<li>Plugged a few more memory leaks found by Valgrind.</li> </ul> <h1>Changes to the Cyrus IMAP Server since 2.4.17-caldav-beta6</h1>
View file
cyrus-imapd-2.5.tar.gz/doc/install-http.html
Changed
@@ -7,7 +7,7 @@ </head> <body> -<h1>Cyrus HTTP (RSS, CalDAV, CardDAV, iSchedule, DomainKey)</h1> +<h1>Cyrus HTTP (RSS, CalDAV, CardDAV, iSchedule, Timezone Service)</h1> <b><i>Note that the HTTP service and associated modules in Cyrus are still under development. This release should be considered beta @@ -28,6 +28,10 @@ <li>Allow scheduling transactions between separate calendaring and scheduling systems via the iSchedule protocol <i>(currently only used within a Cyrus Murder)</i>.</li> +<li>Act as a Timezone Service by serving iCalendar (VTIMEZONE) + data to client systems.</li> +<li>Serve static content (such as the RSS feed list template and/or + the CalDAV/CardDAV JavaScript clients mentioned below).</li> </ul> <i>Unlike the <a href="http://httpd.apache.org/">Apache HTTP @@ -61,12 +65,13 @@ <ul> <li>Must have <a href="http://xmlsoft.org/">libxml2</a> installed.</li> -<li>Must have a recent SASL build (v2.1.26 or later) in order to - support HTTP Digest, Negotiate, and NTLM authentication. - Otherwise, only HTTP Basic authentication will be available</li> +<li>Must have a recent <a href="http://www.cyrusimap.org/">SASL</a> + release (v2.1.26 or later) in order to support HTTP Digest, + Negotiate, and NTLM authentication. Otherwise, only HTTP Basic + authentication will be available.</li> </ul> -<h3>CalDAV / CardDAV Requirements</h3> +<h3>Additional CalDAV / CardDAV Requirements</h3> <ul> <li>Must have <a href="http://freeassociation.sourceforge.net/">libical</a> @@ -74,19 +79,29 @@ <li>Must have <a href="http://www.sqlite.org/">SQLite</a> v3.x (or later) installed.</li> <li>Optionally - install <a href="https://github.com/jehiah/json-c">json-c</a> for + install <a href="http://www.digip.org/jansson/">Jansson</a> for jCal/jCard support.</li> </ul> <!-- -<h3>iSchedule Requirements</h3> +<h3>Additional iSchedule Requirements</h3> <ul> +<li>Must meet CalDAV requirements above.</li> <li>Must - have <a href="http://www.opendkim.org/">OpenDKIM v2.9.x (or higher)</a> + have <a href="http://www.opendkim.org/">OpenDKIM v2.x.x (or higher)</a> installed.</li> </ul> --> +<h3>Additional Timezone Service Requirements</h3> +<ul> +<li>Must + have <a href="http://freeassociation.sourceforge.net/">libical</a> + installed.</li> +<li>Must have <a href="http://www.digip.org/jansson/">Jansson</a> + installed.</li> +</ul> + <h2 id="config">General Configuration</h2> <p>The Cyrus <tt>httpd</tt> service is configurable via several @@ -512,6 +527,72 @@ </p> +<h2>Timezone Service Module</h2> + +<h3>Configuration</h3> + +<p>When enabled, the Timezone module allows Cyrus to function as a + timezone service, providing timezone data to client systems. This + module stores timezone data in the <tt>zoneinfo/</tt> subdirectory of + the Cyrus configuration directory (as specified by + the <tt>configdir</tt> option). The data is indexed by a database + whose location is specified by the <tt>zoneinfo_db_path</tt> option, + using the format specified by the <tt>zoneinfo_db</tt> option.</p> + +<h3>Administration</h3> + +<p>This module is designed to use the <i>Time Zone Database</i> data + (a.k.a. <i>Olson Database</i>) converted to the iCalendar format. The + steps to populate the Cyrus <tt>zoneinfo/</tt> directory are as follows: + +<ol start=0> +<li>Build the <tt>vzic</tt> utility located in + the <tt>tools/vzic/</tt> subdirectory of the Cyrus source code. + Simply running <tt>make</tt> in the <tt>tools/vzic/</tt> + subdirectory should suffice.</li> +<li>Download the latest version of the Time Zone Database data + from <a href="http://www.iana.org/time-zones">IANA</a>. <i>Only the + data is required, NOT the code</i>.</li> +<li>Expand the downloaded timezone data into the temporary directory + of your choice.</li> +<li>Populate <tt>configdir/zoneinfo/</tt> with iCalendar data: + <p><i>Initial Install Only</i></p> + <ol type=a> + <li>Convert the raw data into iCalendar format by + running <tt>vzic</tt> as follows: + <p><tt>vzic --pure --olson-dir <location-of-raw-data> + --output-dir <configdir>/zoneinfo</tt></p> + <p>This will create and install iCalendar data directly into + the <tt>configdir/zoneinfo/</tt> directory.</p> + </li> + </ol> + <p><i>Updating Data Only</i></p> + <ol type=a> + <li>Convert the raw data into iCalendar format by + running <tt>vzic</tt> as follows: + <p><tt>vzic --pure --olson-dir <location-of-raw-data></tt></p> + <p>This will create a <tt>zoneinfo/</tt> subdirectory in your + current location (preferably <tt>tools/vzic/</tt>).</p> + </li> + <li>Merge new/updated iCalendar data into + the <tt>configdir/zoneinfo/</tt> directory by + running <tt>vzic-merge.pl</tt> in your current location: + <p><tt>vzic-merge.pl</tt></p> + </li> + </ol> +</li> +<li>Rebuild the Cyrus zoneinfo index by + running <tt>ctl_zoneinfo</tt> as follows: + <p><tt>ctl_zoneinfo -r <version-string></tt></p> + <p>where <tt><version-string></tt> describes the recently + downloaded timezone data (e.g. "Time Zone Database + v.2013h").</p></li> +<li>Verify that the zoneinfo index database and all iCalendar data + files/links are readable by the <tt>cyrus</tt> user.</li> +</ol> +</p> + + <h2>iSchedule Module</h2> <p>This module will be automatically enabled if and only if both the @@ -527,6 +608,7 @@ <h3>Administration</h3> --> + <h2>DomainKey Module</h2> <p><i>Currently unavailable. Will be available once iSchedule support to
View file
cyrus-imapd-2.5.tar.gz/doc/install.html
Changed
@@ -37,7 +37,8 @@ <li><a href="install-sieve.html">Installing SIEVE</a> <li><a href="install-snmpmon.html">SNMP Monitoring</a> <li><a href="install-netnews.html">Cyrus and Netnews</a> -<li><a href="install-http.html">Cyrus HTTP (RSS, CalDAV, CardDAV)</a> +<li><a href="install-http.html">Cyrus HTTP (RSS, CalDAV, CardDAV, + Timezone Service)</a> <li><a href="install-virtdomains.html">Virtual Domains</a> <li><a href="install-replication.html">Cyrus Replication</a> <li><a href="install-murder.html">Cyrus Murder: The IMAP @@ -61,7 +62,5 @@ </ul> <P><HR> -last modified: $Date: 2006/11/30 17:11:16 $ -<br> <A HREF="index.html">Return</A> to the Cyrus IMAP Server Home Page </BODY></HTML>
View file
cyrus-imapd-2.5.tar.gz/doc/internal/caldav_scheduling_flowchart.html
Added
@@ -0,0 +1,337 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" + "http://www.w3.org/TR/html4/strict.dtd"> +<html> +<head> + <title>Cyrus CalDAV Scheduling Flowchart</title> + <meta http-equiv="content-type" content="text/html; charset=UTF-8"> +</head> +<body> + <h1>Cyrus CalDAV Scheduling Flowchart</h1> + + <h3 id="caldav_put">caldav_put() - create/modify via HTTP PUT on a + resource or POST (add-member) on a calendar</h3> + <ol> + <li>Check if the new resource is a scheduling resource (contains + ORGANIZER property). If not, skip to step 4.</li> + <li>Check for (and load) any existing resource.</li> + <li>Check if the authenticated user matches ORGANIZER. If yes, + goto <a href="#sched_request">sched_request()</a>, otherwise + goto <a href="#sched_reply">sched_reply()</a>.</li> + <li>Store the new/modified resource.</li> + </ol> + + <h3 id="caldav_delete_sched">caldav_delete_sched() - remove via HTTP + DELETE on a resource</h3> + <ol> + <li>Check if the existing resource is a scheduling resource (has + Schedule-Tag). If not, we are done.</li> + <li>Load the existing resource.</li> + <li>Check if the authenticated user matches ORGANIZER. If yes, + goto <a href="#sched_request">sched_request()</a>, otherwise + goto <a href="#sched_reply">sched_reply()</a>.</li> + </ol> + + <h3 id="caldav_post">caldav_post() - busytime query via HTTP POST on + Scheduling Outbox</h3> + <ol> + <li>Check the ACL on the owner's Scheduling Outbox. If the + authenticated user doesn't have the DACL_SCHEDFB right, fail.</li> + <li><a href="#sched_busytime_query">sched_busytime_query()</a>.</li> + </ol> + + <hr> + + <h3 id="sched_request">sched_request() - perform an organizer + request / attendee status update</h3> + <ol> + <li>Check the ACL on the owner's Scheduling Outbox. If the + authenticated user doesn't have the DACL_INVITE right, fail.</li> + <li>If the request includes a resource, then set METHOD:REQUEST, + otherwise set METHOD:CANCEL.</li> + <li>Create an iTIP message template, copying over any + CALSCALE property and VTIMEZONE components.</li> + <li>If not an attendee status update and the existing resource is a + scheduling resource: + Foreach component in the existing resource, add it and + its SEQUENCE to our hash table keyed by RECURRENCE-ID (for + comparison against new/modified resource).</li> + <li>Create a hash table of attendees. This will hold + attendee-specific iTIP messages.</li> + <li>Foreach component in the new/modified resource:</li> + <ol type=a> + <li>Lookup (by RECURRENCE-ID) and remove the component from the + hash table of existing components.</li> + <li>If the component exists compare all of DTSTART, DTEND, + DURATION, RRULE, RDATE, EXDATE to those of the new + component.</li> + <li>If the component is new or changed, + then <a href="#process_attendees">process_attendees()</a>.</li> + </ol> + <li>Foreach remaining component in the hash table of existing + components do <a href="#sched_cancel">sched_cancel()</a>.</li> + <li>Foreach iTIP message in our hash table of + ATTENDEES, <a href="#sched_deliver">sched_deliver()</a> the iTIP + message.</li> + <li>Foreach component in the new/modified resource update the + SCHEDULE-STATUS of each ATTENDEE.</li> + </ol> + + <h3 id="process_attendees">process_attendees() - create a suitable + iTIP request message for each attendee</h3> + <ol> + <li>Foreach ATTENDEE in the component, remove the SCHEDULE-STATUS + parameter, and set PROPSTAT=NEEDS-ACTION if required.</li> + <li>Make a copy of the component and + <a href="#clean_component">clean_component()</a>.</li> + <li>Foreach ATTENDEE in the cleaned component:</li> + <ol type=a> + <li>Check the CalDAV Scheduling parameters. If SCHEDULE-AGENT + != SERVER, skip to the next attendee.</li> + <li>Lookup attendee in our hash table.</li> + <li>If it doesn't exist, create a clone of our iTIP template and + insert it into our hash table of attendees.</li> + <li>Add the component to the attendee's iTIP message.</li> + <li>Add the component “number” to our mask of new components + appearing in the attendee's iTIP message.</li> + </ol> + <li>If the component is not the "master", foreach attendee do + <a href="#sched_exclude">sched_exclude()</a>.</li> + </ol> + + <h3 id="sched_exclude">sched_exclude() - exclude an attendee from a + recurrence instance</h3> + <ol> + <li>If the component did not appear in the attendee's iTIP + message, add an EXDATE property (based on the RECURRENCE-ID of + the component) to the master component of the attendee's iTIP + message.</li> + </ol> + + <h3 id="sched_cancel">sched_cancel() - cancel an organizer event/task</h3> + <ol> + <li>Set STATUS:CANCELLED on the component.</li> + <li><a href="#process_attendees">process_attendees()</a>.</li> + </ol> + + <hr> + + <h3 id="sched_reply">sched_reply() - perform an attendee reply</h3> + <ol> + <li>Check the CalDAV Scheduling parameters on ORGANIZER. If + SCHEDULE-AGENT != SERVER, we are done.</li> + <li>Check the ACL on the owner's Scheduling Outbox. If the + authenticated user doesn't have the DACL_REPLY right, fail.</li> + <li>Create a new iTIP (METHOD:REPLY) message, copying over any + CALSCALE property and VTIMEZONE components.</li> + <li>Foreach component in the existing resource:</li> + <ol type=a> + <li><a href="#trim_attendees">trim_attendees()</a>.</li> + <li>Add the trimmed component and the attendee's PARTSTAT to our + hash table keyed by RECURRENCE-ID (for comparison against + new/modified resource).</li> + </ol> + <li>Foreach component in the new/modified resource:</li> + <ol type=a> + <li><a href="#trim_attendees">trim_attendees()</a>.</li> + <li>Lookup (by RECURRENCE-ID) and remove the component from the + hash table of existing components.</li> + <li>If the component exists, compare the PARTSTAT of the + ATTENDEE to that of the new component.</li> + <li>If the component is new or the PARTSTAT has changed:</li> + <ol type=i> + <li><a href="#clean_component">clean_component()</a>.</li> + <li>Add the component to our iTIP message.</li> + <li>Add the component “number” to our mask of new components + appearing in our iTIP message.</li> + </ol> + </ol> + <li>Foreach remaining component in the hash table of existing + components do <a href="#sched_decline">sched_decline()</a>.</li> + <li><a href="#sched_deliver">sched_deliver()</a> our iTIP + message.</li> + <li>Foreach component in the new/modified resource that appeared + in our iTIP message, update the SCHEDULE-STATUS of the ORGANIZER.</li> + </ol> + + <h3 id="trim_attendees">trim_attendees() - remove all attendees + other than the one replying</h3> + <ol> + <li>Clone the component and remove all ATTENDEE properties other + than the one corresponding to the owner of the calendar.</li> + <li>Return the ATTENDEE property of owner, his/her PARTSTAT + parameter, and the RECURRENCE-ID of the component.</li> + </ol> + + <h3 id="sched_decline">sched_decline() - decline a recurrence + instance for an attendee</h3> + <ol> + <li>Set PARTSTAT of ATTENDEE to DECLINED.</li> + <li><a href="#clean_component">clean_component()</a>.</li> + <li>Add the component to our iTIP message.</li> + </ol> + + <hr> + + <h3 id="clean_component">clean_component() - sanitize a component + for use in an iTIP message</h3> + <ol> + <li>Update DTSTAMP.</li> + <li>Remove any VALARM components.</li> + <li>For a reply/decline only, remove scheduling parameters from + ORGANIZER.</li> + </ol> + + <h3 id="sched_deliver">sched_deliver() - deliver an iTIP message to + a recipient</h3> + <ol> + <li>Lookup the recipient.</li> + <li>If local to our server goto + <a href="#sched_deliver_local">sched_deliver_local()</a>, + otherwise goto + <a href="#sched_deliver_remote">sched_deliver_remote()</a>.</li> + </ol> + + <hr> + + <h3 id="sched_deliver_local">sched_deliver_local() - deliver an + iTIP message to a local user</h3> + <ol> + <li>Check the ACL on the owner's Scheduling Inbox. If the
View file
cyrus-imapd-2.5.tar.gz/doc/internal/database-formats.html
Changed
@@ -158,6 +158,21 @@ Data: <Version>TAB<Deny List (comma-separated wildmat patterns)>TAB<Deny Message> </pre> +<h2>Timezone Info (zoneinfo.db)</h2> + +<p>This database is used for the timezone service and contains records + relating to timezones and their aliases. The database is indexed by + timezone ID and each data record contains the database version + number, a record type, a timestamp, and an optional list of strings + (either aliases for a timezone or the reference timezone for an + alias). The format of each record is as follows:</p> + +<pre> +Key: <TZID> + +Data: <Version>SP<Record Type>SP<Timestamp>SP<Data Strings (TAB-separated)> +</pre> + <h2>Seen State (<userid>.seen)</h2> <p>This database is a per-user database and maintains the list of
View file
cyrus-imapd-2.5.tar.gz/doc/specs.html
Changed
@@ -255,6 +255,8 @@ <TD>Locating Services for Calendaring Extensions to WebDAV (CalDAV) and vCard Extensions to WebDAV (CardDAV)</TD></TR> <TR><TD><A HREF="http://tools.ietf.org/html/draft-desruisseaux-ischedule">draft-desruisseaux-ischedule</A></TD> <TD>Internet Calendar Scheduling Protocol (iSchedule)</TD></TR> +<TR><TD><A HREF="http://tools.ietf.org/html/draft-douglass-timezone-service">draft-douglass-timezone-service</A></TD> +<TD>Timezone Service Protocol</TD></TR> <TR><TD><A HREF="http://tools.ietf.org/html/draft-thomson-hybi-http-timeout">draft-thomson-hybi-http-timeout</A></TD> <TD>Hypertext Transfer Protocol (HTTP) Keep-Alive Header</TD></TR> <TR><TD><A HREF="http://tools.ietf.org/html/draft-ietf-appsawg-http-forwarded">draft-ietf-appsawg-http-forwarded</A></TD>
View file
cyrus-imapd-2.5.tar.gz/imap/Makefile.in
Added
@@ -0,0 +1,407 @@ +# Makefile for cyrus imap server and associated programs +# +# Copyright (c) 1994-2008 Carnegie Mellon University. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# 3. The name "Carnegie Mellon University" must not be used to +# endorse or promote products derived from this software without +# prior written permission. For permission or any legal +# details, please contact +# Carnegie Mellon University +# Center for Technology Transfer and Enterprise Creation +# 4615 Forbes Avenue +# Suite 302 +# Pittsburgh, PA 15213 +# (412) 268-7393, fax: (412) 268-7395 +# innovation@andrew.cmu.edu +# +# 4. Redistributions of any form whatsoever must retain the following +# acknowledgment: +# "This product includes software developed by Computing Services +# at Carnegie Mellon University (http://www.cmu.edu/computing/)." +# +# CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO +# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE +# FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN +# AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +# OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +DEFINES=-DSETPROCTITLE + +# \Seen state database. Either 'db' (berkeley db) or +# 'local' (legacy flat file). +SEEN=seen_db.o + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +CC = @CC@ +INSTALL = @INSTALL@ +RANLIB = @RANLIB@ +AWK = @AWK@ + +CYRUS_USER=@cyrus_user@ +CYRUS_GROUP=@cyrus_group@ + +DEFS = @DEFS@ @LOCALDEFS@ +CPPFLAGS = -I.. -I$(srcdir)/../lib @COM_ERR_CPPFLAGS@ @SIEVE_CPPFLAGS@ @CPPFLAGS@ @SASLFLAGS@ @XML2_CFLAGS@ @ICAL_CFLAGS@ @SQLITE3_CFLAGS@ @DKIM_CFLAGS@ +IMAP_LIBS = @IMAP_LIBS@ @LIB_RT@ + +RSS_OBJS = http_rss.o +DAV_OBJS = http_dav.o dav_db.o +CALDAV_OBJS = http_caldav.o caldav_db.o smtpclient.o xcal.o jcal.o +CARDDAV_OBJS = http_carddav.o carddav_db.o +ISCHED_OBJS = http_ischedule.o +TIMEZONE_OBJS = http_timezone.o zoneinfo_db.o +HTTP_OBJS = httpd.o http_err.o http_proxy.o @HTTP_OBJS@ +HTTP_LIBS = @XML2_LIBS@ @ICAL_LIBS@ @SQLITE3_LIBS@ @DKIM_LIBS@ @JSON_LIBS@ + +SIEVE_OBJS = @SIEVE_OBJS@ +SIEVE_LIBS = @SIEVE_LIBS@ +IMAP_COM_ERR_LIBS = @IMAP_COM_ERR_LIBS@ +LIB_WRAP = @LIB_WRAP@ +LIBS = $(IMAP_LIBS) $(IMAP_COM_ERR_LIBS) +DEPLIBS = ../lib/libcyrus.a ../lib/libcyrus_min.a @DEPLIBS@ + +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ @COM_ERR_LDFLAGS@ + +SHELL = /bin/sh +MAKEDEPEND = @MAKEDEPEND@ + +COMPILE_ET=@COMPILE_ET@ + +# +# Some notes on purify -- +# you probably want to run the make as the cyrus user as +# purify sets the cache directory based on the user. So, +# if you don't, purify can't find the instrumented libraries +# and so you don't get any useful information. +# It may also help to run purify by hand to instrument any of +# the dynamic libraries that may crop up during run time. +# +PURIFY=/usr/local/bin/purify +PUREOPT= -best-effort -logfile=/tmp/pure/%v.%p.log -always_use_cache_dir -cachedir=/usr/tmp/$(USER) +QUANTIFY=/usr/local/bin/quantify +QUANTOPT=-windows=no -filename-prefix=/tmp/quant/%v.%p -write-summary-file= -logfile=/tmp/quant/%v.%p.log + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +cyrus_prefix = @cyrus_prefix@ +service_path = @service_path@ + +LOBJS= append.o mailbox.o mboxlist.o mupdate-client.o mboxname.o message.o \ + global.o imap_err.o mupdate_err.o proc.o setproctitle.o \ + convert_code.o duplicate.o saslclient.o saslserver.o ../lib/signals.o \ + annotate.o search_engines.o squat.o squat_internal.o mbdump.o \ + imapparse.o telemetry.o user.o notify.o idle.o quota_db.o \ + sync_log.o $(SEEN) mboxkey.o backend.o tls.o message_guid.o \ + statuscache_db.o userdeny_db.o sequence.o upgrade_index.o \ + dlist.o version.o dav_util.o + +IMAPDOBJS=pushstats.o imapd.o proxy.o imap_proxy.o index.o + +LMTPOBJS=lmtpstats.o lmtpengine.o spool.o + +# Your typical objects for the command line utilities +CLIOBJS=cli_fatal.o mutex_fake.o + +SERVICE=../master/service.o +SERVICETHREAD=../master/service-thread.o + +PROGS = imapd lmtpd pop3d \ + fud smmapd reconstruct quota mbpath ipurge cyr_dbtool cyr_synclog \ + cyrdump chk_cyrus cvt_cyrusdb deliver ctl_mboxlist \ + ctl_deliver ctl_cyrusdb squatter mbexamine cyr_expire arbitron \ + unexpunge cyr_df cyr_sequence cyr_userseen \ + @IMAP_PROGS@ + +BUILTSOURCES = imap_err.c imap_err.h pushstats.c pushstats.h \ + lmtpstats.c lmtpstats.h mupdate_err.c mupdate_err.h \ + nntp_err.c nntp_err.h http_err.c http_err.h + +all: $(BUILTSOURCES) $(PROGS) $(SUIDPROGS) + +pure: imapd.pure lmtpd.pure mupdate.pure + + +install: + $(srcdir)/../install-sh -d ${DESTDIR}$(service_path) + for file in $(PROGS); \ + do \ + $(INSTALL) -m 755 $$file $(DESTDIR)$(service_path) || exit 1; \ + done + ln -f $(DESTDIR)$(service_path)/pop3d $(DESTDIR)$(service_path)/pop3proxyd + ln -f $(DESTDIR)$(service_path)/imapd $(DESTDIR)$(service_path)/proxyd + ln -f $(DESTDIR)$(service_path)/lmtpd $(DESTDIR)$(service_path)/lmtpproxyd + +.c.o: + $(CC) -c $(CPPFLAGS) $(DEFS) $(CFLAGS) \ + $< + +### libimap + +libimap.a: $(LOBJS) + rm -f libimap.a + ar cr libimap.a $(LOBJS) + $(RANLIB) libimap.a + +### Built Source Files + +version.o: ../xversion.h + +pushstats.c: pushstats.snmp $(srcdir)/../snmp/snmpgen + $(srcdir)/../snmp/snmpgen $(srcdir)/pushstats.snmp + +pushstats.h: pushstats.c + +lmtpstats.c: lmtpstats.snmp $(srcdir)/../snmp/snmpgen + $(srcdir)/../snmp/snmpgen $(srcdir)/lmtpstats.snmp + +lmtpstats.h: lmtpstats.c + +imap_err.c: imap_err.et + $(COMPILE_ET) $(srcdir)/imap_err.et + +imap_err.h: imap_err.c + +nntp_err.c: nntp_err.et + $(COMPILE_ET) $(srcdir)/nntp_err.et + +nntp_err.h: nntp_err.c + +mupdate_err.c: mupdate_err.et + $(COMPILE_ET) $(srcdir)/mupdate_err.et + +mupdate_err.h: mupdate_err.c + +http_err.c: http_err.et + $(COMPILE_ET) $(srcdir)/http_err.et + +http_err.h: http_err.c + +### Services +idled: idled.o mutex_fake.o libimap.a $(DEPLIBS)
View file
cyrus-imapd-2.5.tar.gz/imap/annotate.c
Changed
@@ -811,56 +811,45 @@ const char **entryp, const char **useridp) { -#define NFIELDS 3 - const char *fields[NFIELDS]; - int nfields = 0; + static struct buf keybuf; const char *p; - unsigned int uid = 0; - const char *mboxname = ""; - - /* paranoia: ensure the last character in the key is - * a NUL, which it should be because of the way we - * always build keys */ - if (key[keysize-1]) - return IMAP_ANNOTATION_BADENTRY; - keysize--; + const char *end; + + buf_setmap(&keybuf, key, keysize); + buf_putc(&keybuf, '\0'); /* safety tricks due to broken FM code */ + p = buf_cstring(&keybuf); + end = p + keysize; + /* * paranoia: split the key into fields on NUL characters. * We would use strarray_nsplit() for this, except that * by design that function cannot split on NULs and does * not handle embedded NULs. */ - fields[nfields++] = key; - for (p = key ; (p-key) < keysize ; p++) { - if (!*p) { - if (nfields == NFIELDS) - return IMAP_ANNOTATION_BADENTRY; - fields[nfields++] = p+1; - } - } - if (nfields != NFIELDS) - return IMAP_ANNOTATION_BADENTRY; if (d->mboxname) { - /* per-folder db for message scope annotations */ - char *end = NULL; - uid = strtoul(fields[0], &end, 10); - if (uid == 0 || end == NULL || *end) - return IMAP_ANNOTATION_BADENTRY; - mboxname = d->mboxname; + *mboxnamep = d->mboxname; + *uidp = 0; + while (*p && p < end) *uidp = (10 * (*uidp)) + (*p++ - '0'); + if (p < end) p++; + else return IMAP_ANNOTATION_BADENTRY; } else { /* global db for mailnbox & server scope annotations */ - uid = 0; - mboxname = fields[0]; + *uidp = 0; + *mboxnamep = p; + while (*p && p < end) p++; + if (p < end) p++; + else return IMAP_ANNOTATION_BADENTRY; } - if (mboxnamep) *mboxnamep = mboxname; - if (uidp) *uidp = uid; - if (entryp) *entryp = fields[1]; - if (useridp) *useridp = fields[2]; + *entryp = p; /* XXX: trailing NULLs on non-userid keys? Bogus just at FM */ + while (*p && p < end) p++; + if (p < end && !*p) + *useridp = p+1; + else + *useridp = NULL; return 0; -#undef NFIELDS } #if DEBUG @@ -949,26 +938,28 @@ struct find_rock *frock = (struct find_rock *) rock; const char *mboxname, *entry, *userid; unsigned int uid; + char newkey[MAX_MAILBOX_NAME+1]; + size_t newkeylen; struct buf value = BUF_INITIALIZER; - char keycopy[MAX_MAILBOX_PATH+1]; int r; assert(keylen < MAX_MAILBOX_PATH); - /* take a copy, we may be deleting this record, so the key - * pointer will no longer be valid */ - memcpy(keycopy, key, keylen); - #if DEBUG syslog(LOG_ERR, "find_cb: found key %s in %s", - key_as_string(frock->d, keycopy, keylen), frock->d->filename); + key_as_string(frock->d, key, keylen), frock->d->filename); #endif - r = split_key(frock->d, keycopy, keylen, &mboxname, + r = split_key(frock->d, key, keylen, &mboxname, &uid, &entry, &userid); if (r) return r; + newkeylen = make_key(mboxname, uid, entry, userid, newkey, sizeof(newkey)); + if (keylen != newkeylen || strncmp(newkey, key, keylen)) { + syslog(LOG_ERR, "find_cb: bogus key %s %d %s %s (%d %d)", mboxname, uid, entry, userid, (int)keylen, (int)newkeylen); + } + r = split_attribs(data, datalen, &value); if (!r) r = frock->proc(mboxname, uid, entry, userid, &value, frock->rock); @@ -2498,8 +2489,8 @@ static int annotate_canon_value(struct buf *value, int type) { char *p = NULL; - unsigned long uwhatever; - long whatever; + unsigned long uwhatever = 0; + long whatever = 0; /* check for NIL */ if (value->s == NULL) @@ -3035,7 +3026,7 @@ const char *newuserid = userid; if (rrock->olduserid && rrock->newuserid && - !strcmp(rrock->olduserid, userid)) { + !strcmpsafe(rrock->olduserid, userid)) { /* renaming a user, so change the userid for priv annots */ newuserid = rrock->newuserid; }
View file
cyrus-imapd-2.5.tar.gz/imap/append.c
Changed
@@ -1369,3 +1369,8 @@ seen_close(&seendb); return r; } + +EXPORTED const char *append_stagefname(struct stagemsg *stage) +{ + return strarray_nth(&stage->parts, 0); +}
View file
cyrus-imapd-2.5.tar.gz/imap/append.h
Changed
@@ -149,4 +149,6 @@ extern int append_run_annotator(struct appendstate *as, struct index_record *record); +extern const char *append_stagefname(struct stagemsg *stage); + #endif /* INCLUDED_APPEND_H */
View file
cyrus-imapd-2.5.tar.gz/imap/arbitron.c
Changed
@@ -135,7 +135,7 @@ break; case 'D': { - unsigned month, day, year; + unsigned month = 0, day = 0, year = 0; struct tm date; if (strlen(optarg) < 8 ||
View file
cyrus-imapd-2.5.tar.gz/imap/caldav_db.c
Changed
@@ -138,8 +138,7 @@ " UNIQUE( mailbox, resource ) );" \ "CREATE INDEX IF NOT EXISTS idx_ical_uid ON ical_objs ( ical_uid );" -/* Open DAV DB corresponding to userid */ -EXPORTED struct caldav_db *caldav_open(const char *userid, int flags) +static struct caldav_db *caldav_open_fname(const char *fname, int flags) { sqlite3 *db; struct caldav_db *caldavdb = NULL; @@ -147,14 +146,45 @@ if (flags & CALDAV_TRUNC) cmds = CMD_DROP CMD_CREATE; - db = dav_open(userid, cmds); + db = dav_open(fname, cmds); if (db) { caldavdb = xzmalloc(sizeof(struct caldav_db)); caldavdb->db = db; + } + + return caldavdb; +} + +EXPORTED struct caldav_db *caldav_open_userid(const char *userid, int flags) +{ + struct caldav_db *caldavdb = NULL; + struct buf fname = BUF_INITIALIZER; + + dav_getpath_byuserid(&fname, userid); + caldavdb = caldav_open_fname(buf_cstring(&fname), flags); + buf_free(&fname); + + /* Construct mbox name corresponding to userid's scheduling Inbox */ + strncpy(caldavdb->sched_inbox, caldav_mboxname(userid, SCHED_INBOX), sizeof(caldavdb->sched_inbox)); - /* Construct mailbox name corresponding to userid's scheduling Inbox */ - strcpy(caldavdb->sched_inbox, caldav_mboxname(userid, SCHED_INBOX)); + return caldavdb; +} + +/* Open DAV DB corresponding to userid */ +EXPORTED struct caldav_db *caldav_open_mailbox(struct mailbox *mailbox, int flags) +{ + struct caldav_db *caldavdb = NULL; + const char *userid = mboxname_to_userid(mailbox->name); + + if (userid) { + caldavdb = caldav_open_userid(userid, flags); + } + else { + struct buf fname = BUF_INITIALIZER; + dav_getpath(&fname, mailbox); + caldavdb = caldav_open_fname(buf_cstring(&fname), flags); + buf_free(&fname); } return caldavdb; @@ -723,6 +753,7 @@ case ICAL_VTODO_COMPONENT: mykind = CAL_COMP_VTODO; break; case ICAL_VJOURNAL_COMPONENT: mykind = CAL_COMP_VJOURNAL; break; case ICAL_VFREEBUSY_COMPONENT: mykind = CAL_COMP_VFREEBUSY; break; + case ICAL_VAVAILABILITY_COMPONENT: mykind = CAL_COMP_VAVAILABILITY; break; default: break; } cdata->comp_type = mykind; @@ -730,6 +761,7 @@ /* Get organizer */ prop = icalcomponent_get_first_property(comp, ICAL_ORGANIZER_PROPERTY); if (prop) cdata->organizer = icalproperty_get_organizer(prop)+7; + else cdata->organizer = NULL; /* Get transparency */ prop = icalcomponent_get_first_property(comp, ICAL_TRANSP_PROPERTY);
View file
cyrus-imapd-2.5.tar.gz/imap/caldav_db.h
Changed
@@ -50,6 +50,27 @@ #include "dav_db.h" +#ifndef HAVE_VAVAILABILITY +/* Allow us to compile without #ifdef HAVE_VAVAILABILITY everywhere */ +#define ICAL_VAVAILABILITY_COMPONENT ICAL_XLICINVALID_COMPONENT +#endif + +/* Bitmask of calendar components */ +enum { + /* "Real" components - MUST remain in this order (values used in DAV DB) */ + CAL_COMP_VEVENT = (1<<0), + CAL_COMP_VTODO = (1<<1), + CAL_COMP_VJOURNAL = (1<<2), + CAL_COMP_VFREEBUSY = (1<<3), + CAL_COMP_VAVAILABILITY = (1<<4), + /* Append additional "real" components here */ + + /* Other components - values don't matter - prepend here */ + CAL_COMP_VALARM = (1<<13), + CAL_COMP_VTIMEZONE = (1<<14), + CAL_COMP_VCALENDAR = (1<<15) +}; + struct caldav_db; #define CALDAV_CREATE 0x01 @@ -73,8 +94,9 @@ /* done with all caldav operations for this process */ int caldav_done(void); -/* get a database handle corresponding to userid */ -struct caldav_db *caldav_open(const char *userid, int flags); +/* get a database handle corresponding to mailbox */ +struct caldav_db *caldav_open_mailbox(struct mailbox *mailbox, int flags); +struct caldav_db *caldav_open_userid(const char *userid, int flags); /* close this handle */ int caldav_close(struct caldav_db *caldavdb);
View file
cyrus-imapd-2.5.tar.gz/imap/carddav_db.c
Changed
@@ -141,8 +141,8 @@ #define CMD_DROP CMD_DROP_OBJ CMD_DROP_EM CMD_DROP_GR #define CMD_CREATE CMD_CREATE_OBJ CMD_CREATE_EM CMD_CREATE_GR -/* Open DAV DB corresponding to userid */ -struct carddav_db *carddav_open(const char *userid, int flags) +/* Open DAV DB corresponding to mailbox */ +static struct carddav_db *carddav_open_fname(const char *fname, int flags) { sqlite3 *db; struct carddav_db *carddavdb = NULL; @@ -150,7 +150,7 @@ if (flags & CARDDAV_TRUNC) cmds = CMD_DROP CMD_CREATE; - db = dav_open(userid, cmds); + db = dav_open(fname, cmds); if (db) { carddavdb = xzmalloc(sizeof(struct carddav_db)); @@ -160,6 +160,30 @@ return carddavdb; } +EXPORTED struct carddav_db *carddav_open_userid(const char *userid, int flags) +{ + struct buf fname = BUF_INITIALIZER; + struct carddav_db *carddavdb = NULL; + + dav_getpath_byuserid(&fname, userid); + carddavdb = carddav_open_fname(buf_cstring(&fname), flags); + buf_free(&fname); + + return carddavdb; +} + +EXPORTED struct carddav_db *carddav_open_mailbox(struct mailbox *mailbox, int flags) +{ + struct buf fname = BUF_INITIALIZER; + struct carddav_db *carddavdb = NULL; + + dav_getpath(&fname, mailbox); + carddavdb = carddav_open_fname(buf_cstring(&fname), flags); + buf_free(&fname); + + return carddavdb; +} + /* Close DAV DB */ EXPORTED int carddav_close(struct carddav_db *carddavdb)
View file
cyrus-imapd-2.5.tar.gz/imap/carddav_db.h
Changed
@@ -72,8 +72,9 @@ /* done with all carddav operations for this process */ int carddav_done(void); -/* get a database handle corresponding to userid */ -struct carddav_db *carddav_open(const char *userid, int flags); +/* get a database handle corresponding to mailbox */ +struct carddav_db *carddav_open_mailbox(struct mailbox *mailbox, int flags); +struct carddav_db *carddav_open_userid(const char *userid, int flags); /* close this handle */ int carddav_close(struct carddav_db *carddavdb);
View file
cyrus-imapd-2.5.tar.gz/imap/ctl_conversationsdb.c
Changed
@@ -778,7 +778,7 @@ { char *inboxname; char *fname; - int r; + int r = 0; fname = conversations_getuserpath(userid); if (fname == NULL) {
View file
cyrus-imapd-2.5.tar.gz/imap/ctl_zoneinfo.c
Added
@@ -0,0 +1,310 @@ +/* ctl_zoneinfo.c -- Program to perform operations on zoneinfo db + * + * Copyright (c) 1994-2013 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Carnegie Mellon University + * Center for Technology Transfer and Enterprise Creation + * 4615 Forbes Avenue + * Suite 302 + * Pittsburgh, PA 15213 + * (412) 268-7393, fax: (412) 268-7395 + * innovation@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include <config.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <dirent.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include <libical/ical.h> + +#include "annotate.h" /* for strlist functionality */ +#include "global.h" +#include "hash.h" +#include "map.h" +#include "util.h" +#include "xmalloc.h" +#include "zoneinfo_db.h" + +extern int optind; +extern char *optarg; + +/* config.c stuff */ +const int config_need_data = 0; + +int verbose = 0; + +/* forward declarations */ +void usage(void); +void free_zoneinfo(void *data); +void store_zoneinfo(const char *tzid, void *data, void *rock); +void do_zonedir(const char *prefix, struct hash_table *tzentries, + struct zoneinfo *info); +void shut_down(int code); + + +int main(int argc, char **argv) +{ + int opt, r = 0; + char *alt_config = NULL, *version = NULL; + enum { REBUILD, NONE } op = NONE; + + if ((geteuid()) == 0 && (become_cyrus() != 0)) { + fatal("must run as the Cyrus user", EC_USAGE); + } + + while ((opt = getopt(argc, argv, "C:r:v")) != EOF) { + switch (opt) { + case 'C': /* alt config file */ + alt_config = optarg; + break; + + case 'r': + if (op == NONE) { + op = REBUILD; + version = optarg; + } + else usage(); + break; + + case 'v': + verbose = 1; + break; + + default: + usage(); + } + } + + cyrus_init(alt_config, "ctl_zoneinfo", 0); + + signals_set_shutdown(&shut_down); + signals_add_handlers(0); + + switch (op) { + case REBUILD: { + struct hash_table tzentries; + struct zoneinfo *zi; + struct txn *tid = NULL; + char prefix[2048]; + + construct_hash_table(&tzentries, 500, 1); + + /* Add INFO record (overall lastmod and TZ DB source version) */ + zi = xzmalloc(sizeof(struct zoneinfo)); + zi->type = ZI_INFO; + appendstrlist(&zi->data, version); + hash_insert(INFO_TZID, zi, &tzentries); + + snprintf(prefix, sizeof(prefix), "%s%s", config_dir, FNAME_ZONEINFODIR); + + do_zonedir(prefix, &tzentries, zi); + + zoneinfo_open(NULL); + + hash_enumerate(&tzentries, &store_zoneinfo, &tid); + + zoneinfo_close(tid); + + free_hash_table(&tzentries, &free_zoneinfo); + break; + } + + case NONE: + r = 2; + usage(); + break; + } + + cyrus_done(); + + return r; +} + + +void usage(void) +{ + fprintf(stderr, + "usage: zoneinfo_reconstruct [-C <alt_config>] [-v]" + " -r <version-string>\n"); + exit(EC_USAGE); +} + + +/* Add all ZONEs and LINKs in the given directory to the hash table */ +void do_zonedir(const char *dir, struct hash_table *tzentries, + struct zoneinfo *info) +{ + DIR *dirp; + struct dirent *dirent; + + signals_poll(); + + if (verbose) printf("Rebuilding %s\n", dir); + + dirp = opendir(dir); + if (!dirp) { + fprintf(stderr, "can't open zoneinfo directory %s\n", dir); + } + + while ((dirent = readdir(dirp))) { + char path[2048], *tzid; + int plen; + struct stat sbuf; + struct zoneinfo *zi; + + if (*dirent->d_name == '.') continue; + + plen = snprintf(path, sizeof(path), "%s/%s", dir, dirent->d_name); + lstat(path, &sbuf); + + if (S_ISDIR(sbuf.st_mode)) { + /* Path is a directory (region) */
View file
cyrus-imapd-2.5.tar.gz/imap/cyr_dbtool.c
Changed
@@ -63,11 +63,14 @@ #include "global.h" #include "mailbox.h" #include "util.h" +#include "retry.h" #include "xmalloc.h" #define STACKSIZE 64000 static char stack[STACKSIZE+1]; +int outfd; + static struct db *db = NULL; static int read_key_value(char **keyptr, size_t *keylen, char **valptr, size_t *vallen) { @@ -108,7 +111,16 @@ const char *key, size_t keylen, const char *data, size_t datalen) { - printf("%.*s\t%.*s\n", (int)keylen, key, (int)datalen, data); + struct iovec io[4]; + io[0].iov_base = (char *)key; + io[0].iov_len = keylen; + io[1].iov_base = "\t"; + io[1].iov_len = 1; + io[2].iov_base = (char *)data; + io[2].iov_len = datalen; + io[3].iov_base = "\n"; + io[3].iov_len = 1; + retry_writev(outfd, io, 4); return 0; } @@ -294,6 +306,8 @@ exit(EC_OSERR); } + outfd = fileno(stdout); + cyrus_init(alt_config, "cyr_dbtool", 0, 0); r = cyrusdb_open(argv[optind+1], fname, db_flags, &db);
View file
cyrus-imapd-2.5.tar.gz/imap/cyr_expire.c
Changed
@@ -58,6 +58,7 @@ #include "annotate.h" #include "duplicate.h" #include "exitcodes.h" +#include "imap_err.h" #include "global.h" #include "hash.h" #include "imap_err.h"
View file
cyrus-imapd-2.5.tar.gz/imap/dav_db.c
Changed
@@ -102,32 +102,9 @@ } -/* Create filename corresponding to userid's DAV DB */ -EXPORTED void dav_getpath(struct buf *fname, const char *userid) +static void dav_debug(void *fname, const char *sql) { - char c, *domain; - - buf_reset(fname); - if (config_virtdomains && (domain = strchr(userid, '@'))) { - char d = (char) dir_hash_c(domain+1, config_fulldirhash); - *domain = '\0'; /* split user@domain */ - c = (char) dir_hash_c(userid, config_fulldirhash); - buf_printf(fname, "%s%s%c/%s%s%c/%s%s", config_dir, FNAME_DOMAINDIR, d, - domain+1, FNAME_USERDIR, c, userid, FNAME_DAVSUFFIX); - *domain = '@'; /* reassemble user@domain */ - } - else { - c = (char) dir_hash_c(userid, config_fulldirhash); - buf_printf(fname, "%s%s%c/%s%s", config_dir, FNAME_USERDIR, c, userid, - FNAME_DAVSUFFIX); - } -} - - -static void dav_debug(void *userid, const char *sql) -{ - syslog(LOG_DEBUG, "dav_exec(%s%s): %s", - (const char *) userid, FNAME_DAVSUFFIX, sql); + syslog(LOG_DEBUG, "dav_exec(%s): %s", (const char *) fname, sql); } static void free_dav_open(struct open_davdb *open) @@ -136,19 +113,15 @@ free(open); } - -/* Open DAV DB corresponding to userid */ -EXPORTED sqlite3 *dav_open(const char *userid, const char *cmds) +/* Open DAV DB corresponding in file */ +EXPORTED sqlite3 *dav_open(const char *fname, const char *cmds) { int rc = SQLITE_OK; - struct buf fname = BUF_INITIALIZER; struct stat sbuf; struct open_davdb *open; - dav_getpath(&fname, userid); - for (open = open_davdbs; open; open = open->next) { - if (!strcmp(open->path, buf_cstring(&fname))) { + if (!strcmp(open->path, fname)) { /* already open! */ open->refcount++; goto docmds; @@ -156,7 +129,7 @@ } open = xzmalloc(sizeof(struct open_davdb)); - open->path = buf_release(&fname); + open->path = xstrdup(fname); rc = stat(open->path, &sbuf); if (rc == -1 && errno == ENOENT) { @@ -180,7 +153,7 @@ #if SQLITE_VERSION_NUMBER >= 3006000 sqlite3_extended_result_codes(open->db, 1); #endif - sqlite3_trace(open->db, dav_debug, (void *) userid); + sqlite3_trace(open->db, dav_debug, open->path); } /* stitch on up */ @@ -188,7 +161,7 @@ open->next = open_davdbs; open_davdbs = open; -docmds: + docmds: if (cmds) { rc = sqlite3_exec(open->db, cmds, NULL, NULL, NULL); if (rc != SQLITE_OK) { @@ -198,8 +171,6 @@ } } - buf_free(&fname); - return open->db; } @@ -207,7 +178,7 @@ /* Close DAV DB */ EXPORTED int dav_close(sqlite3 *davdb) { - int rc, r = 0;; + int rc, r = 0; struct open_davdb *open, *prev = NULL; if (!davdb) return 0; @@ -292,12 +263,12 @@ } -EXPORTED int dav_delete(const char *userid) +EXPORTED int dav_delete(struct mailbox *mailbox) { struct buf fname = BUF_INITIALIZER; int r = 0; - dav_getpath(&fname, userid); + dav_getpath(&fname, mailbox); if (unlink(buf_cstring(&fname)) && errno != ENOENT) { syslog(LOG_ERR, "dav_db: error unlinking %s: %m", buf_cstring(&fname)); r = CYRUSDB_INTERNAL;
View file
cyrus-imapd-2.5.tar.gz/imap/dav_db.h
Changed
@@ -45,8 +45,7 @@ #define DAV_DB_H #include <sqlite3.h> - -#include "util.h" +#include "dav_util.h" struct dav_data { unsigned rowid; @@ -75,10 +74,8 @@ /* done with all DAV operations for this process */ int dav_done(void); -void dav_getpath(struct buf *buf, const char *userid); - -/* get a database handle corresponding to userid */ -sqlite3 *dav_open(const char *userid, const char *cmds); +/* get a database handle corresponding to mailbox */ +sqlite3 *dav_open(const char *fname, const char *cmds); /* close this handle */ int dav_close(sqlite3 *davdb); @@ -89,7 +86,7 @@ int (*cb)(sqlite3_stmt *stmt, void *rock), void *rock, sqlite3_stmt **stmt); -/* delete database corresponding to userid */ -int dav_delete(const char *userid); +/* delete database corresponding to mailbox */ +int dav_delete(struct mailbox *mailbox); #endif /* DAV_DB_H */
View file
cyrus-imapd-2.5.tar.gz/imap/dav_reconstruct.c
Changed
@@ -68,6 +68,7 @@ #include "mboxlist.h" #include "util.h" #include "xmalloc.h" +#include "xstrlcat.h" extern int optind; extern char *optarg; @@ -140,7 +141,7 @@ /* remove existing database entirely */ /* XXX - build a new file and rename into place? */ - dav_getpath(&fnamebuf, userid); + dav_getpath_byuserid(&fnamebuf, userid); if (buf_len(&fnamebuf)) unlink(buf_cstring(&fnamebuf));
View file
cyrus-imapd-2.5.tar.gz/imap/dav_util.c
Added
@@ -0,0 +1,84 @@ +/* dav_util.c -- utility functions for dealing with DAV database + * + * Copyright (c) 1994-2014 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Carnegie Mellon University + * Center for Technology Transfer and Enterprise Creation + * 4615 Forbes Avenue + * Suite 302 + * Pittsburgh, PA 15213 + * (412) 268-7393, fax: (412) 268-7395 + * innovation@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include <config.h> + +#include <string.h> + +#include "dav_util.h" +#include "global.h" +#include "mailbox.h" +#include "mboxname.h" +#include "util.h" + +/* Create filename corresponding to DAV DB for mailbox */ +EXPORTED void dav_getpath(struct buf *fname, struct mailbox *mailbox) +{ + const char *userid; + + userid = mboxname_to_userid(mailbox->name); + + if (userid) dav_getpath_byuserid(fname, userid); + else buf_setcstr(fname, mailbox_meta_fname(mailbox, META_DAV)); +} + +/* Create filename corresponding to DAV DB for userid */ +EXPORTED void dav_getpath_byuserid(struct buf *fname, const char *userid) +{ + char c, *domain; + + buf_reset(fname); + if (config_virtdomains && (domain = strchr(userid, '@'))) { + char d = (char) dir_hash_c(domain+1, config_fulldirhash); + *domain = '\0'; /* split user@domain */ + c = (char) dir_hash_c(userid, config_fulldirhash); + buf_printf(fname, "%s%s%c/%s%s%c/%s%s", config_dir, FNAME_DOMAINDIR, d, + domain+1, FNAME_USERDIR, c, userid, FNAME_DAVSUFFIX); + *domain = '@'; /* reassemble user@domain */ + } + else { + c = (char) dir_hash_c(userid, config_fulldirhash); + buf_printf(fname, "%s%s%c/%s%s", config_dir, FNAME_USERDIR, c, userid, + FNAME_DAVSUFFIX); + } +}
View file
cyrus-imapd-2.5.tar.gz/imap/dav_util.h
Added
@@ -0,0 +1,58 @@ +/* dav_util.h -- utility functions for dealing with DAV database + * + * Copyright (c) 1994-2014 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Carnegie Mellon University + * Center for Technology Transfer and Enterprise Creation + * 4615 Forbes Avenue + * Suite 302 + * Pittsburgh, PA 15213 + * (412) 268-7393, fax: (412) 268-7395 + * innovation@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifndef DAV_UTIL_H +#define DAV_UTIL_H + +#include "mailbox.h" +#include "util.h" + +#define FNAME_DAVSUFFIX ".dav" /* per-user DAV DB extension */ + +/* Create filename corresponding to DAV DB for mailbox */ +void dav_getpath(struct buf *fname, struct mailbox *mailbox); + +/* Create filename corresponding to DAV DB for userid */ +void dav_getpath_byuserid(struct buf *fname, const char *userid); + +#endif /* DAV_UTIL_H */
View file
cyrus-imapd-2.5.tar.gz/imap/dlist.c
Changed
@@ -591,7 +591,10 @@ printfile(out, dl); break; case DL_BUF: - prot_printliteral(out, dl->sval, dl->nval); + if (strlen(dl->sval) == dl->nval) + prot_printastring(out, dl->sval); + else + prot_printliteral(out, dl->sval, dl->nval); break; case DL_GUID: prot_printf(out, "%s", message_guid_encode(dl->gval)); @@ -644,6 +647,191 @@ *dlp = NULL; } +struct dlistsax_state { + const char *base; + const char *p; + const char *end; + dlistsax_cb_t *proc; + int depth; + struct dlistsax_data d; + struct buf gbuf; +}; + +static int _parseqstring(struct dlistsax_state *s, struct buf *buf) +{ + buf->len = 0; + + /* get over the first quote */ + if (*s->p++ != '"') return IMAP_INVALID_IDENTIFIER; + + while (s->p < s->end) { + /* found the end quote */ + if (*s->p == '"') { + s->p++; + return 0; + } + /* backslash just quotes the next char, no matter what it is */ + if (*s->p == '\\') { + s->p++; + if (s->p == s->end) break; + /* fall through */ + } + + buf_putc(buf, *s->p++); + } + + return IMAP_INVALID_IDENTIFIER; +} + +static int _parseliteral(struct dlistsax_state *s, struct buf *buf) +{ + size_t len = 0; + + if (*s->p++ != '{') return IMAP_INVALID_IDENTIFIER; + + while (s->p < s->end) { + if (cyrus_isdigit(*s->p)) { + len = (len * 10) + (*s->p++ - '0'); + } + else if (*s->p == '}') { + if (s->p + 3 + len >= s->end) break; + if (s->p[1] != '\r') break; + if (s->p[2] != '\n') break; + buf_setmap(buf, s->p+3, len); + s->p += len = 3; + return 0; + } + } + + return IMAP_INVALID_IDENTIFIER; +} + +static int _parseitem(struct dlistsax_state *s, struct buf *buf) +{ + const char *sp; + if (*s->p == '"') + return _parseqstring(s, buf); + else if (*s->p == '{') + return _parseliteral(s, buf); + + sp = memchr(s->p, ' ', s->end - s->p); + if (!sp) sp = s->end; + while (sp[-1] == ')' && sp > s->p) sp--; + /* this is much faster because it doesn't do a reset and check the MMAP flag */ + buf->len = 0; + buf_appendmap(buf, s->p, sp - s->p); + s->p = sp; + return 0; /* this could be the last thing, so end is OK */ +} + +static int _parsesax(struct dlistsax_state *s, int parsekey) +{ + int r = 0; + + s->depth++; + + /* handle the key if wanted */ + if (parsekey) { + r = _parseitem(s, &s->d.kbuf); + if (r) return r; + if (s->p >= s->end) return IMAP_INVALID_IDENTIFIER; + if (*s->p == ' ') s->p++; + else return IMAP_INVALID_IDENTIFIER; + } + else { + s->d.kbuf.len = 0; + } + + if (s->p >= s->end) return IMAP_INVALID_IDENTIFIER; + + /* check what sort of value we have */ + if (*s->p == '(') { + r = s->proc(DLISTSAX_LISTSTART, &s->d); + if (r) return r; + + s->p++; + if (s->p >= s->end) return IMAP_INVALID_IDENTIFIER; + + while (*s->p != ')') { + r = _parsesax(s, 0); + if (r) return r; + if (*s->p == ')') break; + if (*s->p == ' ') s->p++; + else return IMAP_INVALID_IDENTIFIER; + if (s->p >= s->end) return IMAP_INVALID_IDENTIFIER; + } + + r = s->proc(DLISTSAX_LISTEND, &s->d); + if (r) return r; + + s->p++; + } + else if (*s->p == '%') { + s->p++; + if (s->p >= s->end) return IMAP_INVALID_IDENTIFIER; + /* no whitespace allowed here */ + if (*s->p == '(') { + r = s->proc(DLISTSAX_KVLISTSTART, &s->d); + if (r) return r; + + s->p++; + if (s->p >= s->end) return IMAP_INVALID_IDENTIFIER; + + while (*s->p != ')') { + r = _parsesax(s, 1); + if (r) return r; + if (*s->p == ')') break; + if (*s->p == ' ') s->p++; + else return IMAP_INVALID_IDENTIFIER; + if (s->p >= s->end) return IMAP_INVALID_IDENTIFIER; + } + + r = s->proc(DLISTSAX_KVLISTEND, &s->d); + if (r) return r; + + s->p++; + } + else { + /* unknown percent type */ + return IMAP_INVALID_IDENTIFIER; + } + } + else { + r = _parseitem(s, &s->d.buf); + if (r) return r; + + r = s->proc(DLISTSAX_STRING, &s->d); + if (r) return r; + } + + s->depth--; + + /* success */ + return 0; +} + +EXPORTED int dlist_parsesax(const char *base, size_t len, int parsekey, + dlistsax_cb_t *proc, void *rock) +{ + static struct dlistsax_state state; + int r; + + state.base = base; + state.p = base; + state.end = base + len; + state.proc = proc; + state.d.rock = rock; + + r = _parsesax(&state, parsekey); + + if (r) return r; + + if (state.p < state.end) + return IMAP_IOERROR; + + return 0; +}
View file
cyrus-imapd-2.5.tar.gz/imap/dlist.h
Changed
@@ -51,6 +51,25 @@ #include "mailbox.h" #include "message_guid.h" +enum dlistsax_t { + DLISTSAX_LISTSTART, + DLISTSAX_LISTEND, + DLISTSAX_KVLISTSTART, + DLISTSAX_KVLISTEND, + DLISTSAX_RESERVE, + DLISTSAX_LITERAL, + DLISTSAX_FLAG, + DLISTSAX_STRING, + /* error callbacks */ + DLISTSAX_ERROR +}; + +struct dlistsax_data { + struct buf kbuf; + struct buf buf; + void *rock; +}; + enum dlist_t { DL_NIL = 0, DL_ATOM, @@ -203,6 +222,11 @@ int dlist_parsemap(struct dlist **dlp, int parsekeys, const char *base, unsigned len); +typedef int dlistsax_cb_t(int type, struct dlistsax_data *data); + +int dlist_parsesax(const char *base, size_t len, int parsekey, + dlistsax_cb_t *proc, void *rock); + void dlist_stitch(struct dlist *parent, struct dlist *child); void dlist_unstitch(struct dlist *parent, struct dlist *child); struct dlist *dlist_splice(struct dlist *parent, int num);
View file
cyrus-imapd-2.5.tar.gz/imap/global.c
Changed
@@ -100,6 +100,7 @@ EXPORTED const char *config_ptscache_db; EXPORTED const char *config_statuscache_db; HIDDEN const char *config_userdeny_db; +EXPORTED const char *config_zoneinfo_db; EXPORTED const char *config_conversations_db; EXPORTED int charset_flags; @@ -264,6 +265,7 @@ config_ptscache_db = config_getstring(IMAPOPT_PTSCACHE_DB); config_statuscache_db = config_getstring(IMAPOPT_STATUSCACHE_DB); config_userdeny_db = config_getstring(IMAPOPT_USERDENY_DB); + config_zoneinfo_db = config_getstring(IMAPOPT_ZONEINFO_DB); config_conversations_db = config_getstring(IMAPOPT_CONVERSATIONS_DB); /* configure libcyrus as needed */
View file
cyrus-imapd-2.5.tar.gz/imap/global.h
Changed
@@ -146,6 +146,7 @@ extern const char *config_ptscache_db; extern const char *config_statuscache_db; extern const char *config_userdeny_db; +extern const char *config_zoneinfo_db; extern const char *config_conversations_db; extern int charset_flags;
View file
cyrus-imapd-2.5.tar.gz/imap/http_caldav.c
Changed
@@ -81,6 +81,7 @@ #include "xcal.h" #include "mailbox.h" #include "mboxlist.h" +#include "md5.h" #include "message.h" #include "message_guid.h" #include "proxy.h" @@ -113,9 +114,12 @@ struct busytime busytime; /* array of found busytime periods */ }; +static unsigned config_allowsched = IMAP_ENUM_CALDAV_ALLOWSCHEDULING_OFF; static struct caldav_db *auth_caldavdb = NULL; static time_t compile_time; +static struct caldav_db *my_caldav_open(struct mailbox *mailbox); +static void my_caldav_close(struct caldav_db *caldavdb); static void my_caldav_init(struct buf *serverinfo); static void my_caldav_auth(const char *userid); static void my_caldav_reset(void); @@ -131,6 +135,7 @@ static int caldav_copy(struct transaction_t *txn, struct mailbox *src_mbox, struct index_record *src_rec, struct mailbox *dest_mbox, const char *dest_rsrc, + struct caldav_db *dest_davdb, unsigned overwrite, unsigned flags); static int caldav_delete_sched(struct transaction_t *txn, struct mailbox *mailbox, @@ -139,7 +144,9 @@ static int caldav_post(struct transaction_t *txn); static int caldav_put(struct transaction_t *txn, struct mime_type_t *mime, - struct mailbox *mailbox, unsigned flags); + struct mailbox *mailbox, + struct caldav_db *caldavdb, + unsigned flags); static int propfind_getcontenttype(const xmlChar *name, xmlNsPtr ns, struct propfind_ctx *fctx, xmlNodePtr resp, @@ -171,9 +178,15 @@ static int proppatch_caltransp(xmlNodePtr prop, unsigned set, struct proppatch_ctx *pctx, struct propstat propstat[], void *rock); +static int propfind_tz_avail(const xmlChar *name, xmlNsPtr ns, + struct propfind_ctx *fctx, xmlNodePtr resp, + struct propstat propstat[], void *rock); static int proppatch_timezone(xmlNodePtr prop, unsigned set, struct proppatch_ctx *pctx, struct propstat propstat[], void *rock); +static int proppatch_availability(xmlNodePtr prop, unsigned set, + struct proppatch_ctx *pctx, + struct propstat propstat[], void *rock); static int report_cal_query(struct transaction_t *txn, xmlNodePtr inroot, struct propfind_ctx *fctx); @@ -199,23 +212,23 @@ static struct mime_type_t caldav_mime_types[] = { /* First item MUST be the default type and storage format */ { "text/calendar; charset=utf-8", "2.0", "ics", "ifb", - (const char* (*)(void *)) &icalcomponent_as_ical_string, + (char* (*)(void *)) &icalcomponent_as_ical_string_r, (void * (*)(const char*)) &icalparser_parse_string, - &begin_icalendar, &end_icalendar + (void (*)(void *)) &icalcomponent_free, &begin_icalendar, &end_icalendar }, { "application/calendar+xml; charset=utf-8", NULL, "xcs", "xfb", - (const char* (*)(void *)) &icalcomponent_as_xcal_string, + (char* (*)(void *)) &icalcomponent_as_xcal_string, (void * (*)(const char*)) &xcal_string_as_icalcomponent, - &begin_xcal, &end_xcal + NULL, &begin_xcal, &end_xcal }, #ifdef WITH_JSON { "application/calendar+json; charset=utf-8", NULL, "jcs", "jfb", - (const char* (*)(void *)) &icalcomponent_as_jcal_string, + (char* (*)(void *)) &icalcomponent_as_jcal_string, (void * (*)(const char*)) &jcal_string_as_icalcomponent, - &begin_jcal, &end_jcal + NULL, &begin_jcal, &end_jcal }, #endif - { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } }; /* Array of known "live" properties */ @@ -293,8 +306,9 @@ propfind_caldata, NULL, NULL }, { "calendar-description", NS_CALDAV, PROP_COLLECTION, propfind_fromdb, proppatch_todb, NULL }, - { "calendar-timezone", NS_CALDAV, PROP_COLLECTION, - propfind_fromdb, proppatch_timezone, NULL }, + { "calendar-timezone", NS_CALDAV, + PROP_COLLECTION | PROP_PRESCREEN | PROP_NEEDPROP, + propfind_tz_avail, proppatch_timezone, NULL }, { "supported-calendar-component-set", NS_CALDAV, PROP_COLLECTION, propfind_calcompset, proppatch_calcompset, NULL }, { "supported-calendar-data", NS_CALDAV, PROP_COLLECTION, @@ -313,6 +327,11 @@ { "schedule-calendar-transp", NS_CALDAV, PROP_COLLECTION, propfind_caltransp, proppatch_caltransp, NULL }, + /* Calendar Availability (draft-daboo-calendar-availability) properties */ + { "calendar-availability", NS_CALDAV, + PROP_COLLECTION | PROP_PRESCREEN | PROP_NEEDPROP, + propfind_tz_avail, proppatch_availability, NULL }, + /* Apple Calendar Server properties */ { "getctag", NS_CS, PROP_ALLPROP | PROP_COLLECTION, propfind_sync_token, NULL, NULL }, @@ -325,18 +344,19 @@ caldav_mime_types, &caldav_parse_path, &caldav_check_precond, - { (void **) &auth_caldavdb, + { (db_open_proc_t) &my_caldav_open, + (db_close_proc_t) &my_caldav_close, (db_lookup_proc_t) &caldav_lookup_resource, (db_foreach_proc_t) &caldav_foreach, (db_write_proc_t) &caldav_write, (db_delete_proc_t) &caldav_delete, (db_delmbox_proc_t) &caldav_delmbox }, &caldav_acl, - &caldav_copy, + (copy_proc_t) &caldav_copy, &caldav_delete_sched, { MBTYPE_CALENDAR, "mkcalendar", "mkcalendar-response", NS_CALDAV }, &caldav_post, - { CALDAV_SUPP_DATA, &caldav_put }, + { CALDAV_SUPP_DATA, (put_proc_t) &caldav_put }, caldav_props, { { "calendar-query", &report_cal_query, DACL_READ, REPORT_NEED_MBOX | REPORT_MULTISTATUS }, @@ -354,6 +374,9 @@ struct namespace_t namespace_calendar = { URL_NS_CALENDAR, 0, "/dav/calendars", "/.well-known/caldav", 1 /* auth */, (ALLOW_READ | ALLOW_POST | ALLOW_WRITE | ALLOW_DELETE | +#ifdef HAVE_VAVAILABILITY + ALLOW_CAL_AVAIL | +#endif ALLOW_DAV | ALLOW_WRITECOL | ALLOW_CAL ), &my_caldav_init, &my_caldav_auth, my_caldav_reset, &my_caldav_shutdown, { @@ -378,6 +401,23 @@ }; +static struct caldav_db *my_caldav_open(struct mailbox *mailbox) +{ + if (httpd_userid && mboxname_userownsmailbox(httpd_userid, mailbox->name)) { + return auth_caldavdb; + } + else { + return caldav_open_mailbox(mailbox, CALDAV_CREATE); + } +} + + +static void my_caldav_close(struct caldav_db *caldavdb) +{ + if (caldavdb && (caldavdb != auth_caldavdb)) caldav_close(caldavdb); +} + + static void my_caldav_init(struct buf *serverinfo) { namespace_calendar.enabled = @@ -398,7 +438,8 @@ #endif } - if (config_getswitch(IMAPOPT_CALDAV_ALLOWSCHEDULING)) { + config_allowsched = config_getenum(IMAPOPT_CALDAV_ALLOWSCHEDULING); + if (config_allowsched) { namespace_calendar.allow |= ALLOW_CAL_SCHED; /* Need to set this to parse CalDAV Scheduling parameters */ @@ -414,6 +455,9 @@ const char *mailboxname; int r; + /* Generate mailboxname of calendar-home-set */ + mailboxname = caldav_mboxname(userid, NULL); + if (httpd_userisadmin || global_authisa(httpd_authstate, IMAPOPT_PROXYSERVERS)) { /* admin or proxy from frontend - won't have DAV database */ @@ -425,14 +469,13 @@ else { /* Open CalDAV DB for 'userid' */ my_caldav_reset(); - auth_caldavdb = caldav_open(userid, CALDAV_CREATE); + auth_caldavdb = caldav_open_userid(userid, CALDAV_CREATE); if (!auth_caldavdb) fatal("Unable to open CalDAV DB", EC_IOERR); } /* Auto-provision calendars for 'userid' */ /* calendar-home-set */
View file
cyrus-imapd-2.5.tar.gz/imap/http_carddav.c
Changed
@@ -85,6 +85,8 @@ static struct carddav_db *auth_carddavdb = NULL; +static struct carddav_db *my_carddav_open(struct mailbox *mailbox); +static void my_carddav_close(struct carddav_db *carddavdb); static void my_carddav_init(struct buf *serverinfo); static void my_carddav_auth(const char *userid); static void my_carddav_reset(void); @@ -96,10 +98,13 @@ static int carddav_copy(struct transaction_t *txn, struct mailbox *src_mbox, struct index_record *src_rec, struct mailbox *dest_mbox, const char *dest_rsrc, + struct carddav_db *dest_davdb, unsigned overwrite, unsigned flags); static int carddav_put(struct transaction_t *txn, struct mime_type_t *mime, - struct mailbox *mailbox, unsigned flags); + struct mailbox *mailbox, + struct carddav_db *carddavdb, + unsigned flags); static VObject *vcard_string_as_vobject(const char *str) { return Parse_MIME(str, strlen(str)); @@ -135,9 +140,9 @@ /* First item MUST be the default type and storage format */ { "text/vcard; charset=utf-8", "3.0", NULL, "vcf", NULL, (void * (*)(const char*)) &vcard_string_as_vobject, - NULL, NULL + (void (*)(void *)) &cleanVObject, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } }; /* Array of known "live" properties */ @@ -230,18 +235,19 @@ carddav_mime_types, &carddav_parse_path, &check_precond, - { (void **) &auth_carddavdb, + { (db_open_proc_t) &my_carddav_open, + (db_close_proc_t) &my_carddav_close, (db_lookup_proc_t) &carddav_lookup_resource, (db_foreach_proc_t) &carddav_foreach, (db_write_proc_t) &carddav_write, (db_delete_proc_t) &carddav_delete, (db_delmbox_proc_t) &carddav_delmbox }, NULL, /* No ACL extensions */ - &carddav_copy, + (copy_proc_t) &carddav_copy, NULL, /* No special DELETE handling */ { MBTYPE_ADDRESSBOOK, NULL, NULL, 0 }, /* No special MK* method */ NULL, /* No special POST handling */ - { CARDDAV_SUPP_DATA, &carddav_put }, + { CARDDAV_SUPP_DATA, (put_proc_t) &carddav_put }, carddav_props, { { "addressbook-query", &report_card_query, DACL_READ, REPORT_NEED_MBOX | REPORT_MULTISTATUS }, @@ -291,12 +297,25 @@ }; -static struct namespace carddav_namespace; +static struct carddav_db *my_carddav_open(struct mailbox *mailbox) +{ + if (httpd_userid && mboxname_userownsmailbox(httpd_userid, mailbox->name)) { + return auth_carddavdb; + } + else { + return carddav_open_mailbox(mailbox, CALDAV_CREATE); + } +} -static void my_carddav_init(struct buf *serverinfo) + +static void my_carddav_close(struct carddav_db *carddavdb) { - int r; + if (carddavdb && (carddavdb != auth_carddavdb)) carddav_close(carddavdb); +} + +static void my_carddav_init(struct buf *serverinfo) +{ namespace_addressbook.enabled = config_httpmodules & IMAP_ENUM_HTTPMODULES_CARDDAV; @@ -306,12 +325,6 @@ fatal("Required 'addressbookprefix' option is not set", EC_CONFIG); } - /* Set namespace -- force standard (internal) */ - if ((r = mboxname_init_namespace(&carddav_namespace, 1))) { - syslog(LOG_ERR, "%s", error_message(r)); - fatal(error_message(r), EC_CONFIG); - } - carddav_init(); if (config_serverinfo == IMAP_ENUM_SERVERINFO_ON && @@ -329,6 +342,8 @@ struct buf boxbuf = BUF_INITIALIZER; const char *mailboxname; + mailboxname = mboxname_user_mbox(userid, NULL); + if (httpd_userisadmin || global_authisa(httpd_authstate, IMAPOPT_PROXYSERVERS)) { /* admin or proxy from frontend - won't have DAV database */ @@ -340,7 +355,7 @@ else { /* Open CardDAV DB for 'userid' */ my_carddav_reset(); - auth_carddavdb = carddav_open(userid, CARDDAV_CREATE); + auth_carddavdb = carddav_open_userid(userid, CARDDAV_CREATE); if (!auth_carddavdb) fatal("Unable to open CardDAV DB", EC_IOERR); } @@ -541,6 +556,7 @@ static int carddav_copy(struct transaction_t *txn, struct mailbox *src_mbox, struct index_record *src_rec, struct mailbox *dest_mbox, const char *dest_rsrc, + struct carddav_db *dest_davdb, unsigned overwrite, unsigned flags) { int r; @@ -563,8 +579,8 @@ mailbox_unlock_index(src_mbox, NULL); /* Store source resource at destination */ - r = store_resource(txn, vcard, dest_mbox, dest_rsrc, auth_carddavdb, - overwrite, flags); + r = store_resource(txn, vcard, dest_mbox, dest_rsrc, dest_davdb, + overwrite, flags); cleanVObject(vcard); cleanStrTbl(); @@ -582,7 +598,9 @@ */ static int carddav_put(struct transaction_t *txn, struct mime_type_t *mime, - struct mailbox *mailbox, unsigned flags) + struct mailbox *mailbox, + struct carddav_db *davdb, + unsigned flags) { int ret; VObject *vcard = NULL; @@ -597,7 +615,7 @@ /* Store resource at target */ ret = store_resource(txn, vcard, mailbox, txn->req_tgt.resource, - auth_carddavdb, OVERWRITE_CHECK, flags); + davdb, OVERWRITE_CHECK, flags); if (flags & PREFER_REP) { struct resp_body_t *resp_body = &txn->resp_body; @@ -718,90 +736,30 @@ } -/* Callback to fetch CARDDAV:address-data */ +/* Callback to prescreen/fetch CARDDAV:address-data */ static int propfind_addrdata(const xmlChar *name, xmlNsPtr ns, struct propfind_ctx *fctx, - xmlNodePtr resp, + xmlNodePtr resp __attribute__((unused)), struct propstat propstat[], void *rock) { xmlNodePtr prop = (xmlNodePtr) rock; - xmlChar *attr; - const char *data; - unsigned long datalen; - xmlNodePtr node; - - if (!resp || !propstat) { - /* Prescreen address-data "property" request */ - unsigned allowed = 1; - - if ((attr = xmlGetProp(prop, BAD_CAST "content-type"))) { - struct mime_type_t *mime; - - /* Check requested MIME type */ - for (mime = carddav_mime_types; mime->content_type; mime++) { - if (is_mediatype((const char *) attr, mime->content_type)) { - xmlFree(attr); - - if ((attr = xmlGetProp(prop, BAD_CAST "version")) && - (!mime->version || - xmlStrcmp(attr, BAD_CAST mime->version))) { - allowed = 0; - } - break; - } - } - if (!mime->content_type) allowed = 0; + const char *data = NULL; + size_t datalen = 0;
View file
cyrus-imapd-2.5.tar.gz/imap/http_dav.c
Changed
@@ -210,7 +210,7 @@ { &meth_propfind, &princ_params }, /* PROPFIND */ { NULL, NULL }, /* PROPPATCH */ { NULL, NULL }, /* PUT */ - { &meth_report, NULL }, /* REPORT */ + { &meth_report, &princ_params }, /* REPORT */ { &meth_trace, NULL }, /* TRACE */ { NULL, NULL } /* UNLOCK */ } @@ -222,7 +222,7 @@ if (config_httpmodules & IMAP_ENUM_HTTPMODULES_CALDAV) { namespace_principal.enabled = 1; namespace_principal.allow |= ALLOW_CAL; - if (config_getswitch(IMAPOPT_CALDAV_ALLOWSCHEDULING)) + if (config_getenum(IMAPOPT_CALDAV_ALLOWSCHEDULING)) namespace_principal.allow |= ALLOW_CAL_SCHED; } if (config_httpmodules & IMAP_ENUM_HTTPMODULES_CARDDAV) { @@ -454,6 +454,29 @@ } +/* Check requested MIME type */ +struct mime_type_t *get_accept_type(const char **hdr, struct mime_type_t *types) +{ + struct mime_type_t *ret = NULL; + struct accept *e, *enc = parse_accept(hdr); + + for (e = enc; e && e->token; e++) { + if (!ret && e->qual > 0.0) { + struct mime_type_t *m; + + for (m = types; !ret && m->content_type; m++) { + if (is_mediatype(e->token, m->content_type)) ret = m; + } + } + + free(e->token); + } + if (enc) free(enc); + + return ret; +} + + static int add_privs(int rights, unsigned flags, xmlNodePtr parent, xmlNodePtr root, xmlNsPtr *ns); @@ -803,6 +826,74 @@ } +/* Helper function to prescreen/fetch resource data */ +int propfind_getdata(const xmlChar *name, xmlNsPtr ns, + struct propfind_ctx *fctx, + struct propstat propstat[], xmlNodePtr prop, + struct mime_type_t *mime_types, int precond, + const char *data, unsigned long datalen) +{ + int ret = 0; + xmlChar *type, *ver = NULL; + struct mime_type_t *mime; + + type = xmlGetProp(prop, BAD_CAST "content-type"); + if (type) ver = xmlGetProp(prop, BAD_CAST "version"); + + /* Check/find requested MIME type */ + for (mime = mime_types; type && mime->content_type; mime++) { + if (is_mediatype((const char *) type, mime->content_type)) { + if (ver && + (!mime->version || xmlStrcmp(ver, BAD_CAST mime->version))) { + continue; + } + break; + } + } + + if (!propstat) { + /* Prescreen "property" request */ + if (!mime->content_type) { + fctx->err->precond = precond; + ret = *fctx->ret = HTTP_FORBIDDEN; + } + } + else { + /* Add "property" */ + char *freeme = NULL; + + prop = xml_add_prop(HTTP_OK, fctx->ns[NS_DAV], + &propstat[PROPSTAT_OK], name, ns, NULL, 0); + + if (mime != mime_types) { + /* Not the storage format - convert into requested MIME type */ + void *obj = mime_types->from_string(data); + + data = freeme = mime->to_string(obj); + datalen = strlen(data); + mime_types->free(obj); + } + + if (type) { + xmlSetProp(prop, BAD_CAST "content-type", type); + if (ver) xmlSetProp(prop, BAD_CAST "version", ver); + } + + xmlAddChild(prop, + xmlNewCDataBlock(fctx->root->doc, BAD_CAST data, datalen)); + + fctx->fetcheddata = 1; + + if (freeme) free(freeme); + } + + if (type) xmlFree(type); + if (ver) xmlFree(ver); + + return ret; +} + + /* Callback to fetch DAV:creationdate */ int propfind_creationdate(const xmlChar *name, xmlNsPtr ns, struct propfind_ctx *fctx, @@ -811,7 +902,7 @@ void *rock __attribute__((unused))) { time_t t = 0; - struct tm *tm; + char datestr[21]; if (fctx->data) { struct dav_data *ddata = (struct dav_data *) fctx->data; @@ -828,15 +919,10 @@ if (!t) return HTTP_NOT_FOUND; - tm = gmtime(&t); - - buf_reset(&fctx->buf); - buf_printf(&fctx->buf, "%4d-%02d-%02dT%02d:%02d:%02dZ", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec); + rfc3339date_gen(datestr, sizeof(datestr), t); xml_add_prop(HTTP_OK, fctx->ns[NS_DAV], &propstat[PROPSTAT_OK], - name, ns, BAD_CAST buf_cstring(&fctx->buf), 0); + name, ns, BAD_CAST datestr, 0); return 0; } @@ -1549,8 +1635,14 @@ if (fctx->userid) { buf_reset(&fctx->buf); - buf_printf(&fctx->buf, "%s/user/%s/", - namespace_principal.prefix, fctx->userid); + if (strchr(fctx->userid, '@')) { + buf_printf(&fctx->buf, "%s/user/%s/", + namespace_principal.prefix, fctx->userid); + } + else { + buf_printf(&fctx->buf, "%s/user/%s@%s/", + namespace_principal.prefix, fctx->userid, httpd_extradomain); + } xml_add_href(node, NULL, buf_cstring(&fctx->buf)); } else { @@ -1789,7 +1881,7 @@ else if (entry->flags & PROP_PRESCREEN) { void *rock = (entry->flags & PROP_NEEDPROP) ? prop : entry->rock; - allowed = entry->get(prop->name, NULL, fctx, NULL, NULL, rock); + allowed = !entry->get(prop->name, NULL, fctx, NULL, NULL, rock); } return allowed; @@ -2008,8 +2100,8 @@ /* Check Content-Type */ if (!(hdr = spool_getheader(txn->req_hdrs, "Content-Type")) || - (!is_mediatype(hdr[0], "text/xml") && - !is_mediatype(hdr[0], "application/xml"))) { + (!is_mediatype("text/xml", hdr[0]) && + !is_mediatype("application/xml", hdr[0]))) { txn->error.desc = "This method requires an XML body\r\n"; return HTTP_BAD_MEDIATYPE; } @@ -2119,7 +2211,7 @@ /* Local Mailbox */ /* Open mailbox for writing */ - r = http_mailbox_open(txn->req_tgt.mboxname, &mailbox, LOCK_EXCLUSIVE); + r = mailbox_open_iwl(txn->req_tgt.mboxname, &mailbox); if (r) { syslog(LOG_ERR, "http_mailbox_open(%s) failed: %s", txn->req_tgt.mboxname, error_message(r)); @@ -2349,7 +2441,7 @@ done: buf_free(&acl); if (indoc) xmlFreeDoc(indoc);
View file
cyrus-imapd-2.5.tar.gz/imap/http_dav.h
Changed
@@ -151,17 +151,6 @@ schedule-send-reply, schedule-send-freebusy) */ -/* Bitmask of calendar components */ -enum { - CAL_COMP_VCALENDAR = 0xf000, - CAL_COMP_VEVENT = (1<<0), - CAL_COMP_VTODO = (1<<1), - CAL_COMP_VJOURNAL = (1<<2), - CAL_COMP_VFREEBUSY = (1<<3), - CAL_COMP_VTIMEZONE = (1<<4), - CAL_COMP_VALARM = (1<<5) -}; - /* Index into preconditions array */ enum { /* WebDAV (RFC 4918) preconditons */ @@ -241,6 +230,9 @@ #define NO_DUP_CHECK (1<<7) +typedef void *(*db_open_proc_t)(struct mailbox *mailbox); +typedef void (*db_close_proc_t)(void *davdb); + /* Function to lookup DAV 'resource' in 'mailbox', with optional 'lock', * placing the record in 'data' */ @@ -265,7 +257,7 @@ const char *int_userid; /* internal userid */ int userisadmin; /* is userid an admin */ struct auth_state *authstate; /* authorization state for userid */ - void *davdb; /* DAV DB corresponding to userid */ + void *davdb; /* DAV DB corresponding to collection */ struct mailbox *mailbox; /* mailbox correspondng to collection */ struct quota quota; /* quota info for collection */ struct index_record *record; /* cyrus.index record for resource */ @@ -275,8 +267,10 @@ int (*filter)(struct propfind_ctx *, void *data); /* callback to filter resources */ void *filter_crit; /* criteria to filter resources */ - db_lookup_proc_t lookup_resource; - db_foreach_proc_t foreach_resource; + db_open_proc_t open_db; /* open DAV DB for a given mailbox */ + db_close_proc_t close_db; /* close DAV DB for a given mailbox */ + db_lookup_proc_t lookup_resource; /* lookup a specific resource */ + db_foreach_proc_t foreach_resource; /* process all resources in a mailbox */ int (*proc_by_resource)(void *rock, /* Callback to process a resource */ void *data); struct propfind_entry_list *elist; /* List of props to fetch w/callbacks */ @@ -366,7 +360,8 @@ typedef int (*db_delmbox_proc_t)(void *davdb, const char *mailbox, int commit); struct davdb_params { - void **db; /* DAV DB to use for resources */ + db_open_proc_t open_db; /* open DAV DB for a given mailbox */ + db_close_proc_t close_db; /* close DAV DB for a given mailbox */ db_lookup_proc_t lookup_resource; /* lookup a specific resource */ db_foreach_proc_t foreach_resource; /* process all resources in a mailbox */ db_write_proc_t write_resource; /* write a specific resource */ @@ -386,6 +381,7 @@ typedef int (*copy_proc_t)(struct transaction_t *txn, struct mailbox *src_mbox, struct index_record *src_rec, struct mailbox *dest_mbox, const char *dest_rsrc, + void *dest_davdb, unsigned overwrite, unsigned flags); /* Function to do special processing for DELETE method (optional) */ @@ -398,8 +394,9 @@ const char *version; const char *file_ext; const char *file_ext2; - const char* (*to_string)(void *); + char* (*to_string)(void *); void* (*from_string)(const char *); + void (*free)(void *); const char* (*begin_stream)(struct buf *); void (*end_stream)(struct buf *); }; @@ -420,9 +417,8 @@ typedef int (*post_proc_t)(struct transaction_t *txn); /* meth_put() parameters */ -typedef int (*put_proc_t)(struct transaction_t *txn, - struct mime_type_t *mime, - struct mailbox *mailbox, unsigned flags); +typedef int (*put_proc_t)(struct transaction_t *txn, struct mime_type_t *mime, + struct mailbox *mailbox, void *davdb, unsigned flags); struct put_params { unsigned supp_data_precond; /* precond code for unsupported data */ @@ -476,6 +472,7 @@ int parse_path(struct request_target_t *tgt, const char **errstr); int target_to_mboxname(struct request_target_t *req_tgt, char *mboxname); unsigned get_preferences(struct transaction_t *txn); +struct mime_type_t *get_accept_type(const char **hdr, struct mime_type_t *types); int parse_xml_body(struct transaction_t *txn, xmlNodePtr *root); @@ -514,6 +511,11 @@ /* PROPFIND callbacks */ +int propfind_getdata(const xmlChar *name, xmlNsPtr ns, + struct propfind_ctx *fctx, + struct propstat propstat[], xmlNodePtr prop, + struct mime_type_t *mime_types, int precond, + const char *data, unsigned long datalen); int propfind_fromdb(const xmlChar *name, xmlNsPtr ns, struct propfind_ctx *fctx, xmlNodePtr resp, struct propstat propstat[], void *rock);
View file
cyrus-imapd-2.5.tar.gz/imap/http_dblookup.c
Changed
@@ -77,13 +77,13 @@ }; static int get_email(struct transaction_t *txn __attribute__((unused)), - const char *user, const char *key) + const char *userid, const char *key) { struct carddav_db *db = NULL; int ret = HTTP_NOT_FOUND; /* XXX init just incase carddav not enabled? */ - db = carddav_open(user, /*flags*/0); + db = carddav_open_userid(userid, /*flags*/0); if (!db) goto done; if (carddav_getemail(db, key)) @@ -94,7 +94,7 @@ return ret; } -static int get_group(struct transaction_t *txn, const char *user, const char *key) +static int get_group(struct transaction_t *txn, const char *userid, const char *key) { struct carddav_db *db = NULL; strarray_t *array = NULL; @@ -104,7 +104,7 @@ int i; /* XXX init just incase carddav not enabled? */ - db = carddav_open(user, /*flags*/0); + db = carddav_open_userid(userid, /*flags*/0); if (!db) goto done; array = carddav_getgroup(db, key);
View file
cyrus-imapd-2.5.tar.gz/imap/http_ischedule.c
Changed
@@ -63,6 +63,7 @@ #include "tok.h" #include "util.h" #include "xmalloc.h" +#include "xcal.h" #include "xstrlcpy.h" #include <sasl/saslutil.h> @@ -93,18 +94,23 @@ static struct mime_type_t isched_mime_types[] = { /* First item MUST be the default type and storage format */ { "text/calendar; charset=utf-8", "2.0", "ics", "ifb", - (const char* (*)(void *)) &icalcomponent_as_ical_string, + (char* (*)(void *)) &icalcomponent_as_ical_string_r, (void * (*)(const char*)) &icalparser_parse_string, - NULL, NULL + (void (*)(void *)) &icalcomponent_free, NULL, NULL + }, + { "application/calendar+xml; charset=utf-8", NULL, "xcs", "xfb", + (char* (*)(void *)) &icalcomponent_as_xcal_string, + (void * (*)(const char*)) &xcal_string_as_icalcomponent, + NULL, NULL, NULL }, #ifdef WITH_JSON { "application/calendar+json; charset=utf-8", NULL, "jcs", "jfb", - (const char* (*)(void *)) &icalcomponent_as_jcal_string, + (char* (*)(void *)) &icalcomponent_as_jcal_string, (void * (*)(const char*)) &jcal_string_as_icalcomponent, - NULL, NULL, + NULL, NULL, NULL, }, #endif - { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } }; struct namespace_t namespace_ischedule = { @@ -171,7 +177,8 @@ /* We don't handle GET on a anything other than ?action=capabilities */ if (!URI_QUERY(txn->req_uri) || strcmp(URI_QUERY(txn->req_uri), "action=capabilities")) { - return HTTP_NOT_FOUND; + txn->error.desc = "Invalid action"; + return HTTP_BAD_REQUEST; } /* Generate ETag based on compile date/time of this source file. @@ -207,6 +214,7 @@ if (txn->resp_body.lastmod > lastmod) { xmlNodePtr root, capa, node, comp, meth; xmlNsPtr ns[NUM_NAMESPACE]; + struct mime_type_t *mime; /* Start construction of our query-result */ if (!(root = init_xml_response("query-result", NS_ISCHED, NULL, ns))) { @@ -247,9 +255,22 @@ node = xmlNewChild(capa, NULL, BAD_CAST "calendar-data-types", NULL); - node = xmlNewChild(node, NULL, BAD_CAST "calendar-data-type", NULL); - xmlNewProp(node, BAD_CAST "content-type", BAD_CAST "text/calendar"); - xmlNewProp(node, BAD_CAST "version", BAD_CAST "2.0"); + for (mime = isched_mime_types; mime->content_type; mime++) { + xmlNodePtr type = xmlNewChild(node, NULL, + BAD_CAST "calendar-data-type", NULL); + + /* Trim any charset from content-type */ + buf_reset(&txn->buf); + buf_printf(&txn->buf, "%.*s", + (int) strcspn(mime->content_type, ";"), + mime->content_type); + + xmlNewProp(type, BAD_CAST "content-type", + BAD_CAST buf_cstring(&txn->buf)); + + if (mime->version) + xmlNewProp(type, BAD_CAST "version", BAD_CAST mime->version); + } node = xmlNewChild(capa, NULL, BAD_CAST "attachments", NULL); node = xmlNewChild(node, NULL, BAD_CAST "inline", NULL); @@ -302,7 +323,7 @@ /* Check Content-Type */ if ((hdr = spool_getheader(txn->req_hdrs, "Content-Type"))) { for (mime = isched_mime_types; mime->content_type; mime++) { - if (is_mediatype(hdr[0], mime->content_type)) break; + if (is_mediatype(mime->content_type, hdr[0])) break; } } if (!mime || !mime->content_type) { @@ -823,17 +844,70 @@ static int meth_get_domainkey(struct transaction_t *txn, void *params __attribute__((unused))) { - txn->flags.cc |= CC_REVALIDATE; - txn->resp_body.type = "text/plain"; + int ret = 0, r, fd = -1, precond; + const char *path; + static struct buf pathbuf = BUF_INITIALIZER; + struct stat sbuf; + const char *msg_base = NULL; + unsigned long msg_size = 0; + struct resp_body_t *resp_body = &txn->resp_body; + + /* See if file exists and get Content-Length & Last-Modified time */ + buf_setcstr(&pathbuf, config_dir); + buf_appendcstr(&pathbuf, txn->req_uri->path); + path = buf_cstring(&pathbuf); + r = stat(path, &sbuf); + if (r || !S_ISREG(sbuf.st_mode)) return HTTP_NOT_FOUND; + + /* Generate Etag */ + assert(!buf_len(&txn->buf)); + buf_printf(&txn->buf, "%ld-%ld", (long) sbuf.st_mtime, (long) sbuf.st_size); - return meth_get_doc(txn, NULL); + /* Check any preconditions, including range request */ + txn->flags.ranges = 1; + precond = check_precond(txn, NULL, buf_cstring(&txn->buf), sbuf.st_mtime); + + switch (precond) { + case HTTP_OK: + case HTTP_PARTIAL: + case HTTP_NOT_MODIFIED: + /* Fill in Content-Type, ETag, Last-Modified, and Expires */ + resp_body->type = "text/plain"; + resp_body->etag = buf_cstring(&txn->buf); + resp_body->lastmod = sbuf.st_mtime; + resp_body->maxage = 86400; /* 24 hrs */ + txn->flags.cc |= CC_MAXAGE | CC_REVALIDATE; + if (httpd_userid) txn->flags.cc |= CC_PUBLIC; + + if (precond != HTTP_NOT_MODIFIED) break; + + default: + /* We failed a precondition - don't perform the request */ + resp_body->type = NULL; + return precond; + } + + if (txn->meth == METH_GET) { + /* Open and mmap the file */ + if ((fd = open(path, O_RDONLY)) == -1) return HTTP_SERVER_ERROR; + map_refresh(fd, 1, &msg_base, &msg_size, sbuf.st_size, path, NULL); + } + + write_body(precond, txn, msg_base, sbuf.st_size); + + if (fd != -1) { + map_free(&msg_base, &msg_size); + close(fd); + } + + return ret; } static void isched_init(struct buf *serverinfo) { if (!(config_httpmodules & IMAP_ENUM_HTTPMODULES_CALDAV) || - !config_getswitch(IMAPOPT_CALDAV_ALLOWSCHEDULING)) { + !config_getenum(IMAPOPT_CALDAV_ALLOWSCHEDULING)) { /* Need CALDAV and CALDAV_SCHED in order to have ISCHEDULE */ return; }
View file
cyrus-imapd-2.5.tar.gz/imap/http_proxy.c
Changed
@@ -46,6 +46,7 @@ #ifdef HAVE_UNISTD_H #include <unistd.h> #endif +#include <assert.h> #include <ctype.h> #include <syslog.h> #include <sasl/sasl.h> @@ -628,6 +629,7 @@ if (*code < 200) return 0; /* Final response */ + if (!body) return 0; /* body will be piped */ if (!(body->flags & BODY_DISCARD)) buf_reset(&body->payload); /* Check connection persistence */ @@ -762,7 +764,7 @@ switch (resp_body->framing) { case FRAMING_LENGTH: /* Read 'len' octets */ - if (!pipe_chunk(pin, pout, resp_body->len)) { + if (resp_body->len && !pipe_chunk(pin, pout, resp_body->len)) { syslog(LOG_ERR, "prot_read() error"); *errstr = "Unable to read body data"; return HTTP_BAD_GATEWAY; @@ -851,7 +853,7 @@ int r = 0, sent_body = 0; xmlChar *uri; unsigned code; - const char *statline; + const char **hdr, *statline; hdrcache_t resp_hdrs = NULL; struct body_t resp_body; @@ -875,6 +877,9 @@ write_forwarding_hdrs(be->out, txn->req_hdrs, txn->req_line.ver, https ? "https" : "http"); spool_enum_hdrcache(txn->req_hdrs, &write_cachehdr, be->out); + if ((hdr = spool_getheader(txn->req_hdrs, "TE"))) { + for (; *hdr; hdr++) prot_printf(be->out, "TE: %s\r\n", *hdr); + } if (http_methods[txn->meth].flags & METH_NOBODY) prot_puts(be->out, "Content-Length: 0\r\n"); else if (spool_getheader(txn->req_hdrs, "Transfer-Encoding") || @@ -887,11 +892,10 @@ /* Read response(s) from backend until final response or error */ memset(&resp_body, 0, sizeof(struct body_t)); - resp_body.flags = BODY_DONE; /* Don't read body, we want to pipe it */ do { r = http_read_response(be, txn->meth, &code, &statline, - &resp_hdrs, &resp_body, &txn->error.desc); + &resp_hdrs, NULL, &txn->error.desc); if (r) break; if (code == 100) { /* Continue */ @@ -938,8 +942,11 @@ default: if (txn->meth == METH_HEAD) break; - r = pipe_resp_body(be->in, httpd_out, resp_hdrs, &resp_body, - txn->flags.ver1_0, &txn->error.desc); + if (pipe_resp_body(be->in, httpd_out, resp_hdrs, &resp_body, + txn->flags.ver1_0, &txn->error.desc)) { + /* Couldn't pipe the body and can't finish response */ + txn->flags.conn = CONN_CLOSE; + } } } @@ -956,159 +963,268 @@ * on different backends. This is handled as a GET from the source and * PUT on the destination, while obeying any Overwrite header. * - * XXX This function currently buffers the response headers and body. - * Should work on sending them to the client on-the-fly. + * For a MOVE request, we also LOCK, DELETE, and possibly UNLOCK the source. + * + * XXX This function buffers the response bodies of the LOCK & GET requests. + * The response body of the PUT request is piped to the client. */ EXPORTED int http_proxy_copy(struct backend *src_be, struct backend *dest_be, struct transaction_t *txn) { - int r = 0; + int r = 0, sent_body; unsigned code; - char *etag = NULL, *lastmod = NULL;; + char *lock = NULL; const char **hdr, *statline; hdrcache_t resp_hdrs = NULL; struct body_t resp_body; +#define write_hdr(pout, name, hdrs) \ + if ((hdr = spool_getheader(hdrs, name))) \ + for (; *hdr; hdr++) prot_printf(pout, "%s: %s\r\n", name, *hdr) + + + resp_body.payload = txn->resp_body.payload; + + if (txn->meth == METH_MOVE) { + /* + * Send a LOCK request to source backend: + * + * - Use any relevant conditional headers specified by client + */ + prot_printf(src_be->out, "LOCK %s %s\r\n" + "Host: %s\r\n" + "User-Agent: %s\r\n", + txn->req_tgt.path, HTTP_VERSION, + src_be->hostname, buf_cstring(&serverinfo)); + write_hdr(src_be->out, "If", txn->req_hdrs); + write_hdr(src_be->out, "If-Match", txn->req_hdrs); + write_hdr(src_be->out, "If-Unmodified-Since", txn->req_hdrs); + write_hdr(src_be->out, "If-Schedule-Tag-Match", txn->req_hdrs); + + assert(!buf_len(&txn->buf)); + buf_printf_markup(&txn->buf, 0, + "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"); + buf_printf_markup(&txn->buf, 0, "<D:lockinfo xmlns:D='DAV:'>"); + buf_printf_markup(&txn->buf, 1, + "<D:lockscope><D:exclusive/></D:lockscope>"); + buf_printf_markup(&txn->buf, 1, + "<D:locktype><D:write/></D:locktype>"); + buf_printf_markup(&txn->buf, 1, "<D:owner>%s</D:owner>", httpd_userid); + buf_printf_markup(&txn->buf, 0, "</D:lockinfo>"); + + prot_printf(src_be->out, + "Content-Type: application/xml; charset=utf-8\r\n" + "Content-Length: %u\r\n\r\n%s", + (unsigned)buf_len(&txn->buf), buf_cstring(&txn->buf)); + buf_reset(&txn->buf); + + prot_flush(src_be->out); + + /* Read response(s) from source backend until final response or error */ + resp_body.flags = 0; + + do { + r = http_read_response(src_be, METH_LOCK, &code, &statline, + &resp_hdrs, &resp_body, &txn->error.desc); + if (r) { + proxy_downserver(src_be); + goto done; + } + } while (code < 200); + + /* Get lock token */ + if ((hdr = spool_getheader(resp_hdrs, "Lock-Token"))) + lock = xstrdup(*hdr); + + switch (code) { + case 200: + /* Success, continue */ + break; + + case 201: + /* Created empty resource, treat as 404 (Not Found) */ + r = HTTP_NOT_FOUND; + goto delete; + + case 409: + /* Failed to create resource, treat as 404 (Not Found) */ + r = HTTP_NOT_FOUND; + goto done; + + default: + /* Send failure response to client */ + send_response(statline, resp_hdrs, &resp_body.payload, &txn->flags); + goto done; + } + } + + /* * Send a GET request to source backend to fetch body: * * - Use any relevant conditional headers specified by client + * (if not already sent in LOCK request) */ - prot_printf(src_be->out, "GET %s %s\r\n", txn->req_tgt.path, HTTP_VERSION); - prot_printf(src_be->out, "Host: %s\r\n", src_be->hostname); - prot_printf(src_be->out, "User-Agent: %s\r\n", buf_cstring(&serverinfo)); - if ((hdr = spool_getheader(txn->req_hdrs, "If"))) - prot_printf(src_be->out, "If: %s\r\n", hdr[0]); - if ((hdr = spool_getheader(txn->req_hdrs, "If-Match"))) { - for (; *hdr; hdr++) prot_printf(src_be->out, "If-Match: %s\r\n", *hdr); + prot_printf(src_be->out, "GET %s %s\r\n" + "Host: %s\r\n" + "User-Agent: %s\r\n", + txn->req_tgt.path, HTTP_VERSION, + src_be->hostname, buf_cstring(&serverinfo)); + if (txn->meth != METH_MOVE) { + write_hdr(src_be->out, "If", txn->req_hdrs); + write_hdr(src_be->out, "If-Match", txn->req_hdrs); + write_hdr(src_be->out, "If-Unmodified-Since", txn->req_hdrs); + write_hdr(src_be->out, "If-Schedule-Tag-Match", txn->req_hdrs); } - if ((hdr = spool_getheader(txn->req_hdrs, "If-Unmodified-Since")))
View file
cyrus-imapd-2.5.tar.gz/imap/http_rss.c
Changed
@@ -195,7 +195,8 @@ /* Local Mailbox */ /* Open mailbox for reading */ - if ((r = http_mailbox_open(txn->req_tgt.mboxname, &mailbox, LOCK_SHARED))) { + r = mailbox_open_irl(txn->req_tgt.mboxname, &mailbox); + if (r) { syslog(LOG_ERR, "http_mailbox_open(%s) failed: %s", txn->req_tgt.mboxname, error_message(r)); txn->error.desc = error_message(r); @@ -293,7 +294,7 @@ } } - if (mailbox) mailbox_unlock_index(mailbox, NULL); + mailbox_close(&mailbox); return ret; @@ -710,6 +711,7 @@ if (!replace && config_httpprettytelemetry) buf_appendcstr(buf, "\n"); } + /* List messages as an RSS feed */ static int list_messages(struct transaction_t *txn, struct mailbox *mailbox) {
View file
cyrus-imapd-2.5.tar.gz/imap/http_timezone.c
Added
@@ -0,0 +1,1169 @@ +/* http_timezone.c -- Routines for handling timezone service requests in httpd + * + * Copyright (c) 1994-2013 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Carnegie Mellon University + * Center for Technology Transfer and Enterprise Creation + * 4615 Forbes Avenue + * Suite 302 + * Pittsburgh, PA 15213 + * (412) 268-7393, fax: (412) 268-7395 + * innovation@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* + * TODO: + * - Implement localized names and "lang" parameter + * - Implement action=find with case-insensitive match - strncasecmp()? + */ + +#include <config.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <ctype.h> +#include <string.h> +#include <syslog.h> +#include <assert.h> + +#include "global.h" +#include "hash.h" +#include "httpd.h" +#include "http_dav.h" +#include "http_err.h" +#include "http_proxy.h" +#include "jcal.h" +#include "map.h" +#include "tok.h" +#include "strhash.h" +#include "util.h" +#include "version.h" +#include "xcal.h" +#include "xstrlcpy.h" +#include "zoneinfo_db.h" + + +#define TIMEZONE_WELLKNOWN_URI "/.well-known/timezone" + +static time_t compile_time; +static void timezone_init(struct buf *serverinfo); +static void timezone_shutdown(void); +static int meth_get(struct transaction_t *txn, void *params); +static int action_capa(struct transaction_t *txn, struct hash_table *params); +static int action_list(struct transaction_t *txn, struct hash_table *params); +static int action_get(struct transaction_t *txn, struct hash_table *params); +static int action_expand(struct transaction_t *txn, struct hash_table *params); +static int json_response(int code, struct transaction_t *txn, json_t *root, + char **resp); +static int json_error_response(struct transaction_t *txn, const char *err); + +struct observance { + const char *name; + icaltimetype onset; + int offset_from; + int offset_to; + int is_daylight; +}; + +static const struct action_t { + const char *name; + int (*proc)(struct transaction_t *txn, struct hash_table *params); +} actions[] = { + { "capabilities", &action_capa }, + { "list", &action_list }, + { "get", &action_get }, + { "expand", &action_expand }, + { "find", &action_list }, + { NULL, NULL} +}; + + +static struct mime_type_t tz_mime_types[] = { + /* First item MUST be the default type and storage format */ + { "text/calendar; charset=utf-8", "2.0", "ics", "ifb", + (char* (*)(void *)) &icalcomponent_as_ical_string_r, + NULL, NULL, NULL, NULL + }, + { "application/calendar+xml; charset=utf-8", NULL, "xcs", "xfb", + (char* (*)(void *)) &icalcomponent_as_xcal_string, + NULL, NULL, NULL, NULL + }, + { "application/calendar+json; charset=utf-8", NULL, "jcs", "jfb", + (char* (*)(void *)) &icalcomponent_as_jcal_string, + NULL, NULL, NULL, NULL + }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } +}; + + +/* Namespace for TIMEZONE feeds of mailboxes */ +struct namespace_t namespace_timezone = { + URL_NS_TIMEZONE, 0, "/timezone", TIMEZONE_WELLKNOWN_URI, 0 /* auth */, ALLOW_READ, + timezone_init, NULL, NULL, timezone_shutdown, + { + { NULL, NULL }, /* ACL */ + { NULL, NULL }, /* COPY */ + { NULL, NULL }, /* DELETE */ + { &meth_get, NULL }, /* GET */ + { &meth_get, NULL }, /* HEAD */ + { NULL, NULL }, /* LOCK */ + { NULL, NULL }, /* MKCALENDAR */ + { NULL, NULL }, /* MKCOL */ + { NULL, NULL }, /* MOVE */ + { &meth_options, NULL }, /* OPTIONS */ + { NULL, NULL }, /* POST */ + { NULL, NULL }, /* PROPFIND */ + { NULL, NULL }, /* PROPPATCH */ + { NULL, NULL }, /* PUT */ + { NULL, NULL }, /* REPORT */ + { &meth_trace, NULL }, /* TRACE */ + { NULL, NULL } /* UNLOCK */ + } +}; + + +static void timezone_init(struct buf *serverinfo) +{ + namespace_timezone.enabled = + config_httpmodules & IMAP_ENUM_HTTPMODULES_TIMEZONE; + + if (!namespace_timezone.enabled) return; + + /* Open zoneinfo db */ + if (zoneinfo_open(NULL)) { + namespace_timezone.enabled = 0; + return; + } + + if (config_serverinfo == IMAP_ENUM_SERVERINFO_ON && + !strstr(buf_cstring(serverinfo), " Jansson/")) { + buf_printf(serverinfo, " Jansson/%s", JANSSON_VERSION); + } + + compile_time = calc_compile_time(__TIME__, __DATE__); +} + + +static void timezone_shutdown(void) +{ + zoneinfo_close(NULL); +} + + +/* Perform a GET/HEAD request */ +static int meth_get(struct transaction_t *txn, + void *params __attribute__((unused))) +{ + int ret; + tok_t tok; + char *param; + struct strlist *action; + struct hash_table query_params; + const struct action_t *ap = NULL; + + /* Parse the query string and add param/value pairs to hash table */ + construct_hash_table(&query_params, 10, 1); + tok_initm(&tok, URI_QUERY(txn->req_uri), "&=", TOK_TRIMLEFT|TOK_TRIMRIGHT); + while ((param = tok_next(&tok))) { + struct strlist *vals;
View file
cyrus-imapd-2.5.tar.gz/imap/httpd.c
Changed
@@ -126,10 +126,10 @@ sasl_conn_t *httpd_saslconn; /* the sasl connection context */ -static struct mailbox *httpd_mailbox = NULL; static struct wildmat *allow_cors = NULL; int httpd_timeout, httpd_keepalive; char *httpd_userid = NULL, *proxy_userid = NULL; +char *httpd_extradomain = NULL; struct auth_state *httpd_authstate = 0; int httpd_userisadmin = 0; int httpd_userisproxyadmin = 0; @@ -149,6 +149,7 @@ unsigned long config_httpmodules; int config_httpprettytelemetry; +static time_t compile_time; struct buf serverinfo = BUF_INITIALIZER; static void digest_send_success(const char *name __attribute__((unused)), @@ -208,6 +209,7 @@ static int http_auth(const char *creds, struct transaction_t *txn); static void keep_alive(int sig); +static int meth_get(struct transaction_t *txn, void *params); static int meth_propfind_root(struct transaction_t *txn, void *params); @@ -255,8 +257,8 @@ { NULL, NULL }, /* ACL */ { NULL, NULL }, /* COPY */ { NULL, NULL }, /* DELETE */ - { &meth_get_doc, NULL }, /* GET */ - { &meth_get_doc, NULL }, /* HEAD */ + { &meth_get, NULL }, /* GET */ + { &meth_get, NULL }, /* HEAD */ { NULL, NULL }, /* LOCK */ { NULL, NULL }, /* MKCALENDAR */ { NULL, NULL }, /* MKCOL */ @@ -277,9 +279,12 @@ #ifdef WITH_DAV &namespace_principal, &namespace_calendar, + &namespace_addressbook, &namespace_ischedule, &namespace_domainkey, - &namespace_addressbook, +#ifdef WITH_JSON + &namespace_timezone, +#endif #endif #ifdef WITH_RSS &namespace_rss, @@ -316,9 +321,6 @@ backend_cached = NULL; backend_current = NULL; - if (httpd_mailbox) mailbox_close(&httpd_mailbox); - httpd_mailbox = NULL; - if (httpd_in) { prot_NONBLOCK(httpd_in); prot_fill(httpd_in); @@ -360,6 +362,10 @@ free(httpd_userid); httpd_userid = NULL; } + if (httpd_extradomain != NULL) { + free(httpd_extradomain); + httpd_extradomain = NULL; + } if (proxy_userid != NULL) { free(proxy_userid); proxy_userid = NULL; @@ -486,7 +492,7 @@ #ifdef HAVE_ZLIB buf_printf(&serverinfo, " zlib/%s", ZLIB_VERSION); #endif - buf_printf(&serverinfo, " libxml/%s", LIBXML_DOTTED_VERSION); + buf_printf(&serverinfo, " libxml2/%s", LIBXML_DOTTED_VERSION); } /* Do any namespace specific initialization */ @@ -496,6 +502,8 @@ if (namespaces[i]->init) namespaces[i]->init(&serverinfo); } + compile_time = calc_compile_time(__TIME__, __DATE__); + return 0; } @@ -696,8 +704,6 @@ } if (backend_cached) free(backend_cached); - if (httpd_mailbox) mailbox_close(&httpd_mailbox); - sync_log_done(); mboxlist_close(); @@ -932,10 +938,12 @@ txn.auth_chal.param = NULL; txn.req_hdrs = NULL; txn.req_body.flags = 0; + buf_reset(&txn.req_body.payload); txn.location = NULL; memset(&txn.error, 0, sizeof(struct error_t)); memset(&txn.resp_body, 0, /* Don't zero the response payload buffer */ sizeof(struct resp_body_t) - sizeof(struct buf)); + buf_reset(&txn.resp_body.payload); buf_reset(&txn.buf); ret = empty = 0; @@ -1078,6 +1086,13 @@ txn.flags.conn &= ~CONN_UPGRADE; } + /* Check for HTTP method override */ + if (!strcmp(req_line->meth, "POST") && + (hdr = spool_getheader(txn.req_hdrs, "X-HTTP-Method-Override"))) { + txn.flags.override = 1; + req_line->meth = (char *) hdr[0]; + } + /* Check Method against our list of known methods */ for (txn.meth = 0; (txn.meth < METH_UNKNOWN) && strcmp(http_methods[txn.meth].name, req_line->meth); @@ -1335,8 +1350,9 @@ struct accept *e, *enc = parse_accept(hdr); for (e = enc; e && e->token; e++) { - if (!strcasecmp(e->token, "gzip") || - !strcasecmp(e->token, "x-gzip")) { + if (e->qual > 0.0 && + (!strcasecmp(e->token, "gzip") || + !strcasecmp(e->token, "x-gzip"))) { txn.flags.te = TE_GZIP; } free(e->token); @@ -1347,8 +1363,9 @@ struct accept *e, *enc = parse_accept(hdr); for (e = enc; e && e->token; e++) { - if (!strcasecmp(e->token, "gzip") || - !strcasecmp(e->token, "x-gzip")) { + if (e->qual > 0.0 && + (!strcasecmp(e->token, "gzip") || + !strcasecmp(e->token, "x-gzip"))) { txn.resp_body.enc = CE_GZIP; } free(e->token); @@ -1452,12 +1469,31 @@ /* Compare Content-Types */ -EXPORTED int is_mediatype(const char *hdr, const char *type) +EXPORTED int is_mediatype(const char *pat, const char *type) { - size_t tlen = strcspn(type, "; \r\n\0"); - size_t hlen = strcspn(hdr, "; \r\n\0"); + const char *psep = strchr(pat, '/'); + const char *tsep = strchr(type, '/'); + size_t plen; + size_t tlen; + int alltypes; + + /* Check type */ + if (!psep || !tsep) return 0; + plen = psep - pat; + tlen = tsep - type; + + alltypes = !strncmp(pat, "*", plen); + + if (!alltypes && ((tlen != plen) || strncasecmp(pat, type, tlen))) return 0; + + /* Check subtype */ + pat = ++psep; + plen = strcspn(pat, "; \r\n\0"); + type = ++tsep; + tlen = strcspn(type, "; \r\n\0"); - return ((tlen == hlen) && !strncasecmp(hdr, type, tlen)); + return (!strncmp(pat, "*", plen) || + (!alltypes && (tlen == plen) && !strncasecmp(pat, type, tlen))); } @@ -1907,20 +1943,34 @@ /**************************** Response Routines *****************************/ +/* Create RFC3339 date ('buf' must be at least 21 characters) */ +EXPORTED char *rfc3339date_gen(char *buf, size_t len, time_t t) +{ + struct tm *tm = gmtime(&t); + + snprintf(buf, len, "%4d-%02d-%02dT%02d:%02d:%02dZ", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec);
View file
cyrus-imapd-2.5.tar.gz/imap/httpd.h
Changed
@@ -130,9 +130,10 @@ URL_NS_PRINCIPAL, URL_NS_CALENDAR, URL_NS_ADDRESSBOOK, - URL_NS_RSS, URL_NS_ISCHEDULE, URL_NS_DOMAINKEY, + URL_NS_TIMEZONE, + URL_NS_RSS, URL_NS_DBLOOKUP }; @@ -146,9 +147,10 @@ ALLOW_DAV = (1<<5), /* WebDAV specific methods/features */ ALLOW_WRITECOL = (1<<6), /* Create/modify collections */ ALLOW_CAL = (1<<7), /* CalDAV specific methods/features */ - ALLOW_CAL_SCHED = (1<<8), /* CalDAV Scheduling specific features */ - ALLOW_CARD = (1<<9), /* CardDAV specific methods/features */ - ALLOW_ISCHEDULE = (1<<10) /* iSchedule specific methods/features */ + ALLOW_CAL_AVAIL = (1<<8), /* CalDAV Availability specific features */ + ALLOW_CAL_SCHED = (1<<9), /* CalDAV Scheduling specific features */ + ALLOW_CARD = (1<<10),/* CardDAV specific methods/features */ + ALLOW_ISCHEDULE = (1<<11) /* iSchedule specific methods/features */ }; struct auth_scheme_t { @@ -282,7 +284,9 @@ struct txn_flags_t { unsigned char ver1_0; /* Request from HTTP/1.0 client */ unsigned char conn; /* Connection opts on req/resp */ + unsigned char override; /* HTTP method override */ unsigned char cors; /* Cross-Origin Resource Sharing */ + unsigned char mime; /* MIME-conformant response */ unsigned char te; /* Transfer-Encoding for resp */ unsigned char cc; /* Cache-Control directives for resp */ unsigned char ranges; /* Accept range requests for resource */ @@ -421,14 +425,15 @@ struct accept *next; }; +extern struct namespace_t namespace_default; extern struct namespace_t namespace_principal; extern struct namespace_t namespace_calendar; extern struct namespace_t namespace_addressbook; extern struct namespace_t namespace_ischedule; extern struct namespace_t namespace_domainkey; +extern struct namespace_t namespace_timezone; extern struct namespace_t namespace_rss; extern struct namespace_t namespace_dblookup; -extern struct namespace_t namespace_default; /* XXX These should be included in struct transaction_t */ @@ -442,6 +447,7 @@ extern int httpd_userisadmin; extern int httpd_userisproxyadmin; extern char *httpd_userid, *proxy_userid; +extern char *httpd_extradomain; extern struct auth_state *httpd_authstate; extern struct namespace httpd_namespace; extern struct sockaddr_storage httpd_localaddr, httpd_remoteaddr; @@ -451,12 +457,11 @@ extern xmlURIPtr parse_uri(unsigned meth, const char *uri, unsigned path_reqd, const char **errstr); extern struct accept *parse_accept(const char **hdr); -extern int is_mediatype(const char *hdr, const char *type); +extern int is_mediatype(const char *pat, const char *type); extern time_t calc_compile_time(const char *time, const char *date); -extern int http_mailbox_open(const char *name, struct mailbox **mailbox, - int locktype); extern const char *http_statusline(long code); -extern void httpdate_gen(char *buf, size_t len, time_t t); +extern char *rfc3339date_gen(char *buf, size_t len, time_t t); +extern char *httpdate_gen(char *buf, size_t len, time_t t); extern void comma_list_hdr(const char *hdr, const char *vals[], unsigned flags, ...); extern void response_header(long code, struct transaction_t *txn); @@ -469,7 +474,6 @@ const char *buf, unsigned len); extern void write_multipart_body(long code, struct transaction_t *txn, const char *buf, unsigned len); -extern int meth_get_doc(struct transaction_t *txn, void *params); extern int meth_options(struct transaction_t *txn, void *params); extern int meth_trace(struct transaction_t *txn, void *params); extern int etagcmp(const char *hdr, const char *etag);
View file
cyrus-imapd-2.5.tar.gz/imap/imapd.c
Changed
@@ -5422,19 +5422,17 @@ searchargs = new_searchargs(tag, GETSEARCH_CHARSET_KEYWORD|GETSEARCH_RETURN, &imapd_namespace, imapd_userid, imapd_authstate, imapd_userisadmin || imapd_userisproxyadmin); + + /* special case quirk for iPhones */ if (imapd_id.quirks & QUIRK_SEARCHFUZZY) searchargs->fuzzy_depth++; + c = get_search_program(imapd_in, imapd_out, searchargs); if (c == EOF) { eatline(imapd_in, ' '); freesearchargs(searchargs); return; } - if (imapd_id.quirks & QUIRK_SEARCHFUZZY) { - char *expr = search_expr_serialise(searchargs->root); - syslog(LOG_NOTICE, "fuzzy search %s", expr); - free(expr); - } if (c == '\r') c = prot_getc(imapd_in); if (c != '\n') { @@ -10098,10 +10096,9 @@ int i=0, j=0; char tagbuf[128]; int c; /* getword() returns an int */ - struct buf tag, cmd, tmp, user; + struct buf cmd, tmp, user; int r = 0; - memset(&tag, 0, sizeof(struct buf)); memset(&cmd, 0, sizeof(struct buf)); memset(&tmp, 0, sizeof(struct buf)); memset(&user, 0, sizeof(struct buf)); @@ -10110,28 +10107,21 @@ strlen(mailbox), mailbox); while(1) { - c = getword(pin, &tag); - if (c == EOF) { - r = IMAP_SERVER_UNAVAILABLE; + c = prot_getc(pin); + if (c != '*') { + prot_ungetc(c, pin); + r = getresult(pin, "ACL0"); break; } + c = prot_getc(pin); /* skip SP */ c = getword(pin, &cmd); if (c == EOF) { r = IMAP_SERVER_UNAVAILABLE; break; } - if(c == '\r') { - c = prot_getc(pin); - if(c != '\n') { - r = IMAP_SERVER_UNAVAILABLE; - goto cleanup; - } - } - if(c == '\n') goto cleanup; - - if (tag.s[0] == '*' && !strncmp(cmd.s, "ACL", 3)) { + if (!strncmp(cmd.s, "ACL", 3)) { while(c != '\n') { /* An ACL response, we should send a DELETEACL command */ c = getastring(pin, pout, &tmp); @@ -10147,7 +10137,7 @@ goto cleanup; } } - if(c == '\n') goto cleanup; + if(c == '\n') break; /* end of * ACL */ c = getastring(pin, pout, &user); if (c == EOF) { @@ -10170,13 +10160,10 @@ } /* if the next character is \n, we'll exit the loop */ } - continue; - } else if (!strncmp(tag.s, "ACL0", 4)) { - /* end of this command */ - if (!strcasecmp(cmd.s, "OK")) { break; } - if (!strcasecmp(cmd.s, "NO")) { r = IMAP_REMOTE_DENIED; break; } - r = IMAP_SERVER_UNAVAILABLE; - break; + } + else { + /* skip this line, we don't really care */ + eatline(pin, c); } } @@ -10185,17 +10172,9 @@ /* Now cleanup after all the DELETEACL commands */ if(!r) { while(j < i) { - c = getword(pin, &tag); - if (c == EOF) { - r = IMAP_SERVER_UNAVAILABLE; - break; - } - - eatline(pin, c); - - if(!strncmp("ACL", tag.s, 3)) { - j++; - } + snprintf(tagbuf, sizeof(tagbuf), "ACL%d", ++j); + r = getresult(pin, tagbuf); + if (r) break; } } @@ -10204,7 +10183,6 @@ buf_free(&user); buf_free(&tmp); buf_free(&cmd); - buf_free(&tag); return r; } @@ -10213,15 +10191,11 @@ const char *mboxname, const char *acl_in) { int r = 0; - int c; /* getword() returns an int */ char tag[128]; int tagnum = 1; char *rights, *nextid; char *acl_safe = acl_in ? xstrdup(acl_in) : NULL; char *acl = acl_safe; - struct buf inbuf; - - memset(&inbuf, 0, sizeof(struct buf)); while (acl) { rights = strchr(acl, '\t'); @@ -10241,40 +10215,12 @@ strlen(acl), acl, strlen(rights), rights); - while(1) { - c = getword(pin, &inbuf); - if (c == EOF) { - r = IMAP_SERVER_UNAVAILABLE; - break; - } - if(strncmp(tag, inbuf.s, strlen(tag))) { - eatline(pin, c); - continue; - } else { - /* this is our line */ - break; - } - } - - /* Are we OK? */ - - c = getword(pin, &inbuf); - if (c == EOF) { - r = IMAP_SERVER_UNAVAILABLE; - break; - } - - if(strncmp("OK", inbuf.s, 2)) { - r = IMAP_REMOTE_DENIED; - break; - } + r = getresult(pin, tag); + if (r) break; - /* Eat the line and get the next one */ - eatline(pin, c); acl = nextid; } - buf_free(&inbuf); if(acl_safe) free(acl_safe); return r; @@ -10582,6 +10528,7 @@ "Could not move mailbox: %s, mboxlist_update() failed %s", item->mbentry->name, error_message(r)); } + else item->state = XFER_LOCAL_MOVING; if (!r && xfer->seendb) { /* Backport the user's seendb on-the-fly */
View file
cyrus-imapd-2.5.tar.gz/imap/jcal.c
Changed
@@ -381,21 +381,18 @@ /* * Construct a jCal string for an iCalendar component. */ -const char *icalcomponent_as_jcal_string(icalcomponent *ical) +char *icalcomponent_as_jcal_string(icalcomponent *ical) { json_t *jcal; size_t flags = JSON_PRESERVE_ORDER; - char *freeme; - const char *buf; + char *buf; if (!ical) return NULL; jcal = icalcomponent_as_json_array(ical); flags |= (config_httpprettytelemetry ? JSON_INDENT(2) : JSON_COMPACT); - freeme = json_dumps(jcal, flags); - buf = icalmemory_tmp_copy(freeme); - free(freeme); + buf = json_dumps(jcal, flags); json_decref(jcal); @@ -761,16 +758,14 @@ buf_printf_markup(buf, 1, "["); buf_printf_markup(buf, 2, "["); buf_printf_markup(buf, 3, "\"prodid\","); - buf_printf_markup(buf, 3, "{"); - buf_printf_markup(buf, 3, "},"); + buf_printf_markup(buf, 3, "{},"); buf_printf_markup(buf, 3, "\"text\","); buf_printf_markup(buf, 3, "\"-//CyrusIMAP.org/Cyrus %s//EN\"", cyrus_version()); buf_printf_markup(buf, 2, "],"); buf_printf_markup(buf, 2, "["); buf_printf_markup(buf, 3, "\"version\","); - buf_printf_markup(buf, 3, "{"); - buf_printf_markup(buf, 3, "},"); + buf_printf_markup(buf, 3, "{},"); buf_printf_markup(buf, 3, "\"text\","); buf_printf_markup(buf, 3, "\"2.0\""); buf_printf_markup(buf, 2, "]");
View file
cyrus-imapd-2.5.tar.gz/imap/jcal.h
Changed
@@ -50,7 +50,7 @@ #include "util.h" -extern const char *icalcomponent_as_jcal_string(icalcomponent* comp); +extern char *icalcomponent_as_jcal_string(icalcomponent* comp); extern icalcomponent *jcal_string_as_icalcomponent(const char *str); extern const char *begin_jcal(struct buf *buf); extern void end_jcal(struct buf *buf);
View file
cyrus-imapd-2.5.tar.gz/imap/lmtp_sieve.c
Changed
@@ -118,6 +118,16 @@ } } +static int getfname(void *v, const char **fnamep) +{ + deliver_data_t *d = (deliver_data_t *)v; + *fnamep = NULL; + if (d->stage) + *fnamep = append_stagefname(d->stage); + /* XXX GLOBAL STUFF HERE */ + return 0; +} + static int getsize(void *mc, int *size) { message_data_t *m = ((deliver_data_t *) mc)->m; @@ -487,7 +497,7 @@ static int sieve_fileinto(void *ac, void *ic __attribute__((unused)), void *sc, - void *mc __attribute__((unused)), + void *mc, const char **errmsg __attribute__((unused))) { sieve_fileinto_context_t *fc = (sieve_fileinto_context_t *) ac; @@ -573,9 +583,9 @@ /* "default" is a magic value that implies the default */ notify(!strcmp("default",nc->method) ? notifier : nc->method, "SIEVE", nc->priority, sd->username, NULL, - nopt, nc->options, nc->message); + nopt, nc->options, nc->message, nc->fname); } - + return SIEVE_OK; } @@ -781,6 +791,7 @@ sieve_register_notify(interp, &sieve_notify); sieve_register_size(interp, &getsize); sieve_register_header(interp, &getheader); + sieve_register_fname(interp, &getfname); sieve_register_envelope(interp, &getenvelope); sieve_register_body(interp, &getbody);
View file
cyrus-imapd-2.5.tar.gz/imap/lmtpd.c
Changed
@@ -638,7 +638,7 @@ config_virtdomains ? strcspn(userbuf, "@") : 0); notify(notifier, "MAIL", NULL, userbuf, namebuf, 0, NULL, - notifyheader ? notifyheader : ""); + notifyheader ? notifyheader : "", /*fname*/NULL); } }
View file
cyrus-imapd-2.5.tar.gz/imap/mailbox.c
Changed
@@ -921,7 +921,7 @@ return IMAP_MAILBOX_LOCKED; /* can't reuse an already locked index */ if (listitem->m.index_locktype) - return IMAP_MAILBOX_LOCKED; + return IMAP_MAILBOX_LOCKED; listitem->nopen++; mailbox = &listitem->m; @@ -970,19 +970,7 @@ } lockindex: - /* this will open, map and parse the header file */ - r = mailbox_lock_index_internal(mailbox, index_locktype); - if (r) { - syslog(LOG_ERR, "IOERROR: locking index %s: %s", - mailbox->name, error_message(r)); - goto done; - } - - /* oops, a race, it got deleted meanwhile. That's OK */ - if (mailbox->i.options & OPT_MAILBOX_DELETED) { - r = IMAP_MAILBOX_NONEXISTENT; - goto done; - } + r = mailbox_lock_index(mailbox, index_locktype); done: if (r) mailbox_close(&mailbox); @@ -1723,9 +1711,6 @@ mailbox->is_readonly = 0; r = mailbox_open_index(mailbox); } - /* XXX - this could be handled out a layer, but we always - * need to have a locked conversations DB */ - if (!r) r = mailbox_lock_conversations(mailbox); if (!r) r = lock_blocking(mailbox->index_fd, index_fname); } else if (locktype == LOCK_SHARED) { @@ -1846,7 +1831,16 @@ EXPORTED int mailbox_lock_index(struct mailbox *mailbox, int locktype) { - int r = mailbox_lock_index_internal(mailbox, locktype); + int r = 0; + + /* XXX: only lock convdb if we're in read-write mode. This is kinda + * bogus really, but there's no way to get a read lock on convdb */ + if (locktype != LOCK_SHARED) { + r = mailbox_lock_conversations(mailbox); + if (r) return r; + } + + r = mailbox_lock_index_internal(mailbox, locktype); if (r) return r; /* otherwise, sanity checks for regular use, but not for internal @@ -2683,7 +2677,7 @@ if (!userid) goto done; /* phantom record - never really existed here */ - if (!old && (new->system_flags && FLAG_EXPUNGED)) + if (!old && (new->system_flags & FLAG_EXPUNGED)) goto done; r = mailbox_cacherecord(mailbox, new); @@ -2699,7 +2693,7 @@ assert(resource); - carddavdb = carddav_open(userid, 0); + carddavdb = carddav_open_mailbox(mailbox, 0); /* Find existing record for this resource */ carddav_lookup_resource(carddavdb, mailbox->name, resource, 1, &cdata); @@ -2803,7 +2797,7 @@ if (!userid) goto done; /* phantom record - never really existed here */ - if (!old && (new->system_flags && FLAG_EXPUNGED)) + if (!old && (new->system_flags & FLAG_EXPUNGED)) goto done; r = mailbox_cacherecord(mailbox, new); @@ -2820,7 +2814,7 @@ } } - caldavdb = caldav_open(userid, 0); + caldavdb = caldav_open_mailbox(mailbox, 0); /* Find existing record for this resource */ caldav_lookup_resource(caldavdb, mailbox->name, resource, 1, &cdata); @@ -3116,15 +3110,14 @@ if (r) return r; r = mailbox_update_conversations(mailbox, old, new); + if (r) return r; - /* NOTE - we do these last */ + /* NOTE - we do these last, once the counts are updated */ - if (old) { + if (old) mailbox_index_update_counts(mailbox, old, 0); - } - if (new) { + if (new) mailbox_index_update_counts(mailbox, new, 1); - } return 0; } @@ -4244,7 +4237,7 @@ uint32_t recno; int r = 0; - if (!(mailbox->mbtype & (MBTYPE_ADDRESSBOOK|MBTYPE_CALENDAR))) + if (!(mailbox->mbtype & (MBTYPES_DAV))) return 0; for (recno = 1; recno <= mailbox->i.num_records; recno++) { @@ -4434,7 +4427,7 @@ for (i = 0; i < paths.count; i++) { char *path = paths.data[i]; /* need direct reference, because we're fiddling */ r = rmdir(path); - if (r && errno != -ENOENT) + if (r && errno != ENOENT) syslog(LOG_NOTICE, "Remove of supposedly empty directory %s failed: %m", path);
View file
cyrus-imapd-2.5.tar.gz/imap/mailbox.h
Changed
@@ -76,6 +76,7 @@ #define FNAME_SQUAT "/cyrus.squat" #define FNAME_EXPUNGE "/cyrus.expunge" #define FNAME_ANNOTATIONS "/cyrus.annotations" +#define FNAME_DAV "/cyrus.dav" enum meta_filename { META_HEADER = 1, @@ -84,6 +85,7 @@ META_SQUAT, META_EXPUNGE, META_ANNOTATIONS, + META_DAV, META_ARCHIVECACHE }; @@ -575,6 +577,8 @@ uint32_t mailbox_sync_crc(struct mailbox *mailbox, unsigned vers, int recalc); unsigned mailbox_best_crcvers(unsigned minvers, unsigned maxvers); +extern int mailbox_add_dav(struct mailbox *mailbox); + /* Rename a CID. Note - this is just one mailbox! */ extern int mailbox_cid_rename(struct mailbox *mailbox, conversation_id_t from_cid, @@ -587,6 +591,4 @@ extern int mailbox_update_xconvmodseq(struct mailbox *mailbox, modseq_t, int force); extern int mailbox_has_conversations(struct mailbox *mailbox); -extern int mailbox_add_dav(struct mailbox *mailbox); - #endif /* INCLUDED_MAILBOX_H */
View file
cyrus-imapd-2.5.tar.gz/imap/mbdump.c
Changed
@@ -59,6 +59,7 @@ #include <utime.h> #include "annotate.h" +#include "dav_util.h" #include "exitcodes.h" #include "global.h" #include "imap/imap_err.h" @@ -458,11 +459,12 @@ { META_INDEX, "cyrus.index" }, { META_CACHE, "cyrus.cache" }, { META_EXPUNGE, "cyrus.expunge" }, + { META_DAV, "cyrus.dav" }, { 0, NULL } }; -enum { SEEN_DB = 0, SUBS_DB = 1, MBOXKEY_DB = 2 }; -static int NUM_USER_DATA_FILES = 3; +enum { SEEN_DB = 0, SUBS_DB = 1, MBOXKEY_DB = 2, DAV_DB = 3 }; +static int NUM_USER_DATA_FILES = 4; EXPORTED int dump_mailbox(const char *tag, struct mailbox *mailbox, uint32_t uid_start, int oldversion, @@ -628,6 +630,14 @@ fname = mboxkey_getpath(userid); ftag = "MBOXKEY"; break; + case DAV_DB: { + struct buf dav_file = BUF_INITIALIZER; + + dav_getpath_byuserid(&dav_file, userid); + fname = (char *) buf_cstring(&dav_file); + ftag = "DAV"; + break; + } default: fatal("unknown user data file", EC_OSFILE); } @@ -1062,6 +1072,12 @@ char *s = user_hash_subs(userid); strlcpy(fnamebuf, s, sizeof(fnamebuf)); free(s); + } else if (userid && !strcmp(file.s, "DAV")) { + /* overwriting this outright is absolutely what we want to do */ + struct buf dav_file = BUF_INITIALIZER; + dav_getpath_byuserid(&dav_file, userid); + strlcpy(fnamebuf, buf_cstring(&dav_file), sizeof(fnamebuf)); + buf_free(&dav_file); } else if (userid && !strcmp(file.s, "SEEN")) { seen_file = seen_getpath(userid);
View file
cyrus-imapd-2.5.tar.gz/imap/mboxevent.c
Changed
@@ -76,8 +76,9 @@ EVENT_MESSAGE_TRASH) #define MAILBOX_EVENTS (EVENT_MAILBOX_CREATE|EVENT_MAILBOX_DELETE|\ - EVENT_MAILBOX_RENAME|EVENT_MAILBOX_SUBSCRIBE|\ - EVENT_MAILBOX_UNSUBSCRIBE) + EVENT_MAILBOX_RENAME) + +#define SUBS_EVENTS (EVENT_MAILBOX_SUBSCRIBE|EVENT_MAILBOX_UNSUBSCRIBE) #define QUOTA_EVENTS (EVENT_QUOTA_EXCEED|EVENT_QUOTA_WITHIN|EVENT_QUOTA_CHANGE) @@ -130,10 +131,10 @@ { EVENT_PID, "pid", EVENT_PARAM_INT, 0, 0 }, { EVENT_USER, "user", EVENT_PARAM_STRING, 0, 0 }, { EVENT_MESSAGE_SIZE, "messageSize", EVENT_PARAM_INT, 0, 0 }, - { EVENT_MESSAGE_CID, "vnd.fastmail.cid", EVENT_PARAM_STRING, 0, 0 }, { EVENT_MBTYPE, "vnd.cmu.mbtype", EVENT_PARAM_STRING, 0, 0 }, { EVENT_DAV_FILENAME, "vnd.cmu.davFilename", EVENT_PARAM_STRING, 0, 0 }, { EVENT_DAV_UID, "vnd.cmu.davUid", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_MESSAGE_CID, "vnd.fastmail.cid", EVENT_PARAM_STRING, 0, 0 }, /* always at end to let the parser to easily truncate this part */ { EVENT_ENVELOPE, "vnd.cmu.envelope", EVENT_PARAM_STRING, 0, 0 }, { EVENT_BODYSTRUCTURE, "bodyStructure", EVENT_PARAM_STRING, 0, 0 }, @@ -188,6 +189,9 @@ if (groups & IMAP_ENUM_EVENT_GROUPS_ACCESS) enabled_events |= (EVENT_LOGIN|EVENT_LOGOUT); + if (groups & IMAP_ENUM_EVENT_GROUPS_SUBSCRIPTION) + enabled_events |= SUBS_EVENTS; + if (groups & IMAP_ENUM_EVENT_GROUPS_MAILBOX) enabled_events |= MAILBOX_EVENTS; } @@ -384,15 +388,15 @@ case EVENT_MESSAGE_SIZE: return (extra_params & IMAP_ENUM_EVENT_EXTRA_PARAMS_MESSAGESIZE) && (type & (EVENT_MESSAGE_APPEND|EVENT_MESSAGE_NEW)); - case EVENT_MESSAGE_CID: - return (extra_params & IMAP_ENUM_EVENT_EXTRA_PARAMS_VND_FASTMAIL_CID) && - (type & (EVENT_MESSAGE_APPEND|EVENT_MESSAGE_NEW)); case EVENT_DAV_FILENAME: return (extra_params & IMAP_ENUM_EVENT_EXTRA_PARAMS_VND_CMU_DAVFILENAME) && (type & EVENT_CALENDAR); case EVENT_DAV_UID: return (extra_params & IMAP_ENUM_EVENT_EXTRA_PARAMS_VND_CMU_DAVUID) && (type & EVENT_CALENDAR); + case EVENT_MESSAGE_CID: + return (extra_params & IMAP_ENUM_EVENT_EXTRA_PARAMS_VND_FASTMAIL_CID) && + (type & (EVENT_MESSAGE_APPEND|EVENT_MESSAGE_NEW)); case EVENT_MESSAGES: if (type & (EVENT_QUOTA_EXCEED|EVENT_QUOTA_WITHIN)) return 1; @@ -453,6 +457,7 @@ struct mboxevent *event; char stimestamp[TIMESTAMP_MAX+1]; char *formatted_message; + const char *fname = NULL; /* nothing to notify */ if (!mboxevents) @@ -549,7 +554,7 @@ /* notification is ready to send */ formatted_message = json_formatter(type, event->params); - notify(notifier, "EVENT", NULL, NULL, NULL, 0, NULL, formatted_message); + notify(notifier, "EVENT", NULL, NULL, NULL, 0, NULL, formatted_message, fname); free(formatted_message); } @@ -759,12 +764,10 @@ FILL_STRING_PARAM(event, EVENT_DAV_FILENAME, xstrdup(resource)); if (mboxevent_expected_param(event->type, EVENT_DAV_UID)) { - const char *userid = mboxname_to_userid(mailbox->name); - if (!userid) return; if (mailbox->mbtype & MBTYPE_ADDRESSBOOK) { struct carddav_db *carddavdb = NULL; struct carddav_data *cdata = NULL; - carddavdb = carddav_open(userid, 0); + carddavdb = carddav_open_mailbox(mailbox, 0); carddav_lookup_resource(carddavdb, mailbox->name, resource, 0, &cdata); FILL_STRING_PARAM(event, EVENT_DAV_UID, xstrdup(cdata->vcard_uid)); carddav_close(carddavdb); @@ -772,14 +775,13 @@ if (mailbox->mbtype & MBTYPE_CALENDAR) { struct caldav_db *caldavdb = NULL; struct caldav_data *cdata = NULL; - caldavdb = caldav_open(userid, 0); + caldavdb = caldav_open_mailbox(mailbox, 0); caldav_lookup_resource(caldavdb, mailbox->name, resource, 0, &cdata); FILL_STRING_PARAM(event, EVENT_DAV_UID, xstrdup(cdata->ical_uid)); caldav_close(caldavdb); } } } - } void mboxevent_extract_copied_record(struct mboxevent *event,
View file
cyrus-imapd-2.5.tar.gz/imap/mboxevent.h
Changed
@@ -112,10 +112,10 @@ EVENT_PID, EVENT_USER, EVENT_MESSAGE_SIZE, - EVENT_MESSAGE_CID, EVENT_MBTYPE, EVENT_DAV_FILENAME, EVENT_DAV_UID, + EVENT_MESSAGE_CID, EVENT_ENVELOPE, EVENT_BODYSTRUCTURE, EVENT_CLIENT_ID,
View file
cyrus-imapd-2.5.tar.gz/imap/mboxlist.c
Changed
@@ -254,20 +254,6 @@ /* never get here */ } -static char *_parse_acl(struct dlist *di) -{ - struct buf buf = BUF_INITIALIZER; - struct dlist *ai; - - /* gotta make it all tabby again */ - for (ai = di->head; ai; ai = ai->next) { - buf_printf(&buf, "%s\t", ai->name); - buf_printf(&buf, "%s\t", dlist_cstring(ai)); - } - - return buf_release(&buf); -} - EXPORTED uint32_t mboxlist_string_to_mbtype(const char *string) { uint32_t mbtype = 0; @@ -303,6 +289,58 @@ return mbtype; } +struct parseentry_rock { + struct mboxlist_entry *mbentry; + struct buf *aclbuf; + int doingacl; +}; + +int parseentry_cb(int type, struct dlistsax_data *d) +{ + struct parseentry_rock *rock = (struct parseentry_rock *)d->rock; + + switch(type) { + case DLISTSAX_KVLISTSTART: + if (!strcmp(buf_cstring(&d->kbuf), "A")) { + rock->doingacl = 1; + } + break; + case DLISTSAX_KVLISTEND: + rock->doingacl = 0; + break; + case DLISTSAX_STRING: + if (rock->doingacl) { + buf_append(rock->aclbuf, &d->kbuf); + buf_putc(rock->aclbuf, '\t'); + buf_append(rock->aclbuf, &d->buf); + buf_putc(rock->aclbuf, '\t'); + } + else { + const char *key = buf_cstring(&d->kbuf); + if (!strcmp(key, "I")) { + rock->mbentry->uniqueid = buf_newcstring(&d->buf); + } + else if (!strcmp(key, "M")) { + rock->mbentry->mtime = atoi(buf_cstring(&d->buf)); + } + else if (!strcmp(key, "P")) { + rock->mbentry->partition = buf_newcstring(&d->buf); + } + else if (!strcmp(key, "S")) { + rock->mbentry->server = buf_newcstring(&d->buf); + } + else if (!strcmp(key, "T")) { + rock->mbentry->mbtype = mboxlist_string_to_mbtype(buf_cstring(&d->buf)); + } + else if (!strcmp(key, "V")) { + rock->mbentry->uidvalidity = atoi(buf_cstring(&d->buf)); + } + } + } + + return 0; +} + /* * parse a record read from the mailboxes.db into its parts. * @@ -319,6 +357,7 @@ const char *name, size_t namelen, const char *data, size_t datalen) { + static struct buf aclbuf; int r = IMAP_MAILBOX_BADFORMAT; char *freeme = NULL; char **target; @@ -336,39 +375,13 @@ /* check for DLIST mboxlist */ if (*data == '%') { - struct dlist *dl = NULL; - struct dlist *di; - r = dlist_parsemap(&dl, 0, data, datalen); - if (r) goto done; - if (!dl) goto done; - for (di = dl->head; di; di = di->next) { - switch(di->name[0]) { - case 'A': - mbentry->acl = _parse_acl(di); - break; - case 'I': - mbentry->uniqueid = xstrdupnull(dlist_cstring(di)); - break; - case 'M': - mbentry->mtime = dlist_num(di); - break; - case 'P': - mbentry->partition = xstrdupnull(dlist_cstring(di)); - break; - case 'S': - mbentry->server = xstrdupnull(dlist_cstring(di)); - break; - case 'T': - mbentry->mbtype = mboxlist_string_to_mbtype(dlist_cstring(di)); - break; - case 'V': - mbentry->uidvalidity = dlist_num(di); - break; - } - } - dlist_free(&dl); - - r = 0; + struct parseentry_rock rock; + memset(&rock, 0, sizeof(struct parseentry_rock)); + rock.mbentry = mbentry; + rock.aclbuf = &aclbuf; + aclbuf.len = 0; + r = dlist_parsesax(data, datalen, 0, parseentry_cb, &rock); + if (!r) mbentry->acl = buf_newcstring(&aclbuf); goto done; } @@ -1789,7 +1802,7 @@ mode = ACL_MODE_REMOVE; } /* do not allow non-admin user to remove the admin rights from mailbox owner */ - if (!isadmin && isidentifiermbox) { + if (!isadmin && isidentifiermbox && mode != ACL_MODE_ADD) { int has_admin_rights = mboxlist_have_admin_rights(rights); if ((has_admin_rights && mode == ACL_MODE_REMOVE) || (!has_admin_rights && mode != ACL_MODE_REMOVE)) {
View file
cyrus-imapd-2.5.tar.gz/imap/mboxname.c
Changed
@@ -1521,6 +1521,11 @@ metaflag = IMAP_ENUM_METAPARTITION_FILES_ANNOTATIONS; filename = FNAME_ANNOTATIONS; break; + case META_DAV: + snprintf(confkey, 256, "metadir-dav-%s", partition); + metaflag = IMAP_ENUM_METAPARTITION_FILES_DAV; + filename = FNAME_DAV; + break; case META_ARCHIVECACHE: snprintf(confkey, 256, "metadir-archivecache-%s", partition); metaflag = IMAP_ENUM_METAPARTITION_FILES_ARCHIVECACHE;
View file
cyrus-imapd-2.5.tar.gz/imap/nntpd.c
Changed
@@ -1023,13 +1023,12 @@ be = backend_current; if (arg1.len && - (!is_newsgroup(arg1.s) || - (r = open_group(arg1.s, 0, &be, NULL)))) goto nogroup; + (r = open_group(arg1.s, 0, &be, NULL))) goto nogroup; else if (be) { prot_printf(be->out, "%s", cmd.s); if (arg1.len) { prot_printf(be->out, " %s", arg1.s); - if (LISTGROUP) prot_printf(be->out, " %s", arg2.s); + if (LISTGROUP) prot_printf(be->out, " %s", arg2.s); } prot_printf(be->out, "\r\n"); @@ -1741,6 +1740,8 @@ if (!has_prefix) { snprintf(mailboxname, sizeof(mailboxname), "%s%s", newsprefix, name); name = mailboxname; + + if (!is_newsgroup(name)) return IMAP_MAILBOX_NONEXISTENT; } if (!r) r = mlookup(name, &mbentry);
View file
cyrus-imapd-2.5.tar.gz/imap/notify.c
Changed
@@ -77,19 +77,94 @@ return 0; } +static void notify_dlist(const char *sockpath, const char *method, + const char *class, const char *priority, + const char *user, const char *mailbox, + int nopt, const char **options, + const char *message, const char *fname) +{ + struct sockaddr_un sun_data; + struct protstream *in = NULL, *out = NULL; + struct dlist *dl = dlist_newkvlist(NULL, "NOTIFY"); + struct dlist *res = NULL; + struct dlist *il; + int c; + int soc = -1; + int i; + + dlist_setatom(dl, "METHOD", method); + dlist_setatom(dl, "CLASS", class); + dlist_setatom(dl, "PRIORITY", priority); + dlist_setatom(dl, "USER", user); + dlist_setatom(dl, "MAILBOX", mailbox); + il = dlist_newlist(dl, "OPTIONS"); + for (i = 0; i < nopt; i++) + dlist_setatom(il, NULL, options[i]); + dlist_setatom(dl, "MESSAGE", message); + dlist_setatom(dl, "FILEPATH", fname); + + memset((char *)&sun_data, 0, sizeof(sun_data)); + sun_data.sun_family = AF_UNIX; + strlcpy(sun_data.sun_path, sockpath, sizeof(sun_data.sun_path)); + + soc = socket(PF_UNIX, SOCK_STREAM, 0); + if (soc < 0) { + syslog(LOG_ERR, "unable to create notify socket(): %m"); + goto out; + } + + if (connect(soc, (struct sockaddr *)&sun_data, sizeof(sun_data)) < 0) { + syslog(LOG_ERR, "failed to connect to %s: %m", sockpath); + goto out; + } + + in = prot_new(soc, 0); + out = prot_new(soc, 1); + /* Force use of LITERAL+ */ + prot_setisclient(in, 1); + prot_setisclient(out, 1); + + dlist_print(dl, 1, out); + prot_printf(out, "\r\n"); + prot_flush(out); + + c = dlist_parse(&res, 1, in); + if (c == '\r') c = prot_getc(in); + /* XXX - do something with the response? Like have NOTIFY answer */ + if (c == '\n' && res && res->name) { + syslog(LOG_NOTICE, "NOTIFY: response %s to method %s", res->name, method); + } + else { + syslog(LOG_ERR, "NOTIFY: error sending %s to %s", method, sockpath); + } + +out: + if (in) prot_free(in); + if (out) prot_free(out); + if (soc >= 0) close(soc); + dlist_free(&dl); + dlist_free(&res); +} + EXPORTED void notify(const char *method, const char *class, const char *priority, const char *user, const char *mailbox, int nopt, const char **options, - const char *message) + const char *message, const char *fname) { - const char *notify_sock; + const char *notify_sock = config_getstring(IMAPOPT_NOTIFYSOCKET); int soc = -1; struct sockaddr_un sun_data; char buf[NOTIFY_MAXSIZE] = "", noptstr[20]; int buflen = 0; int i, r = 0; + if (!strncmp(notify_sock, "dlist:", 6)) { + return notify_dlist(notify_sock+6, method, class, priority, + user, mailbox, nopt, options, + message, fname); + } + soc = socket(AF_UNIX, SOCK_DGRAM, 0); if (soc == -1) { syslog(LOG_ERR, "unable to create notify socket(): %m"); @@ -98,8 +173,7 @@ memset((char *)&sun_data, 0, sizeof(sun_data)); sun_data.sun_family = AF_UNIX; - notify_sock = config_getstring(IMAPOPT_NOTIFYSOCKET); - if (notify_sock) { + if (notify_sock) { strlcpy(sun_data.sun_path, notify_sock, sizeof(sun_data.sun_path)); } else { @@ -129,6 +203,7 @@ } if (!r) r = add_arg(buf, sizeof(buf), message, &buflen); + if (!r && fname) r = add_arg(buf, sizeof(buf), fname, &buflen); if (r) { syslog(LOG_ERR, "notify datagram too large, %s, %s", @@ -150,5 +225,4 @@ out: xclose(soc); - return; }
View file
cyrus-imapd-2.5.tar.gz/imap/notify.h
Changed
@@ -47,6 +47,6 @@ const char *class, const char *priority, const char *user, const char *mailbox, int nopt, const char **options, - const char *message); + const char *message, const char *fname); #endif /* NOTIFY_H */
View file
cyrus-imapd-2.5.tar.gz/imap/search_engines.c
Changed
@@ -207,7 +207,7 @@ int incremental = (flags & SEARCH_UPDATE_INCREMENTAL); r = rx->begin_mailbox(rx, mailbox, flags); - if (r) return r; + if (r) goto done; first = mailbox_finduid(mailbox, rx->first_unindexed_uid(rx)); if (!first) first = 1; /* empty mailbox */ @@ -235,6 +235,7 @@ if (batch.count) r = flush_batch(rx, mailbox, &batch); + done: ptrarray_fini(&batch); r2 = rx->end_mailbox(rx, mailbox); if (r) return r;
View file
cyrus-imapd-2.5.tar.gz/imap/search_expr.c
Changed
@@ -1759,7 +1759,7 @@ struct conv_rock *rock = (struct conv_rock *)internalised; conversation_id_t cid = NULLCONVERSATION; conversation_t *conv = NULL; - int r; + int r = 0; /* invalid flag name */ if (!rock->cstate) return 0; @@ -1767,9 +1767,7 @@ if (conversation_load(rock->cstate, cid, &conv)) return 0; if (!conv) return 0; - if (rock->num < 0) - r = 0; /* invalid flag name */ - else if (rock->num == 0) + if (rock->num == 0) r = !conv->unseen; else if (rock->num > 0) r = !!conv->counts[rock->num-1];
View file
cyrus-imapd-2.5.tar.gz/imap/search_xapian.c
Changed
@@ -1012,8 +1012,8 @@ if (!dirs || !dirs->count) goto out; /* if there are directories, open the databases */ - bb->db = xapian_db_open((const char **)dirs->data); - if (!bb->db) goto out; + r = xapian_db_open((const char **)dirs->data, &bb->db); + if (r) goto out; /* read the list of all indexed messages to allow (optional) false positives * for unindexed messages */ @@ -1029,6 +1029,7 @@ out: strarray_free(dirs); strarray_free(active); + /* XXX - error return? */ return &bb->super; }
View file
cyrus-imapd-2.5.tar.gz/imap/sync_support.c
Changed
@@ -1130,8 +1130,8 @@ { struct sync_annot *item = xzmalloc(sizeof(struct sync_annot)); - item->entry = xstrdup(entry); - item->userid = xstrdup(userid); + item->entry = xstrdupnull(entry); + item->userid = xstrdupnull(userid); buf_copy(&item->value, value); item->mark = 0; @@ -1153,8 +1153,8 @@ current = l->head; while (current) { next = current->next; - if (current->entry) free(current->entry); - if (current->userid) free(current->userid); + free(current->entry); + free(current->userid); buf_free(¤t->value); free(current); current = next; @@ -1367,6 +1367,7 @@ struct dlist *kl, struct dlist *kupload, int printrecords) { + struct sync_annot_list *annots = NULL; modseq_t xconvmodseq = 0; int r = 0; @@ -1394,6 +1395,15 @@ dlist_setnum64(kl, "XCONVMODSEQ", xconvmodseq); } + /* always send mailbox annotations */ + r = read_annotations(mailbox, NULL, &annots); + if (r) goto done; + + if (annots) { + encode_annotations(kl, annots); + sync_annot_list_free(&annots); + } + if (printrecords) { struct index_record record; struct dlist *il; @@ -1401,7 +1411,6 @@ uint32_t recno; int send_file; uint32_t prevuid = 0; - struct sync_annot_list *annots = NULL; for (recno = 1; recno <= mailbox->i.num_records; recno++) { /* we can't send bogus records */ @@ -1461,14 +1470,6 @@ sync_annot_list_free(&annots); } } - - r = read_annotations(mailbox, NULL, &annots); - if (r) goto done; - - if (annots) { - encode_annotations(kl, annots); - sync_annot_list_free(&annots); - } } done: @@ -1645,13 +1646,13 @@ struct dlist *annots = NULL; struct dlist *aa; - if (!sal) + if (!sal) return; for (sa = sal->head ; sa ; sa = sa->next) { if (!annots) annots = dlist_newlist(parent, "ANNOTATIONS"); - aa = dlist_newkvlist(annots, "A"); + aa = dlist_newkvlist(annots, NULL); dlist_setatom(aa, "ENTRY", sa->entry); dlist_setatom(aa, "USERID", sa->userid); dlist_setmap(aa, "VALUE", sa->value.s, sa->value.len); @@ -1716,9 +1717,9 @@ diff++; if (!diff) - diff = strcmp(a->entry, b->entry); + diff = strcmpnull(a->entry, b->entry); if (!diff) - diff = strcmp(a->userid, b->userid); + diff = strcmpnull(a->userid, b->userid); if (!diff && diff_value) diff = buf_cmp(&a->value, &b->value);
View file
cyrus-imapd-2.5.tar.gz/imap/tls.c
Changed
@@ -674,53 +674,6 @@ SSL_CTX_set_options(s_ctx, off); SSL_CTX_set_info_callback(s_ctx, apps_ssl_info_callback); - /* Don't use an internal session cache */ - SSL_CTX_sess_set_cache_size(s_ctx, 1); /* 0 is unlimited, so use 1 */ - SSL_CTX_set_session_cache_mode(s_ctx, SSL_SESS_CACHE_SERVER | - SSL_SESS_CACHE_NO_AUTO_CLEAR | - SSL_SESS_CACHE_NO_INTERNAL_LOOKUP); - - /* Get the session timeout from the config file (in minutes) */ - timeout = config_getint(IMAPOPT_TLS_SESSION_TIMEOUT); - if (timeout < 0) timeout = 0; - if (timeout > 1440) timeout = 1440; /* 24 hours max */ - - /* A timeout of zero disables session caching */ - if (timeout) { - const char *fname = NULL; - char *tofree = NULL; - int r; - - /* Set the context for session reuse -- use the service ident */ - SSL_CTX_set_session_id_context(s_ctx, (void*) ident, strlen(ident)); - - /* Set the timeout for the internal/external cache (in seconds) */ - SSL_CTX_set_timeout(s_ctx, timeout*60); - - /* Set the callback functions for the external session cache */ - SSL_CTX_sess_set_new_cb(s_ctx, new_session_cb); - SSL_CTX_sess_set_remove_cb(s_ctx, remove_session_cb); - SSL_CTX_sess_set_get_cb(s_ctx, get_session_cb); - - fname = config_getstring(IMAPOPT_TLSCACHE_DB_PATH); - - /* create the name of the db file */ - if (!fname) { - tofree = strconcat(config_dir, FNAME_TLSSESSIONS, (char *)NULL); - fname = tofree; - } - - r = cyrusdb_open(DB, fname, CYRUSDB_CREATE, &sessdb); - if (r != 0) { - syslog(LOG_ERR, "DBERROR: opening %s: %s", - fname, cyrusdb_strerror(ret)); - } - else - sess_dbopen = 1; - - free(tofree); - } - cipher_list = config_getstring(IMAPOPT_TLS_CIPHER_LIST); if (!SSL_CTX_set_cipher_list(s_ctx, cipher_list)) { syslog(LOG_ERR,"TLS server engine: cannot load cipher list '%s'", @@ -776,6 +729,53 @@ } } + /* Don't use an internal session cache */ + SSL_CTX_sess_set_cache_size(s_ctx, 1); /* 0 is unlimited, so use 1 */ + SSL_CTX_set_session_cache_mode(s_ctx, SSL_SESS_CACHE_SERVER | + SSL_SESS_CACHE_NO_AUTO_CLEAR | + SSL_SESS_CACHE_NO_INTERNAL_LOOKUP); + + /* Get the session timeout from the config file (in minutes) */ + timeout = config_getint(IMAPOPT_TLS_SESSION_TIMEOUT); + if (timeout < 0) timeout = 0; + if (timeout > 1440) timeout = 1440; /* 24 hours max */ + + /* A timeout of zero disables session caching */ + if (timeout) { + const char *fname = NULL; + char *tofree = NULL; + int r; + + /* Set the context for session reuse -- use the service ident */ + SSL_CTX_set_session_id_context(s_ctx, (void*) ident, strlen(ident)); + + /* Set the timeout for the internal/external cache (in seconds) */ + SSL_CTX_set_timeout(s_ctx, timeout*60); + + /* Set the callback functions for the external session cache */ + SSL_CTX_sess_set_new_cb(s_ctx, new_session_cb); + SSL_CTX_sess_set_remove_cb(s_ctx, remove_session_cb); + SSL_CTX_sess_set_get_cb(s_ctx, get_session_cb); + + fname = config_getstring(IMAPOPT_TLSCACHE_DB_PATH); + + /* create the name of the db file */ + if (!fname) { + tofree = strconcat(config_dir, FNAME_TLSSESSIONS, (char *)NULL); + fname = tofree; + } + + r = cyrusdb_open(DB, fname, CYRUSDB_CREATE, &sessdb); + if (r != 0) { + syslog(LOG_ERR, "DBERROR: opening %s: %s", + fname, cyrusdb_strerror(ret)); + } + else + sess_dbopen = 1; + + free(tofree); + } + tls_serverengine = 1; return (0); }
View file
cyrus-imapd-2.5.tar.gz/imap/xapian_wrap.cpp
Changed
@@ -69,11 +69,10 @@ int xapian_dbw_open(const char *path, xapian_dbw_t **dbwp) { - xapian_dbw_t *dbw = 0; + xapian_dbw_t *dbw = (xapian_dbw_t *)xzmalloc(sizeof(xapian_dbw_t)); int r = 0; try { - dbw = (xapian_dbw_t *)xzmalloc(sizeof(xapian_dbw_t)); int action = Xapian::DB_CREATE_OR_OPEN; dbw->database = new Xapian::WritableDatabase(path, action); dbw->term_generator = new Xapian::TermGenerator(); @@ -93,7 +92,7 @@ } if (r) - free(dbw); + xapian_dbw_close(dbw); else *dbwp = dbw; @@ -221,13 +220,13 @@ Xapian::QueryParser *parser; }; -xapian_db_t *xapian_db_open(const char **paths) +int xapian_db_open(const char **paths, xapian_db_t **dbp) { - xapian_db_t *db = NULL; + xapian_db_t *db = (xapian_db_t *)xzmalloc(sizeof(xapian_db_t)); const char *thispath = "(unknown)"; + int r = 0; try { - db = (xapian_db_t *)xzmalloc(sizeof(xapian_db_t)); db->paths = new std::string(); db->database = new Xapian::Database(); while (*paths) { @@ -247,9 +246,15 @@ catch (const Xapian::Error &err) { syslog(LOG_ERR, "IOERROR: Xapian: caught exception: %s: %s", thispath, err.get_description().c_str()); - db = NULL; + r = IMAP_IOERROR; } - return db; + + if (r) + xapian_db_close(db); + else + *dbp = db; + + return r; } void xapian_db_close(xapian_db_t *db) @@ -262,6 +267,7 @@ free(db); } catch (const Xapian::Error &err) { + /* XXX - memory leak? */ syslog(LOG_ERR, "IOERROR: Xapian: caught exception: %s: %s", err.get_context().c_str(), err.get_description().c_str()); }
View file
cyrus-imapd-2.5.tar.gz/imap/xapian_wrap.h
Changed
@@ -66,7 +66,7 @@ extern int xapian_dbw_end_doc(xapian_dbw_t *dbw); /* query-side interface */ -extern xapian_db_t *xapian_db_open(const char **paths); +extern int xapian_db_open(const char **paths, xapian_db_t **dbp); extern void xapian_db_close(xapian_db_t *); extern xapian_query_t *xapian_query_new_match(const xapian_db_t *, const char *prefix, const char *term); extern xapian_query_t *xapian_query_new_compound(const xapian_db_t *, int is_or, xapian_query_t **children, int n);
View file
cyrus-imapd-2.5.tar.gz/imap/xcal.c
Changed
@@ -579,12 +579,12 @@ /* * Construct a xcal string for an iCalendar component. */ -const char *icalcomponent_as_xcal_string(icalcomponent *ical) +char *icalcomponent_as_xcal_string(icalcomponent *ical) { xmlDocPtr doc; xmlNodePtr root, xcomp; + xmlChar *buf; int bufsiz; - const char *xcal = NULL; if (!ical) return NULL; @@ -599,13 +599,8 @@ if (!xmlStrcmp(xcomp->name, BAD_CAST "vcalendar")) { /* Complete iCalendar stream */ - xmlChar *buf; - xmlDocDumpFormatMemoryEnc(doc, &buf, &bufsiz, "utf-8", config_httpprettytelemetry); - xcal = icalmemory_tmp_copy((char *) buf); - - xmlFree(buf); } else { /* Single iCalendar object */ @@ -613,14 +608,13 @@ bufsiz = xmlNodeDump(xbuf, doc, xcomp, 0, config_httpprettytelemetry); - xcal = icalmemory_tmp_copy((char *) xbuf); - + buf = xmlBufferDetach(xbuf); xmlBufferFree(xbuf); } xmlFreeDoc(doc); - return xcal; + return (char *) buf; } @@ -1166,3 +1160,46 @@ buf_printf_markup(buf, 1, "</vcalendar>"); buf_printf_markup(buf, 0, "</icalendar>"); } + + +/* libxml2 replacement functions for those missing in older versions */ +#if (LIBXML_VERSION < 20800) +xmlChar *xmlBufferDetach(xmlBufferPtr buf) +{ + xmlChar *ret; + + if (!buf) return NULL; + + ret = buf->content; + buf->content = NULL; + buf->use = buf->size = 0; + + return ret; +} + + +#if (LIBXML_VERSION < 20703) +xmlNodePtr xmlFirstElementChild(xmlNodePtr node) +{ + if (!node) return NULL; + + for (node = node->children; node; node = node->next) { + if (node->type == XML_ELEMENT_NODE) return (node); + } + + return NULL; +} + + +xmlNodePtr xmlNextElementSibling(xmlNodePtr node) +{ + if (!node) return NULL; + + for (node = node->next; node; node = node->next) { + if (node->type == XML_ELEMENT_NODE) return (node); + } + + return NULL; +} +#endif /* < 2.7.3 */ +#endif /* < 2.8.0 */
View file
cyrus-imapd-2.5.tar.gz/imap/xcal.h
Changed
@@ -64,7 +64,19 @@ int (*get_int)(void *), const char* (*get_str)(void *)); -extern const char *icalcomponent_as_xcal_string(icalcomponent* comp); +extern char *icalcomponent_as_xcal_string(icalcomponent* comp); extern icalcomponent *xcal_string_as_icalcomponent(const char *str); extern const char *begin_xcal(struct buf *buf); extern void end_xcal(struct buf *buf); + +/* libxml2 replacement functions for those missing in older versions */ +#if (LIBXML_VERSION < 20800) +#include <libxml/tree.h> + +extern xmlChar *xmlBufferDetach(xmlBufferPtr buf); + +#if (LIBXML_VERSION < 20703) +extern xmlNodePtr xmlFirstElementChild(xmlNodePtr parent); +extern xmlNodePtr xmlNextElementSibling(xmlNodePtr node); +#endif /* < 2.7.3 */ +#endif /* < 2.8.0 */
View file
cyrus-imapd-2.5.tar.gz/imap/zoneinfo_db.c
Added
@@ -0,0 +1,323 @@ +/* zoneinfo_db.c -- zoneinfo DB routines + * + * Copyright (c) 1994-2013 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Carnegie Mellon University + * Center for Technology Transfer and Enterprise Creation + * 4615 Forbes Avenue + * Suite 302 + * Pittsburgh, PA 15213 + * (412) 268-7393, fax: (412) 268-7395 + * innovation@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include <config.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> + +#include "assert.h" +#include "cyrusdb.h" +#include "exitcodes.h" +#include "global.h" +#include "tok.h" +#include "util.h" +#include "xmalloc.h" + +#include "zoneinfo_db.h" + +#define DB config_zoneinfo_db + +struct db *zoneinfodb; +static int zoneinfo_dbopen = 0; +static struct buf databuf = BUF_INITIALIZER; + +EXPORTED int zoneinfo_open(const char *fname) +{ + int ret; + char *tofree = NULL; + + if (!fname) fname = config_getstring(IMAPOPT_ZONEINFO_DB_PATH); + + /* create db file name */ + if (!fname) { + tofree = strconcat(config_dir, FNAME_ZONEINFODB, (char *)NULL); + fname = tofree; + } + + ret = cyrusdb_open(DB, fname, CYRUSDB_CREATE, &zoneinfodb); + if (ret != 0) { + syslog(LOG_ERR, "DBERROR: opening %s: %s", fname, + cyrusdb_strerror(ret)); + } + else zoneinfo_dbopen = 1; + + free(tofree); + + return ret; +} + +void zoneinfo_close(struct txn *tid) +{ + if (zoneinfo_dbopen) { + int r; + + if (tid) { + r = cyrusdb_commit(zoneinfodb, tid); + if (r) { + syslog(LOG_ERR, "DBERROR: error committing zoneinfo: %s", + cyrusdb_strerror(r)); + } + } + r = cyrusdb_close(zoneinfodb); + if (r) { + syslog(LOG_ERR, "DBERROR: error closing zoneinfo: %s", + cyrusdb_strerror(r)); + } + zoneinfo_dbopen = 0; + + buf_free(&databuf); + } +} + +void zoneinfo_done(void) +{ + /* DB->done() handled by cyrus_done() */ +} + +static int parse_zoneinfo(const char *data, int datalen, + struct zoneinfo *zi, int all) +{ + const char *dend = data + datalen; + unsigned version; + char *p; + + memset(zi, 0, sizeof(struct zoneinfo)); + + /* version SP type SP dtstamp SP (string *(TAB string)) */ + + version = strtoul(data, &p, 10); + if (version != ZONEINFO_VERSION) return CYRUSDB_IOERROR; + + if (p < dend) zi->type = strtoul(p, &p, 10); + if (p < dend) zi->dtstamp = strtol(p, &p, 10); + + if (all && p < dend) { + size_t len = dend - ++p; + char *str = xstrndup(p, len); + tok_t tok; + + tok_initm(&tok, str, "\t", TOK_FREEBUFFER); + while ((str = tok_next(&tok))) appendstrlist(&zi->data, str); + tok_fini(&tok); + } + + return 0; +} + +EXPORTED int zoneinfo_lookup(const char *tzid, struct zoneinfo *zi) +{ + const char *data = NULL; + size_t datalen; + int r; + + /* Don't access DB if it hasn't been opened */ + if (!zoneinfo_dbopen) return CYRUSDB_INTERNAL; + + assert(tzid); + + /* Check if there is an entry in the database */ + do { + r = cyrusdb_fetch(zoneinfodb, tzid, strlen(tzid), &data, &datalen, NULL); + } while (r == CYRUSDB_AGAIN); + + if (r || !data || (datalen < 6)) return r ? r : CYRUSDB_IOERROR; + + return parse_zoneinfo(data, datalen, zi, 1); +} + +EXPORTED int zoneinfo_store(const char *tzid, struct zoneinfo *zi, struct txn **tid) +{ + struct strlist *sl; + const char *sep; + int r; + + /* Don't access DB if it hasn't been opened */ + if (!zoneinfo_dbopen) return CYRUSDB_INTERNAL; + + assert(tzid && zi); + + /* version SP type SP dtstamp SP (string *(TAB string)) */ + buf_reset(&databuf); + buf_printf(&databuf, "%u %u %ld ", ZONEINFO_VERSION, zi->type, zi->dtstamp); + for (sl = zi->data, sep = ""; sl; sl = sl->next, sep = "\t") + buf_printf(&databuf, "%s%s", sep, sl->s); + + r = cyrusdb_store(zoneinfodb, tzid, strlen(tzid), + buf_cstring(&databuf), buf_len(&databuf), tid); + + if (r != CYRUSDB_OK) { + syslog(LOG_ERR, "DBERROR: error updating zoneinfo: %s (%s)", + tzid, cyrusdb_strerror(r)); + }
View file
cyrus-imapd-2.5.tar.gz/imap/zoneinfo_db.h
Added
@@ -0,0 +1,97 @@ +/* zoneinfo_db.h -- zoneinfo DB routines + * + * Copyright (c) 1994-2013 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Carnegie Mellon University + * Center for Technology Transfer and Enterprise Creation + * 4615 Forbes Avenue + * Suite 302 + * Pittsburgh, PA 15213 + * (412) 268-7393, fax: (412) 268-7395 + * innovation@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifndef ZONEINFO_DB_H +#define ZONEINFO_DB_H + +#include <time.h> + +#include "annotate.h" /* for strlist functionality */ + +/* name of the zoneinfo directory */ +#define FNAME_ZONEINFODIR "/zoneinfo" + +/* name of the zoneinfo database */ +#define FNAME_ZONEINFODB "/zoneinfo.db" +#define ZONEINFO_VERSION 1 + +#define INFO_TZID ".info" +#define zoneinfo_lookup_info(zi) zoneinfo_lookup(INFO_TZID, zi) + +struct zoneinfo { + unsigned type; + time_t dtstamp; + struct strlist *data; +}; + +/* zoneinfo record types */ +enum { + ZI_ZONE = 0, + ZI_LINK, + ZI_INFO +}; + +/* open the zoneinfo db */ +extern int zoneinfo_open(const char *name); + +/* lookup a single zoneinfo entry and return result, or error if it + doesn't exist or doesn't have the fields we need */ +extern int zoneinfo_lookup(const char *tzid, struct zoneinfo *zi); + +/* store a zoneinfo entry */ +extern int zoneinfo_store(const char *tzid, struct zoneinfo *zi, + struct txn **tid); + +/* process all zoneinfo entries (optionally matching 'find') */ +extern int zoneinfo_find(const char *find, int tzid_only, time_t changedsince, + int (*proc)(const char *tzid, int tzidlen, + struct zoneinfo *zi, void *rock), + void *rock); + +/* close the database (optionally committing txn) */ +extern void zoneinfo_close(struct txn *tid); + +/* done with database stuff */ +extern void zoneinfo_done(void); + +#endif /* ZONEINFO_DB_H */
View file
cyrus-imapd-2.5.tar.gz/lib/imapoptions
Changed
@@ -297,8 +297,10 @@ layers of MIME structure. The default of 1000 is much higher than any sane message should have. */ -{ "caldav_allowscheduling", 1, SWITCH } -/* If enabled, the server will perform calendar scheduling operations. */ +{ "caldav_allowscheduling", "on", ENUM("off", "on", "apple") } +/* Enable calendar scheduling operations. If set to "apple", the + server will emulate Apple CalendarServer behavior as closely as + possible. */ { "caldav_realm", NULL, STRING } /* The realm to present for HTTP authentication of CalDAV resources. @@ -503,10 +505,10 @@ /* Don't send event notification for folder with given special-use attributes. Set ALL for any folder */ -{ "event_extra_params", "timestamp", BITFIELD("bodyStructure", "clientAddress", "diskUsed", "flagNames", "messageContent", "messageSize", "messages", "modseq", "service", "timestamp", "uidnext", "vnd.cmu.midset", "vnd.cmu.unseenMessages", "vnd.cmu.envelope", "vnd.fastmail.clientId", "vnd.fastmail.sessionId", "vnd.fastmail.convExists", "vnd.fastmail.convUnseen", "vnd.fastmail.cid", "vnd.cmu.mbtype", "vnd.cmu.davFilename", "vnd.cmu.davUid") } -/* Space-separated list of extra parameters to add to any appropriated event. */ +{ "event_extra_params", "timestamp", BITFIELD("bodyStructure", "clientAddress", "diskUsed", "flagNames", "messageContent", "messageSize", "messages", "modseq", "service", "timestamp", "uidnext", "vnd.cmu.midset", "vnd.cmu.unseenMessages", "vnd.cmu.envelope", "vnd.cmu.mbtype", "vnd.cmu.davFilename", "vnd.cmu.davUid", "vnd.fastmail.clientId", "vnd.fastmail.sessionId", "vnd.fastmail.convExists", "vnd.fastmail.convUnseen", "vnd.fastmail.cid") } +/* Space-separated list of extra parameters to add to any appropriated event. */ -{ "event_groups", "message mailbox", BITFIELD("message", "quota", "flags", "access", "mailbox") } +{ "event_groups", "message mailbox", BITFIELD("message", "quota", "flags", "access", "mailbox", "subscription") } /* Space-separated list of groups of related events to turn on notification */ { "event_notifier", NULL, STRING } @@ -640,7 +642,7 @@ provisional responses every \fIhttpkeepalive\fR seconds until the final response can be sent */ -{ "httpmodules", "", BITFIELD("caldav", "carddav", "domainkey", "ischedule", "rss") } +{ "httpmodules", "", BITFIELD("caldav", "carddav", "domainkey", "ischedule", "rss", "timezone") } /* Space-separated list of HTTP modules that will be enabled in httpd(8). This option has no effect on modules that are disabled at compile time due to missing dependencies (e.g. libical). */ @@ -724,6 +726,21 @@ { "ldap_deref", "never", STRINGLIST("search", "find", "always", "never") } /* Specify how aliases dereferencing is handled during search. */ +{ "ldap_domain_base_dn", "", STRING } +/* Base DN to search for domain name spaces. */ + +{ "ldap_domain_filter", "(&(objectclass=domainrelatedobject)(associateddomain=%s))", STRING } +/* Filter to use searching for domains */ + +{ "ldap_domain_name_attribute", "associateddomain", STRING } +/* The attribute name for domains. */ + +{ "ldap_domain_scope", "sub", STRINGLIST("sub", "one", "base") } +/* Search scope */ + +{ "ldap_domain_result_attribute", "inetdomainbasedn", STRING } +/* Result attribute */ + { "ldap_filter", "(uid=%u)", STRING } /* Specify a filter that searches user identifiers. The following tokens can be used in the filter string: @@ -964,7 +981,7 @@ { "mboxname_lockpath", NULL, STRING } /* Path to mailbox name lock files (default $conf/lock) */ -{ "metapartition_files", "", BITFIELD("header", "index", "cache", "expunge", "squat", "annotations", "lock", "archivecache") } +{ "metapartition_files", "", BITFIELD("header", "index", "cache", "expunge", "squat", "annotations", "lock", "dav", "archivecache") } /* Space-separated list of metadata files to be stored on a \fImetapartition\fR rather than in the mailbox directory on a spool partition. */ @@ -1464,8 +1481,13 @@ { "servername", NULL, STRING } /* This is the hostname visible in the greeting messages of the POP, IMAP and LMTP daemons. If it is unset, then the result returned - from gethostname(2) is used. */ - + from gethostname(2) is used. This is also the value used by murder + clusters to identify the host name. It should be resolvable by + DNS to the correct host, and unique within an active cluster. If + you are using low level replication (e.g. drbd) then it should be + the same on each copy and the DNS name should also be moved to + the new master on failover. */ + { "serverinfo", "on", ENUM("off", "min", "on") } /* The server information to display in the greeting and capability responses. Information is displayed as follows: @@ -1811,6 +1833,13 @@ { "defaultsearchtier", "", STRING } /* Name of the default tier that messages will be indexed to */ +{ "zoneinfo_db", "skiplist", STRINGLIST("flat", "berkeley", "berkeley-hash", "skiplist")} +/* The cyrusdb backend to use for zoneinfo. */ + +{ "zoneinfo_db_path", NULL, STRING } +/* The absolute path to the zoneinfo db file. If not specified, + will be confdir/zoneinfo.db */ + /* .SH SEE ALSO .PP
View file
cyrus-imapd-2.5.tar.gz/lib/retry.c
Changed
@@ -48,6 +48,7 @@ #include <unistd.h> #endif +#include "exitcodes.h" #include "retry.h" #include "xmalloc.h" @@ -114,7 +115,8 @@ int i; ssize_t n; size_t written = 0; - struct iovec *iov, *baseiov; + size_t len = 0; + struct iovec *iov, *baseiov = NULL; static int iov_max = #ifdef MAXIOV MAXIOV @@ -130,6 +132,17 @@ if (!iovcnt) return 0; + for (i = 0; i < iovcnt; i++) { + len += srciov[i].iov_len; + } + + n = written = writev(fd, srciov, iovcnt > iov_max ? iov_max : iovcnt); + + /* did we get lucky and write it all? */ + if (written == len) + return written; + + /* oh well, welcome to the slow path - we have copies */ baseiov = iov = (struct iovec *)xmalloc(iovcnt * sizeof(struct iovec)); for (i = 0; i < iovcnt; i++) { iov[i].iov_base = srciov[i].iov_base; @@ -137,13 +150,18 @@ } for (;;) { - while (iovcnt && iov[0].iov_len == 0) { + for (i = 0; i < iovcnt; i++) { + if (iov[i].iov_len > (size_t)n) { + iov[i].iov_base += n; + iov[i].iov_len -= n; + break; + } + n -= iov[i].iov_len; iov++; iovcnt--; + if (!iovcnt) fatal("ran out of iov", EC_SOFTWARE); } - if (!iovcnt) break; - n = writev(fd, iov, iovcnt > iov_max ? iov_max : iovcnt); if (n == -1) { if (errno == EINVAL && iov_max > 10) { @@ -157,17 +175,7 @@ written += n; - for (i = 0; i < iovcnt; i++) { - if (iov[i].iov_len > (size_t)n) { - iov[i].iov_base = (char *)iov[i].iov_base + n; - iov[i].iov_len -= n; - break; - } - n -= iov[i].iov_len; - iov[i].iov_len = 0; - } - - if (i == iovcnt) break; + if (written == len) break; } free(baseiov);
View file
cyrus-imapd-2.5.tar.gz/lib/util.c
Changed
@@ -266,6 +266,17 @@ (b == NULL ? "" : b)); } +/* in which NULL is NOT equal to "" */ +EXPORTED int strcmpnull(const char *a, const char *b) +{ + if (a) { + if (b) return strcmp(a, b); + return 1; + } + if (b) return -1; + return 0; +} + /* do a binary search in a keyvalue array * nelem is the number of keyvalue elements in the kv array @@ -821,24 +832,23 @@ } /* this function has a side-effect of always leaving the buffer writable */ -EXPORTED void buf_ensure(struct buf *buf, size_t n) +EXPORTED void _buf_ensure(struct buf *buf, size_t n) { - size_t newalloc = roundup(buf->len + n); + size_t newlen = buf->len + n; + char *s; - /* can't create a zero byte buffer */ - assert(newalloc); + assert(newlen); /* we never alloc zero bytes */ - /* protect against wrap */ - assert(newalloc >= buf->len); - - if (buf->alloc >= newalloc) + if (buf->alloc >= newlen) return; if (buf->alloc) { - buf->s = xrealloc(buf->s, newalloc); + buf->alloc = roundup(newlen); + buf->s = xrealloc(buf->s, buf->alloc); } else { - char *s = xmalloc(newalloc); + buf->alloc = roundup(newlen); + s = xmalloc(buf->alloc); /* if no allocation, but data exists, it means copy on write. * grab a copy of what's there now */ @@ -847,32 +857,31 @@ memcpy(s, buf->s, buf->len); } - /* can release MMAP now, we've already copied the data out */ + /* can release MMAP now, we've copied the data out */ if (buf->flags & BUF_MMAP) { - const char *base = buf->s; - size_t len = buf->len; - map_free(&base, &len); + size_t len = buf->len; /* don't wipe the length, we still need it */ + map_free((const char **)&buf->s, &len); buf->flags &= ~BUF_MMAP; } buf->s = s; } - - /* either way, our allocated space is now this long */ - buf->alloc = newalloc; } EXPORTED const char *buf_cstring(struct buf *buf) { - if (!(buf->flags & BUF_CSTRING) || buf->s == NULL) { - buf_ensure(buf, 1); - buf->s[buf->len] = '\0'; - buf->flags |= BUF_CSTRING; - } - + buf_ensure(buf, 1); + buf->s[buf->len] = '\0'; return buf->s; } +EXPORTED char *buf_newcstring(struct buf *buf) +{ + char *ret = xstrdup(buf_cstring(buf)); + buf_reset(buf); + return ret; +} + EXPORTED char *buf_release(struct buf *buf) { char *ret = (char *)buf_cstring(buf); @@ -935,8 +944,10 @@ EXPORTED void buf_reset(struct buf *buf) { + if (buf->flags & BUF_MMAP) + map_free((const char **)&buf->s, &buf->len); buf->len = 0; - buf->flags &= ~BUF_CSTRING; + buf->flags = 0; } EXPORTED void buf_truncate(struct buf *buf, size_t len) @@ -948,7 +959,6 @@ memset(buf->s + buf->len, 0, more); } buf->len = len; - buf->flags &= ~BUF_CSTRING; } EXPORTED void buf_setcstr(struct buf *buf, const char *str) @@ -993,7 +1003,6 @@ buf_ensure(buf, len); memcpy(buf->s + buf->len, base, len); buf->len += len; - buf->flags &= ~BUF_CSTRING; } } @@ -1020,13 +1029,6 @@ } } -EXPORTED void buf_putc(struct buf *buf, char c) -{ - buf_ensure(buf, 1); - buf->s[buf->len++] = c; - buf->flags &= ~BUF_CSTRING; -} - EXPORTED void buf_vprintf(struct buf *buf, const char *fmt, va_list args) { va_list ap; @@ -1052,9 +1054,6 @@ va_end(ap); buf->len += n; - /* vsnprintf() gave us a trailing NUL, so we may as well remember - * that for later */ - buf->flags |= BUF_CSTRING; } EXPORTED void buf_printf(struct buf *buf, const char *fmt, ...) @@ -1066,18 +1065,6 @@ va_end(args); } -static void buf_writable_cstring(struct buf *buf) -{ - if ((buf->flags & BUF_CSTRING) && !buf->alloc) { - /* has a \0 terminator but not writable: force - * re-allocation of the data and initialisation - * of the terminator */ - buf->flags &= ~BUF_CSTRING; - } - buf_cstring(buf); - assert(buf->alloc > 0); -} - static void buf_replace_buf(struct buf *buf, size_t offset, size_t length, @@ -1088,7 +1075,7 @@ length = buf->len - offset; /* we need buf to be a writable C string now please */ - buf_writable_cstring(buf); + buf_cstring(buf); if (replace->len > length) { /* string will need to expand */ @@ -1142,7 +1129,7 @@ size_t i; /* we need writable, so may as well cstring it */ - buf_writable_cstring(buf); + buf_cstring(buf); for (i = 0; i < buf->len; i++) { if (buf->s[i] == match) { @@ -1300,7 +1287,7 @@ { buf->alloc = 0; buf->len = (str ? strlen(str) : 0); - buf->flags = (str ? BUF_CSTRING : 0); + buf->flags = 0; buf->s = (char *)str; } @@ -1321,11 +1308,8 @@ { if (buf->alloc) free(buf->s); - else if (buf->flags & BUF_MMAP) {
View file
cyrus-imapd-2.5.tar.gz/lib/util.h
Changed
@@ -141,6 +141,9 @@ /* ditto strncmp */ int strncmpsafe(const char *a, const char *b, size_t n); +/* NULL isn't "" */ +int strcmpnull(const char *a, const char *b); + /* do a binary search in a keyvalue array * nelem is the number of keyvalue elements in the kv array * cmpf is the comparison function (strcmp, stricmp, etc). @@ -220,7 +223,6 @@ extern clock_t sclock(void); -#define BUF_CSTRING (1<<0) #define BUF_MMAP (1<<1) struct buf { @@ -231,11 +233,15 @@ }; #define BUF_INITIALIZER { NULL, 0, 0, 0 } +#define buf_ensure(b, n) do { if ((b)->alloc < (b)->len + (n)) _buf_ensure((b), (n)); } while (0) +#define buf_putc(b, c) do { buf_ensure((b), 1); (b)->s[(b)->len++] = (c); } while (0) + +void _buf_ensure(struct buf *buf, size_t len); const char *buf_cstring(struct buf *buf); const char *buf_cstringnull(struct buf *buf); char *buf_release(struct buf *buf); +char *buf_newcstring(struct buf *buf); char *buf_releasenull(struct buf *buf); -void buf_ensure(struct buf *buf, size_t morebytes); void buf_getmap(struct buf *buf, const char **base, size_t *len); int buf_getline(struct buf *buf, FILE *fp); size_t buf_len(const struct buf *buf); @@ -254,7 +260,6 @@ void buf_insert(struct buf *dst, unsigned int off, const struct buf *src); void buf_insertcstr(struct buf *buf, unsigned int off, const char *str); void buf_insertmap(struct buf *buf, unsigned int off, const char *base, int len); -void buf_putc(struct buf *buf, char c); void buf_vprintf(struct buf *buf, const char *fmt, va_list args); void buf_printf(struct buf *buf, const char *fmt, ...) __attribute__((format(printf,2,3)));
View file
cyrus-imapd-2.5.tar.gz/man/ctl_zoneinfo.8
Added
@@ -0,0 +1,86 @@ +.\" -*- nroff -*- +.TH CTL_ZONEINFO 8 "Project Cyrus" CMU +.\" +.\" Copyright (c) 1994-2013 Carnegie Mellon University. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" 3. The name "Carnegie Mellon University" must not be used to +.\" endorse or promote products derived from this software without +.\" prior written permission. For permission or any legal +.\" details, please contact +.\" Carnegie Mellon University +.\" Center for Technology Transfer and Enterprise Creation +.\" 4615 Forbes Avenue +.\" Suite 302 +.\" Pittsburgh, PA 15213 +.\" (412) 268-7393, fax: (412) 268-7395 +.\" innovation@andrew.cmu.edu + * +.\" 4. Redistributions of any form whatsoever must retain the following +.\" acknowledgment: +.\" "This product includes software developed by Computing Services +.\" at Carnegie Mellon University (http://www.cmu.edu/computing/)." +.\" +.\" CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO +.\" THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +.\" AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE +.\" FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN +.\" AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.SH NAME +ctl_zoneinfo \- perform operations on the zoneinfo database +.SH SYNOPSIS +.B ctl_zoneinfo +[ +.B \-C +.I config-file +] +[ +.B \-v +] +.B \-r +.I version-string +.SH DESCRIPTION +.I Ctl_zoneinfo +is used to perform various administrative operations on the zoneinfo +database. +.PP +.I Ctl_zoneinfo +reads its configuration options out of the +.IR imapd.conf (5) +file unless specified otherwise by \fB-C\fR. +.SH OPTIONS +.TP +.BI \-C " config-file" +Read configuration options from \fIconfig-file\fR. +.TP +.B \-v +Enable verbose output. +.TP +.BI \-r " version-string" +Rebuild the zoneinfo database based on the directory structure of +\fIconfigdirectory\fB/zoneinfo\fR. The database to be rebuilt will be +in the default location of \fIconfigdirectory\fB/zoneinfo.db\fR unless +otherwise specified by the \fIzoneinfo_db_path\fR option in +\fBimapd.conf\fR. The \fIversion-string\fR should describe the source +of the timezone data (e.g. "Olson 2013h") and will be used by the +\fItimezone\fR module of \fBhttpd\fR. +.SH FILES +.TP +.B /etc/imapd.conf +.SH SEE ALSO +.PP +\fBimapd.conf(5)\fR, \fBmaster(8)\fR, \fBhttpd(8)\fR
View file
cyrus-imapd-2.5.tar.gz/notifyd/notify_external.c
Changed
@@ -61,10 +61,10 @@ const char *user, const char *mailbox, int nopt __attribute__((unused)), char **options __attribute__((unused)), - const char *message) + const char *message, const char *fname) { const char *notify; - const char *buf[10]; + const char *buf[12]; int fds[2], status; pid_t child_pid; FILE *stream; @@ -89,7 +89,9 @@ buf[6] = user; buf[7] = "-m"; buf[8] = mailbox; - buf[9] = NULL; + buf[9] = "-f"; + buf[10] = fname; + buf[11] = NULL; if (pipe(fds) < 0) { syslog(LOG_ERR,
View file
cyrus-imapd-2.5.tar.gz/notifyd/notify_external.h
Changed
@@ -49,7 +49,8 @@ char* notify_external(const char *class, const char *priority, const char *user, const char *mailbox, - int nopt, char **options, const char *message); + int nopt, char **options, + const char *message, const char *fname); #endif /* _NOTIFY_EXTERNAL_H */
View file
cyrus-imapd-2.5.tar.gz/notifyd/notify_log.c
Changed
@@ -51,7 +51,8 @@ char* notify_log(const char *class, const char *priority, const char *user, const char *mailbox, int nopt, char **options, - const char *message) + const char *message, + const char *fname __attribute__((unused))) { char opt_str[1024] = ""; char *sep = "";
View file
cyrus-imapd-2.5.tar.gz/notifyd/notify_log.h
Changed
@@ -48,6 +48,6 @@ char* notify_log(const char *class, const char *priority, const char *user, const char *mailbox, int nopt, char **options, - const char *message); + const char *message, const char *fname); #endif /* _NOTIFY_LOG_H_ */
View file
cyrus-imapd-2.5.tar.gz/notifyd/notify_mailto.c
Changed
@@ -65,7 +65,8 @@ const char *user __attribute__((unused)), const char *mailbox __attribute__((unused)), int nopt, char **options, - const char *message) + const char *message, + const char *fname __attribute__((unused))) { FILE *sm; const char *smbuf[7]; @@ -109,14 +110,14 @@ return strdup("NO mailto could not spawn sendmail process"); t = time(NULL); - snprintf(outmsgid, sizeof(outmsgid), "<cmu-sieve-%d-%lu-%d@%s>", + snprintf(outmsgid, sizeof(outmsgid), "<cmu-sieve-%d-%lu-%d@%s>", (int) sm_pid, t, global_outgoing_count++, config_servername); - + fprintf(sm, "Message-ID: %s\r\n", outmsgid); time_to_rfc822(t, datestr, sizeof(datestr)); fprintf(sm, "Date: %s\r\n", datestr); - + fprintf(sm, "X-Sieve: %s\r\n", SIEVE_VERSION); fprintf(sm, "From: Mail Sieve Subsystem <%s>\r\n", config_getstring(IMAPOPT_POSTMASTER)); fprintf(sm, "To: <%s>\r\n", options[0]); @@ -146,7 +147,7 @@ if (msg) { const unsigned char *s = (const unsigned char *)msg; - + while (*s) { if (0 != (*s & 0x80)) { result = 1;
View file
cyrus-imapd-2.5.tar.gz/notifyd/notify_mailto.h
Changed
@@ -46,11 +46,9 @@ #include <config.h> /* the only option should be a mailto URI */ -char* notify_mailto(const char *class __attribute__((unused)), - const char *priority __attribute__((unused)), - const char *user __attribute__((unused)), - const char *mailbox __attribute__((unused)), +char* notify_mailto(const char *class, const char *priority, + const char *user, const char *mailbox, int nopt, char **options, - const char *message); + const char *message, const char *fname); #endif /* _NOTIFY_MAILTO_H_ */
View file
cyrus-imapd-2.5.tar.gz/notifyd/notify_null.c
Changed
@@ -52,7 +52,8 @@ const char *mailbox __attribute__((unused)), int nopt __attribute__((unused)), char **options __attribute__((unused)), - const char *message __attribute__((unused))) + const char *message __attribute__((unused)), + const char *fname __attribute__((unused))) { return strdup("OK null notification successful"); }
View file
cyrus-imapd-2.5.tar.gz/notifyd/notify_null.h
Changed
@@ -45,12 +45,9 @@ #include <config.h> -char* notify_null(const char *class __attribute__((unused)), - const char *priority __attribute__((unused)), - const char *user __attribute__((unused)), - const char *mailbox __attribute__((unused)), - int nopt __attribute__((unused)), - char **options __attribute__((unused)), - const char *message __attribute__((unused))); +char* notify_null(const char *class, const char *priority, + const char *user, const char *mailbox, + int nopt, char **options, + const char *message, const char *fname); #endif /* _NOTIFY_NULL_H_ */
View file
cyrus-imapd-2.5.tar.gz/notifyd/notify_zephyr.c
Changed
@@ -73,7 +73,8 @@ char* notify_zephyr(const char *class, const char *priority, const char *user, const char *mailbox, int nopt, char **options, - const char *message) + const char *message, + const char *fname __attribute__((unused))) { ZNotice_t notice; int retval;
View file
cyrus-imapd-2.5.tar.gz/notifyd/notify_zephyr.h
Changed
@@ -49,6 +49,6 @@ char* notify_zephyr(const char *class, const char *priority, const char *user, const char *mailbox, int nopt, char **options, - const char *message); + const char *message, const char *fname); #endif /* _NOTIFY_ZEPHYR_H_ */
View file
cyrus-imapd-2.5.tar.gz/notifyd/notifyd.c
Changed
@@ -107,6 +107,7 @@ strarray_t options = STRARRAY_INITIALIZER; long nopt; char *reply; + char *fname; notifymethod_t *nmethod; while (1) { @@ -147,6 +148,7 @@ strarray_appendm(&options, cp = fetch_arg(cp, tail)); if (cp) message = (cp = fetch_arg(cp, tail)); + if (cp) fname = (cp = fetch_arg(cp, tail)); if (!message) { syslog(LOG_ERR, "malformed notify request"); @@ -169,7 +171,7 @@ if (nmethod->name) { reply = nmethod->notify(class, priority, user, mailbox, - nopt, options.data, message); + nopt, options.data, message, fname); } #if 0 /* we don't care about responses right now */ else {
View file
cyrus-imapd-2.5.tar.gz/notifyd/notifyd.h
Changed
@@ -54,7 +54,7 @@ char *(*notify)(const char *class, const char *priority, const char *user, const char *mailbox, int nopt, char **options, - const char *message); /* notification function */ + const char *message, const char *fname); /* notification function */ } notifymethod_t; /* array of supported notification methods */
View file
cyrus-imapd-2.5.tar.gz/perl/imap/Cyrus/CacheFile.pm
Added
@@ -0,0 +1,212 @@ +#!/usr/bin/perl -c + +package Cyrus::CacheFile; + +use strict; +use warnings; + +use IO::File; +use IO::File::fcntl; +use IO::Handle; +use File::Temp; +use YAML; + +=pod + +=head1 NAME + +Cyrus::CacheFile - A pure perl interface to the "cyrus.cache" file +format as generated by Cyrus IMAPd. + +=head1 EXAMPLES + +XXX: document. + +See examples/index_uids.pl for some usage + +=cut + +# /* Access assistance macros for memory-mapped cache file data */ +# /* CACHE_ITEM_BIT32: Convert to host byte order */ +# /* CACHE_ITEM_LEN: Get the length out */ +# /* CACHE_ITEM_NEXT: Return a pointer to the next entry. Sizes are +# * 4-byte aligned, so round up to the next 4 byte boundry */ +# #define CACHE_ITEM_BIT32(ptr) (ntohl(*((bit32 *)(ptr)))) +# #define CACHE_ITEM_LEN(ptr) CACHE_ITEM_BIT32(ptr) +# #define CACHE_ITEM_NEXT(ptr) ((ptr)+4+((3+CACHE_ITEM_LEN(ptr))&~3)) + +# #define MAILBOX_CACHE_MINOR_VERSION 2 +# #define NUM_CACHE_FIELDS 10 + +our $NUM_CACHE_FIELDS = 10; +our @NAMES = qw( + ENVELOPE + BODYSTRUCTURE + BODY + SECTION + HEADERS + FROM + TO + CC + BCC + SUBJECT +); + +# PUBLIC API + +sub new { + my $class = shift; + my $handle = shift; + + # read header + my $buf; + # XXX - check for success! + sysread($handle, $buf, 4); + my $version = unpack('N', $buf); + my $Self = bless { version => $version, handle => $handle, offset => 4 }, ref($class) || $class; + return $Self; +} + +sub new_file { + my $class = shift; + my $file = shift; + my $lockopts = shift; + + my $fh; + if ($lockopts) { + $lockopts = ['lock_ex'] unless ref($lockopts) eq 'ARRAY'; + $fh = IO::File::fcntl->new($file, '+<', @$lockopts) + || die "Can't open $file for locked read: $!"; + } else { + $fh = IO::File->new("< $file") + || die "Can't open $file for read: $!"; + } + + return $class->new($fh); +} + +sub next_record { + my $Self = shift; + my $buf; + + my @record; + my $size = 0; + for (1..$NUM_CACHE_FIELDS) { + sysread($Self->{handle}, $buf, 4); + return undef unless $buf; + my $num = unpack('N', $buf); + my $bytes = $num; + $bytes += 4 - $num % 4 if $num % 4; # offsets are multiple of 4 bytes + sysread($Self->{handle}, $buf, $bytes); + push @record, [$num, $bytes, $buf]; + $size += $bytes + 4; + } + + my $ret = { + size => $size, + records => \@record, + }; + + $Self->{record} = $ret; + $Self->{offset} += $size; + + return $ret; +} + +sub record { + my $Self = shift; + my $Field = shift; + + return undef unless ($Self->{record}); + + if ($Field) { + return $Self->{record}{$Field}; + } + return $Self->{record}; +} + +sub offset { + my $Self = shift; + + if (@_) { + my $spot = shift; + seek($Self->{handle}, $spot, 0); + $Self->{offset} = $spot; + } + + return $Self->{offset}; +} + +sub dump { + my $Self = shift; + + while (my $rec = $Self->next_record()) { + $Self->dump_record($rec); + } +} + +sub dump_record { + my $Self = shift; + my $rec = shift || $Self->{record}; + return unless $rec; + print Dump($rec->{records}); +} + +sub print_record { + my $Self = shift; + my $rec = shift || $Self->{record}; + return unless $rec; + foreach my $rnum (0..$NUM_CACHE_FIELDS-1) { + my $record = $rec->{records}[$rnum]; + my $str = substr($record->[2], 0, $record->[0]); + if ($rnum == 3) { # section + my @items = unpack('N*', $str); + $str = parse_section(0, \@items); + } + print "$NAMES[$rnum]: $str\n"; + } +} + +sub parse_section { + my $part = shift; + my $items = shift; + my $num_parts = shift @$items; + if ($num_parts == 0) { + return "$part:()"; + } + my $ret = "$part:(" . parse_item($items); + my $n = 1; + while ($n < $num_parts) { + my $subpart = $part ? "$part.$n" : $n; + $ret .= " " . parse_item($items); + $n++; + } + $n = 1; + $ret .= ")"; + while ($n < $num_parts) { + my $subpart = $part ? "$part.$n" : $n; + $ret .= " " . parse_section($subpart, $items); + $n++; + } + return $ret; +} + +sub parse_item { + my $items = shift; + my $header_offset = shift @$items; + my $header_size = shift @$items; + my $content_offset = shift @$items; + my $content_size = shift @$items;
View file
cyrus-imapd-2.5.tar.gz/perl/imap/Cyrus/HeaderFile.pm
Added
@@ -0,0 +1,175 @@ +#!/usr/bin/perl -c + +# Package to handle Cyrus Header files + +package Cyrus::HeaderFile; + +use strict; +use warnings; + +use IO::File; +use IO::File::fcntl; +use IO::Handle; +use File::Temp; +use Data::Dumper; + +=pod + +=head1 NAME + +Cyrus::HeaderFile - A pure perl interface to the "cyrus.header" file +format as generated by Cyrus IMAPd. + +=head1 EXAMPLES + +Like Cyrus::IndexFile, uses fcntl locking (default for Cyrus on systems +which support it) + +my $header = Cyrus::HeaderFile->new_file("path/to/cyrus.header"); + +XXX: see index_uids.pl + +=cut + +our $HL1 = qq{\241\002\213\015Cyrus mailbox header}; +our $HL2 = qq{"The best thing about this system was that it had lots of goals."}; +our $HL3 = qq{\t--Jim Morris on Andrew}; + +=head1 PUBLIC API + +=over + +=item Cyrus::HeaderFile->new($fh) + +Read the header file in $fh + +=cut + +sub new { + my $class = shift; + my $handle = shift; + + # read header + local $/ = undef; + my $body = <$handle>; + + my $Self = bless {}, ref($class) || $class; + $Self->{handle} = $handle; # keep for locking + $Self->{rawheader} = $body; + $Self->{header} = $Self->parse_header($body); + + return $Self; +} + +=item Cyrus::HeaderFile->new_file($fname, $lockopts) + +Open the file to read, optionally locking it with IO::File::fcntl. If you +pass a scalar for lockopts then it will be locked with ['lock_ex'], otherwise +you can pass a tuple, e.g. ['lock_ex', 5] for a 5 second timeout. + +This function will die if it can't open or lock the file. On success, it +calls $class->new() with the filehandle. + +=cut + +sub new_file { + my $class = shift; + my $file = shift; + my $lockopts = shift; + + my $fh; + if ($lockopts) { + $lockopts = ['lock_ex'] unless ref($lockopts) eq 'ARRAY'; + $fh = IO::File::fcntl->new($file, '+<', @$lockopts) + || die "Can't open $file for locked read: $!"; + } else { + $fh = IO::File->new("< $file") + || die "Can't open $file for read: $!"; + } + + return $class->new($fh); +} + +=item $header->header([$Field]) + +Return the entire header as a hash, or individual named field. + +=cut + +sub header { + my $Self = shift; + my $Field = shift; + + if ($Field) { + return $Self->{header}{$Field}; + } + + return $Self->{header}; +} + +=item $header->write_header($fh, $headerData) + +Write a header file with the data (e.g. returned from ->header()) +to the given filehandle. + +=cut + +sub write_header { + my $Self = shift; + my $fh = shift; + my $header = shift || $Self->header(); + + $fh->print($Self->make_header($header)); +} + +sub make_header { + my $Self = shift; + my $ds = shift || $Self->header(); + + # NOTE: acl and flags should have '' as the last element! + my $flags = join(" ", @{$ds->{Flags}}, ''); + my $acl = join("\t", @{$ds->{ACL}}, ''); + my $buf = <<EOF; +$HL1 +$HL2 +$HL3 +$ds->{QuotaRoot} $ds->{UniqueId} +$flags +$acl +EOF + return $buf; +} + +sub parse_header { + my $Self = shift; + my $body = shift; + + my @lines = split /\n/, $body; + + die "Not a mailbox header file" unless $lines[0] eq $HL1; + die "Not a mailbox header file" unless $lines[1] eq $HL2; + die "Not a mailbox header file" unless $lines[2] eq $HL3; + my ($quotaroot, $uniqueid) = split /\t/, $lines[3]; + my (@flags) = split / /, $lines[4]; + my (@acl) = split /\t/, $lines[5]; + + return { + QuotaRoot => $quotaroot, + UniqueId => $uniqueid, + Flags => \@flags, + ACL => \@acl, + }; +} + +=back + +=head1 AUTHOR AND COPYRIGHT + +Bron Gondwana <brong@fastmail.fm> - Copyright 2008 FastMail + +Licenced under the same terms as Cyrus IMAPd. + +=cut + + +1;
View file
cyrus-imapd-2.5.tar.gz/perl/imap/Cyrus/IndexFile.pm
Added
@@ -0,0 +1,1472 @@ +#!/usr/bin/perl -c + +package Cyrus::IndexFile; + +use strict; +use warnings; + +use IO::File; +use IO::Handle; +use String::CRC32 qw(crc32); + +=pod + +=head1 NAME + +Cyrus::IndexFile - A pure perl interface to the "cyrus.index" file +format as generated by Cyrus IMAPd. + +=head1 EXAMPLES + + use Cyrus::IndexFile; + + # Note: requires IO::File::fcntl module installed for locking support + my $index = Cyrus::IndexFile->new_file("$path/cyrus.index", ['lock_ex', 5]); + + print "EXISTS: " . $index->header('Exists') . "\n"; + while (my $record = $index->next_record_hash()) { + print "$record->{Uid}: $record->{MessageGuid} $record->{Size}\n"; + } + +=head1 SUPPORTED FORMAT VERSIONS + + Definitions: + ============ + + * int32 4 - 32 bit value taking 4 octets on disk. Visible in perl as an integer + * int64 8 - 64 bit value taking 8 octets on disk. Visible in perl as an integer + * time_t 4 - same as int32 + * bitmap N - a bitmap taking up N octets on disk. Visible in perl as a string of 1s and 0s. + * hex N - a big value taking up N octets on disk. Visible in perl as a hexadecimal string (0-9a-f) + + These values can be referenced by name using the hash API, or by index using the array API. + You can also use the 'raw' API to get the record in on-disk format. + + All numbers are in network byte order as per Cyrus standard encoding. Bitmap and hex values are + layed out as octets on disk and encoded directly in order. + + Version 9: + ========== + + Header: + 0: Generation int32 4 + 1: Format int32 4 + 2: MinorVersion int32 4 + 3: StartOffset int32 4 + 4: RecordSize int32 4 + 5: Exists int32 4 + 6: LastAppenddate time_t 4 + 7: LastUid int32 4 + 8: QuotaUsed int64 8 + 9: Pop3LastLogin time_t 4 + 10: UidValidity int32 4 + 11: Deleted int32 4 + 12: Answered int32 4 + 13: Flagged int32 4 + 14: Options bitmap 4 + 15: LeakedCache int32 4 + 16: HighestModseq int64 8 + 17: Spare0 int32 4 + 18: Spare1 int32 4 + 19: Spare2 int32 4 + 20: Spare3 int32 4 + 21: Spare4 int32 4 + + Record: + 0: Uid int32 4 + 1: InternalDate time_t 4 + 2: SentDate time_t 4 + 3: Size int32 4 + 4: HeaderSize int32 4 + 5: ContentOffset int32 4 + 6: CacheOffset int32 4 + 7: LastUpdated time_t 4 + 8: SystemFlags bitmap 4 + 9: UserFlags bitmap 16 + 10: ContentLines int32 4 + 11: CacheVersion int32 4 + 12: MessageUuid hex 12 + 13: Modseq int64 8 + + Version 10: + =========== + + Header: + 0: Generation int32 4 + 1: Format int32 4 + 2: MinorVersion int32 4 + 3: StartOffset int32 4 + 4: RecordSize int32 4 + 5: Exists int32 4 + 6: LastAppenddate time_t 4 + 7: LastUid int32 4 + 8: QuotaUsed int64 8 + 9: Pop3LastLogin time_t 4 + 10: UidValidity int32 4 + 11: Deleted int32 4 + 12: Answered int32 4 + 13: Flagged int32 4 + 14: Options bitmap 4 + 15: LeakedCache int32 4 + 16: HighestModseq int64 8 + 17: Spare0 int32 4 + 18: Spare1 int32 4 + 19: Spare2 int32 4 + 20: Spare3 int32 4 + 21: Spare4 int32 4 + + Record: + 0: Uid int32 4 + 1: InternalDate time_t 4 + 2: SentDate time_t 4 + 3: Size int32 4 + 4: HeaderSize int32 4 + 5: ContentOffset int32 4 + 6: CacheOffset int32 4 + 7: LastUpdated time_t 4 + 8: SystemFlags bitmap 4 + 9: UserFlags bitmap 16 + 10: ContentLines int32 4 + 11: CacheVersion int32 4 + 12: MessageGuid hex 20 + 13: Modseq int64 8 + +SKIPPED VERSION 11 - Fastmail internal only + + Version 12: + =========== + + Header: + 0: Generation int32 4 + 1: Format int32 4 + 2: MinorVersion int32 4 + 3: StartOffset int32 4 + 4: RecordSize int32 4 + 5: Exists int32 4 + 6: LastAppenddate time_t 4 + 7: LastUid int32 4 + 8: QuotaUsed int64 8 + 9: Pop3LastLogin time_t 4 + 10: UidValidity int32 4 + 11: Deleted int32 4 + 12: Answered int32 4 + 13: Flagged int32 4 + 14: Options bitmap 4 + 15: LeakedCache int32 4 + 16: HighestModseq int64 8 + 17: DeletedModseq int64 8 + 18: Exists int32 4 + 19: FirstExpunged time_t 4 + 20: LastCleanup time_t 4 + 21: HeaderFileCRC int32 4 + 22: SyncCRC int32 4 + 23: RecentUid int32 4 + 24: RecentTime time_t 4 + 25: Spare0 int32 4 + 26: Spare1 int32 4 + 27: Spare2 int32 4 + 28: HeaderCRC int32 4 + + Record: + 0: Uid int32 4 + 1: InternalDate time_t 4 + 2: SentDate time_t 4 + 3: Size int32 4 + 4: HeaderSize int32 4 + 5: GmTime time_t 4 + 6: CacheOffset int32 4 + 7: LastUpdated time_t 4 + 8: SystemFlags bitmap 4 + 9: UserFlags bitmap 16 + 10: ContentLines int32 4 + 11: CacheVersion int32 4 + 12: MessageGuid hex 20 + 13: Modseq int64 8 + 14: CacheCRC int32 4 + 15: RecordCRC int32 4 + + Version 13: + =========== + + Header: + 0: Generation int32 4 + 1: Format int32 4 + 2: MinorVersion int32 4 + 3: StartOffset int32 4 + 4: RecordSize int32 4 + 5: Exists int32 4 + 6: LastAppenddate time_t 4 + 7: LastUid int32 4
View file
cyrus-imapd-2.5.tar.gz/perl/imap/examples/index_uids.pl
Added
@@ -0,0 +1,76 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Getopt::Std; + +use Cyrus::IndexFile; +use Cyrus::CacheFile; +use Cyrus::HeaderFile; + +my %Opts; +getopts('CHcdDu:', \%Opts); + +my $file = shift || die "Usage: $0 <indexfile>\n"; +unless (-f $file) { + die "File doesn't exist $file\n"; +} + +my $cfile = $Opts{C}; +my $hfile = $Opts{H}; +unless ($cfile) { + $cfile = $file; + $cfile =~ s/index$/cache/; +} +unless ($hfile) { + $hfile = $file; + $hfile =~ s/index$/header/; +} +my $index = Cyrus::IndexFile->new_file($file); +my $cache; +if ($Opts{c}) { + $cache = Cyrus::CacheFile->new_file($cfile); +} +my $headerfile = Cyrus::HeaderFile->new_file($hfile); +my $header = $index->header(); +unless ($Opts{u}) { + if ($Opts{d}) { + print $index->header_dump() . "\n"; + } elsif ($Opts{D}) { + print $index->header_longdump() . "\n"; + } else { + $header->{NumRecords} ||= $header->{Exists}; + print "V:$header->{MinorVersion} E:$header->{Exists} N:$header->{NumRecords} U:$header->{LastUid} M:$header->{HighestModseq}\n"; + } +} +while (my $r = $index->next_record) { + next if ($Opts{u} and $Opts{u} != $r->{Uid}); + if ($Opts{d}) { + print $index->record_dump() . "\n"; + } + elsif ($Opts{D}) { + my $offset = sysseek($index->{handle}, 0, 1); + print "Offset: $offset\n"; + print $index->record_longdump(); + my @flags = $index->flagslist($headerfile); + print "FLAGS: @flags\n"; + print "\n"; + } + elsif ($header->{MinorVersion} == 9) { + print "$r->{Uid} $r->{MessageUuid} $r->{Size}\n"; + } + elsif ($header->{MinorVersion} < 13) { + my @flags = $index->flagslist(); + print "$r->{Uid}\@$r->{Modseq} $r->{MessageGuid} $r->{Size} (@flags)\n"; + } + else { + my @flags = $index->flagslist($headerfile); + printf "$r->{Uid}\@$r->{Modseq} $r->{MessageGuid} $r->{CID} $r->{Size} (@flags)\n"; + } + if ($Opts{c}) { + $cache->offset($r->{CacheOffset}); + my $r = $cache->next_record(); + print $cache->print_record($r); + print "------------------------------------------------\n"; + } +}
View file
cyrus-imapd-2.5.tar.gz/ptclient/ldap.c
Changed
@@ -131,42 +131,50 @@ }; typedef struct _ptsm { - const char *uri; - int version; - struct timeval timeout; - int size_limit; - int time_limit; - int deref; - int referrals; - int restart; - int scope; - const char *base; - int sasl; - const char *id; - const char *bind_dn; - const char *password; - const char *authz; - const char *mech; - const char *realm; - const char *filter; - const char *sasl_secprops; - int start_tls; - int tls_check_peer; - const char *tls_cacert_file; - const char *tls_cacert_dir; - const char *tls_ciphers; - const char *tls_cert; - const char *tls_key; - int member_method; - const char *user_attribute; - const char *member_attribute; - const char *member_filter; - const char *member_base; - int member_scope; - const char *group_filter; - const char *group_base; - int group_scope; - LDAP *ld; + const char *uri; + int version; + struct timeval timeout; + int size_limit; + int time_limit; + int deref; + int referrals; + int restart; + int scope; + const char *base; + int sasl; + const char *id; + const char *bind_dn; + const char *password; + const char *authz; + const char *mech; + const char *realm; + const char *filter; + const char *sasl_secprops; + int start_tls; + int tls_check_peer; + const char *tls_cacert_file; + const char *tls_cacert_dir; + const char *tls_ciphers; + const char *tls_cert; + const char *tls_key; + int member_method; + const char *user_attribute; + const char *member_attribute; + const char *member_filter; + const char *member_base; + int member_scope; + const char *group_filter; + const char *group_base; + int group_scope; + + /* Used for domain name space -> root dn discovery */ + const char *domain_base_dn; + const char *domain_filter; + const char *domain_name_attribute; + int domain_scope; + const char *domain_result_attribute; + + LDAP *ld; } t_ptsm; #define PTSM_OK 0 @@ -448,11 +456,14 @@ ptsm->uri = (config_getstring(IMAPOPT_LDAP_URI) ? config_getstring(IMAPOPT_LDAP_URI) : config_getstring(IMAPOPT_LDAP_SERVERS)); + ptsm->version = (config_getint(IMAPOPT_LDAP_VERSION) == 2 ? LDAP_VERSION2 : LDAP_VERSION3); ptsm->timeout.tv_sec = config_getint(IMAPOPT_LDAP_TIME_LIMIT); ptsm->timeout.tv_usec = 0; ptsm->restart = config_getswitch(IMAPOPT_LDAP_RESTART); + p = config_getstring(IMAPOPT_LDAP_DEREF); + if (!strcasecmp(p, "search")) { ptsm->deref = LDAP_DEREF_SEARCHING; } else if (!strcasecmp(p, "find")) { @@ -462,10 +473,13 @@ } else { ptsm->deref = LDAP_DEREF_NEVER; } + ptsm->referrals = config_getswitch(IMAPOPT_LDAP_REFERRALS); ptsm->size_limit = config_getint(IMAPOPT_LDAP_SIZE_LIMIT); ptsm->time_limit = config_getint(IMAPOPT_LDAP_TIME_LIMIT); + p = config_getstring(IMAPOPT_LDAP_SCOPE); + if (!strcasecmp(p, "one")) { ptsm->scope = LDAP_SCOPE_ONELEVEL; } else if (!strcasecmp(p, "base")) { @@ -473,18 +487,24 @@ } else { ptsm->scope = LDAP_SCOPE_SUBTREE; } + ptsm->bind_dn = config_getstring(IMAPOPT_LDAP_BIND_DN); ptsm->sasl = config_getswitch(IMAPOPT_LDAP_SASL); ptsm->id = (config_getstring(IMAPOPT_LDAP_ID) ? config_getstring(IMAPOPT_LDAP_ID) : config_getstring(IMAPOPT_LDAP_SASL_AUTHC)); + ptsm->authz = (config_getstring(IMAPOPT_LDAP_AUTHZ) ? config_getstring(IMAPOPT_LDAP_AUTHZ) : config_getstring(IMAPOPT_LDAP_SASL_AUTHZ)); + ptsm->mech = (config_getstring(IMAPOPT_LDAP_MECH) ? config_getstring(IMAPOPT_LDAP_MECH) : config_getstring(IMAPOPT_LDAP_SASL_MECH)); + ptsm->realm = (config_getstring(IMAPOPT_LDAP_REALM) ? config_getstring(IMAPOPT_LDAP_REALM) : config_getstring(IMAPOPT_LDAP_SASL_REALM)); + ptsm->password = (config_getstring(IMAPOPT_LDAP_PASSWORD) ? config_getstring(IMAPOPT_LDAP_PASSWORD) : config_getstring(IMAPOPT_LDAP_SASL_PASSWORD)); + ptsm->start_tls = config_getswitch(IMAPOPT_LDAP_START_TLS); ptsm->tls_check_peer = config_getswitch(IMAPOPT_LDAP_TLS_CHECK_PEER); ptsm->tls_cacert_file = config_getstring(IMAPOPT_LDAP_TLS_CACERT_FILE); @@ -492,12 +512,14 @@ ptsm->tls_ciphers = config_getstring(IMAPOPT_LDAP_TLS_CIPHERS); ptsm->tls_cert = config_getstring(IMAPOPT_LDAP_TLS_CERT); ptsm->tls_key = config_getstring(IMAPOPT_LDAP_TLS_KEY); + p = config_getstring(IMAPOPT_LDAP_MEMBER_METHOD); if (!strcasecmp(p, "filter")) { ptsm->member_method = PTSM_MEMBER_METHOD_FILTER; } else { ptsm->member_method = PTSM_MEMBER_METHOD_ATTRIBUTE; } + p = config_getstring(IMAPOPT_LDAP_MEMBER_SCOPE); if (!strcasecmp(p, "one")) { ptsm->member_scope = LDAP_SCOPE_ONELEVEL; @@ -506,12 +528,15 @@ } else { ptsm->member_scope = LDAP_SCOPE_SUBTREE; } + ptsm->member_filter = config_getstring(IMAPOPT_LDAP_MEMBER_FILTER); ptsm->member_base = config_getstring(IMAPOPT_LDAP_MEMBER_BASE); ptsm->member_attribute = (config_getstring(IMAPOPT_LDAP_MEMBER_ATTRIBUTE) ? config_getstring(IMAPOPT_LDAP_MEMBER_ATTRIBUTE) : config_getstring(IMAPOPT_LDAP_MEMBER_ATTRIBUTE)); + ptsm->user_attribute = (config_getstring(IMAPOPT_LDAP_USER_ATTRIBUTE) ? config_getstring(IMAPOPT_LDAP_USER_ATTRIBUTE) : config_getstring(IMAPOPT_LDAP_USER_ATTRIBUTE)); + p = config_getstring(IMAPOPT_LDAP_GROUP_SCOPE); if (!strcasecmp(p, "one")) { ptsm->group_scope = LDAP_SCOPE_ONELEVEL; @@ -520,16 +545,31 @@ } else { ptsm->group_scope = LDAP_SCOPE_SUBTREE; } + ptsm->group_filter = config_getstring(IMAPOPT_LDAP_GROUP_FILTER); ptsm->group_base = config_getstring(IMAPOPT_LDAP_GROUP_BASE); ptsm->filter = config_getstring(IMAPOPT_LDAP_FILTER); ptsm->base = config_getstring(IMAPOPT_LDAP_BASE); - if (ptsm->version != LDAP_VERSION3 && - (ptsm->sasl || - ptsm->start_tls)) + if (ptsm->version != LDAP_VERSION3 && (ptsm->sasl || ptsm->start_tls)) ptsm->version = LDAP_VERSION3; + ptsm->domain_base_dn = config_getstring(IMAPOPT_LDAP_DOMAIN_BASE_DN); + ptsm->domain_filter = config_getstring(IMAPOPT_LDAP_DOMAIN_FILTER); + ptsm->domain_name_attribute = config_getstring(IMAPOPT_LDAP_DOMAIN_NAME_ATTRIBUTE); + + p = config_getstring(IMAPOPT_LDAP_DOMAIN_SCOPE); + + if (!strcasecmp(p, "one")) { + ptsm->domain_scope = LDAP_SCOPE_ONELEVEL; + } else if (!strcasecmp(p, "base")) { + ptsm->domain_scope = LDAP_SCOPE_BASE; + } else { + ptsm->domain_scope = LDAP_SCOPE_SUBTREE;
View file
cyrus-imapd-2.5.tar.gz/sieve/interp.c
Changed
@@ -213,6 +213,11 @@ interp->getheader = f; } +EXPORTED void sieve_register_fname(sieve_interp_t *interp, sieve_get_fname *f) +{ + interp->getfname = f; +} + EXPORTED void sieve_register_envelope(sieve_interp_t *interp, sieve_get_envelope *f) { interp->getenvelope = f;
View file
cyrus-imapd-2.5.tar.gz/sieve/interp.h
Changed
@@ -57,6 +57,7 @@ sieve_get_envelope *getenvelope; sieve_get_body *getbody; sieve_get_include *getinclude; + sieve_get_fname *getfname; sieve_parse_error *err;
View file
cyrus-imapd-2.5.tar.gz/sieve/script.c
Changed
@@ -350,8 +350,8 @@ } static int send_notify_callback(sieve_interp_t *interp, - void *message_context, - void * script_context, notify_list_t *notify, + void *message_context, + void *script_context, notify_list_t *notify, char *actions_string __attribute__((unused)), const char **errmsg) { @@ -380,12 +380,15 @@ /* buf_appendcstr(&out, actions_string); */ nc.message = buf_cstring(&out); + nc.fname = NULL; + if (interp->getfname) + interp->getfname(message_context, &nc.fname); ret = interp->notify(&nc, interp->interp_context, script_context, message_context, - errmsg); + errmsg); buf_free(&out);
View file
cyrus-imapd-2.5.tar.gz/sieve/sieve_interface.h
Changed
@@ -66,6 +66,7 @@ typedef int sieve_get_header(void *message_context, const char *header, const char ***contents); +typedef int sieve_get_fname(void *message_context, const char **fname); typedef int sieve_get_envelope(void *message_context, const char *field, const char ***contents); @@ -119,6 +120,7 @@ const char **options; const char *priority; const char *message; + const char *fname; } sieve_notify_context_t; #define SIEVE_HASHLEN 16 @@ -156,6 +158,7 @@ sieve_script_parse */ void sieve_register_size(sieve_interp_t *interp, sieve_get_size *f); void sieve_register_header(sieve_interp_t *interp, sieve_get_header *f); +void sieve_register_fname(sieve_interp_t *interp, sieve_get_fname *f); void sieve_register_envelope(sieve_interp_t *interp, sieve_get_envelope *f); void sieve_register_body(sieve_interp_t *interp, sieve_get_body *f);
View file
cyrus-imapd-2.5.tar.gz/tools/vzic
Added
+(directory)
View file
cyrus-imapd-2.5.tar.gz/tools/vzic/ChangeLog
Added
@@ -0,0 +1,57 @@ +2006-03-18 Damon Chaplin <damon@gnome.org> + + * Released Vzic 1.3 + +2006-03-18 Damon Chaplin <damon@gnome.org> + + * vzic-output.c (expand_tzname): added special case for America/Nome. + (output_rrule): made hacks a bit more general, to handle Asia/Gaza + which now has a day=4 rule. At some point we should check what newer + versions of Outlook can handle so we can be more accurate. + + * vzic-dump.c (dump_time_zone_names): try looking for timezone info + using original and linked name. + + * README, *.c: fixed spelling 'compatable' -> 'compatible'. + + * vzic.c: patch from Jonathan Guthrie to support a --olson-dir option. + +2003-10-25 Damon Chaplin <damon@gnome.org> + + * Released Vzic 1.2 + +2003-10-25 Damon Chaplin <damon@gnome.org> + + * vzic-output.c: + * Makefile: moved the PRODUCT_ID and TZID_PREFIX settings to the + Makefile and changed the default so people don't accidentally use + the same IDs as Evolution. + + * vzic-parse.c (parse_time): substitute 23:59:59 when we read a time + of 24:00:00. This is a bit of a kludge to avoid problems, since + 24:00:00 is not a valid iCalendar time. Since 24:00:00 is only used + for a few timezones in the 1930s it doesn't matter too much. + + To write a correct fix we'd need to review all the code that deals + with times to see if it would be affected, e.g. a time of 24:00 on + one day should be considered equal to 0:00 the next day. + + We'd also need to adjust the output times to use 0:00 the next day + rather than 24:00. If we need to output recurrence rules that would + be a problem, since 'last saturday at 24:00' can't be easily + converted to another rule that uses 0:00 instead. + +2003-10-22 Damon Chaplin <damon@gnome.org> + + * Released Vzic 1.1 + +2003-10-22 Damon Chaplin <damon@gnome.org> + + * vzic-parse.c (parse_time): allow a time of 24:00, as used in + the America/Montreal and America/Toronto rules in the 1930s! + I'm not 100% sure the rest of the code will handle this OK, but + it only affects the 'pure' output. + +2003-09-01 Damon Chaplin <damon@gnome.org> + + * Released Vzic 1.0
View file
cyrus-imapd-2.5.tar.gz/tools/vzic/Makefile
Added
@@ -0,0 +1,90 @@ + +# +# You will need to set this to the directory that the Olson timezone data +# files are in. +# +OLSON_DIR = . + + +# This is used as the PRODID property on the iCalendar files output. +# It identifies the product which created the iCalendar objects. +# So you need to substitute your own organization name and product. +PRODUCT_ID = -//CyrusIMAP.org//Cyrus %s//EN + +# This is what libical-evolution uses. +#PRODUCT_ID = -//Ximian//NONSGML Evolution Olson-VTIMEZONE Converter//EN + + +# This is used to create unique IDs for each VTIMEZONE component. +# The prefix is put before each timezone city name. It should start and end +# with a '/'. The first part, i.e. 'myorganization.org' below, should be +# a unique vendor ID, e.g. use a hostname. The part after that can be +# anything you want. We use a date and version number for libical. The %D +# gets expanded to today's date. There is also a vzic-merge.pl which can be +# used to merge changes into a master set of VTIMEZONEs. If a VTIMEZONE has +# changed, it bumps the version number on the end of this prefix. */ +#TZID_PREFIX = /myorganization.org/%D_1/ +TZID_PREFIX = + +# This is what libical-evolution uses. +#TZID_PREFIX = /softwarestudio.org/Olson_%D_1/ + + +# Set any -I include directories to find the libical header files, and the +# libical library to link with. You only need these if you want to run the +# tests. You may need to change the '#include <ical.h>' line at the top of +# test-vzic.c as well. +LIBICAL_CFLAGS = +LIBICAL_LDADD = -lical + + +# +# You shouldn't need to change the rest of the file. +# + +GLIB_CFLAGS = `pkg-config --cflags glib-2.0` +GLIB_LDADD = `pkg-config --libs glib-2.0` + +CFLAGS = -g -I../.. -DOLSON_DIR=\"$(OLSON_DIR)\" -DPRODUCT_ID='"$(PRODUCT_ID)"' -DTZID_PREFIX='"$(TZID_PREFIX)"' $(GLIB_CFLAGS) $(LIBICAL_CFLAGS) + +OBJECTS = vzic.o vzic-parse.o vzic-dump.o vzic-output.o + +all: vzic + +vzic: $(OBJECTS) + $(CC) $(OBJECTS) $(GLIB_LDADD) -o vzic + +test-vzic: test-vzic.o + $(CC) test-vzic.o $(LIBICAL_LDADD) -o test-vzic + +# Dependencies. +$(OBJECTS): vzic.h +vzic.o vzic-parse.o: vzic-parse.h +vzic.o vzic-dump.o: vzic-dump.h +vzic.o vzic-output.o: vzic-output.h + +test-parse: vzic + ./vzic-dump.pl $(OLSON_DIR) + ./vzic --dump --pure + @echo + @echo "#" + @echo "# If either of these diff commands outputs anything there may be a problem." + @echo "#" + diff -ru zoneinfo/ZonesPerl zoneinfo/ZonesVzic + diff -ru zoneinfo/RulesPerl zoneinfo/RulesVzic + +test-changes: vzic test-vzic + ./test-vzic --dump-changes + ./vzic --dump-changes --pure + @echo + @echo "#" + @echo "# If this diff command outputs anything there may be a problem." + @echo "#" + diff -ru zoneinfo/ChangesVzic test-output + +clean: + -rm -rf vzic $(OBJECTS) *~ ChangesVzic RulesVzic ZonesVzic RulesPerl ZonesPerl test-vzic test-vzic.o + +.PHONY: clean perl-dump test-parse + +
View file
cyrus-imapd-2.5.tar.gz/tools/vzic/README
Added
@@ -0,0 +1,202 @@ + + +VZIC README +=========== + +This is 'vzic', a program to convert the Olson timezone database files into +VTIMEZONE files compatible with the iCalendar specification (RFC2445). + +(The name is based on the 'zic' program which converts the Olson files into +time zone information files used by several Unix C libraries, including +glibc. See zic(8) and tzfile(5).) + + + +REQUIREMENTS +============ + +You need the Olson timezone database files, which can be found at: + + ftp://elsie.nci.nih.gov/pub/ + + (Old versions can be found at ftp://munnari.oz.au/pub/oldtz/) + + +Vzic also uses the GLib library (for hash tables, dynamic arrays, and date +calculations). You need version 2.0 or higher. You can get this from: + + http://www.gtk.org + + + +BUILDING +======== + +Edit the Makefile to set the OLSON_DIR, PRODUCT_ID and TZID_PREFIX variables. + +Then run 'make'. + + + +RUNNING +======= + +Run 'vzic'. + +The output is placed in the zoneinfo subdirectory by default, +but you can use the --output-dir options to set another toplevel output +directory. + +By default it outputs VTIMEZONEs that try to be compatible with Outlook +(2000, at least). Outlook can't handle certain iCalendar constructs in +VTIMEZONEs, such as RRULEs using BYMONTHDAY, so it has to adjust the RRULEs +slightly to get Outlook to parse them. Unfortunately this means they are +slightly wrong. If given the --pure option, vzic outputs the exact data, +without worrying about compatability. + +NOTE: We don't convert all the Olson files. We skip 'backward', 'etcetera', +'leapseconds', 'pacificnew', 'solar87', 'solar88' and 'solar89', 'factory' +and 'systemv', since these don't really provide any useful timezones. +See vzic.c. + + + +MERGING CHANGES INTO A MASTER SET OF VTIMEZONES +=============================================== + +The Olson timezone files are updated fairly often, so we need to build new +sets of VTIMEZONE files. Though we have to be careful to ensure that the TZID +of updated timezones is also updated, since it must remain unique. + +We use a version number on the end of the TZID prefix (see the TZIDPrefix +variable in vzic-output.c) to ensure this uniqueness. + +But we don't want to update the version numbers of VTIMEZONEs which have not +changed. So we use the vzic-merge.pl Perl script. This merges in the new set +of VTIMEZONEs with a 'master' set. It compares each new VTIMEZONE file with +the one in the master set (ignoring changes to the TZID). If the new +VTIMEZONE file is different, it copies it to the master set and sets the +version number to the old VTIMEZONE's version number + 1. + +To use vzic-merge.pl you must change the $MASTER_ZONEINFO_DIR and +$NEW_ZONEINFO_DIR variables at the top of the file to point to your 2 sets of +VTIMEZONEs. You then just run the script. (I recommend you keep a backup of +the old master VTIMEZONE files, and use diff to compare the new master set +with the old one, in case anything goes wrong.) + +You must merge in changes to the zones.tab file by hand. + +Note that some timezones are renamed or removed occasionally, so applications +should be able to cope with this. + + + +COMPATABILITY NOTES +=================== + +It seems that Microsoft Outlook is very picky about the iCalendar files it +will accept. (I've been testing with Outlook 2000. I hope the other versions +are no worse.) Here's a few problems we've had with the VTIMEZONEs: + + o Outlook doesn't like any years before 1600. We were using '1st Jan 0001' + in all VTIMEZONEs to specify the first UTC offset known for the timezone. + (The Olson data does not give a start date for this.) + + Now we just skip this first component for most timezones. The UTC offset + can still be found from the TZOFFSETFROM property of the first component. + + Though some timezones only specify one UTC offset that applies forever, + so in these cases we output '1st Jan 1970' (Indian/Cocos, + Pacific/Johnston). + + o Outlook doesn't like the BYMONTHDAY specifier in RRULEs. + + We have changed most of the VTIMEZONEs to use things like 'BYDAY=2SU' + rather than 'BYMONTHDAY=8,9,10,11,12,13,14;BYDAY=SU', though some of + them were impossible to convert correctly so they are not always correct. + + o Outlook doesn't like TZOFFSETFROM/TZOFFSETTO properties which include a + seconds component, e.g. 'TZOFFSETFROM:+110628'. + Quite a lot of the Olson timezones include seconds in their UTC offsets, + though no timezones currently have a UTC offset that uses the seconds + value. + + We've rounded all UTC offsets to the nearest minute. Since all timezone + offsets currently used have '00' as the seconds offset, this doesn't lose + us much. + + o Outlook doesn't like lines being split in certain places, even though + the iCalendar spec says they can be split anywhere. + + o Outlook can only handle one RDATE or a pair of RRULEs. So we had to remove + all historical data. + + +TESTING +======= + +Do a 'make test-vic', then run ./test-vic. + +The test-vzic program compares our libical code and VTIMEZONE data against +the Unix functions like mktime(). It steps over a period of time (1970-2037) +converting from UTC to a given timezone and back again every 15 minutes. +Any differences are output into the test-output directory. + +The output matches for all of the timezones, except in a few places where the +result can't be determined. So I think we can be fairly confident that the +VTIMEZONEs are correct. + +Note that you must use the same Olson data in libical that the OS is using +for mktime() etc. For example, I am using RedHat 9 which uses tzdata2002d, +so I converted this to VTIMEZONE files and installed it into the libical +timezone data directory before testing. (You need to use '--pure' when +creating the VTIMEZONE files as well.) + + +Testing the Parsing Code +------------------------ + +Run 'make test-parse'. + +This runs 'vzic --dump' and 'perl-dump' and compares the output. The diff +commands should not produce any output. + +'vzic --dump' dumps all the parsed data out in the original Olson format, +but without comments. The files are written into the ZonesVzic and RulesVzic +subdirectories of the zoneinfo directory. + +'make perl-dump' runs the vzic-dump.pl perl script which outputs the files +in the same format as 'vzic --dump' in the ZonesPerl and RulesPerl +subdirectories. The perl script doesn't actually parse the fields; it only +strips comments and massages the fields so we have the same output format. + +Currently they both produce exactly the same output so we know the parsing +code is OK. + + +Testing the VTIMEZONE Files +--------------------------- + +Run 'make test-changes'. + +This runs 'vzic --dump-changes' and 'test-vzic --dump-changes' and compares +the output. The diff command should not produce any output. + +Both commands output timezone changes for each zone up to a specific year +(2030) into files for each timezone. It outputs the timezone changes in a +list in this format: + + Timezone Name Date and Time of Change in UTC New Offset from UTC + + America/Dawson 26 Oct 1986 2:00:00 -0800 + +Unfortunately there are some differences here, but they all happen before +1970 so it doesn't matter too much. It looks like the libical code has +problems determining things like 'last Sunday of the month' before 1970. +This is because it uses mktime() etc. which can't really handle dates +before 1970. + +
View file
cyrus-imapd-2.5.tar.gz/tools/vzic/test-vzic.c
Added
@@ -0,0 +1,422 @@ +/* + * Vzic - a program to convert Olson timezone database files into VZTIMEZONE + * files compatible with the iCalendar specification (RFC2445). + * + * Copyright (C) 2000-2001 Ximian, Inc. + * Copyright (C) 2003 Damon Chaplin. + * + * Author: Damon Chaplin <damon@gnome.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * test-vzic.c - test vzic + libical against mktime() and friends. + * + * Note that when we output VCALENDAR data compatible with Outlook the + * results aren't all correct. + * + * We have to modify some RRULEs which makes these timezones incorrect: + * + * Africa/Cairo + * America/Godthab + * America/Santiago + * Antarctica/Palmer + * Asia/Baghdad + * Asia/Damascus + * Asia/Jerusalem + * + * Also, we can only output one RDATE or a pair of RRULEs which may make some + * other timezones incorrect sometimes (e.g. if they change). + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <errno.h> + +#include <ical.h> +/*#include <evolution/ical.h>*/ + +#define CHANGES_MAX_YEAR 2030 + +/* These are the years between which we test against the Unix timezone + functions, inclusive. When using 'vzic --pure' you can test the full + range from 1970 to 2037 and it should match against mktime() etc. + (assuming you are using the same Olson timezone data for both). + + But when using VTIMEZONE's that are compatible with Outlook, it is only + worth testing times in the future. There will be lots of differences in + the past, since we can't include any historical changes in the files. */ +#if 1 +#define DUMP_START_YEAR 2003 +#define DUMP_END_YEAR 2038 +#else +#define DUMP_START_YEAR 1970 +#define DUMP_END_YEAR 2038 +#endif + +/* The maximum size of any complete pathname. */ +#define PATHNAME_BUFFER_SIZE 1024 + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +int VzicDumpChanges = FALSE; + +/* We output beneath the current directory for now. */ +char *directory = "test-output"; + +static void usage (void); +static int parse_zone_name (char *name, + char **directory, + char **subdirectory, + char **filename); +static void ensure_directory_exists (char *directory); +static void dump_local_times (icaltimezone *zone, + FILE *fp); + + +int main(int argc, char* argv[]) +{ + icalarray *zones; + icaltimezone *zone; + char *zone_directory, *zone_subdirectory, *zone_filename, *location; + char output_directory[PATHNAME_BUFFER_SIZE]; + char filename[PATHNAME_BUFFER_SIZE]; + FILE *fp; + int i; + int skipping = TRUE; + + /* + * Command-Line Option Parsing. + */ + for (i = 1; i < argc; i++) { + /* --dump-changes: Dumps a list of times when each timezone changed, + and the new local time offset from UTC. */ + if (!strcmp (argv[i], "--dump-changes")) + VzicDumpChanges = TRUE; + + else + usage (); + } + + + zones = icaltimezone_get_builtin_timezones (); + + ensure_directory_exists (directory); + + for (i = 0; i < zones->num_elements; i++) { + zone = icalarray_element_at (zones, i); + + location = icaltimezone_get_location (zone); + +#if 0 + /* Use this to start at a certain zone. */ + if (skipping && strcmp (location, "America/Boise")) + continue; +#endif + + skipping = FALSE; + + /* Use this to only output data for certain timezones. */ +#if 0 + if (strcmp (location, "America/Cancun") + && strcmp (location, "Asia/Baku") + && strcmp (location, "Asia/Nicosia") + && strcmp (location, "Asia/Novosibirsk") + && strcmp (location, "Asia/Samarkand") + && strcmp (location, "Asia/Tashkent") + && strcmp (location, "Asia/Tbilisi") + && strcmp (location, "Asia/Yerevan") + && strcmp (location, "Australia/Broken_Hill") + && strcmp (location, "Europe/Simferopol") + && strcmp (location, "Europe/Tallinn") + && strcmp (location, "Europe/Zaporozhye") + ) + continue; +#endif + +#if 0 + printf ("%s\n", location); +#endif + + parse_zone_name (location, &zone_directory, &zone_subdirectory, + &zone_filename); + + sprintf (output_directory, "%s/%s", directory, zone_directory); + ensure_directory_exists (output_directory); + sprintf (filename, "%s/%s", output_directory, zone_filename); + + if (zone_subdirectory) { + sprintf (output_directory, "%s/%s/%s", directory, zone_directory, + zone_subdirectory); + ensure_directory_exists (output_directory); + sprintf (filename, "%s/%s", output_directory, zone_filename); + } + + fp = fopen (filename, "w"); + if (!fp) { + fprintf (stderr, "Couldn't create file: %s\n", filename); + exit (1); + } + + /* We can run 2 different tests - output all changes for each zone, or + test against mktime()/localtime(). Should have a command-line option + or something. */ + if (VzicDumpChanges) + icaltimezone_dump_changes (zone, CHANGES_MAX_YEAR, fp); + else + dump_local_times (zone, fp); + + if (ferror (fp)) { + fprintf (stderr, "Error writing file: %s\n", filename); + exit (1); + } + + fclose (fp); + } + + return 0; +} +
View file
cyrus-imapd-2.5.tar.gz/tools/vzic/vzic-dump.c
Added
@@ -0,0 +1,409 @@ +/* + * Vzic - a program to convert Olson timezone database files into VZTIMEZONE + * files compatible with the iCalendar specification (RFC2445). + * + * Copyright (C) 2000-2001 Ximian, Inc. + * Copyright (C) 2003 Damon Chaplin. + * + * Author: Damon Chaplin <damon@gnome.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * These functions are for dumping all the parsed Zones and Rules to + * files, to be compared with the output of vzic-dump.pl to check our parsing + * code is OK. Some of the functions are also used for producing debugging + * output. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "vzic.h" +#include "vzic-dump.h" + + +static void dump_add_rule (char *name, + GArray *rule_array, + GPtrArray *name_array); +static int dump_compare_strings (const void *arg1, + const void *arg2); + + +void +dump_zone_data (GArray *zone_data, + char *filename) +{ + static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + FILE *fp; + ZoneData *zone; + ZoneLineData *zone_line; + int i, j; + gboolean output_month, output_day, output_time; + + fp = fopen (filename, "w"); + if (!fp) { + fprintf (stderr, "Couldn't create file: %s\n", filename); + exit (1); + } + + for (i = 0; i < zone_data->len; i++) { + zone = &g_array_index (zone_data, ZoneData, i); + + fprintf (fp, "Zone\t%s\t", zone->zone_name); + + for (j = 0; j < zone->zone_line_data->len; j++) { + zone_line = &g_array_index (zone->zone_line_data, ZoneLineData, j); + + if (j != 0) + fprintf (fp, "\t\t\t"); + + fprintf (fp, "%s\t", dump_time (zone_line->stdoff_seconds, TIME_WALL, + FALSE)); + + if (zone_line->rules) + fprintf (fp, "%s\t", zone_line->rules); + else if (zone_line->save_seconds != 0) + fprintf (fp, "%s\t", dump_time (zone_line->save_seconds, TIME_WALL, + FALSE)); + else + fprintf (fp, "-\t"); + + fprintf (fp, "%s\t", zone_line->format ? zone_line->format : "-"); + + if (zone_line->until_set) { + fprintf (fp, "%s\t", dump_year (zone_line->until_year)); + + output_month = output_day = output_time = FALSE; + + if (zone_line->until_time_code != TIME_WALL + || zone_line->until_time_seconds != 0) + output_month = output_day = output_time = TRUE; + else if (zone_line->until_day_code != DAY_SIMPLE + || zone_line->until_day_number != 1) + output_month = output_day = TRUE; + else if (zone_line->until_month != 0) + output_month = TRUE; + + if (output_month) + fprintf (fp, "%s", months[zone_line->until_month]); + + fprintf (fp, "\t"); + + if (output_day) + fprintf (fp, "%s", dump_day_coded (zone_line->until_day_code, + zone_line->until_day_number, + zone_line->until_day_weekday)); + + fprintf (fp, "\t"); + + if (output_time) + fprintf (fp, "%s", dump_time (zone_line->until_time_seconds, + zone_line->until_time_code, FALSE)); + + } else { + fprintf (fp, "\t\t\t"); + } + + fprintf (fp, "\n"); + } + } + + fclose (fp); +} + + +void +dump_rule_data (GHashTable *rule_data, + char *filename) +{ + FILE *fp; + GPtrArray *name_array; + GArray *rule_array; + int i; + char *name; + + fp = fopen (filename, "w"); + if (!fp) { + fprintf (stderr, "Couldn't create file: %s\n", filename); + exit (1); + } + + /* We need to sort the rules by their names, so they are in the same order + as the Perl output. So we place all the names in a temporary GPtrArray, + sort it, then output them. */ + name_array = g_ptr_array_new (); + g_hash_table_foreach (rule_data, (GHFunc) dump_add_rule, name_array); + qsort (name_array->pdata, name_array->len, sizeof (char*), + dump_compare_strings); + + for (i = 0; i < name_array->len; i++) { + name = g_ptr_array_index (name_array, i); + rule_array = g_hash_table_lookup (rule_data, name); + if (!rule_array) { + fprintf (stderr, "Couldn't access rules: %s\n", name); + exit (1); + } + dump_rule_array (name, rule_array, fp); + } + + g_ptr_array_free (name_array, TRUE); + + fclose (fp); +} + + +static void +dump_add_rule (char *name, + GArray *rule_array, + GPtrArray *name_array) +{ + g_ptr_array_add (name_array, name); +} + + +static int +dump_compare_strings (const void *arg1, + const void *arg2) +{ + char **a, **b; + + a = (char**) arg1; + b = (char**) arg2; + + return strcmp (*a, *b); +} + + +void +dump_rule_array (char *name, + GArray *rule_array, + FILE *fp) +{ + static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
View file
cyrus-imapd-2.5.tar.gz/tools/vzic/vzic-dump.h
Added
@@ -0,0 +1,58 @@ +/* + * Vzic - a program to convert Olson timezone database files into VZTIMEZONE + * files compatible with the iCalendar specification (RFC2445). + * + * Copyright (C) 2000-2001 Ximian, Inc. + * Copyright (C) 2003 Damon Chaplin. + * + * Author: Damon Chaplin <damon@gnome.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * These functions are for dumping all the parsed Zones and Rules to + * files, to be compared with the output of vzic-dump.pl to check our parsing + * code is OK. Some of the functions are also used for producing debugging + * output. + */ + +#ifndef _VZIC_DUMP_H_ +#define _VZIC_DUMP_H_ + +#include <glib.h> + +void dump_zone_data (GArray *zone_data, + char *filename); +void dump_rule_data (GHashTable *rule_data, + char *filename); + +void dump_rule_array (char *name, + GArray *rule_array, + FILE *fp); + +char* dump_year (int year); +char* dump_day_coded (DayCode day_code, + int day_number, + int day_weekday); +char* dump_time (int seconds, + TimeCode time_code, + gboolean use_zero); + +void dump_time_zone_names (GList *names, + char *output_dir, + GHashTable *zones_hash); + +#endif /* _VZIC_DUMP_H_ */
View file
cyrus-imapd-2.5.tar.gz/tools/vzic/vzic-dump.pl
Added
@@ -0,0 +1,222 @@ +#!/usr/bin/perl -w + +# +# Vzic - a program to convert Olson timezone database files into VZTIMEZONE +# files compatible with the iCalendar specification (RFC2445). +# +# Copyright (C) 2000-2001 Ximian, Inc. +# Copyright (C) 2003 Damon Chaplin. +# +# Author: Damon Chaplin <damon@gnome.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. +# + +# +# This reads the Olson timezone files, strips any comments, and outputs them +# in a very simple format with tab-separated fields. It is used to compare +# with the output of dump_zone_data() and dump_rule_data() to double-check +# that we have parsed the files correctly. +# + +my $zones_fh = "zonesfile"; +my $rules_fh = "rulesfile"; + +my %Rules; + +if ($#ARGV != 0) { + die "Usage: $0 <OlsonDirectory>"; +} + +my $OLSON_DIR = $ARGV[0]; + +# We place output in subdirectories of the current directory. +my $OUTPUT_DIR = "zoneinfo"; + +if (! -d "$OUTPUT_DIR") { + mkdir ("$OUTPUT_DIR", 0777) + || die "Can't create directory: $OUTPUT_DIR"; +} +if (! -d "$OUTPUT_DIR/ZonesPerl") { + mkdir ("$OUTPUT_DIR/ZonesPerl", 0777) + || die "Can't create directory: $OUTPUT_DIR/ZonesPerl"; +} +if (! -d "$OUTPUT_DIR/RulesPerl") { + mkdir ("$OUTPUT_DIR/RulesPerl", 0777) + || die "Can't create directory: $OUTPUT_DIR/RulesPerl"; +} + + +&ReadOlsonFile ("africa"); +&ReadOlsonFile ("antarctica"); +&ReadOlsonFile ("asia"); +&ReadOlsonFile ("australasia"); +&ReadOlsonFile ("europe"); +&ReadOlsonFile ("northamerica"); +&ReadOlsonFile ("southamerica"); + +# These are backwards-compatability and weird stuff. +#&ReadOlsonFile ("backward"); +#&ReadOlsonFile ("etcetera"); +#&ReadOlsonFile ("leapseconds"); +#&ReadOlsonFile ("pacificnew"); +#&ReadOlsonFile ("solar87"); +#&ReadOlsonFile ("solar88"); +#&ReadOlsonFile ("solar89"); + +# We don't do this one since it is not useful and the use of '"' in the Zone +# line messes up our split() command. +#&ReadOlsonFile ("factory"); + +# We don't do this since the vzic program can't do it. +#&ReadOlsonFile ("systemv"); + + + + +1; + + +sub ReadOlsonFile { + my ($file) = @_; + +# print ("Reading olson file: $file\n"); + + open (OLSONFILE, "$OLSON_DIR/$file") + || die "Can't open file: $file"; + + open ($zones_fh, ">$OUTPUT_DIR/ZonesPerl/$file") + || die "Can't open file: $OUTPUT_DIR/ZonesPerl/$file"; + + open ($rules_fh, ">$OUTPUT_DIR/RulesPerl/$file") + || die "Can't open file: $OUTPUT_DIR/RulesPerl/$file"; + + %Rules = (); + + my $zone_continues = 0; + + while (<OLSONFILE>) { + next if (m/^#/); + + # '#' characters can appear in strings, but the Olson files don't use + # that feature at present so we treat all '#' as comments for now. + s/#.*//; + + next if (m/^\s*$/); + + if ($zone_continues) { + $zone_continues = &ReadZoneContinuationLine; + + } elsif (m/^Rule\s/) { + &ReadRuleLine; + + } elsif (m/^Zone\s/) { + $zone_continues = &ReadZoneLine; + + } elsif (m/^Link\s/) { +# print "Link: $link_from, $link_to\n"; + + } elsif (m/^Leap\s/) { +# print "Leap\n"; + + } else { + die "Invalid line: $_"; + } + } + +# print ("Read olson file: $file\n"); + + foreach $key (sort (keys (%Rules))) { + print $rules_fh "$Rules{$key}" + } + + close ($zones_fh); + close ($rules_fh); + close (OLSONFILE); +} + + +sub ReadZoneLine { + my ($zone, $name, $gmtoff, $rules_save, $format, + $until_year, $until_month, $until_day, $until_time, $remainder) + = split ' ', $_, 10; + + return &ReadZoneLineCommon ($zone, $name, $gmtoff, $rules_save, $format, + $until_year, $until_month, $until_day, + $until_time); +} + + +sub ReadZoneContinuationLine { + my ($gmtoff, $rules_save, $format, + $until_year, $until_month, $until_day, $until_time, $remainder) + = split ' ', $_, 8; + + return &ReadZoneLineCommon ("", "", $gmtoff, $rules_save, $format, + $until_year, $until_month, $until_day, + $until_time); +} + + +sub ReadZoneLineCommon { + my ($zone, $name, $gmtoff, $rules_save, $format, + $until_year, $until_month, $until_day, $until_time) = @_; + + if (!defined ($until_year)) { $until_year = ""; } + if (!defined ($until_month)) { $until_month = ""; } + if (!defined ($until_day)) { $until_day = ""; } + if (!defined ($until_time)) { $until_time = ""; } + + # A few of the gmtoffsets have an unnecessary :00 seconds. + $gmtoff =~ s/(\d+):(\d+):00/$1:$2/; + + # Make sure the gmtoff does have minutes. + $gmtoff =~ s/^(-?\d+)$/$1:00/; + + # Fix a few other bits so they all use the same format. + if ($gmtoff eq "0") { $gmtoff = "0:00"; } + $until_time =~ s/^0(\d):/$1:/; + if ($until_time eq "0:00") { $until_time = ""; } + if ($until_day eq "1" && $until_time eq "") { $until_day = ""; } + if ($until_month eq "Jan" && $until_day eq "" && $until_time eq "") { + $until_month = ""; + } + + # For Zone continuation lines we need to insert an extra TAB. + if (!$zone) { $zone = "\t" }; +
View file
cyrus-imapd-2.5.tar.gz/tools/vzic/vzic-merge.pl
Added
@@ -0,0 +1,177 @@ +#!/usr/bin/perl -w + +# +# Vzic - a program to convert Olson timezone database files into VZTIMEZONE +# files compatible with the iCalendar specification (RFC2445). +# +# Copyright (C) 2001 Ximian, Inc. +# Copyright (C) 2003 Damon Chaplin. +# +# Author: Damon Chaplin <damon@gnome.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. +# + +# +# This merges in a new set of VTIMEZONE files with the 'master' set. It only +# updates the files in the master set if the VTIMEZONE component has really +# been changes. Note that the TZID normally includes the date the VTIMEZONE +# file was generated on, so we have to ignore this when comparing the files. +# + +# Set these to the toplevel directories of the 2 sets of VTIMEZONE files. +$NEW_ZONEINFO_DIR = "zoneinfo"; + +# Set this to 1 if you have version numbers in the TZID like libical. +$LIBICAL_VERSIONING = 0; + +# Set this to 0 for dry-runs, and 1 to actually update. +$DO_UPDATES = 1; + +# Save this so we can restore it later. +$input_record_separator = $/; + +sub read_conf { + my $file = shift; + + open CONF, $file or die "can't open $file"; + while (<CONF>) { + if (/^#/) { + next; + } + if (/\@include:\s+(.*)$/) { + push @configs, $1; + } + if (/^configdirectory:\s+(.*)$/) { + $confdir = $1; + } + } + close CONF; +} + +$imapdconf = shift || "/etc/imapd.conf"; + +push @configs, $imapdconf; + +while ($conf = shift @configs) { + read_conf($conf); +} + +if (! $confdir) { $confdir = "/var/imap"; } + +$MASTER_ZONEINFO_DIR = $confdir . "/zoneinfo"; + + +chdir $NEW_ZONEINFO_DIR + || die "Can't cd to $NEW_ZONEINFO_DIR"; + +foreach $new_file (`find -name "*.ics"`) { + # Get rid of './' at start and whitespace at end. + $new_file =~ s/^\.\///; + $new_file =~ s/\s+$//; + +# print "File: $new_file\n"; + + open (NEWZONEFILE, "$new_file") + || die "Can't open file: $NEW_ZONEINFO_DIR/$new_file"; + undef $/; + $new_contents = <NEWZONEFILE>; + $/ = $input_record_separator; + close (NEWZONEFILE); + + $master_file = $MASTER_ZONEINFO_DIR . "/$new_file"; + +# print "Master File: $master_file\n"; + + $copy_to_master = 0; + + # If the ics file exists in the master copy we have to compare them, + # otherwise we can just copy the new file into the master directory. + if (-l $new_file) { + $link_to = readlink($new_file); + + if (! -e $master_file || ! -l $master_file || + (readlink($master_file) ne $link_to)) { + + print "Linking $new_file to $link_to...\n"; + + if ($DO_UPDATES) { + unlink($master_file); + symlink($link_to, $master_file); + } + } + } elsif (-e $master_file) { + open (MASTERZONEFILE, "$master_file") + || die "Can't open file: $master_file"; + undef $/; + $master_contents = <MASTERZONEFILE>; + $/ = $input_record_separator; + close (MASTERZONEFILE); + + $new_contents_copy = $new_contents; + + # Strip the TZID from both contents. +# $new_contents_copy =~ s/^TZID:\S+\r$//m; +# $new_tzid = $&; +# $master_contents =~ s/^TZID:\S+\r$//m; +# $master_tzid = $&; + + # Strip the PRODID from both contents. + $new_contents_copy =~ s/^PRODID:.*$//m; + $master_contents =~ s/^PRODID:.*$//m; + + # Strip the LAST-MODIFIED from both contents. + $new_contents_copy =~ s/^LAST-MODIFIED:(\S+)\r$//m; + $master_contents =~ s/^LAST-MODIFIED:(\S+)\r$//m; + +# print "Matched: $master_tzid\n"; + + + if ($new_contents_copy ne $master_contents) { + print "$new_file has changed. Updating...\n"; + $copy_to_master = 1; + + if ($LIBICAL_VERSIONING) { + # We bump the version number in the new file. +# $master_tzid =~ m%_(\d+)/%; + $version_num = $1; +# print "Version: $version_num\n"; + + $version_num++; + $new_tzid =~ s%_(\d+)/%_$version_num/%; + +# print "New TZID: $new_tzid\n"; + $new_contents =~ s/^TZID:\S+$/$new_tzid/m; + } + } + + } else { + print "$new_file doesn't exist in master directory. Copying...\n"; + $copy_to_master = 1; + } + + if ($copy_to_master) { +# print "Updating: $new_file\n"; + + if ($DO_UPDATES) { + open (MASTERZONEFILE, ">$master_file") + || die "Can't create file: $master_file"; + print MASTERZONEFILE $new_contents; + close (MASTERZONEFILE); + } + } + +} +
View file
cyrus-imapd-2.5.tar.gz/tools/vzic/vzic-output.c
Added
@@ -0,0 +1,2367 @@ +/* + * Vzic - a program to convert Olson timezone database files into VZTIMEZONE + * files compatible with the iCalendar specification (RFC2445). + * + * Copyright (C) 2000-2001 Ximian, Inc. + * Copyright (C) 2003 Damon Chaplin. + * + * Author: Damon Chaplin <damon@gnome.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* ALGORITHM: + * + * First we expand all the Rule arrays, so that each element only represents 1 + * year. If a Rule extends to infinity we expand it up to a few years past the + * maximum UNTIL year used in any of the timezones. We do this to make sure + * that the last of the expanded Rules (which may be infinite) is only used + * in the last of the time periods (i.e. the last Zone line). + * + * The Rule arrays are also sorted by the start time (FROM + IN + ON + AT). + * Doing all this makes it much easier to find which rules apply to which + * periods. + * + * For each timezone (i.e. ZoneData element), we step through each of the + * time periods, the ZoneLineData elements (which represent each Zone line + * from the Olson file.) + * + * We calculate the start & end time of the period. + * - For the first line the start time is -infinity. + * - For the last line the end time is +infinity. + * - The end time of each line is also the start time of the next. + * + * We create an array of time changes which occur in this period, including + * the one implied by the Zone line itself (though this is later taken out + * if it is found to be at exactly the same time as the first Rule). + * + * Now we iterate over the time changes, outputting them as STANDARD or + * DAYLIGHT components. We also try to merge them together into RRULEs or + * use RDATEs. + */ + + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "vzic.h" +#include "vzic-output.h" + +#include "vzic-dump.h" + +#include "xversion.h" + + +/* These come from the Makefile. See the comments there. */ +char *ProductID = PRODUCT_ID; +char *TZIDPrefix = TZID_PREFIX; + +/* We expand the TZIDPrefix, replacing %D with the date, in here. */ +char TZIDPrefixExpanded[1024]; + + +/* We only use RRULEs if there are at least MIN_RRULE_OCCURRENCES occurrences, + since otherwise RDATEs are more efficient. Actually, I've set this high + so we only use RRULEs for infinite recurrences. Since expanding RRULEs is + very time-consuming, this seems sensible. */ +#define MIN_RRULE_OCCURRENCES 1 + + +/* The year we go up to when dumping the list of timezone changes (used + for testing & debugging). */ +#define MAX_CHANGES_YEAR 2030 + +/* This is the maximum year that time_t value can typically hold on 32-bit + systems. */ +#define MAX_TIME_T_YEAR 2038 + + +/* The year we use to start RRULEs. */ +#define RRULE_START_YEAR 1970 + +/* The year we use for RDATEs. */ +#define RDATE_YEAR 1970 + + +static char *WeekDays[] = { "SU", "MO", "TU", "WE", "TH", "FR", "SA" }; +static int DaysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + +char *CurrentZoneName; + + +typedef struct _VzicTime VzicTime; +struct _VzicTime +{ + /* Normal years, e.g. 2001. */ + int year; + + /* 0 (Jan) to 11 (Dec). */ + int month; + + /* The day, either a simple month day number, 1-31, or a rule such as + the last Sunday, or the first Monday on or after the 8th. */ + DayCode day_code; + int day_number; /* 1 to 31. */ + int day_weekday; /* 0 (Sun) to 6 (Sat). */ + + /* The time, in seconds from midnight. The code specifies whether the + time is a wall clock time, local standard time, or universal time. */ + int time_seconds; + TimeCode time_code; + + /* The offset from UTC for local standard time. */ + int stdoff; + + /* The offset from UTC for local wall clock time. If this is different to + stdoff then this is a DAYLIGHT component. This is TZOFFSETTO. */ + int walloff; + + /* TRUE if the time change recurs every year to infinity. */ + gboolean is_infinite; + + /* TRUE if the change has already been output. */ + gboolean output; + + /* These are the offsets of the previous VzicTime, and are used when + calculating the time of the change. We place them here in + output_zone_components() to simplify the output code. */ + int prev_stdoff; + int prev_walloff; + + /* The abbreviated form of the timezone name. Note that this may not be + unique. */ + char *tzname; +}; + + +static void expand_and_sort_rule_array (gpointer key, + gpointer value, + gpointer data); +static int rule_sort_func (const void *arg1, + const void *arg2); +static void output_zone (char *directory, + ZoneData *zone, + char *zone_name, + GHashTable *rule_data); +static gboolean parse_zone_name (char *name, + char **directory, + char **subdirectory, + char **filename); +static void output_zone_to_files (ZoneData *zone, + char *zone_name, + GHashTable *rule_data, + FILE *fp, + FILE *changes_fp); +static gboolean add_rule_changes (ZoneLineData *zone_line, + char *zone_name, + GArray *changes, + GHashTable *rule_data, + VzicTime *start, + VzicTime *end, + char **start_letter_s, + int *save_seconds); +static char* expand_tzname (char *zone_name, + char *format, + gboolean have_letter_s, + char *letter_s, + gboolean is_daylight); +static int compare_times (VzicTime *time1, + int stdoff1, + int walloff1, + VzicTime *time2, + int stdoff2, + int walloff2); +static gboolean times_match (VzicTime *time1, + int stdoff1, + int walloff1, + VzicTime *time2, + int stdoff2, + int walloff2); +static void output_zone_components (FILE *fp, + char *name, + GArray *changes);
View file
cyrus-imapd-2.5.tar.gz/tools/vzic/vzic-output.h
Added
@@ -0,0 +1,38 @@ +/* + * Vzic - a program to convert Olson timezone database files into VZTIMEZONE + * files compatible with the iCalendar specification (RFC2445). + * + * Copyright (C) 2000-2001 Ximian, Inc. + * Copyright (C) 2003 Damon Chaplin. + * + * Author: Damon Chaplin <damon@gnome.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _VZIC_OUTPUT_H_ +#define _VZIC_OUTPUT_H_ + +#include <glib.h> + +void output_vtimezone_files (char *directory, + GArray *zone_data, + GHashTable *rule_data, + GHashTable *link_data, + int max_until_year); + +void ensure_directory_exists (char *directory); + +#endif /* _VZIC_OUTPUT_H_ */
View file
cyrus-imapd-2.5.tar.gz/tools/vzic/vzic-parse.c
Added
@@ -0,0 +1,938 @@ +/* + * Vzic - a program to convert Olson timezone database files into VZTIMEZONE + * files compatible with the iCalendar specification (RFC2445). + * + * Copyright (C) 2000-2001 Ximian, Inc. + * Copyright (C) 2003 Damon Chaplin. + * + * Author: Damon Chaplin <damon@gnome.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <ctype.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <libgen.h> + +#include "vzic.h" +#include "vzic-parse.h" + +/* This is the maximum line length we allow. */ +#define MAX_LINE_LEN 1024 + +/* The maximum number of fields on a line. */ +#define MAX_FIELDS 12 + +#define CREATE_SYMLINK 1 + +typedef enum +{ + ZONE_ID = 0, /* The 'Zone' at the start of the line. */ + ZONE_NAME = 1, + ZONE_GMTOFF = 2, + ZONE_RULES_SAVE = 3, + ZONE_FORMAT = 4, + ZONE_UNTIL_YEAR = 5, + ZONE_UNTIL_MONTH = 6, + ZONE_UNTIL_DAY = 7, + ZONE_UNTIL_TIME = 8 +} ZoneFieldNumber; + + +typedef enum +{ + RULE_ID = 0, /* The 'Rule' at the start of the line. */ + RULE_NAME = 1, + RULE_FROM = 2, + RULE_TO = 3, + RULE_TYPE = 4, + RULE_IN = 5, + RULE_ON = 6, + RULE_AT = 7, + RULE_SAVE = 8, + RULE_LETTER_S = 9 +} RuleFieldNumber; + + +typedef enum +{ + LINK_ID = 0, /* The 'Link' at the start of the line. */ + LINK_FROM = 1, + LINK_TO = 2 +} LinkFieldNumber; + + +/* This struct contains information used while parsing the files, and is + passed to most parsing functions. */ +typedef struct _ParsingData ParsingData; +struct _ParsingData +{ + /* This is the line being parsed. buffer is a copy that we break into fields + and sub-fields as it is parsed. */ + char line[MAX_LINE_LEN]; + char buffer[MAX_LINE_LEN]; + + /* These are pointers to the start of each field in buffer. */ + char *fields[MAX_FIELDS]; + int num_fields; + + /* These are just for producing error messages. */ + char *filename; + int line_number; + + + /* This is an array of ZoneData structs, 1 for each timezone read. */ + GArray *zone_data; + + /* This is a hash table of arrays of RuleData structs. As each Rule line is + read in, a new RuleData struct is filled in and appended to the + appropriate GArray in the hash table. */ + GHashTable *rule_data; + + /* A hash containing data on the Link lines. The keys are the timezones + where the link is from (i.e. the timezone we will be outputting anyway) + and the data is a GList of timezones to link to (where we will copy the + timezone data to). */ + GHashTable *link_data; + + int max_until_year; +}; + + +/* + * Parsing functions, used when reading the Olson timezone data file. + */ +static void parse_fields (ParsingData *data); +static gboolean parse_zone_line (ParsingData *data); +static gboolean parse_zone_continuation_line (ParsingData *data); +static gboolean parse_zone_common (ParsingData *data, + int offset); +static void parse_rule_line (ParsingData *data); +static void parse_link_line (ParsingData *data); + +static int parse_year (ParsingData *data, + char *field, + gboolean accept_only, + int only_value); +static int parse_month (ParsingData *data, + char *field); +static DayCode parse_day (ParsingData *data, + char *field, + int *day, + int *weekday); +static int parse_weekday (ParsingData *data, + char *field); +static int parse_time (ParsingData *data, + char *field, + TimeCode *time_code); +static int parse_number (ParsingData *data, + char **num); +static int parse_rules_save (ParsingData *data, + char *field, + char **rules); + +static void parse_coord (char *coord, + int len, + int *result); + +void +parse_olson_file (char *filename, + GArray **zone_data, + GHashTable **rule_data, + GHashTable **link_data, + int *max_until_year) +{ + ParsingData data; + FILE *fp; + int zone_continues = 0; + + *zone_data = g_array_new (FALSE, FALSE, sizeof (ZoneData)); + *rule_data = g_hash_table_new (g_str_hash, g_str_equal); + *link_data = g_hash_table_new (g_str_hash, g_str_equal); + + fp = fopen (filename, "r"); + if (!fp) { + fprintf (stderr, "Couldn't open file: %s\n", filename); + exit (1); + } + + data.filename = filename; + data.zone_data = *zone_data; + data.rule_data = *rule_data; + data.link_data = *link_data; + data.max_until_year = 0; + + for (data.line_number = 0; ; data.line_number++) { + if (fgets (data.line, sizeof (data.line), fp) != data.line) + break; + + strcpy (data.buffer, data.line); + + parse_fields (&data); + if (data.num_fields == 0) + continue; + + if (zone_continues) { + zone_continues = parse_zone_continuation_line (&data); + } else if (!strcmp (data.fields[0], "Zone")) { + zone_continues = parse_zone_line (&data); + } else if (!strcmp (data.fields[0], "Rule")) { + parse_rule_line (&data); + } else if (!strcmp (data.fields[0], "Link")) { + parse_link_line (&data); + } else if (!strcmp (data.fields[0], "Leap")) {
View file
cyrus-imapd-2.5.tar.gz/tools/vzic/vzic-parse.h
Added
@@ -0,0 +1,38 @@ +/* + * Vzic - a program to convert Olson timezone database files into VZTIMEZONE + * files compatible with the iCalendar specification (RFC2445). + * + * Copyright (C) 2000-2001 Ximian, Inc. + * Copyright (C) 2003 Damon Chaplin. + * + * Author: Damon Chaplin <damon@gnome.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _VZIC_PARSE_H_ +#define _VZIC_PARSE_H_ + +#include <glib.h> + +void parse_olson_file (char *filename, + GArray **zone_data, + GHashTable **rule_data, + GHashTable **link_data, + int *max_until_year); + +GHashTable* parse_zone_tab (char *filename); + +#endif /* _VZIC_PARSE_H_ */
View file
cyrus-imapd-2.5.tar.gz/tools/vzic/vzic-test.pl
Added
@@ -0,0 +1,164 @@ +#!/usr/bin/perl -w + +# +# Vzic - a program to convert Olson timezone database files into VZTIMEZONE +# files compatible with the iCalendar specification (RFC2445). +# +# Copyright (C) 2001 Ximian, Inc. +# Copyright (C) 2003 Damon Chaplin. +# +# Author: Damon Chaplin <damon@gnome.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. +# + +# +# This outputs an iCalendar file containing one event in each timezone, +# as well as all the VTIMEZONEs. We use it for testing compatability with +# other iCalendar apps like Outlook, by trying to import it there. +# +# Currently we have 377 timezones (with tzdata2001d). +# + +# Set this to the toplevel directory of the VTIMEZONE files. +$ZONEINFO_DIR = "/home/damon/src/zoneinfo"; + +$output_file = "calendar.ics"; + + +# Save this so we can restore it later. +$input_record_separator = $/; + +chdir $ZONEINFO_DIR + || die "Can't cd to $ZONEINFO_DIR"; + +# Create the output file, to contain all the VEVENTs & VTIMEZONEs. +open (OUTPUTFILE, ">$output_file") + || die "Can't create file: $output_file"; + +# Output the standard header. + print OUTPUTFILE <<EOF; +BEGIN:VCALENDAR +PRODID:-//Ximian//NONSGML Vzic Test//EN +VERSION:2.0 +METHOD:PUBLISH +EOF + +$zone_num = 0; + +# 365 days in a non-leap year. +@days_in_month = ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ); + +foreach $file (`find -name "*.ics"`) { + # Get rid of './' at start and whitespace at end. + $file =~ s/^\.\///; + $file =~ s/\s+$//; + + if ($file eq $output_file) { + next; + } + +# print "File: $file\n"; + + # Get the VTIMEZONE data. + open (ZONEFILE, "$file") + || die "Can't open file: $ZONEINFO_DIR/$file"; + undef $/; + $vtimezone = <ZONEFILE>; + $/ = $input_record_separator; + close (ZONEFILE); + + # Strip the stuff before and after the VTIMEZONE component + $vtimezone =~ s/^.*BEGIN:VTIMEZONE/BEGIN:VTIMEZONE/s; + $vtimezone =~ s/END:VTIMEZONE.*$/END:VTIMEZONE\n/s; + + print OUTPUTFILE $vtimezone; + + # Find the TZID. + $vtimezone =~ m/TZID:(.*)/; + $tzid = $1; +# print "TZID: $tzid\n"; + + # Find the location. + $file =~ m/(.*)\.ics/; + $location = $1; +# print "LOCATION: $location\n"; + + # Try to find the current UTC offset that Outlook will use. + # If there is an RRULE, we look for the first 2 TZOFFSETTO properties, + # else we just get the first one. + if ($vtimezone =~ m/RRULE/) { + $vtimezone =~ m/TZOFFSETTO:([+-]?\d+)/; + $tzoffsetto = $1; + $vtimezone =~ m/TZOFFSETFROM:([+-]?\d+)/; + $tzoffsetfrom = $1; + $tzoffset = "$tzoffsetfrom/$tzoffsetto"; + } else { + $vtimezone =~ m/TZOFFSETTO:([+-]?\d+)/s; + $tzoffset = $1; + } +# print "TZOFFSET: $tzoffset\n"; + + # We put each event on a separate day in 2001 and Jan 2002. + $day_num = $zone_num; + if ($day_num >= 365) { + $year = 2002; + $day_num -= 365; + } else { + $year = 2001; + } + $month = -1; + for ($i = 0; $i < 12; $i++) { + if ($day_num < $days_in_month[$i]) { + $month = $i; + last; + } + $day_num -= $days_in_month[$i] + } + if ($month == -1) { + die "month = -1"; + } + + $month++; + $day_num++; + $date = sprintf ("%i%02i%02i", $year, $month, $day_num); +# print "Date: $date\n"; + + # Output a VEVENT using the timezone. + print OUTPUTFILE <<EOF; +BEGIN:VEVENT +UID:vzic-test-${zone_num} +DTSTAMP:20010101T000000Z +DTSTART;TZID=${tzid}:${date}T120000 +DTEND;TZID=${tzid}:${date}T130000 +RRULE:FREQ=MONTHLY;BYMONTHDAY=${day_num} +SUMMARY:($tzoffset) ${location} 12:00-13:00 UTC +SEQUENCE:1 +END:VEVENT +EOF + + $zone_num++; + + # Use this to stop after a certain number. +# last if ($zone_num == 100); +} + +# Output the standard footer. + print OUTPUTFILE <<EOF; +END:VCALENDAR +EOF + +close (OUTPUTFILE); +
View file
cyrus-imapd-2.5.tar.gz/tools/vzic/vzic.c
Added
@@ -0,0 +1,321 @@ +/* + * Vzic - a program to convert Olson timezone database files into VZTIMEZONE + * files compatible with the iCalendar specification (RFC2445). + * + * Copyright (C) 2000-2001 Ximian, Inc. + * Copyright (C) 2003 Damon Chaplin. + * + * Author: Damon Chaplin <damon@gnome.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "vzic.h" +#include "vzic-parse.h" +#include "vzic-dump.h" +#include "vzic-output.h" + + +/* + * Global command-line options. + */ + +/* By default we output Outlook-compatible output. If --pure is used we + output pure output, with no changes to be compatible with Outlook. */ +gboolean VzicPureOutput = FALSE; + +gboolean VzicDumpOutput = FALSE; +gboolean VzicDumpChanges = FALSE; +gboolean VzicDumpZoneNamesAndCoords = FALSE; +gboolean VzicDumpZoneTranslatableStrings= TRUE; +gboolean VzicNoRRules = FALSE; +gboolean VzicNoRDates = FALSE; +char* VzicOutputDir = "zoneinfo"; +char* VzicUrlPrefix = NULL; +char* VzicOlsonDir = OLSON_DIR; + +GList* VzicTimeZoneNames = NULL; + +static void convert_olson_file (char *olson_file); + +static void usage (void); + +static void free_zone_data (GArray *zone_data); +static void free_rule_array (gpointer key, + gpointer value, + gpointer data); +static void free_link_data (gpointer key, + gpointer value, + gpointer data); + + +int +main (int argc, + char *argv[]) +{ + int i; + char directory[PATHNAME_BUFFER_SIZE]; + char filename[PATHNAME_BUFFER_SIZE]; + GHashTable *zones_hash; + + /* + * Command-Line Option Parsing. + */ + for (i = 1; i < argc; i++) { + /* + * User Options. + */ + + /* --pure: Output the perfect VCALENDAR data, which Outlook won't parse + as it has problems with certain iCalendar constructs. */ + if (!strcmp (argv[i], "--pure")) + VzicPureOutput = TRUE; + + /* --output-dir: specify where to output all the files beneath. The + default is the current directory. */ + else if (argc > i + 1 && !strcmp (argv[i], "--output-dir")) + VzicOutputDir = argv[++i]; + + /* --url-prefix: Used as the base for the TZURL property in each + VTIMEZONE. The default is to not output TZURL properties. */ + else if (argc > i + 1 && !strcmp (argv[i], "--url-prefix")) { + int length; + VzicUrlPrefix = argv[++i]; + /* remove the trailing '/' if there is one */ + length = strlen (VzicUrlPrefix); + if (VzicUrlPrefix[length - 1] == '/') + VzicUrlPrefix[length - 1] = '\0'; + } + + else if (argc > i + 1 && !strcmp (argv[i], "--olson-dir")) { + VzicOlsonDir = argv[++i]; + } + + /* + * Debugging Options. + */ + + /* --dump: Dump the Rule and Zone data that we parsed from the Olson + timezone files. This is used to test the parsing code. */ + else if (!strcmp (argv[i], "--dump")) + VzicDumpOutput = TRUE; + + /* --dump-changes: Dumps a list of times when each timezone changed, + and the new local time offset from UTC. */ + else if (!strcmp (argv[i], "--dump-changes")) + VzicDumpChanges = TRUE; + + /* --no-rrules: Don't output RRULE properties in the VTIMEZONEs. Instead + it will just output RDATEs for each year up to a certain year. */ + else if (!strcmp (argv[i], "--no-rrules")) + VzicNoRRules = TRUE; + + /* --no-rdates: Don't output multiple RDATEs in a single VTIMEZONE + component. Instead they will be output separately. */ + else if (!strcmp (argv[i], "--no-rdates")) + VzicNoRDates = TRUE; + + else + usage (); + } + + /* + * Create any necessary directories. + */ + ensure_directory_exists (VzicOutputDir); + + if (VzicDumpOutput) { + /* Create the directories for the dump output, if they don't exist. */ + sprintf (directory, "%s/ZonesVzic", VzicOutputDir); + ensure_directory_exists (directory); + sprintf (directory, "%s/RulesVzic", VzicOutputDir); + ensure_directory_exists (directory); + } + + if (VzicDumpChanges) { + /* Create the directory for the changes output, if it doesn't exist. */ + sprintf (directory, "%s/ChangesVzic", VzicOutputDir); + ensure_directory_exists (directory); + } + + /* + * Convert the Olson timezone files. + */ + convert_olson_file ("africa"); + convert_olson_file ("antarctica"); + convert_olson_file ("asia"); + convert_olson_file ("australasia"); + convert_olson_file ("europe"); + convert_olson_file ("northamerica"); + convert_olson_file ("southamerica"); + + /* These are backwards-compatability and weird stuff. */ + convert_olson_file ("backward"); +#if 0 + convert_olson_file ("etcetera"); + convert_olson_file ("leapseconds"); + convert_olson_file ("pacificnew"); + convert_olson_file ("solar87"); + convert_olson_file ("solar88"); + convert_olson_file ("solar89"); +#endif + + /* This doesn't really do anything and it messes up vzic-dump.pl so we + don't bother. */ +#if 0 + convert_olson_file ("factory"); +#endif + + /* This is old System V stuff, which we don't currently support since it + uses 'min' as a Rule FROM value which messes up our algorithm, making + it too slow and use too much memory. */ +#if 0 + convert_olson_file ("systemv"); +#endif + + /* Output the timezone names and coordinates in a zone.tab file, and + the translatable strings to feed to gettext. */ + if (VzicDumpZoneNamesAndCoords) { + sprintf (filename, "%s/zone.tab", VzicOlsonDir); + zones_hash = parse_zone_tab (filename); + + dump_time_zone_names (VzicTimeZoneNames, VzicOutputDir, zones_hash); + }
View file
cyrus-imapd-2.5.tar.gz/tools/vzic/vzic.h
Added
@@ -0,0 +1,197 @@ +/* + * Vzic - a program to convert Olson timezone database files into VZTIMEZONE + * files compatible with the iCalendar specification (RFC2445). + * + * Copyright (C) 2000-2001 Ximian, Inc. + * Copyright (C) 2003 Damon Chaplin. + * + * Author: Damon Chaplin <damon@gnome.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _VZIC_H_ +#define _VZIC_H_ + +#include <glib.h> + + +/* + * Global command-line options. + */ + +/* By default we output Outlook-compatible output. If --pure is used we output + pure output, with no changes to be compatible with Outlook. */ +extern gboolean VzicPureOutput; + +extern gboolean VzicDumpOutput; +extern gboolean VzicDumpChanges; +extern gboolean VzicDumpZoneNamesAndCoords; +extern gboolean VzicDumpZoneTranslatableStrings; +extern gboolean VzicNoRRules; +extern gboolean VzicNoRDates; +extern char* VzicUrlPrefix; +extern char* VzicOutputDir; + +extern GList* VzicTimeZoneNames; + +/* The minimum & maximum years we can use. */ +#define YEAR_MINIMUM G_MININT +#define YEAR_MAXIMUM G_MAXINT + +/* The maximum size of any complete pathname. */ +#define PATHNAME_BUFFER_SIZE 1024 + +/* Days can be expressed either as a simple month day number, 1-31, or a rule + such as the last Sunday, or the first Monday on or after the 8th. */ +typedef enum +{ + DAY_SIMPLE, + DAY_WEEKDAY_ON_OR_AFTER, + DAY_WEEKDAY_ON_OR_BEFORE, + DAY_LAST_WEEKDAY +} DayCode; + + +/* Times can be given either as universal time (UTC), local standard time + (without daylight-saving adjustments) or wall clock time (local standard + time plus daylight-saving adjustments, i.e. what you would see on a clock + on the wall!). */ +typedef enum +{ + TIME_WALL, + TIME_STANDARD, + TIME_UNIVERSAL +} TimeCode; + + +/* This represents one timezone, e.g. "Africa/Algiers". + It contains the timezone name, and an array of ZoneLineData structs which + hold data from each Zone line, including the continuation lines. */ +typedef struct _ZoneData ZoneData; +struct _ZoneData +{ + char *zone_name; + + /* An array of ZoneLineData, one for each Zone & Zone continuation line + read in. */ + GArray *zone_line_data; +}; + + +typedef struct _ZoneLineData ZoneLineData; +struct _ZoneLineData +{ + /* The amount of time to add to UTC to get local standard time for the + current time range, in seconds. */ + int stdoff_seconds; + + /* Either rules is set to the name of a set of rules, or rules is NULL and + save is set to the time to add to local standard time to get wall time, in + seconds. If save is 0 as well, then standard time always applies. */ + char *rules; + int save_seconds; + + /* The format to use for the abbreviated timezone name, e.g. WE%sT. + The %s is replaced by variable part of the name. (See the letter_s field + in the RuleData struct below). */ + char *format; + + /* TRUE if an UNTIL time is given. */ + gboolean until_set; + + /* The UNTIL year, e.g. 2000. */ + int until_year; + + /* The UNTIL month 0 (Jan) to 11 (Dec). */ + int until_month; + + /* The UNTIL day, either a simple month day number, 1-31, or a rule such as + the last Sunday, or the first Monday on or after the 8th. */ + DayCode until_day_code; + int until_day_number; /* 1 to 31. */ + int until_day_weekday; /* 0 (Sun) to 6 (Sat). */ + + /* The UNTIL time, in seconds from midnight. The code specifies whether the + time is a wall clock time, local standard time, or universal time. */ + int until_time_seconds; + TimeCode until_time_code; +}; + + +typedef struct _RuleData RuleData; +struct _RuleData +{ + /* The first year that the rule applies to, e.g. 1996. + Can also be YEAR_MINIMUM. */ + int from_year; + + /* The last year that the rule applies to, e.g. 1996. + Can also be YEAR_MAXIMUM. */ + int to_year; + + /* A string used to only match certain years between from and to. + The rule only applies to the years which match. If type is NULL the rule + applies to all years betweeen from and to. + zic uses an external program called yearistype to check the string. + Currently it is not used in the Olson database. */ + char *type; + + /* The month of the rule 0 (Jan) to 11 (Dec). */ + int in_month; + + /* The day, either a simple month day number, 1-31, or a rule such as + the last Sunday, or the first Monday on or after the 8th. */ + DayCode on_day_code; + int on_day_number; + int on_day_weekday; /* 0 (Sun) to 6 (Sat). */ + + /* The time, in seconds from midnight. The code specifies whether the + time is a wall clock time, local standard time, or universal time. */ + int at_time_seconds; + TimeCode at_time_code; + + /* The amount of time to add to local standard time when the rule is in + effect, in seconds. If this is not 0 then it must be a daylight-saving + time. */ + int save_seconds; + + /* The letter(s) to use as the variable part in the abbreviated timezone + name. If this is NULL then no variable part is used. (See the format field + in the ZoneLineData struct above.) */ + char *letter_s; + + + /* This is set to TRUE if this element is a shallow copy of another one, + in which case we don't free any of the fields. */ + gboolean is_shallow_copy; +}; + + +typedef struct _ZoneDescription ZoneDescription; +struct _ZoneDescription +{ + /* 2-letter ISO 3166 country code. */ + char country_code[2]; + + /* latitude and longitude in degrees, minutes & seconds. The degrees value + holds the sign of the entire latitude/longitude. */ + int latitude[3]; + int longitude[3]; + + char *comment; +}; + +#endif /* _VZIC_H_ */
View file
cyrus-imapd.cvt_cyrusdb_all
Changed
@@ -124,12 +124,18 @@ # # v1.3.4, Dec 22 2009 Simon Matter <simon.matter@invoca.ch> # - add support for user_deny.db +# # v1.3.5, Mar 6 2014 Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> # - use default database configuration values if not specified in # configuration VERSION=1.3.5 +[ -f /etc/sysconfig/cyrus-imapd${INSTANCE} ] && \ + . /etc/sysconfig/cyrus-imapd${INSTANCE} + +[ "${QUICK}" == "1" ] && exit 0 + PIDFILE=/var/run/cyrus-master${INSTANCE}.pid # instance config
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.