source: trunk/LATMOS-Accounts/lib/LATMOS/Accounts/Utils.pm @ 1950

Last change on this file since 1950 was 1770, checked in by nanardon, 8 years ago

longueur des mots de passe à partir de 8 caractères

  • Property svn:keywords set to Id Rev
File size: 8.0 KB
Line 
1package LATMOS::Accounts::Utils;
2use 5.010000;
3use strict;
4use warnings;
5use Exporter ();
6use vars qw(@ISA @EXPORT_OK @EXPORT);
7use utf8;
8use LATMOS::Accounts::Log;
9use File::Temp qw(tempfile);
10use Crypt::Cracklib;
11
12our $VERSION = (q$Rev$ =~ /^Rev: (\d+) /)[0];
13
14=head1 NAME
15
16LATMOS::Accounts::Utils - Utils functions
17
18=head1 FUNCTIONS
19
20=cut
21
22@ISA = qw(Exporter);
23@EXPORT = qw(to_ascii exec_command switch_user run_via_sudo yesno);
24@EXPORT_OK = qw(to_ascii exec_command switch_user run_via_sudo yesno);
25
26=head2 to_ascii($text)
27
28Replace in C<$text> non ascii caracters from iso-8859-15 table to ascii
29equivalent caracter.
30
31=cut
32
33sub to_ascii {
34    my ($text) = @_;
35    return $text unless(defined($text));
36    utf8::decode($text) unless(utf8::is_utf8($text));
37    $text =~ s/œ/oe/g;
38    $text =~ s/Ê/ae/g;
39    $text =~ tr {uàâÀÂÄÀçéÚêëÉÈÊËïîÏÎÞöÎÖÔÌûÛÜć}
40                {uaaaAAAceeeeEEEEiiIIoooOOuuUUc};
41    $text =~ s/([^[:ascii:]])/_/g;
42    $text
43} 
44
45=head2 exec_command($command, $env)
46
47Execute C<$command> and redirect output to log system.
48
49C<$env> is a hashref containing environment variable to set, all variables are
50prefixed by 'LA_'.
51
52=cut
53
54sub exec_command {
55    my ($command, $env) = @_;
56    my $rout = undef;
57    $rout = \$_[2] if(@_ > 2);
58
59    my @exec = ref $command
60        ? (@$command)
61        : ($command);
62    la_log(LA_DEBUG, 'running command `%s\'', join(' ', @exec));
63
64    pipe(my $rh, my $wh);
65    my $pid = fork;
66    if (!defined($pid)) {
67        la_log(LA_ERR, "Can't launch script: cannot fork");
68    } elsif ($pid) {
69        # Father
70        close($wh);
71        my $header;
72        while (<$rh>) {
73            if ($rout) {
74                $$rout .= $_;
75            } else {
76                chomp;
77                if (!$header) {
78                    $header = 1;
79                    la_log(LA_NOTICE, "exec `%s'", join(' ', @exec));
80                }
81                la_log(LA_NOTICE, "output: %s", $_);
82            }
83        }
84        waitpid($pid, 0);
85        if (my $exitstatus = $?) {
86            la_log(LA_ERR, 'command %s exit with status %d',
87                join(' ', @exec), $exitstatus);
88            return;
89        } else {
90            return 1;
91        }
92    } else {
93        # Child
94        close($rh);
95        ( $ENV{LA_MODULE} ) = caller();
96        foreach (keys %{ $env || {} }) {
97            $ENV{"LA_$_"} = $env->{$_};
98        }
99        open(STDOUT, ">&=" . fileno($wh));
100        open(STDERR, ">&=" . fileno($wh));
101        exec(@exec);
102        exit($!);
103    }
104    1
105}
106
107=head2 parse_obj_file($handle)
108
109Read file content from C<$handle> and return hash containing parsed attributes
110
111=cut
112
113sub parse_obj_file {
114    my ($handle) = @_;
115
116    my %attributes;
117    while (my $line = <$handle>) {
118        $line =~ /^#/ and next;
119        chomp($line);
120        my ($attr, $value) = $line =~ /^\s*(\S+):\s*(.*)\s*$/ or
121            die "Malformed input file\n";
122        $value =~ s/\s*$//;
123        $value =~ s/\\n/\n/g;
124        if ($attributes{$attr}) {
125            if (ref $attributes{$attr}) {
126                push(@{ $attributes{$attr} }, $value);
127            } else {
128                my $temp = $attributes{$attr};
129                $attributes{$attr} = [ $temp, $value ];
130            }
131        } else {
132            $attributes{$attr} = $value eq '' ? undef : $value;
133            # Don't remember why this is here
134            #$attr eq 'exported' && !defined $attributes{$attr} and $attributes{$attr} = 1;
135        }
136    }
137    %attributes
138}
139
140=head2 dump_read_temp_file($writecb, $readcb)
141
142Create a temporary file, call C<$writecb()> function, run editor and if file get
143modified call C<$readcb>.
144
145=cut
146
147sub dump_read_temp_file {
148    my ($writecb, $readcb) = @_;
149
150    my ($fh, $filename) = tempfile(CLEANUP => 0);
151    $writecb->($fh) or return;
152    $fh = undef; # closing file
153    my $res;
154   
155    my @stat = stat($filename);
156    while (1) {
157        my $cmd = ($ENV{EDITOR} || 'vi') . " $filename";
158        warn "Running $cmd\n";
159        if (system($cmd) == -1 ) {
160            warn "Cannot run editor $!\n";
161            last;
162        }
163        if ((stat($filename))[9] == $stat[9]) {
164            warn "No change existing\n";
165            last;
166        }
167
168        open($fh, '<', $filename) or return;
169        $res = $readcb->($fh);
170        $fh = undef; # closing again
171        $res < 2 and last;
172    }
173    unlink($filename);
174    $res;
175}
176
177=head2 check_oid_validity($name)
178
179Check C<$name> is suitable to be used as object identifier. Return the error
180text, undef if no error.
181
182=cut
183
184sub check_oid_validity {
185    my ($name) = @_;
186    return "leadind space" if ($name =~ /^\s/);
187    return "trailing space" if ($name =~ /\s$/);
188    return "containing space" if ($name =~ /\s/);
189
190    return;
191}
192
193=head2 check_ug_validity($name)
194
195Check C<$name> is suitable to used as user or group identifier.
196
197=cut
198
199sub check_ug_validity {
200    my ($name) = @_;
201    return "Empty name is not a valid name !"
202        if (!$name);
203    return "first caractere must be a-z"
204        if ($name !~ /^[a-z]/);
205    return "must contain only a-z,0-9"
206        if ($name !~ /^[a-z,0-9,_,\-,\.]+$/);
207
208    return check_oid_validity($name);
209}
210
211=head2 switch_user($runas)
212
213Switch effective id of the process to user named C<$runas>
214
215=cut
216
217sub switch_user {
218    my ($runas) = @_;
219
220    if ($< == 0 || $> == 0) {
221        my @info = getpwnam($runas) or do {
222            warn "Can find user $runas";
223            return;
224        };
225        $> = $info[3];
226        return;
227    } else {
228        warn "we are not root";
229    }
230}
231
232=head2 run_via_sudo($runas)
233
234Rerun current programme as C<$runas> user using sudo
235
236=cut
237
238sub run_via_sudo {
239    my ($runas) = @_;
240
241    my @info = getpwnam($runas) or do {
242        warn "Can find user $runas";
243        return;
244    }; 
245    if ($< != $info[3]) {
246        exec('sudo', '-u', $runas, $0, @ARGV) or "Can run $!";
247    }
248}
249
250=head2 genpassword(%options)
251
252Generate a random password, options are:
253
254=over 4
255
256=item length
257
258The minimum password length (default is 6)
259
260=item nonalpha
261
262Include non alpha-numeric caracters
263
264=item syllables
265
266Use a set of syllables instead letter
267
268=back
269
270=cut
271
272sub genpassword {
273    my (%options) = @_;
274    my @non_alpha = (qw$; : / ! ( ) [ ] { } + = @ - " ' % * & . ? < >$, ',', '$');
275    my @letters = ('a' .. 'z', 'A' .. 'Z', 0 .. 9);
276
277    my @consonants = qw(b d f g j k l m n r s t v x z ch);
278    my @vowels = qw(a e i o u ou oi io ia iu);
279
280    $options{length} ||= 8 + int(rand(3));
281
282    while (1) {
283        if ($options{syllables}) {
284            $options{length} = int($options{length} / 2);
285            $options{length} = 3 if ($options{length} < 3);
286        } else {
287            $options{length} = 6 if ($options{length} < 6);
288        }
289
290        my @chars;
291
292        if ($options{nonalpha}) {
293            for(0 .. (0 + int(rand(3)))) {
294                push(@chars, (@non_alpha[rand(scalar(@non_alpha))]));
295            }
296        }
297
298        foreach (1 .. ($options{length} - scalar(@chars))) {
299            if ($options{syllables}) {
300                my $c = @consonants[rand(scalar(@consonants))];
301                my $v = @vowels[rand(scalar(@vowels))];
302                push(@chars, "$c$v");
303            } else {
304                push(@chars, (@letters[rand(scalar(@letters))]));
305            }
306        }
307
308
309        my $pass = join('', sort { rand() <=> rand() } @chars);
310        if (length($pass) >= 6 && fascist_check($pass) eq 'ok') {
311            return $pass;
312        }
313    }
314}
315
316=head2 yesno($value, $default)
317
318Check is a paramter mean yes or no
319
320=cut
321
322sub yesno {
323    my ($value, $default) = @_;
324
325    if ($value =~ /^(yes|1|true)$/i) {
326        return 1;
327    }
328    if ($value =~ /^(no|0|false)$/i) {
329        return 0;
330    }
331    if ($value =~ /^\d+$/ and $value != 0) {
332        return 1;
333    }
334    return $default || $value;
335}
336
3371;
338
339__END__
340
341=head1 SEE ALSO
342
343L<sudo>
344
345=head1 AUTHOR
346
347Olivier Thauvin, E<lt>olivier.thauvin@aerov.jussieu.frE<gt>
348
349=head1 COPYRIGHT AND LICENSE
350
351Copyright (C) 2008, 2009, 2010, 2011, 2012 CNRS SA/CETP/LATMOS
352
353This library is free software; you can redistribute it and/or modify
354it under the same terms as Perl itself, either Perl version 5.10.0 or,
355at your option, any later version of Perl 5 you may have available.
356
357=cut
Note: See TracBrowser for help on using the repository browser.