# # Copyright (c) 2001 SuSE GmbH Nuernberg, Germany. All rights reserved. # Copyright (c) 2002 SuSE Linux AG Nuernberg, Germany. All rights reserved. # # # $Id: edit_user4user.pm,v 1.3 2003/11/14 10:55:39 varkoly Exp $ # package edit_user4user; use Encode; use strict; use CGI qw(-no_xhtml); use CGI::Carp qw(fatalsToBrowser); use Net::LDAP qw(:all); use Storable qw(freeze thaw); use Date::Calc qw(check_date); use Image::Magick; use Utils; use LDAPUtils; use Display; use vars qw(@ISA); use subs qw(exit); # Select the correct exit function *exit = $ENV{MOD_PERL} ? \&Apache::exit : sub { CORE::exit }; @ISA = qw(Display); my $JavaScript=<{"cgi"}; my $doit = $cgi->param("doit"); my $displayphoto = $cgi->param('displayphoto'); if(defined $doit && $doit eq "edit") { $this->update_user(); }elsif(defined $displayphoto && $displayphoto ne ""){ $this->printimage(); } else { $this->startup(); } } sub startup { my $this = shift; my $q = $this->{"cgi"}; my $session = $this->{"session"}; my $confParam = $session->{"confParam"}; my $sessionID = $confParam->{"sessionID"}; my $message = ($session->getLanguage($confParam->{LANG},"CREATE_USER", "EDIT_USER"))->data(); $this->{'message'} = $message; my $LOGINuid = $confParam->{uid}; my $ldapbase = $confParam->{baseDN}; my $params = (); my $tab = $q->param('tab'); my $stab = $q->param('stab'); my @group = (); my %g_label = (); my @alias_arr = (); my $errs = ""; my @write_access = (); my $read_attrs; my $disp_attrs; $read_attrs = ['uid', 'sn', 'givenname', 'alias', 'o', 'l', 'c', 'susetimezone', 'ou', 'title', 'initials', 'birthday', 'description', 'homephone', 'telephonenumber', 'mobile', 'facsimiletelephonenumber', 'pager', 'labeleduri', 'street', 'postalcode', 'st', 'jpegphoto']; $disp_attrs = ['givenname', 'sn', 'initials', 'birthday', 'xxxx', 'title', 'o', 'ou', 'xxxx', 'description', 'xxxx', 'street', 'postalcode', 'l', 'st', 'c', 'susetimezone', 'xxxx', 'homephone', 'mobile', 'telephonenumber', 'facsimiletelephonenumber', 'pager', 'labeleduri', 'xxxx', 'jpegphoto' ]; my $must_attr = {"sn" => 1, "c" => 1}; my $user_dn = "uid=".$LOGINuid.",".$ldapbase; my ($code,$entry) = LDAP_read_entry($confParam, $user_dn , $read_attrs); if ( $code == 0 ) { foreach my $attr ( @{$read_attrs} ) { $params->{$attr} = $entry->get_value($attr); if ( $params->{$attr} && ($attr ne 'jpegphoto')) { Encode::from_to($params->{$attr} , "utf8", "$this->{'charset'}"); $params->{$attr} =~ s/\"/"/g ; if ($attr eq "birthday") { ($params->{'birth_year'}, $params->{'birth_month'}, $params->{'birth_day'}) = split /-/, $params->{$attr}; } } } @alias_arr = $entry->get_value('alias'); push @alias_arr, $params->{'uid'}; } else { $errs = "search $message->{failed}\n\n"; $errs .= $entry; $this->display_error($errs, "$confParam->{cgi_path}/menu.pl?sessionID=$sessionID"); exit; } if ( $q->param('read_from_session') ) { my $tmp_params=$this->session_to_form(); foreach my $key (keys %$tmp_params) { $params->{$key} = $tmp_params->{$key}; } } ## Get Users ACI ($code,$entry) = LDAP_read_entry($confParam, $user_dn, ['openldapaci']); if ($code == 0) { my $aci = $entry->get_value("openldapaci"); #print STDERR "My ACI: $aci\n"; if ( ! $aci ) { @write_access = @$read_attrs; } else { @write_access = $this->get_attributes_by_access("w", $aci); } } else { $errs = "search $message->{failed}\n\n"; $errs .= $entry; $this->display_error($errs, "$confParam->{cgi_path}/menu.pl?sessionID=$sessionID"); exit; } my @timezones = getTimeZones(); my $html = ""; $html .= $q->start_table({-class=>'AdminBorder', -cellspacing=>2, -cellpadding=>0, -width=>"100%"}); $html .= $q->start_Tr(); $html .= $q->start_td(); $html .= $q->start_table({-cellspacing=>0, -cellpadding=>3, -width=>"100%"}); $html .= $q->start_multipart_form(-action=>$confParam->{cgi_path}."/edit_user4user.pl", -name=>"form"); $html .= $q->Tr( $this->help_th(2, $message->{edit_user}, "EDIT_USER_USER") ); $html .= $q->start_Tr(); $html .= $q->td({-colspan=>2, -class=>'AdminSubHeader'}, ["$message->{star_fields}"]); foreach my $act_attr (@$disp_attrs) { if ($act_attr eq "xxxx") { $html .= $q->start_Tr(); $html .= $q->start_td({-colspan=>2}); $html .= $q->hr({-noshade => '1', -size => '1', -width=>'98%'}); $html .= $q->end_td(); $html .= $q->end_Tr(); next; } $html .= $q->start_Tr(); $html .= $q->start_td(); $html .= $message->{$act_attr}; if ( $must_attr->{$act_attr} ) { $html .= "*"; } $html .= $q->end_td(); $html .= $q->start_td(); if ($act_attr eq "o") { $html .= $params->{'o'}; } elsif ($act_attr eq "c") { if ( grep(/^c$/i, @write_access) ) { $html .= $q->textfield(-name=>"c", -override=>0, -size=>30, -maxlength=>2, -value=>$params->{'c'}). $q->a({-href=>"javascript:void(0);", -onclick=>"$JavaScript; open_help_win('$confParam->{cgi_path}/country_codes.pl?sessionID=$sessionID')"}, $q->img({-border=>0, -src=>"$confParam->{image_path}/help1.gif", -width=>18, -height=>18, -alt=>"Help" }) ); } else { $html .= $params->{'c'}; } } elsif ($act_attr eq "susetimezone") { if (! $params->{$act_attr}) { my @dflt_timezone = parse_file("/etc/sysconfig/clock", "TIMEZONE="); $params->{$act_attr} = $dflt_timezone[0]; $params->{$act_attr} =~ s/\"//g; } if (grep(/^susetimezone$/i, @write_access)) { $html .= $q->popup_menu(-name=>"susetimezone", -values => \@timezones, -default => $params->{$act_attr}, -override=>0); } else { $html .= $params->{$act_attr}; } } elsif ($act_attr eq "logindestination" ) { if (! $params->{$act_attr}) { $params->{$act_attr} = "groupware"; } if (grep(/^logindestination$/i, @write_access)) { $html .= $q->popup_menu(-name=>$act_attr, -values => ['groupware', 'webmail', 'config'], -labels => { 'groupware' => $message->{'groupware'}, 'webmail' => $message->{'webmail'}, 'config' => $message->{'config'} }, -default => $params->{$act_attr}, -override=>0); } else { $html .= $message->{$params->{$act_attr}}; } } elsif ($act_attr eq "description") { if ( grep(/^description$/i, @write_access) ) { $html .= $q->textarea(-name => $act_attr, -default => $params->{$act_attr}, -rows => 4, -columns => 30); } else { if ( defined $params->{'description'}) { $params->{'description'} =~ s/\n/
/mg; $html .= $params->{'description'}; } else { $html .= "".$message->{'no_value'}.""; } } } elsif ( ($act_attr eq "comfireappointmentdays") || ($act_attr eq "comfiretaskdays") ) { my @numbers = ( 1,2,3,4,5,6,7,8,9,10,11,12,13,14 ); $html .= $q->popup_menu(-name=> $act_attr, -values=> \@numbers, -default=>$params->{$act_attr}); $html .= " ".$message->{'daysAhead'}; } elsif ($act_attr eq "birthday") { if (grep(/^birthday$/i, @write_access)) { my $month = [ '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12' ], my $days = [ '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31']; $html .= $message->{'year'}.": ".$q->textfield(-name =>"birth_year", -size => 4, -default => $params->{'birth_year'}); $html .= " ".$message->{'month'}.": ".$q->popup_menu(-name=>"birth_month", -values => $month, -default => $params->{'birth_month'}, -override=>0); $html .= " ".$message->{'day'}.": ".$q->popup_menu(-name=>"birth_day", -values => $days, -default => $params->{'birth_day'}, -override=>0); } else { if ((defined $params->{$act_attr}) && ($params->{$act_attr} ne "") ) { $html .= $params->{$act_attr}; } else { $html .= "" .$this->{'message'}->{'no_value'}. ""; } } } elsif ( $act_attr eq "jpegphoto" ) { $html .= $q->img({-src => $confParam->{'cgi_path'}. "/edit_user4user.pl?displayphoto=1&sessionID=$sessionID", -alt => $message->{'no_image_present'} }).$q->br(); $html .= $q->end_td(); $html .= $q->end_Tr(); $html .= $q->start_Tr(); $html .= $q->start_td(); if (grep(/^jpegphoto$/i, @write_access)) { $html .= $q->end_td(); $html .= $q->start_td(); $html .= $q->filefield(-name=>$act_attr, -default => ""); } } else { $html .= $this->create_text_element($act_attr, $params, \@write_access); } $html .= $q->end_td(); $html .= $q->end_Tr(); } $html .= $q->start_Tr(); $html .= $q->td({-colspan=>2, -align=>"center"}, [$q->submit(-class=>"button",-name=>"$message->{save}"). $q->hidden(-name=>"uid", -value=>$params->{'uid'}). $q->hidden(-name=>"doit", -value=>"edit"). $q->hidden(-name=>"sessionID", -value=>$sessionID). $q->hidden(-name=>"tab", -value=>$tab). $q->hidden(-name=>"stab", -value=>$stab). $q->end_form() ]); $html .= $q->end_Tr(); $html .= $q->end_table(); $html .= $q->end_td(); $html .= $q->end_Tr(); $html .= $q->end_table(); $this->SUPER::display($html); } sub update_user { my $this = shift; $this->form_to_session(); my $q = $this->{"cgi"}; my $disp_attrs = ['givenname', 'sn', 'initials', 'title', 'ou', 'description', 'street', 'postalcode', 'l', 'st', 'c', 'susetimezone', 'homephone', 'mobile', 'telephonenumber', 'facsimiletelephonenumber', 'pager', 'jpegphoto', 'birthday', 'labeleduri' ]; my $session = $this->{"session"}; my $confParam = $session->{"confParam"}; my $sessionID = $confParam->{"sessionID"}; my $message = ($session->getLanguage($confParam->{LANG},"CREATE_USER", "EDIT_USER"))->data(); my $LOGINuid = $confParam->{uid}; my $LOGINpasswd = $confParam->{passwd}; my $ldapbase = $confParam->{baseDN}; my $ldaphost = $confParam->{LDAPserver}; my $ldapport = $confParam->{LDAPport}; my $tab = $q->param('tab'); my $stab = $q->param('stab'); my $uid = $q->param('uid'); my @write_access = (); my $cgi_params = $q->Vars(); foreach my $p ( keys %$cgi_params ) { if( $p eq 'homephone' || $p eq 'mobile' || $p eq 'facsimiletelephonenumber' || $p eq 'pager' || $p eq 'telephonenumber' ) { next if $cgi_params->{$p} eq ""; if( $cgi_params->{$p} !~ /[^-\s]/ ) { $this->display_error("$p $message->{invalid_number}", "$confParam->{cgi_path}/edit_user4user.pl?sessionID=$sessionID". "\&tab=$tab\&stab=$stab&read_from_session=1"); exit; } } } if($cgi_params->{'telephonenumber'} =~ /[^a-zA-Z0-9-+.()\/ ]+/ ) { $this->display_error($message->{false_value}.": ".$message->{'telephonenumber'}, "$confParam->{cgi_path}/edit_user4user.pl?sessionID=$sessionID". "\&tab=$tab\&stab=$stab\&read_from_session=1"); exit; } if($cgi_params->{'facsimiletelephonenumber'} =~ /[^a-zA-Z0-9-+.()\/ ]+/ ) { $this->display_error($message->{false_value}.": ".$message->{'facsimiletelephonenumber'}, "$confParam->{cgi_path}/edit_user4user.pl?sessionID=$sessionID". "\&tab=$tab\&stab=$stab\&read_from_session=1"); exit; } if($cgi_params->{'mobile'} =~ /[^a-zA-Z0-9-+.()\/ ]+/ ) { $this->display_error($message->{false_value}.": ".$message->{'mobile'}, "$confParam->{cgi_path}/edit_user4user.pl?sessionID=$sessionID". "\&tab=$tab\&stab=$stab\&read_from_session=1"); exit; } if($cgi_params->{'homephone'} =~ /[^a-zA-Z0-9-+.()\/ ]+/ ) { $this->display_error($message->{false_value}.": ".$message->{'homephone'}, "$confParam->{cgi_path}/edit_user4user.pl?sessionID=$sessionID". "\&tab=$tab\&stab=$stab\&read_from_session=1"); exit; } if($cgi_params->{'pager'} =~ /[^a-zA-Z0-9-+.()\/ ]+/ ) { $this->display_error($message->{false_value}.": ".$message->{'pager'}, "$confParam->{cgi_path}/edit_user4user.pl?sessionID=$sessionID". "\&tab=$tab\&stab=$stab\&read_from_session=1"); exit; } # some basic validy check for the birthdate if( $cgi_params->{'birth_year'} != "" ){ if( $cgi_params->{'birth_year'} !~ /^\d{4}$/ ){ $this->display_error($message->{'year_four_digit'}, "$confParam->{cgi_path}/edit_user4user.pl?sessionID=$sessionID". "\&tab=$tab\&stab=$stab\&read_from_session=1"); exit; }elsif( ! check_date($cgi_params->{'birth_year'},$cgi_params->{'birth_month'},$cgi_params->{'birth_day'}) ){ $this->display_error($message->{'invalid_birth_date'}, "$confParam->{cgi_path}/edit_user4user.pl?sessionID=$sessionID". "\&tab=$tab\&stab=$stab\&read_from_session=1"); exit; }else{ $cgi_params->{'birthday'} = $cgi_params->{'birth_year'}."-".$cgi_params->{'birth_month'}. "-".$cgi_params->{'birth_day'}; } } foreach my $attr (@$disp_attrs){ if( $cgi_params->{$attr} && ($attr ne "jpegphoto") ){ Encode::from_to($cgi_params->{$attr} , "$this->{'charset'}", "utf8"); } } my $errs = ""; my $bind_dn = "uid=".$LOGINuid.",".$ldapbase; my $ldap = Net::LDAP->new("$ldaphost", port => $ldapport, version => 3); if(!defined $ldap) { $this->display_error("can't contact LDAP Server", "$confParam->{cgi_path}/menu.pl?sessionID=$sessionID"); exit; } my $mesg = $ldap->bind ( # bind to a directory with dn and password dn => "$bind_dn", password => "$LOGINpasswd" ); if($mesg->code != 0) { $errs = "bind $message->{failed}\n\n"; $errs .= &LDAPerror($mesg); $this->display_error($errs, "$confParam->{cgi_path}/menu.pl?sessionID=$sessionID"); exit; } ## Get Users ACI $mesg = $ldap->search( base => $bind_dn, scope => "base", filter => "objectClass=*", attrs => ["openldapaci"]); if($mesg->code == LDAP_SUCCESS){ my $aci = $mesg->entry(0)->get_value("openldapaci"); #print STDERR "My ACI: $aci\n"; if( ! $aci ) { foreach my $attr ( @$disp_attrs ) { push @write_access, $attr; } push @write_access, "cn"; } else { @write_access = $this->get_attributes_by_access("w", $aci); } }else{ $errs = "search $message->{failed}\n\n"; $errs .= &LDAPerror($mesg); $ldap->unbind; # take down session $this->display_error($errs, "$confParam->{cgi_path}/menu.pl?sessionID=$sessionID"); exit; } if( (! $cgi_params->{'sn'}) && (grep( /^sn$/, @write_access) ) || (! $cgi_params->{'c'} ) && (grep( /^c$/, @write_access) ) ){ $this->display_error($message->{miss_some_values}, "$confParam->{cgi_path}/edit_user4user.pl?sessionID=$sessionID". "\&tab=$tab\&stab=$stab\&read_from_session=1"); exit; } my @mod_op; foreach my $val ( @write_access ) { #print STDERR "ATTR: $val\n"; my $e_val = $cgi_params->{$val}; if( $val eq "cn" ){ if( $cgi_params->{'givenname'} ){ push @mod_op, "replace", [ "cn", [ $cgi_params->{'givenname'}." ".$cgi_params->{'sn'} ] ]; }else{ push @mod_op, "replace", [ "cn", [ $cgi_params->{'sn'} ] ]; } #print STDERR "MOD: $val e_val: ".$cgi_params->{'givenname'}." ".$cgi_params->{'sn'}."\n"; }elsif( $val eq "jpegphoto" ){ my $jpegfile = $q->upload('jpegphoto'); if( $jpegfile ){ if( $q->uploadInfo($jpegfile)->{'Content-Type'} =~ /image\/p*jpeg/i ){ my $buf = ""; my $bytesread; my $jpegdata = ""; while ($bytesread=read($jpegfile,$buf,1024)) { $jpegdata .= $buf; } my @blob = ( $jpegdata ); my $image = Image::Magick->new('magick' => 'jpg'); if( $image->BlobToImage(@blob) ){ $this->display_error($message->{'no_jpeg'}, "$confParam->{cgi_path}/edit_user4user.pl?sessionID=$sessionID". "&read_from_session=1&tab=$tab&stab=$stab"); exit; }; my $act_width = $image->Get('width'); my $act_height = $image->Get('height'); my $new_width = int( $::CONF_GLOBAL{'GENERAL'}{'UserJpegPhotoMaxWidth'} ) || 150; my $new_height = int( $::CONF_GLOBAL{'GENERAL'}{'UserJpegPhotoMaxHeight'} ) || 200; # scale the image if( ( $act_height > $new_height ) || ( $act_width > $new_width ) ){ my $scale_w = $new_width / $act_width; my $scale_h = $new_height / $act_height; my $scale = ($scale_w < $scale_h) ? $scale_w : $scale_h; $new_width = $act_width * $scale; $new_height = $act_height * $scale; $image->Scale('width' => $new_width, 'height' => $new_height); } @blob = $image->ImageToBlob(); push @mod_op, "replace", [ $val, [$blob[0]] ]; }else{ $this->display_error($message->{'no_jpeg'}, "$confParam->{cgi_path}/edit_user4user.pl?sessionID=$sessionID". "&read_from_session=1&tab=$tab&stab=$stab"); exit; } } }elsif($val eq "mail" || $val eq "faxdid" || $val eq "smsdid" || $val eq "printid" ){ # these attributs aren't written here next; }else{ if( defined $e_val && $e_val ne "" ) { push @mod_op, "replace", [ $val, [$e_val] ]; #print STDERR "MOD: $val e_val: $e_val\n"; } else { push @mod_op, "replace", [ $val, [] ]; #print STDERR "MOD: $val \n"; } } } $mesg = $ldap->modify( "uid=$uid,$ldapbase", changes => \@mod_op ); if($mesg->code != 0) { $errs = "modify $message->{failed}\n\n"; $errs .= &LDAPerror($mesg); $ldap->unbind; # take down session $this->display_error($errs, "$confParam->{cgi_path}/menu.pl?sessionID=$sessionID"); exit; } $q->delete('ou'); $q->delete('title'); $q->delete('givenname'); $q->delete('sn'); $q->delete('initials'); $q->delete('description'); $q->delete('homephone'); $q->delete('mobile'); $q->delete('pager'); $q->delete('facsimiletelephonenumber'); $q->delete('telephonenumber'); $q->delete('labeleduri'); $q->delete('street'); $q->delete('postalcode'); $q->delete('l'); $q->delete('c'); $q->delete('st'); my $text = ""; $text .= "insUpdSystemUser $uid $message->{success}
\n"; $this->display_msg($message->{user_edit_ok}."\n".$text, "$confParam->{cgi_path}/edit_user4user.pl?sessionID=$sessionID\&tab=$tab\&stab=$stab", 1); $this->cleanupsession(); } sub get_attributes_by_access(){ my ($this, $right, $aci) = @_; my ($oid, $scope, $rights, $type, $subject) = split /#/, $aci; my @rights_arr = split /;/, $rights; my @attrs = (); my $action = shift(@rights_arr); if($type ne "self"){ return (); } for( my $i=0; $i < scalar(@rights_arr); $i+=2){ #print STDERR "rights: $rights_arr[$i]\n"; if( $rights_arr[$i] =~ /w/ ){ push @attrs, (split /,/, lc($rights_arr[$i+1]) ); } } return @attrs; } sub create_text_element{ my ($this, $name, $value, $access) = @_; my $q = $this->{'cgi'}; my $res = ""; if(grep(/^$name$/i, @{$access})){ $res .= $q->textfield(-name=> $name, -size=>30, -default=>$value->{$name}); }else{ if((defined $value->{$name}) && ($value->{$name} ne "") ){ $res .= $value->{$name}; }else{ $res .= "" .$this->{'message'}->{'no_value'}. ""; } } return $res; } sub form_to_session{ my $this = shift; my $session = $this->{"session"}; my $cgi = $this->{'cgi'}; my %cgi_params = $cgi->Vars(); my $frozen = freeze (\%cgi_params); $frozen = unpack('H*',$frozen); my %tmp = ( "u4u_formdata" => $frozen ); my $s_reply=$session->modify(\%tmp); if( $s_reply->code() ne "OK" ) { return "ERR" }else { return "OK"; } } sub session_to_form{ my $this = shift; my $session = $this->{"session"}; my $confParam = $session->{'confParam'}; my $frozen = $confParam->{'u4u_formdata'}; $frozen = pack('H*',$frozen); my $formdata = thaw($frozen); return $formdata; } sub cleanupsession{ my $this = shift; my $session = $this->{"session"}; my $reply = $session->modify({"u4u_formdata" => "" }); } sub printimage{ my $this = shift; my $q = $this->{"cgi"}; my $session = $this->{"session"}; my $confParam = $session->{"confParam"}; my $message = ($session->getLanguage($confParam->{LANG},"CREATE_USER", "EDIT_USER"))->data(); my $sessionID = $confParam->{"sessionID"}; my $uid = $confParam->{uid}; my $passwd = $confParam->{passwd}; my $ldapbase = $confParam->{baseDN}; my $ldaphost = $confParam->{LDAPserver}; my $ldapport = $confParam->{LDAPport}; my $bind_dn = "uid=$uid,$ldapbase"; my $ldap = Net::LDAP->new("$ldaphost", port => $ldapport, version => 3); if(!defined $ldap) { $this->display_error("can't contact LDAP Server", "$confParam->{cgi_path}/menu.pl?sessionID=$sessionID"); exit; } my $mesg = $ldap->bind ( # bind to a directory with dn and password dn => "$bind_dn", password => "$passwd" ); if($mesg->code != 0) { my $errs = "bind $message->{failed}\n\n"; $errs .= &LDAPerror($mesg); $this->display_error($errs, "$confParam->{cgi_path}/menu.pl?sessionID=$sessionID"); exit; } $mesg = $ldap->search( base => "uid=$uid,".$confParam->{baseDN}, scope => 'base', attrs => [ 'jpegphoto' ], filter => "objectclass=*" ); if ($mesg->count == 0) { my $text = "search failed\n".&LDAPerror($mesg); $this->display_error($text,"$confParam->{cgi_path}/menu.pl?sessionID=$sessionID"); $ldap->unbind; exit; } my $photo = $mesg->entry(0)->get_value('jpegPhoto'); print $q->header("image/jpeg"); binmode STDOUT; print $photo; } 1;