File Coverage

blib/lib/Linux/usermod.pm
Criterion Covered Total %
statement 210 431 48.7
branch 78 244 31.9
condition 13 72 18.0
subroutine 15 26 57.6
pod 12 14 85.7
total 328 787 41.6


line stmt bran cond sub pod time code
1             package Linux::usermod;
2              
3 1     1   7474 use strict;
  1         3  
  1         35  
4 1     1   5 use Carp;
  1         2  
  1         85  
5 1     1   5 use Fcntl ':flock';
  1         5  
  1         139  
6 1     1   11 use vars qw($VERSION);
  1         1  
  1         2573  
7             $VERSION = 0.69;
8              
9             our $file_passwd = '/etc/passwd';
10             our $file_shadow = '/etc/shadow';
11             our $file_group = '/etc/group';
12             our $file_gshadow = '/etc/gshadow';
13              
14             my %field = (
15             NAME => 0, #The user's name
16             PPASSWORD=> 1, #The "passwd" file password
17             UID => 2, #The user's id
18             GID => 3, #The user's group id
19             COMMENT => 4, #The comment about the user
20             HOME => 5, #The user's home directory
21             SHELL => 6, #The user's shell
22             SNAME => 7, #The user's name in shadow file
23             PASSWORD => 8, #The 13-character encrypted password
24             LASTCHG => 9, #The number of days since January 1, 1970 of the last password changed date
25             MIN => 10, #The minimum number of days required between password changes
26             MAX => 11, #The maximum number of days the password is valid
27             WARN => 12, #The number of days before expiring the password that the user is warned
28             INACTIVE => 13, #The number of days of inactivity allowed for the user
29             EXPIRE => 14, #The number of days since January 1, 1970 that account is disabled
30             FLAG => 15 #Currently not used.
31             );
32              
33             my %gfield = (
34             NAME => 0, #The group name
35             PPASSWORD=> 1, #The group password
36             GID => 2, #The group id number
37             USERS => 3, #The group members (users)
38             SNAME => 4, #The group name in gshadow file
39             PASSWORD => 5, #The encrypted ggroup password
40             GA => 6, #The group administrators
41             GU => 7 #The group members (users)
42             );
43              
44 0     0 0 0 sub fields { keys %field }
45              
46 0     0 0 0 sub gfields { keys %gfield }
47              
48             sub new {
49 2     2 1 15 my $class = shift;
50 2         5 my $user = shift;
51 2         5 my $flag = shift;
52 2         2 my @args;
53 2 100       8 if ($flag){
54 1 50       3 croak "no such group" unless _exists($user, $flag);
55 1         4 @args = _read_grp($user);
56 1         3 push @args, '__G__';
57             }else{
58 1 50       4 croak "no such user" unless _exists($user, $flag);
59 1         5 @args = _read_user($user);
60 1         4 push @args, '__U__';
61             }
62 2   33     25 return bless [ @args ], ref($class)||$class;
63             }
64              
65             sub get {
66 9     9 1 75 my $self = shift;
67 9         13 my $what = shift;
68 9         10 my $key;
69 9 100       32 if($self->[-1] eq '__U__'){
    50          
70 6 50       16 if($what =~ /^\d{1,2}$/){
71 0         0 while(my($k, $v) = each %field){
72 0 0       0 $v == $what and $key = $k
73             }
74 0         0 return $self->[$field{$key}]
75             }
76 6         7 $what = uc $what;
77 6         25 return $self->[$field{$what}]
78             }
79             elsif($self->[-1] eq '__G__'){
80 3 50       11 if($what =~ /^\d{1,2}$/){
81 0         0 while(my($k, $v) = each %gfield){
82 0 0       0 $v == $what and $key = $k
83             }
84 0         0 return $self->[$gfield{$key}]
85             }
86 3         5 $what = uc $what;
87 3         14 return $self->[$gfield{$what}]
88             }
89             }
90              
91             sub set {
92 1     1 1 9 my $self = shift;
93 1         2 my $what = shift;
94 1         3 my $newval = shift;
95 1         11 $what = uc $what;
96 1 50 33     12 return 0 unless exists($field{$what}) or exists($gfield{$what});
97 1 0 0     10 return 0 if $newval =~ /:/ and ($field{$what} != 8 or $gfield{$what} != 4);
      33        
98 1 50       5 $newval = '' if $newval =~ /^undef$/i;
99 1 50       12 if($self->[-1] eq '__U__'){
    50          
100 0   0     0 my $flag = shift || 0;
101 0         0 my $oldval = $self->[$field{$what}];
102 0         0 my $name = $self->[$field{NAME}];
103 0         0 _clean($name);
104 0         0 $self->[$field{$what}] = $newval;
105 0 0       0 if($field{$what} <= 6){
106 0         0 my @file = _io("$file_passwd", '', 'r');
107 0         0 my @user;
108 0         0 push @user, $self->[$_] for 0..6;
109 0         0 my $user = join ':', @user;
110 0 0       0 for(@file){ s/.+/$user/ if /^\Q$name\E:/ }
  0         0  
111 0         0 _io("$file_passwd", \@file, 'w');
112 0 0       0 if($field{$what} == 0){
113 0 0       0 croak "invalid name" if $newval !~ /^([A-Z]|[a-z]){1}\w{0,254}/;
114 0         0 my %names;
115 0         0 @file = @user = ();
116 0         0 @file = _io("$file_shadow", '', 'r');
117 0 0       0 map{ /^(.[^:]+):/ and $names{$1} = 1 }@file;
  0         0  
118 0 0       0 croak "user name $newval already exists" if defined($names{$newval});
119 0         0 undef %names;
120 0         0 push @user, $self->[$_] for 8..14;
121 0         0 unshift @user, $self->[0];
122 0         0 $user = join ':', @user;
123 0 0       0 for(@file){ s/.+/$user/ if /^\Q$name\E:/ }
  0         0  
124 0 0       0 _io("$file_shadow", \@file, 'w') and return 1
125             }
126            
127             }
128 0 0       0 if($field{$what} > 6){
129 0         0 my @file = _io("$file_shadow", '', 'r');
130 0 0       0 $self->[9] = _get_1970_diff() if $field{$what} == 8;
131 0 0 0     0 if($field{$what} == 8 && $newval){
132 0 0       0 $oldval =~ /^!/ and my $lock = 1;
133 0 0       0 $self->[8] = _gen_pass($self->[$field{$what}], $lock) unless $flag;
134             }
135 0         0 my @user;
136 0         0 push @user, "$self->[$_]" for 7..15;
137 0         0 my $user = join ':', @user;
138 0 0       0 for(@file){ s/.+/$user/ if /^\Q$name\E:/ }
  0         0  
139 0         0 _io("$file_shadow", \@file, 'w');
140 0 0       0 if($field{$what} == 7){
141 0         0 @file = @user = ();
142 0         0 @file = _io("$file_passwd", '', 'r');
143 0         0 push @user, $self->[$_] for 1..6;
144 0         0 unshift @user, $self->[7];
145 0         0 $user = join ':', @user;
146 0 0       0 for(@file){ s/.+/$user/ if /^\Q$name\E:/ }
  0         0  
147 0 0       0 _io("$file_passwd", \@file, 'w') and return 1
148             }
149             }
150             }
151             elsif($self->[-1] eq '__G__'){
152 1         4 my $name = $self->[$gfield{NAME}];
153 1         3 my $oldval = $self->[$gfield{$what}];
154 1         4 $self->[$gfield{$what}] = $newval;
155 1 50 33     7 if($gfield{$what} == 0 or $gfield{$what} == 4){
156 0 0       0 croak "invalid name" if $newval !~ /^([A-Z]|[a-z]){1}\w{0,254}/;
157 0         0 my @file = _io($file_group, '', 'r');
158 0         0 my %names;
159 0 0       0 map{ m#^(.[^:]+):# and $names{$1} }@file;
  0         0  
160 0 0       0 croak "group name $newval already exists" if exists($names{$newval});
161 0         0 undef %names;
162 0         0 for(@file){
163 0 0       0 /^$oldval:/ or next;
164 0         0 my $newline = "$self->[0]:$self->[1]:$self->[2]:$self->[3]";
165 0         0 s/.+/$newline/;
166             }
167 0         0 _io($file_group, \@file, 'w');
168 0         0 @file = _io($file_gshadow, '', 'r');
169 0         0 for(@file){
170 0 0       0 /^$oldval:/ or next;
171 0         0 $self->[4] = $newval;
172 0         0 my $newline = "$self->[4]:$self->[5]:$self->[6]:$self->[7]";
173 0         0 s/.+/$newline/;
174             }
175 0 0       0 _io($file_gshadow, \@file, 'w') and return 1
176             }
177 1 50 33     8 if($gfield{$what} == 3 or $gfield{$what} == 7){
178 0         0 for(split /\s+/, $newval){
179 0 0       0 croak "$_ does not exist" unless(_exists($_))
180             }
181 0         0 my $users = join ',', split /\s+/, "$newval";
182 0         0 $self->[3] = $users;
183 0         0 my @file = _io($file_group, '', 'r');
184 0         0 for(@file){
185 0 0       0 /^\Q$name\E:/ or next;
186 0         0 my $newline = "$self->[0]:$self->[1]:$self->[2]:$self->[3]";
187 0         0 s/.+/$newline/;
188             }
189 0         0 _io($file_group, \@file, 'w');
190 0         0 @file = _io($file_gshadow, '', 'r');
191 0         0 $self->[7] = $users;
192 0         0 for(@file){
193 0 0       0 /^\Q$name\E:/ or next;
194 0         0 my $newline = "$self->[4]:$self->[5]:$self->[6]:$self->[3]";
195 0         0 s/.+/$newline/;
196             }
197 0 0       0 _io($file_gshadow, \@file, 'w') and return 1
198             }
199 1 50       6 if($gfield{$what} == 2){
200 0 0 0     0 croak "wrong group id" if $newval < 1 or $newval > 65535;
201 0         0 my %ids;
202 0         0 my @file = _io("$file_group", '', 'r');
203 0 0       0 map { /^.+?:.*?:(.+):/ and $ids{$1} = 1 } @file;
  0         0  
204 0 0       0 croak "group id $newval already exists" if $ids{$newval};
205 0         0 for(@file){
206 0 0       0 /^\Q$name\E:/ or next;
207 0         0 my $newline = "$self->[0]:$self->[1]:$self->[2]:$self->[3]";
208 0         0 s/.+/$newline/;
209             }
210 0 0       0 _io($file_group, \@file, 'w') and return 1
211             }
212 1 50       4 if($gfield{$what} == 6){
213 1 50       2 croak "user $newval does not exist" unless(_exists($newval));
214 1         2 $self->[6] = $newval;
215 1         3 my @file = _io($file_gshadow, '', 'r');
216 1         3 for(@file){
217 1 50       35 /^\Q$name\E:/ or next;
218 1         6 my $newline = "$self->[4]:$self->[5]:$self->[6]:$self->[7]";
219 1         6 s/.+/$newline/;
220             }
221 1 50       5 _io($file_gshadow, \@file, 'w') and return 1
222             }
223 0 0 0     0 if($gfield{$what} == 1 or $gfield{$what} == 5){
224 1     1   15 no strict 'refs';
  1         1  
  1         3799  
225 0         0 my $salt = join '', ('a'..'z', 'A'..'Z', 0..9)[rand 26,rand 26,rand 26];
226 0         0 my $newpass;
227 0 0       0 if($newval)
228 0         0 { $newpass = crypt($newval, $salt) }
229             else
230 0         0 { $newpass = '!' }
231 0         0 my @file = _io($file_gshadow, '', 'r');
232 0         0 $self->[1] = 'x';
233 0         0 $self->[5] = $newpass;
234 0         0 for(@file){
235 0 0       0 /^\Q$name\E:/ or next;
236 0         0 my $newline = "$self->[4]:$self->[5]:$self->[6]:$self->[7]";
237 0         0 s/.+/$newline/;
238             }
239 0         0 _io($file_gshadow, \@file, 'w');
240 0         0 @file = _io($file_group, '', 'r');
241 0         0 for(@file){
242 0 0       0 /^\Q$name\E:/ or next;
243 0         0 my $newline = "$self->[0]:$self->[1]:$self->[2]:$self->[3]";
244 0         0 s/.+/$newline/;
245             }
246 0 0       0 _io($file_group, \@file, 'w') and return 1
247             }
248             }
249 0         0 return 0
250             }
251              
252             sub _read_user {
253 1     1   2 my $username = shift;
254 1         2 my (@user, @tmp, @file);
255 1         4 @file = _io($file_passwd, '', 'r');
256 1         3 for(@file){
257 1 50       14 /^\Q$username\E:/ or next;
258 1         2 my $user = $_;
259 1         3 for(1..7){
260 7         98 $user =~ m#(.[^:]*){$_}#;
261 7         15 my $ss = $1;
262 7         20 $ss =~ s/(^:*|:*$)//;
263 7         20 $tmp[$_ - 1] = $ss;
264             } last
265 1         3 }
266 1         5 @user = @tmp;
267 1         3 @tmp = ();
268 1         4 @file = _io($file_shadow, '', 'r');
269 1         4 for(@file){
270 1 50       14 /^\Q$username\E:/ or next;
271 1         2 my $user = $_;
272 1         3 for(1..9){
273 9         123 $user =~ m#(.[^:]*){$_}#;
274 9         15 my $ss = $1;
275 9         23 $ss =~ s/(^:*|:*$)//;
276 9         20 $tmp[$_ - 1] = $ss;
277             } last
278 1         2 }
279 1         7 @user = (@user, @tmp);
280 1         9 return (@user);
281             }
282              
283             sub _gen_pass {
284 0     0   0 my $password = shift;
285 0         0 my $flag = shift;
286 0 0       0 $password or croak "no password given";
287 0         0 my @rands = ( "A" .. "Z", "a" .. "z", 0 .. 9 );
288 0         0 my $salt = join("", @rands[ map { rand @rands } ( 1 .. 8 ) ]);
  0         0  
289 0 0       0 $password = ($flag)?'!'.crypt($password, q($1$)."$salt"):crypt($password, q($1$)."$salt");
290 0         0 return $password
291             }
292              
293             sub _exists {
294 4     4   8 my $name = shift;
295 4         4 my $gflag = shift;
296 4 100       11 my $file = ($gflag) ? "$file_group" : "$file_passwd";
297 4         12 my @file = _io("$file", '', 'r');
298 4         6 my $flag;
299 4   50     58 /^\Q$name\E:/ and $flag = 1 for @file;
300 4 100       21 return $flag ? 1 : 0
301             }
302              
303             sub add {
304 1     1 1 418 my $class = shift;
305 1         2 my (%fields, $c, @args);
306 1         10 push @args, $_ for @_;
307 1 50       6 croak "no username given" if scalar @args == 0;
308 1 50       5 croak "user $args[0] exists" if _exists($args[0]);
309 1         3 for(@args){
310 7         15 chomp($_);
311 7 100 66     36 /^\s*$/ and $c++ and next;
312 6         7 $c++;
313 6 100       10 if($c == 1){
314 1 50       6 croak "wrong username given" if /:/;
315 1 50       554 croak "wrong username" unless /^([A-Z]|[a-z]){1}\w{0,254}/;
316 1   33     6 $fields{username} = $_ || croak "no username given";
317             }
318 6 50       13 if($c == 2){
319 0 0       0 croak "wrong password length" unless /^(.*){0,254}$/;
320 0 0       0 $fields{password} = _gen_pass($_) if $_;
321             }
322 6 100       13 if($c == 3){
323 1 50       4 $_ eq '' and $_ = 1000;
324 1 50       7 croak "wrong uid" unless /^\d+$/;
325 1 50 33     8 croak "wrong uid" if $_ > 65535 or $_ < 1;
326 1   50     6 $fields{uid} = $_ || 1000;
327             }
328 6 100       12 if($c == 4){
329 1 50       4 $_ eq '' and $_ = 1000;
330 1 50       6 croak "wrong gid" unless /^\d+$/;
331 1 50 33     6 if(/^\d+$/){ croak "wrong gid" if $_ > 65535 or $_ < 1 }
  1 50       19  
332 1   33     5 $fields{gid} = $_ || $fields{uid};
333             }
334 6 100       13 if($c == 5){
335 1 50       13 croak "wrong comment given" if /:/;
336 1         3 $fields{comment} = $_;
337             }
338 6 100       11 if($c == 6){
339 1 50       4 croak "wrong home given" if /:/;
340 1         3 $fields{home} = $_;
341             }
342 6 100       13 if($c == 7){
343 1 50       5 croak " wrong shell given" if /:/;
344 1         4 $fields{shell} = $_;
345             }
346             }
347 1 50       4 $fields{password} or $fields{password} = '!';
348 1         5 my @file = _io("$file_passwd", '', 'r');
349 1         2 my @ids;
350 1         2 push @ids, (split /:/)[2] for @file;
351 1         3 for (@ids){
352 0 0       0 if ($fields{uid} == $_){
353 0         0 $fields{uid} = 1000;
354             last
355 0         0 }
356             }
357 1 50       4 if($fields{uid} == 1000){
358 0         0 for(sort @ids){
359 0 0       0 $_ < 1000 and next;
360 0 0       0 $fields{uid} == $_ and $fields{uid}++;
361             }
362             }
363 1 50       4 $fields{gid} = $fields{uid} if !$fields{gid};
364 1         7 my @newuser = ("$fields{username}:x:$fields{uid}:$fields{gid}:$fields{comment}:$fields{home}:$fields{shell}");
365 1         4 _io("$file_passwd", \@newuser, 'a');
366 1         4 my $time_1970 = _get_1970_diff();
367 1         5 @newuser = ("$fields{username}:$fields{password}:$time_1970:0:99999:7:::");
368 1         3 _io("$file_shadow", \@newuser, 'a');
369 1         4 return 1
370             }
371              
372             sub grpadd {
373 1     1 1 9 my $class = shift;
374 1 50       4 my $group = shift or croak "empty group name";
375 1         1 my $gid = shift;
376 1         2 my $users = shift;
377 1         1 my (@tmp, %file, @newgroup);
378 1         4 my @file = _io("$file_group", '', 'r');
379 1 50       6 croak "wrong group name" unless $group =~ /^([A-Z]|[a-z]){1}\w{0,254}/;
380 1 0       2 map { @tmp = split /:/, $_ and $file{$tmp[0]} = $tmp[2] } @file;
  0         0  
381 1 50       4 exists($file{$group}) and croak "group $group already exists";
382 1 50       4 if(!$gid){
383 0         0 $gid = 100;
384 0         0 for(sort {$a <=> $b} values %file){
  0         0  
385 0 0       0 next if $_ < 100;
386 0 0       0 $gid == $_ and $gid++
387             }
388             }
389 1         4 my $userlist = join(',', split(/\s+/, $users));
390 1         4 @newgroup = ("$group:x:$gid:$userlist");
391 1         4 _io("$file_group", \@newgroup, 'a');
392 1         3 @newgroup = ("$group:!!::$userlist");
393 1         3 _io("$file_gshadow", \@newgroup, 'a');
394             }
395              
396             sub del {
397 0     0 1 0 my $class = shift;
398 0         0 my $username = shift;
399 0 0       0 _exists($username) or croak "user $username does not exist";
400 0         0 my @old = _io("$file_passwd", '', 'r');
401 0         0 my @new;
402 0   0     0 /^\Q$username\E:/ or push @new, $_ for @old;
403 0         0 _io("$file_passwd", \@new, 'w');
404 0         0 @new = ();
405 0         0 @old = _io("$file_shadow", '', 'r');
406 0   0     0 /^\Q$username\E:/ or push @new, $_ for @old;
407 0         0 _io("$file_shadow", \@new, 'w');
408 0         0 return 1
409             }
410              
411             sub grpdel {
412 0     0 1 0 my $class = shift;
413 0 0       0 my $group = shift or croak "empty group name/gid";
414 0         0 my (@tmp, %file);
415 0         0 my @file = _io("$file_group", '', 'r');
416 0 0       0 map { @tmp = split /:/, $_ and $file{$tmp[0]} = $tmp[2] } @file;
  0         0  
417 0 0       0 exists($file{$group}) or croak "group $group does not exists";
418 0         0 @tmp = ();
419 0   0     0 /^$group/ or push @tmp, $_ for @file;
420 0         0 _io("$file_group", \@tmp, 'w');
421 0         0 @file = _io("$file_gshadow", '', 'r');
422 0         0 @tmp = ();
423 0   0     0 /^$group/ or push @tmp, $_ for @file;
424 0         0 _io("$file_gshadow", \@tmp, 'w');
425            
426             }
427              
428             sub _read_grp {
429 1 50   1   3 my $group = shift or croak "empty group name/gid";
430 1         2 my (@tmp, @grp);
431 1         6 my @file = _io("$file_group", '', 'r');
432 1         4 for(@file){
433 1 50       23 /^$group:/ or next;
434 1         4 my $user = $_;
435 1         4 for(1..4){
436 4         153 $user =~ /(.[^:]*){$_}/;
437 4         13 my $ss = $1;
438 4         15 $ss =~ s/(^:*|:*$)//;
439 4         20 $tmp[$_ - 1] = $ss;
440             } last
441 1         3 }
442 1         4 @grp = @tmp;
443 1         4 @file = _io("$file_gshadow", '', 'r');
444 1         3 for(@file){
445 1 50       16 /^$group:/ or next;
446 1         3 my $user = $_;
447 1         3 for(1..4){
448 4         698 $user =~ /(.[^:]*){$_}/;
449 4         11 my $ss = $1;
450 4         17 $ss =~ s/(^:*|:*$)//;
451 4         13 $tmp[$_ - 1] = $ss;
452             } last
453 1         3 }
454 1         7 @grp = (@grp, @tmp);
455 1         9 return (@grp)
456             }
457              
458             sub tobsd{
459 0     0 1 0 my $self = shift;
460 0         0 (my @file) = _io("$file_shadow", '', 'r');
461 0         0 my $name = $self->get('name');
462 0         0 my @user;
463 0         0 for(@file){
464 0 0       0 /^\Q$name\E:/ or next;
465 0         0 push @user, $name, ':';
466 0         0 push @user, $self->get('password'), ':';
467 0         0 push @user, $self->get('uid'), ':';
468 0         0 push @user, $self->get('gid'), ':';
469 0         0 push @user, ':';
470 0   0     0 push @user, $self->get('expire') || 0, ':';
471 0   0     0 push @user, $self->get('expire') || 0, ':';
472 0         0 push @user, $self->get('comment'), ':';
473 0         0 push @user, $self->get('home'), ':';
474 0         0 push @user, $self->get('shell');
475 0         0 my $user = join '', @user;
476 0         0 s/.*/$user/;
477             }
478 0         0 _io("$file_shadow", \@file, 'w');
479 0         0 return 1
480             }
481              
482             sub _io{
483 16     16   21 my $file = shift;
484 16         18 my $newvals = shift;
485 16         19 my $flag = shift;
486 16         19 my @file;
487 16 50       223 croak $! unless -f $file;
488 16         36 local *FH;
489 16 50       59 die "posible flags: r/w/a" unless $flag =~ /^(r|w|a)$/;
490 16 100       37 if($flag eq 'r'){
491 11 50       468 open FH, $file or croak "can't open_r $file $!";
492 11 50       79 flock FH, LOCK_SH or croak "can't lock_sh $file";
493 11         217 @file = ;
494 11         116 close FH;
495 11         21 map { s/\n// } @file;
  8         32  
496 11         47 return @file;
497             }
498 5 100       12 if($flag eq 'w'){
499 1 50       98 open FH, "> $file" or croak "can't open_w $file $!";
500 1 50       9 flock FH, LOCK_EX or croak "can't lock_ex $file";
501 1         2 print FH "$_\n" for @{$newvals};
  1         18  
502 1         33 close FH;
503 1         7 return 1
504             }
505 4 50       8 if($flag eq 'a'){
506 4 50       126 open FH, ">> $file" or croak "can't open_a $file $!";
507 4 50       27 flock FH, LOCK_EX or croak "can't lock_ex $file";
508 4         4 print FH "$_\n" for @{$newvals};
  4         43  
509 4         220 close FH;
510 4         14 return 1
511             }
512             }
513            
514             sub users{
515 0     0 1 0 my $class = shift;
516 0         0 (my @file) = _io("$file_passwd", '', 'r');
517 0         0 my (%users, @users);
518 0   0     0 m#^(.[^:]+):# and push @users, $1 for @file;
519 0         0 map{ $users{$_} = 1 }@users;
  0         0  
520 0         0 return %users
521             }
522              
523             sub grps{
524 0     0 1 0 my $class = shift;
525 0         0 (my @file) = _io("$file_group", '', 'r');
526 0         0 my (%users, @users);
527 0   0     0 m#^(.[^:]+):# and push @users, $1 for @file;
528 0         0 map{ $users{$_} = 1 }@users;
  0         0  
529 0         0 return %users
530             }
531            
532             sub lock{
533 0     0 1 0 my $self = shift;
534 0         0 my $password = $self->get("password");
535 0 0       0 return 1 if $password =~ /^\!/;
536 0         0 $password =~ s/(.*)/!$1/;
537 0         0 $self->set("password", $password, 1);
538             }
539              
540             sub unlock{
541 0     0 1 0 my $self = shift;
542 0         0 my $password = $self->get("password");
543 0 0       0 return if $password !~ /^\!/;
544 0         0 $password =~ s/^\!//;
545 0   0     0 $password ||= 'undef';
546 0         0 $self->set("password", $password, 1);
547             }
548              
549 1     1   9 sub _get_1970_diff{ return int time / (3600 * 24) }
550              
551             sub _clean{
552 0     0     my $specchars = \shift;
553 0           my $special = qr#\$|\*|\@|\^|\+|\.|\?|\)|\(|\||\]|\[|\{|\}#;
554 0           $$specchars =~ s/($special)/\\$1/g;
555             }
556              
557             1
558              
559             __END__