/[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 - (hide 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 wakaba 1.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