| 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__ |