blib/lib/CGI/AuthRegister.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 18 | 504 | 3.5 |
branch | 0 | 202 | 0.0 |
condition | 0 | 39 | 0.0 |
subroutine | 6 | 40 | 15.0 |
pod | 2 | 33 | 6.0 |
total | 26 | 818 | 3.1 |
line | stmt | bran | cond | sub | pod | time | code | ||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | # read_starfish_conf(); &generate_header; !> | ||||||||||||||||||||||||||||||||||||||||||||
2 | #+ | ||||||||||||||||||||||||||||||||||||||||||||
3 | # file: AuthRegister.pm | ||||||||||||||||||||||||||||||||||||||||||||
4 | # CGI::AuthRegister - Simple CGI Authentication and Registration in Perl | ||||||||||||||||||||||||||||||||||||||||||||
5 | # (c) 2012-14 Vlado Keselj http://web.cs.dal.ca/~vlado | ||||||||||||||||||||||||||||||||||||||||||||
6 | # $Date: $ | ||||||||||||||||||||||||||||||||||||||||||||
7 | # $Id: $ | ||||||||||||||||||||||||||||||||||||||||||||
8 | #- | ||||||||||||||||||||||||||||||||||||||||||||
9 | |||||||||||||||||||||||||||||||||||||||||||||
10 | package CGI::AuthRegister; | ||||||||||||||||||||||||||||||||||||||||||||
11 | 1 | 1 | 5558 | use strict; | |||||||||||||||||||||||||||||||||||||||||
1 | 2 | ||||||||||||||||||||||||||||||||||||||||||||
1 | 43 | ||||||||||||||||||||||||||||||||||||||||||||
12 | # &generate_standard_vars !> | ||||||||||||||||||||||||||||||||||||||||||||
13 | #+ | ||||||||||||||||||||||||||||||||||||||||||||
14 | 1 | 1 | 5 | use vars qw($NAME $ABSTRACT $VERSION); | |||||||||||||||||||||||||||||||||||||||||
1 | 3 | ||||||||||||||||||||||||||||||||||||||||||||
1 | 80 | ||||||||||||||||||||||||||||||||||||||||||||
15 | $NAME = 'AuthRegister'; | ||||||||||||||||||||||||||||||||||||||||||||
16 | $ABSTRACT = 'Simple CGI Authentication and Registration in Perl'; | ||||||||||||||||||||||||||||||||||||||||||||
17 | $VERSION = '1.0'; | ||||||||||||||||||||||||||||||||||||||||||||
18 | #- | ||||||||||||||||||||||||||||||||||||||||||||
19 | 1 | 1 | 807169 | use CGI qw(:standard); | |||||||||||||||||||||||||||||||||||||||||
1 | 29679 | ||||||||||||||||||||||||||||||||||||||||||||
1 | 9 | ||||||||||||||||||||||||||||||||||||||||||||
20 | # Useful diagnostics: | ||||||||||||||||||||||||||||||||||||||||||||
21 | # use CGI qw(:standard :Carp -debug); | ||||||||||||||||||||||||||||||||||||||||||||
22 | # use CGI::Carp 'fatalsToBrowser'; | ||||||||||||||||||||||||||||||||||||||||||||
23 | # use diagnostics; # verbose error messages | ||||||||||||||||||||||||||||||||||||||||||||
24 | # use strict; # check for mistakes | ||||||||||||||||||||||||||||||||||||||||||||
25 | 1 | 1 | 5172 | use Carp; | |||||||||||||||||||||||||||||||||||||||||
1 | 8 | ||||||||||||||||||||||||||||||||||||||||||||
1 | 115 | ||||||||||||||||||||||||||||||||||||||||||||
26 | require Exporter; | ||||||||||||||||||||||||||||||||||||||||||||
27 | 1 | 1 | 6 | use vars qw(@ISA @EXPORT); | |||||||||||||||||||||||||||||||||||||||||
1 | 2 | ||||||||||||||||||||||||||||||||||||||||||||
1 | 107 | ||||||||||||||||||||||||||||||||||||||||||||
28 | @ISA = qw(Exporter); | ||||||||||||||||||||||||||||||||||||||||||||
29 | @EXPORT = qw($Error $SessionId $SiteId $SiteName $User | ||||||||||||||||||||||||||||||||||||||||||||
30 | $UserEmail $SendLogs $LogReport | ||||||||||||||||||||||||||||||||||||||||||||
31 | analyze_cookie header_delete_cookie header_session_cookie | ||||||||||||||||||||||||||||||||||||||||||||
32 | import_dir_and_config login logout | ||||||||||||||||||||||||||||||||||||||||||||
33 | require_https require_login send_email_reminder | ||||||||||||||||||||||||||||||||||||||||||||
34 | get_user get_user_by_userid set_new_session store_log | ||||||||||||||||||||||||||||||||||||||||||||
35 | ); | ||||||||||||||||||||||||||||||||||||||||||||
36 | |||||||||||||||||||||||||||||||||||||||||||||
37 | 1 | 8529 | use vars qw($Email_from $Email_bcc $Error $ErrorInternal $LogReport $Sendmail | ||||||||||||||||||||||||||||||||||||||||||
38 | 1 | 1 | 5 | $Session $SessionId $SiteId $SiteName $Ticket $User $UserEmail $SendLogs); | |||||||||||||||||||||||||||||||||||||||||
1 | 3 | ||||||||||||||||||||||||||||||||||||||||||||
39 | # $Error = ''; # Appended error messages, OK to be sent to user | ||||||||||||||||||||||||||||||||||||||||||||
40 | # $ErrorInternal = ''; # Appended internal error messages, intended | ||||||||||||||||||||||||||||||||||||||||||||
41 | # for administrator | ||||||||||||||||||||||||||||||||||||||||||||
42 | # $LogReport = ''; # Collecting some important log events if needed | ||||||||||||||||||||||||||||||||||||||||||||
43 | # $Session = ''; # Session data structure | ||||||||||||||||||||||||||||||||||||||||||||
44 | # $SessionId = ''; # Session identifier, generated | ||||||||||||||||||||||||||||||||||||||||||||
45 | $SiteId = 'Site'; # Site identifier, used in cookies and emails | ||||||||||||||||||||||||||||||||||||||||||||
46 | $SiteName = 'Site'; # Site name, can include spaces | ||||||||||||||||||||||||||||||||||||||||||||
47 | # $Ticket = ''; # Session ticket for security, generated | ||||||||||||||||||||||||||||||||||||||||||||
48 | # $User = ''; # User data structure | ||||||||||||||||||||||||||||||||||||||||||||
49 | # $UserEmail = ''; # User email address | ||||||||||||||||||||||||||||||||||||||||||||
50 | # $SendLogs = ''; # If true, send logs by email to admin ($Email_bcc) | ||||||||||||||||||||||||||||||||||||||||||||
51 | |||||||||||||||||||||||||||||||||||||||||||||
52 | $Email_from = ''; # Example: $SiteId.' |
||||||||||||||||||||||||||||||||||||||||||||
53 | $Email_bcc = ''; # Example: $SiteId.' Bcc |
||||||||||||||||||||||||||||||||||||||||||||
54 | |||||||||||||||||||||||||||||||||||||||||||||
55 | $Sendmail = "/usr/lib/sendmail"; # Sendmail with full path | ||||||||||||||||||||||||||||||||||||||||||||
56 | |||||||||||||||||||||||||||||||||||||||||||||
57 | # Functions | ||||||||||||||||||||||||||||||||||||||||||||
58 | sub putfile($@); | ||||||||||||||||||||||||||||||||||||||||||||
59 | |||||||||||||||||||||||||||||||||||||||||||||
60 | ######################################################################## | ||||||||||||||||||||||||||||||||||||||||||||
61 | # Configuration | ||||||||||||||||||||||||||||||||||||||||||||
62 | # sets site id as the base directory name; imports configuration.pl if exists | ||||||||||||||||||||||||||||||||||||||||||||
63 | sub import_dir_and_config { | ||||||||||||||||||||||||||||||||||||||||||||
64 | 0 | 0 | 1 | my $base = `pwd`; $base =~ /\/([^\/]*)$/; $base = $1; $base =~ s/\s+$//; | |||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
65 | 0 | $SiteId = $SiteName = $base; | |||||||||||||||||||||||||||||||||||||||||||
66 | 0 | 0 | if (-r 'configuration.pl') { package main; require 'configuration.pl'; } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
67 | } | ||||||||||||||||||||||||||||||||||||||||||||
68 | |||||||||||||||||||||||||||||||||||||||||||||
69 | ######################################################################## | ||||||||||||||||||||||||||||||||||||||||||||
70 | # HTTPS Connection and Cookies Management | ||||||||||||||||||||||||||||||||||||||||||||
71 | |||||||||||||||||||||||||||||||||||||||||||||
72 | # Check that the connection is HTTPS and if not, redirect to HTTPS. | ||||||||||||||||||||||||||||||||||||||||||||
73 | # It must be done before script produces any output. | ||||||||||||||||||||||||||||||||||||||||||||
74 | sub require_https { | ||||||||||||||||||||||||||||||||||||||||||||
75 | 0 | 0 | 0 | 0 | if ($ENV{'HTTPS'} ne 'on') { | ||||||||||||||||||||||||||||||||||||||||
76 | 0 | print "Status: 301 Moved Permanently\nLocation: https://$ENV{SERVER_NAME}$ENV{SCRIPT_NAME}\n\n"; | |||||||||||||||||||||||||||||||||||||||||||
77 | 0 | exit 0; | |||||||||||||||||||||||||||||||||||||||||||
78 | } | ||||||||||||||||||||||||||||||||||||||||||||
79 | } | ||||||||||||||||||||||||||||||||||||||||||||
80 | |||||||||||||||||||||||||||||||||||||||||||||
81 | # If not logged in, ask for userid/email and password. Catches ?logout | ||||||||||||||||||||||||||||||||||||||||||||
82 | # request as well. Allows parentheses in userid/email for login, which are | ||||||||||||||||||||||||||||||||||||||||||||
83 | # removed. This allows users to use auxiliary comments with userid, so that | ||||||||||||||||||||||||||||||||||||||||||||
84 | # browser can distinguish passwords. | ||||||||||||||||||||||||||||||||||||||||||||
85 | sub require_login { | ||||||||||||||||||||||||||||||||||||||||||||
86 | 0 | 0 | 0 | my $title = "Login Page for Site: $SiteId"; | |||||||||||||||||||||||||||||||||||||||||
87 | 0 | my $HTMLstart = "$title\n"; |
|||||||||||||||||||||||||||||||||||||||||||
88 | 0 | my $Formstart = " | |||||||||||||||||||||||||||||||||||||||||||
89 | 0 | my $Back = "Click here for the main page.\n"; | |||||||||||||||||||||||||||||||||||||||||||
90 | 0 | my $LoginForm = " Please log in to access the site: |
|||||||||||||||||||||||||||||||||||||||||||
91 | "
|
||||||||||||||||||||||||||||||||||||||||||||
96 | 0 | my $SendResetForm = " If you forgot your password, it may be possible to ". |
|||||||||||||||||||||||||||||||||||||||||||
97 | "retrieve it by email: \n".$Formstart."Email: ". |
||||||||||||||||||||||||||||||||||||||||||||
98 | textfield(-name=>"email_pw_send")."\n". | ||||||||||||||||||||||||||||||||||||||||||||
99 | ''. | ||||||||||||||||||||||||||||||||||||||||||||
100 | "\n". | ||||||||||||||||||||||||||||||||||||||||||||
101 | "Or, you can reqest password to be reset and sent to you: \n". |
||||||||||||||||||||||||||||||||||||||||||||
102 | $Formstart."Email: ".textfield(-name=>"email_reset")."\n". | ||||||||||||||||||||||||||||||||||||||||||||
103 | ''. | ||||||||||||||||||||||||||||||||||||||||||||
104 | "\n"; | ||||||||||||||||||||||||||||||||||||||||||||
105 | |||||||||||||||||||||||||||||||||||||||||||||
106 | 0 | &analyze_cookie; | |||||||||||||||||||||||||||||||||||||||||||
107 | 0 | 0 | 0 | if ($SessionId ne '' && param('keywords') eq 'logout') { | |||||||||||||||||||||||||||||||||||||||||
108 | 0 | logout(); print header_delete_cookie(), $HTMLstart, | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
109 | 0 | " You are logged out.\n", $LoginForm, $SendResetForm; exit; } |
|||||||||||||||||||||||||||||||||||||||||||
110 | |||||||||||||||||||||||||||||||||||||||||||||
111 | 0 | 0 | if ($SessionId ne '') { print header(); return 1; } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
112 | |||||||||||||||||||||||||||||||||||||||||||||
113 | 0 | my $Request_type = param('request_type'); | |||||||||||||||||||||||||||||||||||||||||||
114 | |||||||||||||||||||||||||||||||||||||||||||||
115 | 0 | 0 | if ($Request_type eq 'Login') { | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
116 | 0 | my $email = param('userid'); my $password = param('password'); | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
117 | 0 | $email =~ s/\(.*\)//g; $email =~ s/\s+$//; $email =~ s/^\s+//; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
118 | |||||||||||||||||||||||||||||||||||||||||||||
119 | 0 | 0 | if (! &login($email, $password) ) { # checks for userid and email | ||||||||||||||||||||||||||||||||||||||||||
120 | 0 | print header(), $HTMLstart, "Unsuccessful login!\n"; | |||||||||||||||||||||||||||||||||||||||||||
121 | 0 | print $LoginForm, $SendResetForm; exit; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
122 | } | ||||||||||||||||||||||||||||||||||||||||||||
123 | 0 | else { print header_session_cookie(); return 1; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
124 | } | ||||||||||||||||||||||||||||||||||||||||||||
125 | elsif ($Request_type eq 'Send_Password') { | ||||||||||||||||||||||||||||||||||||||||||||
126 | 0 | &send_email_reminder(param('email_pw_send'), 'raw'); | |||||||||||||||||||||||||||||||||||||||||||
127 | 0 | print header(), $HTMLstart, "You should receive password reminder if ". | |||||||||||||||||||||||||||||||||||||||||||
128 | "your email is registered at this site.\n". | ||||||||||||||||||||||||||||||||||||||||||||
129 | "If you do not receive remider, you can contact the administrator.\n", | ||||||||||||||||||||||||||||||||||||||||||||
130 | $LoginForm, $SendResetForm; | ||||||||||||||||||||||||||||||||||||||||||||
131 | 0 | $LogReport.=$Error; &store_log; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
132 | 0 | exit; | |||||||||||||||||||||||||||||||||||||||||||
133 | } | ||||||||||||||||||||||||||||||||||||||||||||
134 | elsif ($Request_type eq 'Reset_Password') { | ||||||||||||||||||||||||||||||||||||||||||||
135 | 0 | &reset_and_send_email_reminder(param('email_reset'), 'raw'); | |||||||||||||||||||||||||||||||||||||||||||
136 | 0 | print header(), $HTMLstart, "You should receive new password if ". | |||||||||||||||||||||||||||||||||||||||||||
137 | "your email is registered at this site.\n". | ||||||||||||||||||||||||||||||||||||||||||||
138 | "If you do not receive remider, you can contact the administrator.\n", | ||||||||||||||||||||||||||||||||||||||||||||
139 | 0 | $LoginForm, $SendResetForm; exit; | |||||||||||||||||||||||||||||||||||||||||||
140 | } | ||||||||||||||||||||||||||||||||||||||||||||
141 | else { # should be: $Request_type eq '' | ||||||||||||||||||||||||||||||||||||||||||||
142 | 0 | print header(), $HTMLstart, $LoginForm, $SendResetForm; exit; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
143 | |||||||||||||||||||||||||||||||||||||||||||||
144 | 0 | die; # Not supposed to be reached | |||||||||||||||||||||||||||||||||||||||||||
145 | } | ||||||||||||||||||||||||||||||||||||||||||||
146 | |||||||||||||||||||||||||||||||||||||||||||||
147 | # Requires session (i.e., to be logged in). Otherwise, makes redirection. | ||||||||||||||||||||||||||||||||||||||||||||
148 | sub require_session { | ||||||||||||||||||||||||||||||||||||||||||||
149 | 0 | 0 | 0 | my %args=@_; my $defaultcgi = 'index.cgi'; | |||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
150 | 0 | 0 | 0 | if (exists($args{-redirect}) && $args{-redirect} ne '' && | |||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
151 | $args{-redirect} ne $ENV{SCRIPT_NAME}) | ||||||||||||||||||||||||||||||||||||||||||||
152 | 0 | { $defaultcgi = $args{-redirect} } | |||||||||||||||||||||||||||||||||||||||||||
153 | 0 | 0 | 0 | if (exists($args{-back}) && $args{-back}) { | |||||||||||||||||||||||||||||||||||||||||
154 | 0 | $defaultcgi.="?goto=$args{-back}"; | |||||||||||||||||||||||||||||||||||||||||||
155 | } | ||||||||||||||||||||||||||||||||||||||||||||
156 | 0 | &analyze_cookie; | |||||||||||||||||||||||||||||||||||||||||||
157 | 0 | 0 | if ($SessionId eq '') { | ||||||||||||||||||||||||||||||||||||||||||
158 | 0 | 0 | if ($ENV{SCRIPT_NAME} eq $defaultcgi) { | ||||||||||||||||||||||||||||||||||||||||||
159 | 0 | print CGI::header(), CGI::start_html, CGI::h1("147-ERR:Login required"); | |||||||||||||||||||||||||||||||||||||||||||
160 | 0 | exit; } | |||||||||||||||||||||||||||||||||||||||||||
161 | 0 | print CGI::redirect(-uri=>$defaultcgi); exit; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
162 | } | ||||||||||||||||||||||||||||||||||||||||||||
163 | } | ||||||||||||||||||||||||||||||||||||||||||||
164 | |||||||||||||||||||||||||||||||||||||||||||||
165 | # Prepare HTTP header. If SessionId is not empty, generate cookie with | ||||||||||||||||||||||||||||||||||||||||||||
166 | # the sessionid and ticket. | ||||||||||||||||||||||||||||||||||||||||||||
167 | sub header_session_cookie { | ||||||||||||||||||||||||||||||||||||||||||||
168 | 0 | 0 | 0 | my %args=@_; my $redirect=$args{-redirect}; | |||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
169 | 0 | 0 | if ($redirect ne '') { | ||||||||||||||||||||||||||||||||||||||||||
170 | 0 | 0 | if ($SessionId eq '') { return redirect(-uri=>$redirect) } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
171 | else { | ||||||||||||||||||||||||||||||||||||||||||||
172 | 0 | return redirect(-uri=>$redirect,-cookie=> | |||||||||||||||||||||||||||||||||||||||||||
173 | cookie(-name=>$SiteId, | ||||||||||||||||||||||||||||||||||||||||||||
174 | -value=>"$SessionId $Ticket")); | ||||||||||||||||||||||||||||||||||||||||||||
175 | } | ||||||||||||||||||||||||||||||||||||||||||||
176 | } else { | ||||||||||||||||||||||||||||||||||||||||||||
177 | 0 | 0 | if ($SessionId eq '') { return header } else | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
178 | 0 | { return header(-cookie=>cookie(-name=>$SiteId, | |||||||||||||||||||||||||||||||||||||||||||
179 | -value=>"$SessionId $Ticket")) } | ||||||||||||||||||||||||||||||||||||||||||||
180 | } | ||||||||||||||||||||||||||||||||||||||||||||
181 | } | ||||||||||||||||||||||||||||||||||||||||||||
182 | |||||||||||||||||||||||||||||||||||||||||||||
183 | # Delete cookie after logging out. Return string. | ||||||||||||||||||||||||||||||||||||||||||||
184 | sub header_delete_cookie { | ||||||||||||||||||||||||||||||||||||||||||||
185 | 0 | 0 | 0 | return header(-cookie=>cookie(-name=>$SiteId, -value=>'', -expires=>"now")) } | |||||||||||||||||||||||||||||||||||||||||
186 | |||||||||||||||||||||||||||||||||||||||||||||
187 | # Analyze cookie to detect session, and check the ticket as well. It | ||||||||||||||||||||||||||||||||||||||||||||
188 | # should be called at the beginning of a script. $SessionId and | ||||||||||||||||||||||||||||||||||||||||||||
189 | # $Ticket are set to empty string if not successful. The information | ||||||||||||||||||||||||||||||||||||||||||||
190 | # about the session is stored in db/sessions.d/$SessionId/session.info | ||||||||||||||||||||||||||||||||||||||||||||
191 | # file. The structures $Session and $User are set if successful. | ||||||||||||||||||||||||||||||||||||||||||||
192 | sub analyze_cookie { | ||||||||||||||||||||||||||||||||||||||||||||
193 | 0 | 0 | 1 | my $c = cookie(-name=>$SiteId); # sessionid and ticket | |||||||||||||||||||||||||||||||||||||||||
194 | 0 | 0 | if ($c eq '') { $SessionId = $Ticket = ''; return; } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
195 | 0 | ($SessionId, $Ticket) = split(/\s+/, $c); | |||||||||||||||||||||||||||||||||||||||||||
196 | 0 | 0 | 0 | if ($SessionId !~ /^[\w.:-]+$/ or $Ticket !~ /^\w+$/) | |||||||||||||||||||||||||||||||||||||||||
197 | 0 | { $User = $SessionId = $Ticket = ''; return; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
198 | |||||||||||||||||||||||||||||||||||||||||||||
199 | # check validity of session and set user variables | ||||||||||||||||||||||||||||||||||||||||||||
200 | 0 | my $sessioninfofile = "db/sessions.d/$SessionId/session.info"; | |||||||||||||||||||||||||||||||||||||||||||
201 | 0 | 0 | if (!-f $sessioninfofile) { $SessionId = $Ticket = ''; return; } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
202 | 0 | my $se = &read_db_record("file=$sessioninfofile"); | |||||||||||||||||||||||||||||||||||||||||||
203 | 0 | 0 | 0 | if (!ref($se) or $Ticket ne $se->{'Ticket'}) | |||||||||||||||||||||||||||||||||||||||||
204 | 0 | { $User = $SessionId = $Ticket = ''; return; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
205 | 0 | $Session = $se; | |||||||||||||||||||||||||||||||||||||||||||
206 | 0 | $UserEmail = $se->{email}; | |||||||||||||||||||||||||||||||||||||||||||
207 | 0 | $User = &get_user_by_email($UserEmail); | |||||||||||||||||||||||||||||||||||||||||||
208 | 0 | 0 | if ($Error ne '') { $User = $SessionId = $Ticket = ''; return; } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
209 | } | ||||||||||||||||||||||||||||||||||||||||||||
210 | |||||||||||||||||||||||||||||||||||||||||||||
211 | ######################################################################## | ||||||||||||||||||||||||||||||||||||||||||||
212 | # Session Management | ||||||||||||||||||||||||||||||||||||||||||||
213 | |||||||||||||||||||||||||||||||||||||||||||||
214 | # params: $email, opt: pwstore type: md5 raw | ||||||||||||||||||||||||||||||||||||||||||||
215 | sub reset_password { | ||||||||||||||||||||||||||||||||||||||||||||
216 | 0 | 0 | 0 | 0 | my $email = shift; my $pwstore = shift; $pwstore = 'md5' if $pwstore eq ''; | ||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
217 | 0 | my $password = &random_password(6); | |||||||||||||||||||||||||||||||||||||||||||
218 | 0 | 0 | if (!-f 'db/passwords') { | ||||||||||||||||||||||||||||||||||||||||||
219 | 0 | putfile 'db/passwords', ''; chmod 0600, 'db/passwords' } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
220 | 0 | 0 | if (!&lock_mkdir('db/passwords')) { $Error.="95-ERR:\n"; return ''; } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
221 | 0 | 0 | local *PH; open(PH,"db/passwords") or croak($!); | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
222 | 0 | my $content = ''; | |||||||||||||||||||||||||||||||||||||||||||
223 | 0 | while ( |
|||||||||||||||||||||||||||||||||||||||||||
224 | 0 | my ($e,$p) = split; | |||||||||||||||||||||||||||||||||||||||||||
225 | 0 | 0 | $content .= $_ if $e ne $email; | ||||||||||||||||||||||||||||||||||||||||||
226 | } | ||||||||||||||||||||||||||||||||||||||||||||
227 | 0 | close(PH); | |||||||||||||||||||||||||||||||||||||||||||
228 | 0 | $content .= "$email "; | |||||||||||||||||||||||||||||||||||||||||||
229 | 0 | 0 | if ($pwstore eq 'raw') { $content.="raw:$password" } | ||||||||||||||||||||||||||||||||||||||||||
0 | 0 | ||||||||||||||||||||||||||||||||||||||||||||
230 | 0 | elsif($pwstore eq 'md5') { $content.="md5:".md5_base64($password) } | |||||||||||||||||||||||||||||||||||||||||||
231 | #else { $content.="md5:".md5_base64($password) } | ||||||||||||||||||||||||||||||||||||||||||||
232 | 0 | else { $content.="raw:$password" } | |||||||||||||||||||||||||||||||||||||||||||
233 | 0 | $content .= "\n"; | |||||||||||||||||||||||||||||||||||||||||||
234 | 0 | putfile 'db/passwords', $content; chmod 0600, 'db/passwords'; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
235 | 0 | &unlock_mkdir('db/passwords'); | |||||||||||||||||||||||||||||||||||||||||||
236 | 0 | return $password; | |||||||||||||||||||||||||||||||||||||||||||
237 | } | ||||||||||||||||||||||||||||||||||||||||||||
238 | |||||||||||||||||||||||||||||||||||||||||||||
239 | sub md5_base64 { | ||||||||||||||||||||||||||||||||||||||||||||
240 | 0 | 0 | 0 | my $arg=shift; require Digest::MD5; return Digest::MD5::md5_base64($arg); } | |||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
241 | |||||||||||||||||||||||||||||||||||||||||||||
242 | sub random_password { | ||||||||||||||||||||||||||||||||||||||||||||
243 | 0 | 0 | 0 | 0 | my $n = shift; $n = 8 unless $n > 0; | ||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
244 | 0 | my @chars = (2..9, 'a'..'k', 'm'..'z', 'A'..'N', 'P'..'Z', | |||||||||||||||||||||||||||||||||||||||||||
245 | qw(, . / ? ; : - = + ! @ $ % *) ); | ||||||||||||||||||||||||||||||||||||||||||||
246 | 0 | return join('', map { $chars[rand($#chars+1)] } (1..$n)); | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
247 | } | ||||||||||||||||||||||||||||||||||||||||||||
248 | |||||||||||||||||||||||||||||||||||||||||||||
249 | # removes session file and return the appropriate HTTP header | ||||||||||||||||||||||||||||||||||||||||||||
250 | sub logout { | ||||||||||||||||||||||||||||||||||||||||||||
251 | 0 | 0 | 0 | 0 | if ($Session eq '') { $Error.= "217-ERR: No session to log out\n"; return; } | ||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
252 | 0 | 0 | if (!-d "db/sessions.d/$SessionId") { $Error.="218-ERR: No session dir\n" } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
253 | else { | ||||||||||||||||||||||||||||||||||||||||||||
254 | 0 | unlink( |
|||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
255 | 0 | $LogReport.=$Error."User $UserEmail logged out."; &store_log; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
256 | 0 | $Session = $SessionId = $Ticket = ''; | |||||||||||||||||||||||||||||||||||||||||||
257 | 0 | return 1; | |||||||||||||||||||||||||||||||||||||||||||
258 | } | ||||||||||||||||||||||||||||||||||||||||||||
259 | |||||||||||||||||||||||||||||||||||||||||||||
260 | # The first parameter can be an userid and email. (diff by @) | ||||||||||||||||||||||||||||||||||||||||||||
261 | sub login { | ||||||||||||||||||||||||||||||||||||||||||||
262 | 0 | 0 | 0 | my $email = shift; my $password = shift; | |||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
263 | 0 | $email = lc $email; my $userid; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
264 | 0 | 0 | if ($email !~ /@/) { $userid=$email; $email=''; } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
265 | 0 | 0 | if ($email ne '') { | ||||||||||||||||||||||||||||||||||||||||||
266 | 0 | 0 | if (!&emailcheckok($email)) { | ||||||||||||||||||||||||||||||||||||||||||
267 | 0 | $Error.="242-ERR:Incorrect email address format"; return; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
268 | #my $u = &get_user_by_email($email); | ||||||||||||||||||||||||||||||||||||||||||||
269 | 0 | my $u = &get_user_unique('email', $email); | |||||||||||||||||||||||||||||||||||||||||||
270 | 0 | 0 | if ($u eq '') { $Error.='245-ERR:Email not registered'; return; } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
271 | 0 | $userid = $u->{userid}; | |||||||||||||||||||||||||||||||||||||||||||
272 | 0 | $User = $u; | |||||||||||||||||||||||||||||||||||||||||||
273 | } else { | ||||||||||||||||||||||||||||||||||||||||||||
274 | 0 | 0 | if ($userid eq '') { $Error.="249-ERR:Empty userid"; return; } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
275 | #my $u = &get_user_by_userid($userid); | ||||||||||||||||||||||||||||||||||||||||||||
276 | 0 | my $u = &get_user_unique('userid', $userid); | |||||||||||||||||||||||||||||||||||||||||||
277 | 0 | 0 | if ($u eq '') { $Error.='252-ERR:Not exist-unique'; return; } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
278 | 0 | $email = $u->{email}; | |||||||||||||||||||||||||||||||||||||||||||
279 | 0 | $User = $u; | |||||||||||||||||||||||||||||||||||||||||||
280 | } | ||||||||||||||||||||||||||||||||||||||||||||
281 | |||||||||||||||||||||||||||||||||||||||||||||
282 | 0 | 0 | if (!password_check($User, $password)) { | ||||||||||||||||||||||||||||||||||||||||||
283 | 0 | $Error.="258:Invalid password\n"; return ''; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
284 | |||||||||||||||||||||||||||||||||||||||||||||
285 | 0 | &set_new_session($User); | |||||||||||||||||||||||||||||||||||||||||||
286 | 0 | $LogReport.="User $UserEmail logged in.\n"; &store_log; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
287 | 0 | return 1; | |||||||||||||||||||||||||||||||||||||||||||
288 | } | ||||||||||||||||||||||||||||||||||||||||||||
289 | |||||||||||||||||||||||||||||||||||||||||||||
290 | sub set_new_session { | ||||||||||||||||||||||||||||||||||||||||||||
291 | 0 | 0 | 0 | my $u = shift; my $email = $u->{email}; | |||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
292 | 0 | 0 | 0 | mkdir('db', 0700) or croak unless -d 'db'; | |||||||||||||||||||||||||||||||||||||||||
293 | 0 | 0 | 0 | mkdir('db/sessions.d', 0700) or croak unless -d 'db/sessions.d'; | |||||||||||||||||||||||||||||||||||||||||
294 | |||||||||||||||||||||||||||||||||||||||||||||
295 | 0 | my $sessionid = $email."______"; $sessionid =~ /.*?(\w).*?(\w).*?(\w).*?(\w).*?(\w).*?(\w)/; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
296 | 0 | $sessionid = $1.$2.$3.$4.$5; $^T =~ /\d{6}$/; $sessionid.= "_$&"; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
297 | 0 | 0 | if (! mkdir("db/sessions.d/$sessionid", 0700)) { | ||||||||||||||||||||||||||||||||||||||||||
298 | 0 | 0 | my $cnt=1; for(;$cnt<100 and !mkdir("db/sessions.d/${sessionid}_$cnt", 0700); ++$cnt) {} | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
299 | 0 | 0 | croak "Cannot create sessions!" if $cnt == 100; | ||||||||||||||||||||||||||||||||||||||||||
300 | 0 | $sessionid = "${sessionid}_$cnt"; | |||||||||||||||||||||||||||||||||||||||||||
301 | } | ||||||||||||||||||||||||||||||||||||||||||||
302 | 0 | $SessionId = $sessionid; $Ticket = &random_name; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
303 | 0 | putfile("db/sessions.d/$SessionId/session.info", | |||||||||||||||||||||||||||||||||||||||||||
304 | "SessionId:$SessionId\nTicket:$Ticket\nemail:$email\n"); | ||||||||||||||||||||||||||||||||||||||||||||
305 | 0 | $UserEmail = $email; | |||||||||||||||||||||||||||||||||||||||||||
306 | 0 | return $SessionId; | |||||||||||||||||||||||||||||||||||||||||||
307 | } | ||||||||||||||||||||||||||||||||||||||||||||
308 | |||||||||||||||||||||||||||||||||||||||||||||
309 | # Return 1 if OK, '' otherwise | ||||||||||||||||||||||||||||||||||||||||||||
310 | sub password_check { | ||||||||||||||||||||||||||||||||||||||||||||
311 | 0 | 0 | 0 | my $u = shift; my $password = shift; my $pwstored = &find_password($u->{email}); | |||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
312 | 0 | 0 | if ($pwstored =~ /^raw:/) { | ||||||||||||||||||||||||||||||||||||||||||
313 | 0 | 0 | $pwstored=$'; return ( ($pwstored eq $password) ? 1 : '' ); } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
314 | 0 | 0 | if ($pwstored =~ /^md5:/) { | ||||||||||||||||||||||||||||||||||||||||||
315 | 0 | 0 | $pwstored=$'; return ( ($pwstored eq md5_base64($password)) ? 1 : ''); } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
316 | 0 | $Error.="316-ERR:PWCheck error($pwstored)\n"; $ErrorInternal="AuthRegister:$Error"; return ''; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
317 | } | ||||||||||||||||||||||||||||||||||||||||||||
318 | |||||||||||||||||||||||||||||||||||||||||||||
319 | sub find_password { | ||||||||||||||||||||||||||||||||||||||||||||
320 | 0 | 0 | 0 | my $email = shift; my $pwfile = "db/passwords"; | |||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
321 | 0 | $email = lc $email; | |||||||||||||||||||||||||||||||||||||||||||
322 | 0 | 0 | if (!-f $pwfile) { putfile $pwfile, ''; chmod 0600, $pwfile } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
323 | 0 | 0 | if (!&lock_mkdir($pwfile)) { $Error.="309-ERR:\n"; return ''; } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
324 | 0 | 0 | local *PH; if (!open(PH,$pwfile)) { | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
325 | 0 | &unlock_mkdir($pwfile); | |||||||||||||||||||||||||||||||||||||||||||
326 | 0 | $Error.="312-ERR: Cannot open ($pwfile):$!\n"; return ''; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
327 | 0 | while ( |
|||||||||||||||||||||||||||||||||||||||||||
328 | 0 | my ($e,$p) = split; $e = lc $e; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
329 | 0 | 0 | if ($e eq $email) { close(PH); &unlock_mkdir($pwfile); return $p; } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
330 | } | ||||||||||||||||||||||||||||||||||||||||||||
331 | 0 | $Error.="NOTFOUND($email)"; | |||||||||||||||||||||||||||||||||||||||||||
332 | 0 | close(PH); &unlock_mkdir($pwfile); return ''; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
333 | } | ||||||||||||||||||||||||||||||||||||||||||||
334 | |||||||||||||||||||||||||||||||||||||||||||||
335 | sub random_name { | ||||||||||||||||||||||||||||||||||||||||||||
336 | 0 | 0 | 0 | 0 | my $n = shift; $n = 8 unless $n > 0; | ||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
337 | 0 | my @chars = (0..9, 'a'..'z', 'A'..'Z'); | |||||||||||||||||||||||||||||||||||||||||||
338 | 0 | return join('', map { $chars[rand($#chars+1)] } (1..$n)); | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
339 | } | ||||||||||||||||||||||||||||||||||||||||||||
340 | |||||||||||||||||||||||||||||||||||||||||||||
341 | sub store_log { | ||||||||||||||||||||||||||||||||||||||||||||
342 | 0 | 0 | 0 | 0 | if($#_>=-1) { $LogReport.=$_[0] } | ||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
343 | 0 | 0 | return if $LogReport eq ''; | ||||||||||||||||||||||||||||||||||||||||||
344 | 0 | 0 | if ($SendLogs) { &send_email_to_admin('Log entry', $LogReport) } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
345 | 0 | $LogReport = ''; | |||||||||||||||||||||||||||||||||||||||||||
346 | } | ||||||||||||||||||||||||||||||||||||||||||||
347 | |||||||||||||||||||||||||||||||||||||||||||||
348 | ######################################################################## | ||||||||||||||||||||||||||||||||||||||||||||
349 | # Email communication | ||||||||||||||||||||||||||||||||||||||||||||
350 | |||||||||||||||||||||||||||||||||||||||||||||
351 | # params: $email, opt: 'raw' or 'md5' to generate passord | ||||||||||||||||||||||||||||||||||||||||||||
352 | sub reset_and_send_email_reminder { | ||||||||||||||||||||||||||||||||||||||||||||
353 | 0 | 0 | 0 | my $email = shift; my $pwstore = shift; | |||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
354 | 0 | $email=lc $email; $email =~ s/\s/ /g; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
355 | 0 | 0 | if ($email eq '') { | ||||||||||||||||||||||||||||||||||||||||||
356 | 0 | $Error.="328-ERR:No e-mail provided to send password\n"; return; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
357 | 0 | 0 | if (!emailcheckok($email)) { | ||||||||||||||||||||||||||||||||||||||||||
358 | 0 | $Error.="330-ERR:Invalid e-mail address provided($email)\n"; return; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
359 | 0 | my $user = get_user_unique('email',$email); | |||||||||||||||||||||||||||||||||||||||||||
360 | 0 | 0 | if ($user eq '') { | ||||||||||||||||||||||||||||||||||||||||||
361 | 0 | $Error.="333-ERR: No user with email ($email)\n"; return; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
362 | 0 | my $pw = &reset_password($email, $pwstore); | |||||||||||||||||||||||||||||||||||||||||||
363 | 0 | &send_email_reminder1($email, $pw); | |||||||||||||||||||||||||||||||||||||||||||
364 | 0 | return 1; | |||||||||||||||||||||||||||||||||||||||||||
365 | } | ||||||||||||||||||||||||||||||||||||||||||||
366 | |||||||||||||||||||||||||||||||||||||||||||||
367 | # params: $email, opt: 'raw' or 'md5' to generate new password if not found | ||||||||||||||||||||||||||||||||||||||||||||
368 | sub send_email_reminder { | ||||||||||||||||||||||||||||||||||||||||||||
369 | 0 | 0 | 0 | my $email = shift; my $pwstore = shift; | |||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
370 | 0 | $email=lc $email; $email =~ s/\s/ /g; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
371 | 0 | 0 | if ($email eq '') { | ||||||||||||||||||||||||||||||||||||||||||
372 | 0 | $Error.="356-ERR:No e-mail provided to send password\n"; return; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
373 | 0 | 0 | if (!emailcheckok($email)) { | ||||||||||||||||||||||||||||||||||||||||||
374 | 0 | $Error.="358-ERR:Invalid e-mail address provided($email)\n"; return; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
375 | 0 | my $user = get_user_by_email($email); | |||||||||||||||||||||||||||||||||||||||||||
376 | 0 | 0 | if ($user eq '') { | ||||||||||||||||||||||||||||||||||||||||||
377 | 0 | $Error.="361-ERR: No user with email ($email)\n"; return; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
378 | 0 | my $pw = find_password($email); | |||||||||||||||||||||||||||||||||||||||||||
379 | 0 | 0 | if ($pw =~ /^raw:/) { $pw = $' } | ||||||||||||||||||||||||||||||||||||||||||
0 | 0 | ||||||||||||||||||||||||||||||||||||||||||||
380 | 0 | elsif ($pw ne '') { $Error.="364-ERR:Cannot retrieve password\n"; return; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
381 | 0 | else { $pw = &reset_password($email, $pwstore) } | |||||||||||||||||||||||||||||||||||||||||||
382 | |||||||||||||||||||||||||||||||||||||||||||||
383 | 0 | &send_email_reminder1($email, $pw); | |||||||||||||||||||||||||||||||||||||||||||
384 | 0 | return 1; | |||||||||||||||||||||||||||||||||||||||||||
385 | } | ||||||||||||||||||||||||||||||||||||||||||||
386 | |||||||||||||||||||||||||||||||||||||||||||||
387 | sub send_email_reminder1 { | ||||||||||||||||||||||||||||||||||||||||||||
388 | 0 | 0 | 0 | my $email = shift; my $pw = shift; | |||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
389 | 0 | my $httpslogin = "https://$ENV{SERVER_NAME}$ENV{SCRIPT_NAME}"; | |||||||||||||||||||||||||||||||||||||||||||
390 | |||||||||||||||||||||||||||||||||||||||||||||
391 | 0 | my $msg = "Hi,\n\nYour email and password for the $SiteId site is:\n\n". | |||||||||||||||||||||||||||||||||||||||||||
392 | "Email: $email\nPassword: $pw\n\n". | ||||||||||||||||||||||||||||||||||||||||||||
393 | "You can log in at:\n\n$httpslogin\n\n\n". | ||||||||||||||||||||||||||||||||||||||||||||
394 | # "$HttpsBaseLink/login.cgi\n\n\n". | ||||||||||||||||||||||||||||||||||||||||||||
395 | "Best regards,\n$SiteId Admin\n"; | ||||||||||||||||||||||||||||||||||||||||||||
396 | 0 | &send_email_to($email, "Subject: $SiteId Password Reminder", $msg); | |||||||||||||||||||||||||||||||||||||||||||
397 | } | ||||||||||||||||||||||||||||||||||||||||||||
398 | |||||||||||||||||||||||||||||||||||||||||||||
399 | sub send_email_to_admin { | ||||||||||||||||||||||||||||||||||||||||||||
400 | 0 | 0 | 0 | my $subject = shift; my $msg1 = shift; | |||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
401 | 0 | $subject =~ s/\s+/ /g; | |||||||||||||||||||||||||||||||||||||||||||
402 | 0 | $subject = "Subject: [$SiteId System Report] $subject"; | |||||||||||||||||||||||||||||||||||||||||||
403 | 0 | 0 | return if $Email_bcc eq ''; | ||||||||||||||||||||||||||||||||||||||||||
404 | 0 | my $msg = ''; | |||||||||||||||||||||||||||||||||||||||||||
405 | 0 | 0 | $msg.="From: $Email_from\n" unless $Email_from eq ''; | ||||||||||||||||||||||||||||||||||||||||||
406 | 0 | $msg.="To: $Email_bcc\n"; | |||||||||||||||||||||||||||||||||||||||||||
407 | 0 | $msg.="$subject\n\n$msg1"; | |||||||||||||||||||||||||||||||||||||||||||
408 | 0 | &_send_email($msg); | |||||||||||||||||||||||||||||||||||||||||||
409 | } | ||||||||||||||||||||||||||||||||||||||||||||
410 | |||||||||||||||||||||||||||||||||||||||||||||
411 | sub send_email_to { | ||||||||||||||||||||||||||||||||||||||||||||
412 | 0 | 0 | 0 | 0 | my $email = shift; croak unless &emailcheckok($email); | ||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
413 | 0 | my $subject = shift; $subject =~ s/[\n\r]/ /g; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
414 | 0 | 0 | if ($subject !~ /^Subject: /) { $subject = "Subject: $subject" } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
415 | 0 | my $msg1 = shift; | |||||||||||||||||||||||||||||||||||||||||||
416 | |||||||||||||||||||||||||||||||||||||||||||||
417 | 0 | my $msg = ''; | |||||||||||||||||||||||||||||||||||||||||||
418 | 0 | 0 | $msg.="From: $Email_from\n" unless $Email_from eq ''; | ||||||||||||||||||||||||||||||||||||||||||
419 | 0 | $msg.="To: $email\n"; | |||||||||||||||||||||||||||||||||||||||||||
420 | 0 | 0 | $msg.="Bcc: $Email_bcc\n" unless $Email_bcc eq ''; | ||||||||||||||||||||||||||||||||||||||||||
421 | 0 | $msg.="$subject\n\n$msg1"; | |||||||||||||||||||||||||||||||||||||||||||
422 | 0 | &_send_email($msg); | |||||||||||||||||||||||||||||||||||||||||||
423 | } | ||||||||||||||||||||||||||||||||||||||||||||
424 | |||||||||||||||||||||||||||||||||||||||||||||
425 | sub _send_email { | ||||||||||||||||||||||||||||||||||||||||||||
426 | 0 | 0 | my $fullmessage = shift; | ||||||||||||||||||||||||||||||||||||||||||
427 | 0 | 0 | if (! -x $Sendmail) { | ||||||||||||||||||||||||||||||||||||||||||
428 | 0 | $Error.="390-ERR:No sendmail ($Sendmail)\n"; return ''; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
429 | 0 | local *S; | |||||||||||||||||||||||||||||||||||||||||||
430 | 0 | 0 | if (!open(S,"|$Sendmail -ti")) { | ||||||||||||||||||||||||||||||||||||||||||
431 | 0 | $Error.="393-ERR:Cannot run sendmail:$!\n"; return ''; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
432 | 0 | print S $fullmessage; close(S); | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
433 | } | ||||||||||||||||||||||||||||||||||||||||||||
434 | |||||||||||||||||||||||||||||||||||||||||||||
435 | ######################################################################## | ||||||||||||||||||||||||||||||||||||||||||||
436 | # Data checks | ||||||||||||||||||||||||||||||||||||||||||||
437 | |||||||||||||||||||||||||||||||||||||||||||||
438 | sub emailcheckok { | ||||||||||||||||||||||||||||||||||||||||||||
439 | 0 | 0 | 0 | my $email = shift; | |||||||||||||||||||||||||||||||||||||||||
440 | 0 | 0 | if ($email =~ /^[a-zA-Z][\w\.+-]*[a-zA-Z0-9+-]@ | ||||||||||||||||||||||||||||||||||||||||||
441 | [a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$/x) | ||||||||||||||||||||||||||||||||||||||||||||
442 | 0 | { return 1 } | |||||||||||||||||||||||||||||||||||||||||||
443 | 0 | return ''; | |||||||||||||||||||||||||||||||||||||||||||
444 | } | ||||||||||||||||||||||||||||||||||||||||||||
445 | |||||||||||||||||||||||||||||||||||||||||||||
446 | sub useridcheckok { | ||||||||||||||||||||||||||||||||||||||||||||
447 | 0 | 0 | 0 | 0 | my $userid = shift; return 1 if $userid=~/^[a-zA-Z0-9-]+$/; return ''; } | ||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
448 | |||||||||||||||||||||||||||||||||||||||||||||
449 | # DB related functions | ||||||||||||||||||||||||||||||||||||||||||||
450 | |||||||||||||||||||||||||||||||||||||||||||||
451 | # Uses file db/users.db. Empty string returned if unsuccessful, with | ||||||||||||||||||||||||||||||||||||||||||||
452 | # error message appended to $Error. | ||||||||||||||||||||||||||||||||||||||||||||
453 | sub get_user_by_email { | ||||||||||||||||||||||||||||||||||||||||||||
454 | 0 | 0 | 0 | my $email = shift; | |||||||||||||||||||||||||||||||||||||||||
455 | 0 | 0 | if (!-f 'db/users.db') | ||||||||||||||||||||||||||||||||||||||||||
456 | 0 | { $Error.= "454-ERR: no file db/users.db\n"; return; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
457 | 0 | my @db = @{ &read_db('file=db/users.db') }; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
458 | 0 | 0 | for my $r (@db) { if (lc($email) eq lc($r->{email})) { return $User=$r } } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
459 | 0 | $Error.="457-ERR: no user with email ($email)\n"; return $User=''; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
460 | } | ||||||||||||||||||||||||||||||||||||||||||||
461 | |||||||||||||||||||||||||||||||||||||||||||||
462 | sub get_user_by_userid { | ||||||||||||||||||||||||||||||||||||||||||||
463 | 0 | 0 | 0 | my $userid = shift; | |||||||||||||||||||||||||||||||||||||||||
464 | 0 | 0 | if (!-f 'db/users.db') | ||||||||||||||||||||||||||||||||||||||||||
465 | 0 | { $Error.= "463-ERR: no file db/users.db\n"; return; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
466 | 0 | my @db = @{ &read_db('file=db/users.db') }; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
467 | 0 | 0 | for my $r (@db) { if ($userid eq $r->{userid}) { return $User=$r } } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
468 | 0 | $Error.="466-ERR: no user with userid ($userid)."; return $User=''; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
469 | } | ||||||||||||||||||||||||||||||||||||||||||||
470 | |||||||||||||||||||||||||||||||||||||||||||||
471 | sub get_user { | ||||||||||||||||||||||||||||||||||||||||||||
472 | 0 | 0 | 0 | my $k = shift; my $v = shift; | |||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
473 | 0 | 0 | if (!-f 'db/users.db') | ||||||||||||||||||||||||||||||||||||||||||
474 | 0 | { $Error.= "472-ERR: no file db/users.db\n"; return; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
475 | 0 | my @db = @{ &read_db('file=db/users.db') }; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
476 | 0 | for my $r (@db) | |||||||||||||||||||||||||||||||||||||||||||
477 | 0 | 0 | 0 | { if (exists($r->{$k}) && $v eq $r->{$k}) { return $User=$r } } | |||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
478 | 0 | $Error.="476-ERR: no user with key=($k) v=($v)."; return $User=''; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
479 | } | ||||||||||||||||||||||||||||||||||||||||||||
480 | |||||||||||||||||||||||||||||||||||||||||||||
481 | # Get user by a key,value, but make sure there is exactly one such user | ||||||||||||||||||||||||||||||||||||||||||||
482 | # Normalizes whitespace and case insensitive | ||||||||||||||||||||||||||||||||||||||||||||
483 | sub get_user_unique { | ||||||||||||||||||||||||||||||||||||||||||||
484 | 0 | 0 | 0 | my $k = shift; my $v = shift; | |||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
485 | 0 | 0 | if (!-f 'db/users.db') | ||||||||||||||||||||||||||||||||||||||||||
486 | 0 | { $Error.= "455-ERR: no file db/users.db\n"; return ''; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
487 | 0 | my @db = @{ &read_db('file=db/users.db') }; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
488 | 0 | $v=~s/^\s+//; $v=~s/\s+$//; $v=~s/\s+/ /g; $v = lc $v; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
489 | 0 | 0 | 0 | if ($k eq '' or $v eq '') | |||||||||||||||||||||||||||||||||||||||||
490 | 0 | { $Error.="461-ERR:Empty k or v ($k:$v)\n"; return ''; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
491 | 0 | my $u = ''; | |||||||||||||||||||||||||||||||||||||||||||
492 | 0 | for my $r (@db) { | |||||||||||||||||||||||||||||||||||||||||||
493 | 0 | 0 | next unless exists($r->{$k}); my $v1 = $r->{$k}; | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
494 | 0 | $v1=~s/^\s+//; $v1=~s/\s+$//; $v1=~s/\s+/ /g; $v1 = lc $v1; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
495 | 0 | 0 | next unless $v eq $v1; | ||||||||||||||||||||||||||||||||||||||||||
496 | 0 | 0 | if ($u eq '') { $u = $r; next; } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
497 | 0 | $Error.= "467-ERR: double user key ($k:$v)\n"; return ''; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
498 | } | ||||||||||||||||||||||||||||||||||||||||||||
499 | 0 | 0 | return $User=$u unless $u eq ''; | ||||||||||||||||||||||||||||||||||||||||||
500 | 0 | $Error.="470-ERR: no user with key ($k:$v)\n"; return ''; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
501 | } | ||||||||||||||||||||||||||||||||||||||||||||
502 | |||||||||||||||||||||||||||||||||||||||||||||
503 | # Read DB records in the RFC822-like style (to add reference). | ||||||||||||||||||||||||||||||||||||||||||||
504 | sub read_db { | ||||||||||||||||||||||||||||||||||||||||||||
505 | 0 | 0 | 0 | my $arg = shift; | |||||||||||||||||||||||||||||||||||||||||
506 | 0 | 0 | if ($arg =~ /^file=/) { | ||||||||||||||||||||||||||||||||||||||||||
507 | 0 | 0 | my $f = $'; if (!&lock_mkdir($f)) { return '' } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
508 | 0 | 0 | local *F; open(F, $f) or die "cannot open $f:$!"; | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
509 | 0 | $arg = join('', |
|||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
510 | } | ||||||||||||||||||||||||||||||||||||||||||||
511 | |||||||||||||||||||||||||||||||||||||||||||||
512 | 0 | my $db = []; | |||||||||||||||||||||||||||||||||||||||||||
513 | 0 | while ($arg) { | |||||||||||||||||||||||||||||||||||||||||||
514 | 0 | $arg =~ s/^\s*(#.*\s*)*//; # allow comments betwen records | |||||||||||||||||||||||||||||||||||||||||||
515 | 0 | my $record; | |||||||||||||||||||||||||||||||||||||||||||
516 | 0 | 0 | if ($arg =~ /\n\n+/) { $record = "$`\n"; $arg = $'; } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
517 | 0 | else { $record = $arg; $arg = ''; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
518 | 0 | my $r = {}; | |||||||||||||||||||||||||||||||||||||||||||
519 | 0 | while ($record) { | |||||||||||||||||||||||||||||||||||||||||||
520 | 0 | while ($record =~ /^(.*)(\\\n|\n[ \t]+)(.*)/) | |||||||||||||||||||||||||||||||||||||||||||
521 | 0 | { $record = "$1 $3$'" } | |||||||||||||||||||||||||||||||||||||||||||
522 | 0 | 0 | $record =~ /^([^\n:]*):(.*)\n/ or die; | ||||||||||||||||||||||||||||||||||||||||||
523 | 0 | my $k = $1; my $v = $2; $record = $'; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
524 | 0 | 0 | if (exists($r->{$k})) { | ||||||||||||||||||||||||||||||||||||||||||
525 | 0 | my $c = 0; | |||||||||||||||||||||||||||||||||||||||||||
526 | 0 | while (exists($r->{"$k-$c"})) { ++$c } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
527 | 0 | $k = "$k-$c"; | |||||||||||||||||||||||||||||||||||||||||||
528 | } | ||||||||||||||||||||||||||||||||||||||||||||
529 | 0 | $r->{$k} = $v; | |||||||||||||||||||||||||||||||||||||||||||
530 | } | ||||||||||||||||||||||||||||||||||||||||||||
531 | 0 | push @{ $db }, $r; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
532 | } | ||||||||||||||||||||||||||||||||||||||||||||
533 | 0 | return $db; | |||||||||||||||||||||||||||||||||||||||||||
534 | } | ||||||||||||||||||||||||||||||||||||||||||||
535 | |||||||||||||||||||||||||||||||||||||||||||||
536 | # Read one DB record in the RFC822-like style (to add reference). | ||||||||||||||||||||||||||||||||||||||||||||
537 | sub read_db_record { | ||||||||||||||||||||||||||||||||||||||||||||
538 | 0 | 0 | 0 | my $arg = shift; | |||||||||||||||||||||||||||||||||||||||||
539 | 0 | 0 | if ($arg =~ /^file=/) { | ||||||||||||||||||||||||||||||||||||||||||
540 | 0 | 0 | my $f = $'; local *F; open(F, $f) or die "cannot open $f:$!"; | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
541 | 0 | $arg = join('', |
|||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
542 | } | ||||||||||||||||||||||||||||||||||||||||||||
543 | |||||||||||||||||||||||||||||||||||||||||||||
544 | 0 | while ($arg =~ s/^(\s*|\s*#.*)\n//) {} # allow comments before record | |||||||||||||||||||||||||||||||||||||||||||
545 | 0 | my $record; | |||||||||||||||||||||||||||||||||||||||||||
546 | 0 | 0 | if ($arg =~ /\n\n+/) { $record = "$`\n"; $arg = $'; } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
547 | 0 | else { $record = $arg; $arg = ''; } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
548 | 0 | my $r = {}; | |||||||||||||||||||||||||||||||||||||||||||
549 | 0 | while ($record) { | |||||||||||||||||||||||||||||||||||||||||||
550 | 0 | while ($record =~ /^(.*)(\\\n|\n[ \t]+)(.*)/) | |||||||||||||||||||||||||||||||||||||||||||
551 | 0 | { $record = "$1 $3$'" } | |||||||||||||||||||||||||||||||||||||||||||
552 | 0 | 0 | $record =~ /^([^\n:]*):(.*)\n/ or die; | ||||||||||||||||||||||||||||||||||||||||||
553 | 0 | my $k = $1; my $v = $2; $record = $'; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
554 | 0 | 0 | if (exists($r->{$k})) { | ||||||||||||||||||||||||||||||||||||||||||
555 | 0 | my $c = 0; | |||||||||||||||||||||||||||||||||||||||||||
556 | 0 | while (exists($r->{"$k-$c"})) { ++$c } | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
557 | 0 | $k = "$k-$c"; | |||||||||||||||||||||||||||||||||||||||||||
558 | } | ||||||||||||||||||||||||||||||||||||||||||||
559 | 0 | $r->{$k} = $v; | |||||||||||||||||||||||||||||||||||||||||||
560 | } | ||||||||||||||||||||||||||||||||||||||||||||
561 | 0 | return $r; | |||||||||||||||||||||||||||||||||||||||||||
562 | } | ||||||||||||||||||||||||||||||||||||||||||||
563 | |||||||||||||||||||||||||||||||||||||||||||||
564 | sub putfile($@) { | ||||||||||||||||||||||||||||||||||||||||||||
565 | 0 | 0 | 0 | my $f = shift; local *F; | |||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
566 | 0 | 0 | if (!open(F, ">$f")) { $Error.="325-ERR:Cannot write ($f):$!\n"; return; } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
567 | 0 | for (@_) { print F } close(F); | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
568 | } | ||||||||||||||||||||||||||||||||||||||||||||
569 | |||||||||||||||||||||||||||||||||||||||||||||
570 | ######################################################################## | ||||||||||||||||||||||||||||||||||||||||||||
571 | # Simple file locking using mkdir | ||||||||||||||||||||||||||||||||||||||||||||
572 | |||||||||||||||||||||||||||||||||||||||||||||
573 | # Exlusive locking using mkdir | ||||||||||||||||||||||||||||||||||||||||||||
574 | # lock_mkdir($fname); # return 1=success ''=fail | ||||||||||||||||||||||||||||||||||||||||||||
575 | sub lock_mkdir { | ||||||||||||||||||||||||||||||||||||||||||||
576 | 0 | 0 | 0 | my $fname = shift; my $lockd = "$fname.lock"; my $locked; | |||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
577 | # First, hopefully most usual case | ||||||||||||||||||||||||||||||||||||||||||||
578 | 0 | 0 | 0 | if (!-e $lockd && ($locked = mkdir($lockd,0700))) { return $locked } | |||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
579 | 0 | my $tryfor=10; #sec | |||||||||||||||||||||||||||||||||||||||||||
580 | 0 | $locked = ''; # flag | |||||||||||||||||||||||||||||||||||||||||||
581 | 0 | for (my $i=0; $i<2*$tryfor; ++$i) { | |||||||||||||||||||||||||||||||||||||||||||
582 | 0 | select(undef,undef,undef,0.5); # wait for 0.5 sec | |||||||||||||||||||||||||||||||||||||||||||
583 | 0 | 0 | !-e $lockd && ($locked = mkdir($lockd,0700)); | ||||||||||||||||||||||||||||||||||||||||||
584 | 0 | 0 | if ($locked) { return $locked } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
585 | } | ||||||||||||||||||||||||||||||||||||||||||||
586 | 0 | $Error.="393-ERR:Could not lock file ($fname)\n"; return $locked; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
587 | } | ||||||||||||||||||||||||||||||||||||||||||||
588 | |||||||||||||||||||||||||||||||||||||||||||||
589 | # Unlock using mkdir | ||||||||||||||||||||||||||||||||||||||||||||
590 | # unlock_mkdir($fname); # return 1=success ''=fail or no lock | ||||||||||||||||||||||||||||||||||||||||||||
591 | sub unlock_mkdir { | ||||||||||||||||||||||||||||||||||||||||||||
592 | 0 | 0 | 0 | my $fname = shift; my $lockd = "$fname.lock"; | |||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
593 | 0 | 0 | if (!-e $lockd) { $Error.="400-ERR:No lock on ($fname)\n"; return '' } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
594 | 0 | 0 | if (-d $lockd) { return rmdir($lockd) } | ||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
595 | 0 | 0 | 0 | if (-f $lockd or -l $lockd) { unlink($lockd) } | |||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
596 | 0 | $Error.="403-ERR:Unknown error"; return ''; | |||||||||||||||||||||||||||||||||||||||||||
0 | |||||||||||||||||||||||||||||||||||||||||||||
597 | } | ||||||||||||||||||||||||||||||||||||||||||||
598 | |||||||||||||||||||||||||||||||||||||||||||||
599 | 1; | ||||||||||||||||||||||||||||||||||||||||||||
600 | |||||||||||||||||||||||||||||||||||||||||||||
601 | __END__ |