]> git.donarmstrong.com Git - debbugs.git/blobdiff - Debbugs/User.pm
[project @ 2005-10-09 14:17:41 by ajt]
[debbugs.git] / Debbugs / User.pm
index fff2eea78cee0b871b9deb42072f105b444a1796..68ae1c4566e642943652fe867843c77e3e64c96e 100644 (file)
@@ -9,6 +9,20 @@ Debbugs::User -- User settings
 
 use Debbugs::User qw(is_valid_user read_usertags write_usertags);
 
+Debbugs::User::is_valid_user($userid);
+
+$u = Debbugs::User::open($userid);
+$u = Debbugs::User::open(user => $userid, locked => 0);
+
+$u = Debbugs::User::open(user => $userid, locked => 1);
+$u->write();
+
+$u->{"tags"}
+$u->{"categories"}
+$u->{"is_locked"}
+$u->{"name"}
+
+
 read_usertags(\%ut, $userid);
 write_usertags(\%ut, $userid);
 
@@ -26,31 +40,52 @@ write_usertags(\%ut, $userid);
 
 use warnings;
 use strict;
+use Fcntl ':flock';
 use vars qw($VERSION $DEBUG %EXPORT_TAGS @EXPORT_OK @EXPORT);
 use base qw(Exporter);
 
 BEGIN {
-    ($VERSION) = q$Revision: 1.2 $ =~ /^Revision:\s+([^\s+])/;
+    ($VERSION) = q$Revision: 1.3 $ =~ /^Revision:\s+([^\s+])/;
     $DEBUG = 0 unless defined $DEBUG;
 
     @EXPORT = ();
-    @EXPORT_OK = qw(is_valid_user read_usertags write_usertags);
+    @EXPORT_OK = qw(is_valid_user open);
     $EXPORT_TAGS{all} = [@EXPORT_OK];
 }
 
-
 my $gSpoolPath = "/org/bugs.debian.org/spool";
 
-sub esc { 
-    my $s = shift;
-    if ($s =~ m/^[0-9a-zA-Z_+.-]$/) { return $s; } 
-    else { return sprintf("%%%02X", ord($s)); } 
-} 
+# Obsolete compatability functions
+
+sub read_usertags {
+    my $ut = shift;
+    my $u = shift;
+    
+    my $user = get_user($u);
+    for my $t (keys %{$user->{"tags"}}) {
+        $ut->{$t} = [] unless defined $ut->{$t};
+        push @{$ut->{$t}}, @{$user->{"tags"}->{$t}};
+    }
+}
+
+sub write_usertags {
+    my $ut = shift;
+    my $u = shift;
+    
+    my $user = get_user($u, 1); # locked
+    $user->{"tags"} = { %{$ut} };
+    $user->write();
+}
+
+#######################################################################
+# Helper functions
 
 sub filefromemail {
     my $e = shift;
     my $l = length($e) % 7;
-    return "$gSpoolPath/user/$l/" . join("", map { esc($_); } split //, $e);
+    return "$gSpoolPath/user/$l/" . join("", 
+        map { m/^[0-9a-zA-Z_+.-]$/ ? $_ : sprintf("%%%02X", ord($_)) }
+            split //, $e);
 }
 
 sub read_stanza {
@@ -58,39 +93,19 @@ sub read_stanza {
     my $field = 0;
     my @res;
     while (<$f>) {
-       chomp;
-       last if (m/^$/);
+          chomp;
+          last if (m/^$/);
 
         if ($field && m/^ (.*)$/) {
             $res[-1] .= "\n" . $1;
-       } elsif (m/^([^:]+):\s+(.*)$/) {
+        } elsif (m/^([^:]+):(\s+(.*))?$/) {
             $field = $1;
-           push @res, ($1, $2);
+            push @res, ($1, $3);
         }
     }
     return @res;
 }
 
-sub read_usertags {
-    my $ut = shift;
-    my $u = shift;
-    my $p = filefromemail($u);
-    my $uf;
-
-    open($uf, "< $p") or return;
-    while(1) {
-        my @stanza = read_stanza($uf);
-       last if ($#stanza == -1);
-       if ($stanza[0] eq "Tag") {
-            my %tag = @stanza;
-            my $t = $tag{"Tag"};
-            $ut->{$t} = [] unless defined $ut->{$t};
-            push @{$ut->{$t}}, split /\s*,\s*/, $tag{Bugs};
-        }
-    }
-    close($uf);
-}
-               
 sub fmt {
     my $s = shift;
     my $n = shift;
@@ -98,37 +113,158 @@ sub fmt {
     my $res = "";
     while ($s =~ m/^([^,]*,\s*)(.*)$/ || $s =~ m/^([^,]+)()$/) {
         my $k = $1;
-       $s = $2;
+        $s = $2;
         unless ($sofar == 0 or $sofar + length($k) <= $n) {
-           $res .= "\n ";
-           $sofar = 1;
-       }
-       $res .= $k;
-       $sofar += length($k);
+               $res .= "\n ";
+               $sofar = 1;
+           }
+           $res .= $k;
+           $sofar += length($k);
     }
     return $res . $s;
 }
 
-sub write_usertags {
-    my $ut = shift;
+sub is_valid_user {
+    my $u = shift;
+    return ($u =~ /^[a-zA-Z0-9._+-]+[@][a-z0-9-.]{4,}$/);
+}
+
+#######################################################################
+# The real deal
+
+sub get_user {
+    my $ut = {};
+    my $user = { 
+        "tags" => $ut, 
+        "categories" => {}, 
+        "visible_cats" => [],
+        "unknown_stanzas" => [] 
+    };
+
     my $u = shift;
+    my $need_lock = shift || 0;
     my $p = filefromemail($u);
 
-    open(U, "> $p") or die "couldn't write to $p";
+    my $uf;
+    $user->{"filename"} = $p;
+    open($uf, "< $p") or bless $user, "Debbugs::User";
+    if ($need_lock) {
+        flock($uf, LOCK_EX); 
+        $user->{"locked"} = $uf;
+    }
+    
+    while(1) {
+        my @stanza = read_stanza($uf);
+        last if ($#stanza == -1);
+        if ($stanza[0] eq "Tag") {
+            my %tag = @stanza;
+            my $t = $tag{"Tag"};
+            $ut->{$t} = [] unless defined $ut->{$t};
+            push @{$ut->{$t}}, split /\s*,\s*/, $tag{Bugs};
+        } elsif ($stanza[0] eq "Category") {
+            my @cat = ();
+            my %stanza = @stanza;
+            my $catname = $stanza{"Category"};
+            my $i = 0;
+            while (++$i && defined $stanza{"Cat${i}"}) {
+                if (defined $stanza{"Cat${i}Options"}) {
+                    # parse into a hash
+                    my %c = ("nam" => $stanza{"Cat${i}"});
+                    $c{"def"} = $stanza{"Cat${i}Default"}
+                        if defined $stanza{"Cat${i}Default"};
+                    $c{"ord"} = [ split /,/, $stanza{"Cat${i}Order"} ]
+                        if defined $stanza{"Cat${i}Order"};
+                    my @pri; my @ttl;
+                    for my $l (split /\n/, $stanza{"Cat${i}Options"}) {
+                        if ($l =~ m/^\s*(\S+)\s+-\s+(.*\S)\s*$/) {
+                            push @pri, $1;
+                            push @ttl, $2;
+                        } elsif ($l =~ m/^\s*(\S+)\s*$/) {
+                            push @pri, $1;
+                            push @ttl, $1;
+                        }
+                    }
+                    $c{"ttl"} = [@ttl];
+                    $c{"pri"} = [@pri];
+                    push @cat, { %c };                    
+                } else {
+                    push @cat, $stanza{"Cat${i}"};
+                }
+            }
+            $user->{"categories"}->{$catname} = [@cat];
+            push @{$user->{"visible_cats"}}, $catname
+                unless ($stanza{"Hidden"} || "no") eq "yes";                        
+        } else {
+            push @{$user->{"unknown_stanzas"}}, [@stanza];
+        }
+    }
+    close($uf) unless $need_lock;
+
+    bless $user, "Debbugs::User";
+    return $user;
+}
+
+sub write {
+    my $user = shift;
+    my $uf;
+    my $ut = $user->{"tags"};
+    my $p = $user->{"filename"};
+
+    if ($p =~ m/^(.+)$/) { $p = $1; } else { return; } 
+    open $uf, "> $p" or return;
+
+    for my $us (@{$user->{"unknown_stanzas"}}) {
+        my @us = @{$us};
+        while (@us) {
+            my $k = shift @us; my $v = shift @us;
+           $v =~ s/\n/\n /g;
+            print $uf "$k: $v\n";
+        }
+        print $uf "\n";
+    }
+
     for my $t (keys %{$ut}) {
         next if @{$ut->{$t}} == 0;
-        print U "Tag: $t\n";
-        print U fmt("Bugs: " . join(", ", @{$ut->{$t}}), 77) . "\n";
-        print U "\n";
+        print $uf "Tag: $t\n";
+        print $uf fmt("Bugs: " . join(", ", @{$ut->{$t}}), 77) . "\n";
+        print $uf "\n";
     }
-    close(U);
-}
 
-sub is_valid_user {
-    my $u = shift;
-    return ($u =~ /^[a-zA-Z0-9._+-]+[@][a-z0-9-.]{4,}$/);
-}
+    my $uc = $user->{"categories"};
+    my %vis = map { $_, 1 } @{$user->{"visible_cats"}};
+    for my $c (keys %{$uc}) {
+        next if @{$uc->{$c}} == 0;
 
+        print $uf "Category: $c\n";
+       print $uf "Hidden: yes\n" unless defined $vis{$c};
+       my $i = 0;
+       for my $cat (@{$uc->{$c}}) {
+           $i++;
+           if (ref($cat) eq "HASH") {
+               printf $uf "Cat%d: %s\n", $i, $cat->{"nam"};
+               printf $uf "Cat%dOptions:\n", $i;
+               for my $j (0..$#{$cat->{"pri"}}) {
+                   if (defined $cat->{"ttl"}->[$j]) {
+                       printf $uf " %s - %s\n",
+                           $cat->{"pri"}->[$j], $cat->{"ttl"}->[$j];
+                   } else {
+                       printf $uf " %s\n", $cat->{"pri"}->[$j];
+                   }
+               }
+               printf $uf "Cat%dDefault: %s\n", $i, $cat->{"def"}
+                   if defined $cat->{"def"};
+               printf $uf "Cat%dOrder: %s\n", $i, join(", ", @{$cat->{"ord"}})
+                   if defined $cat->{"ord"};
+           } else {
+               printf $uf "Cat%d: %s\n", $i, $cat;
+           }
+       }
+       print $uf "\n";
+    }
+
+    close($uf);
+    delete $user->{"locked"};
+}
 
 1;