Attached find two additional and incremental cyradm patches for the 
the current cyrus-imapd-2.5 branch (HEAD at 61dfed2a4):

* 0001-cyradm-hide-value.priv-and-value.shared-from-user-in.patch
  Change cyradm info command output to (replace "value.shared" and
  "value.priv" in output):
      > info mailbox
      {mailbox}
         private:
          [all private annotations of mailbox]
         shared:
          [all shared annotations of mailbox]

  The new getmetadata and setmeatada commands also use "private" and
  "shared" (though with a different display format).

  New mboxconfig interface to select private annotation (instead of 
  "mboxconfig mailbox annotation value [value.priv|value.shared]"):
       mboxconfig --private INBOX.Trash /specialuse none
       mboxconfig --private INBOX.Trash /specialuse \\Trash
     
       mboxconfig INBOX.test comment "shared comment"
       mboxconfig --private INBOX.test comment "private comment"

* 0002-cyradm-fix-info-command-output-with-wildcard-mailbox.patch
  The info command accepts wildcards. I failed to test this case
  and broke it's display with "cyradm: request and print value.shared 
  and value.priv attribures".


Both patches can be applied cleanly to the cyrus-imapd-2.5 branch 
with git-am(1) ("git am 000[12]*") but fail on the master branch 
because of missing commits:
  commit 314fb26a683a915f276e1b890b0ac02355faf4aa
  perl: add documentation on the new ACL flag

  commit 32881190a8b3186193cbfa23664a21005ad16b67
  patch to add metadata to cyradm etc.


While preparing 0002 I noticed that my patches change the interface
of the Cyrus::IMAP::Admin::getinfo subroutine. Now it returns a complex
data structure instead of a simple hash, i. e. this is not backwards
compatible with the original 2.5 implementation.

If Cyrus::IMAP::Admin provides a public interface used outside cyradm
this might be an undesirable change. One possibility to fix it would 
be to rename the new getinfo (used by cyradm to display private 
annotations) and restore the original getinfo function (which can't be 
tested easily because cyradm doesn't use it).

Regards,
Norbert

>From 51761df72ca1277a73f37177e946bc8d2ef0d674 Mon Sep 17 00:00:00 2001
From: Norbert Warmuth <n...@arcor.de>
Date: Sat, 4 Apr 2015 07:51:55 +0200
Subject: [PATCH 1/2] cyradm: hide value.priv and value.shared from user
 interface

Hide the imap protocol details "value.priv" and "value.shared" which
have been recently added to the cyradm info and mailboxconfig commands by
   [PATCH 2/3] cyradm: request and print value.shared and value.priv attribures
   [PATCH 3/3] cyradm: add support to set private annotations
from the user interface.

In the cyradm info command display it as "private" and "shared". In the
cyradm mboxconfig command replace it with an optional --private option
which switches from the default shared to the private version of an
annotation (e.g. "mboxconfig --private INBOX.Trash /specialuse \\Trash").

The new getmetadata and setmeatada commands also use "private" and "shared" 
(though with a different display format).

---
 perl/imap/IMAP/Admin.pm | 29 ++++++++++++++++++++++++-----
 perl/imap/IMAP/Shell.pm | 25 ++++++++++++++++---------
 perl/imap/cyradm.sh     | 10 ++++------
 3 files changed, 44 insertions(+), 20 deletions(-)

diff --git a/perl/imap/IMAP/Admin.pm b/perl/imap/IMAP/Admin.pm
index fd5d60d..0a839df 100644
--- a/perl/imap/IMAP/Admin.pm
+++ b/perl/imap/IMAP/Admin.pm
@@ -699,6 +699,20 @@ sub setquota {
   }
 }
 
+
+# map protocol name to user visible name
+sub _attribname2access {
+  my $k = shift;
+
+  if ($k eq 'value.priv' ) {
+     return 'private';
+  } elsif ($k eq 'value.shared') {
+     return 'shared';
+  } else {
+    return $k;
+  }
+}
+
 sub getinfo {
   my $self = shift;
   my $box = shift;
@@ -769,8 +783,8 @@ sub getinfo {
 			  } else {
 				$key = "/server$2";
 			  }
-			  $d{-rock}{$3}->{$key} = $4;
-			  $d{-rock}{$5}->{$key} = $6 if (defined ($5) && defined ($6));
+			  $d{-rock}{_attribname2access($3)}->{$key} = $4;
+			  $d{-rock}{_attribname2access($5)}->{$key} = $6 if (defined ($5) && defined ($6));
 		        }  elsif ($text =~
 			       /^\s*"([^"]*)"\s+"([^"]*)"\s+\("([^"]*)"\s+\{(.*)\}\r\n/ ||
 			   $text =~ 
@@ -788,7 +802,7 @@ sub getinfo {
 			  } else {
 				$key = "/server$2";
 			  }
-			  $d{-rock}{$3}->{$key} = $text;
+			  $d{-rock}{_attribname2access($3)}->{$key} = $text;
 			} else {
 			  ; # XXX: unrecognized line, how to notify caller?
 			  1;
@@ -820,7 +834,7 @@ sub getinfo {
 *info = *getinfo;
 
 sub mboxconfig {
-  my ($self, $mailbox, $entry, $value, $attribname) = @_;
+  my ($self, $mailbox, $entry, $value, $private) = @_;
 
   my %values = ( "comment" => "/comment",
 		 "expire" => "/vendor/cmu/cyrus-imapd/expire",
@@ -845,7 +859,12 @@ sub mboxconfig {
   my ($rc, $msg);
 
   $value = undef if($value eq "none");
-  $attribname = "value.shared" unless defined ($attribname);
+  my $attribname;
+  if (defined ($private)) {
+    $attribname = "value.priv";
+  } else {
+    $attribname = "value.shared";
+  }
 
   if(defined($value)) {
     ($rc, $msg) = $self->send('', '',
diff --git a/perl/imap/IMAP/Shell.pm b/perl/imap/IMAP/Shell.pm
index e167e35..7f3e762 100644
--- a/perl/imap/IMAP/Shell.pm
+++ b/perl/imap/IMAP/Shell.pm
@@ -129,7 +129,7 @@ my %builtins = (exit =>
 		  [\&_sc_info, '[mailbox]',
 		   'display mailbox/server annotations'],
 		mboxcfg =>
-		  [\&_sc_mboxcfg, 'mailbox [comment|expire|news2mail|sieve|squat|/<explicit annotation>] value',
+		  [\&_sc_mboxcfg, '[--private] mailbox [comment|expire|news2mail|sieve|squat|/<explicit annotation>] value',
 		   'configure mailbox'],
 		mboxconfig => 'mboxcfg',
 		reconstruct =>
@@ -1549,12 +1549,14 @@ sub _sc_unsubscribe {
 
 sub _sc_mboxcfg {
   my ($cyrref, $name, $fh, $lfh, @argv) = @_;
-  my (@nargv, $opt);
+  my (@nargv, $opt, $private);
   shift(@argv);
   while (defined ($opt = shift(@argv))) {
     last if $opt eq '--';
-    if ($opt =~ /^-/) {
-      die "usage: mboxconfig mailbox [comment|expire|news2mail|pop3showafter|sharedseen|sieve|squat|/<explicit annotation>] value [attributename]\n";
+    if ($opt ne '' && '-private' =~ /^\Q$opt/ || $opt eq '--private') {
+      $private = 1;
+    } elsif ($opt =~ /^-/) {
+      die "usage: mboxconfig [--private] mailbox [comment|expire|news2mail|pop3showafter|sharedseen|sieve|squat|/<explicit annotation>] value\n";
     }
     else {
       push(@nargv, $opt);
@@ -1563,7 +1565,10 @@ sub _sc_mboxcfg {
   }
   push(@nargv, @argv);
   if (@nargv < 2) {
-    die "usage: mboxconfig mailbox [comment|expire|news2mail|pop3showafter|sharedseen|sieve|squat|/<explicit annotation>] value [attributename]\n";
+    die "usage: mboxconfig [--private] mailbox [comment|expire|news2mail|pop3showafter|sharedseen|sieve|squat|/<explicit annotation>] value\n";
+  }
+  if (defined ($private)) {
+    push(@nargv, $private);
   }
   if (!$cyrref || !$$cyrref) {
     die "mboxconfig: no connection to server\n";
@@ -1780,12 +1785,14 @@ find the quota root for a mailbox.
 
 show quota roots and quotas for mailbox
 
-=item C<mboxconfig> I<mailbox> I<attribute> I<value>
+=item C<mboxconfig> [C<--private>] I<mailbox> I<attribute> I<value>
 
-=item C<mboxcfg> I<mailbox> I<attribute> I<value>
+=item C<mboxcfg> [C<--private>] I<mailbox> I<attribute> I<value>
 
-Set mailbox metadata.  A value of "none" will remove the attribute.
-The currently supported attributes are: 
+Set mailbox metadata, optionally set the private instead of the shared
+version of the metadata. A value of "none" will remove the attribute.
+
+The currently supported attributes are:
 
 =over 4
 
diff --git a/perl/imap/cyradm.sh b/perl/imap/cyradm.sh
index b8b03f4..4a7caaa 100644
--- a/perl/imap/cyradm.sh
+++ b/perl/imap/cyradm.sh
@@ -197,14 +197,12 @@ find the quota root for a mailbox.
 
 show quota roots and quotas for mailbox
 
-=item C<mboxconfig> I<mailbox> I<attribute> I<value> [I<attributname>]
+=item C<mboxconfig> [C<--private>] I<mailbox> I<attribute> I<value>
 
-=item C<mboxcfg> I<mailbox> I<attribute> I<value> [I<attributname>]
+=item C<mboxcfg> [C<--private>] I<mailbox> I<attribute> I<value>
 
-Set mailbox metadata.  A value of "none" will remove the attribute.
-The optional attributname allows to switch from the default attribute
-name and prefix "value.shared" to "value.priv" which is required to
-set for example the /specialuse annotation on a mailbox.
+Set mailbox metadata, optionally set the private instead of the shared
+version of the metadata. A value of "none" will remove the attribute.
 
 The currently supported attributes are:
 
-- 
2.1.4

>From aff5168bc80e5e1ae8a4ff42b464911ecf15d663 Mon Sep 17 00:00:00 2001
From: Norbert Warmuth <n...@arcor.de>
Date: Sat, 4 Apr 2015 08:05:26 +0200
Subject: [PATCH 2/2] cyradm: fix info command output with wildcard mailboxes

Since support of private annotiations has been added to the "info [mailbox]"
command with
  "cyradm: request and print value.shared and value.priv attribures"
the output for "mailbox" containing wildcards has been broken.

With three matching mailboxes:
  > info mailbox*
  {mailbox1}
    privat:
      [all private annotations mailbox1]
  {mailbox2}
      [all private annotations mailbox2]
  {mailbox3}
      [all private annotations mailbox2]
    shared:
      [all shared annotations mailbox1, mailbox2 and mailbox3]

Make Cyrus::IMAP::Admin::getinfo return a different data structure
and fix the output in Cyrus::IMAP::Shell::_sc_info.
---
 perl/imap/IMAP/Admin.pm | 10 +++++-----
 perl/imap/IMAP/Shell.pm | 34 ++++++++++++++--------------------
 2 files changed, 19 insertions(+), 25 deletions(-)

diff --git a/perl/imap/IMAP/Admin.pm b/perl/imap/IMAP/Admin.pm
index 0a839df..4582932 100644
--- a/perl/imap/IMAP/Admin.pm
+++ b/perl/imap/IMAP/Admin.pm
@@ -779,12 +779,12 @@ sub getinfo {
 			       /^\s*(?|"([^"]*)"|([^\s]+))\s+"([^"]*)"\s+\("([^"]*)"\s+(?|"([^"]*)"|(NIL))(?:\s+"([^"]*)"\s+(?|"([^"]*)"|(NIL)))*\)/) {
 			  my $key;
 			  if($1 ne "") {
-				$key = "/mailbox/{$1}$2";
+				$key = "/mailbox$2";
 			  } else {
 				$key = "/server$2";
 			  }
-			  $d{-rock}{_attribname2access($3)}->{$key} = $4;
-			  $d{-rock}{_attribname2access($5)}->{$key} = $6 if (defined ($5) && defined ($6));
+			  $d{-rock}->{"$1"}->{_attribname2access($3)}->{$key} = $4;
+			  $d{-rock}->{"$1"}->{_attribname2access($5)}->{$key} = $6 if (defined ($5) && defined ($6));
 		        }  elsif ($text =~
 			       /^\s*"([^"]*)"\s+"([^"]*)"\s+\("([^"]*)"\s+\{(.*)\}\r\n/ ||
 			   $text =~ 
@@ -798,11 +798,11 @@ sub getinfo {
 
 			  my $key;
 			  if($1 ne "") {
-				$key = "/mailbox/{$1}$2";
+				$key = "/mailbox/$2";
 			  } else {
 				$key = "/server$2";
 			  }
-			  $d{-rock}{_attribname2access($3)}->{$key} = $text;
+			  $d{-rock}{"$1"}->{_attribname2access($3)}->{$key} = $text;
 			} else {
 			  ; # XXX: unrecognized line, how to notify caller?
 			  1;
diff --git a/perl/imap/IMAP/Shell.pm b/perl/imap/IMAP/Shell.pm
index 7f3e762..9fb4a3a 100644
--- a/perl/imap/IMAP/Shell.pm
+++ b/perl/imap/IMAP/Shell.pm
@@ -1392,31 +1392,25 @@ sub _sc_info {
     return 1;
   }
 
-  # keep track of what mailboxes we've printed a header for already
-  my %section = ();
-  my %attribname = ();
-  foreach my $attribname (sort keys %info) {
-    foreach my $attrib (sort keys %{$info{$attribname}}) {
-      # server metadata does not contain '{}'
-      my $sect = undef;
-      $sect = $1 if $attrib =~ /(\{.*\})/;
-      if(!defined($sect)) {
-	  $sect = "Server Wide";
-      }
-
-      if(!exists $section{$sect}) {
-	  $section{$sect} = 'x';
-	  print "$sect:\n";
+  foreach my $mailbox (sort keys %info) {
+      if($mailbox eq "") {
+        print "{Server Wide}\n";
+      } else {
+        print "{$mailbox}:\n";
       }
 
-      if(!exists $attribname{$attribname}) {
+    my %attribname = ();
+    foreach my $attribname (sort keys %{$info{$mailbox}}) {
+      foreach my $attrib (sort keys %{$info{$mailbox}->{$attribname}}) {
+        if(!exists $attribname{$attribname}) {
 	  $attribname{$attribname} = 'x';
 	  print "  $attribname:\n";
-      }
-      $attrib =~ /([^\/]*)$/;
-      my $attrname = $1;
+        }
+        $attrib =~ /([^\/]*)$/;
+        my $attrname = $1;
 
-      $lfh->[1]->print("    ", $attrname, ": ", $info{$attribname}->{$attrib}, "\n");
+        $lfh->[1]->print("    ", $attrname, ": ", $info{$mailbox}->{$attribname}->{$attrib}, "\n");
+      }
     }
   }
   0;
-- 
2.1.4

Reply via email to