/[suikacvs]/test/suika-accounts/users.pl
Suika

Contents of /test/suika-accounts/users.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show annotations) (download)
Wed Oct 29 14:43:28 2008 UTC (15 years, 6 months ago) by wakaba
Branch: MAIN
File MIME type: text/plain
New

1 use strict;
2
3 my $user_data_dir_name = 'data/';
4 my $user_prop_file_suffix = '.user';
5
6 my $group_data_dir_name = 'data/';
7 my $group_prop_file_suffix = '.group';
8
9 my $htpasswd_file_name = 'data/htpasswd';
10 my $htgroup_file_name = 'data/htgroup';
11
12 my $lock_file_name = $user_data_dir_name . '.lock';
13
14 use Fcntl ':flock';
15 my $Lock;
16
17 sub lock_start () {
18 return if $Lock;
19
20 open $Lock, '>', $lock_file_name or die "$0: $lock_file_name: $!";
21 flock $Lock, LOCK_EX;
22 } # lock_start
23
24 sub get_prop_hash ($) {
25 my $user_prop_file_name = shift;
26
27 return undef unless -f $user_prop_file_name;
28
29 my $r = {};
30
31 open my $user_prop_file, '<:encoding(utf8)', $user_prop_file_name
32 or die "$0: $user_prop_file_name: $!";
33 while (<$user_prop_file>) {
34 tr/\x0D\x0A//d;
35 my ($n, $v) = split /:/, $_, 2;
36 if ($n =~ s/^\@//) {
37 push @{$r->{$n} ||= []}, $v // '';
38 } elsif ($n =~ s/^%//) {
39 $r->{$n}->{$v // ''} = 1;
40 } else {
41 $n =~ s/^\$//;
42 $r->{$n} = $v // '';
43 }
44 }
45
46 return $r;
47 } # get_prop_hash
48
49 sub set_prop_hash ($$) {
50 my $user_prop_file_name = shift;;
51 my $prop = shift;
52
53 my $has_file = -f $user_prop_file_name;
54
55 open my $user_prop_file, '>:encoding(utf8)', $user_prop_file_name
56 or die "$0: $user_prop_file_name: $!";
57 for my $prop_name (sort {$a cmp $b} keys %$prop) {
58 if (ref $prop->{$prop_name} eq 'ARRAY') {
59 my $v = '@' . $prop_name;
60 $v =~ tr/\x0D\x0A://d;
61 for (@{$prop->{$prop_name}}) {
62 my $pv = $_;
63 $pv =~ tr/\x0D\x0A/ /;
64 print $user_prop_file $v . ':' . $pv . "\x0A";
65 }
66 } elsif (ref $prop->{$prop_name} eq 'HASH') {
67 my $v = '%' . $prop_name;
68 $v =~ tr/\x0D\x0A://d;
69 for (sort {$a cmp $b} keys %{$prop->{$prop_name}}) {
70 next unless $prop->{$prop_name}->{$_};
71 my $pv = $_;
72 $pv =~ tr/\x0D\x0A/ /;
73 print $user_prop_file $v . ':' . $pv . "\x0A";
74 }
75 } else {
76 my $v = '$' . $prop_name;
77 $v =~ tr/\x0D\x0A://d;
78 my $pv = $prop->{$prop_name};
79 $pv =~ tr/\x0D\x0A/ /;
80 print $user_prop_file $v . ':' . $pv . "\x0A";
81 }
82 }
83 close $user_prop_file_name;
84
85 system_ ('cvs', 'add', $user_prop_file_name) unless $has_file;
86 } # set_prop_hash
87
88 sub commit ($) {
89 my $msg = shift // $0;
90 system_ ('cvs', 'commit', -m => $msg, $user_data_dir_name);
91 } # commit
92
93 sub get_user_prop ($) {
94 my $user_id = shift;
95 return get_prop_hash ($user_data_dir_name . $user_id . $user_prop_file_suffix);
96 } # get_user_prop
97
98 sub set_user_prop ($$) {
99 my ($user_id, $prop) = @_;
100 return set_prop_hash ($user_data_dir_name . $user_id . $user_prop_file_suffix,
101 $prop);
102 } # set_user_prop
103
104 sub get_group_prop ($) {
105 my $group_id = shift;
106 return get_prop_hash ($group_data_dir_name .
107 $group_id . $group_prop_file_suffix);
108 } # get_group_prop
109
110 sub set_group_prop ($$) {
111 my ($group_id, $prop) = @_;
112 return set_prop_hash ($group_data_dir_name .
113 $group_id . $group_prop_file_suffix,
114 $prop);
115 } # set_group_prop
116
117 sub get_all_users () {
118 my @r;
119 opendir my $user_data_dir, $user_data_dir_name;
120 for (readdir $user_data_dir) {
121 if (/^([0-9a-z-]+)\Q$user_prop_file_suffix\E$/) {
122 push @r, $1;
123 }
124 }
125 return @r;
126 } # get_all_users
127
128 sub get_all_groups () {
129 my @r;
130 opendir my $group_data_dir, $group_data_dir_name;
131 for (readdir $group_data_dir) {
132 if (/^([0-9a-z-]+)\Q$group_prop_file_suffix\E$/) {
133 push @r, $1;
134 }
135 }
136 return @r;
137 } # get_all_groups
138
139 sub regenerate_htpasswd_and_htgroup () {
140 my %htpasswd;
141 my %htgroup;
142
143 my @group = get_all_groups ();
144
145 for my $user_id (get_all_users ()) {
146 my $user_prop = get_user_prop ($user_id);
147 next if $user_prop->{disabled};
148 next unless $user_prop->{pass_crypted};
149
150 $htpasswd{$user_id} = $user_prop->{pass_crypted};
151
152 for (@group) {
153 if ($user_prop->{'group.' . $_}->{member}) {
154 $htgroup{$_}->{$user_id} = 1;
155 }
156 }
157 }
158
159 open my $file, '>', $htpasswd_file_name or die "$0: $htpasswd_file_name: $!";
160 for (sort {$a cmp $b} keys %htpasswd) {
161 print $file $_, ':', $htpasswd{$_}, "\x0A";
162 }
163
164 open my $file, '>', $htgroup_file_name or die "$0: $htgroup_file_name: $!";
165 for my $group_id (sort {$a cmp $b} keys %htgroup) {
166 print $file $group_id, ': ',
167 join ' ', sort {$a cmp $b} keys %{$htgroup{$group_id}};
168 print $file "\x0A";
169 }
170 } # regenerate_htpasswd_and_htgroup
171
172 sub print_error ($$) {
173 my ($code, $text) = @_;
174 binmode STDOUT, ':encoding(utf-8)';
175 print qq[Status: $code $text
176 Content-Type: text/html; charset=utf-8
177
178 <!DOCTYPE HTML>
179 <html lang=en>
180 <title>$code @{[htescape ($text)]}</title>
181 <h1>Error</h1>
182 <p>@{[htescape ($text)]}.<!--];
183 print 0 for 0..511; # for WinIE
184 print q[-->];
185 } # print_error
186
187 sub check_password ($) {
188 my $cgi = shift;
189
190 my $user_pass = $cgi->get_parameter ('user-pass');
191 my $user_pass2 = $cgi->get_parameter ('user-pass2');
192 if ($user_pass ne $user_pass2) {
193 print_error (400, 'Two passwords you input are different');
194 exit;
195 }
196
197 if (4 > length $user_pass) {
198 print_error (400, 'Password must be longer than 3 characters');
199 exit;
200 }
201
202 my $pass_crypted = crypt $user_pass,
203 join '', (0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64];
204 return $pass_crypted;
205 } # check_password
206
207 sub system_ (@) {
208 (system join (' ', map {quotemeta $_} @_) . " > /dev/null") == 0
209 or die "$0: $?";
210 } # system_
211
212 sub htescape ($) {
213 my $s = shift;
214 $s =~ s/&/&amp;/g;
215 $s =~ s/</&lt;/g;
216 $s =~ s/>/&gt;/g;
217 $s =~ s/"/&quot;/g;
218 return $s;
219 } # htescape
220
221 1;

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24