[prev in list] [next in list] [prev in thread] [next in thread] 

List:       cyrus-devel
Subject:    Re[2]: Need advice: mailbox-based \Seen flag
From:       Boris Lytochkin <boris.lytochkin () e-port ! ru>
Date:       2007-09-02 10:07:01
Message-ID: 139325802.20070902140701 () e-port ! ru
[Download RAW message or body]

Ken,

Thanks for patch!

Here it is full patch (with cyradm patch additions) that works OK on
my imapd 2.3.9 setup. I can not check replication process for now.

Here it is some logs:
cyradm:
localhost> info user.rootmail
{user.rootmail}:
  condstore: false
  lastpop:
  lastupdate:  2-Sep-2007 13:57:45 +0400
  partition: default
  sharedseen: true
  size: 18220
localhost> info user.lytochkin
{user.lytochkin}:
  condstore: false
  lastpop:
  lastupdate:  1-Sep-2007 08:11:08 +0400
  partition: default
  sharedseen: false
  size: 61128298

local6.debug:
Sep  2 13:57:45 svr imaps[7810]: seen_db: user anyone opened /var/imap/user/a/anyone.seen

-- 
Boris Lytochkin
JCS e-port, Moscow

______________________________________

From: Ken Murchison
Sent: 1 сентября 2007 г., 22:05
To:   Boris Lytochkin
Subject: Need advice: mailbox-based \Seen flag
I had some time while waiting for paint to dry, so I whipped up this 
quick patch for shared seen state, based on our previous discussions. 
It uses a "/vendor/cmu/cyrus-imapd/sharedseen" mailbox annotation, 
stored as a mailbox option in the index header, to enable/disable shared 
seen state, and stores the shared seen state in "anyone.seen".  Note 
that this patch is completely untested, although it compiles against 
CVS.  I also didn't consider replication yet.

Feel free to try this and see if it has the intended behavior.  Remember 
that the 's' ACL right controls whether a person can change the \Seen 
flag on a message.


Boris Lytochkin wrote:
> Hello!
> 
> I need an advice in implementing per-mailbox \Seen flag (or 'shared'
> \Seen flag in per-user basis).
> 
> For now I want to implement it this way:
> 1) add a new mailbox attribute, say 'sharedseen'
> 2) switch path for .seen file in imap/seen_*.c:seen_getpath() if
>    'sharedseen' flag is set on mailbox.
> 3) changes in replication module?
> 
> So, setting 'sharedseen' attribute to mailbox will cause using
> per-mailbox seen-file.
> 
> What are weak points of this implementation?
> Is there more correct way to make per-mailbox \Seen flag?
> 
> 


-- 
Kenneth Murchison
Systems Programmer
Project Cyrus Developer/Maintainer
Carnegie Mellon University

 
["sharedseen.patch" (application/octet-stream)]

--- perl/imap/IMAP/Admin.pm	Thu Nov 30 20:11:23 2006
+++ perl/imap/IMAP/Admin.pm	Sat Sep  1 11:57:16 2007
@@ -788,6 +788,7 @@
 		 "news2mail" => "/vendor/cmu/cyrus-imapd/news2mail",
 		 "expire" => "/vendor/cmu/cyrus-imapd/expire",
 		 "sieve" => "/vendor/cmu/cyrus-imapd/sieve",
+		 "sharedseen" => "/vendor/cmu/cyrus-imapd/sharedseen",
 		 "squat" => "/vendor/cmu/cyrus-imapd/squat" );
 
   if(!$self->{support_annotatemore}) {
--- perl/imap/IMAP/Shell.pm	Thu Nov 30 20:11:24 2006
+++ perl/imap/IMAP/Shell.pm	Sat Sep  1 11:57:16 2007
@@ -126,7 +126,7 @@
 		  [\&_sc_info, '[mailbox]',
 		   'display mailbox/server metadata'],
 		mboxcfg =>
-		  [\&_sc_mboxcfg, 'mailbox [comment|condstore|news2mail|expire|sieve|squat] \
value', +		  [\&_sc_mboxcfg, 'mailbox \
[comment|condstore|news2mail|expire|sieve|sharedseen|squat] value',  'configure \
mailbox'],  mboxconfig => 'mboxcfg',
 		reconstruct =>
@@ -1424,7 +1424,7 @@
   while (defined ($opt = shift(@argv))) {
     last if $opt eq '--';
     if ($opt =~ /^-/) {
-      die "usage: mboxconfig mailbox \
[comment|condstore|news2mail|expire|sieve|squat] value\n"; +      die "usage: \
mboxconfig mailbox [comment|condstore|news2mail|expire|sieve|sharedseen|squat] \
value\n";  }
     else {
       push(@nargv, $opt);
@@ -1433,7 +1433,7 @@
   }
   push(@nargv, @argv);
   if (@nargv < 2) {
-    die "usage: mboxconfig mailbox [comment|condstore|news2mail|expire|sieve|squat] \
value\n"; +    die "usage: mboxconfig mailbox \
[comment|condstore|news2mail|expire|sieve|sharedseen|squat] value\n";  }
   if (!$cyrref || !$$cyrref) {
     die "mboxconfig: no connection to server\n";
@@ -1685,6 +1685,11 @@
 
 Sets an email address to which messages injected into the server via NNTP 
 will be sent.
+
+=item C<sharedseen>
+
+Indicates that shared seendb must be used for this mailbox instead of per-user.
+This enables sharing \Seen flag with all users that have ACLs to use this mailbox.
 
 =back 
 
--- perl/imap/cyradm.sh	Thu Nov 30 20:11:23 2006
+++ perl/imap/cyradm.sh	Sat Sep  1 11:57:16 2007
@@ -235,6 +235,11 @@
 Sets an email address to which messages injected into the server via NNTP 
 will be sent.
 
+=item C<sharedseen>
+
+Indicates that shared seendb must be used for this mailbox instead of per-user.
+This enables sharing \Seen flag with all users that have ACLs to use this mailbox.
+
 =back 
 
 =item C<renamemailbox> [C<--partition> I<partition>] I<oldname> I<newname>
--- imap/annotate.c	15 Aug 2007 17:20:55 -0000
+++ imap/annotate.c	1 Sep 2007 18:00:26 -0000
@@ -869,20 +869,20 @@
     output_entryatt(ext_mboxname, entry, "", &attrib, fdata);
 }
 
-static void annotation_get_condstore(const char *int_mboxname,
-				     const char *ext_mboxname,
-				     const char *entry,
-				     struct fetchdata *fdata,
-				     struct mailbox_annotation_rock *mbrock,
-				     void *rock __attribute__((unused)))
+static void annotation_get_mailboxopt(const char *int_mboxname,
+				      const char *ext_mboxname,
+				      const char *entry,
+				      struct fetchdata *fdata,
+				      struct mailbox_annotation_rock *mbrock,
+				      void *rock __attribute__((unused)))
 { 
     struct mailbox mailbox;
-    int r = 0;
+    int flag, r = 0;
     char value[40];
     struct annotation_data attrib;
   
-    if(!int_mboxname || !ext_mboxname || !fdata || !mbrock)
-      fatal("annotation_get_condstore called with bad parameters",
+    if(!int_mboxname || !ext_mboxname || !entry || !fdata || !mbrock)
+      fatal("annotation_get_mailboxopt called with bad parameters",
               EC_TEMPFAIL);
 
     get_mb_data(int_mboxname, mbrock);
@@ -890,6 +890,15 @@
     /* Make sure its a local mailbox */
     if (mbrock->server) return;
 
+    /* Check entry */
+    if (!strcmp(entry, "/vendor/cmu/cyrus-imapd/condstore")) {
+	flag = OPT_IMAP_CONDSTORE;
+    } else if (!strcmp(entry, "/vendor/cmu/cyrus-imapd/sharedseen")) {
+	flag = OPT_IMAP_SHAREDSEEN;
+    } else {
+	return;
+    }
+  
     /* Check ACL */
     if(!fdata->isadmin &&
        (!mbrock->acl ||
@@ -906,7 +915,7 @@
     }
 
     if (!r) {
-      if (mailbox.options & OPT_IMAP_CONDSTORE) {
+      if (mailbox.options & flag) {
           strcpy(value, "true");
       } else {
           strcpy(value, "false");
@@ -1017,7 +1026,9 @@
     { "/vendor/cmu/cyrus-imapd/lastpop", BACKEND_ONLY,
       annotation_get_lastpop, NULL },
     { "/vendor/cmu/cyrus-imapd/condstore", BACKEND_ONLY,
-      annotation_get_condstore, NULL },
+      annotation_get_mailboxopt, NULL },
+    { "/vendor/cmu/cyrus-imapd/sharedseen", BACKEND_ONLY,
+      annotation_get_mailboxopt, NULL },
     { NULL, ANNOTATION_PROXY_T_INVALID, NULL, NULL }
 };
 
@@ -1694,14 +1705,23 @@
     return r;
 }
 
-static int annotation_set_condstore(const char *int_mboxname,
-				    struct annotate_st_entry_list *entry,
-				    struct storedata *sdata,
-				    struct mailbox_annotation_rock *mbrock,
-				    void *rock __attribute__((unused)))
+static int annotation_set_mailboxopt(const char *int_mboxname,
+				     struct annotate_st_entry_list *entry,
+				     struct storedata *sdata,
+				     struct mailbox_annotation_rock *mbrock,
+				     void *rock __attribute__((unused)))
 {
     struct mailbox mailbox;
-    int r = 0;
+    int flag, r = 0;
+
+    /* Check entry */
+    if (!strcmp(entry->entry->name, "/vendor/cmu/cyrus-imapd/condstore")) {
+	flag = OPT_IMAP_CONDSTORE;
+    } else if (!strcmp(entry->entry->name, "/vendor/cmu/cyrus-imapd/sharedseen")) {
+	flag = OPT_IMAP_SHAREDSEEN;
+    } else {
+	return IMAP_PERMISSION_DENIED;
+    }
   
     /* Check ACL */
     if(!sdata->isadmin &&
@@ -1717,9 +1737,9 @@
 
     if (!r) {
 	if (!strcmp(entry->shared.value, "true")) {
-	    mailbox.options |= OPT_IMAP_CONDSTORE;
+	    mailbox.options |= flag;
 	} else {
-	    mailbox.options &= ~OPT_IMAP_CONDSTORE;
+	    mailbox.options &= ~flag;
 	}
 
 	r = mailbox_write_index_header(&mailbox);
@@ -1793,7 +1813,10 @@
       ACL_ADMIN, annotation_set_todb, NULL },
     { "/vendor/cmu/cyrus-imapd/condstore", ATTRIB_TYPE_BOOLEAN, BACKEND_ONLY,
       ATTRIB_VALUE_SHARED | ATTRIB_CONTENTTYPE_SHARED,
-      ACL_ADMIN, annotation_set_condstore, NULL },
+      ACL_ADMIN, annotation_set_mailboxopt, NULL },
+    { "/vendor/cmu/cyrus-imapd/sharedseen", ATTRIB_TYPE_BOOLEAN, BACKEND_ONLY,
+      ATTRIB_VALUE_SHARED | ATTRIB_CONTENTTYPE_SHARED,
+      ACL_ADMIN, annotation_set_mailboxopt, NULL },
     { NULL, 0, ANNOTATION_PROXY_T_INVALID, 0, 0, NULL, NULL }
 };
 
--- imap/append.c	5 Feb 2007 18:41:45 -0000	1.110
+++ imap/append.c	1 Sep 2007 18:00:26 -0000
@@ -1091,7 +1091,9 @@
     /* what's the first uid in our new list? */
     start = atoi(msgrange);
 
-    r = seen_open(mailbox, userid, SEEN_CREATE, &seendb);
+    r = seen_open(mailbox,
+		  (mailbox->options & OPT_IMAP_SHAREDSEEN) ? "anyone" : userid,
+		  SEEN_CREATE, &seendb);
     if (r) return r;
     
     r = seen_lockread(seendb, &last_read, &last_uid, &last_change, &seenuids);
--- imap/index.c	2 Aug 2007 14:18:52 -0000	1.226
+++ imap/index.c	1 Sep 2007 18:00:26 -0000
@@ -367,7 +367,10 @@
 
     /* If opening mailbox, get \Recent info */
     if (oldexists == -1 && mailbox->keepingseen) {
-	r = seen_open(mailbox, imapd_userid, SEEN_CREATE, &seendb);
+	r = seen_open(mailbox,
+		      (mailbox->options & OPT_IMAP_SHAREDSEEN) ? "anyone" :
+		      imapd_userid,
+		      SEEN_CREATE, &seendb);
 	if (!r) {
 	    free(seenuids);
 	    seenuids = NULL;
@@ -1481,7 +1484,10 @@
     if (mailbox->exists != 0 &&
 	(statusitems &
 	 (STATUS_RECENT | STATUS_UNSEEN))) {
-	r = seen_open(mailbox, imapd_userid, SEEN_CREATE, &status_seendb);
+	r = seen_open(mailbox,
+		      (mailbox->options & OPT_IMAP_SHAREDSEEN) ? "anyone" :
+		      imapd_userid,
+		      SEEN_CREATE, &status_seendb);
 	if (r) return r;
 
 	r = seen_lockread(status_seendb, &last_read, &last_uid,
--- imap/mailbox.h	30 Aug 2007 14:25:08 -0000	1.83
+++ imap/mailbox.h	1 Sep 2007 18:00:27 -0000
@@ -255,6 +255,7 @@
 
 #define OPT_POP3_NEW_UIDL (1<<0)	/* added for Outlook stupidity */
 #define OPT_IMAP_CONDSTORE (1<<1)	/* added for CONDSTORE extension */
+#define OPT_IMAP_SHAREDSEEN (1<<2)	/* added for shared \Seen state */
 
 
 struct mailbox_header_cache {



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic