#!/usr/bin/perl use strict; use warnings; use 5.008; # used to manage files use Path::Class; # used for checking config dirs rights (make the translation for lstat output) use Fcntl ':mode'; # used to handle ldap connections use Net::LDAP; # used to base64 encode use MIME::Base64; # used to generate {CRYPT} password (for LDAP) use Crypt::PasswdMD5; # used to uncompress tar.gz use Archive::Extract; # used to copy files use File::Copy::Recursive qw(rcopy); #XML parser use XML::Twig; # fd's directory and class.cache file's path declaration my %vars = ( fd_home => "/var/www/fusiondirectory", fd_cache => "/var/cache/fusiondirectory", fd_config_dir => "/etc/fusiondirectory", fd_spool_dir => "/var/spool/fusiondirectory", config_file => "fusiondirectory.conf", locale_dir => "locale", class_cache => "class.cache", locale_cache_dir => "locale", tmp_dir => "tmp", fai_log_dir => "fai", template_dir => "template" ); my ($fd_config,$locale_dir,$class_cache,$locale_cache_dir,$tmp_dir,$fai_log_dir,$template_dir); my (@root_config_dirs,@apache_config_dirs,@config_dirs); my @plugin_types = qw(addons admin personal); my $yes_flag = 0; my %classes_hash_result = (); my %i18n_hash_result = (); my $oupeople = "people"; my $peopleou = "ou=$oupeople"; ################################################################################################################################################# # ask a question send as parameter, and return true if the answer is "yes" sub ask_yn_question { return 1 if ($yes_flag); my ($question) = @_; print ( "$question [Yes/No]?\n" ); while ( my $input = <STDIN> ) { # remove the \n at the end of $input chomp $input; # if user's answer is "yes" if ( lc($input) eq "yes" || lc($input) eq "y") { return 1; # else if he answer "no" } elsif ( lc($input) eq "no" || lc($input) eq "n") { return 0; } } } # function that ask for an user input and do some checks sub ask_user_input { my ($thing_to_ask, $default_answer) = @_; my $answer; if (defined $default_answer) { $thing_to_ask .= " [$default_answer]"; } print $thing_to_ask.":\n"; do { $answer = <STDIN>; chomp $answer; $answer =~ s/^\s+|\s+$//g; } while (($answer eq "") && (not defined $default_answer)); if ($answer eq "") { return $default_answer; } return $answer; } ####################################################### class.cache update ######################################################################### # function that scan recursivly a directory to find .inc and . php # then return a hash with class => path to the class file sub get_classes { my ($path) = @_; # if this function has been called without a parameter die ("! function get_classes called without parameter\n") if ( !defined($path) ); # create a "dir" object with the path my $dir = dir ($path) or die ("! Can't open $path\n"); my $contrib_dir = dir($vars{fd_home},"contrib"); if ("$dir" eq "$contrib_dir") { return; } # create an array with the content of $dir my @dir_files = $dir->children; foreach my $file (@dir_files) { # recursive call if $file is a directory if ( -d $file ) { get_classes($file); next; } # only process if $file is a .inc or a .php file if ( ( $file =~ /.*\.inc$/ ) && ( $file !~ /.*smarty.*/ ) ) { # put the entire content of the file pointed by $file in $data my @lines = $file->slurp; # modifing $file, to contains relative path, not complete one $file =~ s/^$vars{fd_home}//; foreach my $line ( @lines ) { # remove \n from the end of each line chomp $line; # only process for lines beginning with "class", and extracting the 2nd word (the class name) if ( $line =~ /^class\s*(\w+).*/ ) { # adding the values (class name and file path) to the hash $classes_hash_result{$1} = $file; } } } } return %classes_hash_result; } # call get_classes and create /var/cache/fusiondirectory/class.cache sub rescan_classes { # hash that will contain the result of the "get_classes" function my %get_classes_result = get_classes ($vars{fd_home}); # create a "file" object with the $class_cache path my $file_class = file ($class_cache); # create the handler (write mode) for the file previoulsy created my $fhw = $file_class->openw() or die ("! Unable to open $class_cache in write mode\n"); # first lines of class.cache $fhw->print ("<?php\n\t\$class_mapping= array(\n"); # for each $key/$value, writting a new line to $class_cache while ( my($key,$value) = each %get_classes_result ) { $fhw->print ("\t\t\"$key\" => \"$value\",\n"); } # last line of classe.cache $fhw->print ("\t);\n?>"); $fhw->close or die ("! Can't close $class_cache\n"); } ###################################################### Internalisation's update #################################################################################### # function that create .mo files with .po for each language sub get_i18n { my ($path) = @_; # if this function has been called without a parameter die ("! function get_i18n called without parameter" ) if ( !defined($path) ); # create a "dir" object my $dir = dir ($path) or die ("! Can't open $path\n"); # create an array with the content of $dir my @dir_files = $dir->children; foreach my $file (@dir_files) { # recursive call if $file is a directory if (-d $file) { %i18n_hash_result = get_i18n ($file); next; } # if the file's directory is ???/language/fusiondirectory.po if ($file =~ qr{^.*/(\w+)/fusiondirectory.po$}) { # push the file's path in the language (fr/en/es/it...) array (wich is inside the hash pointed by $ref_result push @{$i18n_hash_result{$1}}, $file; } } return %i18n_hash_result; } # call get_i18n with the FusionDirectory's locales's directory and the hash that will contain the result in parameter sub rescan_i18n { # hash that will contain the result of the "get_i18n" function my %get_i18n_result = get_i18n ($locale_dir); while ( my ($lang, $files) = each %get_i18n_result ) { # directory wich will contain the .mo file for each language my $lang_cache_dir = dir ("$locale_cache_dir/$lang/LC_MESSAGES"); # if $lang_cache_dir doesn't already exists, creating it if ( !-d $lang_cache_dir ) { $lang_cache_dir->mkpath or die ("! Can't create $locale_cache_dir/$lang/LC_MESSAGES"); } # glue .po files's names my $po_files = join(" ", @{$files}); chomp $po_files; # merging .po files system ( "msgcat --use-first ".$po_files.">".$lang_cache_dir."/fusiondirectory.po" ) and die ("! Unable to merge .po files for $lang with msgcat, is it already installed?\n"); # compiling .po files in .mo files system ( "msgfmt -o $lang_cache_dir/fusiondirectory.mo $lang_cache_dir/fusiondirectory.po && rm $lang_cache_dir/fusiondirectory.po" ) and die ("! Unable to compile .mo files with msgfmt, is it already installed?\n"); } } ############################################################# Directories checking ################################################################################### #get the apache user group name sub get_apache_user { my $apache_user = ""; # try to identify the running distribution, if it's not debian or rehat like, script ask for user input if (-e "/etc/debian_version") { $apache_user = "www-data"; } elsif ((-e "/etc/redhat-release") || (-e "/etc/mageia-release")) { $apache_user = "apache"; } else { print ("! Looks like you are not a Debian, Redhat or Mageia, I don't know your distribution !\n"); $apache_user = ask_user_input ("Who is your apache user ?"); } return $apache_user; } #check the rights of a directory or file, creates missing directory if needed sub check_rights { my ($dir,$user,$group,$rights,$create) = @_; my $user_uid = getpwnam ( $user ); my $group_gid = getgrnam ( $group ); # if the current dir exists if (-e $dir) { print("$dir existsâ¦\n"); # retrieve dir's informations my @lstat = lstat ($dir); # extract the owner and the group of the directory my $dir_owner = getpwuid ( $lstat[4] ); my $dir_group = getgrgid ( $lstat[5] ); # extract the dir's rights my $dir_rights = S_IMODE( $lstat[2] ); if ( ($dir_owner ne $user) || ($dir_group ne $group) || ($dir_rights ne $rights) ) { if ( ask_yn_question ("$dir is not set properly, do you want to fix it ?: ") ) { chown ($user_uid,$group_gid,$dir) or die ("! Unable to change $dir owner\n") if ( ($dir_owner ne $user) || ($dir_group ne $group) ); chmod ( $rights, $dir ) or die ("! Unable to change $dir rights\n") if ($dir_rights ne $rights); } else { print ("Skiping...\n"); } } else { print("Rights on $dir are correct\n"); } } elsif ($create) { if ( ask_yn_question("Directory $dir doesn't exists, do you want to create it ?: ") ) { my $conf_dir = dir ($dir); # create the directory, and change the rights $conf_dir->mkpath (0,$rights); chmod ($rights, $dir); chown ($user_uid,$group_gid,$dir) or die ("Unable to change $dir rights\n"); } else { print ( "Skiping...\n" ); } } else { return 0; } return 1; } # function that check FusionDirectory's directories sub check_directories { my $apache_user = get_apache_user(); # for each config directory foreach my $dir (@config_dirs) { # if $dir is one of the dirs that remains to root if ( grep (/.*$dir.*/, @root_config_dirs) ) { check_rights($dir,"root","root",0755,1); # else if $dir is one of the dirs that remains to apache's user, and the dir's owner is not root or the group is not the apache's user, modifying owner } elsif ( grep ( /.*$dir.*/, @apache_config_dirs) ) { check_rights($dir,"root",$apache_user,0770,1); } } } # function that check FusionDirectory's config file sub check_config { my $apache_user = get_apache_user(); # check config file check_rights($fd_config,"root",$apache_user,0640,0) or die 'The config file does not exists!'; } ############################################################# Change install directories ################################################################################# sub write_vars { my $filecontent = <<eof; <?php require_once('variables_common.inc'); /*! \\file * Define common locations and variables * Generated by fusiondirectory-setup */ if(!defined("CONFIG_DIR")){ define ("CONFIG_DIR", "$vars{fd_config_dir}/"); /* FusionDirectory etc path */ } /* Allow setting the config file in the apache configuration e.g. SetEnv CONFIG_FILE fusiondirectory.conf 1.0 */ if(!defined("CONFIG_FILE")){ define ("CONFIG_FILE", "$vars{config_file}"); /* FusionDirectory filename */ } /* Smarty compile dir */ define ("SPOOL_DIR","$vars{fd_spool_dir}/"); /* FusionDirectory spool directory */ /* Global cache dir */ define ("CACHE_DIR","$vars{fd_cache}/"); /* FusionDirectory var directory */ /* Global locale cache dir */ define ("LOCALE_DIR", "$locale_cache_dir/"); /* FusionDirectory locale directory */ /* Global tmp dir */ define ("TEMP_DIR", "$tmp_dir/"); /* FusionDirectory tmp directory */ /* Directory containing the configuration template */ define ("CONFIG_TEMPLATE_DIR", "$template_dir/"); /* FusionDirectory template directory */ /* Directory containing the fai logs */ define ("FAI_LOG_DIR", "$fai_log_dir/"); /* FusionDirectory fai directory */ /* Directory containing the supann files define ("SUPANN_DIR", "$vars{fd_config_dir}/supann/"); /* FusionDirectory supann template directory */ /* name of the class.cache file */ define("CLASS_CACHE", "$vars{class_cache}"); /* name of the class cache */ ?> eof my $variables_path = "$vars{fd_home}/include/variables.inc"; my $variables_file = file ($variables_path); my $vars_file = $variables_file->openw() or die ("! Unable to open $variables_path in write mode\n"); $vars_file->print($filecontent); $vars_file->close or die ("! Can't close $variables_file\n"); } ############################################################# LDAP conformity check ################################################################################# # function that add the FusionDirectory's admin account # return nothing is it a problem? sub add_ldap_admin { my ($base, $ldap, $acllines, $people_entries) = @_; # Get the configuration to know which attribute must be used in the dn my $mesg = $ldap->search( base => "$base", filter => "(&(objectClass=fusionDirectoryConf)(cn=fusiondirectory))", attrs => ['fdAccountPrimaryAttribute'] ); my $attr; if ($mesg->count <= 0) { print "Could not find configuration object, using default value\n"; $attr = 'uid'; } elsif (($mesg->entries)[0]->exists('fdAccountPrimaryAttribute')) { $attr = ($mesg->entries)[0]->get_value('fdAccountPrimaryAttribute'); } else { $attr = 'uid'; } my $fd_admin_uid = ask_user_input ("Please enter a login for FusionDirectory's admin", "fd-admin"); # Does this user exists? my $dn = ""; foreach my $entry (@$people_entries) { my $mesg = $ldap->search( base => "$entry", filter => "(&(objectClass=gosaAccount)(uid=$fd_admin_uid))", attrs => ['uid'] ); if ($mesg->count) { print "User $fd_admin_uid already existing, adding admin acl to it\n"; $dn = ($mesg->entries)[0]->dn; last; } } if ($dn eq "") { my $fd_admin_pwd = ask_user_input ("Please enter FusionDirectory's admin password"); my $fd_admin_pwd_confirm = ask_user_input ("Please enter it again"); # while the confirmation password is not the same than the first one while ( ($fd_admin_pwd_confirm ne $fd_admin_pwd) && ($fd_admin_pwd_confirm ne "quit" ) ) { $fd_admin_pwd_confirm = ask_user_input ("! Inputs don't match, try again or type 'quit' to end this function"); } return -1 if ($fd_admin_pwd_confirm eq "quit"); my %obj = ( 'cn' => 'System Administrator', 'sn' => 'Administrator', 'uid' => $fd_admin_uid, 'givenname' => 'System', 'objectclass' => [ 'top', 'person', 'gosaAccount', 'organizationalPerson', 'inetOrgPerson' ], 'userPassword' => "{CRYPT}".unix_md5_crypt($fd_admin_pwd) ); if (not defined $obj{$attr}) { print "Error : invalid account primary attribute $attr, using uid\n"; $attr = 'uid'; } $dn = "$attr=".$obj{$attr}.",$peopleou,$base"; # Add the administator user object my @options = %obj; my $admin_add = $ldap->add( $dn, attr => \@options ); # send a warning if the ldap's admin's add didn't gone well $admin_add->code && die "\n! failed to add LDAP's $dn entry - ".$admin_add->error_name.": ".$admin_add->error_text; } # Add the acl that make him an administrator my $acls = $ldap->search ( base => "$base", scope => 'base', filter => "(objectClass=*)", attrs => ['objectClass', 'gosaAclEntry'] ); $acls->code && die "\n! failed to search acls in '$base' - ".$acls->error_name.": ".$acls->error_text; my $oclass = ($acls->entries)[0]->get_value("objectClass", asref => 1); # Add admin acl my $newacl = ["0:psub:".encode_base64($dn).":all;cmdrw"]; if (not (grep $_ eq 'gosaAcl', @$oclass)) { push (@$oclass, 'gosaAcl'); } else { my $acl = ($acls->entries)[0]->get_value("gosaAclEntry", asref => 1); my $i = 1; if (defined $acl) { foreach my $line (@$acl) { # Ignore existing admin acls if (not (grep $_ eq $line, @$acllines)) { # Reorder existing non-admin acls $line =~ s/^\d+:/$i:/; push (@$newacl, $line); $i++; } } } } my $result = $ldap->modify ( $base, replace => { 'objectClass' => $oclass, 'gosaAclEntry' => $newacl } ); $result->code && warn "\n! failed to add ACL for admin on '$base' - ".$result->error_name.": ".$result->error_text; } # function that initiate the ldap connexion, and bind as the ldap's admin sub get_ldap_connexion { my %hash_result = (); my $bind_dn = ""; my $bind_pwd = ""; my $uri = ""; my $base = ""; # read ldap's server's info from /etc/fusiondirectory/fusiondirectory.conf if (-e $fd_config) { my $twig = XML::Twig->new(); # create the twig $twig->parsefile($fd_config); # build it my @locs = $twig->root->first_child('main')->children('location'); my %locations = (); foreach my $loc (@locs) { my $ref = $loc->first_child('referral'); $locations{$loc->{'att'}->{'name'}} = { 'uri' => $ref->{'att'}->{'URI'}, 'bind_dn' => $ref->{'att'}->{'adminDn'}, 'bind_pwd' => $ref->{'att'}->{'adminPassword'} }; } my ($location) = keys(%locations); if (scalar(keys(%locations)) > 1) { my $question = "There are several locations in your config file, which one should be used : (".join(',',keys(%locations)).")"; my $answer; do { $answer = ask_user_input ($question, $location); } while (not exists($locations{$answer})); $location = $answer; } if ($locations{$location}->{'uri'} =~ qr|^(.*)/([^/]+)$|) { $uri = $1; $base = $2; } else { die '"'.$locations{$location}->{'uri'}.'" does not contain any base!'; } $bind_dn = $locations{$location}->{'bind_dn'}; $bind_pwd = $locations{$location}->{'bind_pwd'}; # if can't find fusiondirectory.conf } else { if ( ask_yn_question ("Can't find fusiondirectory.conf, do you want to specify LDAP's informations yourself ?: ") ) { $uri = ask_user_input ("LDAP server's URI"); $base = ask_user_input ("Search base"); $hash_result{base} = $base; $bind_dn = ask_user_input ("Bind DN"); $bind_pwd = ask_user_input("Bind password"); } else { return; } } # ldap connection my $ldap = Net::LDAP->new ($uri) or die ("! Can't contact LDAP server $uri\n"); $hash_result{ldap} = $ldap; $hash_result{base} = $base; # bind to the LDAP server my $bind = $ldap->bind ($bind_dn, password => $bind_pwd); # send a warning if the bind didn't gone well $bind->code && die ("! Failed to bind to LDAP server: ", $bind->error."\n"); return %hash_result; } # function that check if there is an admin sub check_admin { my ($base, $ldap, $people_entries) = @_; # search for FusionDirectory's admin account my $acls = $ldap->search ( base => "$base", filter => "(objectClass=gosaAcl)", attrs => ['gosaAclEntry'] ); my @dns = (); if ($acls->count < 1) { print ("! ACL entries are missing\n"); } else { my $acl = ($acls->entries)[0]->get_value("gosaAclEntry", asref => 1); if (defined $acl) { foreach my $line (@$acl) { my @parts = split(':',$line); if ($parts[1] =~ /sub$/) { my @domains = split(",",$parts[3]); foreach my $domain (@domains) { if ($domain eq 'all;cmdrw') { push (@dns,$line); last; } } } } } foreach my $line (@dns) { my @parts = split(':',$line); my $dn = decode_base64($parts[2]); my $mesg = $ldap->search ( base => $dn, scope => 'base', filter => "(objectClass=gosaAccount)" ); if ( $mesg->count == 1 ) { print ("$dn is a valid admin\n"); return; } } } foreach my $line (@dns) { my @parts = split(':',$line); my $dn = decode_base64($parts[2]); print ("! $dn is supposed to be admin but does not exists\n"); } if (ask_yn_question("No valid admin account found, do you want to create it ?")) { return add_ldap_admin($base, $ldap, \@dns, $people_entries); } } # function that check LDAP configuration sub check_ldap { # initiate the LDAP connexion my %hash_ldap_param = get_ldap_connexion(); # LDAP's connection's parameters my $base = $hash_ldap_param{base}; my $ldap = $hash_ldap_param{ldap}; # search for branch people my $people = $ldap->search (base => $base, filter => $peopleou); # stock search results my @people_entries = $people->entries; my $admin_add = ""; # if ou=people exists if ( defined ($people_entries[0]) ) { @people_entries = map {$_->dn} @people_entries; check_admin($base, $ldap, \@people_entries); # if ou=people doesn't exists } else { print ( "! $peopleou,$base not found in your LDAP directory\n" ); # if user's answer is "yes", creating ou=people branch if ( ask_yn_question("Do you want to create it ?: ") ) { my $people_add = $ldap->add( "$peopleou,$base", attr => [ 'ou' => $oupeople, 'objectClass' => 'organizationalUnit' ] ); $people_add->code and warn "! failed to add LDAP's $peopleou,$base branch\n"; $admin_add = add_ldap_admin($base, $ldap); return -1 if ($admin_add eq "-1"); } else { print ("Skiping...\n"); } } # search for ou=groups my $ldap_groups = $ldap->search ( base => $base, filter => "ou=groups" ); my @groups_entries = $ldap_groups->entries; # if ou=groups don't exists if ( !defined $groups_entries[0] ) { print ("! ou=groups,$base not found in your LDAP directory\n"); # if user's answer is "yes", creating ou=groups branch if ( ask_yn_question("Do you want to create it ?: ") ) { my $group_add = $ldap->add( "ou=groups,$base", attr => [ 'ou' => 'groups', 'objectClass' => 'organizationalUnit' ] ); $group_add->code and warn "! failed to add LDAP's ou=groups,$base branch\n"; } else { print ("skiping...\n"); } } # search for workstations and object groups my $faiclasses = $ldap->search (base => "$base", filter => "(&(FAIclass=*)(!(objectClass~=FAIprofile)))" ); my @faiclass_entries = $faiclasses->entries; foreach my $entry (@faiclass_entries) { my $faiclass = $entry->get_value('FAIclass'); my (@profiles) = split(' ',$faiclass); if (scalar @profiles > 2) { print "! System or group ".$entry->get_value('cn')." have more than one FAI profile : ".$faiclass."\n"; } elsif (scalar @profiles < 2) { print "! System or group ".$entry->get_value('cn')." have no release set in its FAIclass : ".$faiclass."\n"; } } # unbind to the LDAP server my $unbind = $ldap->unbind; $unbind->code && warn "! Unable to unbind from LDAP server: ", $unbind->error."\n"; } # function that migrate old FAI repos sub migrate_repo { # initiate the LDAP connexion my %hash_ldap_param = get_ldap_connexion(); # LDAP's connection's parameters my $base = $hash_ldap_param{base}; my $ldap = $hash_ldap_param{ldap}; # search for FAI repository server my $fai_repo = $ldap->search (base => $base, filter => "(&(FAIrepository=*)(objectClass=FAIrepositoryServer))"); # stock search's results my @fai_entries = $fai_repo->entries; foreach my $repoServer (@fai_entries) { # retrieve the FAIrepository from the LDAP object my $ref_FAIrepo = $repoServer->get_value('fairepository', asref=>1); my @repos; # foreach FAIrepository of the LDAP object foreach my $repo (@{$ref_FAIrepo}) { my (@items) = split('\|',$repo); # Unless the FAIrepository has already been migrated if (scalar @items < 5) { print "modifying $repo\n"; push @repos, $repo."|install|local|i386"; } elsif (scalar @items < 6) { print "repository $repo seems malformed\n"; push @repos, $repo; } elsif (scalar @items < 7) { print "modifying $repo\n"; push @repos, $repo."|i386"; } else { print "keeping $repo\n"; push @repos, $repo; } } my $modify = $ldap->modify ($repoServer->dn, replace => [ FAIrepository => \@repos]); $modify->code && warn "! Unable to modify FAI repositories for ".$repoServer->dn." : ".$modify->error."\n"; } # unbind to the LDAP server my $unbind = $ldap->unbind; $unbind->code && warn "! Unable to unbind from LDAP server: ", $unbind->error."\n"; } # function that create a directory and copy plugin files in it sub create_and_copy_plugin_dir { my ($plugin_dir,$dest_dir) = @_; if ( -e $plugin_dir ){ my $dir = dir ($dest_dir); $dir->mkpath() or warn ("! Unable to make ".$dest_dir."\n") if ( !-e $dest_dir); my $files_dirs_copied = rcopy($plugin_dir."/*", $dest_dir); } } # function that install all the FD's plugins from a directory sub install_plugins { # ask for the plugins archive my $plugins_archive = ask_user_input ("Where is your plugins archive ?"); die ("! ".$plugins_archive." doesn't exists") if (!-e $plugins_archive); # check the archive format $plugins_archive =~ /^.*\/(.*).tar.gz$/; my $name = $1 or die ("! Unkwnow archive $plugins_archive"); # where the extract files will go my $tmp_plugins_dir = "/tmp"; print ("Installing plugins into $vars{fd_home}, please wait...\n"); my $dir = dir ($tmp_plugins_dir."/".$name); # extract the plugins archive my $archive = Archive::Extract->new (archive => $plugins_archive); my $extract = $archive->extract( to => "$tmp_plugins_dir" ) or die ("! Unable to extract $plugins_archive\n"); my @plugins = $dir->children; chdir ($dir) or die ("! Unable to move to $dir\n"); foreach my $plugin_path (@plugins){ $plugin_path =~ /^$tmp_plugins_dir\/$name\/(.*)$/; my $plugin = $1; # copy addons into plugins create_and_copy_plugin_dir($plugin_path."/addons/",$vars{fd_home}."/plugins/addons/"); # copy admin into plugins create_and_copy_plugin_dir($plugin_path."/admin/",$vars{fd_home}."/plugins/admin/"); # copy personal into plugins create_and_copy_plugin_dir($plugin_path."/personal/",$vars{fd_home}."/plugins/personal/"); # copy extra HTML and images create_and_copy_plugin_dir($plugin_path."/html/",$vars{fd_home}."/html/plugins/".$plugin); # copy contrib create_and_copy_plugin_dir($plugin_path."/contrib/",$vars{fd_home}."/doc/contrib/".$plugin); # copy etc FIXME !!! not right all files goes now to /var/cache/fusiondirectory/plugin #my $files_dirs_copied = rcopy($plugin_path."/etc/*", $vars{fd_config_dir}); # copy the locales create_and_copy_plugin_dir($plugin_path."/locale/",$vars{fd_home}."/locale/plugins/".$plugin); } #finally update FusionDirectory's class.cache and locales rescan_classes(); rescan_i18n(); } # function that add object classes to people branch users sub migrate_users { my $scope="one"; # initiate the LDAP connexion my %hash_ldap_param = get_ldap_connexion(); # LDAP's connection's parameters my $base = $hash_ldap_param{base}; my $ldap = $hash_ldap_param{ldap}; print ("Add FusionDirectory attributes for the following users from $peopleou,$base\n"); print ("---------------------------------------------\n"); my $mesg = $ldap->search( filter=>"(|(!(objectClass~=gosaAccount))(!(objectClass~=organizationalPerson))(!(objectClass~=Person)))", base=>"$peopleou,$base", scope=>$scope); my @entries = $mesg->entries; foreach my $entry (@entries) { $mesg = $ldap->modify($entry->dn(), add => { "ObjectClass" => "gosaAccount"}); $mesg = $ldap->modify($entry->dn(), add => { "ObjectClass" => "organizationalPerson"}); $mesg = $ldap->modify($entry->dn(), add => { "ObjectClass" => "Person"}); print $entry->dn(); print "\n"; } # unbind to the LDAP server my $unbind = $ldap->unbind; $unbind->code && warn "! Unable to unbind from LDAP server: ", $unbind->error."\n"; } # function that set useful vars based on user specified folders and files sub set_vars { $fd_config = $vars{fd_config_dir}."/".$vars{config_file}; $locale_dir = $vars{fd_home}."/".$vars{locale_dir}; $class_cache = $vars{fd_cache}."/".$vars{class_cache}; $locale_cache_dir = $vars{fd_cache}."/".$vars{locale_cache_dir}; $tmp_dir = $vars{fd_cache}."/".$vars{tmp_dir}; $fai_log_dir = $vars{fd_cache}."/".$vars{fai_log_dir}; $template_dir = $vars{fd_cache}."/".$vars{template_dir}; my $supann_dir = $vars{fd_cache}."/supann"; my $asterisk_dir = $vars{fd_cache}."/asterisk"; my $systems_dir = $vars{fd_cache}."/systems"; my $mail_dir = $vars{fd_cache}."/mail"; @root_config_dirs = ( $vars{fd_home}, $vars{fd_config_dir} ); @apache_config_dirs = ( $vars{fd_spool_dir}, $vars{fd_cache}, $tmp_dir, $fai_log_dir, $template_dir ); @config_dirs = ( @root_config_dirs, @apache_config_dirs ); } # function that list variables that can be modified by the user sub list_vars { while ( my ($key, $value) = each(%vars) ) { print "$key\t[$value]"."\n"; } } #################### main function ##################### #die if the user is not root die ("! You have to run this script as root\n") if ($<!=0); my @vars_keys = keys %vars; my %commands = (); $commands{"--update-cache"} = ["Updating class.cache", \&rescan_classes]; $commands{"--update-locales"} = ["Updating translations", \&rescan_i18n]; $commands{"--check-directories"} = ["Checking FusionDirectory's directories", \&check_directories]; $commands{"--check-config"} = ["Checking FusionDirectory's config file", \&check_config]; $commands{"--check-ldap"} = ["Checking your LDAP tree", \&check_ldap]; $commands{"--migrate-repositories"} = ["Migrating your FAI repositories", \&migrate_repo]; $commands{"--migrate-users"} = ["Migrating your users", \&migrate_users]; $commands{"--install-plugins"} = ["Installing FusionDirectory's plugins", \&install_plugins]; $commands{"--write-vars"} = ["Choose FusionDirectory Directories", \&write_vars]; $commands{"--list-vars"} = ["List possible vars to give --set", \&list_vars]; $commands{"--set-VAR=value"} = ["Set the variable VAR to value see --list-vars", \&die]; # Won't be called because it contains uppercase my $usage = 0; set_vars(); foreach my $arg ( @ARGV ) { if (( lc($arg) =~ m/^--set-(.*)=(.*)/ ) && (grep {$_ eq lc($1)} @vars_keys)) { $vars{lc($1)} = $2; print "Setting $1 to $2\n"; set_vars(); } elsif ( defined $commands { lc ( $arg ) } ) { my @command = @{ $commands{ $arg } }; print( $command[0]."\n" ); $command[1](); } elsif ( ( lc($arg) eq "--help" ) || ( lc($arg) eq "-h" ) ) { print ( "\nCommands:\n" ); while ( my ( $key,$value ) = each %commands ) { print ( "$key\t".$value->[0]."\n" ); } print ("--yes\t\t\tAlways answer yes to yes/no questions\n"); print ("--help\t\t\tShows this help\n\n"); } elsif (( lc($arg) eq "--yes" ) || ( lc($arg) eq "-y" )) { $yes_flag = 1; } else { print ("\nInvalid argument\n\n"); $usage = 1; } } if( $usage || ( @ARGV <= 0 ) ) { print ( "Usage : $0 [--yes]" ); foreach my $command ( keys ( %commands )) { print ( " [$command]" ); } print "\n\n"; } exit 0; __END__ =head1 NAME fusiondirectory-setup - FusionDirectory setup script =head1 DESCRIPTION This script is designed to perform multiple checks on your FusionDirectory/LDAP architecture, and fix usual misconfiguration. Some extra features allow you to install FusionDirectory's plugins, changes destinations directories, and migrate your old FAIrepositories. =head2 Options =over 4 =item --update-cache This option update the /var/cache/fusiondirectory/class.cache file. Wich contain PHP classes used in FusionDirectory, and their location. =item --update-locales This option update internalization, by generating a new .mo locales file for each language, with every .po files it found. Needs I<msgcat> and I<msgfmt> to be installed. =item --check-directories This option perform a check on all FusionDirectory's files or directories. =item --check-config This option perform a check on FusionDirectory's config file. =item --check-ldap This option check your LDAP tree. Looking for admin account, and groups or people branch. If one of those don't exists, the script will ask you what to do. =item --migrate-repositories This option check the fairepository object in your ldap tree and add the new option for FusionDirectory 1.0.2. =item --migrate-users This option add FusionDirectory attributes to the people branch. =item --install-plugins This option will install the plugin from a tar.gz of the plugin. This option is intended for people wanting to install from the sources. =item --list_vars This option will list the variables you can change to install FusionDirectory on another set of directories. This option is intended for people wanting to install from the sources. =item --set-VAR=variable This option will change the variable for the FusionDirectory installation. it is only usefull with --install-directories and for people installing from sources. =item --write-vars This option will write back the variables.inc file with the updated variables and is only usefull with --set-VAR=variable and for people installing from sources. =item --yes This flag will answer "yes" to every yes/no question asked by the script =back =head1 EXAMPLE benoit@catbert$ fusiondirectory-setup --update-cache --update-locales Update FusionDirectory class cache and update localization benoit@catbert$ fusiondirectory-setup --list-vars List possible vars to give --set locale_cache_dir [locale] config_file [fusiondirectory.conf] fd_cache [/var/cache/fusiondirectory] fd_spool_dir [/var/spool/fusiondirectory] fai_log_dir [fai] tmp_dir [tmp] template_dir [template] locale_dir [locale] fd_config_dir [/etc/fusiondirectory] class_cache [class.cache] fd_home [/var/www/fusiondirectory] benoit@catbert$ fusiondirectory-setup --set-class_cache=class.cache --write-vars update the class.cache name and write back the variables.inc file =head1 BUGS Please report any bugs, or post any suggestions, to the fusiondirectory mailing list fusiondirectory-users or to <https://forge.fusiondirectory.org/projects/fdirectory/issues/new> =head1 AUTHORS Benjamin Carpentier Come Bernigaud =head1 LICENCE AND COPYRIGHT This code is part of FusionDirectory (http://www.fusiondirectory.org/) =over 2 =item Copyright (C) 2011-2013 FusionDirectory =back This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. =cut