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 61
View file
cyrus-imapd.spec
Changed
@@ -251,16 +251,16 @@ %prep %setup -q -n %{_name}-%{real_version}%{?dot_snapshot_version} -%patch0001 -p1 -%patch0002 -p1 -%patch0003 -p1 -%patch0004 -p1 -%patch0005 -p1 -%patch0006 -p1 -%patch0007 -p1 -%patch0008 -p1 -%patch0009 -p1 -%patch0010 -p1 +#%patch0001 -p1 +#%patch0002 -p1 +#%patch0003 -p1 +#%patch0004 -p1 +#%patch0005 -p1 +#%patch0006 -p1 +#%patch0007 -p1 +#%patch0008 -p1 +#%patch0009 -p1 +#%patch0010 -p1 # only to update config.* files aclocal -I cmulocal
View file
cyrus-imapd-2.5.tar.gz/Makefile.am
Changed
@@ -147,6 +147,9 @@ if NNTPD service_PROGRAMS += imap/nntpd endif +if CALALARMD +user_PROGRAMS += imap/calalarmd +endif if HTTPD AM_CPPFLAGS += $(HTTP_CPPFLAGS) AM_LDFLAGS += $(HTTP_LIBS) @@ -164,6 +167,7 @@ imap/http_timezone.c \ imap/zoneinfo_db.c \ imap/caldav_db.c \ + imap/caldav_alarm.c \ imap/proxy.c \ imap/smtpclient.c \ imap/spool.c \ @@ -734,6 +738,9 @@ imap_idled_SOURCES = imap/idled.c imap/mutex_fake.c imap_idled_LDADD = $(LD_UTILITY_ADD) +imap_calalarmd_SOURCES = imap/calalarmd.c imap/mutex_fake.c +imap_calalarmd_LDADD = $(LD_UTILITY_ADD) + imap_imapd_SOURCES = \ imap/imap_proxy.c \ imap/imap_proxy.h \ @@ -945,6 +952,7 @@ imap/mutex_fake.c \ imap/carddav_db.c \ imap/caldav_db.c \ + imap/caldav_alarm.c \ imap/http_proxy.c \ imap/httpd.c \ imap/proxy.c \ @@ -1190,7 +1198,6 @@ man/deliver.8 \ man/fetchnews.8 \ man/fud.8 \ - man/httpd.8 \ man/idled.8 \ man/imapd.8 \ man/ipurge.8 \ @@ -1206,17 +1213,27 @@ 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 \
View file
cyrus-imapd-2.5.tar.gz/configure.ac
Changed
@@ -127,7 +127,6 @@ #define HIDDEN #endif]) -LT_PREREQ([2.2.6]) LT_INIT([disable-static]) AC_SUBST([LIBTOOL_DEPS]) @@ -1155,6 +1154,13 @@ fi dnl +dnl see if we're compiling with calendar alarm support +dnl +AC_ARG_ENABLE(calalarmd, + [AS_HELP_STRING([--enable-calalarmd], [enable CalDAV alarm support])],,[enable_calalarmd="no";]) +AM_CONDITIONAL([CALALARMD], [test "$enable_calalarmd" != "no"]) + +dnl dnl see if we're compiling with HTTP support dnl ENABLE_HTTP=no @@ -1717,6 +1723,7 @@ nttpd: $enable_nntp replication: $enable_replication sieve: $enable_sieve + calalarmd: $enable_calalarmd http: $enable_http External dependencies:
View file
cyrus-imapd-2.5.tar.gz/imap/annotate.c
Changed
@@ -2225,13 +2225,19 @@ /************************** Annotation Storing *****************************/ EXPORTED int annotatemore_lookup(const char *mboxname, const char *entry, - const char *userid, struct buf *value) + const char *userid, struct buf *value) { return annotatemore_msg_lookup(mboxname, /*uid*/0, entry, userid, value); } +EXPORTED int annotatemore_lookupmask(const char *mboxname, const char *entry, + const char *userid, struct buf *value) +{ + return annotatemore_msg_lookupmask(mboxname, /*uid*/0, entry, userid, value); +} + EXPORTED int annotatemore_msg_lookup(const char *mboxname, uint32_t uid, const char *entry, - const char *userid, struct buf *value) + const char *userid, struct buf *value) { char key[MAX_MAILBOX_PATH+1]; size_t keylen, datalen; @@ -2263,6 +2269,20 @@ return r; } +EXPORTED int annotatemore_msg_lookupmask(const char *mboxname, uint32_t uid, const char *entry, + const char *userid, struct buf *value) +{ + int r; + value->len = 0; /* just in case! */ + /* only if the user isn't the owner, we look for a masking value */ + if (!mboxname_userownsmailbox(userid, mboxname)) + r = annotatemore_msg_lookup(mboxname, uid, entry, userid, value); + /* and if there isn't one, we fall through to the shared value */ + if (value->len == 0) + r = annotatemore_msg_lookup(mboxname, uid, entry, NULL, value); + return r; +} + static int read_old_value(annotate_db_t *d, const char *key, int keylen, struct buf *valp) @@ -2486,6 +2506,18 @@ entry, userid, value, /*ignorequota*/1); } +EXPORTED int annotate_state_writemask(annotate_state_t *state, + const char *entry, + const char *userid, + const struct buf *value) +{ + /* if the user is the owner, then write to the shared namespace */ + if (mboxname_userownsmailbox(userid, state->mailbox->name)) + return annotate_state_write(state, entry, NULL, value); + else + return annotate_state_write(state, entry, userid, value); +} + static int annotate_canon_value(struct buf *value, int type) { char *p = NULL;
View file
cyrus-imapd-2.5.tar.gz/imap/annotate.h
Changed
@@ -165,9 +165,15 @@ /* lookup a single annotation and return result */ int annotatemore_lookup(const char *mboxname, const char *entry, const char *userid, struct buf *value); +/* same but check shared if per-user doesn't exist */ +int annotatemore_lookupmask(const char *mboxname, const char *entry, + const char *userid, struct buf *value); /* lookup a single per-message annotation and return result */ int annotatemore_msg_lookup(const char *mboxname, uint32_t uid, const char *entry, const char *userid, struct buf *value); +/* same but check shared if per-user doesn't exist */ +int annotatemore_msg_lookupmask(const char *mboxname, uint32_t uid, const char *entry, + const char *userid, struct buf *value); /* store annotations. Requires an open transaction */ int annotate_state_store(annotate_state_t *state, struct entryattlist *l); @@ -176,6 +182,9 @@ * Requires an open transaction. */ int annotate_state_write(annotate_state_t *, const char *entry, const char *userid, const struct buf *value); +/* same but write to shared if the user owns the mailbox */ +int annotate_state_writemask(annotate_state_t *, const char *entry, + const char *userid, const struct buf *value); /* rename the annotations for 'oldmboxname' to 'newmboxname' * if 'olduserid' is non-NULL then the private annotations
View file
cyrus-imapd-2.5.tar.gz/imap/autocreate.c
Changed
@@ -699,7 +699,7 @@ } if (autocreatequota >= 0 || autocreatequotamessage >= 0) { - int newquotas[QUOTA_NUMRESOURCES]; + quota_t newquotas[QUOTA_NUMRESOURCES]; int res; for (res = 0 ; res < QUOTA_NUMRESOURCES ; res++)
View file
cyrus-imapd-2.5.tar.gz/imap/calalarmd.c
Added
@@ -0,0 +1,171 @@ +/* calalarmd.c - daemon for sending calendar alarms + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <sys/types.h> +#include <syslog.h> +#include <sys/stat.h> +#include <stdlib.h> +#include <errno.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <signal.h> +#include <fcntl.h> +#include <math.h> + +#include "global.h" +#include "xmalloc.h" +#include "exitcodes.h" +#include "caldav_db.h" +#include "caldav_alarm.h" + +extern int optind; +extern char *optarg; + +static int debugmode = 0; + +EXPORTED void fatal(const char *msg, int err) +{ + if (debugmode) fprintf(stderr, "dying with %s %d\n",msg,err); + syslog(LOG_CRIT, "%s", msg); + syslog(LOG_NOTICE, "exiting"); + + cyrus_done(); + + exit(err); +} + +static void shut_down(int ec) __attribute__((noreturn)); +static void shut_down(int ec) +{ + caldav_done(); + dav_done(); + annotatemore_close(); + mboxlist_close(); + mboxlist_done(); + cyrus_done(); + exit(ec); +} + +int main(int argc, char **argv) +{ + int opt; + pid_t pid; + char *alt_config = NULL; + + if ((geteuid()) == 0 && (become_cyrus(/*is_master*/0) != 0)) { + fatal("must run as the Cyrus user", EC_USAGE); + } + + while ((opt = getopt(argc, argv, "C:di:")) != EOF) { + switch (opt) { + case 'C': /* alt config file */ + alt_config = optarg; + break; + case 'd': /* don't fork. debugging mode */ + debugmode = 1; + break; + default: + fprintf(stderr, "invalid argument\n"); + exit(EC_USAGE); + break; + } + } + + cyrus_init(alt_config, "calalarmd", 0, 0); + + mboxlist_init(0); + mboxlist_open(NULL); + + annotatemore_open(); + + dav_init(); + caldav_init(); + + mboxevent_init(); + + signals_set_shutdown(shut_down); + signals_add_handlers(0); + + /* fork unless we were given the -d option or we're running as a daemon */ + if (debugmode == 0 && !getenv("CYRUS_ISDAEMON")) { + + pid = fork(); + + if (pid == -1) { + perror("fork"); + exit(1); + } + + if (pid != 0) { /* parent */ + exit(0); + } + } + /* child */ + + for (;;) { + struct timeval start, end; + double totaltime; + int tosleep; + + signals_poll(); + + gettimeofday(&start, 0); + caldav_alarm_process(); + gettimeofday(&end, 0); + + signals_poll(); + + totaltime = timesub(&start, &end); + tosleep = 10 - round(totaltime); + if (tosleep > 0) + sleep(tosleep); + } + + /* NOTREACHED */ + shut_down(1); +} +
View file
cyrus-imapd-2.5.tar.gz/imap/caldav_alarm.c
Added
@@ -0,0 +1,854 @@ +/* caldav_alarm.c -- implementation of global CalDAV alarm database + * + * Copyright (c) 1994-2012 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 <syslog.h> +#include <string.h> + +#include <libical/ical.h> + +#include "caldav_alarm.h" +#include "cyrusdb.h" +#include "exitcodes.h" +#include "httpd.h" +#include "http_dav.h" +#include "imap_err.h" +#include "http_err.h" +#include "libconfig.h" +#include "mboxname.h" +#include "util.h" +#include "xstrlcat.h" +#include "xmalloc.h" + +enum { + STMT_BEGIN, + STMT_COMMIT, + STMT_ROLLBACK, + STMT_INSERT_ALARM, + STMT_INSERT_RECIPIENT, + STMT_DELETE, + STMT_DELETEALL, + STMT_DELETEMAILBOX, + STMT_DELETEUSER, + STMT_SELECT_ALARM, + STMT_SELECT_RECIPIENT +}; + +#define NUM_STMT 11 + +struct caldav_alarm_db { + sqlite3 *db; + int refcount; + sqlite3_stmt *stmt[NUM_STMT]; + int in_transaction; +}; + +static struct namespace caldav_alarm_namespace; + +EXPORTED int caldav_alarm_init(void) +{ + int r; + + /* Set namespace -- force standard (internal) */ + if ((r = mboxname_init_namespace(&caldav_alarm_namespace, 1))) { + syslog(LOG_ERR, "%s", error_message(r)); + fatal(error_message(r), EC_CONFIG); + } + + /* XXX initializes sqlite, but we're not really supposed to know that */ + return dav_init(); +} + + +EXPORTED int caldav_alarm_done(void) +{ + /* XXX shuts down sqlite, but we're not really supposed to know that */ + return dav_done(); +} + + +#define CMD_DROP "DROP TABLE IF EXISTS alarms;" + +#define CMD_CREATE \ + "CREATE TABLE IF NOT EXISTS alarms (" \ + " rowid INTEGER PRIMARY KEY AUTOINCREMENT," \ + " mailbox TEXT NOT NULL," \ + " resource TEXT NOT NULL," \ + " action INTEGER NOT NULL," \ + " nextalarm TEXT NOT NULL," \ + " tzid TEXT NOT NULL," \ + " start TEXT NOT NULL," \ + " end TEXT NOT NULL" \ + ");" \ + "CREATE TABLE IF NOT EXISTS alarm_recipients (" \ + " rowid INTEGER PRIMARY KEY AUTOINCREMENT," \ + " alarmid INTEGER NOT NULL," \ + " email TEXT NOT NULL," \ + " FOREIGN KEY (alarmid) REFERENCES alarms (rowid) ON DELETE CASCADE" \ + ");" \ + "CREATE INDEX IF NOT EXISTS idx_alarm_id ON alarm_recipients ( alarmid );" + +static struct caldav_alarm_db *my_alarmdb; +static struct mboxlock *my_alarmdb_lock; + +/* get a database handle to the alarm db */ +EXPORTED struct caldav_alarm_db *caldav_alarm_open() +{ + if (my_alarmdb) { + my_alarmdb->refcount++; + return my_alarmdb; + } + + sqlite3 *db; + const char *cmds = CMD_CREATE; + + char *dbfilename = strconcat(config_dir, "/caldav_alarm.sqlite3", NULL); + + int r = mboxname_lock("$CALDAVALARMDB", &my_alarmdb_lock, LOCK_EXCLUSIVE); + if (r) + return NULL; + + int rc = sqlite3_open(dbfilename, &db); + if (rc != SQLITE_OK) { + syslog(LOG_ERR, "IOERROR: caldav_alarm_open (open): %s", db ? sqlite3_errmsg(db) : "failed"); + sqlite3_close(db); + free(dbfilename); + mboxname_release(&my_alarmdb_lock); + return NULL; + } + + free(dbfilename); + + rc = sqlite3_exec(db, "PRAGMA foreign_keys = ON;", NULL, NULL, NULL); + if (rc) goto fail; + + if (cmds) { + rc = sqlite3_exec(db, cmds, NULL, NULL, NULL); + if (rc) goto fail; + } + + my_alarmdb = xzmalloc(sizeof(struct caldav_alarm_db)); + my_alarmdb->db = db; + my_alarmdb->refcount = 1; + my_alarmdb->in_transaction = 0; + + return my_alarmdb; + +fail: + syslog(LOG_ERR, "IOERROR: caldav_alarm_open (exec): %s", sqlite3_errmsg(db)); + sqlite3_close(db); + mboxname_release(&my_alarmdb_lock); + return NULL; +} + +/* close this handle */ +EXPORTED int caldav_alarm_close(struct caldav_alarm_db *alarmdb) +{ + assert(my_alarmdb == alarmdb); + + if (--(my_alarmdb->refcount)) return 0; + + int i; + for (i = 0; i < NUM_STMT; i++) { + sqlite3_stmt *stmt = my_alarmdb->stmt[i]; + if (stmt) sqlite3_finalize(stmt); + } + + sqlite3_close(my_alarmdb->db); +
View file
cyrus-imapd-2.5.tar.gz/imap/caldav_alarm.h
Added
@@ -0,0 +1,113 @@ +/* caldav_alarm.h -- interface to global CalDAV alarm database + * + * Copyright (c) 1994-2012 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 CALDAV_ALARM_DB_H +#define CALDAV_ALARM_DB_H + +#include <config.h> + +#include <sqlite3.h> +#include "strarray.h" + +struct caldav_alarm_db; + +enum caldav_alarm_action { + CALDAV_ALARM_ACTION_NONE = 0, + CALDAV_ALARM_ACTION_DISPLAY = 1, + CALDAV_ALARM_ACTION_EMAIL = 2, + + CALDAV_ALARM_ACTION_FIRST = CALDAV_ALARM_ACTION_DISPLAY, + CALDAV_ALARM_ACTION_LAST = CALDAV_ALARM_ACTION_EMAIL +}; + +struct caldav_alarm_data { + sqlite3_int64 rowid; + const char *mailbox; + const char *resource; + enum caldav_alarm_action action; + icaltimetype nextalarm; + const char *tzid; + icaltimetype start; + icaltimetype end; + strarray_t recipients; +}; + +/* prepare for caldav alarm operations in this process */ +int caldav_alarm_init(void); + +/* done with all caldav operations for this process */ +int caldav_alarm_done(void); + +/* get a database handle to the alarm db */ +struct caldav_alarm_db *caldav_alarm_open(void); + +/* close this handle */ +int caldav_alarm_close(struct caldav_alarm_db *alarmdb); + +/* transactions */ +int caldav_alarm_begin(struct caldav_alarm_db *alarmdb); +int caldav_alarm_commit(struct caldav_alarm_db *alarmdb); +int caldav_alarm_rollback(struct caldav_alarm_db *alarmdb); + +/* add a calendar alarm */ +int caldav_alarm_add(struct caldav_alarm_db *alarmdb, struct caldav_alarm_data *alarmdata); + +/* delete all alarms matching the event */ +int caldav_alarm_delete_all(struct caldav_alarm_db *alarmdb, struct caldav_alarm_data *alarmdata); + +/* delete all alarms for a user */ +int caldav_alarm_delete_user(struct caldav_alarm_db *alarmdb, const char *userid); + +/* fill alarmdata with data for next alarm of given type for given entry */ +int caldav_alarm_prepare(icalcomponent *ical, struct caldav_alarm_data *alarmdata, enum caldav_alarm_action action, icaltimetype after); + +/* delete entire mailbox's alarms */ +int caldav_alarm_delmbox(struct caldav_alarm_db *alarmdb, const char *mboxname); + +/* clean up alarmdata after prepare */ +void caldav_alarm_fini(struct caldav_alarm_data *alarmdata); + +/* distribute alarms with triggers in the next minute */ +int caldav_alarm_process(); + +#endif /* CALDAV_ALARM_H */
View file
cyrus-imapd-2.5.tar.gz/imap/caldav_db.c
Changed
@@ -59,6 +59,8 @@ #include "xstrlcat.h" #include "xmalloc.h" +struct icaltimetype world_start; +struct icaltimetype world_end; enum { STMT_SELRSRC, @@ -104,12 +106,19 @@ fatal(error_message(r), EC_CONFIG); } - return dav_init(); + r = dav_init(); + caldav_alarm_init(); + + /* we're interested in a 200 year range for now */ + world_start = icaltime_from_string("1900-01-01T00:00:00Z"); + world_end = icaltime_from_string("2099-12-31T23:59:59Z"); + return r; } EXPORTED int caldav_done(void) { + caldav_alarm_done(); return dav_done(); } @@ -566,7 +575,7 @@ /* Get time period (start/end) of a component based in RFC 4791 Sec 9.9 */ -static void get_period(icalcomponent *comp, icalcomponent_kind kind, +EXPORTED void caldav_get_period(icalcomponent *comp, icalcomponent_kind kind, struct icalperiodtype *period) { icaltimezone *utc = icaltimezone_get_utc_timezone(); @@ -654,10 +663,8 @@ } else { /* Always */ - period->start = - icaltime_from_timet_with_zone(INT_MIN, 0, NULL); - period->end = - icaltime_from_timet_with_zone(INT_MAX, 0, NULL); + period->start = world_start; + period->end = world_end; } } break; @@ -679,10 +686,8 @@ } else { /* Never */ - period->start = - icaltime_from_timet_with_zone(INT_MAX, 0, NULL); - period->end = - icaltime_from_timet_with_zone(INT_MIN, 0, NULL); + period->start = world_end; + period->end = world_start; } break; @@ -701,10 +706,8 @@ } else { /* Never */ - period->start = - icaltime_from_timet_with_zone(INT_MAX, 0, NULL); - period->end = - icaltime_from_timet_with_zone(INT_MIN, 0, NULL); + period->start = world_end; + period->end = world_start; } } break; @@ -782,19 +785,22 @@ cdata->transp = transp; /* Get base dtstart and dtend */ - get_period(comp, kind, &span); + caldav_get_period(comp, kind, &span); /* See if its a recurring event */ if (icalcomponent_get_first_property(comp,ICAL_RRULE_PROPERTY) || icalcomponent_get_first_property(comp,ICAL_RDATE_PROPERTY) || icalcomponent_get_first_property(comp,ICAL_EXDATE_PROPERTY)) { + /* fetch the RRULE to check again later */ + icalproperty *rrule_prop = icalcomponent_get_first_property(comp,ICAL_RRULE_PROPERTY); + /* Recurring - find widest time range that includes events */ recurring = 1; icalcomponent_foreach_recurrence( comp, - icaltime_from_timet_with_zone(INT_MIN, 0, NULL), - icaltime_from_timet_with_zone(INT_MAX, 0, NULL), + world_start, + world_end, recur_cb, &span); @@ -802,7 +808,7 @@ while ((comp = icalcomponent_get_next_component(ical, kind))) { struct icalperiodtype period; - get_period(comp, kind, &period); + caldav_get_period(comp, kind, &period); if (icaltime_compare(period.start, span.start) < 0) memcpy(&span.start, &period.start, sizeof(struct icaltimetype)); @@ -810,6 +816,13 @@ if (icaltime_compare(period.end, span.end) > 0) memcpy(&span.end, &period.end, sizeof(struct icaltimetype)); } + + if (rrule_prop) { + struct icalrecurrencetype rrule = icalproperty_get_rrule(rrule_prop); + /* infinte rule? Ignore all times */ + if (icaltime_is_null_time(rrule.until) && !rrule.count) + memcpy(&span.end, &world_end, sizeof(struct icaltimetype)); + } } cdata->dtstart = icaltime_as_ical_string(span.start);
View file
cyrus-imapd-2.5.tar.gz/imap/caldav_db.h
Changed
@@ -73,6 +73,10 @@ struct caldav_db; +struct icaltimetype world_start; +struct icaltimetype world_end; + + #define CALDAV_CREATE 0x01 #define CALDAV_TRUNC 0x02 @@ -141,4 +145,7 @@ const char *caldav_mboxname(const char *userid, const char *name); +/* Get time period (start/end) of a component based in RFC 4791 Sec 9.9 */ +void caldav_get_period(icalcomponent *comp, icalcomponent_kind kind, struct icalperiodtype *period); + #endif /* CALDAV_DB_H */
View file
cyrus-imapd-2.5.tar.gz/imap/conversations.c
Changed
@@ -339,6 +339,9 @@ struct conversations_state *state = (struct conversations_state *)rock; conversation_storestatus(state, key, strlen(key), status); + /* just in case convdb has a higher modseq for any reason (aka deleted and + * recreated while a replica was still valid with the old user) */ + mboxname_setmodseq(key+1, status->modseq); sync_log_mailbox(key+1); /* skip the leading F */ }
View file
cyrus-imapd-2.5.tar.gz/imap/dav_reconstruct.c
Changed
@@ -89,8 +89,6 @@ void shut_down(int code); static int code = 0; -static struct caldav_db *caldavdb = NULL; - int main(int argc, char **argv) { @@ -145,9 +143,15 @@ if (buf_len(&fnamebuf)) unlink(buf_cstring(&fnamebuf)); + struct caldav_alarm_db *alarmdb = caldav_alarm_open(); + + caldav_alarm_delete_user(alarmdb, userid); + mboxlist_allusermbox(userid, do_reconstruct, NULL, 0); - caldav_close(caldavdb); + caldav_alarm_close(alarmdb); + + carddav_done(); caldav_done(); mboxlist_close();
View file
cyrus-imapd-2.5.tar.gz/imap/dlist.c
Changed
@@ -135,11 +135,14 @@ /* XXX - these two functions should be out in append.c or reserve.c * or something more general */ -EXPORTED const char *dlist_reserve_path(const char *part, struct message_guid *guid) +EXPORTED const char *dlist_reserve_path(const char *part, int isarchive, + struct message_guid *guid) { static char buf[MAX_MAILBOX_PATH]; + const char *base = isarchive ? config_archivepartitiondir(part) + : config_partitiondir(part); snprintf(buf, MAX_MAILBOX_PATH, "%s/sync./%lu/%s", - config_partitiondir(part), (unsigned long)getpid(), + base, (unsigned long)getpid(), message_guid_encode(guid)); /* gotta make sure we can create files */ if (cyrus_mkdir(buf, 0755)) { @@ -159,7 +162,7 @@ int r = 0, n; /* XXX - write to a temporary file then move in to place! */ - *fname = dlist_reserve_path(part, guid); + *fname = dlist_reserve_path(part, /*isarchive*/0, guid); /* remove any duplicates if they're still here */ unlink(*fname);
View file
cyrus-imapd-2.5.tar.gz/imap/dlist.h
Changed
@@ -96,7 +96,7 @@ char *part; /* so what if we're big! */ }; -const char *dlist_reserve_path(const char *part, struct message_guid *guid); +const char *dlist_reserve_path(const char *part, int isarchive, struct message_guid *guid); /* set fields */ void dlist_makeatom(struct dlist *dl, const char *val);
View file
cyrus-imapd-2.5.tar.gz/imap/http_caldav.c
Changed
@@ -373,6 +373,7 @@ /* Namespace for CalDAV collections */ struct namespace_t namespace_calendar = { URL_NS_CALENDAR, 0, "/dav/calendars", "/.well-known/caldav", 1 /* auth */, + MBTYPE_CALENDAR, (ALLOW_READ | ALLOW_POST | ALLOW_WRITE | ALLOW_DELETE | #ifdef HAVE_VAVAILABILITY ALLOW_CAL_AVAIL | @@ -502,36 +503,6 @@ userid, httpd_authstate, 0, 0, 0, 0, NULL); } - - /* Default calendar */ - mailboxname = caldav_mboxname(userid, SCHED_DEFAULT); - r = mboxlist_lookup(mailboxname, NULL, NULL); - if (r == IMAP_MAILBOX_NONEXISTENT) { - r = mboxlist_createmailbox(mailboxname, MBTYPE_CALENDAR, - NULL, 0, - userid, httpd_authstate, - 0, 0, 0, 0, NULL); - } - - /* Scheduling Inbox */ - mailboxname = caldav_mboxname(userid, SCHED_INBOX); - r = mboxlist_lookup(mailboxname, NULL, NULL); - if (r == IMAP_MAILBOX_NONEXISTENT) { - r = mboxlist_createmailbox(mailboxname, MBTYPE_CALENDAR, - NULL, 0, - userid, httpd_authstate, - 0, 0, 0, 0, NULL); - } - - /* Scheduling Outbox */ - mailboxname = caldav_mboxname(userid, SCHED_OUTBOX); - r = mboxlist_lookup(mailboxname, NULL, NULL); - if (r == IMAP_MAILBOX_NONEXISTENT) { - r = mboxlist_createmailbox(mailboxname, MBTYPE_CALENDAR, - NULL, 0, - userid, httpd_authstate, - 0, 0, 0, 0, NULL); - } } @@ -572,6 +543,8 @@ return HTTP_FORBIDDEN; } + tgt->prefix = namespace_calendar.prefix; + /* Default to bare-bones Allow bits for toplevel collections */ tgt->allow &= ~(ALLOW_POST|ALLOW_WRITE|ALLOW_DELETE); @@ -636,8 +609,6 @@ tgt->flags = TGT_SCHED_OUTBOX; tgt->allow |= ALLOW_POST; } - else if (!strcmp(tgt->collection, SCHED_DEFAULT)) - tgt->allow |= ALLOW_POST; else tgt->allow |= (ALLOW_POST|ALLOW_DELETE); } @@ -662,19 +633,9 @@ parts.box = buf_release(&boxbuf); /* XXX - hack to allow @domain parts for non-domain-split users */ - if (httpd_userid && !httpd_userisadmin) { - struct mboxname_parts userparts; - mboxname_init_parts(&userparts); - mboxname_userid_to_parts(httpd_userid, &userparts); - if (!parts.domain) { - /* super XXX hack for FastMail magic */ - return HTTP_NOT_FOUND; - } - if (parts.domain && !userparts.domain) { - //free(parts.domain); - XXX - fix when converting to real parts - parts.domain = NULL; - } - mboxname_free_parts(&userparts); + if (httpd_extradomain) { + //free(parts.domain); - XXX - fix when converting to real parts + parts.domain = NULL; } mboxname_parts_to_internal(&parts, tgt->mboxname); @@ -749,7 +710,7 @@ } break; default: - if (xmlStrcmp(priv->name, BAD_CAST "read-free-busy")) + if (!xmlStrcmp(priv->name, BAD_CAST "read-free-busy")) *rights |= DACL_READFB; else { /* DAV:not-supported-privilege */ @@ -1008,7 +969,8 @@ txn->resp_body.type = mime->content_type; /* Set filename of resource */ - r = annotatemore_lookup(mailbox->name, displayname_annot, /* shared */ NULL, &attrib); + r = annotatemore_lookupmask(mailbox->name, displayname_annot, httpd_userid, &attrib); + /* fall back to last part of mailbox name */ if (r || !attrib.len) buf_setcstr(&attrib, strrchr(mailbox->name, '.') + 1); buf_reset(&txn->buf); @@ -1112,6 +1074,7 @@ struct buf *url = &txn->buf; static size_t inboxlen = 0; static size_t outboxlen = 0; + int rights; char *shortname; mbentry_t *mbentry = NULL; size_t len; @@ -1136,7 +1099,10 @@ /* Lookup the mailbox and make sure its readable */ r = http_mlookup(name, &mbentry, NULL); - if (r || !mbentry->acl || !(cyrus_acl_myrights(httpd_authstate, mbentry->acl) & ACL_READ)) + if (r) goto done; + + rights = httpd_myrights(httpd_authstate, mbentry->acl); + if ((rights & DACL_READ) != DACL_READ) goto done; /* Send a body chunk once in a while */ @@ -1146,8 +1112,8 @@ } /* Lookup DAV:displayname */ - r = annotatemore_lookup(name, displayname_annot, - /* shared */ NULL, &displayname); + r = annotatemore_lookupmask(name, displayname_annot, httpd_userid, &displayname); + /* fall back to the last part of the mailbox name */ if (r || !displayname.len) buf_setcstr(&displayname, shortname); /* Add available calendar with link */ @@ -1227,7 +1193,7 @@ /* Create base URL for calendars */ http_proto_host(txn->req_hdrs, &proto, &host); - assert(!buf_len(&txn->buf)); + buf_reset(&txn->buf); buf_printf(&txn->buf, "%s://%s%s", proto, host, txn->req_tgt.path); /* Generate list of calendars */ @@ -1282,7 +1248,7 @@ } /* Check ACL for current user */ - rights = mbentry->acl ? cyrus_acl_myrights(httpd_authstate, mbentry->acl) : 0; + rights = httpd_myrights(httpd_authstate, mbentry->acl); if ((rights & DACL_READ) != DACL_READ) { /* DAV:need-privileges */ txn->error.precond = DAV_NEED_PRIVS; @@ -1368,7 +1334,7 @@ } /* Get rights for current user */ - rights = mbentry->acl ? cyrus_acl_myrights(httpd_authstate, mbentry->acl) : 0; + rights = httpd_myrights(httpd_authstate, mbentry->acl); mboxlist_entry_free(&mbentry); /* Read body */ @@ -1504,7 +1470,6 @@ else if (!icalrestriction_check(ical)) { txn->error.precond = CALDAV_VALID_OBJECT; if ((txn->error.desc = get_icalrestriction_errstr(ical))) { - assert(!buf_len(&txn->buf)); buf_setcstr(&txn->buf, txn->error.desc); txn->error.desc = buf_cstring(&txn->buf); } @@ -1565,6 +1530,7 @@ (strcmp(cdata->dav.mailbox, txn->req_tgt.mboxname) || strcmp(cdata->dav.resource, txn->req_tgt.resource))) { + buf_reset(&txn->buf); buf_printf(&txn->buf, "%s/user/%s/%s/%s", namespace_calendar.prefix, userid, strrchr(cdata->dav.mailbox, '.')+1, @@ -1605,6 +1571,8 @@ buf_free(&msg_buf); } +#if 0 +FastMail hack - make configurable later if (!strcmp(sparam.userid, userid)) { /* Organizer scheduling object resource */ sched_request(organizer, &sparam, oldical, ical, 0); @@ -1613,6 +1581,7 @@ /* Attendee scheduling object resource */ sched_reply(userid, oldical, ical); } +#endif if (oldical) icalcomponent_free(oldical); @@ -1703,6 +1672,18 @@ newp->duration = icaldurationtype_null_duration(); }
View file
cyrus-imapd-2.5.tar.gz/imap/http_carddav.c
Changed
@@ -261,8 +261,8 @@ /* Namespace for Carddav collections */ struct namespace_t namespace_addressbook = { - URL_NS_ADDRESSBOOK, 0, "/dav/addressbooks", "/.well-known/carddav", - 1 /* auth */, + URL_NS_ADDRESSBOOK, 0, "/dav/addressbooks", "/.well-known/carddav", 1 /* auth */, + MBTYPE_ADDRESSBOOK, #if 0 /* Until Apple Contacts fixes their add-member implementation */ (ALLOW_READ | ALLOW_POST | ALLOW_WRITE | ALLOW_DELETE | ALLOW_DAV | ALLOW_WRITECOL | ALLOW_CARD), @@ -389,20 +389,6 @@ userid, httpd_authstate, 0, 0, 0, 0, NULL); } - if (r) return; - - /* Default addressbook */ - buf_setcstr(&boxbuf, config_getstring(IMAPOPT_ADDRESSBOOKPREFIX)); - buf_printf(&boxbuf, ".%s", DEFAULT_ADDRBOOK); - mailboxname = mboxname_user_mbox(userid, buf_cstring(&boxbuf)); - r = mboxlist_lookup(mailboxname, NULL, NULL); - if (r == IMAP_MAILBOX_NONEXISTENT) { - /* XXX - set rights */ - r = mboxlist_createmailbox(mailboxname, MBTYPE_ADDRESSBOOK, - NULL, 0, - userid, httpd_authstate, - 0, 0, 0, 0, NULL); - } } @@ -443,6 +429,8 @@ return HTTP_FORBIDDEN; } + tgt->prefix = namespace_addressbook.prefix; + /* Default to bare-bones Allow bits for toplevel collections */ tgt->allow &= ~(ALLOW_POST|ALLOW_WRITE|ALLOW_DELETE); @@ -525,15 +513,9 @@ parts.box = buf_release(&boxbuf); /* XXX - hack to allow @domain parts for non-domain-split users */ - if (httpd_userid && !httpd_userisadmin) { - struct mboxname_parts userparts; - mboxname_init_parts(&userparts); - mboxname_userid_to_parts(httpd_userid, &userparts); - if (parts.domain && !userparts.domain) { - //free(parts.domain); - XXX fix when converting to real parts - parts.domain = NULL; - } - mboxname_free_parts(&userparts); + if (httpd_extradomain) { + //free(parts.domain); - XXX fix when converting to real parts + parts.domain = NULL; } mboxname_parts_to_internal(&parts, tgt->mboxname);
View file
cyrus-imapd-2.5.tar.gz/imap/http_dav.c
Changed
@@ -95,6 +95,8 @@ { XML_NS_ISCHED, NULL }, { XML_NS_CS, "CS" }, { XML_NS_CYRUS, "CY" }, + { XML_NS_USERFLAG, "UF" }, + { XML_NS_SYSFLAG, "SF" }, }; /* PROPFIND modes */ @@ -193,6 +195,7 @@ /* Namespace for WebDAV principals */ struct namespace_t namespace_principal = { URL_NS_PRINCIPAL, 0, "/dav/principals", NULL, 1 /* auth */, + /*mbtype */ 0, ALLOW_READ | ALLOW_DAV, &my_dav_init, NULL, NULL, NULL, { @@ -701,7 +704,7 @@ struct propstat *propstat; }; -/* Add a response tree to 'root' for the specified href and +/* Add a response tree to 'root' for the specified href and either error code or property list */ static int xml_add_response(struct propfind_ctx *fctx, long code) { @@ -820,8 +823,6 @@ } } - fctx->record = NULL; - return 0; } @@ -1391,8 +1392,8 @@ xmlNodePtr set; if (!fctx->mailbox) return HTTP_NOT_FOUND; - if (((rights = cyrus_acl_myrights(fctx->authstate, fctx->mailbox->acl)) - & DACL_READ) != DACL_READ) { + rights = httpd_myrights(fctx->authstate, fctx->mailbox->acl); + if ((rights & DACL_READ) != DACL_READ) { return HTTP_UNAUTHORIZED; } @@ -1400,8 +1401,10 @@ if (fctx->userisadmin) { rights |= DACL_ADMIN; } - else if (mboxname_userownsmailbox(fctx->int_userid, fctx->mailbox->name)) { + else if (mboxname_userownsmailbox(httpd_userid, fctx->mailbox->name)) { rights |= config_implicitrights; + /* we always allow admin by the owner in DAV */ + rights |= DACL_ADMIN; } /* Build the rest of the XML response */ @@ -1432,15 +1435,17 @@ struct propstat propstat[], void *rock __attribute__((unused))) { - int rights; xmlNodePtr acl; char *aclstr, *userid; unsigned flags = 0; if (!fctx->mailbox) return HTTP_NOT_FOUND; - if (!((rights = cyrus_acl_myrights(fctx->authstate, fctx->mailbox->acl)) - & DACL_ADMIN)) { - return HTTP_UNAUTHORIZED; + + /* owner has implicit admin rights */ + if (!mboxname_userownsmailbox(httpd_userid, fctx->mailbox->name)) { + int rights = httpd_myrights(fctx->authstate, fctx->mailbox->acl); + if (!(rights & DACL_ADMIN)) + return HTTP_UNAUTHORIZED; } if (fctx->req_tgt->namespace == URL_NS_CALENDAR) { @@ -1462,6 +1467,7 @@ userid = aclstr = xstrdup(fctx->mailbox->acl); while (userid) { + int rights; char *rightstr, *nextid; xmlNodePtr ace, node; int deny = 0; @@ -1469,7 +1475,7 @@ rightstr = strchr(userid, '\t'); if (!rightstr) break; *rightstr++ = '\0'; - + nextid = strchr(rightstr, '\t'); if (!nextid) break; *nextid++ = '\0'; @@ -1487,18 +1493,24 @@ ace = xmlNewChild(acl, NULL, BAD_CAST "ace", NULL); /* XXX Need to check for groups. - * Is there any IMAP equivalent to "unauthenticated"? - * Is there any DAV equivalent to "anonymous"? */ node = xmlNewChild(ace, NULL, BAD_CAST "principal", NULL); if (!strcmp(userid, fctx->userid)) xmlNewChild(node, NULL, BAD_CAST "self", NULL); - else if ((strlen(userid) == fctx->req_tgt->userlen) && - !strncmp(userid, fctx->req_tgt->user, fctx->req_tgt->userlen)) + else if (mboxname_userownsmailbox(userid, fctx->mailbox->name)) { xmlNewChild(node, NULL, BAD_CAST "owner", NULL); + /* we always allow admin by the owner in DAV */ + rights |= DACL_ADMIN; + } else if (!strcmp(userid, "anyone")) xmlNewChild(node, NULL, BAD_CAST "authenticated", NULL); + /* XXX - well, it's better than a user called 'anonymous' + * Is there any IMAP equivalent to "unauthenticated"? + * Is there any DAV equivalent to "anonymous"? + */ + else if (!strcmp(userid, "anonymous")) + xmlNewChild(node, NULL, BAD_CAST "unauthenticated", NULL); else { buf_reset(&fctx->buf); buf_printf(&fctx->buf, "%s/user/%s/", @@ -1599,8 +1611,13 @@ buf_reset(&fctx->buf); if (!xmlStrcmp(name, BAD_CAST "quota-available-bytes")) { /* Calculate limit in bytes and subtract usage */ - quota_t limit = fctx->quota.limits[QUOTA_STORAGE] * quota_units[QUOTA_STORAGE]; - buf_printf(&fctx->buf, QUOTA_T_FMT, limit - fctx->quota.useds[QUOTA_STORAGE]); + if (fctx->quota.limits[QUOTA_STORAGE] < 0) { // unlimited + buf_printf(&fctx->buf, QUOTA_T_FMT, (quota_t)INT64_MAX); + } + else { + quota_t limit = fctx->quota.limits[QUOTA_STORAGE] * quota_units[QUOTA_STORAGE]; + buf_printf(&fctx->buf, QUOTA_T_FMT, limit - fctx->quota.useds[QUOTA_STORAGE]); + } } else if (fctx->record) { /* Bytes used by resource */ @@ -1689,6 +1706,9 @@ { if (!fctx->mailbox || fctx->record) return HTTP_NOT_FOUND; + /* not defined on the top-level collection either (aka #calendars) */ + if (!fctx->req_tgt->collection) return HTTP_NOT_FOUND; + buf_reset(&fctx->buf); buf_printf(&fctx->buf, XML_NS_CYRUS "sync/%u-" MODSEQ_FMT, fctx->mailbox->i.uidvalidity, @@ -1738,6 +1758,155 @@ return r; } +static struct flaggedresources { + const char *name; + int flag; +} fres[] = { + { "answered", FLAG_ANSWERED }, + { "flagged", FLAG_FLAGGED }, + { "seen", FLAG_SEEN }, + { NULL, 0 } /* last is always NULL */ +}; + +/* Callback to write a property to annotation DB */ +static int proppatch_toresource(xmlNodePtr prop, unsigned set, + struct proppatch_ctx *pctx, + struct propstat propstat[], + void *rock __attribute__((unused))) +{ + xmlChar *freeme = NULL; + annotate_state_t *astate = NULL; + struct buf value = BUF_INITIALIZER; + int r = 1; /* default to error */ + + /* flags only store "exists" */ + + if (!strcmp((const char *)prop->ns->href, XML_NS_SYSFLAG)) { + struct flaggedresources *frp; + int isset; + for (frp = fres; frp->name; frp++) { + if (strcasecmp((const char *)prop->name, frp->name)) continue; + r = 0; /* ok to do nothing */ + isset = pctx->record->system_flags & frp->flag; + if (set) { + if (isset) goto done; + pctx->record->system_flags |= frp->flag; + } + else { + if (!isset) goto done; + pctx->record->system_flags &= ~frp->flag; + } + r = mailbox_rewrite_index_record(pctx->mailbox, pctx->record); + goto done; + } + goto done; + } +
View file
cyrus-imapd-2.5.tar.gz/imap/http_dav.h
Changed
@@ -72,6 +72,8 @@ #define XML_NS_ISCHED "urn:ietf:params:xml:ns:ischedule" #define XML_NS_CS "http://calendarserver.org/ns/" #define XML_NS_CYRUS "http://cyrusimap.org/ns/" +#define XML_NS_USERFLAG "http://cyrusimap.org/ns/userflag/" +#define XML_NS_SYSFLAG "http://cyrusimap.org/ns/sysflag/" /* Index into known namespace array */ enum { @@ -254,7 +256,6 @@ unsigned depth; /* 0 = root, 1 = calendar, 2 = resrc */ unsigned prefer; /* bitmask of client preferences */ const char *userid; /* userid client has logged in as */ - 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 collection */ @@ -291,6 +292,7 @@ struct request_target_t *req_tgt; /* parsed request target URL */ unsigned meth; /* requested Method */ struct mailbox *mailbox; /* mailbox related to the collection */ + struct index_record *record; /* record of the specific resource */ const struct prop_entry *lprops; /* Array of known "live" properties */ xmlNodePtr root; /* root node to add to XML tree */ xmlNsPtr *ns; /* Array of our supported namespaces */ @@ -364,9 +366,11 @@ 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 */ - db_delete_proc_t delete_resource; /* delete a specific resource */ - db_delmbox_proc_t delete_mbox; /* delete all resources in mailbox */ + /* XXX - convert these to lock management only. For everything else, + * we need to go via mailbox.c for replication support */ + db_write_proc_t write_resourceLOCKONLY; /* write a specific resource */ + db_delete_proc_t delete_resourceLOCKONLY; /* delete a specific resource */ + db_delmbox_proc_t delete_mboxDONTUSE; /* delete all resources in mailbox */ }; /*
View file
cyrus-imapd-2.5.tar.gz/imap/http_dblookup.c
Changed
@@ -53,6 +53,7 @@ /* Namespace for DB lookups */ struct namespace_t namespace_dblookup = { URL_NS_DBLOOKUP, /*enabled*/1, "/dblookup", NULL, 0 /* auth */, + /*mbtype*/0, ALLOW_READ, NULL, NULL, NULL, NULL, {
View file
cyrus-imapd-2.5.tar.gz/imap/http_ischedule.c
Changed
@@ -115,6 +115,7 @@ struct namespace_t namespace_ischedule = { URL_NS_ISCHEDULE, 0, "/ischedule", ISCHED_WELLKNOWN_URI, 0 /* auth */, + /*mbtype*/0, (ALLOW_READ | ALLOW_POST | ALLOW_ISCHEDULE), isched_init, NULL, NULL, isched_shutdown, { @@ -140,6 +141,7 @@ struct namespace_t namespace_domainkey = { URL_NS_DOMAINKEY, 0, "/domainkeys", "/.well-known/domainkey", 0 /* auth */, + /*mbtype*/0, ALLOW_READ, NULL, NULL, NULL, NULL, { { NULL, NULL }, /* ACL */
View file
cyrus-imapd-2.5.tar.gz/imap/http_rss.c
Changed
@@ -109,6 +109,7 @@ /* Namespace for RSS feeds of mailboxes */ struct namespace_t namespace_rss = { URL_NS_RSS, 0, "/rss", NULL, 1 /* auth */, ALLOW_READ, + /*mbtype*/0, rss_init, NULL, NULL, NULL, { { NULL, NULL }, /* ACL */ @@ -376,6 +377,7 @@ struct buf *buf = &lrock->txn->resp_body.payload; if (name) { + int rights; mbentry_t *mbentry = NULL; int r; @@ -387,11 +389,13 @@ /* Lookup the mailbox and make sure its readable */ r = http_mlookup(name, &mbentry, NULL); - if (r || !mbentry->acl || !(cyrus_acl_myrights(httpd_authstate, mbentry->acl) & ACL_READ)) { - mboxlist_entry_free(&mbentry); - return 0; - } + if (r) return 0; + + rights = httpd_myrights(httpd_authstate, mbentry->acl); mboxlist_entry_free(&mbentry); + + if ((rights & ACL_READ) != ACL_READ) + return 0; } if (name &&
View file
cyrus-imapd-2.5.tar.gz/imap/http_timezone.c
Changed
@@ -129,7 +129,9 @@ /* Namespace for TIMEZONE feeds of mailboxes */ struct namespace_t namespace_timezone = { - URL_NS_TIMEZONE, 0, "/timezone", TIMEZONE_WELLKNOWN_URI, 0 /* auth */, ALLOW_READ, + URL_NS_TIMEZONE, 0, "/timezone", TIMEZONE_WELLKNOWN_URI, 0 /* auth */, + /*mbtype*/0, + ALLOW_READ, timezone_init, NULL, NULL, timezone_shutdown, { { NULL, NULL }, /* ACL */
View file
cyrus-imapd-2.5.tar.gz/imap/httpd.c
Changed
@@ -68,6 +68,7 @@ #include "httpd.h" #include "http_proxy.h" +#include "acl.h" #include "assert.h" #include "util.h" #include "iptostring.h" @@ -251,7 +252,9 @@ /* Namespace to fetch static content from filesystem */ struct namespace_t namespace_default = { - URL_NS_DEFAULT, 1, "", NULL, 0 /* no auth */, ALLOW_READ, + URL_NS_DEFAULT, 1, "", NULL, 0 /* no auth */, + /*mbtype*/0, + ALLOW_READ, NULL, NULL, NULL, NULL, { { NULL, NULL }, /* ACL */ @@ -1180,6 +1183,7 @@ if ((namespace = namespaces[i])) { txn.req_tgt.namespace = namespace->id; txn.req_tgt.allow = namespace->allow; + txn.req_tgt.mboxtype = namespace->mboxtype; /* Check if method is supported in this namespace */ meth_t = &namespace->methods[txn.meth]; @@ -4052,3 +4056,11 @@ return 0; } + +/* simple wrapper to implicity add READFB if we have the READ ACL */ +EXPORTED int httpd_myrights(struct auth_state *authstate, const char *acl) +{ + int rights = acl ? cyrus_acl_myrights(authstate, acl) : 0; + if ((rights & DACL_READ) == DACL_READ) rights |= DACL_READFB; + return rights; +}
View file
cyrus-imapd-2.5.tar.gz/imap/httpd.h
Changed
@@ -208,7 +208,9 @@ size_t reslen; unsigned flags; /* target-specific flags/meta-data */ unsigned long allow; /* bitmask of allowed features/methods */ + int mboxtype; /* mailbox types to match on findall */ char mboxname[MAX_MAILBOX_BUFFER+1]; + const char *prefix; /* namespace prefix */ }; /* Request target flags */ @@ -405,6 +407,7 @@ const char *prefix; /* Prefix of URL path denoting namespace */ const char *well_known; /* Any /.well-known/ URI */ unsigned need_auth; /* Do we need to auth for this namespace? */ + int mboxtype; /* what type of mailbox can be seen in this namespace? */ unsigned long allow; /* Bitmask of allowed features/methods */ void (*init)(struct buf *serverinfo); void (*auth)(const char *userid); @@ -484,4 +487,6 @@ extern int read_body(struct protstream *pin, hdrcache_t hdrs, struct body_t *body, const char **errstr); +extern int httpd_myrights(struct auth_state *authstate, const char *acl); + #endif /* HTTPD_H */
View file
cyrus-imapd-2.5.tar.gz/imap/imapd.c
Changed
@@ -177,6 +177,7 @@ static void *imapd_tls_comp = NULL; /* TLS compression method, if any */ static int imapd_compress_done = 0; /* have we done a successful compress? */ static const char *plaintextloginalert = NULL; +static int ignorequota = 0; #define QUIRK_SEARCHFUZZY (1<<0) static struct id_data { @@ -849,7 +850,7 @@ snmp_connect(); /* ignore return code */ snmp_set_str(SERVER_NAME_VERSION,cyrus_version()); - while ((opt = getopt(argc, argv, "sp:N")) != EOF) { + while ((opt = getopt(argc, argv, "Np:sq")) != EOF) { switch (opt) { case 's': /* imaps (do starttls right away) */ imaps = 1; @@ -866,6 +867,9 @@ * you know what you're doing! */ nosaslpasswdcheck = 1; break; + case 'q': /* don't enforce quotas */ + ignorequota = 1; + break; default: break; } @@ -3533,7 +3537,7 @@ /* local mailbox */ if (!r) { qdiffs[QUOTA_MESSAGE] = 1; - r = append_check(mailboxname, imapd_authstate, ACL_INSERT, qdiffs); + r = append_check(mailboxname, imapd_authstate, ACL_INSERT, ignorequota ? NULL : qdiffs); } if (r) { eatline(imapd_in, ' '); @@ -3687,7 +3691,7 @@ qdiffs[QUOTA_MESSAGE] = stages.count; r = append_setup(&appendstate, mailboxname, imapd_userid, imapd_authstate, ACL_INSERT, - qdiffs, &imapd_namespace, + ignorequota ? NULL : qdiffs, &imapd_namespace, (imapd_userisadmin || imapd_userisproxyadmin), EVENT_MESSAGE_APPEND); } @@ -6073,7 +6077,8 @@ r = index_copy(imapd_index, sequence, usinguid, mailboxname, ©uid, !config_getswitch(IMAPOPT_SINGLEINSTANCESTORE), &imapd_namespace, - (imapd_userisadmin || imapd_userisproxyadmin), ismove); + (imapd_userisadmin || imapd_userisproxyadmin), ismove, + ignorequota); } imapd_check(NULL, ismove || usinguid); @@ -6214,7 +6219,7 @@ if (!r) { char *copy = xstrdup(mailboxname); lcase(copy); - if (strstr(copy, "inbox.inbox")) + if (strstr(copy, "inbox.inbox.")) r = IMAP_MAILBOX_BADNAME; free(copy); } @@ -6356,7 +6361,7 @@ int autocreatequotamessage = config_getint(IMAPOPT_AUTOCREATEQUOTAMSG); if (!r && ((autocreatequotastorage > 0) || (autocreatequotamessage > 0))) { int res; - int newquotas[QUOTA_NUMRESOURCES]; + quota_t newquotas[QUOTA_NUMRESOURCES]; for (res = 0 ; res < QUOTA_NUMRESOURCES ; res++) newquotas[res] = QUOTA_UNLIMITED; @@ -6640,6 +6645,14 @@ user_copyquotaroot(name, text->newmailboxname); user_renameacl(text->namespace, text->newmailboxname, text->acl_olduser, text->acl_newuser); +#ifdef WITH_DAV + if (mbentry->mbtype & (MBTYPE_CALENDAR|MBTYPE_ADDRESSBOOK)) { + struct mailbox *mailbox = NULL; + r = mailbox_open_irl(text->newmailboxname, &mailbox); + if (!r) r = mailbox_add_dav(mailbox); + mailbox_close(&mailbox); + } +#endif //WITH_DAV } @@ -7748,7 +7761,7 @@ prot_putc('(', o); for (res = 0 ; res < QUOTA_NUMRESOURCES ; res++) { if (q->limits[res] >= 0) { - prot_printf(o, "%s%s " QUOTA_T_FMT " %d", + prot_printf(o, "%s%s " QUOTA_T_FMT " " QUOTA_T_FMT, sep, quota_names[res], q->useds[res]/quota_units[res], q->limits[res]); @@ -7766,7 +7779,7 @@ prot_putc('(', o); for (res = 0 ; res < QUOTA_NUMRESOURCES ; res++) { if (q->limits[res] >= 0) { - prot_printf(o, "%s%s %d", + prot_printf(o, "%s%s " QUOTA_T_FMT, sep, quota_names[res], q->limits[res]); sep = " "; @@ -7986,7 +7999,7 @@ */ void cmd_setquota(const char *tag, const char *quotaroot) { - int newquotas[QUOTA_NUMRESOURCES]; + quota_t newquotas[QUOTA_NUMRESOURCES]; int res; int c; int force = 0; @@ -8101,7 +8114,7 @@ prot_printf(imapd_out, "%s NO %s\r\n", tag, error_message(r)); return; } - + prot_printf(imapd_out, "%s OK %s\r\n", tag, error_message(IMAP_OK_COMPLETED)); return;
View file
cyrus-imapd-2.5.tar.gz/imap/imapparse.c
Changed
@@ -501,6 +501,14 @@ } while (c == ' '); + /* rfc4731: + * If the list of result options is empty, that requests the server to + * return an ESEARCH response instead of the SEARCH response. This is + * equivalent to "(ALL)". + */ + if (!searchargs->returnopts) + searchargs->returnopts = SEARCH_RETURN_ALL; + if (c != ')') { prot_printf(pout, "%s BAD Missing close parenthesis in Search\r\n",
View file
cyrus-imapd-2.5.tar.gz/imap/index.c
Changed
@@ -2774,7 +2774,8 @@ int nolink, struct namespace *namespace, int isadmin, - int ismove) + int ismove, + int ignorequota) { struct copyargs copyargs; int i; @@ -2837,7 +2838,7 @@ r = append_setup_mbox(&appendstate, destmailbox, state->userid, state->authstate, ACL_INSERT, - qptr, namespace, isadmin, + ignorequota ? NULL : qptr, namespace, isadmin, ismove ? EVENT_MESSAGE_MOVE : EVENT_MESSAGE_COPY); if (r) goto done;
View file
cyrus-imapd-2.5.tar.gz/imap/index.h
Changed
@@ -256,14 +256,15 @@ extern int index_scan(struct index_state *state, const char *contents); extern int index_copy(struct index_state *state, - char *sequence, + char *sequence, int usinguid, - char *name, + char *name, char **copyuidp, int nolink, struct namespace *namespace, int isadmin, - int ismove); + int ismove, + int ignorequota); extern int find_thread_algorithm(char *arg); extern int index_open(const char *name, struct index_init *init,
View file
cyrus-imapd-2.5.tar.gz/imap/mailbox.c
Changed
@@ -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,11 @@ #include "annotate.h" #include "assert.h" +#ifdef WITH_DAV #include "caldav_db.h" +#include "caldav_alarm.h" #include "carddav_db.h" +#endif #include "crc32.h" #include "md5.h" #include "exitcodes.h" @@ -801,15 +806,6 @@ fname = mailbox_record_fname(mailbox, record); msgfd = open(fname, O_RDONLY, 0666); - if (msgfd == -1) { - /* let's try the other file, just in case we're in the middle - * of an archiving */ - if (record->system_flags & FLAG_ARCHIVED) - fname = mailbox_spool_fname(mailbox, record->uid); - else - fname = mailbox_archive_fname(mailbox, record->uid); - msgfd = open(fname, O_RDONLY, 0666); - } if (msgfd == -1) return errno; if (fstat(msgfd, &sbuf) == -1) { @@ -2405,7 +2401,8 @@ MD5Update(&ctx, " ", 1); MD5Update(&ctx, entry, strlen(entry)); MD5Update(&ctx, " ", 1); - MD5Update(&ctx, userid, strlen(userid)); + if (userid) + MD5Update(&ctx, userid, strlen(userid)); MD5Update(&ctx, " ", 1); MD5Update(&ctx, value->s, value->len); @@ -2660,6 +2657,7 @@ return r; } +#ifdef WITH_DAV static int mailbox_update_carddav(struct mailbox *mailbox, struct index_record *old, struct index_record *new) @@ -2828,8 +2826,19 @@ /* does it still come from this UID? */ if (cdata->dav.imap_uid != new->uid) goto done; + /* prepare alarm data for removal */ + struct caldav_alarm_data alarmdata = { + .mailbox = cdata->dav.mailbox, + .resource = cdata->dav.resource, + }; + /* delete entry */ r = caldav_delete(caldavdb, cdata->dav.rowid, 0); + + /* and associated alarms */ + struct caldav_alarm_db *alarmdb = caldav_alarm_open(); + caldav_alarm_delete_all(alarmdb, &alarmdata); + caldav_alarm_close(alarmdb); } else { struct buf msg_buf = BUF_INITIALIZER; @@ -2854,6 +2863,38 @@ caldav_make_entry(ical, cdata); r = caldav_write(caldavdb, cdata, 0); + if (r) { + icalcomponent_free(ical); + goto done; + } + + struct caldav_alarm_db *alarmdb = caldav_alarm_open(); + caldav_alarm_begin(alarmdb); + + struct caldav_alarm_data alarmdata = { + .mailbox = cdata->dav.mailbox, + .resource = cdata->dav.resource, + }; + + /* remove old ones */ + int rc = caldav_alarm_delete_all(alarmdb, &alarmdata); + + int i; + for (i = CALDAV_ALARM_ACTION_FIRST; i <= CALDAV_ALARM_ACTION_LAST; i++) { + /* prepare alarm data */ + if (!rc && + !caldav_alarm_prepare(ical, &alarmdata, i, + icaltime_current_time_with_zone(icaltimezone_get_utc_timezone()))) { + rc = caldav_alarm_add(alarmdb, &alarmdata); + caldav_alarm_fini(&alarmdata); + } + } + + if (rc) + caldav_alarm_rollback(alarmdb); + else + caldav_alarm_commit(alarmdb); + caldav_alarm_close(alarmdb); icalcomponent_free(ical); } @@ -2880,6 +2921,7 @@ 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 +3148,10 @@ { 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; @@ -3175,7 +3219,7 @@ /* handle immediate expunges here... */ if (immediate && (record->system_flags & FLAG_EXPUNGED)) - record->system_flags |= FLAG_UNLINKED; + record->system_flags |= FLAG_UNLINKED | FLAG_NEEDS_CLEANUP; /* make sure highestmodseq gets updated unless we're * being silent about it (i.e. marking an already EXPUNGED @@ -3378,34 +3422,58 @@ return mailbox_refresh_index_map(mailbox); } -static void mailbox_message_unlink(struct mailbox *mailbox, - struct index_record *record) +static void mailbox_message_cleanup(struct mailbox *mailbox, + struct index_record *record) { - const char *fname = mailbox_record_fname(mailbox, record); + const char *spoolfname = mailbox_spool_fname(mailbox, record->uid); + const char *archivefname = mailbox_archive_fname(mailbox, record->uid); int r; - /* XXX - reports errors other than ENOENT ? */ + if (record->system_flags & FLAG_UNLINKED) { + /* try to delete both */ - /* no error, we removed a file */ - if (unlink(fname) == 0) { - if (config_auditlog) - syslog(LOG_NOTICE, "auditlog: unlink sessionid=<%s> " - "mailbox=<%s> uniqueid=<%s> uid=<%u>", - session_id(), mailbox->name, mailbox->uniqueid, record->uid); + if (unlink(spoolfname) == 0) { + if (config_auditlog) + syslog(LOG_NOTICE, "auditlog: unlink sessionid=<%s> " + "mailbox=<%s> uniqueid=<%s> uid=<%u>", + session_id(), mailbox->name, mailbox->uniqueid, record->uid); + } + + if (unlink(archivefname) == 0) { + if (config_auditlog) + syslog(LOG_NOTICE, "auditlog: unlinkarchive sessionid=<%s> " + "mailbox=<%s> uniqueid=<%s> uid=<%u>", + session_id(), mailbox->name, mailbox->uniqueid, record->uid); + } + + r = mailbox_get_annotate_state(mailbox, record->uid, NULL); + if (r) { + syslog(LOG_ERR, "IOERROR: failed to open annotations %s %u: %s", + mailbox->name, record->uid, error_message(r)); + return; + } + + r = annotate_msg_cleanup(mailbox, record->uid); + if (r) { + syslog(LOG_ERR, "IOERROR: failed to cleanup annotations %s %u: %s", + mailbox->name, record->uid, error_message(r)); + return; + } } - r = mailbox_get_annotate_state(mailbox, record->uid, NULL); - if (r) { - syslog(LOG_ERR, "IOERROR: failed to open annotations %s %u: %s", - mailbox->name, record->uid, error_message(r));
View file
cyrus-imapd-2.5.tar.gz/imap/mailbox.h
Changed
@@ -315,14 +315,15 @@ #define FLAG_DELETED (1<<2) #define FLAG_DRAFT (1<<3) #define FLAG_SEEN (1<<4) +#define FLAG_NEEDS_CLEANUP (1<<28) #define FLAG_ARCHIVED (1<<29) #define FLAG_UNLINKED (1<<30) #define FLAG_EXPUNGED (1U<<31) #define FLAGS_SYSTEM (FLAG_ANSWERED|FLAG_FLAGGED|FLAG_DELETED|FLAG_DRAFT|FLAG_SEEN) -#define FLAGS_INTERNAL (FLAG_ARCHIVED|FLAG_UNLINKED|FLAG_EXPUNGED) +#define FLAGS_INTERNAL (FLAG_NEEDS_CLEANUP|FLAG_ARCHIVED|FLAG_UNLINKED|FLAG_EXPUNGED) /* for replication */ -#define FLAGS_LOCAL (FLAG_ARCHIVED|FLAG_UNLINKED) +#define FLAGS_LOCAL (FLAG_NEEDS_CLEANUP|FLAG_ARCHIVED|FLAG_UNLINKED) #define FLAGS_GLOBAL (FLAGS_SYSTEM|FLAG_EXPUNGED) #define OPT_POP3_NEW_UIDL (1<<0) /* added for Outlook stupidity */ @@ -577,7 +578,9 @@ 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,
View file
cyrus-imapd-2.5.tar.gz/imap/mbdump.c
Changed
@@ -509,7 +509,7 @@ r = quota_read(&q, NULL, 0); if (!r) { - prot_printf(pout, "%d", q.limits[QUOTA_STORAGE]); + prot_printf(pout, QUOTA_T_FMT, q.limits[QUOTA_STORAGE]); } else { prot_printf(pout, "NIL"); if (r == IMAP_QUOTAROOT_NONEXISTENT) r = 0; @@ -630,6 +630,7 @@ fname = mboxkey_getpath(userid); ftag = "MBOXKEY"; break; +#ifdef WITH_DAV case DAV_DB: { struct buf dav_file = BUF_INITIALIZER; @@ -638,6 +639,7 @@ ftag = "DAV"; break; } +#endif // WITH_DAV default: fatal("unknown user data file", EC_OSFILE); } @@ -725,7 +727,7 @@ } prot_printliteral(pout, quota_names[res], strlen(quota_names[res])); prot_putc(' ', pout); - prot_printf(pout, "%d", q.limits[res]); + prot_printf(pout, QUOTA_T_FMT, q.limits[res]); } prot_putc(')', pout); } @@ -833,8 +835,8 @@ char *mboxkey_file = NULL; quota_t old_quota_usage[QUOTA_NUMRESOURCES]; int res; - int newquotas[QUOTA_NUMRESOURCES]; - int quotalimit = -1; + quota_t newquotas[QUOTA_NUMRESOURCES]; + quota_t quotalimit = -1; annotate_state_t *astate = NULL; memset(&file, 0, sizeof(file)); @@ -861,7 +863,7 @@ if (!strcmp(data.s, "NIL")) { /* Remove any existing quotaroot */ mboxlist_unsetquota(mbname); - } else if (sscanf(data.s, "%d", "alimit) == 1) { + } else if (sscanf(data.s, QUOTA_T_FMT, "alimit) == 1) { /* Set a Quota (may be -1 for "unlimited") */ for (res = 0; res < QUOTA_NUMRESOURCES; res++) { newquotas[res] = QUOTA_UNLIMITED; @@ -1072,12 +1074,14 @@ 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);
View file
cyrus-imapd-2.5.tar.gz/imap/mboxevent.c
Changed
@@ -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" @@ -76,12 +78,15 @@ 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) #define QUOTA_EVENTS (EVENT_QUOTA_EXCEED|EVENT_QUOTA_WITHIN|EVENT_QUOTA_CHANGE) +#ifdef WITH_DAV +#define CALENDAR_EVENTS (EVENT_CALENDAR_ALARM) +#endif //WITH_DAV #define FILL_STRING_PARAM(e,p,v) e->params[p].value = (uint64_t)v; \ e->params[p].type = EVENT_PARAM_STRING; \ @@ -110,6 +115,7 @@ /* ordered to optimize the parsing of the notification message */ { { EVENT_TIMESTAMP, "timestamp", EVENT_PARAM_STRING, 0, 0 }, { EVENT_SERVICE, "service", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_SERVERFQDN, "serverFQDN", EVENT_PARAM_STRING, 0, 0 }, { EVENT_SERVER_ADDRESS, "serverAddress", EVENT_PARAM_STRING, 0, 0 }, { EVENT_CLIENT_ADDRESS, "clientAddress", EVENT_PARAM_STRING, 0, 0 }, { EVENT_OLD_MAILBOX_ID, "oldMailboxID", EVENT_PARAM_STRING, 0, 0 }, @@ -129,12 +135,39 @@ { 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 { EVENT_MBTYPE, "vnd.cmu.mbtype", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_MAILBOX_ACL, "vnd.cmu.mailboxACL", 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 }, + +#ifdef WITH_DAV + /* calendar params for calalarmd/notifyd */ + { EVENT_CALENDAR_ALARM_TIME, "alarmTime", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_CALENDAR_ALARM_RECIPIENTS, "alarmRecipients", EVENT_PARAM_ARRAY, 0, 0 }, + { EVENT_CALENDAR_USER_ID, "userId", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_CALENDAR_CALENDAR_NAME, "calendarName", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_CALENDAR_UID, "uid", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_CALENDAR_ACTION, "action", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_CALENDAR_SUMMARY, "summary", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_CALENDAR_DESCRIPTION, "description", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_CALENDAR_LOCATION, "location", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_CALENDAR_TIMEZONE, "timezone", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_CALENDAR_START, "start", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_CALENDAR_END, "end", EVENT_PARAM_STRING, 0, 0 }, + { EVENT_CALENDAR_ALLDAY, "allDay", EVENT_PARAM_INT, 0, 0 }, + { EVENT_CALENDAR_ATTENDEE_NAMES, "attendeeNames", EVENT_PARAM_ARRAY, 0, 0 }, + { EVENT_CALENDAR_ATTENDEE_EMAILS, "attendeeEmails", EVENT_PARAM_ARRAY, 0, 0 }, + { EVENT_CALENDAR_ATTENDEE_STATUS, "attendeeStatus", EVENT_PARAM_ARRAY, 0, 0 }, + { EVENT_CALENDAR_ORGANIZER, "organizer", EVENT_PARAM_STRING, 0, 0 }, +#endif //WITH_DAV + /* 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 }, @@ -187,13 +220,19 @@ 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; if (groups & IMAP_ENUM_EVENT_GROUPS_MAILBOX) enabled_events |= MAILBOX_EVENTS; + +#ifdef WITH_DAV + if (groups & IMAP_ENUM_EVENT_GROUPS_CALENDAR) + enabled_events |= CALENDAR_EVENTS; +#endif //WITH_DAV + } EXPORTED void mboxevent_setnamespace(struct namespace *n) @@ -346,8 +385,42 @@ *mboxevent = NULL; } +#ifdef WITH_DAV +static int mboxevent_expected_calendar_param(enum event_param param) +{ + switch (param) { + case EVENT_CALENDAR_ALARM_TIME: + case EVENT_CALENDAR_ALARM_RECIPIENTS: + case EVENT_CALENDAR_USER_ID: + case EVENT_CALENDAR_CALENDAR_NAME: + case EVENT_CALENDAR_UID: + case EVENT_CALENDAR_ACTION: + case EVENT_CALENDAR_SUMMARY: + case EVENT_CALENDAR_DESCRIPTION: + case EVENT_CALENDAR_LOCATION: + case EVENT_CALENDAR_TIMEZONE: + case EVENT_CALENDAR_START: + case EVENT_CALENDAR_END: + case EVENT_CALENDAR_ALLDAY: + case EVENT_CALENDAR_ATTENDEE_NAMES: + case EVENT_CALENDAR_ATTENDEE_EMAILS: + case EVENT_CALENDAR_ATTENDEE_STATUS: + case EVENT_CALENDAR_ORGANIZER: + return 1; + case EVENT_SERVERFQDN: /* needed to see who is master */ + return 1; + default: + return 0; + } +} +#endif //WITH_DAV + static int mboxevent_expected_param(enum event_type type, enum event_param param) { +#ifdef WITH_DAV + if (type == EVENT_CALENDAR_ALARM) + return mboxevent_expected_calendar_param(param); +#endif //WITH_DAV switch (param) { case EVENT_BODYSTRUCTURE: return (extra_params & IMAP_ENUM_EVENT_EXTRA_PARAMS_BODYSTRUCTURE) && @@ -378,8 +451,12 @@ 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_MAILBOX_ACL: + return (type & MAILBOX_EVENTS); case EVENT_MAX_MESSAGES: return type & QUOTA_EVENTS; case EVENT_MESSAGE_CONTENT: @@ -388,12 +465,14 @@ 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)); @@ -415,6 +494,10 @@ 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; @@ -427,6 +510,8 @@ return 1; case EVENT_PID: return 1; + case EVENT_SERVERFQDN: + return 1; case EVENT_USER: return type & (EVENT_MAILBOX_SUBSCRIBE|EVENT_MAILBOX_UNSUBSCRIBE|\ EVENT_LOGIN|EVENT_LOGOUT); @@ -444,6 +529,8 @@ return extra_params & IMAP_ENUM_EVENT_EXTRA_PARAMS_VND_FASTMAIL_CONVUNSEEN; case EVENT_OLD_UIDSET: return type & (EVENT_MESSAGE_COPY|EVENT_MESSAGE_MOVE); + default: + return 0; } /* test if the parameter is related to a message event */ @@ -505,6 +592,10 @@ FILL_STRING_PARAM(event, EVENT_SERVICE, xstrdup(config_ident)); }
View file
cyrus-imapd-2.5.tar.gz/imap/mboxevent.h
Changed
@@ -49,8 +49,10 @@ #include "mailbox.h" #include "mboxname.h" - - +#ifdef WITH_DAV +#include "caldav_db.h" +#include "caldav_alarm.h" +#endif //WITH_DAV /* * event types defined in RFC 5423 - Internet Message Store Events */ @@ -80,7 +82,9 @@ 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), + EVENT_CALENDAR_ALARM = (1<<22) }; /* @@ -91,6 +95,7 @@ enum event_param { EVENT_TIMESTAMP, EVENT_SERVICE, + EVENT_SERVERFQDN, EVENT_SERVER_ADDRESS, /* gather serverDomain and serverPort together */ EVENT_CLIENT_ADDRESS, /* gather clientIP and clientPort together */ EVENT_OLD_MAILBOX_ID, @@ -110,12 +115,34 @@ EVENT_MIDSET, EVENT_FLAG_NAMES, EVENT_PID, + EVENT_ACL_SUBJECT, + EVENT_ACL_RIGHTS, EVENT_USER, EVENT_MESSAGE_SIZE, + EVENT_MAILBOX_ACL, + EVENT_MESSAGE_CID, +#ifdef WITH_DAV EVENT_MBTYPE, EVENT_DAV_FILENAME, EVENT_DAV_UID, - EVENT_MESSAGE_CID, + EVENT_CALENDAR_ALARM_TIME, + EVENT_CALENDAR_ALARM_RECIPIENTS, + EVENT_CALENDAR_USER_ID, + EVENT_CALENDAR_CALENDAR_NAME, + EVENT_CALENDAR_UID, + EVENT_CALENDAR_ACTION, + EVENT_CALENDAR_SUMMARY, + EVENT_CALENDAR_DESCRIPTION, + EVENT_CALENDAR_LOCATION, + EVENT_CALENDAR_TIMEZONE, + EVENT_CALENDAR_START, + EVENT_CALENDAR_END, + EVENT_CALENDAR_ALLDAY, + EVENT_CALENDAR_ATTENDEE_NAMES, + EVENT_CALENDAR_ATTENDEE_EMAILS, + EVENT_CALENDAR_ATTENDEE_STATUS, + EVENT_CALENDAR_ORGANIZER, +#endif EVENT_ENVELOPE, EVENT_BODYSTRUCTURE, EVENT_CLIENT_ID, @@ -219,6 +246,13 @@ 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 @@ -280,6 +314,22 @@ void mboxevent_extract_old_mailbox(struct mboxevent *event, const struct mailbox *mailbox); +#ifdef WITH_DAV +/* + * Extract data from the given ical object + */ +void mboxevent_extract_icalcomponent(struct mboxevent *event, + icalcomponent *ical, + const char *userid, + const char *calname, + enum caldav_alarm_action action, + icaltimetype alarmtime, + const char *timezone, + icaltimetype start, + icaltimetype end, + strarray_t *recipients + ); +#endif //WITH_DAV /* * set the client tag used by vnd.fastmail.clientTagj
View file
cyrus-imapd-2.5.tar.gz/imap/mboxlist.c
Changed
@@ -1854,6 +1854,15 @@ 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) */ @@ -2756,7 +2765,7 @@ * Set all the resource quotas on, or create a quota root. */ EXPORTED int mboxlist_setquotas(const char *root, - int newquotas[QUOTA_NUMRESOURCES], int force) + quota_t newquotas[QUOTA_NUMRESOURCES], int force) { char pattern[MAX_MAILBOX_PATH+1]; struct quota q;
View file
cyrus-imapd-2.5.tar.gz/imap/mboxlist.h
Changed
@@ -233,7 +233,7 @@ /* set or create quota root */ int mboxlist_setquotas(const char *root, - int newquotas[QUOTA_NUMRESOURCES], int force); + quota_t newquotas[QUOTA_NUMRESOURCES], int force); int mboxlist_unsetquota(const char *root); /* open the mailboxes db */
View file
cyrus-imapd-2.5.tar.gz/imap/mboxname.c
Changed
@@ -88,6 +88,8 @@ "*.", "*..*", "user", + "user.anyone", + "user.anonymous", }; #define NUM_BADMBOXPATTERNS (sizeof(badmboxpatterns)/sizeof(*badmboxpatterns)) @@ -576,7 +578,15 @@ 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);
View file
cyrus-imapd-2.5.tar.gz/imap/quota.c
Changed
@@ -669,8 +669,8 @@ static void reportquota_resource(struct quota * quota, const char *root, int res) { if (quota->limits[res] > 0) { - printf(" %7" PRIdMAX " %8" PRIdMAX, (intmax_t)quota->limits[res], - (intmax_t)((((intmax_t)quota->useds[res] / quota_units[res]) + printf(" %7lld %8lld", quota->limits[res], + (quota_t)((quota_t)((quota->useds[res] / quota_units[res]) * 100) / quota->limits[res])); } else if (quota->limits[res] == 0) { @@ -679,8 +679,8 @@ else { printf(" "); } - printf(" %8" PRIdMAX " %20s %s\n", - (intmax_t)((intmax_t)quota->useds[res] / quota_units[res]), + printf(" %8lld %20s %s\n", + (quota_t)(quota->useds[res] / quota_units[res]), quota_names[res], root); }
View file
cyrus-imapd-2.5.tar.gz/imap/quota.h
Changed
@@ -78,7 +78,7 @@ /* Information in quota entry */ quota_t useds[QUOTA_NUMRESOURCES]; - int limits[QUOTA_NUMRESOURCES]; /* in QUOTA_UNITS */ + quota_t limits[QUOTA_NUMRESOURCES]; /* in QUOTA_UNITS */ /* information for scanning */ char *scanmbox; @@ -89,7 +89,7 @@ #define QUOTA_UNLIMITED (-1) extern const char * const quota_names[QUOTA_NUMRESOURCES]; -extern const int quota_units[QUOTA_NUMRESOURCES]; +extern const quota_t quota_units[QUOTA_NUMRESOURCES]; int quota_name_to_resource(const char *str); typedef int quotaproc_t(struct quota *quota, void *rock); @@ -140,5 +140,5 @@ void quotadb_done(void); int quota_is_overquota(const struct quota *quota, enum quota_resource res, - int newquotas[QUOTA_NUMRESOURCES]); + quota_t newquotas[QUOTA_NUMRESOURCES]); #endif /* INCLUDED_QUOTA_H */
View file
cyrus-imapd-2.5.tar.gz/imap/quota_db.c
Changed
@@ -90,7 +90,7 @@ "X-NUM-FOLDERS" /* QUOTA_NUMFOLDERS */ }; -EXPORTED const int quota_units[QUOTA_NUMRESOURCES] = { +EXPORTED const quota_t quota_units[QUOTA_NUMRESOURCES] = { 1024, /* QUOTA_STORAGE -- RFC2087 */ 1, /* QUOTA_MESSAGE -- RFC2087 */ 1024, /* QUOTA_ANNOTSTORAGE */ @@ -194,7 +194,7 @@ goto out; /* need at least 2 more fields */ if (sscanf(fields->data[i++], QUOTA_T_FMT, "a->useds[res]) != 1) goto out; - if (sscanf(fields->data[i++], "%d", "a->limits[res]) != 1) + if (sscanf(fields->data[i++], QUOTA_T_FMT, "a->limits[res]) != 1) goto out; /* skip over temporary extra used data from failed quota -f runs */ if (i < fields->count && @@ -665,7 +665,7 @@ } EXPORTED int quota_is_overquota(const struct quota *quota, enum quota_resource res, - int newquotas[QUOTA_NUMRESOURCES]) + quota_t newquotas[QUOTA_NUMRESOURCES]) { int limit = newquotas ? newquotas[res] : quota->limits[res];
View file
cyrus-imapd-2.5.tar.gz/imap/sync_client.c
Changed
@@ -105,6 +105,8 @@ static int do_compress = 0; static int no_copyback = 0; +static char *prev_userid; + #define CAPA_CRC_VERSIONS (CAPA_COMPRESS<<1) static struct protocol_t csync_protocol = @@ -199,7 +201,7 @@ static int find_reserve_all(struct sync_name_list *mboxname_list, struct sync_folder_list *master_folders, struct sync_folder_list *replica_folders, - struct sync_reserve_list *reserve_guids) + struct sync_reserve_list *reserve_list) { struct sync_name *mbox; struct sync_folder *rfolder; @@ -241,7 +243,7 @@ /* mailbox is open from here, no exiting without closing it! */ - part_list = sync_reserve_partlist(reserve_guids, mailbox->part); + part_list = sync_reserve_partlist(reserve_list, mailbox->part); sync_folder_list_add(master_folders, mailbox->uniqueid, mailbox->name, mailbox->mbtype, @@ -307,60 +309,71 @@ struct sync_msgid_list *part_list) { const char *cmd = "RESERVE"; - struct sync_msgid *msgid; + struct sync_msgid *msgid = part_list->head; struct sync_folder *folder; - struct dlist *kl; + struct dlist *kl = NULL; struct dlist *kin = NULL; struct dlist *ki; - int r; - - if (!part_list->toupload) - return 0; /* nothing to reserve */ + int r = 0; if (!replica_folders->head) return 0; /* nowhere to reserve */ - kl = dlist_newkvlist(NULL, cmd); - dlist_setatom(kl, "PARTITION", partition); + while (msgid) { + int n = 0; - ki = dlist_newlist(kl, "MBOXNAME"); - for (folder = replica_folders->head; folder; folder = folder->next) - dlist_setatom(ki, "MBOXNAME", folder->name); + if (!part_list->toupload) + goto done; /* got them all */ - ki = dlist_newlist(kl, "GUID"); - for (msgid = part_list->head; msgid; msgid = msgid->next) { - if (!msgid->need_upload) continue; - dlist_setatom(ki, "GUID", message_guid_encode(&msgid->guid)); - /* we will re-add the "need upload" if we get a MISSING response */ - msgid->need_upload = 0; - part_list->toupload--; - } + kl = dlist_newkvlist(NULL, cmd); + dlist_setatom(kl, "PARTITION", partition); - sync_send_apply(kl, sync_out); - dlist_free(&kl); + ki = dlist_newlist(kl, "MBOXNAME"); + for (folder = replica_folders->head; folder; folder = folder->next) + dlist_setatom(ki, "MBOXNAME", folder->name); - r = sync_parse_response(cmd, sync_in, &kin); - if (r) return r; + ki = dlist_newlist(kl, "GUID"); + for (; msgid; msgid = msgid->next) { + if (!msgid->need_upload) continue; + if (n > 8192) break; + dlist_setatom(ki, "GUID", message_guid_encode(&msgid->guid)); + /* we will re-add the "need upload" if we get a MISSING response */ + msgid->need_upload = 0; + part_list->toupload--; + n++; + } - r = mark_missing(kin, part_list); - dlist_free(&kin); + sync_send_apply(kl, sync_out); + + r = sync_parse_response(cmd, sync_in, &kin); + if (r) goto done; + r = mark_missing(kin, part_list); + if (r) goto done; + + dlist_free(&kl); + dlist_free(&kin); + } + +done: + dlist_free(&kl); + dlist_free(&kin); return r; } static int reserve_messages(struct sync_name_list *mboxname_list, struct sync_folder_list *master_folders, struct sync_folder_list *replica_folders, - struct sync_reserve_list *reserve_guids) + struct sync_reserve_list *reserve_list) { struct sync_reserve *reserve; int r; r = find_reserve_all(mboxname_list, master_folders, - replica_folders, reserve_guids); + replica_folders, reserve_list); if (r) return r; - for (reserve = reserve_guids->head; reserve; reserve = reserve->next) { + for (reserve = reserve_list->head; reserve; reserve = reserve->next) { r = reserve_partition(reserve->part, replica_folders, reserve->list); if (r) return r; } @@ -819,18 +832,21 @@ } static int fetch_file(struct mailbox *mailbox, unsigned long uid, - struct index_record *rp) + struct index_record *rp, struct sync_msgid_list *part_list) { const char *cmd = "FETCH"; struct dlist *kin = NULL; struct dlist *kl; int r = 0; - const char *fname = dlist_reserve_path(mailbox->part, &rp->guid); + struct sync_msgid *msgid; struct message_guid *guid = NULL; - struct stat sbuf; + size_t size = 0; + const char *fname = NULL; + + msgid = sync_msgid_lookup(part_list, &rp->guid); /* already reserved? great */ - if (stat(fname, &sbuf) == 0) + if (msgid && !msgid->need_upload) return 0; kl = dlist_newkvlist(NULL, cmd); @@ -844,13 +860,20 @@ r = sync_parse_response(cmd, sync_in, &kin); if (r) return r; - if (!dlist_tofile(kin->head, NULL, &guid, NULL, NULL)) { + if (!dlist_tofile(kin->head, NULL, &guid, &size, &fname)) { r = IMAP_MAILBOX_NONEXISTENT; goto done; } - if (!message_guid_equal(guid, &rp->guid)) + if (message_guid_equal(guid, &rp->guid) && (size == rp->size)) { + msgid = sync_msgid_insert(part_list, &rp->guid); + msgid->need_upload = 0; + msgid->size = size; + msgid->fname = xstrdup(fname); + } + else { r = IMAP_IOERROR; + } done: dlist_free(&kin); @@ -858,7 +881,7 @@ } static int copy_remote(struct mailbox *mailbox, uint32_t uid, - struct dlist *kr) + struct dlist *kr, struct sync_msgid_list *part_list) { struct index_record record; struct dlist *ki; @@ -872,10 +895,8 @@ /* choose the destination UID */ record.uid = mailbox->i.last_uid + 1; - /* already fetched the file in the parse phase */ - /* append the file */ - r = sync_append_copyfile(mailbox, &record, annots); + r = sync_append_copyfile(mailbox, &record, annots, part_list); sync_annot_list_free(&annots); @@ -890,7 +911,8 @@ static int copyback_one_record(struct mailbox *mailbox, struct index_record *rp,
View file
cyrus-imapd-2.5.tar.gz/imap/sync_server.c
Changed
@@ -74,9 +74,11 @@ #include "annotate.h" #include "append.h" #include "auth.h" +#ifdef WITH_DAV #include "caldav_db.h" #include "carddav_db.h" #include "dav_db.h" +#endif #include "dlist.h" #include "exitcodes.h" #include "global.h" @@ -291,9 +293,11 @@ statuscache_open(); } +#ifdef WITH_DAV dav_init(); caldav_init(); carddav_init(); +#endif return 0; } @@ -455,9 +459,11 @@ proc_cleanup(); +#ifdef WITH_DAV carddav_done(); caldav_done(); dav_done(); +#endif if (config_getswitch(IMAPOPT_STATUSCACHE)) { statuscache_close(); @@ -1019,16 +1025,14 @@ struct sync_reserve *res; struct sync_reserve_list *l = *reserve_listp; struct sync_msgid *msg; - const char *fname; int hash_size = l->hash_size; struct partition_list *p, *pl = NULL; for (res = l->head; res; res = res->next) { for (msg = res->list->head; msg; msg = msg->next) { + if (!msg->fname) continue; pl = partition_list_add(res->part, pl); - - fname = dlist_reserve_path(res->part, &msg->guid); - unlink(fname); + unlink(msg->fname); } } sync_reserve_list_free(reserve_listp); @@ -1040,6 +1044,11 @@ snprintf(buf, MAX_MAILBOX_PATH, "%s/sync./%lu", config_partitiondir(p->name), (unsigned long)getpid()); rmdir(buf); + + /* and the archive partition too */ + snprintf(buf, MAX_MAILBOX_PATH, "%s/sync./%lu", + config_archivepartitiondir(p->name), (unsigned long)getpid()); + rmdir(buf); } partition_list_free(pl); @@ -1067,6 +1076,8 @@ if (r) return; + /* XXX - this is just on the replica, but still - we shouldn't hold + * the lock for so long */ for (recno = 1; recno <= mailbox->i.num_records; recno++) { /* ok to skip errors here - just means they'll be uploaded * rather than reserved */ @@ -1087,7 +1098,7 @@ /* Attempt to reserve this message */ mailbox_msg_path = mailbox_record_fname(mailbox, &record); - stage_msg_path = dlist_reserve_path(part, &record.guid); + stage_msg_path = dlist_reserve_path(part, record.system_flags & FLAG_ARCHIVED, &record.guid); /* check that the sha1 of the file on disk is correct */ memset(&record2, 0, sizeof(struct index_record)); @@ -1109,6 +1120,9 @@ continue; } + item->size = record.size; + item->fname = xstrdup(stage_msg_path); /* track the correct location */ + item->is_archive = record.system_flags & FLAG_ARCHIVED ? 1 : 0; item->need_upload = 0; part_list->toupload--; @@ -1208,7 +1222,7 @@ static int do_quota(struct dlist *kin) { const char *root; - int limits[QUOTA_NUMRESOURCES]; + quota_t limits[QUOTA_NUMRESOURCES]; if (!dlist_getatom(kin, "ROOT", &root)) return IMAP_PROTOCOL_BAD_PARAMETERS; @@ -1219,7 +1233,8 @@ /* ====================================================================== */ static int mailbox_compare_update(struct mailbox *mailbox, - struct dlist *kr, int doupdate) + struct dlist *kr, int doupdate, + struct sync_msgid_list *part_list) { struct index_record mrecord; struct index_record rrecord; @@ -1261,6 +1276,11 @@ /* found a match, check for updates */ if (rrecord.uid == mrecord.uid) { + /* if they're both EXPUNGED then ignore everything else */ + if ((mrecord.system_flags & FLAG_EXPUNGED) && + (rrecord.system_flags & FLAG_EXPUNGED)) + continue; + /* higher modseq on the replica is an error */ if (rrecord.modseq > mrecord.modseq) { if (opt_force) { @@ -1275,24 +1295,23 @@ } } - /* everything else only matters if we're not expunged */ - if (!(mrecord.system_flags & FLAG_EXPUNGED)) { - /* GUID mismatch on a non-expunged record is an error straight away */ - if (!message_guid_equal(&mrecord.guid, &rrecord.guid)) { - syslog(LOG_ERR, "SYNCERROR: guid mismatch %s %u", - mailbox->name, mrecord.uid); - r = IMAP_SYNC_CHECKSUM; - goto out; - } + /* GUID mismatch is an error straight away, it only ever happens if we + * had a split brain - and it will take a full sync to sort out the mess */ + if (!message_guid_equal(&mrecord.guid, &rrecord.guid)) { + syslog(LOG_ERR, "SYNCERROR: guid mismatch %s %u", + mailbox->name, mrecord.uid); + r = IMAP_SYNC_CHECKSUM; + goto out; + } - /* if it's already expunged on the replica, but alive on the master, - * that's bad */ - if (rrecord.system_flags & FLAG_EXPUNGED) { - syslog(LOG_ERR, "SYNCERROR: expunged on replica %s %u", - mailbox->name, mrecord.uid); - r = IMAP_SYNC_CHECKSUM; - goto out; - } + /* if it's already expunged on the replica, but alive on the master, + * that's bad */ + if (!(mrecord.system_flags & FLAG_EXPUNGED) && + (rrecord.system_flags & FLAG_EXPUNGED)) { + syslog(LOG_ERR, "SYNCERROR: expunged on replica %s %u", + mailbox->name, mrecord.uid); + r = IMAP_SYNC_CHECKSUM; + goto out; } /* skip out on the first pass */ @@ -1345,7 +1364,7 @@ if (!doupdate) continue; mrecord.silent = 1; - r = sync_append_copyfile(mailbox, &mrecord, mannots); + r = sync_append_copyfile(mailbox, &mrecord, mannots, part_list); if (r) { syslog(LOG_ERR, "IOERROR: failed to append file %s %d", mailbox->name, recno); @@ -1367,8 +1386,9 @@ return r; } -static int do_mailbox(struct dlist *kin) +static int do_mailbox(struct dlist *kin, struct sync_reserve_list *reserve_list) { + struct sync_msgid_list *part_list; /* fields from the request */ const char *uniqueid; const char *partition; @@ -1466,6 +1486,8 @@ goto done; } + part_list = sync_reserve_partlist(reserve_list, mailbox->part); + /* hold the annotate state open */ mailbox_get_annotate_state(mailbox, ANNOTATE_ANY_UID, &astate); /* and make it hold a transaction open */ @@ -1557,7 +1579,7 @@ } }
View file
cyrus-imapd-2.5.tar.gz/imap/sync_support.c
Changed
@@ -340,7 +340,7 @@ *lp = NULL; } -struct sync_msgid *sync_msgid_lookup(struct sync_msgid_list *l, +struct sync_msgid *sync_msgid_lookup(const struct sync_msgid_list *l, struct message_guid *guid) { int offset = message_guid_hash(guid, l->hash_size); @@ -649,7 +649,7 @@ *lp = NULL; } -void sync_encode_quota_limits(struct dlist *kl, const int limits[QUOTA_NUMRESOURCES]) +void sync_encode_quota_limits(struct dlist *kl, const quota_t limits[QUOTA_NUMRESOURCES]) { int res; @@ -668,7 +668,7 @@ } } -void sync_decode_quota_limits(/*const*/ struct dlist *kl, int limits[QUOTA_NUMRESOURCES]) +void sync_decode_quota_limits(/*const*/ struct dlist *kl, quota_t limits[QUOTA_NUMRESOURCES]) { uint32_t limit = 0; int res; @@ -1338,24 +1338,29 @@ struct sync_msgid_list *part_list, struct dlist *kupload) { - struct sync_msgid *msgid = sync_msgid_insert(part_list, &record->guid); + struct sync_msgid *msgid; const char *fname; - /* already uploaded, great */ - if (!msgid->need_upload) - return 0; - /* we'll trust that it exists - if not, we'll bail later, * but right now we're under locks, so be fast */ fname = mailbox_record_fname(mailbox, record); if (!fname) return IMAP_MAILBOX_BADNAME; + msgid = sync_msgid_insert(part_list, &record->guid); + + /* already uploaded, great */ + if (!msgid->need_upload) + return 0; + dlist_setfile(kupload, "MESSAGE", mailbox->part, &record->guid, record->size, fname); /* note that we will be sending it, so it doesn't need to be * sent again */ + msgid->size = record->size; + msgid->fname = xstrdup(fname); msgid->need_upload = 0; + msgid->is_archive = record->system_flags & FLAG_ARCHIVED ? 1 : 0; part_list->toupload--; return 0; @@ -1544,45 +1549,53 @@ int sync_append_copyfile(struct mailbox *mailbox, struct index_record *record, - const struct sync_annot_list *annots) + const struct sync_annot_list *annots, + const struct sync_msgid_list *part_list) { - const char *fname, *destname; + const char *destname; struct message_guid tmp_guid; + struct sync_msgid *item; int r; message_guid_copy(&tmp_guid, &record->guid); - fname = dlist_reserve_path(mailbox->part, &tmp_guid); - if (!fname) { + item = sync_msgid_lookup(part_list, &record->guid); + + if (!item || !item->fname) { r = IMAP_IOERROR; syslog(LOG_ERR, "IOERROR: Failed to reserve file %s", message_guid_encode(&tmp_guid)); return r; } - r = message_parse(fname, record); + r = message_parse(item->fname, record); if (r) { /* deal with unlinked master records */ if (record->system_flags & FLAG_EXPUNGED) { + /* no need to set 'needs cleanup' here, it's already expunged */ record->system_flags |= FLAG_UNLINKED; goto just_write; } - syslog(LOG_ERR, "IOERROR: failed to parse %s", fname); + syslog(LOG_ERR, "IOERROR: failed to parse %s", item->fname); return r; } if (!message_guid_equal(&tmp_guid, &record->guid)) { syslog(LOG_ERR, "IOERROR: guid mismatch on parse %s (%s)", - fname, message_guid_encode(&record->guid)); + item->fname, message_guid_encode(&record->guid)); return IMAP_IOERROR; } + /* put back to archive if original was archived, gain single instance store */ + if (item->is_archive) + record->system_flags |= FLAG_ARCHIVED; + destname = mailbox_record_fname(mailbox, record); cyrus_mkdir(destname, 0755); - r = mailbox_copyfile(fname, destname, 0); + r = mailbox_copyfile(item->fname, destname, 0); if (r) { syslog(LOG_ERR, "IOERROR: Failed to copy %s to %s", - fname, destname); + item->fname, destname); return r; }
View file
cyrus-imapd-2.5.tar.gz/imap/sync_support.h
Changed
@@ -85,7 +85,11 @@ struct sync_msgid *next; struct sync_msgid *hash_next; struct message_guid guid; - int need_upload; + struct body *body; + size_t size; + char *fname; + unsigned int need_upload:1; + unsigned int is_archive:1; }; struct sync_msgid_list { @@ -105,7 +109,7 @@ void sync_msgid_remove(struct sync_msgid_list *l, struct message_guid *guid); -struct sync_msgid *sync_msgid_lookup(struct sync_msgid_list *list, +struct sync_msgid *sync_msgid_lookup(const struct sync_msgid_list *list, struct message_guid *guid); void sync_msgid_list_free(struct sync_msgid_list **list); @@ -223,7 +227,7 @@ struct sync_quota { struct sync_quota *next; char *root; - int limits[QUOTA_NUMRESOURCES]; + quota_t limits[QUOTA_NUMRESOURCES]; int done; }; @@ -243,8 +247,8 @@ void sync_quota_list_free(struct sync_quota_list **lp); -void sync_encode_quota_limits(struct dlist *kl, const int limits[QUOTA_NUMRESOURCES]); -void sync_decode_quota_limits(/*const*/ struct dlist *kl, int limits[QUOTA_NUMRESOURCES]); +void sync_encode_quota_limits(struct dlist *kl, const quota_t limits[QUOTA_NUMRESOURCES]); +void sync_decode_quota_limits(/*const*/ struct dlist *kl, quota_t limits[QUOTA_NUMRESOURCES]); /* ====================================================================== */ @@ -413,7 +417,8 @@ struct sync_annot_list **annotsp); int sync_append_copyfile(struct mailbox *mailbox, struct index_record *record, - const struct sync_annot_list *sal); + const struct sync_annot_list *sal, + const struct sync_msgid_list *part_list); /* ====================================================================== */
View file
cyrus-imapd-2.5.tar.gz/imap/unexpunge.c
Changed
@@ -258,13 +258,17 @@ mboxname, record.uid, newrecord.uid); /* mark the old one unlinked so we don't see it again */ - record.system_flags |= FLAG_UNLINKED; + record.system_flags |= FLAG_UNLINKED | FLAG_NEEDS_CLEANUP; r = mailbox_rewrite_index_record(mailbox, &record); if (r) goto done; (*numrestored)++; } + /* better get that seen to */ + if (*numrestored) + mailbox->i.options |= OPT_MAILBOX_NEEDS_UNLINK; + done: return r; }
View file
cyrus-imapd-2.5.tar.gz/imap/user.c
Changed
@@ -228,6 +228,13 @@ /* delete all the search engine data (if any) */ search_deluser(userid); +#ifdef WITH_DAV + /* delete all the calendar alarms for the user */ + struct caldav_alarm_db *alarmdb = caldav_alarm_open(); + caldav_alarm_delete_user(alarmdb, userid); + caldav_alarm_close(alarmdb); +#endif //WITH_DAV + proc_killuser(userid); return 0;
View file
cyrus-imapd-2.5.tar.gz/imap/xapian_wrap.cpp
Changed
@@ -291,6 +291,7 @@ 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; } }
View file
cyrus-imapd-2.5.tar.gz/lib/imapoptions
Changed
@@ -313,6 +313,12 @@ hierarchy will be at the toplevel of the shared namespace. A user's personal calendar hierarchy will be a child of their Inbox. */ +{ "calendar_greedymatch", 1, SWITCH } +/* If yes, return recurrence rules that span over the timeframe without + checking that there is definitely a recurrence in the range. This + is more efficient and true for sensible clients, and hopefully the + others will just ignore the bogons */ + { "carddav_realm", NULL, STRING } /* The realm to present for HTTP authentication of CardDAV resources. If not set (the default), the value of the "servername" option will @@ -505,10 +511,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.cmu.mbtype", "vnd.cmu.davFilename", "vnd.cmu.davUid", "vnd.fastmail.clientId", "vnd.fastmail.sessionId", "vnd.fastmail.convExists", "vnd.fastmail.convUnseen", "vnd.fastmail.cid") } +{ "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.mailboxACL", "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", "subscription") } +{ "event_groups", "message mailbox", BITFIELD("message", "quota", "flags", "access", "mailbox", "subscription", "calendar") } /* Space-separated list of groups of related events to turn on notification */ { "event_notifier", NULL, STRING }
View file
cyrus-imapd-2.5.tar.gz/lib/prot.c
Changed
@@ -820,7 +820,7 @@ int n; time_t newtime; char timebuf[20]; - + time(&newtime); snprintf(timebuf, sizeof(timebuf), ">%ld>", newtime); n = write(s->logfd, timebuf, strlen(timebuf)); @@ -836,7 +836,9 @@ } } while (left); - (void)fsync(s->logfd); + /* we don't care THAT much about logs + * (void)fsync(s->logfd); + */ } }
View file
cyrus-imapd-2.5.tar.gz/man/sync_client.8
Changed
@@ -91,6 +91,9 @@ [ .B \-m ] +[ +.B \-A +] .br [ .B \-s @@ -185,6 +188,12 @@ User mode. Remaining arguments are list of users who should be replicated. .TP +.BI \-A +All users mode. +Sync every user on the server to the replica (doesn't do non-user mailboxes +at all... this could be considered a bug and maybe it should do those mailboxes +independently) +.TP .BI \-m Mailbox mode. Remaining arguments are list of mailboxes which should be replicated.
View file
cyrus-imapd-2.5.tar.gz/master/master.c
Changed
@@ -829,13 +829,6 @@ fcntl_unset(STATUS_FD, FD_CLOEXEC); fcntl_unset(LISTEN_FD, FD_CLOEXEC); - - /* close all listeners */ - for (i = 0; i < nservices; i++) { - xclose(Services[i].socket); - xclose(Services[i].stat[0]); - xclose(Services[i].stat[1]); - } } else { snprintf(name_env3, sizeof(name_env3), "CYRUS_ISDAEMON=1"); @@ -843,6 +836,13 @@ } limit_fds(s->maxfds); + /* close all listeners */ + for (i = 0; i < nservices; i++) { + xclose(Services[i].socket); + xclose(Services[i].stat[0]); + xclose(Services[i].stat[1]); + } + syslog(LOG_DEBUG, "about to exec %s", path); /* add service name to environment */
View file
cyrus-imapd-2.5.tar.gz/mkdebian.pl
Changed
@@ -68,7 +68,7 @@ build: dh_testdir autoreconf -v -i - ./configure --without-krb --with-perl=/usr/bin/perl --enable-http --enable-idled --with-extraident=git-$branch-$num --prefix=/$basedir -with-cyrus-prefix=/$basedir --with-zlib --without-snmp --enable-replication --without-bdb --enable-xapian + ./configure --without-krb --with-perl=/usr/bin/perl --enable-http --enable-calalarmd --enable-idled --with-extraident=git-$branch-$num --prefix=/$basedir -with-cyrus-prefix=/$basedir --with-zlib --without-snmp --enable-replication --without-bdb --enable-xapian make -j 8 all CFLAGS="-g -fPIC -W -Wall -Werror -fstack-protector-all" make sieve/test touch build @@ -100,9 +100,10 @@ # set up source package # no need to actually install the built object files! It's just the source we want mkdir -p debian/$basename-build/usr/src/$basename-build/cyrus - find . -maxdepth 1 -mindepth 1 -not -name debian -not -name .git -print0 | \\ + # but keep the git data so we can build again! + find . -maxdepth 1 -mindepth 1 -not -name debian -print0 | \\ xargs -0 -r -i cp -a {} debian/$basename-build/usr/src/$basename-build/cyrus/ - + dh_compress dh_makeshlibs dh_installdeb
View file
cyrus-imapd-2.5.tar.gz/notifyd/notify_external.c
Changed
@@ -71,15 +71,15 @@ /* 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;
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
.