blob: fae2105b8b59c56a40074fdc591fe4cd8d2baae1 [file] [log] [blame]
#**************************************************************
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
#**************************************************************
package installer::windows::directory;
use installer::exiter;
use installer::files;
use installer::globals;
use installer::pathanalyzer;
use installer::windows::idtglobal;
use installer::windows::msiglobal;
##############################################################
# Collecting all directory trees in global hash
##############################################################
sub collectdirectorytrees
{
my ( $directoryref ) = @_;
for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
{
my $onedir = ${$directoryref}[$i];
my $styles = "";
if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; }
if ( $styles ne "" )
{
foreach my $treestyle ( keys %installer::globals::treestyles )
{
if ( $styles =~ /\b$treestyle\b/ )
{
my $hostname = $onedir->{'HostName'};
# -> hostname is the key, the style the value!
$installer::globals::hostnametreestyles{$hostname} = $treestyle;
}
}
}
}
}
##############################################################
# Overwriting global programfilesfolder, if required
##############################################################
sub overwrite_programfilesfolder
{
my ( $allvariables ) = @_;
if ( $allvariables->{'PROGRAMFILESFOLDERNAME'} )
{
$installer::globals::programfilesfolder = $allvariables->{'PROGRAMFILESFOLDERNAME'};
}
}
##############################################################
# Maximum length of directory name is 72.
# Taking care of underlines, which are the separator.
##############################################################
sub make_short_dir_version
{
my ($longstring) = @_;
my $shortstring = "";
my $cutlength = 60;
my $length = 5; # So the directory can still be recognized
my $longstring_save = $longstring;
# Splitting the string at each "underline" and allowing only $length characters per directory name.
# Checking also uniqueness and length.
my $stringarray = installer::converter::convert_stringlist_into_array_without_newline(\$longstring, "_");
foreach my $onestring ( @{$stringarray} )
{
my $partstring = "";
if ( $onestring =~ /\-/ )
{
my $localstringarray = installer::converter::convert_stringlist_into_array_without_newline(\$onestring, "-");
foreach my $onelocalstring ( @{$localstringarray} )
{
if ( length($onelocalstring) > $length ) { $onelocalstring = substr($onelocalstring, 0, $length); }
$partstring = $partstring . "-" . $onelocalstring;
}
$partstring =~ s/^\s*\-//;
}
else
{
if ( length($onestring) > $length ) { $partstring = substr($onestring, 0, $length); }
else { $partstring = $onestring; }
}
$shortstring = $shortstring . "_" . $partstring;
}
$shortstring =~ s/^\s*\_//;
# Setting unique ID to each directory
# No counter allowed, process must be absolute reproducable due to patch creation process.
# chomp(my $id = `echo $longstring_save | md5sum | sed -e "s/ .*//g"`); # Very, very slow
# my $subid = substr($id, 0, 9); # taking only the first 9 digits
my $subid = installer::windows::msiglobal::calculate_id($longstring_save, 9); # taking only the first 9 digits
if ( length($shortstring) > $cutlength ) { $shortstring = substr($shortstring, 0, $cutlength); }
$shortstring = $shortstring . "_" . $subid;
return $shortstring;
}
##############################################################
# Adding unique directory names to the directory collection
##############################################################
sub create_unique_directorynames
{
my ($directoryref, $allvariables) = @_;
$installer::globals::officeinstalldirectoryset = 0;
my %completedirhashstep1 = ();
my %shortdirhash = ();
my %shortdirhashreverse = ();
my $infoline = "";
my $errorcount = 0;
for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
{
my $onedir = ${$directoryref}[$i];
my $uniquename = $onedir->{'HostName'};
my $styles = "";
if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; }
$uniquename =~ s/^\s*//g; # removing beginning white spaces
$uniquename =~ s/\s*$//g; # removing ending white spaces
$uniquename =~ s/\s//g; # removing white spaces
$uniquename =~ s/\_//g; # removing existing underlines
$uniquename =~ s/\.//g; # removing dots in directoryname
$uniquename =~ s/OpenOffice/OO/g;
$uniquename =~ s/\Q$installer::globals::separator\E/\_/g; # replacing slash and backslash with underline
$uniquename =~ s/_registry/_rgy/g;
$uniquename =~ s/_registration/_rgn/g;
$uniquename =~ s/_extension/_ext/g;
$uniquename =~ s/_frame/_frm/g;
$uniquename =~ s/_table/_tbl/g;
$uniquename =~ s/_chart/_crt/g;
# The names after this small changes must still be unique!
if ( exists($completedirhashstep1{$uniquename}) ) { installer::exiter::exit_program("ERROR: Error in packaging process. Unallowed modification of directory name, not unique (step 1): \"$uniquename\".", "create_unique_directorynames"); }
$completedirhashstep1{$uniquename} = 1;
# Starting to make unique name for the parent and its directory
my $originaluniquename = $uniquename;
$uniquename = make_short_dir_version($uniquename);
# Checking if the same directory already exists, but has another short version.
if (( exists($shortdirhash{$originaluniquename}) ) && ( $shortdirhash{$originaluniquename} ne $uniquename )) { installer::exiter::exit_program("ERROR: Error in packaging process. Unallowed modification of directory name, not unique (step 2A): \"$uniquename\".", "create_unique_directorynames"); }
# Also checking vice versa
# Checking if the same short directory already exists, but has another long version.
if (( exists($shortdirhashreverse{$uniquename}) ) && ( $shortdirhashreverse{$uniquename} ne $originaluniquename )) { installer::exiter::exit_program("ERROR: Error in packaging process. Unallowed modification of directory name, not unique (step 2B): \"$uniquename\".", "create_unique_directorynames"); }
# Creating assignment from long to short directory names
$shortdirhash{$originaluniquename} = $uniquename;
$shortdirhashreverse{$uniquename} = $originaluniquename;
# Important: The unique parent is generated from the string $originaluniquename (with the use of underlines).
my $uniqueparentname = $originaluniquename;
my $keepparent = 1;
if ( $uniqueparentname =~ /^\s*(.*)\_(.*?)\s*$/ ) # the underline is now the separator
{
$uniqueparentname = $1;
$keepparent = 0;
}
else
{
$uniqueparentname = $installer::globals::programfilesfolder;
$keepparent = 1;
}
if ( $styles =~ /\bPROGRAMFILESFOLDER\b/ )
{
$uniqueparentname = $installer::globals::programfilesfolder;
$keepparent = 1;
}
if ( $styles =~ /\bCOMMONFILESFOLDER\b/ )
{
$uniqueparentname = $installer::globals::commonfilesfolder;
$keepparent = 1;
}
if ( $styles =~ /\bCOMMONAPPDATAFOLDER\b/ )
{
$uniqueparentname = $installer::globals::commonappdatafolder;
$keepparent = 1;
}
if ( $styles =~ /\bLOCALAPPDATAFOLDER\b/ )
{
$uniqueparentname = $installer::globals::localappdatafolder;
$keepparent = 1;
}
if ( $styles =~ /\bSHAREPOINTPATH\b/ )
{
$uniqueparentname = "SHAREPOINTPATH";
$installer::globals::usesharepointpath = 1;
$keepparent = 1;
}
# also setting short directory name for the parent
my $originaluniqueparentname = $uniqueparentname;
if ( ! $keepparent )
{
$uniqueparentname = make_short_dir_version($uniqueparentname);
}
# Again checking if the same directory already exists, but has another short version.
if (( exists($shortdirhash{$originaluniqueparentname}) ) && ( $shortdirhash{$originaluniqueparentname} ne $uniqueparentname )) { installer::exiter::exit_program("ERROR: Error in packaging process. Unallowed modification of directory name, not unique (step 3A): \"$uniqueparentname\".", "create_unique_directorynames"); }
# Also checking vice versa
# Checking if the same short directory already exists, but has another long version.
if (( exists($shortdirhashreverse{$uniqueparentname}) ) && ( $shortdirhashreverse{$uniqueparentname} ne $originaluniqueparentname )) { installer::exiter::exit_program("ERROR: Error in packaging process. Unallowed modification of directory name, not unique (step 3B): \"$uniqueparentname\".", "create_unique_directorynames"); }
$shortdirhash{$originaluniqueparentname} = $uniqueparentname;
$shortdirhashreverse{$uniqueparentname} = $originaluniqueparentname;
# Hyphen not allowed in database
$uniquename =~ s/\-/\_/g; # making "-" to "_"
$uniqueparentname =~ s/\-/\_/g; # making "-" to "_"
# And finally setting the values for the directories
$onedir->{'uniquename'} = $uniquename;
$onedir->{'uniqueparentname'} = $uniqueparentname;
# setting the installlocation directory
if ( $styles =~ /\bISINSTALLLOCATION\b/ )
{
if ( $installer::globals::installlocationdirectoryset ) { installer::exiter::exit_program("ERROR: Directory with flag ISINSTALLLOCATION alread set: \"$installer::globals::installlocationdirectory\".", "create_unique_directorynames"); }
$installer::globals::installlocationdirectory = $uniquename;
$installer::globals::installlocationdirectoryset = 1;
if ( $installer::globals::installlocationdirectory =~ /oracle_/i ) { $installer::globals::sundirexists = 1; }
}
# setting the sundirectory
if ( $styles =~ /\bSUNDIRECTORY\b/ )
{
if ( $installer::globals::vendordirectoryset ) { installer::exiter::exit_program("ERROR: Directory with flag SUNDIRECTORY alread set: \"$installer::globals::vendordirectory\".", "create_unique_directorynames"); }
$installer::globals::vendordirectory = $uniquename;
$installer::globals::vendordirectoryset = 1;
}
}
}
#####################################################
# Adding ":." to selected default directory names
#####################################################
sub check_sourcedir_addon
{
my ( $onedir, $allvariableshashref ) = @_;
if (($installer::globals::addchildprojects) ||
($installer::globals::patch) ||
($installer::globals::languagepack) ||
($allvariableshashref->{'CHANGETARGETDIR'}))
{
my $sourcediraddon = "\:\.";
$onedir->{'defaultdir'} = $onedir->{'defaultdir'} . $sourcediraddon;
}
}
#####################################################
# The directory with the style ISINSTALLLOCATION
# will be replaced by INSTALLLOCATION
#####################################################
sub set_installlocation_directory
{
my ( $directoryref, $allvariableshashref ) = @_;
if ( ! $installer::globals::installlocationdirectoryset ) { installer::exiter::exit_program("ERROR: Directory with flag ISINSTALLLOCATION not set!", "set_installlocation_directory"); }
for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
{
my $onedir = ${$directoryref}[$i];
if ( $onedir->{'uniquename'} eq $installer::globals::installlocationdirectory )
{
$onedir->{'uniquename'} = "INSTALLLOCATION";
check_sourcedir_addon($onedir, $allvariableshashref);
}
if ( $onedir->{'uniquename'} eq $installer::globals::vendordirectory )
{
check_sourcedir_addon($onedir, $allvariableshashref);
}
if ( $onedir->{'uniqueparentname'} eq $installer::globals::installlocationdirectory )
{
$onedir->{'uniqueparentname'} = "INSTALLLOCATION";
}
}
}
#####################################################
# Getting the name of the top level directory. This
# can have only one letter
#####################################################
sub get_last_directory_name
{
my ($completepathref) = @_;
if ( $$completepathref =~ /^.*[\/\\](.+?)\s*$/ )
{
$$completepathref = $1;
}
}
#####################################################
# Creating the defaultdir for the file Director.idt
#####################################################
sub create_defaultdir_directorynames
{
my ($directoryref, $shortdirnamehashref) = @_;
my @shortnames = ();
if ( $installer::globals::updatedatabase ) { @shortnames = values(%{$shortdirnamehashref}); }
elsif ( $installer::globals::prepare_winpatch ) { @shortnames = values(%installer::globals::saved83dirmapping); }
for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
{
my $onedir = ${$directoryref}[$i];
my $hostname = $onedir->{'HostName'};
$hostname =~ s/\Q$installer::globals::separator\E\s*$//;
get_last_directory_name(\$hostname);
# installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$hostname); # making program/classes to classes
my $uniquename = $onedir->{'uniquename'};
my $shortstring;
if (( $installer::globals::updatedatabase ) && ( exists($shortdirnamehashref->{$uniquename}) ))
{
$shortstring = $shortdirnamehashref->{$uniquename};
}
elsif (( $installer::globals::prepare_winpatch ) && ( exists($installer::globals::saved83dirmapping{$uniquename}) ))
{
$shortstring = $installer::globals::saved83dirmapping{$uniquename};
}
else
{
$shortstring = installer::windows::idtglobal::make_eight_three_conform($hostname, "dir", \@shortnames);
}
my $defaultdir;
if ( $shortstring eq $hostname )
{
$defaultdir = $hostname;
}
else
{
$defaultdir = $shortstring . "|" . $hostname;
}
$onedir->{'defaultdir'} = $defaultdir;
my $fontdir = "";
if ( $onedir->{'Dir'} ) { $fontdir = $onedir->{'Dir'}; }
my $fontdefaultdir = "";
if ( $onedir->{'defaultdir'} ) { $fontdefaultdir = $onedir->{'defaultdir'}; }
if (( $fontdir eq "PREDEFINED_OSSYSTEMFONTDIR" ) && ( $fontdefaultdir eq $installer::globals::fontsdirhostname ))
{
$installer::globals::fontsdirname = $onedir->{'defaultdir'};
$installer::globals::fontsdirparent = $onedir->{'uniqueparentname'};
}
}
}
###############################################
# Fill content into the directory table
###############################################
sub create_directorytable_from_collection
{
my ($directorytableref, $directoryref) = @_;
for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
{
my $onedir = ${$directoryref}[$i];
my $hostname = $onedir->{'HostName'};
my $dir = "";
if ( $onedir->{'Dir'} ) { $dir = $onedir->{'Dir'}; }
if (( $dir eq "PREDEFINED_PROGDIR" ) && ( $hostname eq "" )) { next; } # removing files from root directory
my $oneline = $onedir->{'uniquename'} . "\t" . $onedir->{'uniqueparentname'} . "\t" . $onedir->{'defaultdir'} . "\n";
push(@{$directorytableref}, $oneline);
}
}
###############################################
# Defining the root installation structure
###############################################
sub add_root_directories
{
my ($directorytableref, $allvariableshashref) = @_;
# my $sourcediraddon = "";
# if (($installer::globals::addchildprojects) ||
# ($installer::globals::patch) ||
# ($installer::globals::languagepack) ||
# ($allvariableshashref->{'CHANGETARGETDIR'}))
# {
# $sourcediraddon = "\:\.";
# }
my $oneline = "";
if (( ! $installer::globals::patch ) && ( ! $installer::globals::languagepack ) && ( ! $allvariableshashref->{'DONTUSESTARTMENUFOLDER'} ))
{
my $productname = $allvariableshashref->{'PRODUCTNAME'};
my $productversion = $allvariableshashref->{'PRODUCTVERSION'};
my $baseproductversion = $productversion;
if (( $installer::globals::prepare_winpatch ) && ( $allvariableshashref->{'BASEPRODUCTVERSION'} ))
{
$baseproductversion = $allvariableshashref->{'BASEPRODUCTVERSION'}; # for example "2.0" for OOo
}
my $realproductkey = $productname . " " . $productversion;
my $productkey = $productname . " " . $baseproductversion;
if (( $allvariableshashref->{'POSTVERSIONEXTENSION'} ) && ( ! $allvariableshashref->{'DONTUSEEXTENSIONINDEFAULTDIR'} ))
{
$productkey = $productkey . " " . $allvariableshashref->{'POSTVERSIONEXTENSION'};
$realproductkey = $realproductkey . " " . $allvariableshashref->{'POSTVERSIONEXTENSION'};
}
if ( $allvariableshashref->{'NOVERSIONINDIRNAME'} )
{
$productkey = $productname;
$realproductkey = $realproductname;
}
if ( $allvariableshashref->{'NOSPACEINDIRECTORYNAME'} )
{
$productkey =~ s/\ /\_/g;
$realproductkey =~ s/\ /\_/g;
}
my $shortproductkey = installer::windows::idtglobal::make_eight_three_conform($productkey, "dir"); # third parameter not used
$shortproductkey =~ s/\s/\_/g; # changing empty space to underline
$oneline = "$installer::globals::officemenufolder\t$installer::globals::programmenufolder\t$shortproductkey|$realproductkey\n";
push(@{$directorytableref}, $oneline);
}
$oneline = "TARGETDIR\t\tSourceDir\n";
push(@{$directorytableref}, $oneline);
$oneline = "$installer::globals::programfilesfolder\tTARGETDIR\t.\n";
push(@{$directorytableref}, $oneline);
$oneline = "$installer::globals::programmenufolder\tTARGETDIR\t.\n";
push(@{$directorytableref}, $oneline);
$oneline = "$installer::globals::startupfolder\tTARGETDIR\t.\n";
push(@{$directorytableref}, $oneline);
$oneline = "$installer::globals::desktopfolder\tTARGETDIR\t.\n";
push(@{$directorytableref}, $oneline);
$oneline = "$installer::globals::startmenufolder\tTARGETDIR\t.\n";
push(@{$directorytableref}, $oneline);
$oneline = "$installer::globals::commonfilesfolder\tTARGETDIR\t.\n";
push(@{$directorytableref}, $oneline);
$oneline = "$installer::globals::commonappdatafolder\tTARGETDIR\t.\n";
push(@{$directorytableref}, $oneline);
$oneline = "$installer::globals::localappdatafolder\tTARGETDIR\t.\n";
push(@{$directorytableref}, $oneline);
if ( $installer::globals::usesharepointpath )
{
$oneline = "SHAREPOINTPATH\tTARGETDIR\t.\n";
push(@{$directorytableref}, $oneline);
}
$oneline = "$installer::globals::systemfolder\tTARGETDIR\t.\n";
push(@{$directorytableref}, $oneline);
my $localtemplatefoldername = $installer::globals::templatefoldername;
my $directorytableentry = $localtemplatefoldername;
my $shorttemplatefoldername = installer::windows::idtglobal::make_eight_three_conform($localtemplatefoldername, "dir");
if ( $shorttemplatefoldername ne $localtemplatefoldername ) { $directorytableentry = "$shorttemplatefoldername|$localtemplatefoldername"; }
$oneline = "$installer::globals::templatefolder\tTARGETDIR\t$directorytableentry\n";
push(@{$directorytableref}, $oneline);
if ( $installer::globals::fontsdirname )
{
$oneline = "$installer::globals::fontsfolder\t$installer::globals::fontsdirparent\t$installer::globals::fontsfoldername\:$installer::globals::fontsdirname\n";
}
else
{
$oneline = "$installer::globals::fontsfolder\tTARGETDIR\t$installer::globals::fontsfoldername\n";
}
push(@{$directorytableref}, $oneline);
}
###############################################
# Creating the file Director.idt dynamically
###############################################
sub create_directory_table
{
my ($directoryref, $basedir, $allvariableshashref, $shortdirnamehashref, $loggingdir) = @_;
# Structure of the directory table:
# Directory Directory_Parent DefaultDir
# Directory is a unique identifier
# Directory_Parent is the unique identifier of the parent
# DefaultDir is .:APPLIC~1|Application Data with
# Before ":" : [sourcedir]:[destdir] (not programmed yet)
# After ":" : 8+3 and not 8+3 the destination directory name
$installer::logger::Lang->add_timestamp("Performance Info: Directory Table start");
my @directorytable = ();
my $infoline;
overwrite_programfilesfolder($allvariableshashref);
if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforidt_local_1.log", $directoryref); }
create_unique_directorynames($directoryref, $allvariableshashref);
if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforidt_local_1a.log", $directoryref); }
create_defaultdir_directorynames($directoryref, $shortdirnamehashref); # only destdir!
if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforidt_local_2.log", $directoryref); }
set_installlocation_directory($directoryref, $allvariableshashref);
if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforidt_local_3.log", $directoryref); }
installer::windows::idtglobal::write_idt_header(\@directorytable, "directory");
add_root_directories(\@directorytable, $allvariableshashref);
create_directorytable_from_collection(\@directorytable, $directoryref);
# Saving the file
my $directorytablename = $basedir . $installer::globals::separator . "Director.idt";
installer::files::save_file($directorytablename ,\@directorytable);
$installer::logger::Lang->printf("Created idt file: %s\n", $directorytablename);
$installer::logger::Lang->add_timestamp("Performance Info: Directory Table end");
}
1;