File Coverage

blib/lib/FAQ/OMatic/Groups.pm
Criterion Covered Total %
statement 9 116 7.7
branch 0 28 0.0
condition 0 3 0.0
subroutine 3 15 20.0
pod 0 12 0.0
total 12 174 6.9


line stmt bran cond sub pod time code
1             ##############################################################################
2             # The Faq-O-Matic is Copyright 1997 by Jon Howell, all rights reserved. #
3             # #
4             # This program is free software; you can redistribute it and/or #
5             # modify it under the terms of the GNU General Public License #
6             # as published by the Free Software Foundation; either version 2 #
7             # of the License, or (at your option) any later version. #
8             # #
9             # This program is distributed in the hope that it will be useful, #
10             # but WITHOUT ANY WARRANTY; without even the implied warranty of #
11             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
12             # GNU General Public License for more details. #
13             # #
14             # You should have received a copy of the GNU General Public License #
15             # along with this program; if not, write to the Free Software #
16             # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.#
17             # #
18             # Jon Howell can be contacted at: #
19             # 6211 Sudikoff Lab, Dartmouth College #
20             # Hanover, NH 03755-3510 #
21             # jonh@cs.dartmouth.edu #
22             # #
23             # An electronic copy of the GPL is available at: #
24             # http://www.gnu.org/copyleft/gpl.html #
25             # #
26             ##############################################################################
27              
28 1     1   5 use strict;
  1         2  
  1         46  
29              
30             ###
31             ### FAQ::OMatic::Groups manages group membership, so you can control postings
32             ### more finely than {moderator-only or anyone-with-an-email-address}.
33             ###
34              
35             package FAQ::OMatic::Groups;
36              
37 1     1   7 use FAQ::OMatic;
  1         3  
  1         19  
38 1     1   5 use FAQ::OMatic::I18N;
  1         1  
  1         2415  
39              
40             sub readGroups {
41             # groups are cached per CGI invocation so we don't have to read
42             # the groups file from the filesystem multiple times.
43             # We store the cache in the s/getLocal() mechanism so that it
44             # doesn't persist across invocations on a mod_perl child.
45 0     0 0   my $groupCache = FAQ::OMatic::getLocal('groupCache');
46 0 0         return $groupCache if (defined $groupCache);
47              
48 0 0         if (not open GROUPS, "$FAQ::OMatic::Config::metaDir/groups") {
49 0           $groupCache = {};
50             } else {
51 0           while (defined($_=)) {
52 0           chomp;
53 0           my ($groupName, $member) = split('\s', $_, 2);
54 0           $groupCache->{$groupName}{$member} = 1;
55             }
56 0           close GROUPS;
57             }
58              
59             # Make sure the one special group ('Administrators') always appears,
60             # even if it has no members. By deleting, we avoid disturbing any
61             # loaded hash, but ensures Perl creates a hash for this group.
62 0           delete $groupCache->{'Administrators'}{''};
63              
64 0           FAQ::OMatic::setLocal('groupCache', $groupCache);
65 0           return $groupCache;
66             }
67              
68             sub writeGroups {
69 0     0 0   my $groups = shift;
70 0           my $groupCache = readGroups();
71 0 0         $groupCache = $groups if (defined $groups); # allow caller to overwrite
72              
73 0 0         if (not open GROUPS, ">$FAQ::OMatic::Config::metaDir/groups") {
74 0           FAQ::OMatic::gripe('abort',
75             "Can't write to $FAQ::OMatic::Config::metaDir/groups: $!.");
76             }
77 0           my ($groupName, $member);
78 0           foreach $groupName (sort keys %{$groupCache}) {
  0            
79 0           foreach $member (sort keys %{$groupCache->{$groupName}}) {
  0            
80 0           print GROUPS "$groupName $member\n";
81             }
82             }
83 0           close GROUPS;
84             }
85              
86             sub getGroupNameList {
87 0     0 0   my $groupCache = readGroups();
88 0           return sort keys %{$groupCache};
  0            
89             }
90              
91             sub groupCodeToName {
92 0     0 0   my $code = shift;
93 0           $code =~ s/^6 //;
94 0           return $code; # boy, that was easy.
95             }
96              
97             sub groupNameToCode {
98 0     0 0   my $code = shift;
99 0           return "6 ".$code;
100             }
101              
102             sub getGroupCodeList {
103 0     0 0   readGroups();
104 0           return map {groupNameToCode($_)} getGroupNameList();
  0            
105             }
106              
107             sub checkMembership {
108 0     0 0   my $code = shift;
109 0           my $id = shift;
110              
111 0           my $groupCache = readGroups();
112 0 0         return 1 if ($id eq $FAQ::OMatic::Config::adminAuth);
113              
114 0           readGroups();
115              
116             # By checking for the existence of the group first, we avoid
117             # "creating" that group in the in-core cache as a side effect of
118             # looking in its hash for $id.
119 0 0         return 0 if (not $groupCache->{groupCodeToName($code)});
120              
121             # check for a direct user match:
122 0 0         return 1 if ($groupCache->{groupCodeToName($code)}{$id});
123              
124             # check if any domains match a suffix of user's id:
125 0           my @members = keys %{$groupCache->{groupCodeToName($code)}};
  0            
126 0           my @domains = grep {not FAQ::OMatic::validEmail($_)} @members;
  0            
127 0           my $domain;
128 0           foreach $domain (@domains) {
129 0 0         return 1 if ($id =~ m/$domain$/);
130             }
131              
132 0           return 0;
133             }
134              
135             sub displayHTML {
136 0     0 0   my $group = shift;
137 0           my $html = '';
138              
139 0           my $groupCache = readGroups();
140              
141 0 0         if (not $group) {
142 0           $html.=gettext("Select a group to edit:")."
\n";
143 0           my ($groupName,$member);
144 0           foreach $groupName (getGroupNameList()) {
145 0           $html.="
"
146             .FAQ::OMatic::makeAref('editGroups', {'group'=>$groupName})
147             ."$groupName\n";
148 0 0         if ($groupName eq 'Administrators') {
149 0           $html.="
"
150             .gettext("(Members of this group are allowed to access these group definition pages.)")
151             ."\n";
152             }
153 0           my $limit=4;
154 0           foreach $member
  0            
155 0           (sort {sortEmail($a,$b)} keys %{$groupCache->{$groupName}}) {
156              
157 0           $html.="
$member\n";
158 0 0         if (--$limit <= 0) {
159 0           $html.="
...\n";
160 0           last;
161             }
162             }
163             }
164 0           $html.="\n";
165 0           $html.=FAQ::OMatic::makeAref('editGroups', {'group'=>''}, 'GET')
166             ."\n"
167             ."
168             .gettext("Add Group")
169             ."\">\n"
170             ."\n";
171             } else {
172 0           validGroupName($group);
173 0           $html.="

".FAQ::OMatic::button(

174             FAQ::OMatic::makeAref('editGroups', {'group'=>''}),
175             gettext("Up To List Of Groups"));
176              
177 0           $html.="\n" \n"; \n"; \n";
178             ."
$group
179 0           my $member;
180 0           foreach $member
  0            
181 0           (sort {sortEmail($a,$b)} keys %{$groupCache->{$group}}) {
182              
183 0           $html.="
\n"
184             .FAQ::OMatic::button(
185             FAQ::OMatic::makeAref('submitGroup',
186             {'_action'=>'remove', '_member'=>$member}),
187             gettext("Remove Member"))
188             .""
189             ."$member\n"
190             ."
191             }
192 0           $html.="
"
193             .FAQ::OMatic::makeAref('submitGroup',
194             {'_action'=>'add'}, 'GET')
195             ."
196             .gettext("Add Member")
197             ."\">\n"
198             ."\n"
199             ."\n"
200             ."
201 0           $html.="
\n";
202             }
203              
204 0           $html.="

".FAQ::OMatic::button(

205             FAQ::OMatic::makeAref('faq', {'group'=>''}),
206             gettext("Go to the Faq-O-Matic"));
207 0           $html.=" ".FAQ::OMatic::button(
208             FAQ::OMatic::makeAref('install', {'group'=>''}),
209             gettext("Go To Install/Configuration Page"));
210 0           $html.="\n";
211              
212 0           return $html;
213             }
214              
215             sub addMember {
216 0     0 0   my $group = shift;
217 0           my $member = shift;
218              
219 0           my $groupCache = readGroups();
220 0           $groupCache->{$group}{$member} = 1;
221 0           writeGroups();
222             }
223              
224             sub removeMember {
225 0     0 0   my $group = shift;
226 0           my $member = shift;
227              
228 0           my $groupCache = readGroups();
229 0           delete $groupCache->{$group}{$member};
230 0           writeGroups();
231             }
232              
233             sub validGroupName {
234 0     0 0   my $group = shift;
235              
236 0 0         if (not $group =~ m/^[\w.-]+$/) {
237 0           FAQ::OMatic::gripe('error',
238             "Group names may only contain alphanumerics, "
239             ."periods, and hyphens.");
240             }
241             }
242              
243             sub sortEmail {
244 0     0 0   my $a = shift;
245 0           my $b = shift;
246 0           my ($auser,$adomain,$buser,$bdomain);
247              
248 0 0         if ($a =~ m'@') {
249 0           ($auser,$adomain) = split('@', $a);
250             } else {
251 0           ($auser,$adomain) = ('', $a);
252             }
253 0 0         if ($b =~ m'@') {
254 0           ($buser,$bdomain) = split('@', $b);
255             } else {
256 0           ($buser,$bdomain) = ('', $b);
257             }
258            
259 0   0       return ($adomain cmp $bdomain) || ($auser cmp $buser);
260             }
261              
262             1;