diff options
Diffstat (limited to 'solenv/bin')
201 files changed, 74168 insertions, 0 deletions
diff --git a/solenv/bin/_mkout b/solenv/bin/_mkout new file mode 100755 index 000000000000..b1ff7b0f5c89 --- /dev/null +++ b/solenv/bin/_mkout @@ -0,0 +1,11 @@ +#!/bin/sh -e +if [ -z "$1" ]; then + exit 1; +fi +mkdir -p "$1"/bin +mkdir -p "$1"/inc +mkdir -p "$1"/lib +mkdir -p "$1"/misc +mkdir -p "$1"/obj +mkdir -p "$1"/slb +mkdir -p "$1"/slo diff --git a/solenv/bin/addsym-macosx.sh b/solenv/bin/addsym-macosx.sh new file mode 100755 index 000000000000..b69f59fff319 --- /dev/null +++ b/solenv/bin/addsym-macosx.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# This script is needed in the process of generating exported +# symbols list out of map files on Mac OS X (see also #i69351#) +# The magic generating the regular expression from the temporary +# mapfile containing only star and question mark symbols +# +# The script has to be called as follows: +# nm -gx <file>.o | addsym-macosx.sh <file-with-wildcard-symbols> <temporary-file-where-to-write-the-search-expression-to> +# See tg_shl.mk for an example of how to use the script +# +# Replace every * with .* and every ? with . to get awk expression +# Put ^ at the beginning of every expression +# Put $ at the beginning of every expression +# Connect them all on one line, separated by | +# Remove | at the end of this regular expression because the last end +# of line was also replaced by | + +cat $1 | sed 's#*#.*#g +s#?#.#g +s#^#^# +s#$#$#' | tr '\n' '|' | sed "s#|\$##" >$2 + +# Please note that the awk expression expects to get the output of 'nm -gx'! +# On Panther we have to filter out symbols with a value "1f" otherwise external +# symbols will erroneously be added to the generated export symbols list file. +awk -v SYMBOLSREGEXP="`cat $2`" ' +match ($6,SYMBOLSREGEXP) > 0 && $6 !~ /_GLOBAL_/ { if (($2 != 1) && ( $2 != "1f" ) ) print $6 }' + diff --git a/solenv/bin/addsym-mingw.sh b/solenv/bin/addsym-mingw.sh new file mode 100644 index 000000000000..f59dbf5e64b7 --- /dev/null +++ b/solenv/bin/addsym-mingw.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# This script is needed in the process of generating exported +# symbols list out of map files on MinGW +# The magic generating the regular expression from the temporary +# mapfile containing only star and question mark symbols +# +# The script has to be called as follows: +# nm -gx <file>.o | addsym-mingw.sh <file-with-wildcard-symbols> <temporary-file-where-to-write-the-search-expression-to> +# See tg_shl.mk for an example of how to use the script +# +# Replace every * with .* and every ? with . to get awk expression +# Remove whitespaces and comments in expression +# Put ^ at the beginning of every expression +# Put $ at the beginning of every expression +# Connect them all on one line, separated by | +# Remove | at the end of this regular expression because the last end +# of line was also replaced by | + +if [ -s $1 ] +then +cat $1 | sed 's#*#.*#g +s#?#.#g +s#;.*##g +s# ##g +s# ##g +s#^#^# +s#$#$#' | tr '\n' '|' | sed "s#|\$##" >$2 + +# Please note that the awk expression expects to get the output of 'nm -gP'! +awk -v SYMBOLSREGEXP="`cat $2`" ' +match (substr ($1,2) ,SYMBOLSREGEXP) > 0 { print substr ($1,2) ";" }' +fi + diff --git a/solenv/bin/addsym.awk b/solenv/bin/addsym.awk new file mode 100644 index 000000000000..b9a1e6e18f66 --- /dev/null +++ b/solenv/bin/addsym.awk @@ -0,0 +1,57 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: header.hxx,v $ +# +# $Revision: 1.1 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +# Add symbol patterns _ZTI* and _ZTS* to the global section of version UDK_3_0_0 +# (and if that version is not yet present, add it). For C++ exception handling +# to work across libraries, it is important that all libraries use those symbols +# with the same version name. +# +# The below code fails with 'perverted' mapfiles (using a strange line layout, +# or containing version UDK_3_0_0 without a global section, ...). + +BEGIN { state = 0 } +END { + if (state == 0) { + print "# Weak RTTI symbols for C++ exceptions:" + print "UDK_3_0_0 {" + print "\tglobal:" + print "\t_ZTI*; _ZTS*;" + print "};" + } +} +state == 2 { + print " _ZTI*; _ZTS*; # weak RTTI symbols for C++ exceptions" + state = 3 +} +# #i66636# - ??? +/^[\t ]*UDK_3_0_0[\t ]*\{/ { state = 1 } +/^[\t ]*global[\t ]*:/ && state == 1 { state = 2 } +{ print } diff --git a/solenv/bin/build.pl b/solenv/bin/build.pl new file mode 100644 index 000000000000..13dde7bb0691 --- /dev/null +++ b/solenv/bin/build.pl @@ -0,0 +1,3228 @@ +: + eval 'exec perl -S $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: build.pl,v $ +# +# $Revision: 1.171 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +# +# build - build entire project +# + use Config; + use POSIX; + use Cwd qw (cwd); + use File::Path; + use File::Temp qw(tmpnam); + use File::Find; + use Socket; + use IO::Socket::INET; + + use lib ("$ENV{SOLARENV}/bin/modules"); + + my $in_so_env = 0; + if (defined $ENV{COMMON_ENV_TOOLS}) { + unshift(@INC, "$ENV{COMMON_ENV_TOOLS}/modules"); + $in_so_env++; + }; + if (defined $ENV{CWS_WORK_STAMP}) { + require GenInfoParser; import GenInfoParser; + require IO::Handle; import IO::Handle; + }; + my $enable_multiprocessing = 1; + my $cygwin = 0; + $cygwin++ if ($^O eq 'cygwin'); + if ($ENV{GUI} eq 'WNT' && !$cygwin) { + eval { require Win32::Process; import Win32::Process; }; + $enable_multiprocessing = 0 if ($@); + }; + + ### for XML file format + eval { require XMLBuildListParser; import XMLBuildListParser; }; + if (!$@) { + $enable_xml = 1; + @modes_array = split('\s' , $ENV{BUILD_TYPE}); + }; +#### script id ##### + + ( $script_name = $0 ) =~ s/^.*\b(\w+)\.pl$/$1/; + + $id_str = ' $Revision$ '; + $id_str =~ /Revision:\s+(\S+)\s+\$/ + ? ($script_rev = $1) : ($script_rev = "-"); + + print "$script_name -- version: $script_rev\n"; + +######################### +# # +# Globale Variablen # +# # +######################### + + $modules_number++; + $perl = ""; + $remove_command = ""; + if ( $^O eq 'MSWin32' ) { + $perl = "$ENV{PERL}"; + $remove_command = "rmdir /S /Q"; + $nul = '> NULL'; + } else { + use Cwd 'chdir'; + $perl = 'perl'; + $remove_command = 'rm -rf'; + $nul = '> /dev/null'; + }; + + $QuantityToBuild = 0; +# delete $pid when not needed + %projects_deps_hash = (); # hash of projects with no dependencies, + # that could be built now + %broken_build = (); # hash of hashes of the modules, + # where build was broken (error occurred) + %folders_hashes = (); + %running_children = (); + $dependencies_hash = 0; + $cmd_file = ''; + $BuildAllParents = 0; + $show = 0; + $checkparents = 0; + $deliver = 0; + $pre_custom_job = ''; + $custom_job = ''; + $post_custom_job = ''; + %LocalDepsHash = (); + %BuildQueue = (); + %PathHash = (); + %PlatformHash = (); + %AliveDependencies = (); + %global_deps_hash = (); # hash of dependencies of the all modules + %broken_modules_hashes = (); # hash of modules hashes, which cannot be built further + @broken_modules_names = (); # array of modules, which cannot be built further + @dmake_args = (); + %dead_parents = (); + $CurrentPrj = ''; + $no_projects = 0; + $only_dependent = 0; + $build_from = ''; + $build_all_cont = ''; + $build_since = ''; + $dlv_switch = ''; + $child = 0; + %processes_hash = (); +# %module_announced = (); + $prepare = ''; # prepare for following incompatible build + $ignore = ''; + $html = ''; + @ignored_errors = (); + %incompatibles = (); + $only_platform = ''; # the only platform to prepare + $only_common = ''; # the only common output tree to delete when preparing + %build_modes = (); + $maximal_processes = 0; # the max number of the processes run + %modules_types = (); # modules types ('mod', 'img', 'lnk') hash + %platforms = (); # platforms available or being working with + %platforms_to_copy = (); # copy output trees for the platforms when --prepare + $tmp_dir = get_tmp_dir(); # temp directory for checkout and other actions +# $dmake_batch = undef; # + @possible_build_lists = ('build.lst', 'build.xlist'); # build lists names + %build_list_paths = (); # build lists names + %build_lists_hash = (); # hash of arrays $build_lists_hash{$module} = \($path, $xml_list_object) + $pre_job = 'announce'; # job to add for not-single module build + $post_job = ''; # -"- + %windows_procs = (); + @warnings = (); # array of warnings to be shown at the end of the process + @errors = (); # array of errors to be shown at the end of the process + %html_info = (); # hash containing all necessary info for generating of html page + %module_by_hash = (); # hash containing all modules names as values and correspondent hashes as keys + %build_in_progress = (); # hash of modules currently being built + %build_is_finished = (); # hash of already built modules + %modules_with_errors = (); # hash of modules with build errors + %build_in_progress_shown = (); # hash of modules being built, + # and shown last time (to keep order) + $build_time = time; + $html_last_updated = 0; + %jobs_hash = (); + $html_path = undef; + $html_file = CorrectPath($ENV{SRC_ROOT} . '/' . $ENV{INPATH}. '.build.html'); + $build_finished = 0; + %had_error = (); # hack for misteriuos windows problems - try run dmake 2 times if first time there was an error + $mkout = CorrectPath("$ENV{SOLARENV}/bin/mkout.pl"); + %weights_hash = (); # hash contains info about how many modules are dependent from one module +# %weight_stored = (); + $grab_output = 1; + $stop_build_on_error = 0; # for multiprocessing mode: do not build further module if there is an error + $server_mode = 0; + $setenv_string = ''; # string for configuration of the client environment + $ports_string = ''; # string with possible ports for server + @server_ports = (); + $socket_obj = undef; # socket object for server + my %clients_jobs = (); + my %clients_times = (); + my $client_timeout = 0; # time for client to build (in sec)... + # The longest time period after that + # the server considered as an error/client crash + my %lost_client_jobs = (); # hash containing lost jobs + my %job_jobdir = (); # hash containing job-dir pairs +### main ### + + get_options(); + + $html_file = CorrectPath($html_path . '/' . $ENV{INPATH}. '.build.html') if (defined $html_path); +# my $temp_html_file = CorrectPath($tmp_dir. '/' . $ENV{INPATH}. '.build.html'); + get_build_modes(); + %deliver_env = (); + if ($prepare) { + get_platforms(\%platforms); + @modules_built = (); + + $deliver_env{'BUILD_SOSL'}++; + $deliver_env{'COMMON_OUTDIR'}++; + $deliver_env{'GUI'}++; + $deliver_env{'INPATH'}++; + $deliver_env{'OFFENV_PATH'}++; + $deliver_env{'OUTPATH'}++; + $deliver_env{'L10N_framework'}++; + }; + + $StandDir = get_stand_dir(); # This also sets $CurrentPrj + provide_consistency() if (defined $ENV{CWS_WORK_STAMP} && defined($ENV{COMMON_ENV_TOOLS})); + + $deliver_command = $ENV{DELIVER}; + $deliver_command .= ' '. $dlv_switch if ($dlv_switch); + $ENV{mk_tmp}++; + %prj_platform = (); + $check_error_string = ''; + $dmake = ''; +# $dmake_bin = ''; + $dmake_args = ''; + $echo = ''; + $new_line = "\n"; + + get_commands(); + unlink ($cmd_file); + if ($cmd_file) { + if (open (CMD_FILE, ">>$cmd_file")) { + select CMD_FILE; + $echo = 'echo '; + if ($ENV{GUI} ne 'UNX') { + $new_line = "echo.\n"; + print "\@$echo off\npushd\n"; + } else { + $new_line = $echo."\"\"\n"; + }; + } else { + print_error ("Cannot open file $cmd_file"); + }; +# } elsif ($show) { +# select STDOUT; + }; + + print $new_line; + + if ($checkparents) { + GetParentDeps( $CurrentPrj, \%global_deps_hash ); + } else { + BuildAll(); + } + if (scalar keys %broken_build) { + cancel_build(); +# } elsif (!$custom_job && $post_custom_job) { +# do_post_custom_job(CorrectPath($StandDir.$CurrentPrj)); + }; + if (scalar @warnings) { + print STDERR $_ foreach (@warnings); + }; + if (scalar keys %dead_parents) { + my ($DeadPrj); + print $new_line.$new_line; + print $echo."WARNING! Project(s):\n"; + foreach $DeadPrj (keys %dead_parents) { + print $echo."$DeadPrj\n"; + }; + print $new_line; + print $echo."not found and couldn't be built. Dependencies on that module(s) ignored. Maybe you should correct build lists.\n"; + print $new_line; + do_exit(1) if ($checkparents); + }; + if (($ENV{GUI} ne 'UNX') && $cmd_file) { + print "popd\n"; + }; + $ENV{mk_tmp} = ''; + if ($cmd_file) { + close CMD_FILE; + print STDOUT "Script $cmd_file generated\n"; + }; + if ($ignore && scalar @ignored_errors) { + print STDERR "\nERROR: next directories could not be built:\n"; + foreach (@ignored_errors) { + print STDERR "\t$_\n"; + }; + print STDERR "\nERROR: please check these directories and build the corresponding module(s) anew!!\n\n"; + do_exit(1); + }; + do_exit(0); + + +######################### +# # +# Procedures # +# # +######################### + +# +# procedure retrieves build list path +# (all possibilities are taken into account) +# +sub get_build_list_path { + my $module = shift; + my @possible_dirs = ($module, $module. '.lnk', $module. '.link'); + return $build_list_paths{$module} if (defined $build_list_paths{$module}); + foreach (@possible_dirs) { + my $possible_dir_path = $StandDir.$_.'/prj/'; + if (-d $possible_dir_path) { + foreach my $build_list (@possible_build_lists) { + my $possible_build_list_path = CorrectPath($possible_dir_path . $build_list); + if (-f $possible_build_list_path) { + $build_list_paths{$module} = $possible_build_list_path; + return $possible_build_list_path; + }; + } + print_error("There's no build list for $module"); + }; + }; + $dead_parents{$module}++; + $build_list_paths{$module} = CorrectPath(retrieve_build_list($module)); + return $build_list_paths{$module}; +}; + +# +# Get dependencies hash of the current and all parent projects +# +sub GetParentDeps { + my (%parents_deps_hash, $module, $parent); + my $prj_dir = shift; + my $deps_hash = shift; + my @UnresolvedParents = get_parents_array($prj_dir); + $parents_deps_hash{$_}++ foreach (@UnresolvedParents); + $$deps_hash{$prj_dir} = \%parents_deps_hash; + while ($module = pop(@UnresolvedParents)) { + my %parents_deps_hash = (); + $parents_deps_hash{$_}++ foreach (get_parents_array($module)); + $$deps_hash{$module} = \%parents_deps_hash; + foreach $Parent (keys %parents_deps_hash) { + if (!defined($$deps_hash{$Parent})) { + push (@UnresolvedParents, $Parent); + }; + }; + }; + check_deps_hash($deps_hash); +}; + +sub store_weights { + my $deps_hash = shift; + foreach (keys %$deps_hash) { + foreach my $module_deps_hash ($$deps_hash{$_}) { + foreach my $dependency (keys %$module_deps_hash) { + $weights_hash{$dependency}++; + }; + }; + }; +}; + +# +# This procedure implements complete in-depth weights search +# it's working, but very slow, so switched off in favor of the +# last (simplified) implementation... +# +#sub store_weights { +# my $deps_hash = shift; +# $weights_hash{$_} = {} foreach (keys %$deps_hash); +# foreach (keys %$deps_hash) { +# foreach my $module_deps_hash ($$deps_hash{$_}) { +# foreach my $dependency (keys %$module_deps_hash) { +# ${$weights_hash{$dependency}}{$_}++; +# }; +# }; +# }; +# my $current_prj_preq = $$deps_hash{$CurrentPrj}; +# foreach (keys %$current_prj_preq) { +# accumulate_weights($deps_hash, $_); +# }; +#}; + +#sub accumulate_weights { +# my ($deps_hash, $module) = @_; +# my @prerequisites = keys %{$$deps_hash{$module}}; +# my @is_prereq_for = keys %{$weights_hash{$module}}; +# foreach my $prereq_module (@prerequisites) { +## next if (defined $weight_stored{$prereq_module}); +## $weight_stored{$prereq_module}++; +# ${$weights_hash{$prereq_module}}{$_}++ foreach @is_prereq_for; +# accumulate_weights($deps_hash, $prereq_module); +# }; +#}; + +# +# Build everything that should be built +# +sub BuildAll { + if ($BuildAllParents) { + my ($Prj, $PrjDir, $orig_prj); + GetParentDeps( $CurrentPrj, \%global_deps_hash); + modules_classify(keys %global_deps_hash); + store_weights(\%global_deps_hash); + prepare_build_from(\%global_deps_hash) if ($build_from); + prepare_incompatible_build(\%global_deps_hash) if ($incompatible); + if ($build_all_cont || $build_since) { + prepare_build_all_cont(\%global_deps_hash); + }; + $modules_number = scalar keys %global_deps_hash; + initialize_html_info($_) foreach (keys %global_deps_hash); + if ($QuantityToBuild) { + build_multiprocessing(); + return; + }; + if ($server_mode) { + run_server(); + }; + while ($Prj = PickPrjToBuild(\%global_deps_hash)) { + if (!defined $dead_parents{$Prj}) { + if (scalar keys %broken_build) { + print $echo . "Skipping project $Prj because of error(s)\n"; + RemoveFromDependencies($Prj, \%global_deps_hash); + $build_is_finished{$Prj}++; + next; + }; + + $PrjDir = CorrectPath($StandDir.$Prj); + get_deps_hash($Prj, \%LocalDepsHash); + my $info_hash = $html_info{$Prj}; + $$info_hash{DIRS} = check_deps_hash(\%LocalDepsHash, $Prj); + $module_by_hash{\%LocalDepsHash} = $Prj; + BuildDependent(\%LocalDepsHash); + print $check_error_string; + }; + + RemoveFromDependencies($Prj, \%global_deps_hash); + $build_is_finished{$Prj}++; + $no_projects = 0; + }; + } else { + store_build_list_content($CurrentPrj); + get_deps_hash($CurrentPrj, \%LocalDepsHash); + initialize_html_info($CurrentPrj); + my $info_hash = $html_info{$CurrentPrj}; + $$info_hash{DIRS} = check_deps_hash(\%LocalDepsHash, $CurrentPrj); + $module_by_hash{\%LocalDepsHash} = $CurrentPrj; + if ($server_mode) { + run_server(); + } else { + BuildDependent(\%LocalDepsHash); + }; + }; +}; + +sub initialize_html_info { + my $module = shift; + return if (defined $dead_parents{$module}); + $html_info{$module} = { 'DIRS' => [], + 'ERRORFUL' => [], + 'SUCCESSFUL' => [], + 'BUILD_TIME' => 0}; +} + +# +# Do job +# +sub dmake_dir { + my ($new_BuildDir, $OldBuildDir, $error_code); + my $BuildDir = shift; + $jobs_hash{$BuildDir}->{START_TIME} = time(); + $jobs_hash{$BuildDir}->{STATUS} = 'building'; + if ($BuildDir =~ /(\s)/o) { + $error_code = do_custom_job($BuildDir, \%LocalDepsHash); +# do_pre_job($`, $pre_job) if ($' eq $pre_job); +# $error_code = do_post_job($`, $', \%LocalDepsHash) if ($' eq $post_job); +# RemoveFromDependencies($BuildDir, \%LocalDepsHash); +# html_store_job_info(\%LocalDepsHash, $BuildDir, $error_code); + } else { + html_store_job_info(\%LocalDepsHash, $BuildDir); + print_error("$BuildDir not found!!\n") if (!-d $BuildDir); + if (!-d $BuildDir) { + $new_BuildDir = $BuildDir; + $new_BuildDir =~ s/_simple//g; + if ((-d $new_BuildDir)) { + print("\nTrying $new_BuildDir, $BuildDir not found!!\n"); + $BuildDir = $new_BuildDir; + } else { + print_error("\n$BuildDir not found!!\n"); + } + } + if ($cmd_file) { + print "cd $BuildDir\n"; + print $check_error_string; + print $echo.$BuildDir."\n"; + print "$dmake\n"; + print $check_error_string; + } else { + print "$BuildDir\n"; + }; + RemoveFromDependencies($BuildDir, \%LocalDepsHash) if (!$child); + return if ($cmd_file || $show); + $error_code = run_job($dmake, $BuildDir); +# chdir $BuildDir; +# getcwd(); +# if ($html) { +# my $log_file = $jobs_hash{$BuildDir}->{LONG_LOG_PATH}; +# my $log_dir = File::Basename::dirname($log_file); +# if (!-d $log_dir) { +# system("$perl $mkout"); +# }; +# $error_code = system ("$dmake > $log_file 2>&1"); +# if (!$grab_output && -f $log_file) { +# system("cat $log_file"); +# }; +# } else { +# $error_code = system ("$dmake"); +# }; + + html_store_job_info(\%LocalDepsHash, $BuildDir, $error_code) if (!$child); + }; + if ($error_code && $ignore) { + push(@ignored_errors, $BuildDir); + $error_code = 0; + }; + if ($child) { + my $oldfh = select STDERR; + $| = 1; + select $oldfh; + $| =1; + if ($error_code) { + _exit($error_code >> 8); + } else { + _exit($? >> 8) if ($? && ($? != -1)); + }; + _exit(0); + } elsif ($error_code && ($error_code != -1)) { + print_error("Error $? occurred while making $BuildDir"); + }; +}; + +# +# Procedure stores information about build list (and) +# build list object in build_lists_hash +# +sub store_build_list_content { + my $module = shift; + my $build_list_path = get_build_list_path($module); + return undef if (!defined $build_list_path); + return if (!$build_list_path); + my $xml_list = undef; + if ($build_list_path =~ /\.xlist$/o) { + print_error("XMLBuildListParser.pm couldn\'t be found, so XML format for build lists is not enabled") if (!defined $enable_xml); + $xml_list = XMLBuildListParser->new(); + if (!$xml_list->loadXMLFile($build_list_path)) { + print_error("Cannot use $build_list_path"); + }; + $build_lists_hash{$module} = $xml_list; + } else { + if (open (BUILD_LST, $build_list_path)) { + my @build_lst = <BUILD_LST>; + $build_lists_hash{$module} = \@build_lst; + close BUILD_LST; + return; + } + $dead_parents{$module}++; + }; +} +# +# Get string (list) of parent projects to build +# +sub get_parents_array { + my $module = shift; + store_build_list_content($module); + my $build_list_ref = $build_lists_hash{$module}; + + if (ref($build_list_ref) eq 'XMLBuildListParser') { + return $build_list_ref->getModuleDependencies(\@modes_array); + }; + foreach (@$build_list_ref) { + if ($_ =~ /#/) { + if ($`) { + $_ = $`; + } else { + next; + }; + }; + s/\r\n//; + if ($_ =~ /\:+\s+/) { + return pick_for_build_type($'); + }; + }; + return (); +}; + +# +# get folders' platform infos +# +sub get_prj_platform { + my $build_list_ref = shift; + my ($prj_alias, $line); + foreach(@$build_list_ref) { + s/\r\n//; + $line++; + if ($_ =~ /\snmake\s/) { + if ($' =~ /\s*-\s+(\w+)[,\S+]*\s+(\S+)/ ) { + my $platform = $1; + my $alias = $2; + print_error ("There is no correct alias set in the line $line!") if ($alias eq 'NULL'); + mark_platform($alias, $platform); + } else { + print_error("Misspelling in line: \n$_"); + }; + }; + }; +#seek(BUILD_LST, 0, 0); +}; + +# +# Procedure populate the dependencies hash with +# information from XML build list object +# +sub get_deps_from_object { + my ($module, $build_list_object, $dependencies_hash) = @_; + + foreach my $dir ($build_list_object->getJobDirectories("make", $ENV{GUI})) { + $PathHash{$dir} = $StandDir . $module; + $PathHash{$dir} .= $dir if ($dir ne '/'); + my %deps_hash = (); + + foreach my $dep ($build_list_object->getJobDependencies($dir, "make", $ENV{GUI})) { + $deps_hash{$dep}++; + }; + $$dependencies_hash{$dir} = \%deps_hash; + }; +}; + + +# +# Getting hashes of all internal dependencies and additional +# information for given project +# +sub get_deps_hash { + my ($dummy, $module_to_build); + %DeadDependencies = (); + $module_to_build = shift; + my $dependencies_hash = shift; + if ($custom_job) { + if ($modules_types{$module_to_build} ne 'lnk') { + add_prerequisite_job($dependencies_hash, $module_to_build, $pre_custom_job); + add_prerequisite_job($dependencies_hash, $module_to_build, $pre_job); + add_dependent_job($dependencies_hash, $module_to_build, $custom_job); + add_dependent_job($dependencies_hash, $module_to_build, $post_job); + add_dependent_job($dependencies_hash, $module_to_build, $post_custom_job); + }; + return; + }; + if ( defined $modules_types{$module_to_build} && $modules_types{$module_to_build} ne 'mod') { + add_prerequisite_job($dependencies_hash, $module_to_build, $pre_job); + return; + }; + + my $build_list_ref = $build_lists_hash{$module_to_build}; + delete $build_lists_hash{$module_to_build}; + if (ref($build_list_ref) eq 'XMLBuildListParser') { + get_deps_from_object($module_to_build, $build_list_ref, $dependencies_hash); + } else { + get_prj_platform($build_list_ref); + foreach (@$build_list_ref) { + if ($_ =~ /#/o) { + next if (!$`); + $_ = $`; + }; + s/\r\n//; + if ($_ =~ /\s+nmake\s+/o) { + my ($Platform, $Dependencies, $Dir, $DirAlias); + my %deps_hash = (); + $Dependencies = $'; + $dummy = $`; + $dummy =~ /(\S+)\s+(\S*)/o; + $Dir = $2; + $Dependencies =~ /(\w+)/o; + $Platform = $1; + $Dependencies = $'; + while ($Dependencies =~ /,(\w+)/o) { + $Dependencies = $'; + }; + $Dependencies =~ /\s+(\S+)\s+/o; + $DirAlias = $1; + if (!CheckPlatform($Platform)) { + next if (defined $PlatformHash{$DirAlias}); + $DeadDependencies{$DirAlias}++; + next; + }; + delete $DeadDependencies{$DirAlias} if (defined $DeadDependencies{$DirAlias}); + print_error("Directory alias $DirAlias is defined at least twice!! Please, correct build.lst in module $module_to_build") if (defined $$dependencies_hash{$DirAlias}); + $PlatformHash{$DirAlias}++; + $Dependencies = $'; + print_error("$module_to_build/prj/build.lst has wrongly written dependencies string:\n$_\n") if (!$Dependencies); + $deps_hash{$_}++ foreach (GetDependenciesArray($Dependencies)); + $$dependencies_hash{$DirAlias} = \%deps_hash; + $BuildQueue{$DirAlias}++; + if ($Dir =~ /(\\|\/)/o) { + $Dir = $module_to_build . $1 . $'; + } else {$Dir = $module_to_build;}; + $PathHash{$DirAlias} = CorrectPath($StandDir . $Dir); + } elsif ($_ !~ /^\s*$/ && $_ !~ /^\w*\s/o) { + chomp; + push(@errors, $_); + }; + }; + if (scalar @errors) { + my $message = "$module_to_build/prj/build.lst has wrongly written string(s):\n"; + $message .= "$_\n" foreach(@errors); + if ($QuantityToBuild) { + $broken_build{$module_to_build} = $message; + $dependencies_hash = undef; + return; + } else { + print_error($message); + }; + }; + foreach my $alias (keys %DeadDependencies) { + next if defined $AliveDependencies{$alias}; + if (!IsHashNative($alias)) { + RemoveFromDependencies($alias, $dependencies_hash); + delete $DeadDependencies{$alias}; + }; + }; + }; +# check_deps_hash($dependencies_hash); + resolve_aliases($dependencies_hash, \%PathHash); + if (!$prepare) { + add_prerequisite_job($dependencies_hash, $module_to_build, $pre_custom_job); + add_prerequisite_job($dependencies_hash, $module_to_build, $pre_job); + add_dependent_job($dependencies_hash, $module_to_build, $custom_job); + add_dependent_job($dependencies_hash, $module_to_build, $post_job) if ($module_to_build ne $CurrentPrj); + add_dependent_job($dependencies_hash, $module_to_build, $post_custom_job); + }; + store_weights($dependencies_hash); +}; + +# +# procedure adds which is independent from anothers, but anothers are dependent from it +# +sub add_prerequisite_job { + my ($dependencies_hash, $module, $job) = @_; + return if (!$job); + $job = "$module $job"; + foreach (keys %$dependencies_hash) { + $deps_hash = $$dependencies_hash{$_}; + $$deps_hash{$job}++; + }; + $$dependencies_hash{$job} = {}; +}; + +# +# procedure adds a job wich is dependent from all already registered jobs +# +sub add_dependent_job { + # $post_job is dependent from all jobs + my ($dependencies_hash, $module, $job) = @_; + return if (!$job); + my %deps_hash = (); + $deps_hash{$_}++ foreach (keys %$dependencies_hash); + $$dependencies_hash{"$module $job"} = \%deps_hash; +}; + +# +# this procedure converts aliases to absolute paths +# +sub resolve_aliases { + my ($dependencies_hash, $PathHash) = @_; + foreach my $dir_alias (keys %$dependencies_hash) { + my $aliases_hash_ref = $$dependencies_hash{$dir_alias}; + my %paths_hash = (); + foreach (keys %$aliases_hash_ref) { + $paths_hash{$$PathHash{$_}}++; + }; + delete $$dependencies_hash{$dir_alias}; + $$dependencies_hash{$$PathHash{$dir_alias}} = \%paths_hash; + }; +}; + +# +# mark platform in order to prove if alias has been used according to specs +# +sub mark_platform { + my $prj_alias = shift; + if (exists $prj_platform{$prj_alias}) { + $prj_platform{$prj_alias} = 'all'; + } else { + $prj_platform{$prj_alias} = shift; + }; +}; + +# +# Convert path from abstract (with '\' and/or '/' delimiters) +# to system-independent +# +sub CorrectPath { + $_ = shift; + if ( ($^O eq 'MSWin32') && (!defined $ENV{SHELL})) { + s/\//\\/g; + } else {; + s/\\/\//g; + }; + return $_; +}; + + +sub check_dmake { +#print "Checking dmake..."; +# my $dmake_batch = CorrectPath("$tmp_dir/dmake.bat"); + if ($QuantityToBuild && ($ENV{GUI} eq 'WNT') && ($ENV{USE_SHELL} eq '4nt')) { + if (open(DMAKEVERSION, "where dmake |")) { + my @output = <DMAKEVERSION>; + close DMAKEVERSION; + $dmake_bin = $output[0]; + $dmake_bin =~ /(\b)$/; + $dmake_bin = $`; + }; + return if (-e $dmake_bin); + } elsif (open(DMAKEVERSION, "dmake -V |")) { +# if (open(DMAKEVERSION, "dmake -V |")) { + my @dmake_version = <DMAKEVERSION>; + close DMAKEVERSION; +# if ($dmake_version[0] =~ /^dmake\s\-\sCopyright\s\(c\)/) { +# print " Using version $1\n" if ($dmake_version[0] =~ /Version\s(\d+\.*\d*)/); +# }; + return; + }; + my $error_message = 'dmake: Command not found.'; + $error_message .= ' Please rerun bootstrap' if (!defined $ENV{COMMON_ENV_TOOLS}); + print_error($error_message); +}; + +# +# Get platform-dependent commands +# +sub get_commands { + my $arg = ''; + # Setting alias for dmake + $dmake = 'dmake'; + check_dmake(); + + if ($cmd_file) { + if ($ENV{GUI} eq 'UNX') { + $check_error_string = "if \"\$?\" != \"0\" exit\n"; + } else { + $check_error_string = "if \"\%?\" != \"0\" quit\n"; + }; + }; + + $dmake_args = join(' ', 'dmake', @dmake_args); + + while ($arg = pop(@dmake_args)) { + $dmake .= ' '.$arg; + }; +# if (($ENV{GUI} eq 'WNT') && $QuantityToBuild) { +# print_error("There is no such executable $_4nt_exe") if (!-e $_4nt_exe); +# $dmake_batch = generate_4nt_batch(); +# }; +}; + +# +# Procedure prooves if current dir is a root dir of the drive +# +#sub IsRootDir { +# my ($Dir); +# $Dir = shift; +# if ( (($ENV{GUI} eq 'UNX') || +# ($ENV{GUI} eq 'MACOSX')) && +# ($Dir eq '/')) { +# return 1; +# } elsif ( (($ENV{GUI} eq 'WNT') || +# ($ENV{GUI} eq 'WIN') || +# ($ENV{GUI} eq 'OS2')) && +# ($Dir =~ /\S:\/$/)) { +# return 1; +# } else { +# return 0; +# }; +#}; + +# +# Procedure retrieves list of projects to be built from build.lst +# +sub get_stand_dir { + if (!(defined $ENV{GUI})) { + $ENV{mk_tmp} = ''; + die "No environment set\n"; + }; + my $StandDir; +# $StandDir = getcwd(); + if ( defined $ENV{PWD} ) { + $StandDir = $ENV{PWD}; + } elsif (defined $ENV{_cwd}) { + $StandDir = $ENV{_cwd}; + } else { + $StandDir = cwd(); + }; + my $previous_dir = ''; + do { + foreach (@possible_build_lists) {# ('build.lst', 'build.xlist'); + if (-e $StandDir . '/prj/'.$_) { + $StandDir =~ /([\-\.\w]+$)/; + $StandDir = $`; + $CurrentPrj = $1; + return $StandDir; + } elsif ($StandDir eq $previous_dir) { + $ENV{mk_tmp} = ''; + print_error('Found no project to build'); + }; + }; + $previous_dir = $StandDir; +# $StandDir = Cwd::realpath($StandDir . '/..'); + my @dirlist = split(/\//,Cwd::realpath($StandDir)); + pop @dirlist; # discard last dirname; + $StandDir = join('/', @dirlist); + print_error('Found no project to build') if (!$StandDir); + } +# while (chdir '..'); + while (chdir "$StandDir"); +}; + +# +# Picks project which can be built now from hash and then deletes it from hash +# +sub PickPrjToBuild { + my $DepsHash = shift; + handle_dead_children(0) if ($QuantityToBuild); + my $Prj = FindIndepPrj($DepsHash); + delete $$DepsHash{$Prj}; + generate_html_file(); + return $Prj; +}; + +# +# Make a decision if the project should be built on this platform +# +sub CheckPlatform { + my $Platform = shift; + return 1 if ($Platform eq 'all'); + return 1 if (($ENV{GUI} eq 'WIN') && ($Platform eq 'w')); + return 1 if (($ENV{GUI} eq 'UNX') && ($Platform eq 'u')); + return 1 if (($ENV{GUI} eq 'OS2') && ($Platform eq 'p')); + return 1 if (($ENV{GUI} eq 'WNT') && + (($Platform eq 'w') || ($Platform eq 'n'))); + return 0; +}; + +# +# Remove project to build ahead from dependencies and make an array +# of all from given project dependent projects +# +sub RemoveFromDependencies { + my ($ExclPrj, $i, $Prj, $Dependencies); + $ExclPrj = shift; + my $ExclPrj_orig = ''; + $ExclPrj_orig = $` if (($ExclPrj =~ /\.lnk$/o) || ($ExclPrj =~ /\.link$/o)); + $Dependencies = shift; + foreach $Prj (keys %$Dependencies) { + my $prj_deps_hash = $$Dependencies{$Prj}; + delete $$prj_deps_hash{$ExclPrj} if (defined $$prj_deps_hash{$ExclPrj}); + }; +}; + + +# +# Check the hash for consistency +# +sub check_deps_hash { + my ($deps_hash_ref, $module) = @_; + my @possible_order; + my $module_path = $StandDir . $module if (defined $module); + return if (!scalar keys %$deps_hash_ref); + my %deps_hash = %$deps_hash_ref; + my $consistent; + foreach $key (keys %$deps_hash_ref) { + my %values_hash = %{$$deps_hash_ref{$key}}; + $deps_hash{$key} = \%values_hash; + }; + my $string; + my $log_name; + my $build_number = 0; + + do { + $consistent = ''; + foreach $key (sort keys %deps_hash) { + $local_deps_ref = $deps_hash{$key}; + if (!scalar keys %$local_deps_ref) { + if (defined $module) { + $build_number++; + $string = undef; + if ($key =~ /(\s)/o) { + $string = $key; + } else { + if (length($key) == length($module_path)) { + $string = './'; + } else { + $string = substr($key, length($module_path) + 1); + $string =~ s/\\/\//go; + }; + }; + $log_name = $string; + if ($log_name eq "$module $custom_job") { + $log_name = "custom_job"; + }; + if ($log_name eq "$module $pre_custom_job") { + $log_name = "pre_custom_job"; + }; + if ($log_name eq "$module $post_custom_job") { + $log_name = "post_custom_job"; + }; + $log_name =~ s/\\|\//\./g; + $log_name =~ s/\s/_/g; + $log_name = $module if ($log_name =~ /^\.+$/); + $log_name .= '.txt'; + push(@possible_order, $key); + $jobs_hash{$key} = { SHORT_NAME => $string, + BUILD_NUMBER => $build_number, + STATUS => 'waiting', + LOG_PATH => $module . "/$ENV{INPATH}/misc/logs/$log_name", + LONG_LOG_PATH => CorrectPath($StandDir . $module . "/$ENV{INPATH}/misc/logs/$log_name"), + START_TIME => 0, + FINISH_TIME => 0, + CLIENT => '-' + }; +# if (-f $jobs_hash{$key}->{LONG_LOG_PATH} && $html) { +# print STDERR 'Warning: log file ' . $jobs_hash{$key}->{LONG_LOG_PATH} . " already exists!!\n"; +# }; + }; + RemoveFromDependencies($key, \%deps_hash); + delete $deps_hash{$key}; + $consistent++; + }; + }; + } while ($consistent && (scalar keys %deps_hash)); + return \@possible_order if ($consistent); + print STDERR "Fatal error:"; + foreach (keys %deps_hash) { + print STDERR "\n\t$_ depends on: "; + foreach my $i (keys %{$deps_hash{$_}}) { + print STDERR (' ', $i); + }; + }; + if ($child) { + my $oldfh = select STDERR; + $| = 1; + _do_exit(1); + } else { + print_error("There are dead or circular dependencies\n"); + }; +}; + +# +# Find project with no dependencies left. +# +sub FindIndepPrj { + my ($Prj, @Prjs, $Dependencies, $i); + my @candidates = (); + my $children = children_number(); + return '' if (!$server_mode && $children && ($children >= $QuantityToBuild)); + $Dependencies = shift; + @Prjs = keys %$Dependencies; + if ($#Prjs != -1) { + foreach $Prj (@Prjs) { + next if (&IsHashNative($Prj)); + my $PrjDeps = $$Dependencies{$Prj}; + push(@candidates, $Prj) if (!scalar keys %$PrjDeps); + #return $Prj if (!scalar keys %$PrjDeps); + }; + if (scalar @candidates) { + my $best_candidate = undef; + my $weight = 0; + foreach my $candidate (sort @candidates) { +# if (defined $weights_hash{$candidate} && scalar keys %{$weights_hash{$candidate}} > $weight) { + if (defined $weights_hash{$candidate} && $weights_hash{$candidate} > $weight) { + $best_candidate = $candidate; +# $weight = scalar keys %{$weights_hash{$candidate}}; + $weight = $weights_hash{$candidate}; + }; + }; + if (defined $best_candidate) { +# delete $weights_hash{$best_candidate}; + return $best_candidate; + } + my @sorted_candidates = sort(@candidates); + return $sorted_candidates[0]; + }; + return ''; + } else { + $no_projects = 1; + return ''; + }; +}; + +# +# Check if given entry is HASH-native, that is not a user-defined data +# +sub IsHashNative { + my $Prj = shift; + return 1 if ($Prj =~ /^HASH\(0x[\d | a | b | c | d | e | f]{6,}\)/); + return 0; +}; + +# +# Getting array of dependencies from the string given +# +sub GetDependenciesArray { + my ($DepString, @Dependencies, $ParentPrj, $prj, $string); + @Dependencies = (); + $DepString = shift; + $string = $DepString; + $prj = shift; + while ($DepString !~ /^NULL/o) { + print_error("Project $prj has wrongly written dependencies string:\n $string") if (!$DepString); + $DepString =~ /(\S+)\s*/o; + $ParentPrj = $1; + $DepString = $'; + if ($ParentPrj =~ /\.(\w+)$/o) { + $ParentPrj = $`; + if (($prj_platform{$ParentPrj} ne $1) && + ($prj_platform{$ParentPrj} ne 'all')) { + print_error ("$ParentPrj\.$1 is a wrongly dependency identifier!\nCheck if it is platform dependent"); + }; + $AliveDependencies{$ParentPrj}++ if (CheckPlatform($1)); + push(@Dependencies, $ParentPrj); + } else { + if ((exists($prj_platform{$ParentPrj})) && + ($prj_platform{$ParentPrj} ne 'all') ) { + print_error("$ParentPrj is a wrongly used dependency identifier!\nCheck if it is platform dependent"); + }; + push(@Dependencies, $ParentPrj); + }; + }; + return @Dependencies; +}; + + +# +# Getting current directory list +# +sub GetDirectoryList { + my ($Path); + $Path = shift; + opendir(CurrentDirList, $Path); + @DirectoryList = readdir(CurrentDirList); + closedir(CurrentDirList); + return @DirectoryList; +}; + +sub print_error { + my $message = shift; + my $force = shift; +# rmtree(CorrectPath($tmp_dir), 0, 1) if ($tmp_dir); + $modules_number -= scalar keys %global_deps_hash; + $modules_number -= 1; + print STDERR "\nERROR: $message\n"; + $ENV{mk_tmp} = ''; + close CMD_FILE if ($cmd_file); + unlink ($cmd_file); + if (!$child) { + $ENV{mk_tmp} = ''; + close CMD_FILE if ($cmd_file); + unlink ($cmd_file); + do_exit(1); + }; + do_exit(1) if (defined $force); +}; + +sub usage { + print STDERR "\nbuild\n"; + print STDERR "Syntax: build [--all|-a[:prj_name]]|[--from|-f prj_name1[:prj_name2] [prj_name3 [...]]]|[--since|-c prj_name] [--with_branches|-b]|[--prepare|-p][:platform] [--dontchekoutmissingmodules]] [--deliver|-d [--dlv_switch deliver_switch]]] [-P processes|--server [--setenvstring \"string\"] [--client_timeout MIN] [--port port1[:port2:...:portN]]] [--show|-s] [--help|-h] [--file|-F] [--ignore|-i] [--version|-V] [--mode|-m OOo[,SO[,EXT]] [--html [--html_path html_file_path] [--dontgraboutput]] [--pre_job=pre_job_sring] [--job=job_string|-j] [--post_job=post_job_sring] [--stoponerror]\n"; + print STDERR "Example1: build --from sfx2\n"; + print STDERR " - build all projects dependent from sfx2, starting with sfx2, finishing with the current module\n"; + print STDERR "Example2: build --all:sfx2\n"; + print STDERR " - the same as --all, but skip all projects that have been already built when using \"--all\" switch before sfx2\n"; + print STDERR "Example3: build --all --server\n"; + print STDERR " - build all projects in server mode, use first available port from default range 7890-7894 (running clients required!!)\n"; + print STDERR "Example4(for unixes):\n"; + print STDERR " build --all --pre_job=echo\\ Starting\\ job\\ in\\ \\\$PWD --job=some_script.sh --post_job=echo\\ Job\\ in\\ \\\$PWD\\ is\\ made\n"; + print STDERR " - go through all projects, echo \"Starting job in \$PWD\" in each module, execute script some_script.sh, and finally echo \"Job in \$PWD is made\"\n"; + print STDERR "\nSwitches:\n"; + print STDERR " --all - build all projects from very beginning till current one\n"; + print STDERR " --from - build all projects dependent from the specified (including it) till current one\n"; + print STDERR " --mode OOo - build only projects needed for OpenOffice.org\n"; + print STDERR " --prepare - clear all projects for incompatible build from prj_name till current one [for platform] (cws version)\n"; + print STDERR " --with_branches- build all projects in neighbour branches and current branch starting from actual project\n"; + print STDERR " --since - build all projects beginning from the specified till current one (the same as \"--all:prj_name\", but skipping prj_name)\n"; + print STDERR " --checkmodules - check if all required parent projects are availlable\n"; + print STDERR " --show - show what is going to be built\n"; + print STDERR " --file - generate command file file_name\n"; + print STDERR " --deliver - only deliver, no build (usable for \'-all\' and \'-from\' keys)\n"; + print STDERR " -P - start multiprocessing build, with number of processes passed\n"; + print STDERR " --server - start build in server mode (clients required)\n"; + print STDERR " --setenvstring - string for configuration of the client environment\n"; + print STDERR " --port - set server port, default is 7890. You may pass several ports, the server will be started on the first available\n"; + print STDERR " otherwise the server will be started on first available port from the default range 7890-7894\n"; + print STDERR " --client_timeout - time frame after which the client/job is considered to be lost. Default is 120 min\n"; + print STDERR " --dlv_switch - use deliver with the switch specified\n"; + print STDERR " --help - print help info\n"; + print STDERR " --ignore - force tool to ignore errors\n"; + print STDERR " --html - generate html page with build status\n"; + print STDERR " file named $ENV{INPATH}.build.html will be generated in $ENV{SRC_ROOT}\n"; + print STDERR " --html_path - set html page path\n"; + print STDERR " --dontgraboutput - do not grab console output when generating html page\n"; + print STDERR " --stoponerror - stop build when error occurs (for mp builds)\n"; + print STDERR " --dontchekoutmissingmodules - do not chekout missing modules when running prepare (links still will be broken)\n"; + print STDERR " Custom jobs:\n"; + print STDERR " --job=job_string - execute custom job in (each) module. job_string is a shell script/command to be executed instead of regular dmake jobs\n"; + print STDERR " --pre_job=pre_job_string - execute preliminary job in (each) module. pre_job_string is a shell script/command to be executed before regular job in the module\n"; + print STDERR " --post_job=job_string - execute a postprocess job in (each) module. post_job_string is a shell script/command to be executed after regular job in the module\n"; + print STDERR "Default: - build current project\n"; + print STDERR "Unknown switches passed to dmake\n"; +}; + +# +# Get all options passed +# +sub get_options { + my ($arg, $dont_grab_output); + while ($arg = shift @ARGV) { + $arg =~ /^-P$/ and $QuantityToBuild = shift @ARGV and next; + $arg =~ /^-P(\d+)$/ and $QuantityToBuild = $1 and next; + $arg =~ /^--all$/ and $BuildAllParents = 1 and next; + $arg =~ /^-a$/ and $BuildAllParents = 1 and next; + $arg =~ /^--show$/ and $show = 1 and next; + $arg =~ /^--checkmodules$/ and $checkparents = 1 and $ignore = 1 and next; + $arg =~ /^-s$/ and $show = 1 and next; + $arg =~ /^--deliver$/ and $deliver = 1 and next; + $arg =~ /^(--job=)/ and $custom_job = $' and next; + $arg =~ /^(--pre_job=)/ and $pre_custom_job = $' and next; + $arg =~ /^(--post_job=)/ and $post_custom_job = $' and next; + $arg =~ /^-d$/ and $deliver = 1 and next; + $arg =~ /^--dlv_switch$/ and $dlv_switch = shift @ARGV and next; + $arg =~ /^--file$/ and $cmd_file = shift @ARGV and next; + $arg =~ /^-F$/ and $cmd_file = shift @ARGV and next; + + $arg =~ /^--with_branches$/ and $BuildAllParents = 1 + and $build_from = shift @ARGV and next; + $arg =~ /^-b$/ and $BuildAllParents = 1 + and $build_from = shift @ARGV and next; + + $arg =~ /^--all:(\S+)$/ and $BuildAllParents = 1 + and $build_all_cont = $1 and next; + $arg =~ /^-a:(\S+)$/ and $BuildAllParents = 1 + and $build_all_cont = $1 and next; + if ($arg =~ /^--from$/ || $arg =~ /^-f$/) { + $BuildAllParents = 1; + get_incomp_projects(); + next; + }; + $arg =~ /^--prepare$/ and $prepare = 1 and next; + $arg =~ /^-p$/ and $prepare = 1 and next; + $arg =~ /^--prepare:/ and $prepare = 1 and $only_platform = $' and next; + $arg =~ /^-p:/ and $prepare = 1 and $only_platform = $' and next; + $arg =~ /^--since$/ and $BuildAllParents = 1 + and $build_since = shift @ARGV and next; + $arg =~ /^-c$/ and $BuildAllParents = 1 + and $build_since = shift @ARGV and next; + $arg =~ /^-s$/ and $BuildAllParents = 1 + and $build_since = shift @ARGV and next; + $arg =~ /^--help$/ and usage() and do_exit(0); + $arg =~ /^-h$/ and usage() and do_exit(0); + $arg =~ /^--ignore$/ and $ignore = 1 and next; + $arg =~ /^--html$/ and $html = 1 and next; + $arg =~ /^--dontgraboutput$/ and $dont_grab_output = 1 and next; + $arg =~ /^--html_path$/ and $html_path = shift @ARGV and next; + $arg =~ /^-i$/ and $ignore = 1 and next; + $arg =~ /^--server$/ and $server_mode = 1 and next; + $arg =~ /^--client_timeout$/ and $client_timeout = (shift @ARGV)*60 and next; + $arg =~ /^--setenvstring$/ and $setenv_string = shift @ARGV and next; + $arg =~ /^--port$/ and $ports_string = shift @ARGV and next; + $arg =~ /^--version$/ and do_exit(0); + $arg =~ /^-V$/ and do_exit(0); + $arg =~ /^-m$/ and get_modes() and next; + $arg =~ /^--mode$/ and get_modes() and next; + $arg =~ /^--stoponerror$/ and $stop_build_on_error = 1 and next; + if ($arg =~ /^--$/) { + push (@dmake_args, get_dmake_args()) if (!$custom_job); + next; + }; + push (@dmake_args, $arg); + }; + if (!$html) { + print_error("\"--html_path\" switch is used only with \"--html\"") if ($html_path); + print_error("\"--dontgraboutput\" switch is used only with \"--html\"") if ($dont_grab_output); + }; + $grab_output = 0 if ($dont_grab_output); + print_error('Switches --with_branches and --all collision') if ($build_from && $build_all_cont); +# print_error('Please prepare the workspace on one of UNIX platforms') if ($prepare && ($ENV{GUI} ne 'UNX')); + print_error('Switches --with_branches and --since collision') if ($build_from && $build_since); + if ($show) { + $QuantityToBuild = 0; + $cmd_file = ''; + }; + print_error('Switches --job and --deliver collision') if ($custom_job && $deliver); + $custom_job = 'deliver' if $deliver; + $post_job = 'deliver' if (!$custom_job); + $incompatible = scalar keys %incompatibles; + if ($prepare) { + print_error("--prepare is for use with --from switch only!\n") if (!$incompatible); + }; + if ($QuantityToBuild) { + if ($ignore && !$html) { + print_error("Cannot ignore errors in multiprocessing build"); + }; + if (!$enable_multiprocessing) { + print_error("Cannot load Win32::Process module for multiprocessing build"); + }; + if ($server_mode) { + print_error("Switches -P and --server collision"); + }; + } elsif ($stop_build_on_error) { + print_error("Switche --stoponerror is only for multiprocessing builds"); + }; + if ($server_mode) { + $html++; + $client_timeout = 60 * 60 * 2 if (!$client_timeout); + } else { + print_error("--ports switch is for server mode only!!") if ($ports_string); + print_error("--setenvstring switch is for server mode only!!") if ($setenv_string); + print_error("--client_timeout switch is for server mode only!!") if ($client_timeout); + }; +# $ignore++ if ($html); + if ($only_platform) { + $only_common = 'common'; + $only_common .= '.pro' if ($only_platform =~ /\.pro$/); + }; + # Default build modes(for OpenOffice.org) + $ENV{BUILD_TYPE} = 'OOo EXT' if (!defined $ENV{BUILD_TYPE}); + @ARGV = @dmake_args; +}; + +sub get_dmake_args { + my $arg; + my @job_args = (); + while ($arg = shift @ARGV) { + next if ($arg =~ /^--$/); + push (@job_args, $arg); + }; + return @job_args; +}; + +# +# get all options without '-' +# +sub get_switch_options { + my $string = ''; + my $option = ''; + while ($option = shift @ARGV) { + if (!($option =~ /^-+/)) { + $string .= '-' . $option; + $string .= ' '; + } else { + unshift(@ARGV, $option); + last; + }; + }; + $string =~ s/\s$//; + return $string; +}; + +# +# cancel build when one of children has error exit code +# +sub cancel_build { +# close_server_socket(); + $modules_number -= scalar keys %global_deps_hash; + my $broken_modules_number = scalar @broken_modules_names; + if ($broken_modules_number) { + $modules_number -= $broken_modules_number; + print "\n"; + print $broken_modules_number; + print " module(s): "; + foreach (@broken_modules_names) { + print "\n\t$_"; +# RemoveFromDependencies($_, \%global_deps_hash); + }; + print "\nneed(s) to be rebuilt\n\nReason(s):\n\n"; + foreach (keys %broken_build) { + print "ERROR: error " . $broken_build{$_} . " occurred while making $_\n"; + }; + print "\nAttention: if you build and deliver the above module(s) you may prolongue your the build issuing command \"build --from @broken_modules_names\"\n"; + } else { +# if ($ENV{GUI} eq 'WNT') { + while (children_number()) { + handle_dead_children(1); + } + foreach (keys %broken_build) { + print "ERROR: error " . $broken_build{$_} . " occurred while making $_\n"; + }; +# } else { +# kill 9 => -$$; +# }; + }; + print "\n"; + do_exit(1); +}; + +# +# Function for storing error in multiprocessing AllParents build +# +sub store_error { + my ($pid, $error_code) = @_; + return 0 if (!$error_code); + my $child_nick = $processes_hash{$pid}; + if ($ENV{GUI} eq 'WNT') { + if (!defined $had_error{$child_nick}) { + $had_error{$child_nick}++; + return 1; + }; + }; + $broken_modules_hashes{$folders_hashes{$child_nick}}++; + $broken_build{$child_nick} = $error_code; + if ($stop_build_on_error) { + clear_from_child($pid); + # Let all children finish their work + while (children_number()) { + handle_dead_children(1); + }; + cancel_build(); + }; + return 0; +}; + +# +# child handler (clears (or stores info about) the terminated child) +# +sub handle_dead_children { + my $running_children = children_number(); + return if (!$running_children); + my $force_wait = shift; + my $try_once_more = 0; + do { + my $pid = 0; + if ($ENV{GUI} eq 'WNT' && !$cygwin) { + foreach $pid (keys %processes_hash) { + my $exit_code = undef; + my $proc_obj = $windows_procs{$pid}; + $proc_obj->GetExitCode($exit_code); + if ( $exit_code != 259 ) { + $try_once_more = store_error($pid, $exit_code); + delete $windows_procs{$pid}; + if ($try_once_more) { + give_second_chance($pid); + } else { + clear_from_child($pid); + }; + }; + }; + sleep 1 if (children_number() >= $QuantityToBuild || ($force_wait && ($running_children == children_number()))); + } else { + if (children_number() >= $QuantityToBuild || + ($force_wait && ($running_children == children_number()))) { + $pid = wait(); + } else { + $pid = waitpid( -1, &WNOHANG); + }; + if ($pid > 0) { + $try_once_more = store_error($pid, $?); + if ($try_once_more) { + give_second_chance($pid); + } else { + clear_from_child($pid); + }; + }; + }; + } while(children_number() >= $QuantityToBuild); +}; + +sub give_second_chance { + my $pid = shift; + # A malicious hack for misterious windows problems - try 2 times + # to run dmake in the same directory if errors occurs + my $child_nick = $processes_hash{$pid}; + $running_children{$folders_hashes{$child_nick}}--; + delete $processes_hash{$pid}; + start_child($child_nick, $folders_hashes{$child_nick}); +}; + +sub clear_from_child { + my $pid = shift; + my $child_nick = $processes_hash{$pid}; + my $error_code = 0; + if (defined $broken_build{$child_nick}) { + $error_code = $broken_build{$child_nick}; + } else { + RemoveFromDependencies($child_nick, + $folders_hashes{$child_nick}); + }; + my $module = $module_by_hash{$folders_hashes{$child_nick}}; + html_store_job_info($folders_hashes{$child_nick}, $child_nick, $error_code); + $running_children{$folders_hashes{$child_nick}}--; + delete $processes_hash{$pid}; + $only_dependent = 0; + print 'Running processes: ' . children_number() . "\n"; +}; + +# +# Build the entire project according to queue of dependencies +# +sub BuildDependent { + $dependencies_hash = shift; + my $pid = 0; + my $child_nick = ''; + $running_children{$dependencies_hash} = 0 if (!defined $running_children{$dependencies_hash}); + while ($child_nick = PickPrjToBuild($dependencies_hash)) { + if (($QuantityToBuild)) { # multiprocessing not for $BuildAllParents (-all etc)!! + do { + handle_dead_children(0); + if (defined $broken_modules_hashes{$dependencies_hash} && !$ignore) { + return if ($BuildAllParents); + last; + }; + # start current child & all + # that could be started now + start_child($child_nick, $dependencies_hash) if ($child_nick); + $child_nick = PickPrjToBuild($dependencies_hash); + if (!$child_nick) { + return if ($BuildAllParents); + handle_dead_children(1) if (!$no_projects); + }; + } while (!$no_projects); + return if ($BuildAllParents); + while (children_number()) { + handle_dead_children(1); + }; +# if (defined $last_module) { +# $build_is_finished{$last_module}++ if (!defined $modules_with_errors{$last_module}); +# }; + + if (defined $broken_modules_hashes{$dependencies_hash}) { + cancel_build(); + } + mp_success_exit(); + } else { + dmake_dir($child_nick); + }; + $child_nick = ''; + }; +}; + +sub children_number { + return scalar keys %processes_hash; +}; + +sub start_child { + my ($job_dir, $dependencies_hash) = @_; + $jobs_hash{$job_dir}->{START_TIME} = time(); + $jobs_hash{$job_dir}->{STATUS} = 'building'; + if ($job_dir =~ /(\s)/o) { + my $error_code = undef; +# do_pre_job($`, $pre_job) if ($' eq $pre_job); + $error_code = do_custom_job($job_dir, $dependencies_hash); +# $error_code = do_post_job($`, $', $dependencies_hash) if ($' eq $post_job); +# html_store_job_info($dependencies_hash, $job_dir, $error_code); +# if ($error_code) { +# # give windows (4nt) one more chance +# if ($ENV{GUI} eq 'WNT' && !$cygwin) { +# $error_code = do_post_job($`, $post_job, $dependencies_hash); +# }; +# if ($error_code) { +# $broken_modules_hashes{$dependencies_hash}++; +# $broken_build{$job_dir} = $error_code; +# } +# } else { +# RemoveFromDependencies($job_dir, $dependencies_hash); +# }; + return; + }; + html_store_job_info($dependencies_hash, $job_dir); + my $pid = undef; + my $children_running; + my $oldfh = select STDOUT; + $| = 1; + if ($ENV{GUI} eq 'WNT' && !$cygwin) { + print "$job_dir\n"; + my $process_obj = undef; + my $rc = Win32::Process::Create($process_obj, $dmake_bin, + $dmake_args, + 0, 0, #NORMAL_PRIORITY_CLASS, + $job_dir); +# my $rc = Win32::Process::Create($process_obj, $_4nt_exe, +# "/c $dmake_batch", +# 0, NORMAL_PRIORITY_CLASS, +# $job_dir); + print_error("Cannot start child process") if (!$rc); + $pid = $process_obj->GetProcessID(); + $windows_procs{$pid} = $process_obj; + } else { + if ($pid = fork) { # parent + } elsif (defined $pid) { # child + select $oldfh; + $child = 1; + dmake_dir($job_dir); + do_exit(1); + }; + }; + select $oldfh; + $processes_hash{$pid} = $job_dir; + $children_running = children_number(); + print 'Running processes: ', $children_running, "\n"; + $maximal_processes = $children_running if ($children_running > $maximal_processes); + $folders_hashes{$job_dir} = $dependencies_hash; + $running_children{$dependencies_hash}++; +}; + +# +# Build everything that should be built multiprocessing version +# +sub build_multiprocessing { + my $Prj; + my @build_queue = (); # array, containing queue of projects + # to build + do { + while ($Prj = PickPrjToBuild(\%global_deps_hash)) { + my $module_type = $modules_types{$Prj}; + push @build_queue, $Prj; + $projects_deps_hash{$Prj} = {}; + get_deps_hash($Prj, $projects_deps_hash{$Prj}); + my $info_hash = $html_info{$Prj}; + $$info_hash{DIRS} = check_deps_hash($projects_deps_hash{$Prj}, $Prj); + $module_by_hash{$projects_deps_hash{$Prj}} = $Prj; + }; + if (!$Prj || !defined $projects_deps_hash{$Prj}) { + cancel_build() if (!scalar @build_queue && !children_number()); + handle_dead_children(1); + } + build_actual_queue(\@build_queue); + } while (scalar (keys %global_deps_hash)); + # Let the last module be built till the end + while (scalar @build_queue) { + build_actual_queue(\@build_queue); + handle_dead_children(1); + }; + # Let all children finish their work + while (children_number()) { + handle_dead_children(1); + }; + cancel_build() if (scalar keys %broken_build); + mp_success_exit(); +}; + +sub mp_success_exit { +# close_server_socket(); +# if (!$custom_job && $post_custom_job) { +# do_post_custom_job(CorrectPath($StandDir.$CurrentPrj)); +# }; + print "\nMultiprocessing build is finished\n"; + print "Maximal number of processes run: $maximal_processes\n"; + do_exit(0); +}; + +# +# Here the built queue is built as long as possible +# +sub build_actual_queue { + my $build_queue = shift; + my $i = 0; + do { + while ($i <= (scalar(@$build_queue) - 1)) { + $Prj = $$build_queue[$i]; + if (defined $broken_modules_hashes{$projects_deps_hash{$Prj}} && !$ignore) { + push (@broken_modules_names, $Prj); + splice (@$build_queue, $i, 1); + next; + }; + $only_dependent = 0; + $no_projects = 0; + BuildDependent($projects_deps_hash{$Prj}); + handle_dead_children(0); + if ($no_projects && + !$running_children{$projects_deps_hash{$Prj}}) { + if (!defined $broken_modules_hashes{$projects_deps_hash{$Prj}} || $ignore) + { +# chdir(&CorrectPath($StandDir.$Prj)); + RemoveFromDependencies($Prj, \%global_deps_hash); + $build_is_finished{$Prj}++; + splice (@$build_queue, $i, 1); + next; + }; + }; + $i++; + }; + $i = 0; + } while (!are_all_dependent($build_queue)); +}; + +sub run_job { + my ($job, $path, $registered_name) = @_; + my $job_to_do = $job; + if ( $show ) { + print "$job_to_do\n"; + return 0; + } + $job_to_do = $deliver_command if ($job eq 'deliver'); + $registered_name = $path if (!defined $registered_name); + chdir $path; + getcwd(); + + if ($html) { + my $log_file = $jobs_hash{$registered_name}->{LONG_LOG_PATH}; + my $log_dir = File::Basename::dirname($log_file); + if (!-d $log_dir) { + system("$perl $mkout"); + }; + $error_code = system ("$job_to_do > $log_file 2>&1"); + if (!$grab_output && -f $log_file) { + system("cat $log_file"); + }; + } else { + $error_code = system ("$job_to_do"); + }; + return $error_code; +}; + +sub do_custom_job { + my ($module_job, $dependencies_hash) = @_; + $module_job =~ /(\s)/o; + my $module = $`; + my $job = $'; + html_store_job_info($dependencies_hash, $module_job); + my $error_code = 0; + if ($job eq $pre_job) { + announce_module($module); +# html_store_job_info($dependencies_hash, $job_dir); + RemoveFromDependencies($module_job, $dependencies_hash); + } else { + $error_code = run_job($job, CorrectPath($StandDir.$module), $module_job); + if ($error_code) { + # give windows (4nt) one more chance + if ($ENV{GUI} eq 'WNT' && !$cygwin) { + $error_code = run_job($job, CorrectPath($StandDir.$module), $module_job); + }; + }; + if ($error_code) { + $broken_modules_hashes{$dependencies_hash}++; + $broken_build{$module} = $error_code; + } else { + RemoveFromDependencies($module_job, $dependencies_hash); + }; + }; + html_store_job_info($dependencies_hash, $module_job, $error_code); + return $error_code; +}; + +#sub do_pre_job { +# my $module = shift; +# announce_module($module); +# if ($pre_custom_job && defined $modules_types{$module} && ($modules_types{$module} eq 'mod')) { +# my $module_path = CorrectPath($StandDir.$module); +# chdir $module_path; +# getcwd(); +# my $cj_error_code = system ("$pre_custom_job"); +# print_error("Cannot run pre job \"$pre_custom_job\"") if ($cj_error_code); +# }; +#}; + + +#sub do_post_custom_job { +# my $module_path = shift; +# chdir $module_path; +# getcwd(); +# my $cj_error_code = system ("$post_custom_job"); +# print_error("Cannot run post job \"$post_custom_job\"") if ($cj_error_code); +#}; + +# +# Print announcement for module just started +# +sub announce_module { + my $Prj = shift; + $build_in_progress{$Prj}++; + print_announce($Prj); +}; + +sub print_announce { + my $Prj = shift; + my $prj_type = ''; + $prj_type = $modules_types{$Prj} if (defined $modules_types{$Prj}); + my $text; + if ($prj_type eq 'lnk') { + $text = "Skipping link to $Prj\n"; + $build_is_finished{$Prj}++; + } elsif ($prj_type eq 'img') { +# return if (defined $module_announced{$`}); + $text = "Skipping incomplete $Prj\n"; + $build_is_finished{$Prj}++; + } elsif ($custom_job) { + $text = "Running custom job \"$custom_job\" in module $Prj\n"; + } else { + $text = "Building module $Prj\n"; + }; + print $echo . "=============\n"; + print $echo . $text; +}; + +sub are_all_dependent { + my $build_queue = shift; + my $folder = ''; + foreach my $prj (@$build_queue) { + $folder = FindIndepPrj($projects_deps_hash{$prj}); + return '' if ($folder); + }; + return '1'; +}; + + +# +# Procedure defines if the local directory is a +# complete module, an image or a link +# return values: lnk link +# img incomplete (image) +# mod complete (module) +# +sub modules_classify { + my @modules = @_; + foreach my $module (sort @modules) { + if ((-e $StandDir.$module.'.lnk') || (-e $StandDir.$module.'.link')) { + $modules_types{$module} = 'lnk'; + next; + }; + if (-d $StandDir.$module) { + $modules_types{$module} = 'mod'; + next; + }; + $modules_types{$module} = 'img'; + }; +}; + +# +# This procedure provides consistency for cws +# and optimized build (ie in case of -with_branches, -all:prj_name +# and -since switches) +# +sub provide_consistency { + check_dir(); + foreach $var_ref (\$build_from, \$build_all_cont, \$build_since) { + if ($$var_ref) { + return if (-d $StandDir.$$var_ref); + $$var_ref .= '.lnk' and return if (-d $StandDir.$$var_ref.'.lnk'); + $$var_ref .= '.link' and return if (-d $StandDir.$$var_ref.'.link'); + print_error("Cannot find module '$$var_ref'", 9); + return; + }; + }; +}; + +# +# Get the workspace list ('stand.lst'), either from 'localini' +# or, if this is not possible, from 'globalini. +# (Heiner's proprietary :) +# +sub get_workspace_lst +{ + my $home; + if ( $^O eq 'MSWin32' ) { + $home = $ENV{TEMP}; + } + else { + $home = $ENV{HOME}; + } + my $inifile = "$home/localini/stand.lst"; + if (-f $inifile) { + return $inifile; +# } else { +# $inifile = get_globalini() . "/stand.lst"; +# return $inifile if (-f $inifile); + }; + return ''; +} + +# +# Procedure clears up module for incompatible build +# +sub ensure_clear_module { + my $module = shift; + my $module_type = $modules_types{$module}; + if ($module_type eq 'mod') { + clear_module($module); + return; + }; + if ($module_type eq 'lnk') { + if((!rename("$StandDir$module.lnk", "$StandDir$module")) && (!rename("$StandDir$module.link", "$StandDir$module"))) { + print_error("Cannot rename link to $module. Please rename it manually"); + } else { + clear_module($module); + }; + }; +}; + +# +# Procedure removes output tree from the module (without common trees) +# +sub clear_module { + my $module = shift; + print "Removing module's $module output trees...\n"; + print "\n" and return if ($show); + opendir DIRHANDLE, $StandDir.$module; + my @dir_content = readdir(DIRHANDLE); + closedir(DIRHANDLE); + foreach (@dir_content) { + next if (/^\.+$/); + my $dir = CorrectPath($StandDir.$module.'/'.$_); + if ((!-d $dir.'/.svn') && is_output_tree($dir)) { + #print "I would delete $dir\n"; + rmtree("$dir", 0, 1) if ($ENV{USE_SHELL} ne '4nt'); + if (-d $dir) { + system("$remove_command $dir"); + if (-d $dir) { + push(@warnings, "Cannot delete $dir"); +#print_error("Cannot delete $dir"); + } else { + print STDERR (">>> Removed $dir by force\n") if ($ENV{USE_SHELL} ne '4nt'); + }; + }; + }; + }; +}; + +# +# Figure out if the directory is an output tree +# +sub is_output_tree { + my $dir = shift; + $dir =~ /([\w\d\.]+)$/; + $_ = $1; + return '1' if (defined $platforms{$_}); + if ($only_common) { + return '1' if ($_ eq $only_common); + } else { + if (scalar keys %platforms < scalar keys %platforms_to_copy) { + return ''; + }; + return '1' if (/^common$/); + return '1' if (/^common\.pro$/); + }; + return ''; +}; + +sub get_tmp_dir { + my $tmp_dir; + if( defined($ENV{TMP}) ) { + $tmp_dir = $ENV{TMP} . '/'; + } else { + $tmp_dir = '/tmp/'; + } + $tmp_dir .= $$ while (-e $tmp_dir); + $tmp_dir = CorrectPath($tmp_dir); + eval {mkpath($tmp_dir)}; + print_error("Cannot create temporary directory in $tmp_dir") if ($@); + return $tmp_dir; +}; + + +sub retrieve_build_list { + my $module = shift; + my $old_fh = select(STDOUT); + + # Try to get global depencies from solver's build.lst if such exists + my $solver_inc_dir = "$ENV{SOLARVER}/common"; + $solver_inc_dir .= $ENV{PROEXT} if (defined $ENV{PROEXT}); + $solver_inc_dir .= '/inc'; + $solver_inc_dir .= $ENV{UPDMINOREXT} if (defined $ENV{UPDMINOREXT}); + $solver_inc_dir .= "/$module"; + $solver_inc_dir = CorrectPath($solver_inc_dir); + $dead_parents{$module}++; + print "Fetching dependencies for module $module from solver..."; + foreach (@possible_build_lists) { + my $possible_build_lst = "$solver_inc_dir/$_"; + if (-e $possible_build_lst) { + print " ok\n"; + select($old_fh); + return $possible_build_lst; + }; + } + print " failed\n"; + + if (!defined $dead_parents{$module}) { + print "WARNING: Cannot figure out CWS for $module. Forgot to set CWS?\n"; + } + select($old_fh); + return undef; +}; + +sub fix_permissions { + my $file = $File::Find::name; + return unless -f $file; + chmod '0664', $file; +}; + +# +# Removes projects which it is not necessary to build +# in incompatible build +# +sub prepare_incompatible_build { + my ($prj, $deps_hash, @missing_modules); + $deps_hash = shift; + foreach (keys %incompatibles) { + my $incomp_prj = $_; + if (!defined $$deps_hash{$_}) { + $incomp_prj .= '.lnk' if (-e $StandDir.$incomp_prj . '.lnk'); + $incomp_prj .= '.link' if (-e $StandDir.$incomp_prj . '.link'); + } + delete $incompatibles{$_}; + $incompatibles{$incomp_prj} = $$deps_hash{$incomp_prj}; + delete $$deps_hash{$incomp_prj}; + } + while ($prj = PickPrjToBuild($deps_hash)) { + RemoveFromDependencies($prj, $deps_hash); + RemoveFromDependencies($prj, \%incompatibles); + }; + foreach (keys %incompatibles) { + $$deps_hash{$_} = $incompatibles{$_}; + }; + if ($build_all_cont) { + prepare_build_all_cont($deps_hash); + delete $$deps_hash{$build_all_cont}; + }; + @modules_built = keys %$deps_hash; + clear_delivered() if ($prepare); + my $old_output_tree = ''; + foreach $prj (sort keys %$deps_hash) { + if ($prepare) { + ensure_clear_module($prj); + } else { + next if ($show); + if ($modules_types{$prj} ne 'mod') { + push(@missing_modules, $prj); + } elsif (-d CorrectPath($StandDir.$prj.'/'. $ENV{INPATH})) { + $old_output_tree++; + }; + }; + }; + if (scalar @missing_modules) { + my $warning_string = 'Following modules are inconsistent/missing: ' . "@missing_modules"; + push(@warnings, $warning_string); + }; + if ($build_all_cont) { + $$deps_hash{$build_all_cont} = (); + $build_all_cont = ''; + }; + if ($old_output_tree) { + push(@warnings, 'Some module(s) contain old output tree(s)!'); + }; + if (scalar @warnings) { + print "WARNING(S):\n"; + print STDERR "$_\n" foreach (@warnings); + print "\nATTENTION: If you are performing an incompatible build, please break the build with Ctrl+C and prepare the workspace with \"--prepare\" switch!\n\n" if (!$prepare); + sleep(10); + }; + if ($prepare) { + print "\nPreparation finished"; + if (scalar @warnings) { + print " with WARNINGS!!\n\n"; + } else {print " successfully\n\n";} + } + do_exit(0) if ($prepare); +}; + +# +# Removes projects which it is not necessary to build +# with -with_branches switch +# +sub prepare_build_from { + my ($prj, $deps_hash); + $deps_hash = shift; + my %from_deps_hash = (); # hash of dependencies of the -from project + GetParentDeps($build_from, \%from_deps_hash); + foreach $prj (keys %from_deps_hash) { + delete $$deps_hash{$prj}; + RemoveFromDependencies($prj, $deps_hash); + }; +}; + +# +# Removes projects which it is not necessary to build +# with --all:prj_name or --since switch +# +sub prepare_build_all_cont { + my ($prj, $deps_hash, $border_prj); + $deps_hash = shift; + $border_prj = $build_all_cont if ($build_all_cont); + $border_prj = $build_since if ($build_since); + while ($prj = PickPrjToBuild($deps_hash)) { + $orig_prj = ''; + $orig_prj = $` if ($prj =~ /\.lnk$/o); + $orig_prj = $` if ($prj =~ /\.link$/o); + if (($border_prj ne $prj) && + ($border_prj ne $orig_prj)) { + RemoveFromDependencies($prj, $deps_hash); + next; + } else { + if ($build_all_cont) { + $$deps_hash{$prj} = (); + } else { + RemoveFromDependencies($prj, $deps_hash); + }; + return; + }; + }; +}; + +sub get_modes { + my $option = ''; + while ($option = shift @ARGV) { + if ($option =~ /^-+/) { + unshift(@ARGV, $option); + return; + } else { + if ($option =~ /,/) { + $build_modes{$`}++; + unshift(@ARGV, $') if ($'); + } else {$build_modes{$option}++;}; + }; + }; + $build_modes{$option}++; +}; + +sub get_incomp_projects { + my $option = ''; + while ($option = shift @ARGV) { + if ($option =~ /^-+/) { + unshift(@ARGV, $option); + return; + } else { + if ($option =~ /(:)/) { + $option = $`; + print_error("-from switch collision") if ($build_all_cont); + $build_all_cont = $'; + }; + $incompatibles{$option}++; + }; + }; +}; + + +sub get_platforms { + my $platforms_ref = shift; + if ($only_platform) { + foreach (split(',', $only_platform)) { + $$platforms_ref{$_}++; + } + $platforms_ref = \%platforms_to_copy; + }; + + my $workspace_lst = get_workspace_lst(); + if ($workspace_lst) { + my $workspace_db = GenInfoParser->new(); + my $success = $workspace_db->load_list($workspace_lst); + if ( !$success ) { + print_error("Can't load workspace list '$workspace_lst'.", 4); + } + my $access_path = $ENV{WORK_STAMP} . '/Environments'; + my @platforms_available = $workspace_db->get_keys($access_path); + my $solver = $ENV{SOLARVERSION}; + foreach (@platforms_available) { + my $s_path = $solver . '/' . $_; + $$platforms_ref{$_}++ if (-d $s_path); + }; + }; + + if (!scalar keys %platforms) { + # An Auses wish - fallback to INPATH for new platforms + if (defined $ENV{INPATH}) { + $$platforms_ref{$ENV{INPATH}}++; + } else { + print_error("There is no platform found!!") ; + }; + }; +}; + +# +# This procedure clears solver from delivered +# by the modules to be build +# +sub clear_delivered { + my $message = 'Clearing up delivered'; + my %backup_vars; + my $deliver_delete_switches = '-delete'; + if (scalar keys %platforms < scalar keys %platforms_to_copy) { + $message .= ' without common trees'; + $deliver_delete_switches .= ' -dontdeletecommon'; + $only_common = ''; + }; + print "$message\n"; + + foreach my $platform (keys %platforms) { + print "\nRemoving delivered for $platform\n"; + my %solar_vars = (); + read_ssolar_vars($platform, \%solar_vars); + if (scalar keys %solar_vars) { + foreach (keys %solar_vars) { + if (!defined $backup_vars{$_}) { + $backup_vars{$_} = $ENV{$_}; + }; + $ENV{$_} = $solar_vars{$_}; + }; + }; + my $undeliver = "$deliver_command $deliver_delete_switches $nul"; +# my $current_dir = getcwd(); + foreach my $module (sort @modules_built) { + my $module_path = CorrectPath($StandDir.$module); + if (!(chdir($module_path.'.lnk') or chdir($module_path.'.link') or chdir($module_path))) { + push(@warnings, "Could not remove delivered files from the module $module. Your build can become inconsistent.\n"); + } else { + print "Removing delivered from module $module\n"; + next if ($show); + if (system($undeliver)) { + $ENV{$_} = $backup_vars{$_} foreach (keys %backup_vars); + print_error("Cannot run: $undeliver"); + } + }; + }; +# chdir $current_dir; +# getcwd(); + }; + $ENV{$_} = $backup_vars{$_} foreach (keys %backup_vars); +}; + +# +# Run setsolar for given platform and +# write all variables needed in %solar_vars hash +# +sub read_ssolar_vars { + my ($setsolar, $tmp_file); + $setsolar = $ENV{ENV_ROOT} . '/etools/setsolar.pl'; + my ($platform, $solar_vars) = @_; + if ( $^O eq 'MSWin32' ) { + $tmp_file = $ENV{TEMP} . "\\solar.env.$$.tmp"; + } else { + $setsolar = '/net/jumbo2.germany/buildenv/r/etools/setsolar.pl' if ! -e $setsolar; + $tmp_file = $ENV{HOME} . "/.solar.env.$$.tmp"; + }; + if (!-e $setsolar) { + print STDERR "There is no setsolar found. Falling back to current platform settings\n"; + return; + } + my $pro = ""; + if ($platform =~ /\.pro$/) { + $pro = "-pro"; + $platform = $`; + }; + + my ($verswitch, $source_root, $cwsname); + $verswitch = "-ver $ENV{UPDMINOR}" if (defined $ENV{UPDMINOR}); + $source_root = '-sourceroot' if (defined $ENV{SOURCE_ROOT_USED}); + $cws_name = "-cwsname $ENV{CWS_WORK_STAMP}" if (defined $ENV{CWS_WORK_STAMP}); + + my $param = "-$ENV{WORK_STAMP} $verswitch $source_root $cws_name $pro $platform"; + my $ss_command = "$perl $setsolar -file $tmp_file $param $nul"; + if (system($ss_command)) { + unlink $tmp_file; + print_error("Cannot run command:\n$ss_command"); + }; + get_solar_vars($solar_vars, $tmp_file); +}; + +# +# read variables to hash +# +sub get_solar_vars { + my ($solar_vars, $file) = @_; + my ($var, $value); + open SOLARTABLE, "<$file" or die "can´t open solarfile $file"; + while(<SOLARTABLE>) { + s/\r\n//o; + next if(!/^\w+\s+(\w+)/o); + next if (!defined $deliver_env{$1}); + $var = $1; + if ( $^O eq 'MSWin32' ) { + my $string_tail = $'; + $string_tail =~ /=(\S+)$/o; + $value = $1; + } else { + /\'(\S+)\'$/o; + $value = $1; + }; + $$solar_vars{$var} = $value; + }; + close SOLARTABLE; + unlink $file; +} + +# +# Procedure renames <module>.lnk (.link) into <module> +# +sub get_current_module { + my $module_name = shift; + my $link_name = $module_name . '.lnk'; + $link_name .= '.link' if (-e $StandDir.$module_name . '.link'); + chdir $StandDir; + getcwd(); + print "\nBreaking link to module $module_name"; + my $result = rename $link_name, $module_name; + if ( ! $result ) { + print_error("Cannot rename $module_name: $!\n"); + } + if ( $CurrentPrj eq $link_name) { + $CurrentPrj = $module_name; + } + chdir $module_name; + getcwd(); +}; + +sub check_dir { + my $start_dir = getcwd(); + my @dir_entries = split(/[\\\/]/, $start_dir); + my $current_module = $dir_entries[$#dir_entries]; + $current_module = $` if (($current_module =~ /(\.lnk)$/) || ($current_module =~ /(\.link)$/)); + my $link_name = $ENV{SRC_ROOT}.'/'.$current_module.$1; + if ( $^O eq 'MSWin32' ) { + $start_dir =~ s/\\/\//go; + $link_name =~ s/\\/\//go; + if (lc($start_dir) eq lc($link_name)) { + get_current_module($current_module); + }; + } elsif ((-l $link_name) && (chdir $link_name)) { + if ($start_dir eq getcwd()) { + # we're dealing with link => fallback to SRC_ROOT under UNIX + $StandDir = $ENV{SRC_ROOT}.'/'; + get_current_module($current_module); + return; + } else { + chdir $start_dir; + getcwd(); + }; + }; +}; + +# +# Store all available build modi in %build_modes +# +sub get_build_modes { + return if (scalar keys %build_modes); + if (defined $ENV{BUILD_TYPE}) { + if ($ENV{BUILD_TYPE} =~ /\s+/o) { + my @build_modes = split (/\s+/, $ENV{BUILD_TYPE}); + $build_modes{$_}++ foreach (@build_modes); + } else { + $build_modes{$ENV{BUILD_TYPE}}++; + }; + return; + }; +}; + +# +# pick only the modules, that should be built for +# build types from %build_modes +# +sub pick_for_build_type { + my $modules = shift; + my @mod_array = split(/\s+/, $modules); + print_error("Wrongly written dependencies string:\n $modules\n") if ($mod_array[$#mod_array] ne 'NULL'); + pop @mod_array; + my @modules_to_build; + foreach (@mod_array) { + if (/(\w+):(\S+)/o) { + push(@modules_to_build, $2) if (defined $build_modes{$1}); + next; + }; + push(@modules_to_build, $_); + }; + return @modules_to_build; +}; + +sub do_exit { +# close_server_socket(); + my $exit_code = shift; + $build_finished++; + generate_html_file(1); + if ( $^O eq 'os2' ) + { + # perl 5.10 returns 'resource busy' for rmtree + rmdir(CorrectPath($tmp_dir)) if ($tmp_dir); + } + rmtree(CorrectPath($tmp_dir), 1, 0) if ($tmp_dir); + exit($exit_code); +}; + +#sub get_post_job { +# my $job = $deliver_command; +# $job = $custom_job if ($custom_job); +# return $job; +#}; + +#sub do_post_job { +# my $job = get_post_job(); +# if ($show) { +# print $job . "\n"; +# return; +# } +# my $module = shift; +# my $post_job_name = shift; +# delete $build_in_progress{$module}; +# $module_path = CorrectPath($StandDir.$module); +# my $error_code = undef; +# if ($cmd_file) { +# print "cd $module_path\n"; +# print "$job\n"; +# } else { +# chdir $module_path; +# getcwd(); +# if ($html) { +# # tested on Linux only!! +# my $log_file = $jobs_hash{$post_job_name}->{LONG_LOG_PATH}; +# my $log_dir = File::Basename::dirname($log_file); +# if (!-d $log_dir) { +# eval {mkpath($log_dir)}; +# print_error("Cannot create log directory $log_dir") if ($@); +# }; +# $error_code = system ("$job > $log_file 2>&1"); +# if (!$grab_output && -f $log_file) { +# system("cat $log_file"); +# }; +# } else { +# $error_code = system ("$job"); +# } +# }; +# $build_is_finished{$module}++ if (!defined $modules_with_errors{$module}); +# if (!$error_code && $post_custom_job) { +# do_post_custom_job(CorrectPath($StandDir.$module)); +# }; +# return $error_code; +#}; + +# +# Procedure sorts module in user-frendly order +# +sub sort_modules_appearance { + foreach (keys %dead_parents) { + delete $build_is_finished{$_} if (defined $build_is_finished{$_}); + delete $build_in_progress{$_} if (defined $build_in_progress{$_}); + }; + foreach (keys %build_is_finished) { + delete $build_in_progress{$_} if (defined $build_in_progress{$_}); + delete $build_in_progress_shown{$_} if (defined $build_in_progress_shown{$_}); + }; + @modules_order = sort keys %modules_with_errors; + foreach (keys %modules_with_errors) { + delete $build_in_progress{$_} if (defined $build_in_progress{$_}); + delete $build_is_finished{$_} if (defined $build_is_finished{$_}); + delete $build_in_progress_shown{$_} if (defined $build_in_progress_shown{$_}); + }; + $build_in_progress_shown{$_}++ foreach (keys %build_in_progress); + push(@modules_order, $_) foreach (sort keys %build_in_progress_shown); + push(@modules_order, $_) foreach (sort keys %build_is_finished); + foreach(sort keys %html_info) { + next if (defined $build_is_finished{$_} || defined $build_in_progress{$_} || defined $modules_with_errors{$_}); + push(@modules_order, $_); + }; + return @modules_order; +}; + +sub generate_html_file { + return if (!$html); + my $force_update = shift; +# $force_update = 1; +# my $html_file = CorrectPath($ENV{HOME} . '/work/' . $ENV{INPATH}. '.build.html'); +# my $write_secs = (stat($html_file))[9]; +# my @stat = stat($html_file); +# if (defined $write_secs) { + # Regular update no often than once in 5 sec +# return if (!$force_update && (time - $html_last_updated < 5)); +# } + $html_last_updated = time; + my @modules_order = sort_modules_appearance(); + my ($successes_percent, $errors_percent) = get_progress_percentage(scalar keys %html_info, scalar keys %build_is_finished, scalar keys %modules_with_errors); + my $build_duration = get_time_line(time - $build_time); + my $temp_html_file = File::Temp::tmpnam($ENV{TMP}),#scalar tmpnam(); + my $title; + $title = $ENV{CWS_WORK_STAMP} . ': ' if (defined $ENV{CWS_WORK_STAMP}); + $title .= $ENV{INPATH}; + die("Cannot open $temp_html_file") if (!open(HTML, ">$temp_html_file")); + print HTML '<html><head>'; + print HTML '<TITLE id=MainTitle>' . $title . '</TITLE>'; + print HTML '<script type="text/javascript">' . "\n"; + print HTML 'initFrames();' . "\n"; + print HTML 'var IntervalID;' . "\n"; + print HTML 'function loadFrame_0() {' . "\n"; + print HTML 'document.write("<html>");' . "\n"; + print HTML 'document.write("<head>");' . "\n"; + print HTML 'document.write("</head>");' . "\n"; + print HTML 'document.write("<body>");' . "\n"; + if ($build_finished) { + print HTML 'document.write("<h3 align=center style=\"color:red\">Build process is finished</h3>");' . "\n"; + print HTML ' top.frames[0].clearInterval(top.frames[0].IntervalID);' . "\n"; + }; + if ($BuildAllParents) { + print HTML 'document.write("<table valign=top cellpadding=0 hspace=0 vspace=0 cellspacing=0 border=0>");' . "\n"; + print HTML 'document.write(" <tr>");' . "\n"; + print HTML 'document.write(" <td><a id=ErroneousModules href=\"javascript:top.Error(\'\', \''; + print HTML join('<br>', sort keys %modules_with_errors); + print HTML '\', \'\')\"); title=\"'; + print HTML scalar keys %modules_with_errors; + print HTML ' module(s) with errors\">Total Progress:</a></td>");' . "\n"; + print HTML 'document.write(" <td>");' . "\n"; + print HTML 'document.write(" <table width=100px valign=top cellpadding=0 hspace=0 vspace=0 cellspacing=0 border=0>");' . "\n"; + print HTML 'document.write(" <tr>");' . "\n"; + print HTML 'document.write(" <td height=20px width='; + print HTML $successes_percent + $errors_percent; + if (scalar keys %modules_with_errors) { + print HTML '% bgcolor=red valign=top></td>");' . "\n"; + } else { + print HTML '% bgcolor=#25A528 valign=top></td>");' . "\n"; + }; + print HTML 'document.write(" <td width='; + print HTML 100 - ($successes_percent + $errors_percent); + print HTML '% bgcolor=lightgrey valign=top></td>");' . "\n"; + print HTML 'document.write(" </tr>");' . "\n"; + print HTML 'document.write(" </table>");' . "\n"; + print HTML 'document.write(" </td>");' . "\n"; + print HTML 'document.write(" <td align=right>  Build time: ' . $build_duration .'</td>");' . "\n"; + print HTML 'document.write(" </tr>");' . "\n"; + print HTML 'document.write("</table>");' . "\n"; + }; + + print HTML 'document.write("<table width=100% bgcolor=white>");' . "\n"; + print HTML 'document.write(" <tr>");' . "\n"; + print HTML 'document.write(" <td width=30% align=\"center\"><strong style=\"color:blue\">Module</strong></td>");' . "\n"; + print HTML 'document.write(" <td width=* align=\"center\"><strong style=\"color:blue\">Status</strong></td>");' . "\n"; + print HTML 'document.write(" <td width=15% align=\"center\"><strong style=\"color:blue\">CPU Time</strong></td>");' . "\n"; + print HTML 'document.write(" </tr>");' . "\n"; + + foreach (@modules_order) { + next if ($modules_types{$_} eq 'lnk'); + my ($errors_info_line, $dirs_info_line, $errors_number, $successes_percent, $errors_percent, $time) = get_html_info($_); +#<one module> + print HTML 'document.write(" <tr>");' . "\n"; + print HTML 'document.write(" <td width=*>");' . "\n"; + + if (defined $dirs_info_line) { + print HTML 'document.write(" <a id='; + print HTML $_; + print HTML ' href=\"javascript:top.Error(\''; + print HTML $_ , '\', ' ; + print HTML $errors_info_line; + print HTML ','; + print HTML $dirs_info_line; + print HTML ')\"); title=\"'; + print HTML $errors_number; + print HTML ' error(s)\">', $_, '</a>");' . "\n"; + } else { + print HTML 'document.write("<em style=color:gray>' . $_ . '</em>");'; + }; + + + print HTML 'document.write(" </td>");' . "\n"; + print HTML 'document.write(" <td>");' . "\n"; + print HTML 'document.write(" <table width=100% valign=top cellpadding=0 hspace=0 vspace=0 cellspacing=0 border=0>");' . "\n"; + print HTML 'document.write(" <tr>");' . "\n"; + print HTML 'document.write(" <td height=15* width='; + + print HTML $successes_percent + $errors_percent; + if ($errors_number) { + print HTML '% bgcolor=red valign=top></td>");' . "\n"; + } else { + print HTML '% bgcolor=#25A528 valign=top></td>");' . "\n"; + }; + print HTML 'document.write(" <td width='; + + print HTML 100 - ($successes_percent + $errors_percent); + print HTML '% bgcolor=lightgrey valign=top></td>");' . "\n"; + print HTML 'document.write(" </tr>");' . "\n"; + print HTML 'document.write(" </table>");' . "\n"; + print HTML 'document.write(" </td>");' . "\n"; + print HTML 'document.write(" <td align=\"center\">', $time, '</td>");' . "\n"; + print HTML 'document.write(" </tr>");' . "\n"; +# </one module> + } + print HTML 'document.write("</table>");' . "\n"; + print HTML 'document.write("</body>");' . "\n"; + print HTML 'document.write("</html>");' . "\n"; + print HTML 'document.close();' . "\n"; + print HTML 'refreshInfoFrames();' . "\n"; + print HTML '}' . "\n"; + + print HTML 'function refreshInfoFrames() { ' . "\n"; + print HTML ' var ModuleNameObj = top.innerFrame.frames[2].document.getElementById("ModuleErrors");' . "\n"; + print HTML ' if (ModuleNameObj != null) {' . "\n"; + print HTML ' var ModuleName = ModuleNameObj.getAttribute(\'name\');' . "\n"; + print HTML ' var ModuleHref = top.innerFrame.frames[0].document.getElementById(ModuleName).getAttribute(\'href\');' . "\n"; + print HTML ' eval(ModuleHref);' . "\n"; + print HTML ' } else if (top.innerFrame.frames[2].document.getElementById("ErroneousModules") != null) {' . "\n"; + print HTML ' var ModuleHref = top.innerFrame.frames[0].document.getElementById("ErroneousModules").getAttribute(\'href\');' . "\n"; + print HTML ' eval(ModuleHref);' . "\n"; + print HTML ' if (top.innerFrame.frames[1].document.getElementById("ModuleJobs") != null) {' . "\n"; + print HTML ' var ModuleName = top.innerFrame.frames[1].document.getElementById("ModuleJobs").getAttribute(\'name\');' . "\n"; + print HTML ' ModuleHref = top.innerFrame.frames[0].document.getElementById(ModuleName).getAttribute(\'href\');' . "\n"; + print HTML ' var HrefString = ModuleHref.toString();' . "\n"; + print HTML ' var RefEntries = HrefString.split(",");' . "\n"; + print HTML ' var RefreshParams = new Array();' . "\n"; + print HTML ' for (i = 0; i < RefEntries.length; i++) {' . "\n"; + print HTML ' RefreshParams[i] = RefEntries[i].substring(RefEntries[i].indexOf("\'") + 1, RefEntries[i].lastIndexOf("\'"));' . "\n"; + print HTML ' };' . "\n"; + print HTML ' FillFrame_1(RefreshParams[0], RefreshParams[1], RefreshParams[2]);' . "\n"; + print HTML ' }' . "\n"; + print HTML ' };' . "\n"; + print HTML '}' . "\n"; + print HTML 'function loadFrame_1() {' . "\n"; + print HTML ' document.write("<h3 align=center>Jobs</h3>");' . "\n"; + print HTML ' document.write("Click on the project of interest");' . "\n"; + print HTML ' document.close();' . "\n"; + print HTML '}' . "\n"; + print HTML 'function loadFrame_2() {' . "\n"; + print HTML ' document.write("<tr bgcolor=lightgrey<td><h3>Errors</h3></pre></td></tr>");' . "\n"; + print HTML ' document.write("Click on the project of interest");' . "\n"; + print HTML ' document.close();' . "\n"; + print HTML '} function getStatusInnerHTML(Status) { var StatusInnerHtml;' . "\n"; + print HTML ' if (Status == "success") {' . "\n"; + print HTML ' StatusInnerHtml = "<em style=color:green>";' . "\n"; + print HTML ' } else if (Status == "building") {' . "\n"; + print HTML ' StatusInnerHtml = "<em style=color:blue>";' . "\n"; + print HTML ' } else if (Status == "error") {' . "\n"; + print HTML ' StatusInnerHtml = "<em style=color:red>";' . "\n"; + print HTML ' } else {' . "\n"; + print HTML ' StatusInnerHtml = "<em style=color:gray>";' . "\n"; + print HTML ' };' . "\n"; + print HTML ' StatusInnerHtml += Status + "</em>";' . "\n"; + print HTML ' return StatusInnerHtml;' . "\n"; + print HTML '} ' . "\n"; + print HTML 'function ShowLog(LogFilePath) {' . "\n"; + if (defined $html_path) { + print HTML ' top.innerFrame.frames[2].document.location.replace("file://"+LogFilePath);' . "\n"; + } else { + print HTML ' top.innerFrame.frames[2].document.location.replace(LogFilePath);' . "\n"; + } + print HTML ' top.innerFrame.frames[2].document.close();' . "\n"; + print HTML '};' . "\n"; + print HTML 'function FillFrame_1(Module, Message1, Message2) {' . "\n"; + print HTML ' var FullUpdate = 1;' . "\n"; + print HTML ' if (top.innerFrame.frames[1].document.getElementById("ModuleJobs") != null) {' . "\n"; + print HTML ' var ModuleName = top.innerFrame.frames[1].document.getElementById("ModuleJobs").getAttribute(\'name\');' . "\n"; + print HTML ' if (Module == ModuleName) FullUpdate = 0;' . "\n"; + print HTML ' }' . "\n"; + print HTML ' if (FullUpdate) {' . "\n"; + print HTML ' top.innerFrame.frames[1].document.write("<h3 align=center>Jobs in module " + Module + ":</h3>");' . "\n"; + print HTML ' top.innerFrame.frames[1].document.write("<table id=ModuleJobs name=" + Module + " width=100% bgcolor=white>");' . "\n"; + print HTML ' top.innerFrame.frames[1].document.write(" <tr>");' . "\n"; + print HTML ' top.innerFrame.frames[1].document.write(" <td width=* align=center><strong style=color:blue>Status</strong></td>");' . "\n"; + print HTML ' top.innerFrame.frames[1].document.write(" <td width=* align=center><strong style=color:blue>Job</strong></td>");' . "\n"; + print HTML ' top.innerFrame.frames[1].document.write(" <td width=* align=center><strong style=color:blue>Start Time</strong></td>");' . "\n"; + print HTML ' top.innerFrame.frames[1].document.write(" <td width=* align=center><strong style=color:blue>Finish Time</strong></td>");' . "\n"; + print HTML ' top.innerFrame.frames[1].document.write(" <td width=* align=center><strong style=color:blue>Client</strong></td>");' . "\n" if ($server_mode); + print HTML ' top.innerFrame.frames[1].document.write(" </tr>");' . "\n"; + print HTML ' var dir_info_strings = Message2.split("<br><br>");' . "\n"; + print HTML ' for (i = 0; i < dir_info_strings.length; i++) {' . "\n"; + print HTML ' var dir_info_array = dir_info_strings[i].split("<br>");' . "\n"; + print HTML ' top.innerFrame.frames[1].document.write(" <tr status=" + dir_info_array[0] + ">");' . "\n"; + print HTML ' top.innerFrame.frames[1].document.write(" <td align=center>");' . "\n"; + print HTML ' top.innerFrame.frames[1].document.write( getStatusInnerHTML(dir_info_array[0]) + " ");' . "\n"; + print HTML ' top.innerFrame.frames[1].document.write(" </td>");' . "\n"; + print HTML ' if (dir_info_array[4] == "@") {' . "\n"; + print HTML ' top.innerFrame.frames[1].document.write(" <td style=white-space:nowrap>" + dir_info_array[1] + "</td>");' . "\n"; + print HTML ' } else {' . "\n"; + print HTML ' top.innerFrame.frames[1].document.write(" <td><a href=\"javascript:top.ShowLog(\'" + dir_info_array[4] + "\')\"); title=\"Show Log\">" + dir_info_array[1] + "</a></td>");' . "\n"; + print HTML ' };' . "\n"; + print HTML ' top.innerFrame.frames[1].document.write(" <td align=center>" + dir_info_array[2] + "</td>");' . "\n"; + print HTML ' top.innerFrame.frames[1].document.write(" <td align=center>" + dir_info_array[3] + "</td>");' . "\n"; + print HTML ' top.innerFrame.frames[1].document.write(" <td align=center>" + dir_info_array[5] + "</td>");' . "\n" if ($server_mode); + print HTML ' top.innerFrame.frames[1].document.write(" </tr>");' . "\n"; + print HTML ' };' . "\n"; + print HTML ' top.innerFrame.frames[1].document.write("</table>");' . "\n"; + print HTML ' } else {' . "\n"; + print HTML ' var dir_info_strings = Message2.split("<br><br>");' . "\n"; + print HTML ' var ModuleRows = top.innerFrame.frames[1].document.getElementById("ModuleJobs").rows;' . "\n"; + print HTML ' for (i = 0; i < dir_info_strings.length; i++) {' . "\n"; + print HTML ' var dir_info_array = dir_info_strings[i].split("<br>");' . "\n"; + print HTML ' var OldStatus = ModuleRows[i + 1].getAttribute(\'status\');' . "\n"; + print HTML ' if(dir_info_array[0] != OldStatus) {' . "\n"; + print HTML ' var DirectoryInfos = ModuleRows[i + 1].cells;' . "\n"; + print HTML ' DirectoryInfos[0].innerHTML = getStatusInnerHTML(dir_info_array[0]) + " ";' . "\n"; + print HTML ' if (dir_info_array[4] != "@") {' . "\n"; + print HTML ' DirectoryInfos[1].innerHTML = "<a href=\"javascript:top.ShowLog(\'" + dir_info_array[4] + "\')\"); title=\"Show Log\">" + dir_info_array[1] + "</a>";' . "\n"; + print HTML ' };' . "\n"; + print HTML ' DirectoryInfos[2].innerHTML = dir_info_array[2];' . "\n"; + print HTML ' DirectoryInfos[3].innerHTML = dir_info_array[3];' . "\n"; + print HTML ' DirectoryInfos[4].innerHTML = dir_info_array[5];' . "\n" if ($server_mode); + print HTML ' };' . "\n"; + print HTML ' };' . "\n"; + print HTML ' };' . "\n"; + print HTML ' top.innerFrame.frames[1].document.close();' . "\n"; + print HTML '};' . "\n"; + print HTML 'function Error(Module, Message1, Message2) {' . "\n"; + print HTML ' if (Module == \'\') {' . "\n"; + print HTML ' if (Message1 != \'\') {' . "\n"; + print HTML ' var erroneous_modules = Message1.split("<br>");' . "\n"; + print HTML ' var ErrorNumber = erroneous_modules.length;' . "\n"; + + print HTML ' top.innerFrame.frames[2].document.write("<h3 id=ErroneousModules errors=" + erroneous_modules.length + ">Modules with errors:</h3>");' . "\n"; + print HTML ' for (i = 0; i < ErrorNumber; i++) {' . "\n"; + print HTML ' var ModuleObj = top.innerFrame.frames[0].document.getElementById(erroneous_modules[i]);' . "\n"; + print HTML ' top.innerFrame.frames[2].document.write("<a href=\"");' . "\n"; + print HTML ' top.innerFrame.frames[2].document.write(ModuleObj.getAttribute(\'href\'));' . "\n"; + print HTML ' top.innerFrame.frames[2].document.write("\"); title=\"");' . "\n"; + print HTML ' top.innerFrame.frames[2].document.write("\">" + erroneous_modules[i] + "</a>  ");' . "\n"; + print HTML ' };' . "\n"; + print HTML ' top.innerFrame.frames[2].document.close();' . "\n"; + print HTML ' };' . "\n"; + print HTML ' } else {' . "\n"; + print HTML ' var ModuleNameObj = top.innerFrame.frames[2].document.getElementById("ModuleErrors");' . "\n"; + print HTML ' var OldErrors = null;' . "\n"; + print HTML ' var ErrorNumber = Message1.split("<br>").length;' . "\n"; + print HTML ' if ((ModuleNameObj != null) && (Module == ModuleNameObj.getAttribute(\'name\')) ) {' . "\n"; + print HTML ' OldErrors = ModuleNameObj.getAttribute(\'errors\');' . "\n"; + print HTML ' }' . "\n"; + print HTML ' if ((OldErrors == null) || (OldErrors != ErrorNumber)) {' . "\n"; + print HTML ' top.innerFrame.frames[2].document.write("<h3 id=ModuleErrors errors=" + ErrorNumber + " name=\"" + Module + "\">Errors in module " + Module + ":</h3>");' . "\n"; + print HTML ' top.innerFrame.frames[2].document.write(Message1);' . "\n"; + print HTML ' top.innerFrame.frames[2].document.close();' . "\n"; + print HTML ' }' . "\n"; + print HTML ' FillFrame_1(Module, Message1, Message2);' . "\n"; + print HTML ' }' . "\n"; + print HTML '}' . "\n"; + print HTML 'function updateInnerFrame() {' . "\n"; + print HTML ' top.innerFrame.frames[0].document.location.reload();' . "\n"; + print HTML ' refreshInfoFrames();' . "\n"; + print HTML '};' . "\n\n"; + + print HTML 'function setRefreshRate() {' . "\n"; + print HTML ' RefreshRate = document.Formular.rate.value;' . "\n"; + print HTML ' if (!isNaN(RefreshRate * 1)) {' . "\n"; + print HTML ' top.frames[0].clearInterval(IntervalID);' . "\n"; + print HTML ' IntervalID = top.frames[0].setInterval("updateInnerFrame()", RefreshRate * 1000);' . "\n"; + print HTML ' };' . "\n"; + print HTML '};' . "\n"; + + print HTML 'function initFrames() {' . "\n"; + print HTML ' var urlquery = location.href.split("?");' . "\n"; + print HTML ' if (urlquery.length == 1) {' . "\n"; + print HTML ' document.write("<html><head><TITLE id=MainTitle>' . $ENV{INPATH} .'</TITLE>");' . "\n"; + print HTML ' document.write(" <frameset rows=\"12%,88%\">");' . "\n"; + print HTML ' document.write(" <frame name=\"topFrame\" src=\"" + urlquery + "?initTop\"/>");' . "\n"; + print HTML ' document.write(" <frame name=\"innerFrame\" src=\"" + urlquery + "?initInnerPage\"/>");' . "\n"; + print HTML ' document.write(" </frameset>");' . "\n"; + print HTML ' document.write("</head></html>");' . "\n"; + print HTML ' } else if (urlquery[1].substring(0,7) == "initTop") {' . "\n"; + print HTML ' var urlquerycontent = urlquery[1].split("=");' . "\n"; + print HTML ' var UpdateRate = 10' . "\n"; + print HTML ' if (urlquerycontent.length > 2) {' . "\n"; + print HTML ' if (isNaN(urlquerycontent[2] * 1)) {' . "\n"; + print HTML ' alert(urlquerycontent[2] + " is not a number. Ignored.");' . "\n"; + print HTML ' } else {' . "\n"; + print HTML ' UpdateRate = urlquerycontent[2];' . "\n"; + print HTML ' };' . "\n"; + print HTML ' };' . "\n"; + print HTML ' document.write("<html><body>");' . "\n"; + print HTML ' document.write("<h3 align=center>Build process progress status</h3>");' . "\n"; + print HTML ' document.write("<div align=\"right\">");' . "\n"; + print HTML ' document.write(" <table border=\"0\"> <tr>");' . "\n"; + print HTML ' document.write("<td>Refresh rate(sec):</td>");' . "\n"; + print HTML ' document.write("<th>");' . "\n"; + print HTML ' document.write("<FORM name=\"Formular\" onsubmit=\"setRefreshRate()\">");' . "\n"; + print HTML ' document.write("<input type=\"hidden\" name=\"initTop\" value=\"\"/>");' . "\n"; + print HTML ' document.write("<input type=\"text\" id=\"RateValue\" name=\"rate\" autocomplete=\"off\" value=\"" + UpdateRate + "\" size=\"1\"/>");' . "\n"; + print HTML ' document.write("<input type=\"submit\" value=\"OK\">");' . "\n"; + print HTML ' document.write("</FORM>");' . "\n"; + print HTML ' document.write("</th></tr></table>");' . "\n"; + print HTML ' document.write("</div>");' . "\n"; + print HTML ' document.write(" </frameset>");' . "\n"; + print HTML ' document.write("</body></html>");' . "\n"; + print HTML ' top.frames[0].clearInterval(IntervalID);' . "\n"; + print HTML ' IntervalID = top.frames[0].setInterval("updateInnerFrame()", UpdateRate * 1000);' . "\n"; + print HTML ' } else if (urlquery[1] == "initInnerPage") {' . "\n"; + print HTML ' document.write("<html><head>");' . "\n"; + print HTML ' document.write(\' <frameset rows="80%,20%\">\');' . "\n"; + print HTML ' document.write(\' <frameset cols="70%,30%">\');' . "\n"; + print HTML ' document.write(\' <frame src="\');' . "\n"; + print HTML ' document.write(urlquery[0]);' . "\n"; + print HTML ' document.write(\'?initFrame0"/>\');' . "\n"; + print HTML ' document.write(\' <frame src="\');' . "\n"; + print HTML ' document.write(urlquery[0]);' . "\n"; + print HTML ' document.write(\'?initFrame1"/>\');' . "\n"; + print HTML ' document.write(\' </frameset>\');' . "\n"; + print HTML ' document.write(\' <frame src="\');' . "\n"; + print HTML ' document.write(urlquery[0]);' . "\n"; + print HTML ' document.write(\'?initFrame2"/>\');' . "\n"; + print HTML ' document.write(\' </frameset>\');' . "\n"; + print HTML ' document.write("</head></html>");' . "\n"; + print HTML ' } else {' . "\n"; + print HTML ' if (urlquery[1] == "initFrame0" ) {' . "\n"; + print HTML ' loadFrame_0();' . "\n"; + print HTML ' } else if (urlquery[1] == "initFrame1" ) { ' . "\n"; + print HTML ' loadFrame_1();' . "\n"; + print HTML ' } else if (urlquery[1] == "initFrame2" ) {' . "\n"; + print HTML ' loadFrame_2();' . "\n"; + print HTML ' }' . "\n"; + print HTML ' };' . "\n"; + print HTML '};' . "\n"; + print HTML '</script><noscript>Your browser doesn\'t support JavaScript!</noscript></head></html>' . "\n"; + close HTML; + + if(-e $temp_html_file) { + rename($temp_html_file, $html_file) or system("mv", $temp_html_file, $html_file); + if (-e $temp_html_file) { + system("rm -rf $temp_html_file") if (!unlink $temp_html_file); + }; + }; +}; + +sub get_local_time_line { + my $epoch_time = shift; + my $local_time_line; + my @time_array; + if ($epoch_time) { + @time_array = localtime($epoch_time); + $local_time_line = sprintf("%02d:%02d:%02d", $time_array[2], $time_array[1], $time_array[0]); + } else { + $local_time_line = '-'; + }; + return $local_time_line; +}; + +sub get_dirs_info_line { + my $job = shift; + my $dirs_info_line = $jobs_hash{$job}->{STATUS} . '<br>'; + my @time_array; + my $log_path_string; + $dirs_info_line .= $jobs_hash{$job}->{SHORT_NAME} . '<br>'; + $dirs_info_line .= get_local_time_line($jobs_hash{$job}->{START_TIME}) . '<br>'; + $dirs_info_line .= get_local_time_line($jobs_hash{$job}->{FINISH_TIME}) . '<br>'; + if ($jobs_hash{$job}->{STATUS} eq 'waiting' || (!-f $jobs_hash{$job}->{LONG_LOG_PATH})) { + $dirs_info_line .= '@'; + } else { + if (defined $html_path) { + $log_path_string = $jobs_hash{$job}->{LONG_LOG_PATH}; + } else { + $log_path_string = $jobs_hash{$job}->{LOG_PATH}; + }; + $log_path_string =~ s/\\/\//g; + $dirs_info_line .= $log_path_string; + }; + $dirs_info_line .= '<br>'; + $dirs_info_line .= $jobs_hash{$job}->{CLIENT} . '<br>' if ($server_mode); + return $dirs_info_line; +}; + +sub get_html_info { + my $module = shift; + my $module_info_hash = $html_info{$module}; + my $dirs = $$module_info_hash{DIRS}; + my $dirs_number = scalar @$dirs; + my $dirs_info_line = '\''; + if ($dirs_number) { + my %dirs_sorted_by_order = (); + foreach (@$dirs) { + $dirs_sorted_by_order{$jobs_hash{$_}->{BUILD_NUMBER}} = $_; + } + foreach (sort {$a <=> $b} keys %dirs_sorted_by_order) { + $dirs_info_line .= get_dirs_info_line($dirs_sorted_by_order{$_}) . '<br>'; + } + } else { + return(undef, undef, 0, 0, 0, '-'); +# $dirs_info_line .= 'No information available yet'; + }; + $dirs_info_line =~ s/(<br>)*$//o; + $dirs_info_line .= '\''; + $dirs = $$module_info_hash{SUCCESSFUL}; + my $successful_number = scalar @$dirs; + $dirs = $$module_info_hash{ERRORFUL}; + my $errorful_number = scalar @$dirs; + my $errors_info_line = '\''; + if ($errorful_number) { + $errors_info_line .= $_ . '<br>' foreach (@$dirs); + } else { + $errors_info_line .= 'No errors'; + }; + $errors_info_line .= '\''; +# if (defined $full_info) { + my $time_line = get_time_line($$module_info_hash{BUILD_TIME}); + my ($successes_percent, $errors_percent) = get_progress_percentage($dirs_number, $successful_number, $errorful_number); + return($errors_info_line, $dirs_info_line, $errorful_number, $successes_percent, $errors_percent, $time_line); +# } else { +# return($errors_info_line, $dirs_info_line, $errorful_number); +# }; +}; + +sub get_time_line { + use integer; + my $seconds = shift; + my $hours = $seconds/3600; + my $minits = ($seconds/60)%60; + $seconds -= ($hours*3600 + $minits*60); + return(sprintf("%02d\:%02d\:%02d" , $hours, $minits, $seconds)); +}; + +sub get_progress_percentage { + use integer; + my ($dirs_number, $successful_number, $errorful_number) = @_; + return (0 ,0) if (!$dirs_number); + my $errors_percent = ($errorful_number * 100)/ $dirs_number; + my $successes_percent; + if ($dirs_number == ($successful_number + $errorful_number)) { + $successes_percent = 100 - $errors_percent; + } else { + $successes_percent = ($successful_number * 100)/ $dirs_number; + }; + return ($successes_percent, $errors_percent); +}; + +# +# This procedure stores the dmake result in %html_info +# +sub html_store_job_info { + return if (!$html); + my ($deps_hash, $build_dir, $error_code) = @_; + my $force_update = 0; + if ($build_dir =~ /(\s)/o && (defined $error_code)) { + $force_update++ if (!children_number()); + } + my $module = $module_by_hash{$deps_hash}; + my $module_info_hash = $html_info{$module}; +# $$module_info_hash{BUILD_TIME} += $jobs_hash{$build_dir}->{FINISH_TIME} - $jobs_hash{$build_dir}->{START_TIME}; + my $dmake_array; + if (defined $error_code) { + $jobs_hash{$build_dir}->{FINISH_TIME} = time(); + $$module_info_hash{BUILD_TIME} += $jobs_hash{$build_dir}->{FINISH_TIME} - $jobs_hash{$build_dir}->{START_TIME}; + if ($error_code) { + $jobs_hash{$build_dir}->{STATUS} = 'error'; + $dmake_array = $$module_info_hash{ERRORFUL}; + $build_dir =~ s/\\/\//g; + $modules_with_errors{$module}++; + } else { + $jobs_hash{$build_dir}->{STATUS} = 'success'; + $dmake_array = $$module_info_hash{SUCCESSFUL}; + }; + push (@$dmake_array, $build_dir); + }; +# generate_html_file($force_update); +}; + +#sub close_server_socket { +# # Actually, the "or warn..." part is for debugging, +# # should be removed for release +# if (defined $new_socket_obj) { +# print $new_socket_obj 'No job'; +# close($new_socket_obj) or warn $! ? "Error closing connection: $!" +# : "Exit status $? from closing connection"; +# }; +# if (defined $socket_obj) { +# close($socket_obj) or warn $! ? "Error closing server socket: $!" +# : "Exit status $? from closing server socket"; +# }; +#}; + +#sub stop_server { +# close_server_socket(); +# print "Server terminated\n"; +# exit($?); +#}; + +sub start_server_on_port { + my $port = shift; + if ($ENV{GUI} eq 'WNT') { + $socket_obj = new IO::Socket::INET (#LocalAddr => hostname(), + LocalPort => $port, + Proto => 'tcp', + Listen => 100); # 100 clients can be on queue, I think it is enough + } else { + $socket_obj = new IO::Socket::INET (#LocalAddr => hostname(), + LocalPort => $port, + Proto => 'tcp', + ReuseAddr => 1, + Listen => 100); # 100 clients can be on queue, I think it is enough + }; + return('Cannot create socket object') if (!defined $socket_obj); + my $timeout = $socket_obj->timeout($client_timeout); + $socket_obj->autoflush(1); + print "SERVER started on port $port\n"; + return 0; +}; + +sub accept_connection { + my $new_socket_obj = undef; + do { + $new_socket_obj = $socket_obj->accept(); + if (!$new_socket_obj) { + print "Timeout on incoming connection\n"; + check_client_jobs(); + }; + } while (!$new_socket_obj); + return $new_socket_obj; +}; + +sub check_client_jobs { + foreach (keys %clients_times) { + if (time - $clients_times{$_} > $client_timeout) { + print "Client's $_ Job: \"$clients_jobs{$_}\" apparently got lost...\n"; + print "Scheduling for rebuild...\n"; + print "You might need to check the $_\n"; + $lost_client_jobs{$clients_jobs{$_}}++; + delete $processes_hash{$_}; + delete $clients_jobs{$_}; + delete $clients_times{$_}; +# } else { +# print time - $clients_times{$_} . "\n"; + }; + }; +}; + +sub run_server { + my @build_queue = (); # array, containing queue of projects + # to build + # use port 7890 as default + my $default_port = 7890; + if ($ports_string) { + @server_ports = split( /:/, $ports_string); + } else { + @server_ports = ($default_port .. $default_port + 4); + }; + my $error = 0; + if (scalar @server_ports) { + foreach (@server_ports) { + $error = start_server_on_port($_); + if ($error) { + print STDERR "port $_: $error\n"; + } else { +# $SIG{KILL} = \&stop_server; +# $SIG{INT} = \&stop_server; +# $SIG{TERM} = \&stop_server; +# $SIG{QUIT} = \&stop_server; + last; + }; + }; + }; + print_error('It is impossible to start server on port(s): ' . "@server_ports\n") if ($error); + + my $client_addr; + my $job_string_base = get_job_string_base(); + my $new_socket_obj; + while ($new_socket_obj = accept_connection()) { + check_client_jobs(); + # find out who connected + my $client_ipnum = $new_socket_obj->peerhost(); + my $client_host = gethostbyaddr(inet_aton($client_ipnum), AF_INET); + # print who is connected +# print "got a connection from: $client_host", "[$client_ipnum]\n"; + # send them a message, close connection + my $client_message = <$new_socket_obj>; +# print $client_message; + chomp $client_message; + my @client_data = split(/ /, $client_message); + my %client_hash = (); + foreach (@client_data) { + /(=)/; + $client_hash{$`} = $'; + } + my $pid = $client_hash{pid} . '@' . $client_host; + if (defined $client_hash{platform}) { + if ($client_hash{platform} ne $ENV{OUTPATH} || (defined $client_hash{osname} && ($^O ne $client_hash{osname}))) { + print $new_socket_obj "Wrong platform"; + close($new_socket_obj); + next; + }; + } else { +# handle_dead_children(0); + if ($client_hash{result} eq "0") { +# print "$clients_jobs{$pid} succedded on $pid\n"; + } else { + print "Error $client_hash{result}\n"; + if (store_error($pid, $client_hash{result})) { + print $new_socket_obj $job_string_base . $clients_jobs{$pid}; + close($new_socket_obj); + $clients_times{$pid} = time; + next; + }; + }; + delete $clients_times{$pid}; + clear_from_child($pid); + delete $clients_jobs{$pid}; + print 'Running processes: ', children_number(), "\n"; + # Actually, next 3 strings are only for even distribution + # of clients if there are more than one build server running + print $new_socket_obj 'No job'; + close($new_socket_obj); + next; + }; + my $job_string; + my @lost_jobs = keys %lost_client_jobs; + if (scalar @lost_jobs) { + $job_string = $lost_jobs[0]; + delete $lost_client_jobs{$lost_jobs[0]}; + } else { +# $job_string = get_job_string(\@build_queue, $pid); + $job_string = get_job_string(\@build_queue); + }; + if ($job_string) { + my $job_dir = $job_jobdir{$job_string}; + $processes_hash{$pid} = $job_dir; + $jobs_hash{$job_dir}->{CLIENT} = $pid; + print "$pid got $job_dir\n"; + print $new_socket_obj $job_string_base . $job_string; + $clients_jobs{$pid} = $job_string; + $clients_times{$pid} = time; + $children_running = children_number(); + print 'Running processes: ', $children_running, "\n"; + $maximal_processes = $children_running if ($children_running > $maximal_processes); + } else { + print $new_socket_obj 'No job'; + }; + close($new_socket_obj); + }; +}; + +# +# Procedure returns the part of the job string that is similar for all clients +# +sub get_job_string_base { + if ($setenv_string) { + return "setenv_string=$setenv_string "; + }; + my $job_string_base = "server_pid=$$ setsolar_cmd=$ENV{SETSOLAR_CMD} "; + $job_string_base .= "source_root=$ENV{SOURCE_ROOT} " if (defined $ENV{SOURCE_ROOT}); + $job_string_base .= "updater=$ENV{UPDATER} " if (defined $ENV{UPDATER}); + return $job_string_base; +}; + +sub get_job_string { + my $build_queue = shift; + my $job = $dmake; + my ($job_dir, $dependencies_hash); + if ($BuildAllParents) { + fill_modules_queue($build_queue); + do { + ($job_dir, $dependencies_hash) = pick_jobdir($build_queue); + return '' if (!$job_dir); + $jobs_hash{$job_dir}->{START_TIME} = time(); + $jobs_hash{$job_dir}->{STATUS} = 'building'; + if ($job_dir =~ /(\s)$pre_job/o) { + do_custom_job($job_dir, $dependencies_hash); + $job_dir = ''; +# if ($' eq $pre_job) { +# do_pre_job($`, $pre_job); +# html_store_job_info($dependencies_hash, $job_dir, undef); +# RemoveFromDependencies($job_dir, $dependencies_hash); +# $job_dir = ''; +# }; + }; + } while (!$job_dir); + } else { + $dependencies_hash = \%LocalDepsHash; + do { + $job_dir = PickPrjToBuild(\%LocalDepsHash); + if (!$job_dir && !children_number()) { + cancel_build() if (scalar keys %broken_build); + mp_success_exit(); + }; + return '' if (!$job_dir); + $jobs_hash{$job_dir}->{START_TIME} = time(); + $jobs_hash{$job_dir}->{STATUS} = 'building'; + if ($job_dir =~ /(\s)$pre_job/o) { +# if ($' eq $pre_job) { + do_custom_job($job_dir, $dependencies_hash); +# do_pre_job($`, $pre_job); +# html_store_job_info($dependencies_hash, $job_dir, undef); +# RemoveFromDependencies($job_dir, $dependencies_hash); + $job_dir = ''; +# } + }; + } while (!$job_dir); + }; + $running_children{$dependencies_hash}++; +# $processes_hash{$pid} = $job_dir; + $folders_hashes{$job_dir} = $dependencies_hash; + my $log_file = $jobs_hash{$job_dir}->{LONG_LOG_PATH}; +# $jobs_hash{$job_dir}->{CLIENT} = $pid; + my $full_job_dir = $job_dir; + if ($job_dir =~ /(\s)/o) { + $job = $'; + $job = $deliver_command if ($job eq $post_job); + $full_job_dir = CorrectPath($StandDir.$`); + } + my $log_dir = File::Basename::dirname($log_file); + if (!-d $log_dir) { + chdir $full_job_dir; + getcwd(); + system("$perl $mkout"); + }; + my $job_string = "job_dir=$full_job_dir job=$job log=$log_file"; + $job_jobdir{$job_string} = $job_dir; + return $job_string; +}; + +sub pick_jobdir { + my $build_queue = shift; + my $i = 0; + foreach (@$build_queue) { + $Prj = $$build_queue[$i]; + my $prj_deps_hash = $projects_deps_hash{$Prj}; + if (defined $broken_modules_hashes{$prj_deps_hash} && !$ignore) { + push (@broken_modules_names, $Prj); + splice (@$build_queue, $i, 1); + next; + }; + $only_dependent = 0; + $no_projects = 0; + $running_children{$prj_deps_hash} = 0 if (!defined $running_children{$prj_deps_hash}); + $child_nick = PickPrjToBuild($prj_deps_hash); + if ($child_nick) { + return ($child_nick, $prj_deps_hash); + } + if ($no_projects && !$running_children{$prj_deps_hash}) { + if (!defined $broken_modules_hashes{$prj_deps_hash} || $ignore) + { + RemoveFromDependencies($Prj, \%global_deps_hash); + $build_is_finished{$Prj}++; + splice (@$build_queue, $i, 1); + next; + }; + }; + $i++; + }; +}; + +sub fill_modules_queue { + my $build_queue = shift; + my $Prj; + while ($Prj = PickPrjToBuild(\%global_deps_hash)) { + my $module_type = $modules_types{$Prj}; + push @$build_queue, $Prj; + $projects_deps_hash{$Prj} = {}; + get_deps_hash($Prj, $projects_deps_hash{$Prj}); + my $info_hash = $html_info{$Prj}; + $$info_hash{DIRS} = check_deps_hash($projects_deps_hash{$Prj}, $Prj); + $module_by_hash{$projects_deps_hash{$Prj}} = $Prj; + }; + if (!$Prj && !children_number() && (!scalar @$build_queue)) { + cancel_build() if (scalar keys %broken_build); + mp_success_exit(); + }; +}; diff --git a/solenv/bin/build_client.pl b/solenv/bin/build_client.pl new file mode 100755 index 000000000000..3d37654c7534 --- /dev/null +++ b/solenv/bin/build_client.pl @@ -0,0 +1,485 @@ +: +eval 'exec perl -S $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: build_client.pl,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +# +# build_client - client for the build tool in server mode +# + +use strict; +use Socket; +use Sys::Hostname; +use File::Temp qw(tmpnam); +use POSIX; +use Cwd qw (cwd); + +$SIG{KILL} = \&handle_temp_files; +$SIG{INT} = \&handle_temp_files; + +### main ### +my $enable_multiprocessing = 1; +my $server_list_file; +my $server_list_time_stamp = 0; +my %ENV_BACKUP; +$ENV_BACKUP{$_} = $ENV{$_} foreach (keys %ENV); + +if ($^O eq 'MSWin32') { + eval { require Win32::Process; import Win32::Process; }; + $enable_multiprocessing = 0 if ($@); +} else { + use Cwd 'chdir'; +}; +my $processes_to_run = 1; + +my %hosts_ports = (); +my $default_port = 7890; +my @ARGV_COPY = @ARGV; # @ARGV BACKUP +#$ARGV_COPY{$_}++ foreach (@ARGV); +print "arguments: @ARGV\n"; +get_options(); + +my $proto = getprotobyname('tcp'); +my $paddr; +my $host = hostname(); +my $current_server = ''; +my $got_job = 0; +my %job_temp_files = (); +my %environments = (); # hash containing all environments +my $env_alias; +my %platform_rejects = (); # hash containing paddr of server, that replied "Wrong platform" + +my $child = 0; +if ($processes_to_run > 1) { + my $started_processes = 1; + if ($^O eq 'MSWin32') { + my $process_obj = undef; + my $child_args = "perl $0"; + foreach (@ARGV_COPY) { + /^-P(\d+)$/ and next; + /^-P$/ and shift @ARGV_COPY and next; + $child_args .= " $_"; + }; + do { + my $rc = Win32::Process::Create($process_obj, $^X, + $child_args, + 0, 0, #NORMAL_PRIORITY_CLASS, + "."); + print_error("Cannot start child process") if (!$rc); + $started_processes++; + } while ($started_processes < $processes_to_run); + } else { + my $pid; + do { + if ($pid = fork) { # parent + $started_processes++; + print $started_processes . "\n"; + } elsif (defined $pid) { # child + $child++; + }; + } while (($started_processes < $processes_to_run) && !$child); + }; +}; + +run_client(); +### end of main procedure ### + +######################### +# # +# Procedures # +# # +######################### +sub handle_temp_files { + print STDERR "Got signal - clearing up...\n"; + foreach (keys %job_temp_files) { + if ($job_temp_files{$_}) { + rename($_, $job_temp_files{$_}) or system("mv", $_, $job_temp_files{$_}); + print STDERR "Could not rename $_ to $job_temp_files{$_}\n" if (-e $_); + } else { + unlink $_ or system("rm -rf $_"); + print STDERR "Could not remove $_\n" if (-e $_); + }; + }; + exit($?); +}; + +sub run_client { +# initialize host and port + if (!scalar keys %hosts_ports) { + $hosts_ports{localhost} = $default_port; + } + + print "Started client with PID $$, hostname $host\n"; + + my $message = ''; + my $current_port = ''; + my %active_servers = (); + + do { + $got_job = 0; + foreach $current_server (keys %hosts_ports) { + foreach $current_port (keys %{$hosts_ports{$current_server}}) { + + #before each "inactive" server/port connect - connect to each "active" server/port + next if (defined ${$active_servers{$current_server}}{$current_port}); + # "active" cycle + foreach my $active_server (keys %active_servers) { + foreach my $active_port (keys %{$active_servers{$active_server}}) { +# print "Active: $active_server:$active_port\n"; + my $iaddr = inet_aton($active_server); + $paddr = sockaddr_in($active_port, $iaddr); + do { + my $server_is_active = 0; + $message = request_job($message, $active_server, $active_port); + $server_is_active++ if ($message); + if (!$server_is_active) { + delete ${$active_servers{$active_server}}{$active_port}; + # throw away obsolete environments + foreach (keys %environments) { + /^\d+@/; + if ($' eq "$active_server:$active_port") { + delete $environments{$_}; + }; + }; + }; + $message = '' if ($message eq 'No job'); + } while ($message); + }; + }; + + # "inactive" cycle +# print "Inactive: $current_server:$current_port\n"; + my $iaddr = inet_aton($current_server); + $paddr = sockaddr_in($current_port, $iaddr); + do { + $message = request_job($message, $current_server, $current_port); + if ($message) { + if (!defined $active_servers{$current_server}) { + my %ports; + $active_servers{$current_server} = \%ports; + }; + ${$active_servers{$current_server}}{$current_port}++; + }; + $message = '' if ($message eq 'No job'); + } while ($message); + }; + }; + sleep 5 if (!$got_job); + read_server_list(); + } while(1); +}; + +sub usage { + my $error = shift; + print STDERR "\nbuild_client\n"; + print STDERR "Syntax: build_client [-PN] host1[:port1:...:portN] [host2[:port1:...:portN] ... hostN[:port1:...:portN]]|\@server_list_file\n"; + print STDERR " -P - start multiprocessing build, with number of processes passed\n"; + print STDERR "Example1: build_client myserver1 myserver2:7891:7892\n"; + print STDERR " the client will be asking for jobs on myserver1's default ports (7890-7894)\n"; + print STDERR " and on myserver2's ports 7891 and 7892\n"; + print STDERR "Example2: build_client -P2 myserver1:7990 myserver2\n"; + print STDERR " start 2 clients which will be asking for jobs myserver1's port 7990\n"; + print STDERR " and myserver2's default ports (7890-7894)\n"; + exit ($error); +}; + +sub get_options { + my $arg; + usage(1) if (!scalar @ARGV); + while ($arg = shift @ARGV) { + usage(0) if /^--help$/; + usage(0) if /^-h$/; + $arg =~ /^-P(\d+)$/ and $processes_to_run = $1 and next; + $arg =~ /^-P$/ and $processes_to_run = shift @ARGV and next; + $arg =~ /^@(\S+)$/ and $server_list_file = $1 and next; + store_server($arg); + }; + if (($processes_to_run > 1) && (!$enable_multiprocessing)) { + print_error("Cannot load Win32::Process module for multiple client start"); + }; + if ($server_list_file) { + print_error("$server_list_file is not a regular file!!") if (!-f $server_list_file); + read_server_list(); + } + print_error("No server info") if (!scalar %hosts_ports); +}; + +sub store_server { + my $server_string = shift; + my @server_params = (); + @server_params = split (/:/, $server_string); + my $host = shift @server_params; + my @names = gethostbyname($host); + my $host_full_name = $names[0]; + my %ports = (); + if (defined $hosts_ports{$host_full_name}) { + %ports = %{$hosts_ports{$host_full_name}}; + }; + # To do: implement keys in form server:port -> priority + if (defined $hosts_ports{$host_full_name}) { + if (!$server_list_time_stamp) { + print "The $host with ip address " . inet_ntoa(inet_aton($host)) . " is at least two times in the server list\n"; + }; + } else { + print "Added server $host as $host_full_name\n"; + }; + if (scalar @server_params) { + $ports{$_}++ foreach (@server_params); + } else { + $ports{$_}++ foreach ($default_port .. $default_port + 4); + }; + $hosts_ports{$host_full_name} = \%ports; +}; + +sub read_server_list { + open(SERVER_LIST, "<$server_list_file") or return; + my $current_time_stamp = (stat($server_list_file))[9]; + return if ($server_list_time_stamp >= $current_time_stamp); + my @server_array = (); + foreach my $file_string(<SERVER_LIST>) { + while ($file_string =~ /(\S+)/) { + $file_string = $'; + store_server($1); + }; + }; + close SERVER_LIST; + $server_list_time_stamp = $current_time_stamp; +}; + +sub request_job { + my ($message, $current_server, $current_port) = @_; + $message = "platform=$ENV_BACKUP{OUTPATH} pid=$$ osname=$^O" if (!$message); + # create the socket, connect to the port + socket(SOCKET, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; + connect(SOCKET, $paddr) or return '';#die "connect: $!"; + my $error_code = 1; + $message .= "\n"; + syswrite SOCKET, $message, length $message; + while (my $line = <SOCKET>) { + chomp $line; + if ($line eq 'No job') { + close SOCKET or die "close: $!"; + return $line; + }; + if ($line eq "Wrong platform") { + if (!defined $platform_rejects{$paddr}) { + $platform_rejects{$paddr}++; + print STDERR $line . "\n"; + } + close SOCKET or die "close: $!"; + delete $hosts_ports{$current_server}; + return ''; + } elsif (defined $platform_rejects{$paddr}) { + delete $platform_rejects{$paddr}; + }; + $got_job++; + $error_code = do_job($line . " server=$current_server port=$current_port"); + } + close SOCKET or die "close: $!"; + return("result=$error_code pid=$$"); +} + +sub do_job { + my @job_parameters = split(/ /, shift); + my %job_hash = (); + my $last_param; + my $error_code; + print "Client $$@" . "$host\n"; + foreach (@job_parameters) { + if (/(=)/) { + $job_hash{$`} = $'; + $last_param = $`; + } else { + $job_hash{$last_param} .= " $_"; + }; + }; + $env_alias = $job_hash{server_pid} . '@' . $job_hash{server} . ':' . $job_hash{port}; + my $result = "1"; # default value + my $cmd_file = File::Temp::tmpnam($ENV_BACKUP{TMP}); + my $tmp_log_file = File::Temp::tmpnam($ENV_BACKUP{TMP}); + $job_temp_files{$tmp_log_file} = $job_hash{log}; + my $setenv_string = ''; + if (defined $job_hash{setenv_string}) { + # use configuration string from server + $setenv_string .= $job_hash{setenv_string}; + if ((defined $ENV{USE_SHELL}) && ($ENV{USE_SHELL} eq '4nt')) { + $cmd_file .= '.btm'; + }; + print "Environment: $setenv_string\n"; + + my $directory = $job_hash{job_dir}; + open (COMMAND_FILE, ">$cmd_file"); + print COMMAND_FILE "$setenv_string\n"; + if (!defined $job_hash{job_dir}) { + close COMMAND_FILE; + print "No job_dir, cmd file: $cmd_file\n"; + foreach (keys %job_hash) { + print "key: $_ $job_hash{$_}\n"; + }; + exit (1); + }; + + print COMMAND_FILE "pushd $job_hash{job_dir} && "; + print COMMAND_FILE $job_hash{job} ." >& $tmp_log_file\n"; + if ((defined $ENV{USE_SHELL}) && ($ENV{USE_SHELL} eq '4nt')) { + print COMMAND_FILE "exit %?\n"; + } else { + print COMMAND_FILE "exit \$?\n"; + }; + close COMMAND_FILE; + $job_temp_files{$cmd_file} = 0; + $job_temp_files{$tmp_log_file} = $job_hash{log}; + if ((defined $ENV{USE_SHELL}) && ($ENV{USE_SHELL} eq '4nt')) { + $error_code = system($ENV{COMSPEC}, '/c', $cmd_file); + } else { + $error_code = system($ENV{SHELL}, $cmd_file); + }; + unlink $cmd_file or system("rm -rf $cmd_file"); + delete $job_temp_files{$cmd_file}; + } else { + # generate setsolar string + if (!defined $environments{$env_alias}) { + $error_code = get_setsolar_environment(\%job_hash); + return($error_code) if ($error_code); + }; + my $solar_vars = $environments{$env_alias}; + + delete $ENV{$_} foreach (keys %ENV); + $ENV{$_} = $$solar_vars{$_} foreach (keys %$solar_vars); + print 'Workspace: '; + if (defined $ENV{CWS_WORK_STAMP}) { + print $ENV{CWS_WORK_STAMP}; + } else { + print $ENV{SOLARSRC}; + }; + + print "\nplatform: $ENV{INPATH} $^O"; + print "\ndir: $job_hash{job_dir}\n"; + print "job: $job_hash{job}\n"; + chdir $job_hash{job_dir}; + getcwd(); + my $job_string = $job_hash{job} . ' > ' . $tmp_log_file . ' 2>&1'; + $error_code = system($job_string); +# rename($tmp_log_file, $job_hash{log}) or system("mv", $tmp_log_file, $job_hash{log}); +# delete $job_temp_files{$tmp_log_file};# = $job_hash{log}; + }; + rename($tmp_log_file, $job_hash{log}) or system("mv", $tmp_log_file, $job_hash{log}); + delete $job_temp_files{$tmp_log_file}; + + if ($error_code) { + print "Error code = $error_code\n\n"; + } else { + print "Success!!\n\n"; + }; + return $error_code; +}; + +sub get_setsolar_environment { + my $job_hash = shift; + my $server_pid = $$job_hash{server_pid}; + my $setsolar_string = $$job_hash{setsolar_cmd}; + # Prepare the string for the client + $setsolar_string =~ s/\s-file\s\S+//g; + my $error_code = 0; + my $cmd_file = File::Temp::tmpnam($ENV_BACKUP{TMP}); + my $tmp_log_file = File::Temp::tmpnam($ENV_BACKUP{TMP}); + if ((defined $ENV{USE_SHELL}) && ($ENV{USE_SHELL} eq '4nt')) { + my $setsolar = $ENV{ENV_ROOT} . '/etools/setsolar.pl'; + $setsolar_string =~ s/^(\S+\s)\S+/$1$setsolar/; #replace the use of the local script with generic setsolar + $cmd_file .= '.btm'; + my $setsolar_tmp_file = File::Temp::tmpnam($ENV_BACKUP{TMP}); + $setsolar_tmp_file .= '.btm'; + open (COMMAND_FILE, ">$setsolar_tmp_file") or return $?; + print COMMAND_FILE "set SOURCE_ROOT=$$job_hash{source_root}\n" if ($$job_hash{source_root}); + print COMMAND_FILE "unset UPDATER\n" if (!defined $$job_hash{updater}); + print COMMAND_FILE "$setsolar_string -file $cmd_file"; + close COMMAND_FILE; + $error_code = system($ENV{COMSPEC}, '/c', $setsolar_tmp_file); + unlink $setsolar_tmp_file or system("rm -rf $setsolar_tmp_file"); + store_env_hash($cmd_file); + return $error_code; + }; + if (defined $$job_hash{updater}) { + $ENV{UPDATER} = $$job_hash{updater}; + } else { + undef $ENV{UPDATER} if (defined $ENV{UPDATER}); + }; + if (defined $$job_hash{source_root}) { + $ENV{SOURCE_ROOT} = $$job_hash{source_root}; + } else { + undef $ENV{SOURCE_ROOT} if (defined $ENV{SOURCE_ROOT}); + }; + $error_code = system("$setsolar_string -file $cmd_file"); + store_env_hash($cmd_file); + return $error_code; +}; + +sub print_error { + my $message = shift; + print STDERR "\nERROR: $message\n"; + exit(1); +}; +sub store_env_hash { + my $ss_setenv_file = shift;#($$job_hash{server_pid}.$$job_hash{setsolar_cmd}, $cmd_file); + my %solar_vars = (); + my $cmd_file = File::Temp::tmpnam($ENV_BACKUP{TMP}); + my $env_vars_file = File::Temp::tmpnam($ENV_BACKUP{TMP}); + print "$cmd_file $env_vars_file\n"; + #get all env variables in $env_vars_file + if ((defined $ENV{USE_SHELL}) && ($ENV{USE_SHELL} eq '4nt')) { + $cmd_file .= '.btm'; + open (COMMAND_FILE, ">$cmd_file"); + print COMMAND_FILE "call $ss_setenv_file\n"; + print COMMAND_FILE "set > $env_vars_file\n"; + close COMMAND_FILE; + system($ENV{COMSPEC}, '/c', $cmd_file); + } else { + open (COMMAND_FILE, ">$cmd_file"); + print COMMAND_FILE "source $ss_setenv_file\n"; + print COMMAND_FILE "env > $env_vars_file\n"; + close COMMAND_FILE; + system($ENV{SHELL}, $cmd_file); + }; + print_error($?) if ($?); + unlink $cmd_file or system("rm -rf $cmd_file"); + unlink $ss_setenv_file or system("rm -rf $ss_setenv_file"); + + open SOLARTABLE, "<$env_vars_file" or die "can´t open solarfile $env_vars_file"; + while(<SOLARTABLE>) { + chomp; + s/\r\n//o; + /(=)/; + $solar_vars{$`} = $'; + }; + close SOLARTABLE; + unlink $env_vars_file or system("rm -rf $env_vars_file"); + $environments{$env_alias} = \%solar_vars; +}; diff --git a/solenv/bin/checkapi b/solenv/bin/checkapi new file mode 100755 index 000000000000..4725045c9583 --- /dev/null +++ b/solenv/bin/checkapi @@ -0,0 +1,57 @@ +#!/bin/sh +PS=":" +# cygwin: +if [ "$GUI" = "WNT" ]; then + PS=";" +fi + +JARFOLDER=$SOLARVERSION/$INPATH/bin$UPDMINOREXT +SOLVER_LIB=$SOLARVERSION/$INPATH/lib$UPDMINOREXT + +if [ -n "$RUNNERJAR" ]; then + myCLASSPATH=$RUNNERJAR +else + myCLASSPATH=$JARFOLDER/OOoRunner.jar +fi + +myCLASSPATH=$myCLASSPATH${PS}${JARFOLDER}/ridl.jar${PS}${JARFOLDER}/unoil.jar${PS}${JARFOLDER}/jurt.jar${PS}${JARFOLDER}/juh.jar${PS}${JARFOLDER}/java_uno.jar +myCLASSPATH=$myCLASSPATH${PS}/net/unoapi/export/unoapi/bin/mysql.jar${PS}$SOLVER_LIB + +if [ -n "$JAVAI" ]; then + JAVABIN=$JAVAI +elif [ -n "$JAVA_HOME" ]; then + if [ "$OS$CPUNAME$CPU" = SOLARISSPARCU ]; then + JAVABIN=$JAVA_HOME/bin/sparcv9/java + else + JAVABIN=$JAVA_HOME/bin/java + fi +else + echo "please set environment variable JAVA_HOME" + exit 1 +fi + +if [ x${USER}x = xx ]; then + if [ x${LOGNAME}x = xx ]; then + echo "ERROR: could not determine username. Please export variable USER" >&2 + exit $EXIT_FAILURE + else + USER=$LOGNAME + export USER + fi +fi + +PARAM="-cs pipe,name=$USER -SRC_ROOT $SRC_ROOT" + +if [ -n "$RUNNERPROPS" ]; then + PARAM="$PARAM -runnerini $RUNNERPROPS" +fi + +MYXDEBUG="" +if [ -n "$XDEBUG" ]; then + # export XDEBUG="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8001" + MYXDEBUG=$XDEBUG +fi + +COMMAND="$JAVABIN -Xmx120m $MYXDEBUG -cp $myCLASSPATH org.openoffice.Runner $PARAM $*" +echo $COMMAND +$COMMAND diff --git a/solenv/bin/checkapi.btm b/solenv/bin/checkapi.btm new file mode 100644 index 000000000000..fde6802f50dd --- /dev/null +++ b/solenv/bin/checkapi.btm @@ -0,0 +1,44 @@ +rem @echo off + +setlocal + +SET JARFOLDER=%SOLARVERSION%\%INPATH%\bin%UPDMINOREXT% + +IFF "%RUNNERJAR%" != "" THEN + SET APICLASSPATH=%RUNNERJAR% +ELSE + SET APICLASSPATH=%JARFOLDER%\OOoRunner.jar +ENDIFF + +SET APICLASSPATH=%APICLASSPATH%;%JARFOLDER%\ridl.jar;%JARFOLDER%\unoil.jar;%JARFOLDER%\jurt.jar;%JARFOLDER%\juh.jar;%JARFOLDER%\java_uno.jar;\\unoapi\export\unoapi\bin\mysql.jar + +IFF "%JAVAI%" != "" THEN + SET JAVABIN=%JAVAI% +ELSEIFF "%JAVA_HOME%" != "" THEN + SET JAVABIN=%JAVA_HOME%\bin\java +ELSE + echo please set environment variable JAVA_HOME + exit 1 +ENDIFF + +SET PARAM=-cs pipe,name=%USERNAME% -SRC_ROOT %SRC_ROOT% + +IFF "%RUNNERPROPS%" != "" THEN + SET PARAM=%PARAM% -runnerini %RUNNERPROPS% +ENDIFF + +SET MYXDEBUG +IFF "%XDEBUG%" != "" THEN + REM SET XDEBUG=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8001 + SET MYXDEBUG=%XDEBUG +ENDIFF + +set COMMAND=%JAVABIN% -Xmx120m %MYXDEBUG -cp %APICLASSPATH% org.openoffice.Runner %PARAM% %& + + +echo %COMMAND +%COMMAND + +endlocal + +quit diff --git a/solenv/bin/checkdll.sh b/solenv/bin/checkdll.sh new file mode 100755 index 000000000000..878ad2606788 --- /dev/null +++ b/solenv/bin/checkdll.sh @@ -0,0 +1,97 @@ +#! /bin/sh +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: header.hxx,v $ +# +# $Revision: 1.1 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +# checkdll.sh - execute checkdll with all -L arguments to this script +# prepended to LD_LIBRARY_PATH + +set -- `getopt "L:" "$@"` || { + echo "Usage: `basename $0` [-L library_path] <shared_library>" 1>&2 + exit 1 +} + +checkdll="$SOLARVERSION/$INPATH/bin$UPDMINOREXT/checkdll" + +if [ -x $checkdll ]; then + while : + do + case $1 in + -L) shift; option=$1;; + --) break;; + esac + case "${libpath+X}" in + X) libpath=$libpath:$option;; + *) libpath=$option;; + esac + shift + done + shift # remove the trailing --- + + case `uname -s` in + Darwin) case "${DYLD_LIBRARY_PATH+X}" in + X) DYLD_LIBRARY_PATH=$libpath:$DYLD_LIBRARY_PATH;; + *) DYLD_LIBRARY_PATH=$libpath;; + esac + export DYLD_LIBRARY_PATH;; + IRIX) case "${LD_LIBRARYN32_PATH+X}" in + X) LD_LIBRARYN32_PATH=$libpath:$LD_LIBRARYN32_PATH;; + *) LD_LIBRARYN32_PATH=$libpath;; + esac + export LD_LIBRARYN32_PATH;; + IRIX64) case "${LD_LIBRARYN32_PATH+X}" in + X) LD_LIBRARYN32_PATH=$libpath:$LD_LIBRARYN32_PATH;; + *) LD_LIBRARYN32_PATH=$libpath;; + esac + export LD_LIBRARYN32_PATH;; + *) case "${LD_LIBRARY_PATH+X}" in + X) LD_LIBRARY_PATH=$libpath:$LD_LIBRARY_PATH;; + *) LD_LIBRARY_PATH=$libpath;; + esac + export LD_LIBRARY_PATH;; + esac + + $checkdll "$*" + if [ $? -ne 0 ]; then exit 1 ; fi + + for parameter in $*; do + library=$parameter; + done + realname=`echo $library | sed "s/check_//"` + if [ $library != $realname ]; then + LD_LIBRARY_PATH= + export LD_LIBRARY_PATH + mv $library $realname + fi +else + echo "WARNING: checkdll not found!" 1>&2 +fi + +exit 0 + diff --git a/solenv/bin/chrel.sed b/solenv/bin/chrel.sed new file mode 100644 index 000000000000..19455b00c252 --- /dev/null +++ b/solenv/bin/chrel.sed @@ -0,0 +1,2 @@ +s/\(\.\.\/\)\{2,4\}/..\//g +s/\(\.\.\\\)\{2,4\}/..\\/g diff --git a/solenv/bin/cleandiff.pl b/solenv/bin/cleandiff.pl new file mode 100644 index 000000000000..6b2e1fbe7244 --- /dev/null +++ b/solenv/bin/cleandiff.pl @@ -0,0 +1,49 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: cleandiff.pl,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +while (<>) +{ + next if /^Only in/ ; + next if /^diff -rc / ; + next if /^diff -ru / ; + next if /^Common sub/ ; + + if ( /^---/ || /^\*\*\*/ || /^\+\+\+/ ) + { + s/\\/\//g; + } + + print ; +} + diff --git a/solenv/bin/cleanzip.pl b/solenv/bin/cleanzip.pl new file mode 100755 index 000000000000..87ff24ffa7ef --- /dev/null +++ b/solenv/bin/cleanzip.pl @@ -0,0 +1,68 @@ +#!/usr/bin/perl -w +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: cleanzip.pl,v $ +# +# $Revision$ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +sub usage +{ + print "Cleanup unwanted unix attributes in zip archives\n\n"; + print "Usage:\n"; + print "$0 archive\n\n"; + exit(1); +} + +usage() if ! defined $ARGV[0]; + +my $filename = $ARGV[0]; +use Archive::Zip qw(:ERROR_CODES :CONSTANTS); +my $zip = Archive::Zip->new(); + +unless ( $zip->read( $filename ) == AZ_OK ) { + die "$0: ERROR reading $filename\n"; +} +my @members = $zip ->members(); + +foreach my $member ( @members ) { +# printf ( "%o\n",$member->unixFileAttributes()); +# printf ( "%o\n",$member->unixFileAttributes() & 0b111111111111); + my $attribs = $member->unixFileAttributes(); + if ( $member->isDirectory ) { + $attribs = $attribs & 0b101111111111; + $member->unixFileAttributes($attribs) + } +# printf ( "%o\n",$member->unixFileAttributes()); +# printf ( "%o\n",$member->unixFileAttributes() & 0b111111111111); +# print ( $member->fileName()."\n"); +} +unless ( $zip->writeToFileNamed( ${filename}."_new" ) == AZ_OK ) { + die "$0: ERROR reading ${filename}_new\n"; +} +rename($filename."_new", $filename); + diff --git a/solenv/bin/clipatchconfig.pl b/solenv/bin/clipatchconfig.pl new file mode 100644 index 000000000000..91025ea8c2be --- /dev/null +++ b/solenv/bin/clipatchconfig.pl @@ -0,0 +1,137 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: clipatchconfig.pl,v $ +# +# $Revision: 1.2 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +use warnings; +use strict; +use diagnostics; + +sub trim; +sub readRedirectionValues($); + +my $usage = + "Usage is: \n clipatchconfig.pl configTemplate redirections policyConfig + + configTemplate: The config file which is used for the policy assembly. It + contains place holders for the binding redirection. + + redirections: file containing the values for oldVersion and newVersion tags + which are used in the BindingRedirect element of the config files. + + policyConfig: Name of the file in which we want to write the config file. +"; + + +if (scalar @ARGV < 3) { + print $usage; + exit -1; +} + + +my %redirectionValue = readRedirectionValues($ARGV[1]); +#print "|$_| |$redirectionValue{$_}|\n", for keys %redirectionValue; + + +#Read config file in which we will replace the versions +$/ = undef; +open TEMPLATE, $ARGV[0] or die $!; +my $templ = <TEMPLATE>; + +#Open the config file we are goint to write to +open CONFIG, "> $ARGV[2]" or die "Cannot write to $ARGV[2] $!"; + +#No substitute the place holders for oldVersion and new Version in the config template with +#the values obtained from the redirections file +for (keys %redirectionValue) { + $templ=~ s/\b$_\b/$redirectionValue{$_}/; +} +#Write the config file +print CONFIG $templ; + +#Reads the key value pairs from the files, which name must be passed in +#the parameter. The file contains lines of the form name=value, for example +#CLI_URETYPES_OLD_VERSION=1.1.0.0-1.1.1.0 +sub readRedirectionValues($) +{ + #Read in the values for the version redirection + open REDIR, $_[0] or die $!; + + my %redirectionValues; + + while (<REDIR>) + { + chomp; + my $trimmed; + #Skip empty lines + if (length($trimmed = trim($_)) == 0) { + next; + } + + #Skip comment symbol: # + if ($trimmed =~ /^#/) { + next; + } + + my @lineParts = split /=/,$_; + + #Check if we have valid name value pairs. + if (scalar @lineParts != 2) { + print "Error: Values in $ARGV[1] are not correct (Entries must have the form name=value). Invalid line: \n$_\n"; + exit -1; + } + + #Trim the strings and check if they still contain characters + my $name = trim($lineParts[0]); + my $value = trim($lineParts[1]); + if (length($name) == 0 || length($value) == 0) { + print "Error: Values in $ARGV[1] are not correct. Invalid line: \n$_\n"; + exit -1; + } + + #Check if we have duplicate key names + for (keys %redirectionValues) { + if ( $name eq $_) { + print "Error: Values in $ARGV[1] are not correct. The name $_ is not unique.\n"; + exit -1; + } + } + + $redirectionValues{$name} = $value; + } + return %redirectionValues; +} + +sub trim($) +{ + my $string = shift; + $string =~ s/^\s+//; + $string =~ s/\s+$//; + return $string; +} diff --git a/solenv/bin/convertlinks.pl b/solenv/bin/convertlinks.pl new file mode 100644 index 000000000000..c8644aa4c9af --- /dev/null +++ b/solenv/bin/convertlinks.pl @@ -0,0 +1,122 @@ +# +# convertlinks - a perl script to make hrefs to +# http://api.openoffice.org/common/ref relativ. +# +# Copyright (c) 2000 Sun Microsystems, Inc. +# + +use File::Find; + +# for the convenience of &wanted calls, including -eval statements: +use vars qw/*name *dir/; +*name = *File::Find::name; +*dir = *File::Find::dir; +@files = (); + +if($#ARGV == 1) +{ + $pattern = "www"; +} else +{ + $pattern = $ARGV[2]; +} + +find(\&wanted, "$ARGV[0]"); + +$return = 1; + +foreach $i (@files) +{ + next if( $i->{directory} =~ /.*common((\/|\\)ref(.*))/ || + $i->{directory} =~ /.*cpp((\/|\\)ref(.*))/ || + $i->{directory} =~ /.*java((\/|\\)ref(.*))/ ); + + open ( FILEIN, $i->{filename} ) || die "could not open $i->{filename} for reading"; + + $relPath = "."; + $relToSource = "."; + if( $i->{directory} =~ /.*$pattern((\/|\\)(.*))/ ) + { + $relPath = $3; + $relPath =~ s#\w+#\.\.#go; + if($pattern eq "examples") + { + $relPath = "\.\.\/$relPath"; + } + if($pattern eq "www") + { + $relToSource = "\.\.\/$relPath"; + } else + { + $relToSource = $relPath; + } + } else + { + if($pattern eq "examples") + { + $relPath = "\.\."; + } + if($pattern eq "www") + { + $relToSource = "\.\."; + } else + { + $relToSource = $relPath; + } + } + + @lines = <FILEIN>; + close( FILEIN ); + open( FILEOUT, ">$i->{filename}.tmp" ) || die "could not open $i->{filename} for writing"; + foreach $_ (@lines) + { + # change the refenreces to the index in dependency of UDK or ODK + if("$ARGV[1]" eq "udk_" | "$ARGV[1]" eq "odk_") + { + s#((\")(index.html\"))#$2$ARGV[1]$3#go; + s#((\/|\")(faq.html\"))#$2$ARGV[1]$3#go; + s#((\/|\")(bylaws.html\"))#$2$ARGV[1]$3#go; + } + + s#((http:\/\/api\.openoffice\.org\/)(common\/ref[^\"]+))#$relPath\/$3#go; + s#((http:\/\/api\.openoffice\.org\/unbranded-source\/)(.*)(examples\/examples.html))#$relToSource\/$4#go; + + if($pattern eq "examples") + { + # change the links for the C++/Java examples in the ODK + s#((http:\/\/api\.openoffice\.org\/source\/browse\/api\/odk\/examples\/)(java\/*))#$3#go; + s#((http:\/\/api\.openoffice\.org\/source\/browse\/api\/odk\/examples\/)(cpp\/*))#$3#go; + s#((http:\/\/api\.openoffice\.org\/source\/browse\/api\/odk\/examples\/)(basic\/*))#$3#go; + s#((http:\/\/api\.openoffice\.org\/source\/browse\/api\/odk\/examples\/)(OLE\/*))#$3#go; + + # change link api specific stuff + s#((http:\/\/api\.openoffice\.org\/)(design_guide.html))#$relPath\/www\/$3#go; + s#(http:\/\/api\.openoffice\.org\/index.html)#$relPath\/www\/odk_index.html#go; + + # change the links for the C++ examples in the UDK + s#((http:\/\/udk\.openoffice\.org\/source\/browse\/udk\/product\/examples\/)(cpp\/*))#$3#go; + + # change the links to udk.openoffice.org to relativ links + s#(http:\/\/udk\.openoffice\.org\/index.html)#$relPath\/www\/udk_index.html#go; + s#((http:\/\/udk\.openoffice\.org)(\/*))#$relPath\/www$3#go; + + # change the link to tutorial + s#((http:\/\/api\.openoffice\.org\/)(basic\/man\/tutorial\/tutorial.pdf))#$relPath\/www\/$3#go; + } + print FILEOUT $_; + } + close FILEOUT; + chmod 0666, $i->{filename}; + rename "$i->{filename}.tmp", $i->{filename} || die "could not rename $i->{filename}.tmp to $i->{filename}"; + $return = 0; +} + +exit $return; + +sub wanted { + %file = ( + directory => $dir, + filename => $name + ); + push @files, {%file} if /^.*\.html\z/s; +} diff --git a/solenv/bin/converttags.pl b/solenv/bin/converttags.pl new file mode 100644 index 000000000000..641b83d696b6 --- /dev/null +++ b/solenv/bin/converttags.pl @@ -0,0 +1,94 @@ +# +# converttags - a perl script to coonvert some predefined tags +# to user specified values +# +# Copyright (c) 2000 Sun Microsystems, Inc. +# + +if($#ARGV == -1) +{ + die "No parameters were specified.\nperl converttags.pl <mode> <title> <productname> [<color1>] [<color2>] file_1 [... file_n]\n"; +} +if($#ARGV < 2) +{ + die "No file were specified -> no file must be converted!\n"; +} + +# mode = 1 -> convert +# = 2 -> exit without conversion +$mode = shift @ARGV; + +$title = shift @ARGV; +$productname = shift @ARGV; + +$color1 = ""; +$color2 = ""; + +if( $mode =~ s/2/$1/go ) +{ + exit 0; +} + +if( $ARGV[0] =~ s/(#[\w]{6})/$1/go ) +{ + $color1 = shift @ARGV; +} +if( $ARGV[0] =~ s/(#[\w]{6})/$1/go ) +{ + $color2 = shift @ARGV; +} + +print "$title\n"; +print "$productname\n"; +print "$color1\n"; +print "$color2\n"; + +$return = 0; + +while (@ARGV) +{ + my $lineCount = 0; + $ARGV = shift @ARGV; + print "convert tags: $ARGV "; + + open ( FILEIN, $ARGV ) || die "could not open $ARGV for reading"; + @lines = <FILEIN>; + close( FILEIN ); + open( FILEOUT, ">$ARGV.tmp" ) || die "could not open $ARGV.tmp for writing"; + + + foreach $_ (@lines) + { + $lineCount++; + if ( $lineCount == 10 ) + { + $lineCount = 0; + print "."; + } + # change [TITLE] tag + s#\[TITLE\]#$title#go; + + # change [PRODUCTNAME] tag + s#\[PRODUCTNAME\]#$productname#go; + + # change color #003399 to #$color1 if color1 was specified! + if ( ! "$color1" eq "" ) + { + s/#003399/$color1/go; + } + + # change color #99CCFF to #$color2 if color2 was specified! + if ( ! "$color2" eq "" ) + { + s/#99CCFF/$color2/go; + } + print FILEOUT $_; + } + print " OK\n"; + + close FILEOUT; + chmod 0666, $ARGV; + rename "$ARGV.tmp", $ARGV || die "could not rename $ARGV.tmp to $ARGV"; +} + +exit $return; diff --git a/solenv/bin/createpdbrelocators b/solenv/bin/createpdbrelocators new file mode 100755 index 000000000000..40a44e8f2e7c --- /dev/null +++ b/solenv/bin/createpdbrelocators @@ -0,0 +1,7 @@ +#!/bin/sh +if [ x${SOLARENV}x = xx ]; then + echo createpdbrelocators: no environment found! + exit 1 +fi +exec perl -w $SOLARENV/bin/createpdbrelocators.pl + diff --git a/solenv/bin/createpdbrelocators.btm b/solenv/bin/createpdbrelocators.btm new file mode 100644 index 000000000000..fe68d5572f3d --- /dev/null +++ b/solenv/bin/createpdbrelocators.btm @@ -0,0 +1,9 @@ +@echo off +iff "%SOLARENV%" == "" then + echo Please configure environment with setsolar +endiff +iff "%PERL%" == "" then + call perl5 -I%SOLARENV%\bin\modules %SOLARENV%\bin\createpdbrelocators.pl %1& +else + call %PERL% -I%SOLARENV%\bin\modules %SOLARENV%\bin\createpdbrelocators.pl %1& +endiff diff --git a/solenv/bin/createpdbrelocators.pl b/solenv/bin/createpdbrelocators.pl new file mode 100644 index 000000000000..66c4301be61e --- /dev/null +++ b/solenv/bin/createpdbrelocators.pl @@ -0,0 +1,85 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: createpdbrelocators.pl,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +#************************************************************************* +# +# createpdbrelocators - create for pdb relocator files +# PDB relocator files are used to find debug infos +# for analysis of creash reports +# +# usage: createpdbrelocators; +# +#************************************************************************* + +use strict; + +#### module lookup + +use lib ("$ENV{SOLARENV}/bin/modules"); +use CreatePDBRelocators; + +#### script id ##### + +( my $script_name = $0 ) =~ s/^.*\b(\w+)\.pl$/$1/; + +my $script_rev; +my $id_str = ' $Revision: 1.5 $ '; +$id_str =~ /Revision:\s+(\S+)\s+\$/ + ? ($script_rev = $1) : ($script_rev = "-"); + +print "$script_name -- version: $script_rev\n"; + +my $inpath = $ENV{INPATH}; +my $milestone = $ENV{UPDMINOR}; + +if ( $ARGV[0] ) { + if ( $milestone && ( $milestone ne $ARGV[0] ) ) { + die "Error: specified milestone $ARGV[0] does not match your environment"; + } + $milestone = $ARGV[0]; +} + +if ( !$inpath || !$milestone ) { + print STDERR "$script_name: INAPTH or UPDMINOR not set!\n"; + exit(1); +} + +my $rc = CreatePDBRelocators::create_pdb_relocators($inpath, $milestone, ""); + +if ( !$rc ) { + print STDERR "$script_name: creating PDB relocators failed!\n"; + exit(2); +} + +exit(0); diff --git a/solenv/bin/cws b/solenv/bin/cws new file mode 100755 index 000000000000..e8bcf5060f39 --- /dev/null +++ b/solenv/bin/cws @@ -0,0 +1,6 @@ +#!/bin/sh +if [ x${SOLARENV}x = xx ]; then + echo No environment found, please use 'configure' + exit 1 +fi +exec perl -w $SOLARENV/bin/cws.pl "$@" diff --git a/solenv/bin/cws.btm b/solenv/bin/cws.btm new file mode 100644 index 000000000000..31bff3ab2d0f --- /dev/null +++ b/solenv/bin/cws.btm @@ -0,0 +1,11 @@ +@echo off +iff "%SOLARENV%" == "" then + echo No environment found, please use 'configure' or 'setsolar' + goto end +endiff +iff "%PERL%" == "" then + call perl5 -I%SOLARENV%\bin\modules %SOLARENV%\bin\cws.pl %1& +else + call %PERL% -I%SOLARENV%\bin\modules %SOLARENV%\bin\cws.pl %1& +endiff +:end diff --git a/solenv/bin/cws.pl b/solenv/bin/cws.pl new file mode 100644 index 000000000000..bca7fe3cc271 --- /dev/null +++ b/solenv/bin/cws.pl @@ -0,0 +1,2559 @@ +#!/usr/bin/perl -w +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: cws.pl,v $ +# +# $Revision: 1.1.2.14 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +#************************************************************************* +# +# cws.pl - wrap common childworkspace operations +# +use strict; +use Getopt::Long; +use File::Basename; +use File::Path; +use Cwd; + +#### module lookup +my @lib_dirs; +BEGIN { + if ( !defined($ENV{SOLARENV}) ) { + die "No environment found (environment variable SOLARENV is undefined)"; + } + push(@lib_dirs, "$ENV{SOLARENV}/bin/modules"); +} +use lib (@lib_dirs); + +use Cws; + +#### script id ##### + +( my $script_name = $0 ) =~ s/^.*\b(\w+)\.pl$/$1/; + +#### globals #### + +# valid command with possible abbreviations +my @valid_commands = ( + 'help', 'h', '?', + 'create', + 'fetch', 'f', + 'rebase', 'rb', + 'analyze', 'an', + 'query', 'q', + 'task', 't', + 'integrate', + 'cdiff', 'cd', + 'eisclone' + ); + +# list the valid options to each command +my %valid_options_hash = ( + 'help' => ['help'], + 'create' => ['help', 'milestone', 'migration'], + 'fetch' => ['help', 'switch', 'milestone', 'childworkspace','platforms','quiet', + 'onlysolver'], + 'rebase' => ['help', 'milestone','commit'], + 'analyze' => ['help'], + 'query' => ['help', 'milestone','masterworkspace','childworkspace'], + 'task' => ['help'], + 'integrate' => ['help', 'childworkspace'], + 'cdiff' => ['help', 'childworkspace', 'masterworkspace', 'files', 'modules'], + 'eisclone' => ['help'] + ); + +my %valid_commands_hash; +for (@valid_commands) { + $valid_commands_hash{$_}++; +} + +# set by --debug switch +my $debug = 0; + +#### main #### + +my ($command, $args_ref, $options_ref) = parse_command_line(); +dispatch_command($command, $args_ref, $options_ref); +exit(0); + +#### subroutines #### + +# Parses the command line. does prelimiary argument and option verification +sub parse_command_line +{ + if (@ARGV == 0) { + usage(); + exit(1); + } + + my %options_hash; + Getopt::Long::Configure ("no_auto_abbrev", "no_ignorecase"); + my $success = GetOptions(\%options_hash, 'milestone|m=s', + 'masterworkspace|master|M=s', + 'migration', + 'childworkspace|child|c=s', + 'debug', + 'commit|C', + 'switch|s', + 'platforms|p=s', + 'onlysolver|o', + 'quiet|q', + 'files', + 'modules', + 'help|h' + ); + + my $command = shift @ARGV; + + if (!exists $valid_commands_hash{$command}) { + print_error("Unkown command: '$command'\n"); + usage(); + exit(1); + } + + if ($command eq 'h' || $command eq '?') { + $command = 'help'; + } + elsif ($command eq 'f') { + $command = 'fetch'; + } + elsif ($command eq 'rb') { + $command = 'rebase'; + } + elsif ($command eq 'an') { + $command = 'analyze'; + } + elsif ($command eq 'q') { + $command = 'query'; + } + elsif ($command eq 't') { + $command = 'task'; + } + elsif ($command eq 'cd') { + $command = 'cdiff'; + } + + # An unkown option might be accompanied with a valid command. + # Show the command specific help + if ( !$success ) { + do_help([$command]) + } + + verify_options($command, \%options_hash); + return ($command, \@ARGV, \%options_hash); +} + +# Verify options against the valid options list. +sub verify_options +{ + my $command = shift; + my $options_ref = shift; + + my $valid_command_options_ref = $valid_options_hash{$command}; + + my %valid_command_options_hash; + foreach (@{$valid_command_options_ref}) { + $valid_command_options_hash{$_}++; + } + + # check all specified options against the valid options for the sub command + foreach (keys %{$options_ref}) { + if ( /debug/ ) { + $debug = 1; + next; + } + if (!exists $valid_command_options_hash{$_}) { + print_error("can't use option '--$_' with subcommand '$command'.", 1); + } + } + + # TODO here should be specific checks for the arguments + # if the check is globally valid +} + +# Dispatches to the do_xxx() routines depending on command. +sub dispatch_command +{ + my $command = shift; + my $args_ref = shift; + my $options_ref = shift; + + no strict 'refs'; + &{"do_".$command}($args_ref, $options_ref); +} + +# Returns the global cws object. +BEGIN { +my $the_cws; + + sub get_this_cws { + if (!defined($the_cws)) { + $the_cws = Cws->new(); + return $the_cws; + } + else { + return $the_cws; + } + } +} + +# Returns a list of the master workspaces. +sub get_master_workspaces +{ + my $cws = get_this_cws(); + my @masters = $cws->get_masters(); + + return wantarray ? @masters : \@masters; +} + +# Checks if master argument is a valid MWS name. +BEGIN { + my %master_hash; + + sub is_master + { + my $master_name = shift; + + if (!%master_hash) { + my @masters = get_master_workspaces(); + foreach (@masters) { + $master_hash{$_}++; + } + } + return exists $master_hash{$master_name} ? 1 : 0; + } +} + +# Fetches milestone URL for given server and milestone. +sub get_milestone_url +{ + my $server = shift; + my $master = shift; + my $milestone = shift; + + my $milestone_url = "$server/tags/${master}_${milestone}"; + return $milestone_url; +} + +# Fetches CWS URL for given server and CWSname. +sub get_cws_url +{ + my $server = shift; + my $cws = shift; + + my $cws_url = "$server/cws/$cws"; + return $cws_url; +} + +sub get_master_url +{ + my $server = shift; + my $master = shift; + my $revision = shift; + + my $url = "${server}/"; + + # TODO: update EIS function for subversion + my $cws = get_this_cws(); + my $trunk = $cws->get_cvs_head(); + if ( $master eq $trunk ) { + $url .= 'trunk'; + } + else { + my $master_label = uc($master); + $url .= "branches/$master_label"; + } + + # attach revision if needed + if ( $revision != 0 ) { + $url .= "\@$revision"; + } + return $url; +} + +# Returns the URL shortened by the server part +sub get_short_url +{ + my $server = shift; + my $url = shift; + + my $offset = length("$server/"); + $url = substr($url, $offset); + + return $url; +} + + +# Fetches the current CWS from environment, returns a Cws object +sub get_cws_from_environment +{ + my $child = $ENV{CWS_WORK_STAMP}; + my $master = $ENV{WORK_STAMP}; + + if ( !$child ) { + print_error("Environment variable CWS_WORK_STAMP is not set. Please set it to your CWS name.", 2); + } + + if ( !$master ) { + print_error("Environment variable WORK_STAMP is not set. Please set it to the MWS name.", 2); + } + + my $cws = get_this_cws(); + $cws->child($child); + $cws->master($master); + + # Check if we got a valid child workspace. + my $id = $cws->eis_id(); + if ( $debug ) { + print STDERR "CWS-DEBUG: ... master: $master, child: $child, $id\n"; + } + if ( !$id ) { + print_error("Child workspace $child for master workspace $master not found in EIS database.", 2); + } + return ($cws); +} + +# Fetches the CWS by name, returns a Cws object +sub get_cws_by_name +{ + my $child = shift; + + my $cws = get_this_cws(); + $cws->child($child); + + # Check if we got a valid child workspace. + my $id = $cws->eis_id(); + if ( $debug ) { + print STDERR "CWS-DEBUG: child: $child, $id\n"; + } + if ( !$id ) { + print_error("Child workspace $child not found in EIS database.", 2); + } + + # Update masterws part of Cws object. + my $masterws = $cws->get_mws(); + $cws->master($masterws); + return ($cws); +} + +# Register child workspace with eis. +sub register_child_workspace +{ + my $cws = shift; + my $is_promotion = shift; + + my $milestone = $cws->milestone(); + my $child = $cws->child(); + my $master = $cws->master(); + + # TODO: introduce a EIS_USER in the configuration, which should be used here + my $config = CwsConfig->new(); + my $vcsid = $config->vcsid(); + # TODO: there is no real need for socustom anymore, should go ASAP + my $socustom = $config->sointernal(); + + if ( !$vcsid ) { + if ( $socustom ) { + print_error("Can't determine owner for CWS '$child'. Please set VCSID environment variable.", 11); + } + else { + print_error("Can't determine owner for CWS '$child'. Please set CVS_ID entry in \$HOME/.cwsrc.", 11); + } + } + + if ( $is_promotion ) { + my $rc = $cws->set_subversion_flag(1); + if ( !$rc ) { + print_error("Failed to set subversion flag on child workspace '$child'.\nContact EIS administrator!\n", 12); + } + + $rc = $cws->promote($vcsid, ""); + + if ( !$rc ) { + print_error("Failed to promote child workspace '$child' to status 'new'.\n", 12); + } + else { + print "\n***** Successfully ***** promoted child workspace '$child' to status 'new'.\n"; + print "Milestone: '$milestone'.\n"; + } + } + else { + + my $eis_id = $cws->register($vcsid, ""); + + if ( !defined($eis_id) ) { + print_error("Failed to register child workspace '$child' for master '$master'.", 12); + } + else { + my $rc = $cws->set_subversion_flag(1); + if ( !$rc ) { + print_error("Failed to set subversion flag on child workspace '$child'.\nContact EIS administrator!\n", 12); + } + print "\n***** Successfully ***** registered child workspace '$child'\n"; + print "for master workspace '$master' (milestone '$milestone').\n"; + print "Child workspace Id: $eis_id.\n"; + } + } + return 0; +} + +sub query_cws +{ + my $query_mode = shift; + my $options_ref = shift; + # get master and child workspace + my $masterws = exists $options_ref->{'masterworkspace'} ? uc($options_ref->{'masterworkspace'}) : $ENV{WORK_STAMP}; + my $childws = exists $options_ref->{'childworkspace'} ? $options_ref->{'childworkspace'} : $ENV{CWS_WORK_STAMP}; + my $milestone = exists $options_ref->{'milestone'} ? $options_ref->{'milestone'} : 'latest'; + + if ( !defined($masterws) && $query_mode ne 'masters') { + print_error("Can't determine master workspace environment.\n", 30); + } + + if ( ($query_mode eq 'integratedinto' || $query_mode eq 'incompatible' || $query_mode eq 'taskids' || $query_mode eq 'state' || $query_mode eq 'current' || $query_mode eq 'owner' || $query_mode eq 'qarep' || $query_mode eq 'issubversion' || $query_mode eq 'ispublic' || $query_mode eq 'build') && !defined($childws) ) { + print_error("Can't determine child workspace environment.\n", 30); + } + + my $cws = Cws->new(); + if ( defined($childws) ) { + $cws->child($childws); + } + if ( defined($masterws) ) { + $cws->master($masterws); + } + + no strict; + &{"query_".$query_mode}($cws, $milestone); + return; +} + +sub query_integratedinto +{ + my $cws = shift; + + if ( is_valid_cws($cws) ) { + my $milestone = $cws->get_milestone_integrated(); + print_message("Integrated into:"); + print defined($milestone) ? "$milestone\n" : "unkown\n"; + } + return; +} + +sub query_incompatible +{ + my $cws = shift; + + if ( is_valid_cws($cws) ) { + my @modules = $cws->incompatible_modules(); + print_message("Incompatible Modules:"); + foreach (@modules) { + if ( defined($_) ) { + print "$_\n"; + } + } + } + return; +} + +sub query_taskids +{ + my $cws = shift; + + if ( is_valid_cws($cws) ) { + my @taskids = $cws->taskids(); + print_message("Task ID(s):"); + foreach (@taskids) { + if ( defined($_) ) { + print "$_\n"; + } + } + } + return; +} + +sub query_status +{ + my $cws = shift; + + if ( is_valid_cws($cws) ) { + my $status = $cws->get_approval(); + if ( !$status ) { + print_error("Internal error: can't get approval status.", 3); + } else { + print_message("Approval status:"); + print "$status\n"; + } + } + return; +} + +sub query_vcs +{ + my $cws = shift; + my $masterws = $cws->master(); + my $childws = $cws->child(); + + if ( is_valid_cws($cws) ) { + my $issvn = $cws->get_subversion_flag(); + if ( !defined($issvn) ) { + print_error("Internal error: can't get isSubVersion flag.", 3); + } else { + if ( $issvn==1 ) { + print_message("Child workspace uses SubVersion"); + } else { + print_message("Child workspace uses CVS"); + } + } + } + + # check if we got a valid child workspace + my $id = $cws->eis_id(); + if ( !$id ) { + print_error("Child workspace '$childws' for master workspace '$masterws' not found in EIS database.", 2); + } + + return; +} + +sub query_ispublic +{ + my $cws = shift; + my $masterws = $cws->master(); + my $childws = $cws->child(); + + if ( is_valid_cws($cws) ) { + my $ispublic = $cws->get_public_flag(); + if ( !defined($ispublic) ) { + print_error("Internal error: can't get isPublic flag.", 3); + } else { + if ( $ispublic==1 ) { + print_message("Child workspace is public"); + } else { + print_message("Child workspace is internal"); + } + } + } + + # check if we got a valid child workspace + my $id = $cws->eis_id(); + if ( !$id ) { + print_error("Child workspace '$childws' for master workspace '$masterws' not found in EIS database.", 2); + } + + return; +} + +sub query_current +{ + my $cws = shift; + + if ( is_valid_cws($cws) ) { + my $milestone = $cws->milestone(); + if ( !$milestone ) { + print_error("Internal error: can't get current milestone.", 3); + } else { + print_message("Current milestone:"); + print "$milestone\n"; + } + } + return; +} + +sub query_owner +{ + my $cws = shift; + + if ( is_valid_cws($cws) ) { + my $owner = $cws->get_owner(); + print_message("Owner:"); + if ( !$owner ) { + print "not set\n" ; + } else { + print "$owner\n"; + } + } + return; +} + +sub query_qarep +{ + my $cws = shift; + + if ( is_valid_cws($cws) ) { + my $qarep = $cws->get_qarep(); + print_message("QA Representative:"); + if ( !$qarep ) { + print "not set\n" ; + } else { + print "$qarep\n"; + } + } + return; +} + + +sub query_build +{ + my $cws = shift; + + if ( is_valid_cws($cws) ) { + my $build = $cws->get_build(); + print_message("Build:"); + if ( $build ) { + print "$build\n"; + } + } + return; +} + +sub query_latest +{ + my $cws = shift; + + my $masterws = $cws->master(); + my $latest = $cws->get_current_milestone($masterws); + + + if ( $latest ) { + print_message("Master workspace '$masterws':"); + print_message("Latest milestone available for rebase:"); + print "$masterws $latest\n"; + } + else { + print_error("Can't determine latest milestone of '$masterws' available for rebase.", 3); + } + + return; +} + +sub query_masters +{ + my $cws = shift; + + my @mws = $cws->get_masters(); + my $list=""; + + if ( @mws ) { + foreach (@mws) { + if ( $list ne "" ) { + $list .= ", "; + } + $list .= $_; + } + print_message("Master workspaces available: $list"); + } + else { + print_error("Can't determine masterworkspaces.", 3); + } + + return; +} + +sub query_milestones +{ + my $cws = shift; + my $masterws = $cws->master(); + + my @milestones = $cws->get_milestones($masterws); + my $list=""; + + if ( @milestones ) { + foreach (@milestones) { + if ( $list ne "" ) { + $list .= ", "; + } + $list .= $_; + } + print_message("Master workspace '$masterws':"); + print_message("Milestones known on Master: $list"); + } + else { + print_error("Can't determine milestones of '$masterws'.", 3); + } + + return; +} + +sub query_ispublicmaster +{ + my $cws = shift; + my $masterws = $cws->master(); + + my $ispublic = $cws->get_publicmaster_flag(); + my $list=""; + + if ( defined($ispublic) ) { + print_message("Master workspace '$masterws':"); + if ( !defined($ispublic) ) { + print_error("Internal error: can't get isPublicMaster flag.", 3); + } else { + if ( $ispublic==1 ) { + print_message("Master workspace is public"); + } else { + print_message("Master workspace is internal"); + } + } + } + else { + print_error("Can't determine isPublicMaster flag of '$masterws'.", 3); + } + + return; +} + +sub query_buildid +{ + my $cws = shift; + my $milestone = shift; + + my $masterws = $cws->master(); + if ( $milestone eq 'latest' ) { + $milestone = $cws->get_current_milestone($masterws); + } + + if ( !$milestone ) { + print_error("Can't determine latest milestone of '$masterws'.", 3); + } + + if ( !$cws->is_milestone($masterws, $milestone) ) { + print_error("Milestone '$milestone' is no a valid milestone of '$masterws'.", 3); + } + + my $buildid = $cws->get_buildid($masterws, $milestone); + + + if ( $buildid ) { + print_message("Master workspace '$masterws':"); + print_message("BuildId for milestone '$milestone':"); + print("$buildid\n"); + } + + return; +} + +sub query_integrated +{ + my $cws = shift; + my $milestone = shift; + + my $masterws = $cws->master(); + if ( $milestone eq 'latest' ) { + $milestone = $cws->get_current_milestone($masterws); + } + + if ( !$milestone ) { + print_error("Can't determine latest milestone of '$masterws'.", 3); + } + + if ( !$cws->is_milestone($masterws, $milestone) ) { + print_error("Milestone '$milestone' is no a valid milestone of '$masterws'.", 3); + } + + my @integrated_cws = $cws->get_integrated_cws($masterws, $milestone); + + + if ( @integrated_cws ) { + print_message("Master workspace '$masterws':"); + print_message("Integrated CWSs for milestone '$milestone':"); + foreach (@integrated_cws) { + print "$_\n"; + } + } + + return; +} + +sub query_approved +{ + my $cws = shift; + + my $masterws = $cws->master(); + + my @approved_cws = $cws->get_cws_with_state($masterws, 'approved by QA'); + + if ( @approved_cws ) { + print_message("Master workspace '$masterws':"); + print_message("CWSs approved by QA:"); + foreach (@approved_cws) { + print "$_\n"; + } + } + + return; +} + +sub query_nominated +{ + my $cws = shift; + + my $masterws = $cws->master(); + + my @nominated_cws = $cws->get_cws_with_state($masterws, 'nominated'); + + if ( @nominated_cws ) { + print_message("Master workspace '$masterws':"); + print_message("Nominated CWSs:"); + foreach (@nominated_cws) { + print "$_\n"; + } + } + + return; +} + +sub query_ready +{ + my $cws = shift; + + my $masterws = $cws->master(); + + my @ready_cws = $cws->get_cws_with_state($masterws, 'ready for QA'); + + if ( @ready_cws ) { + print_message("Master workspace '$masterws':"); + print_message("CWSs ready for QA:"); + foreach (@ready_cws) { + print "$_\n"; + } + } + + return; +} + +sub query_new +{ + my $cws = shift; + + my $masterws = $cws->master(); + + my @ready_cws = $cws->get_cws_with_state($masterws, 'new'); + + if ( @ready_cws ) { + print_message("Master workspace '$masterws':"); + print_message("CWSs with state 'new':"); + foreach (@ready_cws) { + print "$_\n"; + } + } + + return; +} + +sub query_planned +{ + my $cws = shift; + + my $masterws = $cws->master(); + + my @ready_cws = $cws->get_cws_with_state($masterws, 'planned'); + + if ( @ready_cws ) { + print_message("Master workspace '$masterws':"); + print_message("CWSs with state 'planned':"); + foreach (@ready_cws) { + print "$_\n"; + } + } + + return; +} + +sub is_valid_cws +{ + my $cws = shift; + + my $masterws = $cws->master(); + my $childws = $cws->child(); + # check if we got a valid child workspace + my $id = $cws->eis_id(); + if ( !$id ) { + print_error("Child workspace '$childws' for master workspace '$masterws' not found in EIS database.", 2); + } + print STDERR "Master workspace '$masterws', child workspace '$childws'\n"; + return 1; +} + +sub query_release +{ + my $cws = shift; + + if ( is_valid_cws($cws) ) { + my $release = $cws->get_release(); + print_message("Release target:"); + if ( !$release ) { + print "not set\n"; + } else { + print "$release\n"; + } + } + return; +} + +sub query_due +{ + my $cws = shift; + + if ( is_valid_cws($cws) ) { + my $due = $cws->get_due_date(); + print_message("Due date:"); + if ( !$due ) { + print "not set\n"; + } else { + print "$due\n"; + } + } + return; +} + +sub query_due_qa +{ + my $cws = shift; + + if ( is_valid_cws($cws) ) { + my $due_qa = $cws->get_due_date_qa(); + print_message("Due date (QA):"); + if ( !$due_qa ) { + print "not set\n"; + } else { + print "$due_qa\n"; + } + } + return; +} + +sub query_help +{ + my $cws = shift; + + if ( is_valid_cws($cws) ) { + my $help = $cws->is_helprelevant(); + print_message("Help relevant:"); + if ( !$help ) { + print "false\n"; + } else { + print "true\n"; + } + } + return; +} + +sub query_ui +{ + my $cws = shift; + + if ( is_valid_cws($cws) ) { + my $help = $cws->is_uirelevant(); + print_message("UI relevant:"); + if ( !$help ) { + print "false\n"; + } else { + print "true\n"; + } + } + return; +} + +sub verify_milestone +{ + my $cws = shift; + my $qualified_milestone = shift; + + my $invalid = 0; + my ($master, $milestone); + $invalid++ if $qualified_milestone =~ /-/; + + if ( $qualified_milestone =~ /:/ ) { + ($master, $milestone) = split(/:/, $qualified_milestone); + $invalid++ unless ( $master && $milestone ); + } + else { + $milestone = $qualified_milestone; + } + + if ( $invalid ) { + print_error("Invalid milestone", 0); + usage(); + exit(1); + } + + $master = $cws->master() if !$master; + if ( !$cws->is_milestone($master, $milestone) ) { + print_error("Milestone '$milestone' is not registered with master workspace '$master'.", 21); + } + return ($master, $milestone); +} + +sub relink_workspace { + my $linkdir = shift; + my $restore = shift; + + # The list of obligatorily added modules, build will not work + # if these are not present. + my %added_modules_hash; + if (defined $ENV{ADDED_MODULES}) { + for ( split(/\s/, $ENV{ADDED_MODULES}) ) { + $added_modules_hash{$_}++; + } + } + + # clean out pre-existing linkdir + my $bd = dirname($linkdir); + if ( !opendir(DIR, $bd) ) { + print_error("Can't open directory '$bd': $!.", 44); + } + my @old_link_dirs = grep { /^src.m\d+/ } readdir(DIR); + close(DIR); + + if ( @old_link_dirs > 1 ) { + print_error("Found more than one old link directories:", 0); + foreach (@old_link_dirs) { + print STDERR "@old_link_dirs\n"; + } + if ( $restore ) { + print_error("Please remove all old link directories but the last one", 67); + } + } + + # Originally the extension .lnk indicated a linked module. This turned out to be + # not an overly smart choice. Cygwin has some heuristics which regards .lnk + # files as Windows shortcuts, breaking the build. Use .link instead. + # When in restoring mode still consider .lnk as link to modules (for old CWSs) + my $old_link_dir = "$bd/" . $old_link_dirs[0]; + if ( $restore ) { + if ( !opendir(DIR, $old_link_dir) ) { + print_error("Can't open directory '$old_link_dir': $!.", 44); + } + my @links = grep { !(/\.lnk/ || /\.link/) } readdir(DIR); + close(DIR); + # everything which is not a link to a directory can't be an "added" module + foreach (@links) { + next if /^\./; + my $link = "$old_link_dir/$_"; + if ( -s $link && -d $link ) { + $added_modules_hash{$_} = 1; + } + } + } + print_message("... removing '$old_link_dir'"); + rmtree([$old_link_dir], 0); + + print_message("... (re)create '$linkdir'"); + if ( !mkdir("$linkdir") ) { + print_error("Can't create directory '$linkdir': $!.", 44); + } + if ( !opendir(DIR, "$bd/ooo") ) { + print_error("Can't open directory '$bd/sun': $!.", 44); + } + my @ooo_top_level_dirs = grep { !/^\./ } readdir(DIR); + close(DIR); + if ( !opendir(DIR, "$bd/sun") ) { + print_error("Can't open directory '$bd/sun': $!.", 44); + } + my @so_top_level_dirs = grep { !/^\./ } readdir(DIR); + close(DIR); + my $savedir = getcwd(); + if ( !chdir($linkdir) ) { + print_error("Can't chdir() to directory '$linkdir': $!.", 44); + } + my $suffix = '.link'; + foreach(@ooo_top_level_dirs) { + if ( $_ eq 'REBASE.LOG' || $_ eq 'REBASE.CONFIG_DONT_DELETE' ) { + next; + } + my $target = $_; + if ( -d "../ooo/$_" && !exists $added_modules_hash{$_} ) { + $target .= $suffix; + } + if ( !symlink("../ooo/$_", $target) ) { + print_error("Can't symlink directory '../ooo/$_ -> $target': $!.", 44); + } + } + foreach(@so_top_level_dirs) { + if ( $_ eq 'REBASE.LOG' || $_ eq 'REBASE.CONFIG_DONT_DELETE' ) { + next; + } + my $target = $_; + if ( -d "../sun/$_" && !exists $added_modules_hash{$_} ) { + $target .= $suffix; + } + if ( !symlink("../sun/$_", $target) ) { + print_error("Can't symlink directory '../sun/$_ -> $target': $!.", 44); + } + } + if ( !chdir($savedir) ) { + print_error("Can't chdir() to directory '$linkdir': $!.", 44); + } +} + +sub update_solver +{ + my $platform = shift; + my $source = shift; + my $solver = shift; + my $milestone = shift; + + my @zip_sub_dirs = ('bin', 'doc', 'idl', 'inc', 'lib', 'par', 'pck', 'pdb', 'pus', 'rdb', 'res', 'xml'); + + use Archive::Zip qw( :ERROR_CODES :CONSTANTS ); + + my $platform_solver = "$solver/$platform"; + + if ( -d $platform_solver ) { + print_message("... removing old solver for platform '$platform'"); + if ( !rmtree([$platform_solver]) ) { + print_error("Can't remove directory '$platform_solver': $!.", 44); + } + } + + if ( !mkdir("$platform_solver") ) { + print_error("Can't create directory '$platform_solver': $!.", 44); + } + + my $platform_source = "$source/$platform/zip.$milestone"; + if ( !opendir(DIR, "$platform_source") ) { + print_error("Can't open directory '$platform_source': $!.", 44); + } + my @zips = grep { /\.zip$/ } readdir(DIR); + close(DIR); + + my $nzips = @zips; + print_message("... unzipping $nzips zip archives for platform '$platform'"); + + foreach(@zips) { + my $zip = Archive::Zip->new(); + unless ( $zip->read( "$platform_source/$_" ) == AZ_OK ) { + print_error("Can't read zip file '$platform_source/$_': $!.", 44); + } + # TODO: check for erorrs + foreach (@zip_sub_dirs) { + unless ( $zip->extractTree($_, "$platform_solver/$_.$milestone") == AZ_OK ) { + print_error("Can't extract stream from zip file '$platform_source/$_': $!.", 44); + } + } + } +} + +sub write_rebase_configuration +{ + my $workspace = shift; + my $cwsname = shift; + my $master = shift; + my $milestone = shift; + + my $rebase_config = "$workspace/REBASE.CONFIG_DONT_DELETE"; + + open(REBASE, ">$rebase_config") or print_error("Can't open file '$rebase_config' for writing: $!", 98); + print REBASE "CWS-TOOLING: do not delete this file, it's needed for 'cws rebase -C'\n"; + print REBASE "CWS: $cwsname\n"; + print REBASE "New MWS: $master\n"; + print REBASE "New milestone: $milestone\n"; + close(REBASE); +} + +sub read_rebase_configuration +{ + my $workspace = shift; + + my $rebase_config = "$workspace/REBASE.CONFIG_DONT_DELETE"; + + my $master; + my $milestone; + + open(REBASE, "<$rebase_config") or print_error("Can't open file '$rebase_config' for reading: $!", 98); + while(<REBASE>) { + if ( /New MWS: (\w+)/ ) { + $master = $1; + } + if ( /New milestone: (\w+)/ ) { + $milestone = $1; + } + } + close(REBASE); + + if ( !defined($master) || !defined($milestone) ) { + print_error("File '$rebase_config' seems to be garbled. Can't continue.", 98) + } + + return ($master, $milestone); +} + +sub diff_print_files +{ + my $files_ref = shift; + my $diff_options = shift; + + my @files = sort(@{$files_ref}); + + if ( $diff_options eq 'files') { + foreach(@files) { + print "$_\n"; + } + } + else { + my @modules; + foreach(@files) { + my ($module) = split(/\//, $_); + push(@modules, $module); + } + # remove adjacent uniques + my $prev = 'nosuchmodule'; + my @unique_modules = grep($_ ne $prev && (($prev) = $_), @modules); + foreach(@unique_modules) { + print "$_\n"; + } + } +} + +# Executes the help command. +sub do_help +{ + my $args_ref = shift; + my $options_ref = shift; + + if (@{$args_ref} == 0) { + print STDERR "usage: cws <subcommand> [options] [args]\n"; + print STDERR "Type 'cws help <subcommand>' for help on a specific subcommand.\n"; + print STDERR "\n"; + print STDERR "Available subcommands:\n"; + print STDERR "\thelp (h,?)\n"; + print STDERR "\tcreate\n"; + print STDERR "\tfetch (f)\n"; + print STDERR "\trebase (rb)\n"; + print STDERR "\tanalyze (an)\n"; + print STDERR "\tquery (q)\n"; + print STDERR "\ttask (t)\n"; + print STDERR "\tcdiff (cd)\n"; + print STDERR "\tintegrate *** release engineers only ***\n"; + print STDERR "\teisclone *** release engineers only ***\n"; + } + + my $arg = $args_ref->[0]; + + if (!defined($arg) || $arg eq 'help') { + print STDERR "help (h, ?): Describe the usage of this script or its subcommands\n"; + print STDERR "usage: help [subcommand]\n"; + } + elsif ($arg eq 'create') { + print STDERR "create: Create a new child workspace\n"; + print STDERR "usage: create [-m milestone] <master workspace> <child workspace>\n"; + print STDERR "\t-m milestone: Milestone to base the child workspace on. If ommitted the\n"; + print STDERR "\t last published milestone will be used.\n"; + print STDERR "\t--milestone milestone: Same as -m milestone.\n"; + print STDERR "\t--migration: Used only for the migration of an exitisting CWS from CVS to SVN.\n"; + print STDERR "\t Disables existence check in EIS, creates CWS branch in SVN, sets SVN flag.\n"; + } + elsif ($arg eq 'task') { + print STDERR "task: Add a task to a child workspace\n"; + print STDERR "usage: task <task id> [task id ...]\n"; + } + elsif ($arg eq 'query') { + print STDERR "query: Query child workspace for miscellaneous information\n"; + print STDERR "usage: query [-M master] [-c child] <current|integratedinto|incompatible|owner|qarep|status|taskids>\n"; + print STDERR " query [-M master] [-c child] <release|due|due_qa|help|ui|ispublic|vcs|build>\n"; + print STDERR " query [-M master] <latest|milestones|ispublicmaster>\n"; + print STDERR " query <masters>\n"; + print STDERR " query [-M master] [-m milestone] <integrated|buildid>\n"; + print STDERR " query [-M master] <planned|new|approved|nominated|ready>\n"; + print STDERR "\t-M master:\t\toverride MWS specified in environment\n"; + print STDERR "\t-c child:\t\toverride CWS specified in environment\n"; + print STDERR "\t-m milestone:\t\toverride latest milestone with specified one\n"; + print STDERR "\t--master master:\tSame as -M master\t\n"; + print STDERR "\t--child child:\t\tSame -c child\n"; + print STDERR "\t--milestone milestone:\tSame as -m milestone\n"; + print STDERR "Modes:\n"; + print STDERR "\tcurrent\t\tquery current milestone of CWS\n"; + print STDERR "\tincompatible\tquery modules which should be build incompatible\n"; + print STDERR "\towner\t\tquery CWS owner\n"; + print STDERR "\tqarep\t\tquery CWS QA Representative\n"; + print STDERR "\tstatus\t\tquery approval status of CWS\n"; + print STDERR "\ttaskids\t\tquery taskids to be handled on the CWS\n"; + print STDERR "\trelease\t\tquery for target release of CWS\n"; + print STDERR "\tdue\t\tquery for due date of CWS\n"; + print STDERR "\tdue_qa\t\tquery for due date (QA) of CWS\n"; + print STDERR "\thelp\t\tquery if the CWS is help relevant\n"; + print STDERR "\tui\t\tquery if the CWS is UI relevant\n"; + print STDERR "\tbuild\t\tquery build String for CWS\n"; + print STDERR "\tlatest\t\tquery the latest milestone available for resync\n"; + print STDERR "\tbuildid\t\tquery build ID for milestone\n"; + print STDERR "\tintegrated\tquery integrated CWSs for milestone\n"; + print STDERR "\tintegratedinto\tquery milestone which CWS was integrated into\n"; + print STDERR "\tplanned\t\tquery for planned CWSs\n"; + print STDERR "\tnew\t\tquery for new CWSs\n"; + print STDERR "\tapproved\tquery CWSs approved by QA\n"; + print STDERR "\tnominated\tquery nominated CWSs\n"; + print STDERR "\tready\t\tquery CWSs ready for QA\n"; + print STDERR "\tispublic\tquery public flag of CWS\n"; + print STDERR "\tvcs\t\tquery Version Control System used for CWS (either CVS or SubVersion)\n"; + print STDERR "\tmasters\t\tquery available MWS\n"; + print STDERR "\tmilestones\tquery which milestones are know on the given MWS\n"; + print STDERR "\tispublicmaster\tquery public flag of MWS\n"; + + } + elsif ($arg eq 'fetch') { + print STDERR "THE USER-INTERFACE TO THIS SUBCOMMAND IS LIKELY TO CHANGE IN FUTURE\n"; + print STDERR "fetch: fetch a milestone or CWS\n"; + print STDERR "usage: fetch [-q] [-s] [-p platforms] [-o] <-m milestone> <workspace>\n"; + print STDERR "usage: fetch [-q] [-s] [-p platforms] [-o] <-c cws> <workspace>\n"; + print STDERR "usage: fetch [-q] [-s] <-m milestone> <workspace>\n"; + print STDERR "usage: fetch [-q] [-s] <-c cws> <workspace>\n"; + print STDERR "\t-m milestone: Checkout milestone <milestone> to workspace <workspace>\n"; + print STDERR "\t Use 'latest' for the for lastest published milestone on the current master\n"; + print STDERR "\t For cross master checkouts use the form <MWS>:<milestone>\n"; + print STDERR "\t--milestone milestone: Same as -m milestone\n"; + print STDERR "\t-c childworkspace: Checkout CWS <childworkspace> to workspace <workspace>\n"; + print STDERR "\t--child childworkspace: Same as -c childworkspace\n"; + print STDERR "\t-s: Try to switch an existing workspace <workspace> to milestone or CWS\n"; + print STDERR "\t--switch: Same as -s\n"; + print STDERR "\t-p platform: Copy one or more prebuilt platforms 'platform'. \n"; + print STDERR "\t Separate multiple platforms with commas.\n"; + print STDERR "\t--platforms platform: Same as -p\n"; + print STDERR "\t-o Omit checkout of sources, copy only solver. \n"; + print STDERR "\t--onlysolver: Same as -o\n"; + print STDERR "\t-q Silence some of the output of the command.\n"; + print STDERR "\t--quiet: Same as -q\n"; + } + elsif ($arg eq 'rebase') { + print STDERR "rebase: Rebase a child workspace to a new milestone\n"; + print STDERR "usage: rebase <-m milestone> <workspace>\n"; + print STDERR "usage: rebase <-C> <workspace>\n"; + print STDERR "\t-m milestone: Merge changes on MWS into CWS up to and including milestone <milestone>\n"; + print STDERR "\t Use 'latest' for the for lastest published milestone on the current master\n"; + print STDERR "\t For cross master rebases use the form <MWS>:<milestone>\n"; + print STDERR "\t--milestone milestone: Same as -m milestone\n"; + print STDERR "\t-C: Commit changes made by merge step and update current milestone in database\n"; + print STDERR "\t--commit: Same as -C\n" + } + elsif ($arg eq 'integrate') { + print STDERR "integrate: Integrate a child workspace into a master workspace\n"; + print STDERR "usage: integrate <-c childworkspace>\n"; + print STDERR "usage: integrate <-C>\n"; + print STDERR "\t-c childworkspace: Merge changes on CWS <childworkspace> into MWS\n"; + print STDERR "\t--child childworkspace: Same as -c childworkspace\n"; + print STDERR "\t-C: Commit changes made by merge step and update CWS status in database\n"; + print STDERR "\t--commit: Same as -C\n" + } + elsif ($arg eq 'cdiff') { + print STDERR "cdiff: Show changes on CWS relative to current milestone\n"; + print STDERR "usage: cdiff [-M master] [-c child] [--files] [--modules]\n"; + print STDERR "\t-M master:\t\toverride MWS specified in environment\n"; + print STDERR "\t-c child:\t\toverride CWS specified in environment\n"; + print STDERR "\t--master master:\tSame as -M master\t\n"; + print STDERR "\t--child child:\t\tSame -c child\n"; + print STDERR "\t--files: Print only file names\n"; + print STDERR "\t--modules: Print only top level directories aka modules\n" + } + else { + print STDERR "'$arg': unknown subcommand\n"; + exit(1); + } + exit(0); +} + +# Executes the create command. +sub do_create +{ + my $args_ref = shift; + my $options_ref = shift; + + if ( exists $options_ref->{'help'} || @{$args_ref} != 2) { + do_help(['create']); + } + + my $is_migration = 0; + if ( exists $options_ref->{'migration'} ) { + $is_migration = 1; + } + + my $master = uc $args_ref->[0]; + my $cws_name = $args_ref->[1]; + + if (!is_master($master)) { + print_error("'$master' is not a valid master workspace.", 7); + } + + # check if cws name fits the convention + if ( $cws_name !~ /^\w[\w\.\#]*$/ ) { + print_error("Invalid child workspace name '$cws_name'.\nCws names should consist of alphanumeric characters, preferable all lowercase and starting with a letter.\nThe characters . and # are allowed if they are not the first character.", 7); + } + + my $cws = get_this_cws(); + $cws->master($master); + $cws->child($cws_name); + + # check if child workspace already exists + my $eis_id = $cws->eis_id(); + if ( !defined($eis_id) ) { + print_error("Connection with EIS database failed.", 8); + } + + my $is_promotion = 0; + if ( $eis_id > 0 ) { + if ( $cws->get_approval() eq 'planned' ) { + print "Promote child workspace '$cws_name' from 'planned' to 'new'.\n"; + $is_promotion++; + } + else { + if ( $is_migration ) { + print_message("Create CWS branch in Subversion for migrating CWS '$cws_name' from CVS."); + } + else { + print_error("Child workspace '$cws_name' already exists.", 7); + } + } + } + else { + # check if child workspace name is still available + if ( !$cws->is_cws_name_available()) { + print_error("Child workspace name '$cws_name' is already in use.", 7); + } + } + + my $milestone; + # verify milestone or query latest milestone + if ( exists $options_ref->{'milestone'} ) { + $milestone=$options_ref->{'milestone'}; + # check if milestone exists + if ( !$cws->is_milestone($master, $milestone) ) { + print_error("Milestone '$milestone' is not registered with master workspace '$master'.", 8); + } + } + else { + $milestone=$cws->get_current_milestone($cws->master()); + } + + # set milestone + $cws->milestone($milestone); + + + my $config = CwsConfig->new(); + my $ooo_svn_server = $config->get_ooo_svn_server(); + my $so_svn_server = $config->get_so_svn_server(); + + if (!defined($ooo_svn_server)) { + print_error("No OpenOffice.org SVN server defined, please check your configuration file.", 8); + } + + my $ooo_milestone_url = get_milestone_url($ooo_svn_server, $cws->master(), $milestone); + my $ooo_cws_url = get_cws_url($ooo_svn_server, $cws_name); + + my $so_milestone_url; + my $so_cws_url; + if ( defined($so_svn_server) ) { + $so_milestone_url = get_milestone_url($so_svn_server, $cws->master(), $milestone); + $so_cws_url = get_cws_url($so_svn_server, $cws_name); + } + + # There is a slight chance that the cws creation was interrupted before registration before. + # Check for potential remains in the repository + my $ooo_path_exists = 0; + my $so_path_exists = 0; + + print STDERR "... check cws path:\t'$ooo_cws_url'"; + if ( svn_path_exists($ooo_cws_url) ) { + $ooo_path_exists=1; + print STDERR "\n"; + } + else { + print STDERR ", OK\n"; + } + + if ( defined($so_svn_server) ) { + print STDERR "... check cws path:\t'$so_cws_url'"; + if ( svn_path_exists($so_cws_url) ) { + print STDERR "\n"; + $so_path_exists = 1; + } + else { + print STDERR ", OK\n"; + } + } + + if ( $ooo_path_exists ) { + print_error("SVN path '$ooo_cws_url' already exists.\nThis can happen if a previous CWS creation attempt failed before registering the CWS with EIS.\nIf this is the case, please delete the path with:\n\t svn delete -m'CWS-TOOLING: undo broken CWS creation' $ooo_cws_url\n", 0); + } + + if ( $so_path_exists ) { + print_error("SVN path '$so_cws_url' already exists.\nThis can happen if a previous CWS creation attempt failed before registering the CWS with EIS.\nIf this is the case, please delete the path with:\n\t svn delete -m'CWS-TOOLING: undo broken CWS creation' $so_cws_url\n", 0); + } + + if ( $ooo_path_exists || $so_path_exists ) { + exit(15); + } + + # determine the revision from which the milestone was copied + my $ooo_milestone_revision; + my $so_milestone_revision; + + $ooo_milestone_revision = svn_milestone_revision($ooo_milestone_url); + if ( !$ooo_milestone_revision ) { + print_error("Can't retrieve revision for milestone '$milestone', url '$ooo_milestone_url.", 17 ); + } + if ( defined($so_svn_server) ) { + $so_milestone_revision = svn_milestone_revision($so_milestone_url); + if ( !$so_milestone_revision ) { + print_error("Can't retrieve revision for milestone '$milestone', url '$so_milestone_url.", 17 ); + } + } + + my $ooo_master_url; + my $so_master_url; + + $ooo_master_url = get_master_url($ooo_svn_server, $cws->master(), $ooo_milestone_revision); + if ( defined($so_svn_server) ) { + $so_master_url = get_master_url($so_svn_server, $cws->master(), $so_milestone_revision); + } + + my $ooo_short_url = get_short_url($ooo_svn_server, $ooo_master_url); + my $ooo_creation_comment = "CWS-TOOLING: create CWS " . $cws->child() . " from $ooo_short_url (milestone: " . $cws->master() . ":$milestone)"; + # create branches an ooo server and an optional so server + print STDERR "... create branch:\t'$ooo_cws_url'"; + svn_copy($ooo_creation_comment, $ooo_master_url, $ooo_cws_url); + if ( defined($so_svn_server) ) { + my $so_short_url = get_short_url($so_svn_server, $so_master_url); + my $so_creation_comment = "CWS-TOOLING: create CWS " . $cws->child() . " from $so_short_url (milestone: " . $cws->master() . ":$milestone)"; + print STDERR "... create branch:\t'$so_cws_url'"; + svn_copy($so_creation_comment, $so_master_url, $so_cws_url); + } + + if ( $is_migration ) { + # Set master and milestone + $cws->master($master); + $cws->milestone($milestone); + my $rc = $cws->set_subversion_flag(1); + if ( !$rc ) { + print_error("Failed to set subversion flag on child workspace '$cws_name'.\nContact EIS administrator!\n", 12); + } + } + else { + register_child_workspace($cws, $is_promotion); + } + return; +} + +sub do_rebase +{ + my $args_ref = shift; + my $options_ref = shift; + + my $commit_phase = 0; + my $milestone; + + # TODO: Switching to a new master dooes work not correctly yet + + if (exists $options_ref->{'help'} || @{$args_ref} != 1) { + do_help(['rebase']); + } + if ( exists($options_ref->{'commit'}) && exists($options_ref->{'milestone'}) ) { + print_error("Option -m (--milestone) and -C (--commit) are mutually exclusive.", 0 ); + do_help(['rebase']); + } + if ( !exists($options_ref->{'commit'}) && !exists($options_ref->{'milestone'}) ) { + print_error("At least one of the options -m (--milestone) or -C (--commit) are required.", 0 ); + do_help(['rebase']); + } + + if ( !svn_version_check() ) { + print_error("cws rebase requires svn-1.5.4 or later (merge tracking and bug fixes). Please upgrade your svn client.", 1); + } + + my $cws = get_cws_from_environment(); + my $old_masterws = $cws->master(); + my $new_masterws; + my $new_milestone; + + my $workspace = $args_ref->[0]; + + if ( ! -d $workspace ) { + print_error("Can't find workspace '$workspace': $!", 99); + } + + if ( exists($options_ref->{'commit'}) ) { + $commit_phase=1; + ($new_masterws, $new_milestone) = read_rebase_configuration($workspace); + } + elsif( exists($options_ref->{'milestone'}) ) { + $milestone = $options_ref->{'milestone'}; + if ( $milestone eq 'latest' ) { + my $latest = $cws->get_current_milestone($old_masterws); + + if ( !$latest ) { + print_error("Can't determine latest milestone of '$old_masterws' available for rebase.", 22); + } + $new_masterws = $old_masterws; + $new_milestone = $cws->get_current_milestone($old_masterws); + } + else { + ($new_masterws, $new_milestone) = verify_milestone($cws, $milestone); + } + } + else { + do_help(['rebase']); + } + + my $so_setup = 0; + my $ooo_path; + my $so_path; + # Determine if we got a three directory (so) setup or a plain (ooo) setup. + # This is only needed as long the build system still relies + # on having "modules" from different repositories in the same + # directory besides each other. + if ( -d "$workspace/$old_masterws/sun" ) { + $so_setup = 1; + $ooo_path = "$workspace/$old_masterws/ooo"; + $so_path = "$workspace/$old_masterws/sun"; + } + else { + $ooo_path = "$workspace"; + } + + my $config = CwsConfig->new(); + my $ooo_svn_server = $config->get_ooo_svn_server(); + my $so_svn_server = $config->get_so_svn_server(); + + if (!defined($ooo_svn_server)) { + print_error("No OpenOffice.org SVN server defined, please check your configuration file.", 8); + } + + my $ooo_milestone_url = get_milestone_url($ooo_svn_server, $new_masterws, $new_milestone); + my $ooo_cws_url = get_cws_url($ooo_svn_server, $cws->child()); + + my $so_milestone_url; + my $so_cws_url; + if ( $so_setup ) { + $so_milestone_url = get_milestone_url($so_svn_server, $new_masterws, $new_milestone); + $so_cws_url = get_cws_url($so_svn_server, $cws->child()); + } + + my $ooo_milestone_revision; + my $so_milestone_revision; + + $ooo_milestone_revision = svn_milestone_revision($ooo_milestone_url); + if ( !$ooo_milestone_revision ) { + print_error("Can't retrieve revision for milestone '$new_milestone', url '$ooo_milestone_url.", 17 ); + } + if ( defined($so_svn_server) ) { + $so_milestone_revision = svn_milestone_revision($so_milestone_url); + if ( !$so_milestone_revision ) { + print_error("Can't retrieve revision for milestone '$new_milestone', url '$so_milestone_url.", 17 ); + } + } + + my $ooo_master_url; + my $so_master_url; + + $ooo_master_url = get_master_url($ooo_svn_server, $new_masterws, $ooo_milestone_revision); + if ( defined($so_svn_server) ) { + $so_master_url = get_master_url($so_svn_server, $new_masterws, $so_milestone_revision); + } + + if ( $commit_phase ) { + # commit + print_message("... committing merged changes to workspace '$workspace'."); + my $ooo_short_url = get_short_url($ooo_svn_server, $ooo_master_url); + my $commit_message = "CWS-TOOLING: rebase CWS " . $cws->child() . " to $ooo_short_url (milestone: " . $new_masterws . ":$new_milestone)"; + svn_commit($ooo_path, $commit_message); + if ( $so_setup ) { + my $so_short_url = get_short_url($so_svn_server, $so_master_url); + $commit_message = "CWS-TOOLING: rebase CWS " . $cws->child() . " to $so_short_url (milestone: " . $new_masterws . ":$new_milestone)"; + svn_commit($so_path, $commit_message); + } + if ( $so_setup) { + print_message("... rename '$workspace/$old_masterws' -> '$workspace/$new_masterws'\n"); + if ( !rename("$workspace/$old_masterws", "$workspace/$new_masterws") ) { + print_error("Can't rename '$workspace/$old_masterws' -> '$workspace/$new_masterws': $!", 98); + } + print_message("... relinking workspace\n"); + relink_workspace("$workspace/$new_masterws/src.$new_milestone", 1); + if ( !unlink("$workspace/REBASE.CONFIG_DONT_DELETE") ) { + print_error("Can't unlink '$workspace/REBASE.CONFIG_DONT_DELETE': $!", 0); + } + + } + + print_message("... updating EIS database\n"); + my $push_return = $cws->set_master_and_milestone($new_masterws, $new_milestone); + # sanity check + if ( $$push_return[1] ne $new_milestone) { + print_error("Couldn't push new milestone '$new_milestone' to database", 0); + } + } + else { + # merge phase + + # check if working directory is switched to the right cws branch + my $ooo_wc_url; + my $so_wc_url; + my $cwsname = $cws->child(); + print_message("... verifying if workspace '$workspace' is switched to CWS '$cwsname'."); + $ooo_wc_url = svn_wc_url($ooo_path); + if ( $ooo_wc_url !~ /\/$cwsname$/ ) { + print_error("Your working copy '$ooo_path' is not switched to the cws branch.\nPlease fix and restart rebasing.", 24); + } + if ( $so_setup ) { + $so_wc_url = svn_wc_url($so_path); + + if ( $so_wc_url !~ /\/$cwsname$/ ) { + print_error("Your working copy '$so_path' is not switched to the cws branch.\nPlease fix and restart rebasing.", 24); + } + } + # check for mixed revisions, locally modified files etc + if ( !svn_wc_is_clean($ooo_path) || ($so_setup && !svn_wc_is_clean($so_path)) ) { + print_error("Please fix and restart rebasing.", 25); + } + + print_message("... merging changes up to '$new_masterws:$new_milestone' to workspace '$workspace'."); + svn_merge($ooo_milestone_url, $ooo_path); + if ( $so_setup ) { + svn_merge($so_milestone_url, $so_path); + } + # write out the rebase configuration to store new milestone and master information + write_rebase_configuration($workspace, $cwsname, $new_masterws, $new_milestone); + } +} + +sub do_analyze +{ + my $args_ref = shift; + my $options_ref = shift; + + print_error("not yet implemented.", 2); +} + +sub do_integrate +{ + my $args_ref = shift; + my $options_ref = shift; + + if (exists $options_ref->{'help'} || @{$args_ref} > 0) { + do_help(['integrate']); + } + if ( exists($options_ref->{'commit'}) && exists($options_ref->{'childworkspace'}) ) { + print_error("Option -c (--child) and -C (--commit) are mutually exclusive.", 0 ); + do_help(['integrate']); + } +} + +# Executes the fetch command. +sub do_fetch +{ + my $args_ref = shift; + my $options_ref = shift; + + if ( exists $options_ref->{'help'} || @{$args_ref} != 1) { + do_help(['fetch']); + } + + my $milestone_opt = $options_ref->{'milestone'}; + my $child = $options_ref->{'childworkspace'}; + my $platforms = $options_ref->{'platforms'}; + my $quiet = $options_ref->{'quiet'} ? 1 : 0 ; + my $switch = $options_ref->{'switch'} ? 1 : 0 ; + my $onlysolver = $options_ref->{'onlysolver'} ? 1 : 0 ; + + if ( !defined($milestone_opt) && !defined($child) ) { + print_error("Specify one of these options: -m or -c", 0); + do_help(['fetch']); + } + + if ( defined($milestone_opt) && defined($child) ) { + print_error("Options -m and -c are mutally exclusive", 0); + do_help(['fetch']); + } + + if ( defined($platforms) && $switch ) { + print_error("Option '-p' is not yet usuable with Option '-s'. Will be fixed RSN.", 0); + do_help(['fetch']); + } + + if ( $onlysolver && !defined($platforms) ) { + print_error("Option '-o' is Only usuable combination with option '-p'.", 0); + do_help(['fetch']); + } + + my $cws = get_this_cws(); + my $masterws = $ENV{WORK_STAMP}; + if ( !defined($masterws) ) { + print_error("Can't determine current master workspace: check environment variable WORK_STAMP", 21); + } + $cws->master($masterws); + my $milestone; + if( defined($milestone_opt) ) { + if ( $milestone_opt eq 'latest' ) { + $cws->master($masterws); + my $latest = $cws->get_current_milestone($masterws); + + if ( !$latest ) { + print_error("Can't determine latest milestone of master workspace '$masterws'.", 22); + } + $milestone = $cws->get_current_milestone($masterws); + } + else { + ($masterws, $milestone) = verify_milestone($cws, $milestone_opt); + } + } + elsif ( defined($child) ) { + $cws = get_cws_by_name($child); + $masterws = $cws->master(); # CWS can have another master than specified in ENV + $milestone = $cws->milestone(); + } + else { + do_help(['fetch']); + } + + my $config = CwsConfig->new(); + my $ooo_svn_server = $config->get_ooo_svn_server(); + my $so_svn_server = $config->get_so_svn_server(); + # Check early for platforms so we can bail out before anything time consuming is done + # in case of a missing platform + my @platforms; + my $prebuild_dir; + if ( defined($platforms) ) { + use Archive::Zip; # warn early if module is missing + $prebuild_dir = $config->get_prebuild_binaries_location(); + $masterws = $cws->master(); + $prebuild_dir = "$prebuild_dir/$masterws"; + + @platforms = split(/,/, $platforms); + + my $added_product = 0; + my $added_nonproduct = 0; + foreach(@platforms) { + if ( $_ eq 'common.pro' ) { + $added_product = 1; + print_warning("'$_' is added automatically to the platform list, don't specify it explicit"); + } + if ( $_ eq 'common' ) { + $added_nonproduct = 1; + print_warning("'$_' is added automatically to the platform list, don't specify it explicit"); + } + } + + # add common.pro/common to platform list + if ( $so_svn_server ) { + my $product = 0; + my $nonproduct = 0; + foreach(@platforms) { + if ( /\.pro$/ ) { + $product = 1; + } + else { + $nonproduct = 1; + } + } + push(@platforms, 'common.pro') if ($product && !$added_product); + push(@platforms, 'common') if ($nonproduct && !$added_nonproduct); + } + + foreach(@platforms) { + if ( ! -d "$prebuild_dir/$_") { + print_error("Can't find prebuild binaries for platform '$_'.", 22); + } + } + + } + + my $cwsname = $cws->child(); + my $url_suffix = $milestone_opt ? ("/tags/$masterws" . "_$milestone") : ('/cws/' . $cwsname); + my $linkdir = $milestone_opt ? "src.$milestone" : "src." . $cws->milestone; + + my $workspace = $args_ref->[0]; + if ( !$onlysolver ) { + if ( $switch ) { + # check if to be switched working copy exist or bail out + if ( ! -d $workspace ) { + print_error("Can't open workspace '$workspace': $!", 21); + } + + my $so_setup = 0; + my $ooo_path; + my $so_path; + # Determine if we got a three directory (so) setup or a plain (ooo) setup. + # This is only needed as long the build system still relies + # on having "modules" from different repositories in the same + # directory besides each other. + if ( -d "$workspace/$masterws/sun" ) { + $so_setup = 1; + $ooo_path = "$workspace/$masterws/ooo"; + $so_path = "$workspace/$masterws/sun"; + } + else { + $ooo_path = "$workspace"; + } + + # get the working copy URLs + my $ooo_new_url = svn_wc_root($ooo_path) . $url_suffix; + my $so_new_url; + if ( $so_setup ) { + $so_new_url = svn_wc_root($so_path) . $url_suffix; + } + + print_message("... switching '$ooo_path' to URL '$ooo_new_url'"); + svn_switch($ooo_path, $ooo_new_url, $quiet); + # switch working copies + if ( $so_setup ) { + print_message("... switching '$so_path' to URL '$so_new_url'"); + svn_switch($so_path, $so_new_url, $quiet); + } + + if ( $so_setup ) { + relink_workspace("$workspace/$masterws/$linkdir", 0); + } + } + else { + if (!defined($ooo_svn_server)) { + print_error("No OpenOffice.org SVN server defined, please check your configuration file.", 8); + } + + my $ooo_url = $ooo_svn_server . $url_suffix; + if ( -e $workspace ) { + print_error("File or directory '$workspace' already exists.", 8); + } + + # Check if working directory already exists + + if ( defined($so_svn_server) ) { + if ( !mkdir($workspace) ) { + print_error("Can't create directory '$workspace': $!.", 8); + } + my $work_master = "$workspace/$masterws"; + if ( !mkdir($work_master) ) { + print_error("Can't create directory '$work_master': $!.", 8); + } + print_message("... checkout '$ooo_url' to '$work_master/ooo'"); + svn_checkout($ooo_url, "$work_master/ooo", $quiet); + my $so_url = $so_svn_server . $url_suffix; + print_message("... checkout '$so_url' to '$work_master/sun'"); + svn_checkout($so_url, "$work_master/sun", $quiet); + my $linkdir = "$work_master/src.$milestone"; + if ( !mkdir($linkdir) ) { + print_error("Can't create directory '$linkdir': $!.", 8); + } + relink_workspace($linkdir); + } + else { + print_message("... checkout '$ooo_url' to '$workspace'"); + svn_checkout($ooo_url, $workspace, $quiet); + } + } + } + + if ( defined($platforms) ) { + if ( !-d $workspace ) { + if ( !mkdir($workspace) ) { + print_error("Can't create directory '$workspace': $!.", 8); + } + } + my $solver = defined($so_svn_server) ? "$workspace/$masterws" : "$workspace/solver"; + if ( !-d $solver ) { + if ( !mkdir($solver) ) { + print_error("Can't create directory '$solver': $!.", 8); + } + } + foreach(@platforms) { + print_message("... copying platform solver '$_'."); + update_solver($_, $prebuild_dir, $solver, $milestone); + } + } +} + +sub do_query +{ + my $args_ref = shift; + my $options_ref = shift; + + # list of available query modes + my @query_modes = qw(integratedinto incompatible taskids status latest current owner qarep build buildid integrated approved nominated ready new planned release due due_qa help ui milestones masters vcs ispublic ispublicmaster); + my %query_modes_hash = (); + foreach (@query_modes) { + $query_modes_hash{$_}++; + } + + if ( exists $options_ref->{'help'} || @{$args_ref} != 1) { + do_help(['query']); + } + my $mode = lc($args_ref->[0]); + + # cwquery mode 'state' has been renamed to 'status' to be more consistent + # with CVS etc. 'state' is still an alias for 'status' + $mode = 'status' if $mode eq 'state'; + + # there will be more query modes over time + if ( !exists $query_modes_hash{$mode} ) { + do_help(['query']); + } + query_cws($mode, $options_ref); +} + +sub do_task +{ + my $args_ref = shift; + my $options_ref = shift; + + if ( exists $options_ref->{'help'} ) { + do_help(['task']); + } + + # CWS states for which adding tasks are blocked. + my @states_blocked_for_adding = ( + "integrated", + "nominated", + "approved by QA", + "cancelled", + "finished" + ); + my $cws = get_cws_from_environment(); + + # register taskids with EIS database; + # checks taksids for sanity, will notify user + # if taskid is already registered. + my $status = $cws->get_approval(); + + my $child = $cws->child(); + my $master = $cws->master(); + + my @registered_taskids = $cws->taskids(); + + # if called without ids to register just query for tasks + if ( @{$args_ref} == 0 ) { + print_message("Task ID(s):"); + foreach (@registered_taskids) { + if ( defined($_) ) { + print "$_\n"; + } + } + } + + if ( !defined($status) ) { + print_error("Can't determine status of child workspace `$child`.", 20); + } + + if ( grep($status eq $_, @states_blocked_for_adding) ) { + print_error("Can't add tasks to child workspace '$child' with state '$status'.", 21); + } + + # Create hash for easier searching. + my %registered_taskids_hash = (); + for (@registered_taskids) { + $registered_taskids_hash{$_}++; + } + + my @new_taskids = (); + foreach (@{$args_ref}) { + if ( $_ !~ /^([ib]?\d+)$/ ) { + print_error("'$_' is an invalid task ID.", 22); + } + if ( exists $registered_taskids_hash{$1} ) { + print_warning("Task ID '$_' already registered, skipping."); + next; + } + push(@new_taskids, $_); + } + + # TODO: introduce a EIS_USER in the configuration, which should be used here + my $config = CwsConfig->new(); + my $vcsid = $config->vcsid(); + my $added_taskids_ref = $cws->add_taskids($vcsid, @new_taskids); + if ( !$added_taskids_ref ) { + my $taskids_str = join(" ", @new_taskids); + print_error("Couldn't register taskID(s) '$taskids_str' with child workspace '$child'.", 23); + } + my @added_taskids = @{$added_taskids_ref}; + if ( @added_taskids ) { + my $taskids_str = join(" ", @added_taskids); + print_message("Registered taskID(s) '$taskids_str' with child workspace '$child'."); + } + return; +} + +sub do_cdiff +{ + my $args_ref = shift; + my $options_ref = shift; + + if ( exists $options_ref->{'help'} || @{$args_ref} != 0) { + do_help(['cdiff']); + } + + my $files = exists $options_ref->{'files'} ? 1 : 0; + my $modules = exists $options_ref->{'modules'} ? 1 : 0; + + if ( $files && $modules ) { + print_error("Options --files and --modules are mutally exclusive", 0); + do_help(['cdiff']); + } + + my $diff_option; + if ( $files ) { + $diff_option = 'files'; + } + elsif ( $modules ) { + $diff_option = 'modules'; + } + else { + $diff_option = 0; + } + + + my $masterws = exists $options_ref->{'masterworkspace'} ? uc($options_ref->{'masterworkspace'}) : $ENV{WORK_STAMP}; + my $childws = exists $options_ref->{'childworkspace'} ? $options_ref->{'childworkspace'} : $ENV{CWS_WORK_STAMP}; + + if ( !defined($masterws) ) { + print_error("Can't determine master workspace environment.\n", 30); + } + + if ( !defined($childws) ) { + print_error("Can't determine child workspace environment.\n", 30); + } + + my $cws = Cws->new(); + $cws->child($childws); + $cws->master($masterws); + + if ( !is_valid_cws($cws) ) { + print_error("'$childws' is not a valid CWS name.\n", 30); + } + + my $milestone = $cws->milestone(); + + my $config = CwsConfig->new(); + my $ooo_svn_server = $config->get_ooo_svn_server(); + my $so_svn_server = $config->get_so_svn_server(); + + my $ooo_milestone_url = get_milestone_url($ooo_svn_server, $masterws, $milestone); + my $ooo_cws_url = get_cws_url($ooo_svn_server, $childws); + my $ooo_files; + if ( $diff_option ) { + $ooo_files = svn_diff($ooo_milestone_url, $ooo_cws_url, $diff_option); + diff_print_files($ooo_files, $diff_option); + } + else { + svn_diff($ooo_milestone_url, $ooo_cws_url, 0); + } + + my $so_files; + if ( $so_svn_server ) { + my $so_milestone_url = get_milestone_url($so_svn_server, $masterws, $milestone); + my $so_cws_url = get_cws_url($so_svn_server, $childws); + if ( svn_path_exists($so_cws_url) ) { + if ( $diff_option ) { + $so_files = svn_diff($so_milestone_url, $so_cws_url, $diff_option); + diff_print_files($so_files, $diff_option); + } + else { + svn_diff($so_milestone_url, $so_cws_url, 0); + } + } + } + +} + +sub do_eisclone +{ + my $args_ref = shift; + my $options_ref = shift; + + print_error("not yet implemented.", 2); +} + +sub print_message +{ + my $message = shift; + + print "$message\n"; + return; +} + +sub print_warning +{ + my $message = shift; + print STDERR "$script_name: "; + print STDERR "WARNING: $message\n"; + return; +} + +sub print_error +{ + my $message = shift; + my $error_code = shift; + + print STDERR "$script_name: "; + print STDERR "ERROR: $message\n"; + + if ( $error_code ) { + print STDERR "\nFAILURE: $script_name aborted.\n"; + exit($error_code); + } + return; +} + +sub usage +{ + print STDERR "Type 'cws help' for usage.\n"; +} + +### SVN glue ### + +# TODO: is it a better idea to use the SVN bindings? +# pro: +# - SVN make guarantees about API stability but no about the command line +# - finer access to the SVN functionality, better error reporting +# - prevents parsing errors due to localized SVN messages +# con: +# - the bindings are difficult to install, mostly due to subtle install bugs +# - we do not really use much of the SVN functionality here + +sub svn_wc_is_clean +{ + my $wc_path = shift; + + my $result = execute_svnversion_command($wc_path); + + my $error = 0; + + if ( $result =~ /:/ ) { + print_error("Working copy '$wc_path' contains mixed revisions. Please run 'svn update'!", 0); + $error++; + } + if ( $result =~ /M/ ) { + print_error("Working copy '$wc_path' contains locally modified files. Please commit or revert all modified files.", 0); + $error++; + } + if ( $result =~ /S/ ) { + print_error("Working copy '$wc_path' is partially switched. The whole working copy needs to be switched to the CWS branch.", 0); + $error++; + } + if ( $result =~ /P/ ) { + print_error("Working copy '$wc_path' is only partially checked out. CWS tools can't work on partially checked out working copies.", 0); + $error++; + } + + return !$error; +} + +sub svn_version_check +{ + my $major_required = 1; + my $minor_required = 5; + my $patchlevel_required = 4; + + my $version_required = $major_required*1000000 + $minor_required*1000 + $patchlevel_required; + + if ( $debug ) { + print STDERR "\nCWS-DEBUG: ... svn version\n"; + } + + my @result = execute_svn_command(0, '--version --quiet', " "); + # svn --version --quiet returns the version in major.minor.patchlevel scheme + # for example: 1.5.4 or 1.6.0-dev (for developer codelines) + # hopefully they don't change the versioning scheme + my ($major, $minor, $patchlevel); + if ( $result[0] =~ /^(\d+)\.(\d+)\.(\d+)/ ) { + $major = $1; + $minor = $2; + $patchlevel = $3; + } + else { + print_error("Can't determine svn version. Please file an issue with the output of 'svn --version --quiet'. CWS tooling requires svn-1.5.4 or later\n", 1) + } + + my $version = $major*1000000 + $minor*1000 + $patchlevel; + + if ( $version < $version_required ) { + return 0; + } + return 1; +} + +sub svn_copy +{ + my $comment = shift; + my $source = shift; + my $dest = shift; + + if ( $debug ) { + print STDERR "\nCWS-DEBUG: ... preparing branch: '$source' -> '$dest'\n"; + } + + my @result = execute_svn_command(0, 'copy', "-m '$comment'", $source, $dest); + if ( $result[1] =~ /Committed revision (\d+)\./ ) { + print STDERR ", committed revision $1\n"; + } else { + print STDERR "failed!\n"; + print STDERR @result; + } +} + +sub svn_milestone_revision +{ + my $milestone_url = shift; + + if ( $debug ) { + print STDERR "\nCWS-DEBUG: ... preparing log --stop-on-copy: '$milestone_url'\n"; + } + + my @result = execute_svn_command(0, 'log', '--stop-on-copy', $milestone_url); + + # There might be revisions committed to a tag (allowed in subversion). + # The lowestmost revision listed in a 'log --stop-on-copy' is the one which + # was current when the tag was created + my $revision = 0; + foreach ( @result ) { + if ( /^r(\d+)\s+\|\s+/ ) { + $revision = $1; + } + } + + return $revision; +} + +sub svn_path_exists +{ + my $url = shift; + + my @result = svn_info($url); + + foreach ( @result ) { + if ( /^Path: / ) { + return 1; + } + } + return 0; +} + +sub svn_wc_url +{ + my $wc_path = shift; + + my @result = svn_info($wc_path); + + foreach ( @result ) { + if ( /^URL: (.+)$/ ) { + return $1; + } + } + + print_error("Can't retrieve svn info from working copy '$wc_path'\n", 23); +} + +sub svn_wc_root +{ + my $wc_path = shift; + + my @result = svn_info($wc_path); + + foreach ( @result ) { + if ( /^Repository Root: (.+)$/ ) { + return $1; + } + } + + print_error("Can't retrieve svn info from working copy '$wc_path'\n", 23); +} + +sub svn_info +{ + my $url = shift; + + if ( $debug ) { + print STDERR "\nCWS-DEBUG: ... preparing info: '$url'\n"; + } + + my @result = execute_svn_command(0, 'info', '--depth empty', $url); + return @result; +} + +sub svn_merge +{ + my $url = shift; + my $wc = shift; + + if ( $debug ) { + print STDERR "\nCWS-DEBUG: ... preparing merge: '$url -> $wc'\n"; + } + + my $log_file = "$wc/REBASE.LOG"; + my @result = execute_svn_command($log_file, 'merge', '--accept postpone', $url, $wc); + return @result; +} + +sub svn_switch +{ + my $wc = shift; + my $url = shift; + my $quiet = shift; + + if ( $debug ) { + print STDERR "\nCWS-DEBUG: ... preparing switch: '$url -> $wc'\n"; + } + + my $switch = $quiet ? 'switch --quiet' : 'switch'; + + my @result = execute_svn_command('print', $switch, $url, $wc); + return @result; +} + +sub svn_checkout +{ + my $url = shift; + my $wc = shift; + my $quiet = shift; + + if ( $debug ) { + print STDERR "\nCWS-DEBUG: ... preparing checkout: '$url -> $wc'\n"; + } + + my $checkout = $quiet ? 'checkout --quiet' : 'checkout'; + + my @result = execute_svn_command('print', $checkout, $url, $wc); + return @result; +} + +sub svn_commit +{ + my $wc = shift; + my $commit_message = shift; + + if ( $debug ) { + print STDERR "\nCWS-DEBUG: ... preparing commit: '$wc'\n"; + } + + my $log_file = "$wc/REBASE.LOG"; + my @result = execute_svn_command($log_file, 'commit', "-m '$commit_message'", $wc); + return @result; +} + +sub svn_diff +{ + my $url1 = shift; + my $url2 = shift; + my $diff_option = shift; + + my $summarize = ''; + if ( $diff_option ) { + $summarize = '--summarize'; + } + + if ( $debug ) { + print STDERR "\nCWS-DEBUG: ... preparing diff $summarize: '$url1' vs. '$url2'\n"; + } + + if ( $summarize ) { + my $result = execute_svn_command(0, 'diff', $summarize, $url1, $url2); + my $nlen = length($url1); + my @files; + foreach( @{$result} ) { + my ($dummy, $url) = split(); + next if length($url) <= $nlen; # skip short URLs (like $url1) + my $file = substr($url, $nlen+1); + next if index($file, '/') == -1; # skip 'modified' top level dirs + push (@files, $file); + } + return \@files; + } + else { + execute_svn_command('print', 'diff', $url1, $url2); + } +} + +sub execute_svn_command +{ + my $log = shift; + my $command = shift; + my $options = shift; + my @args = @_; + + my $args_str = join(" ", @args); + + # we can only parse english strings, hopefully a C locale is available everywhere + $ENV{LC_ALL}='C'; + $command = "svn $command $options $args_str"; + + if ( $debug ) { + print STDERR "\nCWS-DEBUG: ... execute command line: '$command'\n"; + } + + my @result; + my $date; + if ( $log && $log ne 'print') { + open(LOG, ">>$log") or print_error("can't open log file '$log'", 30); + $date = localtime(); + print LOG "Start $command $args_str at $date\n"; + } + open(OUTPUT, "$command 2>&1 |") or print_error("Can't execute svn command line client", 98); + STDOUT->autoflush(1) if $log; + while (<OUTPUT>) { + if ( $log ) { + print STDOUT $_; + print LOG $_ if $log ne 'print'; + } + else { + push(@result, $_); + } + } + STDOUT->autoflush(0) if $log; + close(OUTPUT); + if ( $log && $log ne 'print') { + $date = localtime(); + print LOG "Stop $command $args_str at $date\n"; + close (LOG); + } + + my $rc = $? >> 8; + + if ( $rc > 0) { + print STDERR "\n"; + print STDERR @result if !$log; + print_error("The subversion command line client failed with exit status '$rc'", 99); + } + return wantarray ? @result : \@result; +} + +sub execute_svnversion_command +{ + my $options = shift; + my @args = @_; + + my $args_str = join(" ", @args); + + # we can only parse english strings, hopefully a C locale is available everywhere + $ENV{LC_ALL}='C'; + $command = "svnversion $options $args_str"; + + if ( $debug ) { + print STDERR "\nCWS-DEBUG: ... execute command line: '$command'\n"; + } + + my $result = `$command`; + my $rc = $? >> 8; + if ($rc > 0) { + print_error("The subversion command line tool 'svnversion' failed with exit status '$rc'", 99); + } + + return $result; +} +# vim: set ts=4 shiftwidth=4 expandtab syntax=perl: diff --git a/solenv/bin/cwsattach b/solenv/bin/cwsattach new file mode 100755 index 000000000000..99bcde52977a --- /dev/null +++ b/solenv/bin/cwsattach @@ -0,0 +1,7 @@ +#!/bin/sh +if [ x${SOLARENV}x = xx ]; then + echo No environment found, please use 'configure' or 'setsolar' + exit 1 +fi +exec perl -w $SOLARENV/bin/cwsattach.pl "$@" + diff --git a/solenv/bin/cwsattach.btm b/solenv/bin/cwsattach.btm new file mode 100644 index 000000000000..94a0f28c7ab8 --- /dev/null +++ b/solenv/bin/cwsattach.btm @@ -0,0 +1,11 @@ +@echo off +iff "%SOLARENV%" == "" then + echo No environment found, please use 'configure' or 'setsolar' + goto end +endiff +iff "%PERL%" == "" then + call perl5 -I%SOLARENV%\bin\modules %SOLARENV%\bin\cwsattach.pl %1& +else + call %PERL% -I%SOLARENV%\bin\modules %SOLARENV%\bin\cwsattach.pl %1& +endiff +:end diff --git a/solenv/bin/cwsattach.pl b/solenv/bin/cwsattach.pl new file mode 100644 index 000000000000..60ad81f2f152 --- /dev/null +++ b/solenv/bin/cwsattach.pl @@ -0,0 +1,224 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: cwsattach.pl,v $ +# +# $Revision: 1.3 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +# +# cwsattach.pl - attach files to CWS +# + +use strict; +use Getopt::Long; +use Cwd; + +#### module lookup +my @lib_dirs; +BEGIN { + if ( !defined($ENV{SOLARENV}) ) { + die "No environment found (environment variable SOLARENV is undefined)"; + } + push(@lib_dirs, "$ENV{SOLARENV}/bin/modules"); + push(@lib_dirs, "$ENV{COMMON_ENV_TOOLS}/modules") if defined($ENV{COMMON_ENV_TOOLS}); +} +use lib (@lib_dirs); + +use Cws; + +#### script id ##### + +( my $script_name = $0 ) =~ s/^.*\b(\w+)\.pl$/$1/; + +my $script_rev; +my $id_str = ' $Revision: 1.3 $ '; +$id_str =~ /Revision:\s+(\S+)\s+\$/ + ? ($script_rev = $1) : ($script_rev = "-"); + +print STDERR "$script_name -- version: $script_rev\n"; + +#### global ##### + +my $is_debug = 1; # enable debug +my $opt_master = ''; # option: master workspace +my $opt_child = ''; # option: child workspace +my $opt_mime_type = ''; # option: mime type + + +#### main ##### + +my $arg_file = parse_options(); +attach_cws($arg_file); +exit(0); + +#### subroutines #### + +sub attach_cws +{ + my $filename = shift; + # get master and child workspace + my $masterws = $opt_master ? uc($opt_master) : $ENV{WORK_STAMP}; + my $childws = $opt_child ? $opt_child : $ENV{CWS_WORK_STAMP}; + + if ( !defined($masterws) ) { + print_error("Can't determine master workspace environment.\n" + . "Please initialize environment with setsolar ...", 1); + } + + if ( !defined($childws) ) { + print_error("Can't determine child workspace environment.\n" + . "Please initialize environment with setsolar ...", 1); + } + + my $cws = Cws->new(); + $cws->child($childws); + $cws->master($masterws); + + my $mime_type = $opt_mime_type ? $opt_mime_type : find_mime_type($filename); + + no strict; + + if ( is_valid_cws($cws) ) { + #print "CWS is valid filename=" . $filename . " mime_type=" . $mime_type . "\n"; + open(DATA,"<$filename") || die "can't open filename"; + $data=""; + while(<DATA>) { + $data.=$_; + } + my $result=$cws->save_attachment($filename,$mime_type,$data); + } else { + print STDERR "cws is not valid"; + } + exit(0) +} + + +sub find_mime_type +{ + my $filename = shift; + $filename=~/(.*)\.(.*$)/; + my $ext=$2; + my $fmime=''; + + if ( defined($ext) ) { + open(MIME,"< $ENV{SOLARENV}/inc/mime.types")|| die "can not open mimetype file"; + while (<MIME>) { + my @a=split(); + my $iscomment=0; + if ( /(\s*\#).*/ ) { + $iscomment=1; + } else { + $iscomment=0; + } + if ( $iscomment eq 0 && $#a >= 1 && $fmime eq '' ) { + my $i=1; + for ($i=1; $i<=$#a; $i++) { + if ( $a[$i] eq $ext ) { + $fmime=$a[0]; + } + } + } + } + + } + if ( $fmime eq '' ) { + $fmime="application/octet-stream"; + } + return $fmime; +} + + +sub is_valid_cws +{ + my $cws = shift; + + my $masterws = $cws->master(); + my $childws = $cws->child(); + # check if we got a valid child workspace + my $id = $cws->eis_id(); + if ( !$id ) { + print_error("Child workspace '$childws' for master workspace '$masterws' not found in EIS database.", 2); + } + print_message("Master workspace '$masterws', child workspace '$childws':"); + return 1; +} + +sub parse_options +{ + # parse options and do some sanity checks + my $help = 0; + my $success = GetOptions('h' => \$help, 'm=s' => \$opt_master, 'c=s'=> \$opt_child, 't=s'=> \$opt_mime_type); + if ( $help || !$success || $#ARGV < 0 ) { + usage(); + exit(1); + } + + return $ARGV[0]; +} + +sub print_message +{ + my $message = shift; + + print STDERR "$script_name: "; + print STDERR "$message\n"; + return; +} + +sub print_error +{ + my $message = shift; + my $error_code = shift; + + print STDERR "$script_name: "; + print STDERR "ERROR: $message\n"; + + if ( $error_code ) { + print STDERR "\nFAILURE: $script_name aborted.\n"; + exit($error_code); + } + return; +} + +sub usage +{ + print STDERR "Usage: cwsattach [-h] [-m master] [-c child] [-t mimetype] filename\n"; + print STDERR "\n"; + print STDERR "Attach files to CWS in EIS database\n"; + print STDERR "\n"; + print STDERR "Options:\n"; + print STDERR "\t-h\t\thelp\n"; + print STDERR "\t-m master\toverride MWS specified in environment\n"; + print STDERR "\t-c child\toverride CWS specified in environment\n"; + print STDERR "\t-t mimetype\texplicitly set mime type\n"; + print STDERR "Examples:\n"; + print STDERR "\tcwsattach barfoo.html\n"; + print STDERR "\tcwsattach -t text bar.cxx\n"; + print STDERR "\tcwsattach -t text/rtf foo.rtf\n"; +} diff --git a/solenv/bin/cwscheckapi b/solenv/bin/cwscheckapi new file mode 100755 index 000000000000..357a40a20ee5 --- /dev/null +++ b/solenv/bin/cwscheckapi @@ -0,0 +1,259 @@ +#!/bin/bash +#************************************************************************* +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: cwscheckapi,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +#***********************************************************************/ + + +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_ERROR=2 +EXIT_BUG=10 + +usage() { + echo "Usage: $SCRIPTNAME [-m MODULE1[,MODULEn]] [-k] [-o] [-h] [-d] [-i] [-t] [-s] [-a]" >&2 + echo "" >&2 + echo "[-m] list of modules to test like: '-m sw,sc,sd' or '-m all' for all modules" >&2 + echo "" >&2 + echo "[-k] keep Office installation, otherwise it will be removed after test" >&2 + echo "" >&2 + echo "[-o] force OpenOffice.org installation instead of StarOffice" >&2 + echo "" >&2 + echo "[-d] debug installation and UnoAPI-Tests" >&2 + echo "" >&2 + echo "[-i] debug installation" >&2 + echo "" >&2 + echo "[-t] debug UnoAPI-Tests" >&2 + echo "" >&2 + echo "[-s] skip installation of Office" >&2 + echo "" >&2 + echo "[-a] NoCwsAttach: do not attach UnoAPI-Test result to EIS database" >&2 + echo "" >&2 + echo "further informations: http://wiki.services.openoffice.org/wiki/Cwscheckapi" >&2 + echo "" >&2 + exit $EXIT_FAILURE +} + +if [ "$PROEXT" != ".pro" ]; then + echo "ERROR: cwscheckapi works only on pro-versions" >&2 + exit $EXIT_FAILURE +fi + +if [ x${USER}x = xx ]; then + if [ x${LOGNAME}x = xx ]; then + echo "ERROR: could not determine username. Please export variable USER" >&2 + exit $EXIT_FAILURE + else + USER=$LOGNAME + export USER + fi +fi + + + +DEBUG_I=false +DEBUG_T=false +INSTALL=true +ATTACH=ture +MODULES="auto" +OOO=false +KEEPOFFICE=false + +while getopts ':m:dkitsaho' OPTION ; do + case $OPTION in + d) DEBUG_I=true + DEBUG_T=true + ;; + m) MODULES="$OPTARG" + ;; + k) KEEPOFFICE=true + ;; + o) OOO=true + ;; + i) DEBUG_I=true + ;; + t) DEBUG_T=true + ;; + s) INSTALL=false + ;; + a) ATTACH=false + ;; + h) usage $EXIT_SUCCESS + ;; + \?) echo "unkown option \"-$OPTARG\"." >&2 + usage $EXIT_ERROR + ;; + *) echo "this is not possible...">&2 + usage $EXIT_BUG + ;; + esac +done + +shift `expr $OPTIND - 1` + +if [ -d /export/home/$USER ]; then + CWSCHECKAPIPATH=/export/home/$USER/cwscheckapi +else + if [ -w /export/home ]; then + mkdir /export/home/$USER + CWSCHECKAPIPATH=/export/home/$USER/cwscheckapi + else + CWSCHECKAPIPATH=/tmp/$USER/cwscheckapi + fi +fi + +# the following line is to cleanup old cwscheckapi-installations. It results form the first version of cwscheckapi +# The disk space on /tmp is limited. If a lot of users run cwscheckapi a lot of installed offices are in /tmp +# The new concept is to remove the offices after test. But old unused installations should be removed... +if [ $CWSCHECKAPIPATH != /tmp/$USER/cwscheckapi ]; then + rm -rf /tmp/$USER/cwscheckapi +fi + +LOCALINSTALLDIR=$CWSCHECKAPIPATH/office +LOCALUNPACKDIR=$CWSCHECKAPIPATH/unpack +export LOCALINSTALLDIR +export LOCALUNPACKDIR + +unset FORCE2ARCHIVE + +date 2>&1 + +if [ $INSTALL = true ]; then + + + if [ $DEBUG_I = true ]; then + echo "start installation: `date`" + echo call "$SOLARENV/bin/installoffice.pl -cwscheckapi true -dest $LOCALINSTALLDIR -debug $DEBUG_I" + fi + perl -w $SOLARENV/bin/installoffice.pl -cwscheckapi true -dest $LOCALINSTALLDIR -ooo $OOO -debug $DEBUG_I + + EXITVAL=$? + + if [ $EXITVAL -ne 0 ]; then + echo "ERROR: could not install office" + exit $EXITVAL + fi + echo "`date` installation successfull, start testing...." +fi + +SOFFICE="soffice" +PS=":" +CYGWIN="" + +SHELL="/bin/bash" +# cygwin: +if [ "$GUI" = "WNT" ]; then + SOFFICE="soffice.exe" + PS=";" + CYGWIN="-Cygwin true" + SHELL=`which bash` + SHELL=`cygpath -w $SHELL` + if [ ! -f $SHELL ]; then + echo "could not determine bash shell" + exit 1 + fi +fi + +if [ $DEBUG_T = true ]; then + echo find $LOCALINSTALLDIR -name $SOFFICE +fi + +OFFICEBIN=`find $LOCALINSTALLDIR -name $SOFFICE` + +if [ ! -f "$OFFICEBIN" ]; then + echo "could not find 'soffice' in subfolders of $LOCALINSTALLDIR" + exit 1 +fi + +if [ "$GUI" = "WNT" ]; then + # transform /tmp/... -> c:\tmp\... + OFFICEBIN=`cygpath -w $OFFICEBIN` +fi + +JARFOLDER=$SOLARVERSION/$INPATH/bin$UPDMINOREXT +SOLVER_LIB=$SOLARVERSION/$INPATH/lib$UPDMINOREXT +myCLASSPATH=${PS}${JARFOLDER}/ridl.jar${PS}${JARFOLDER}/unoil.jar${PS}${JARFOLDER}/jurt.jar${PS}${JARFOLDER}/juh.jar${PS}${JARFOLDER}/java_uno.jar +myCLASSPATH=$myCLASSPATH${PS}${JARFOLDER}/OOoRunner.jar +myCLASSPATH=$myCLASSPATH${PS}/net/unoapi/export/unoapi/bin/mysql.jar${PS}$SOLVER_LIB +PARAM="" +if [ -n "$JAVAI" ]; then + JAVABIN=$JAVAI +elif [ -n "$JAVA_HOME" ]; then + if [ "$OS$CPUNAME$CPU" = SOLARISSPARCU ]; then + JAVABIN=$JAVA_HOME/bin/sparcv9/java + else + JAVABIN=$JAVA_HOME/bin/java + fi +else + echo "please set environment variable JAVA_HOME" + exit 1 +fi + +if [ -n "$WORK_STAMP" ]; then + if [ -n "$CWS_WORK_STAMP" ]; then + PARAM="$PARAM -Version cws_${CWS_WORK_STAMP}" + else + echo "######" + echo CAUTION! You are working on the MWS + echo "######" + PARAM="$PARAM -Version ${WORK_STAMP}_${UPDMINOR}" + fi +fi + +PARAM="$PARAM -cmd '$OFFICEBIN -nofirststartwizard -accept=pipe,name=$USER;urp; -norestore -nocrashreport -nolockcheck -enableautomation'" +PARAM="$PARAM -cs pipe,name=$USER" +PARAM="$PARAM -NoOffice true" +PARAM="$PARAM -SRC_ROOT $SRC_ROOT" +PARAM="$PARAM -COMP_ENV $OUTPATH" +PARAM="$PARAM -Shell $SHELL" +PARAM="$PARAM $CYGWIN" +PARAM="$PARAM -tb java_complex" +PARAM="$PARAM -TimeOut 90000" +PARAM="$PARAM -o complex.unoapi.CheckModuleAPI::module($MODULES)" +if [ $ATTACH = false ]; then + PARAM="$PARAM -nca true" +fi +if [ $DEBUG_T = true ]; then + PARAM="$PARAM -debug true -log true" +fi + +#XDEBUG=" -Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8001 " +COMMAND="$JAVABIN -Xmx120m $XDEBUG -cp $myCLASSPATH org.openoffice.Runner $PARAM $*" +echo "$COMMAND" + +LOGFILE=$CWSCHECKAPIPATH/cwscheckapi.log +$COMMAND | tee $LOGFILE + +if [ $KEEPOFFICE = false ]; then + echo "remove office instrallation in $LOCALINSTALLDIR..." + rm -rf $LOCALINSTALLDIR +fi + +echo +echo A logfile could be found here: $LOGFILE + +date 2>&1
\ No newline at end of file diff --git a/solenv/bin/cwscheckapi.btm b/solenv/bin/cwscheckapi.btm new file mode 100755 index 000000000000..96e2dd7c2afc --- /dev/null +++ b/solenv/bin/cwscheckapi.btm @@ -0,0 +1,186 @@ +@echo off +REM ************************************************************************** +REM * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +REM * +REM * Copyright 2008 by Sun Microsystems, Inc. +REM * +REM * OpenOffice.org - a multi-platform office productivity suite +REM * +REM * $RCSfile: cwscheckapi.btm,v $ +REM * +REM * $Revision: 1.3.6.4 $ +REM * +REM * This file is part of OpenOffice.org. +REM * +REM * OpenOffice.org is free software: you can redistribute it and/or modify +REM * it under the terms of the GNU Lesser General Public License version 3 +REM * only, as published by the Free Software Foundation. +REM * +REM * OpenOffice.org is distributed in the hope that it will be useful, +REM * but WITHOUT ANY WARRANTY; without even the implied warranty of +REM * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +REM * GNU Lesser General Public License version 3 for more details +REM * (a copy is included in the LICENSE file that accompanied this code). +REM * +REM * You should have received a copy of the GNU Lesser General Public License +REM * version 3 along with OpenOffice.org. If not, see +REM * <http://www.openoffice.org/license.html> +REM * for a copy of the LGPLv3 License. +REM ************************************************************************/ + +echo off + +iff "%PROEXT" != ".pro" THEN + echo ERROR: cwscheckapi works only on pro-versions >&2 + quit 1 +endiff + +SET DEBIG_I=false +SET DEBUG_T=false +SET INSTALL=true +SET ATTACH=true +SET MODULES=auto +SET OOO=false +SET KEEPOFFICE=false + +for %opt in (%&%) DO ( + if "%opt%" == "-d" (SET DEBUG_I=true ^ SET DEBUG_T=true ^ shift) + if "%opt%" == "-o" (SET OOO=true ^ shift) + if "%opt%" == "-k" (SET KEEPOFFICE=true ^ shift) + if "%opt%" == "-i" (SET DEBUG_I=true ^ shift) + if "%opt%" == "-m" (SET MODULES=%2 ^ shift ^ shift) + if "%opt%" == "-t" (SET DEBUG_T=true ^ shift) + if "%opt%" == "-s" (SET INSTALL=false ^ shift) + if "%opt%" == "-a" (SET attach=false ^ shift) + if "%opt%" == "-h" goto usage + if "%opt%" == "/h" goto usage +) + +set tmppath=not_set +for %LW in (e:\,d:\,c:\) DO ( + iff NOT ISDIR %tmppath% then + iff ISDIR %LW then + iff ISDIR %LW%temp then + set tmppath=%LW%temp + elseiff ISDIR %LW%tmp then + set tmppath=%LW%tmp + else + mkdir %LW%temp + set tmppath=%LW%temp + endiff + endiff + endiff +) + +SET CWSCHECKAPIPATH=%tmppath%\%USERNAME%\cwscheckapi +SET LOCALINSTALLDIR=%CWSCHECKAPIPATH%\office +SET LOCALUNPACKDIR=%CWSCHECKAPIPATH%\unpack + +iff "%INSTALL%" == "true" THEN + call perl5 %SOLARENV%/bin/installoffice.pl -cwscheckapi true -dest %LOCALINSTALLDIR% -ooo %OOO% -debug %DEBUG_I% + + IFF %? NE 0 THEN + echo ERROR: coud not install office >&2 + quit %? + ENDIFF +ENDIFF + +setlocal + +SET CWD=%_CWD% +cdd %LOCALINSTALLDIR% +SET ffindtxt="ffind.txt" +ffind /s /f /m soffice.exe > %ffindtxt +SET FindFile=%@FILEOPEN[%ffindtxt%, READ] +SET OfficeBin=%@FILEREAD[%FindFile] +set dummy=%@FILECLOSE[%FindFile] +DEL /q %ffindtxt +cdd %CWD + +IFF NOT EXIST %OFFICEBIN% THEN + echo could not find 'soffice.exe' in subfolders of %OFFICEBIN% >&2 + quit 1 +ENDIFF + +SET JARFOLDER=%SOLARVERSION%\%INPATH%\bin%UPDMINOREXT% +SET MYCLASSPATH=%JARFOLDER%\OOoRunner.jar;%JARFOLDER%\ridl.jar;%JARFOLDER%\unoil.jar;%JARFOLDER%\jurt.jar;%JARFOLDER%\juh.jar;%JARFOLDER%\java_uno.jar + +IFF "%JAVAI%" != "" THEN + SET JAVABIN=%JAVAI% +ELSEIFF "%JAVA_HOME%" != "" THEN + SET JAVABIN=%JAVA_HOME%\bin\java +ELSE + echo please set environment variable JAVA_HOME >&2 + quit 1 +ENDIFF + +IFF "%CWS_WORK_STAMP%" != "" THEN + SET PARAM=-Version cws_%CWS_WORK_STAMP% +ELSEIFF "%WORK_STAMP%" != "" THEN + echo ###### >&2 + echo CAUTION! You\'re working on the MWS >&2 + echo ###### >&2 + SET PARAM=-Version %WORK_STAMP%_%UPDMINOR% +ELSE + echo ###### >&2 + echo ERROR: could not determine your CWS or MWS version >&2 + echo ###### >&2 + quit 1 +ENDIFF + +SET KILLCOMMAND="%SOLARVERSION%\%INPATH%\bin%UPDMINOREXT%\kill.exe -9 soffice.bin^%SOLARVERSION%\%INPATH%\bin%UPDMINOREXT%\kill.exe -9 soffice.exe" + +SET PARAM=%PARAM% -cmd '\"%OFFICEBIN%\" -nofirststartwizard -norestore -nocrashreport -nolockcheck -enableautomation -accept=pipe,name=%USERNAME%;urp;' +SET PARAM=%PARAM% -cs pipe,name=%USERNAME% +SET PARAM=%PARAM% -NoOffice true +SET PARAM=%PARAM% -SRC_ROOT %SRC_ROOT% +SET PARAM=%PARAM% -COMP_ENV %OUTPATH% +SET PARAM=%PARAM% -Shell %COMSPEC% +SET PARAM=%PARAM% -tb java_complex +SET PARAM=%PARAM% -o complex.unoapi.CheckModuleAPI::module(%MODULES%) +SET PARAM=%PARAM% -TimeOut 200000 +SET PARAM=%PARAM% -AppKillCommand %KILLCOMMAND% +IF "%ATTACH%" == "false" SET PARAM=%PARAM% -nca true +IF "%DEBUG_T%" == "true" SET PARAM=%PARAM -debug true -log true + +set COMMANDO=%JAVABIN% -Xmx120m -cp %MYCLASSPATH% org.openoffice.Runner %PARAM% %& + +echo %COMMANDO +SET LOGFILE=%CWSCHECKAPIPATH%\cwscheckapi.log +%COMMANDO |& tee %LOGFILE% + +IFF %KEEPOFFICE% == "false" THEN + echo remove office instrallation in %LOCALINSTALLDIR%... + DEL /E/F/Q/K/S/X/Y/Z %LOCALINSTALLDIR% +fi + +echo . +echo A logfile could be found here: %LOGFILE% + +endlocal + +quit 0 + +:usage + echo. + echo Usage: %0% [-m MODULE1[,MODULEn]] [-o] [-k] [-h] [-d] [-i] [-t] [-s] [-a] >&2 + echo. + echo [-m] list of modules to test like: '-m "sw,sc,sd"' or '-m all' for all modules >&2 + echo. >&2 + echo [-o] force OpenOffice.org installation instead of StarOffice >&2 + echo. >&2 + echo [-k] keep Office installation, otherwise it will be removed after test >&2 + echo. >&2 + echo [-d] debug installation and UnoAPI-Tests >&2 + echo. >&2 + echo [-i] debug installation >&2 + echo. >&2 + echo [-t] debug UnoAPI-Tests >&2 + echo. >&2 + echo [-s] skip installation of Office >&2 + echo. >&2 + echo [-a] NoCwsAttach: do not attach UnoAPI-Test result to EIS database >&2 + echo. >&2 + echo further informations: http://wiki.services.openoffice.org/wiki/Cwscheckapi >&2 + echo. >&2 + quit 1 diff --git a/solenv/bin/cwscreate b/solenv/bin/cwscreate new file mode 100755 index 000000000000..c3260f746e39 --- /dev/null +++ b/solenv/bin/cwscreate @@ -0,0 +1,6 @@ +#!/bin/sh +if [ x${SOLARENV}x = xx ]; then + echo No environment found, please use 'configure' or 'setsolar' + exit 1 +fi +echo "Please use the 'cws create' command for creating new child workspaces!" diff --git a/solenv/bin/cwstestresult b/solenv/bin/cwstestresult new file mode 100755 index 000000000000..29b1c0c8e99d --- /dev/null +++ b/solenv/bin/cwstestresult @@ -0,0 +1,7 @@ +#!/bin/sh +if [ x${SOLARENV}x = xx ]; then + echo No environment found, please use 'configure' or 'setsolar' + exit 1 +fi +exec perl -w $SOLARENV/bin/cwstestresult.pl "$@" + diff --git a/solenv/bin/cwstestresult.btm b/solenv/bin/cwstestresult.btm new file mode 100644 index 000000000000..38a012996500 --- /dev/null +++ b/solenv/bin/cwstestresult.btm @@ -0,0 +1,11 @@ +@echo off +iff "%SOLARENV%" == "" then + echo No environment found, please use 'configure' or 'setsolar' + goto end +endiff +iff "%PERL%" == "" then + call perl5 -I%SOLARENV%\bin\modules %SOLARENV%\bin\cwstestresult.pl %1& +else + call %PERL% -I%SOLARENV%\bin\modules %SOLARENV%\bin\cwstestresult.pl %1& +endiff +:end diff --git a/solenv/bin/cwstestresult.pl b/solenv/bin/cwstestresult.pl new file mode 100644 index 000000000000..25321cfa3614 --- /dev/null +++ b/solenv/bin/cwstestresult.pl @@ -0,0 +1,194 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: cwsattach.pl,v $ +# +# $Revision: 1.3 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +# +# cwstestresult.pl - publish results of CWS tests to EIS +# + +use strict; +use Getopt::Long; +use Cwd; + +#### module lookup +my @lib_dirs; +BEGIN { + if ( !defined($ENV{SOLARENV}) ) { + die "No environment found (environment variable SOLARENV is undefined)"; + } + push(@lib_dirs, "$ENV{SOLARENV}/bin/modules"); + push(@lib_dirs, "$ENV{COMMON_ENV_TOOLS}/modules") if defined($ENV{COMMON_ENV_TOOLS}); +} +use lib (@lib_dirs); + +use Cws; + +#### global ##### +( my $script_name = $0 ) =~ s/^.*\b(\w+)\.pl$/$1/; + +my $is_debug = 1; # enable debug +my $opt_master; # option: master workspace +my $opt_child; # option: child workspace +my $opt_milestone; # option: milestone +my $opt_testrunName; # option: testrunName +my $opt_testrunPlatform; # option: testrunPlatfrom +my $opt_resultPage; # option: resultPage + + +#### main ##### + +my $arg_status= parse_options(); +testresult($arg_status); +exit(0); + +#### subroutines #### + +sub testresult +{ + my $status = shift; + # get master and child workspace + my $masterws = $opt_master ? uc($opt_master) : $ENV{WORK_STAMP}; + my $milestone = $opt_milestone ? $opt_milestone : $ENV{UPDMINOR}; + my $childws = $opt_milestone ? undef : ( $opt_child ? $opt_child : $ENV{CWS_WORK_STAMP} ); + + if ( !defined($masterws) ) { + print_error("Can't determine master workspace environment.\n" + . "Please initialize environment with setsolar ...", 1); + } + + if ( !defined($childws) && !defined($milestone) ) { + print_error("Can't determine child workspace environment or milestone.\n" + . "Please initialize environment with setsolar ...", 1); + } + if ( !defined($opt_resultPage) ) { + $opt_resultPage=""; + } + my $cws = Cws->new(); + if ( defined($childws) ) { + $cws->child($childws); + } + $cws->master($masterws); + my $eis = $cws->eis(); + + no strict; + my $result=''; + + if ( defined($childws) ) { + my $id = $cws->eis_id(); + if ( is_valid_cws($cws) ) { + $result=$eis->submitTestResult($id,$opt_testrunName,$opt_testrunPlatform, $opt_resultPage, $status); + } else { + print STDERR "cws is not valid"; + } + } else { + $result=$eis->submitTestResultMWS($masterws,$milestone,$opt_testrunName,$opt_testrunPlatform, $opt_resultPage, $status); + } + + exit(0) +} + + +sub is_valid_cws +{ + my $cws = shift; + + my $masterws = $cws->master(); + my $childws = $cws->child(); + # check if we got a valid child workspace + my $id = $cws->eis_id(); + if ( !$id ) { + print_error("Child workspace '$childws' for master workspace '$masterws' not found in EIS database.", 2); + } + return 1; +} + +sub parse_options +{ + # parse options and do some sanity checks + Getopt::Long::Configure("no_ignore_case"); + my $help = 0; + my $success = GetOptions('h' => \$help, 'M=s' => \$opt_master, 'm=s' => \$opt_milestone, 'c=s' => \$opt_child, 'n=s' => \$opt_testrunName, 'p=s' => \$opt_testrunPlatform , 'r=s' => \$opt_resultPage ); + if ( $help || !$success || $#ARGV < 0 || (!defined($opt_testrunName)) || ( !defined($opt_testrunPlatform)) ) { + usage(); + exit(1); + } + if ( defined($opt_milestone) && defined($opt_child) ) { + print_error("-m and -c are mutually exclusive options",1); + } + + return $ARGV[0]; +} + +sub print_message +{ + my $message = shift; + + print STDERR "$script_name: "; + print STDERR "$message\n"; + return; +} + +sub print_error +{ + my $message = shift; + my $error_code = shift; + + print STDERR "$script_name: "; + print STDERR "ERROR: $message\n"; + + if ( $error_code ) { + print STDERR "\nFAILURE: $script_name aborted.\n"; + exit($error_code); + } + return; +} + +sub usage +{ + print STDERR "Usage: cwstestresult[-h] [-m masterws] [-m milestone|-c childws] <-n testrunName> <-p testrunPlatform> <-r resultPage> statusName\n"; + print STDERR "\n"; + print STDERR "Publish result of CWS- or milestone-test to EIS\n"; + print STDERR "\n"; + print STDERR "Options:\n"; + print STDERR "\t-h\t\t\thelp\n"; + print STDERR "\t-M master\t\toverride MWS specified in environment\n"; + print STDERR "\t-m milestone\t\toverride milestone specified in environment\n"; + print STDERR "\t-c child\t\toverride CWS specified in environment\n"; + print STDERR "\t-n testrunName\t\tspecifiy name of the test\n"; + print STDERR "\t-p testrunPlatform\tspecify platform where the test ran on\n"; + print STDERR "\t-r resultPage\t\tspecify name of attachment or hyperlink\n"; + print STDERR "\t\t\t\tfor resultPage\n"; + + + print STDERR "\nExample:\n"; + print STDERR "\tcwstestresult -c mycws -n Performance -p Windows -r PerfomanceTestWindows.html ok\n"; +} diff --git a/solenv/bin/cwstouched b/solenv/bin/cwstouched new file mode 100755 index 000000000000..1847ce388d76 --- /dev/null +++ b/solenv/bin/cwstouched @@ -0,0 +1,6 @@ +#!/bin/sh +if [ x${SOLARENV}x = xx ]; then + echo No environment found, please use 'configure' or 'setsolar' + exit 1 +fi +exec perl -w $SOLARENV/bin/cwstouched.pl
\ No newline at end of file diff --git a/solenv/bin/cwstouched.btm b/solenv/bin/cwstouched.btm new file mode 100755 index 000000000000..33e442dbb51c --- /dev/null +++ b/solenv/bin/cwstouched.btm @@ -0,0 +1,11 @@ +@echo off +iff "%SOLARENV%" == "" then + echo No environment found, please use 'configure' or 'setsolar' + goto end +endiff +iff "%PERL%" == "" then + call perl5 -I%SOLARENV%\bin\modules %SOLARENV%\bin\cwstouched.pl %1& +else + call %PERL% -I%SOLARENV%\bin\modules %SOLARENV%\bin\cwstouched.pl %1& +endiff +:end diff --git a/solenv/bin/cwstouched.pl b/solenv/bin/cwstouched.pl new file mode 100755 index 000000000000..0171e39d9fd4 --- /dev/null +++ b/solenv/bin/cwstouched.pl @@ -0,0 +1,129 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; + +#************************************************************************* +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +#***********************************************************************/ + +use strict; +use Cwd; + +#### module lookup +my @lib_dirs; +BEGIN { + if ( !defined($ENV{SOLARENV}) ) { + die "No environment found (environment variable SOLARENV is undefined)"; + } + push(@lib_dirs, "$ENV{SOLARENV}/bin/modules"); +} +use lib (@lib_dirs); + +use Cws; + +my $workstamp = $ENV{'WORK_STAMP'}; +my $solenv= $ENV{'SOLARENV'}; +my $cwsWorkStamp = getCwsWorkStamp(); +my $minor = getMinor($cwsWorkStamp); + +my $oldWorkStamp = $workstamp."_".$minor; +my $svndiff="svn diff --summarize --old=svn://svn.services.openoffice.org/ooo/tags/".$oldWorkStamp." --new=svn://svn.services.openoffice.org/ooo/cws/".$cwsWorkStamp; + +my @diff = `$svndiff`; + +my @modules; +foreach(@diff){ + if (/.*svn:\/\/svn.services.openoffice.org.*/){ + $_ =~ /.*$oldWorkStamp\/(\w*)/; + my $newModule=$1; + if (defined($newModule)){ + if ( ! grep(/$newModule/,@modules)){ + push(@modules, $newModule); + } + + } + } +} + +foreach(@modules){ + print "$_\n"; +} + +exit(0); + +sub getMinor{ + my $workst = shift; + my $min=""; + + if ( ! defined($ENV{'UPDMINOR'})){ + my $cws = Cws->new(); + $cws->child($workst); + $cws->master($ENV{'WORK_STAMP'}); + my $masterws = $cws->master(); + my $childws = $cws->child(); + + # check if we got a valid child workspace + my $id = $cws->eis_id(); + if ( !$id ) { + print("Child workspace '$childws' for master workspace '$masterws' not found in EIS database.\n"); + exit(1); + } + + my @milestones = $cws->milestone(); + foreach (@milestones) { + if ( defined($_) ) { + $min=$_; + } + } + } else { + $min = $ENV{'UPDMINOR'}; + } + + chomp($min); + return $min; +} + +sub getCwsWorkStamp { + my $cwsWorkSt=""; + + if ( ! defined($ENV{'CWS_WORK_STAMP'})){ + my $currPath= cwd; + + chdir($ENV{'SOLARENV'}); + + my @info = `svn info`; + + foreach(@info) { + if ( /URL:.*/ ){ + # URL: svn+ssh://svn@svn.services.openoffice.org/ooo/cws/qadev37/solenv + $_ =
~ /.*svn.services.openoffice.org(.*\/(.*))\/\w*/; + $cwsWorkSt=$2; #qadev37 + } + } + + } else { + $cwsWorkSt = $ENV{'CWS_WORK_STAMP'}; + } + return $cwsWorkSt +} diff --git a/solenv/bin/cwstouched.py b/solenv/bin/cwstouched.py new file mode 100755 index 000000000000..6ed3e67757b2 --- /dev/null +++ b/solenv/bin/cwstouched.py @@ -0,0 +1,110 @@ +#!/usr/bin/python + +#************************************************************************* +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +#***********************************************************************/ + +import os +import sys +import string +from os import path + +def getCurrPath(): + currPath = sys.path[0] or os.getcwd() + currPath = path.abspath(currPath) + return currPath + +def getCwsWorkStamp(): + cwsWorkStamp=os.getenv('CWS_WORK_STAMP') + + if not cwsWorkStamp: + currPath=getCurrPath() + + os.chdir(os.getenv('SOLARENV')) + + (input, output) = os.popen4("svn info") + + for outline in output.readlines(): + if outline.startswith("URL:"): + cwsWorkStamp = outline[outline.index("svn.services"):outline.index("solenv")-1] + cwsWorkStamp = cwsWorkStamp[cwsWorkStamp.rfind("/")+1:len(cwsWorkStamp)] + break + + os.putenv("CWS_WORK_STAMP",cwsWorkStamp); + os.chdir(currPath) + + return string.strip(cwsWorkStamp) + +def getMinor(cwsWorkStamp): + minor = os.getenv('UPDMINOR') + + if not minor: + if (os.getenv('OSTYPE') == "cygwin"): + bash=os.getenv("SHELL") + (input, output) = os.popen4("cygpath -w "+bash) + winbash=string.strip(output.readlines()[0]) + cws=winbash+" -c 'cws query -c "+cwsWorkStamp+" current'" + else: + cws="cws query -c "+cwsWorkStamp+" current" + + (input, output) = os.popen4(cws) + + found=0 + for outline in output.readlines(): + if found: + minor=outline + break + elif outline.find("Current milestone:") != -1: + found=1 + + return string.strip(minor) + + +workstamp = os.getenv('WORK_STAMP') +solenv= os.getenv('SOLARENV') +cwsWorkStamp=getCwsWorkStamp() +minor = getMinor(cwsWorkStamp) + +oldWorkStamp = workstamp + "_" + minor +diff="svn diff --summarize --old=svn://svn.services.openoffice.org/ooo/tags/"+oldWorkStamp+" --new=svn://svn.services.openoffice.org/ooo/cws/"+cwsWorkStamp + +modules=[] +(input, output) = os.popen4(diff) + +for outline in output.readlines(): + if outline.find("svn://svn.services.openoffice.org"): + index = outline.index(oldWorkStamp)+len(oldWorkStamp)+1 + newModule="" + if outline.find("/",index) != -1: + # seems to be a file + newModule=string.strip(outline[index:outline.index("/",index)]) + else: + #seems to be a folder + if len(outline[index:]) > 0: + newModule=string.strip(outline[index:]) + if newModule != "" and not modules.count(newModule): + modules.append(newModule) + +for module in modules: + print module
\ No newline at end of file diff --git a/solenv/bin/deliver.pl b/solenv/bin/deliver.pl new file mode 100755 index 000000000000..74ed2020184a --- /dev/null +++ b/solenv/bin/deliver.pl @@ -0,0 +1,1529 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: deliver.pl,v $ +# +# $Revision$ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +# +# deliver.pl - copy from module output tree to solver +# + +use Cwd; +use File::Basename; +use File::Copy; +use File::DosGlob 'glob'; +use File::Path; +use File::Spec; + +#### script id ##### + +( $script_name = $0 ) =~ s/^.*\b(\w+)\.pl$/$1/; + +$id_str = ' $Revision$ '; +$id_str =~ /Revision:\s+(\S+)\s+\$/ + ? ($script_rev = $1) : ($script_rev = "-"); + + +#### globals #### + +### valid actions ### +# if you add a action 'foo', than add 'foo' to this list and +# implement 'do_foo()' in the implemented actions area +@action_list = ( # valid actions + 'copy', + 'dos', + 'addincpath', + 'linklib', + 'mkdir', + 'symlink', + 'touch' + ); + +# copy filter: files matching these patterns won't be copied by +# the copy action +@copy_filter_patterns = ( + ); + +$strip = ''; +$is_debug = 0; + +$error = 0; +$module = 0; # module name +$base_dir = 0; # path to module base directory +$dlst_file = 0; # path to d.lst +$ilst_ext = 'ilst'; # extension of image lists +$umask = 22; # default file/directory creation mask +$dest = 0; # optional destination path +$common_build = 0; # do we have common trees? +$common_dest = 0; # common tree on solver + +@action_data = (); # LoL with all action data +@macros = (); # d.lst macros +@addincpath_list = (); # files which have to be filtered through addincpath +@dirlist = (); # List of 'mkdir' targets +@zip_list = (); # files which have to be zipped +@common_zip_list = (); # common files which have to be zipped +@log_list = (); # LoL for logging all copy and link actions +@common_log_list = (); # LoL for logging all copy and link actions in common_dest +$logfiledate = 0; # Make log file as old as newest delivered file +$commonlogfiledate = 0; # Make log file as old as newest delivered file + +$files_copied = 0; # statistics +$files_unchanged = 0; # statistics + +$opt_force = 0; # option force copy +$opt_minor = 0; # option deliver in minor +$opt_check = 0; # do actually execute any action +$opt_zip = 0; # create an additional zip file +$opt_silent = 0; # be silent, only report errors +$opt_verbose = 0; # be verbose (former default behaviour) +$opt_log = 1; # create an additional log file +$opt_link = 0; # hard link files into the solver to save disk space +$opt_deloutput = 0; # delete the output tree for the project once successfully delivered +$opt_checkdlst = 0; +$delete_common = 1; # for "-delete": if defined delete files from common tree also + +if ($^O ne 'cygwin') { # iz59477 - cygwin needes a dot "." at the end of filenames to disable + $maybedot = ''; # some .exe transformation magic. +} else { + $maybedot = '.'; +} + +($gui = lc($ENV{GUI})) || die "Can't determine 'GUI'. Please set environment.\n"; +$tempcounter = 0; + +# zip is default for RE master builds +$opt_zip = 1 if ( defined($ENV{DELIVER_TO_ZIP}) && uc($ENV{DELIVER_TO_ZIP}) eq 'TRUE' && ! defined($ENV{CWS_WORK_STAMP})); + +$has_symlinks = 0; # system supports symlinks + +for (@action_list) { + $action_hash{$_}++; +} + +# trap normal signals (HUP, INT, PIPE, TERM) +# for clean up on unexpected termination +use sigtrap 'handler' => \&cleanup_and_die, 'normal-signals'; + +#### main #### + +parse_options(); + +print "$script_name -- version: $script_rev\n" if !$opt_silent; + +if ( ! $opt_delete ) { + if ( $ENV{GUI} eq 'WNT' ) { + if ($ENV{COM} eq 'GCC') { + initialize_strip() ; + }; + } else { + initialize_strip(); + } +} + +init_globals(); +push_default_actions(); +parse_dlst(); +check_dlst() if $opt_checkdlst; +walk_action_data(); +walk_addincpath_list(); +write_log() if $opt_log; +zip_files() if $opt_zip; +cleanup() if $opt_delete; +delete_output() if $opt_deloutput; +print_stats(); + +exit($error); + +#### implemented actions ##### + +sub do_copy +{ + # We need to copy two times: + # from the platform dependent output tree + # and from the common output tree + my ($dependent, $common, $from, $to, $file_list); + my $line = shift; + my $touch = 0; + + $dependent = expand_macros($line); + ($from, $to) = split(' ', $dependent); + print "copy dependent: from: $from, to: $to\n" if $is_debug; + glob_and_copy($from, $to, $touch); + + if ($delete_common && $common_build && ( $line !~ /%COMMON_OUTDIR%/ ) ) { + $line =~ s/%__SRC%/%COMMON_OUTDIR%/ig; + if ( $line =~ /%COMMON_OUTDIR%/ ) { + $line =~ s/%_DEST%/%COMMON_DEST%/ig; + $common = expand_macros($line); + ($from, $to) = split(' ', $common); + print "copy common: from: $from, to: $to\n" if $is_debug; + glob_and_copy($from, $to, $touch); + } + } +} + +sub do_dos +{ + my $line = shift; + + my $command = expand_macros($line); + if ( $opt_check ) { + print "DOS: $command\n"; + } + else { + # HACK: remove MACOSX stuff which is wrongly labled with dos + # better: fix broken d.lst + return if ( $command =~ /MACOSX/ ); + $command =~ s#/#\\#g if $^O eq 'MSWin32'; + system($command); + } +} + +sub do_addincpath +{ + # just collect all addincpath files, actual filtering is done later + my $line = shift; + my ($from, $to); + my @globbed_files = (); + + $line = expand_macros($line); + ($from, $to) = split(' ', $line); + + push( @addincpath_list, @{glob_line($from, $to)}); +} + +sub do_linklib +{ + my ($lib_base, $lib_major,$from_dir, $to_dir); + my $lib = shift; + my @globbed_files = (); + my %globbed_hash = (); + + print "linklib: $lib\n" if $is_debug; + print "has symlinks\n" if ( $has_symlinks && $is_debug ); + + return unless $has_symlinks; + + $from_dir = expand_macros('../%__SRC%/lib'); + $to_dir = expand_macros('%_DEST%/lib%_EXT%'); + + @globbed_files = glob("$from_dir/$lib"); + + if ( $#globbed_files == -1 ) { + return; + } + + foreach $lib (@globbed_files) { + $lib = basename($lib); + if ( $lib =~ /^(lib\S+(\.so|\.dylib))\.(\d+)\.(\d+)(\.(\d+))?$/ + || $lib =~ /^(lib\S+(\.so|\.dylib))\.(\d+)$/ ) + { + push(@{$globbed_hash{$1}}, $lib); + } + else { + print_warning("invalid library name: $lib"); + } + } + + foreach $lib_base ( sort keys %globbed_hash ) { + $lib = get_latest_patchlevel(@{$globbed_hash{$lib_base}}); + + if ( $lib =~ /^(lib\S+(\.so|\.dylib))\.(\d+)\.(\d+)(\.(\d+))?$/ ) + { + $lib_major = "$lib_base.$3"; + $long = 1; + } + else + { + # $lib =~ /^(lib[\w-]+(\.so|\.dylib))\.(\d+)$/; + $long = 0; + } + + if ( $opt_check ) { + if ( $opt_delete ) { + print "REMOVE: $to_dir/$lib_major\n" if $long; + print "REMOVE: $to_dir/$lib_base\n"; + } + else { + print "LINKLIB: $to_dir/$lib -> $to_dir/$lib_major\n" if $long; + print "LINKLIB: $to_dir/$lib -> $to_dir/$lib_base\n"; + } + } + else { + if ( $opt_delete ) { + print "REMOVE: $to_dir/$lib_major\n" if ($long && $opt_verbose); + print "REMOVE: $to_dir/$lib_base\n" if $opt_verbose; + unlink "$to_dir/$lib_major" if $long; + unlink "$to_dir/$lib_base"; + if ( $opt_zip ) { + push_on_ziplist("$to_dir/$lib_major") if $long; + push_on_ziplist("$to_dir/$lib_base"); + } + return; + } + my $symlib; + my @symlibs; + if ($long) + { + @symlibs = ("$to_dir/$lib_major", "$to_dir/$lib_base"); + } + else + { + @symlibs = ("$to_dir/$lib_base"); + } + # remove old symlinks + unlink(@symlibs); + foreach $symlib (@symlibs) { + print "LINKLIB: $lib -> $symlib\n" if $opt_verbose; + if ( !symlink("$lib", "$symlib") ) { + print_error("can't symlink $lib -> $symlib: $!",0); + } + else { + push_on_ziplist($symlib) if $opt_zip; + push_on_loglist("LINK", "$lib", "$symlib") if $opt_log; + } + } + } + } +} + +sub do_mkdir +{ + my $path = expand_macros(shift); + # strip whitespaces from path name + $path =~ s/\s$//; + if (( ! $opt_delete ) && ( ! -d $path )) { + if ( $opt_check ) { + print "MKDIR: $path\n"; + } else { + mkpath($path, 0, 0777-$umask); + if ( ! -d $path ) { + print_error("mkdir: could not create directory '$path'", 0); + } + } + } +} + +sub do_symlink +{ + my $line = shift; + + $line = expand_macros($line); + ($from, $to) = split(' ',$line); + my $fullfrom = $from; + if ( dirname($from) eq dirname($to) ) { + $from = basename($from); + } + elsif ( dirname($from) eq '.' ) { + # nothing to do + } + else { + print_error("symlink: link must be in the same directory as file",0); + return 0; + } + + print "symlink: $from, to: $to\n" if $is_debug; + + return unless $has_symlinks; + + if ( $opt_check ) { + if ( $opt_delete ) { + print "REMOVE: $to\n"; + } + else { + print "SYMLINK $from -> $to\n"; + } + } + else { + print "REMOVE: $to\n" if $opt_verbose; + unlink $to; + if ( $opt_delete ) { + push_on_ziplist($to) if $opt_zip; + return; + } + return unless -e $fullfrom; + print "SYMLIB: $from -> $to\n" if $opt_verbose; + if ( !symlink("$from", "$to") ) { + print_error("can't symlink $from -> $to: $!",0); + } + else { + push_on_ziplist($to) if $opt_zip; + push_on_loglist("LINK", "$from", "$to") if $opt_log; + } + } +} + +sub do_touch +{ + my ($from, $to); + my $line = shift; + my $touch = 1; + + $line = expand_macros($line); + ($from, $to) = split(' ', $line); + print "touch: $from, to: $to\n" if $is_debug; + glob_and_copy($from, $to, $touch); +} + +#### subroutines ##### + +sub parse_options +{ + my $arg; + my $dontdeletecommon = 0; + $opt_silent = 1 if ( defined $ENV{VERBOSE} && $ENV{VERBOSE} eq 'FALSE'); + $opt_verbose = 1 if ( defined $ENV{VERBOSE} && $ENV{VERBOSE} eq 'TRUE'); + while ( $arg = shift @ARGV ) { + $arg =~ /^-force$/ and $opt_force = 1 and next; + $arg =~ /^-minor$/ and $opt_minor = 1 and next; + $arg =~ /^-check$/ and $opt_check = 1 and $opt_verbose = 1 and next; + $arg =~ /^-quiet$/ and $opt_silent = 1 and next; + $arg =~ /^-verbose$/ and $opt_verbose = 1 and next; + $arg =~ /^-zip$/ and $opt_zip = 1 and next; + $arg =~ /^-delete$/ and $opt_delete = 1 and next; + $arg =~ /^-dontdeletecommon$/ and $dontdeletecommon = 1 and next; + $arg =~ /^-help$/ and $opt_help = 1 and $arg = ''; + $arg =~ /^-link$/ and $ENV{GUI} ne 'WNT' and $opt_link = 1 and next; + $arg =~ /^-deloutput$/ and $opt_deloutput = 1 and next; + $arg =~ /^-debug$/ and $is_debug = 1 and next; + $arg =~ /^-checkdlst$/ and $opt_checkdlst = 1 and next; + print_error("invalid option $arg") if ( $arg =~ /^-/ ); + if ( $arg =~ /^-/ || $opt_help || $#ARGV > -1 ) { + usage(1); + } + $dest = $arg; + } + # $dest and $opt_zip or $opt_delete are mutually exclusive + if ( $dest and ($opt_zip || $opt_delete) ) { + usage(1); + } + # $opt_silent and $opt_check or $opt_verbose are mutually exclusive + if ( ($opt_check or $opt_verbose) and $opt_silent ) { + print STDERR "Error on command line: options '-check' and '-quiet' are mutually exclusive.\n"; + usage(1); + } + if ($dontdeletecommon) { + if (!$opt_delete) { + usage(1); + } + $delete_common = 0; + }; + # $opt_delete implies $opt_force + $opt_force = 1 if $opt_delete; +} + +sub init_globals +{ + my $ext; + ($module, $base_dir, $dlst_file) = get_base(); + + # for CWS: + $module =~ s/\.lnk$//; + + print "Module=$module, Base_Dir=$base_dir, d.lst=$dlst_file\n" if $is_debug; + + $umask = umask(); + if ( !defined($umask) ) { + $umask = 22; + } + + my $build_sosl = $ENV{'BUILD_SOSL'}; + my $common_outdir = $ENV{'COMMON_OUTDIR'}; + my $inpath = $ENV{'INPATH'}; + my $solarversion = $ENV{'SOLARVERSION'}; + my $updater = $ENV{'UPDATER'}; + my $updminor = $ENV{'UPDMINOR'}; + my $work_stamp = $ENV{'WORK_STAMP'}; + + # special security check for release engineers + if ( defined($updater) && !defined($build_sosl) && !$opt_force) { + my $path = getcwd(); + if ( $path !~ /$work_stamp/io ) { + print_error("can't deliver from local directory to SOLARVERSION"); + print STDERR "\nDANGER! Release Engineer:\n"; + print STDERR "do you really want to deliver from $path to SOLARVERSION?\n"; + print STDERR "If so, please use the -force switch\n\n"; + exit(7); + } + } + + # do we have a valid environment? + if ( !defined($inpath) ) { + print_error("no environment", 0); + exit(3); + } + + $ext = ""; + if ( ($opt_minor || $updminor) && !$dest ) { + if ( $updminor ) { + $ext = ".$updminor"; + } + else { + print_error("can't determine UPDMINOR", 0); + exit(3); + } + } + + # Do we have common trees? + if ( defined($ENV{'common_build'}) && $ENV{'common_build'} eq 'TRUE' ) { + $common_build = 1; + if ((defined $common_outdir) && ($common_outdir ne "")) { + $common_outdir = $common_outdir . ".pro" if $inpath =~ /\.pro$/; + if ( $dest ) { + $common_dest = $dest; + } else { + $common_dest = "$solarversion/$common_outdir"; + $dest = "$solarversion/$inpath"; + } + } else { + print_error("common_build defined without common_outdir", 0); + exit(6); + } + } else { + $common_outdir = $inpath; + $dest = "$solarversion/$inpath" if ( !$dest ); + $common_dest = $dest; + } + $dest =~ s#\\#/#g; + $common_dest =~ s#\\#/#g; + + # the following macros are obsolete, will be flagged as error + # %__WORKSTAMP% + # %GUIBASE% + # %SDK% + # %SOLARVER% + # %__OFFENV% + # %DLLSUFFIX%' + # %OUTPATH% + # %L10N_FRAMEWORK% + # %UPD% + + # valid macros + @macros = ( + [ '%__PRJROOT%', $base_dir ], + [ '%__SRC%', $inpath ], + [ '%_DEST%', $dest ], + [ '%_EXT%', $ext ], + [ '%COMMON_OUTDIR%', $common_outdir ], + [ '%COMMON_DEST%', $common_dest ], + [ '%GUI%', $gui ] + ); + + # find out if the system supports symlinks + $has_symlinks = eval { symlink("",""); 1 }; +} + +sub get_base +{ + # a module base dir contains a subdir 'prj' + # which in turn contains a file 'd.lst' + my (@field, $base, $dlst); + my $path = getcwd(); + + @field = split(/\//, $path); + + while ( $#field != -1 ) { + $base = join('/', @field); + $dlst = $base . '/prj/d.lst'; + last if -e $dlst; + pop @field; + } + + if ( $#field == -1 ) { + print_error("can't determine module"); + exit(2); + } + else { + return ($field[-1], $base, $dlst); + } +} + +sub parse_dlst +{ + my $line_cnt = 0; + open(DLST, "<$dlst_file") or die "can't open d.lst"; + while(<DLST>) { + $line_cnt++; + tr/\r\n//d; + next if /^#/; + next if /^\s*$/; + if (!$delete_common && /%COMMON_DEST%/) { + # Just ignore all lines with %COMMON_DEST% + next; + }; + if ( /^\s*(\w+?):\s+(.*)$/ ) { + if ( !exists $action_hash{$1} ) { + print_error("unknown action: \'$1\'", $line_cnt); + exit(4); + } + push(@action_data, [$1, $2]); + } + else { + if ( /^\s*%(COMMON)?_DEST%\\/ ) { + # only copy from source dir to solver, not from solver to solver + print_warning("illegal copy action, ignored: \'$_\'", $line_cnt); + next; + } + push(@action_data, ['copy', $_]); + # for each ressource file (.res) copy its image list (.ilst) + if ( /\.res\s/ ) { + my $imagelist = $_; + $imagelist =~ s/\.res/\.$ilst_ext/g; + $imagelist =~ s/\\bin%_EXT%\\/\\res%_EXT%\\img\\/; + push(@action_data, ['copy', $imagelist]); + } + } + # call expand_macros()just to find any undefined macros early + # real expansion is done later + expand_macros($_, $line_cnt); + } + close(DLST); +} + +sub expand_macros +{ + # expand all macros and change backslashes to slashes + my $line = shift; + my $line_cnt = shift; + my $i; + + for ($i=0; $i<=$#macros; $i++) { + $line =~ s/$macros[$i][0]/$macros[$i][1]/gi + } + if ( $line =~ /(%\w+%)/ ) { + if ( $1 ne '%OS%' ) { # %OS% looks like a macro but is not ... + print_error("unknown/obsolete macro: \'$1\'", $line_cnt); + } + } + $line =~ s#\\#/#g; + return $line; +} + +sub walk_action_data +{ + # all actions have to be excuted relative to the prj directory + chdir("$base_dir/prj"); + # dispatch depending on action type + for (my $i=0; $i <= $#action_data; $i++) { + &{"do_".$action_data[$i][0]}($action_data[$i][1]); + if ( $action_data[$i][0] eq 'mkdir' ) { + # fill array with (possibly) created directories in + # revers order for removal in 'cleanup' + unshift @dirlist, $action_data[$i][1]; + } + } +} + +sub glob_line +{ + my $from = shift; + my $to = shift; + my $to_dir = shift; + my $replace = 0; + my @globbed_files = (); + + if ( ! ( $from && $to ) ) { + print_warning("Error in d.lst? source: '$from' destination: '$to'"); + return \@globbed_files; + } + + if ( $to =~ /[\*\?\[\]]/ ) { + my $to_fname; + ($to_fname, $to_dir) = fileparse($to); + $replace = 1; + } + + if ( $from =~ /[\*\?\[\]]/ ) { + # globbing necessary, no renaming possible + my $file; + my @file_list = glob($from); + + foreach $file ( @file_list ) { + my ($fname, $dir) = fileparse($file); + my $copy = ($replace) ? $to_dir . $fname : $to . '/' . $fname; + push(@globbed_files, [$file, $copy]); + } + } + else { + # no globbing but renaming possible + push(@globbed_files, [$from, $to]); + } + if ( $opt_checkdlst ) { + my $outtree = expand_macros("%__SRC%"); + my $commonouttree = expand_macros("%COMMON_OUTDIR%"); + if (( $from !~ /\Q$outtree\E/ ) && ( $from !~ /\Q$commonouttree\E/ )) { + print_warning("'$from' does not match any file") if ( $#globbed_files == -1 ); + } + } + return \@globbed_files; +} + + +sub glob_and_copy +{ + my $from = shift; + my $to = shift; + my $touch = shift; + + my @copy_files = @{glob_line($from, $to)}; + + for (my $i = 0; $i <= $#copy_files; $i++) { + next if filter_out($copy_files[$i][0]); # apply copy filter + copy_if_newer($copy_files[$i][0], $copy_files[$i][1], $touch) + ? $files_copied++ : $files_unchanged++; + } +} + +sub is_unstripped { + my $file_name = shift; + my $nm_output; + + if (-f $file_name.$maybedot) { + my $file_type = `file $file_name`; + # OS X file command doesn't know if a file is stripped or not + if (($file_type =~ /not stripped/o) || ($file_type =~ /Mach-O/o) || + (($file_type =~ /PE/o) && ($ENV{GUI} eq 'WNT') && + ($nm_output = `nm $file_name 2>&1`) && $nm_output && + !($nm_output =~ /no symbols/i) && !($nm_output =~ /not recognized/i))) { + return '1' if ($file_name =~ /\.bin$/o); + return '1' if ($file_name =~ /\.so\.*/o); + return '1' if ($file_name =~ /\.dylib\.*/o); + return '1' if ($file_name =~ /\.com\.*/o); + return '1' if ($file_name =~ /\.dll\.*/o); + return '1' if ($file_name =~ /\.exe\.*/o); + return '1' if (basename($file_name) !~ /\./o); + } + }; + return ''; +} + +sub initialize_strip { + if ((!defined $ENV{DISABLE_STRIP}) || ($ENV{DISABLE_STRIP} eq "")) { + $strip .= 'guw ' if ($^O eq 'cygwin'); + $strip .= 'strip'; + $strip .= " -x" if ($ENV{OS} eq 'MACOSX'); + $strip .= " -R '.comment' -s" if ($ENV{OS} eq 'LINUX'); + }; +}; + +sub is_jar { + my $file_name = shift; + + if (-f $file_name && (( `file $file_name` ) =~ /Zip archive/o)) { + return '1' if ($file_name =~ /\.jar\.*/o); + }; + return ''; +} + +sub execute_system { + my $command = shift; + if (system($command)) { + print_error("Failed to execute $command"); + exit($?); + }; +}; + +sub strip_target { + my $file = shift; + my $temp_file = shift; + $temp_file =~ s/\/{2,}/\//g; + my $rc = copy($file, $temp_file); + execute_system("$strip $temp_file"); + return $rc; +}; + +sub copy_if_newer +{ + # return 0 if file is unchanged ( for whatever reason ) + # return 1 if file has been copied + my $from = shift; + my $to = shift; + my $touch = shift; + my $from_stat_ref; + my $rc = 0; + + print "testing $from, $to\n" if $is_debug; + push_on_ziplist($to) if $opt_zip; + push_on_loglist("COPY", "$from", "$to") if $opt_log; + return 0 unless ($from_stat_ref = is_newer($from, $to, $touch)); + + if ( $opt_delete ) { + print "REMOVE: $to\n" if $opt_verbose; + $rc = unlink($to) unless $opt_check; + # handle special packaging of *.dylib files for Mac OS X + if ( $to =~ s/\.dylib$/.jnilib/ ) { + print "REMOVE: $to\n" if $opt_verbose; + $rc += unlink "$to" unless $opt_check; + } + return 1 if $opt_check; + return $rc; + } + + if( !$opt_check && $opt_link ) { + # hard link if possible + if( link($from, $to) ){ + print "LINK: $from -> $to\n" if $opt_verbose; + return 1; + } + } + + if( $touch ) { + print "TOUCH: $from -> $to\n" if $opt_verbose; + } + else { + print "COPY: $from -> $to\n" if $opt_verbose; + } + + return 1 if( $opt_check ); + + # + # copy to temporary file first and rename later + # to minimize the possibility for race conditions + local $temp_file = sprintf('%s.%d-%d', $to, $$, time()); + $rc = ''; + if (($strip ne '') && (defined $ENV{PROEXT}) && (is_unstripped($from))) { + $rc = strip_target($from, $temp_file); + } else { + $rc = copy($from, $temp_file); + }; + if ( $rc) { + if ( is_newer($temp_file, $from, 0) ) { + $rc = utime($$from_stat_ref[9], $$from_stat_ref[9], $temp_file); + if ( !$rc ) { + print_warning("can't update temporary file modification time '$temp_file': $!\n + Check file permissions of '$from'.",0); + } + } + fix_file_permissions($$from_stat_ref[2], $temp_file); + if ( $^O eq 'os2' ) + { + $rc = unlink($to); # YD OS/2 can't rename if $to exists! + } + # Ugly hack: on windows file locking(?) sometimes prevents renaming. + # Until we've found and fixed the real reason try it repeatedly :-( + my $try = 0; + my $maxtries = 1; + $maxtries = 5 if ( $^O eq 'MSWin32' ); + my $success = 0; + while ( $try < $maxtries && ! $success ) { + sleep $try; + $try ++; + $success = rename($temp_file, $to); + } + if ( $success ) { + # handle special packaging of *.dylib files for Mac OS X + if ( $^O eq 'darwin' ) + { + if ( $to =~ /\.dylib/ ) { + system("macosx-create-bundle", $to); + my $bundlelib = $to; + $bundlelib =~ s/\.dylib$//; + $bundlelib .= ".jnilib"; + if ( $opt_delete ) { + print "REMOVE: $bundlelib\n" if $opt_verbose; + unlink "$bundlelib" unless $opt_check; + } else { + push_on_ziplist($bundlelib) if $opt_zip; + push_on_loglist("LINK", basename($to), "$bundlelib") if $opt_log; + } + } + system("macosx-create-bundle", "$to=$from.app") if ( -d "$from.app" ); + system("ranlib", "$to" ) if ( $to =~ /\.a/ ); + } + if ( $try > 1 ) { + print_warning("File '$to' temporarily locked. Dependency bug?"); + } + return 1; + } + else { + print_error("can't rename temporary file to $to: $!",0); + } + } + else { + print_error("can't copy $from: $!",0); + my $destdir = dirname($to); + if ( ! -d $destdir ) { + print_error("directory '$destdir' does not exist", 0); + } + } + unlink($temp_file); + return 0; +} + +sub is_newer +{ + # returns whole stat buffer if newer + my $from = shift; + my $to = shift; + my $touch = shift; + my (@from_stat, @to_stat); + + @from_stat = stat($from.$maybedot); + if ( $opt_checkdlst ) { + my $outtree = expand_macros("%__SRC%"); + my $commonouttree = expand_macros("%COMMON_OUTDIR%"); + if ( $from !~ /$outtree/ ) { + if ( $from !~ /$commonouttree/ ) { + print_warning("'$from' does not exist") unless -e _; + } + } + } + return 0 unless -f _; + + if ( $touch ) { + $from_stat[9] = time(); + } + # adjust timestamps to even seconds + # this is necessary since NT platforms have a + # 2s modified time granularity while the timestamps + # on Samba volumes have a 1s granularity + + $from_stat[9]-- if $from_stat[9] % 2; + + if ( $to =~ /^\Q$dest\E/ ) { + if ( $from_stat[9] > $logfiledate ) { + $logfiledate = $from_stat[9]; + } + } elsif ( $common_build && ( $to =~ /^\Q$common_dest\E/ ) ) { + if ( $from_stat[9] > $commonlogfiledate ) { + $commonlogfiledate = $from_stat[9]; + } + } + + @to_stat = stat($to.$maybedot); + return \@from_stat unless -f _; + + if ( $opt_force ) { + return \@from_stat; + } + else { + return ($from_stat[9] > $to_stat[9]) ? \@from_stat : 0; + } +} + +sub filter_out +{ + my $file = shift; + + foreach my $pattern ( @copy_filter_patterns ) { + if ( $file =~ /$pattern/ ) { + print "filter out: $file\n" if $is_debug; + return 1; + } + } + + return 0; +} + +sub fix_file_permissions +{ + my $mode = shift; + my $file = shift; + + if ( ($mode >> 6) % 2 == 1 ) { + $mode = 0777 & ~$umask; + } + else { + $mode = 0666 & ~$umask; + } + chmod($mode, $file); +} + +sub get_latest_patchlevel +{ + # note: feed only well formed library names to this function + # of the form libfoo.so.x.y.z with x,y,z numbers + + my @sorted_files = sort by_rev @_; + return $sorted_files[-1]; + + sub by_rev { + # comparison function for sorting + my (@field_a, @field_b, $i); + + $a =~ /^(lib[\w-]+(\.so|\.dylib))\.(\d+)\.(\d+)\.(\d+)$/; + @field_a = ($3, $4, $5); + $b =~ /^(lib[\w-]+(\.so|\.dylib))\.(\d+)\.(\d+)\.(\d+)$/; + @field_b = ($3, $4, $5); + + for ($i = 0; $i < 3; $i++) + { + if ( ($field_a[$i] < $field_b[$i]) ) { + return -1; + } + if ( ($field_a[$i] > $field_b[$i]) ) { + return 1; + } + } + + # can't happen + return 0; + } + +} + +sub push_default_actions +{ + # any default action (that is an action which must be done even without + # a corresponding d.lst entry) should be pushed here on the + # @action_data list. + my $subdir; + my @subdirs = ( + 'bin', + 'doc', + 'inc', + 'lib', + 'par', + 'pck', + 'rdb', + 'res', + 'xml' + ); + push(@subdirs, 'zip') if $opt_zip; + push(@subdirs, 'idl') if ! $common_build; + push(@subdirs, 'pus') if ! $common_build; + my @common_subdirs = ( + 'bin', + 'idl', + 'inc', + 'pck', + 'pus', + 'res' + ); + push(@common_subdirs, 'zip') if $opt_zip; + + if ( ! $opt_delete ) { + # create all the subdirectories on solver + foreach $subdir (@subdirs) { + push(@action_data, ['mkdir', "%_DEST%/$subdir%_EXT%"]); + } + if ( $common_build ) { + foreach $subdir (@common_subdirs) { + push(@action_data, ['mkdir', "%COMMON_DEST%/$subdir%_EXT%"]); + } + } + } + push(@action_data, ['mkdir', "%_DEST%/inc%_EXT%/$module"]); + if ( $common_build ) { + push(@action_data, ['mkdir', "%COMMON_DEST%/inc%_EXT%/$module"]); + push(@action_data, ['mkdir', "%COMMON_DEST%/res%_EXT%/img"]); + } else { + push(@action_data, ['mkdir', "%_DEST%/res%_EXT%/img"]); + } + + # deliver build.lst to $dest/inc/$module + push(@action_data, ['copy', "build.lst %_DEST%/inc%_EXT%/$module/build.lst"]); + if ( $common_build ) { + # ... and to $common_dest/inc/$module + push(@action_data, ['copy', "build.lst %COMMON_DEST%/inc%_EXT%/$module/build.lst"]); + } + + # need to copy libstaticmxp.dylib for Mac OS X + if ( $^O eq 'darwin' ) + { + push(@action_data, ['copy', "../%__SRC%/lib/lib*static*.dylib %_DEST%/lib%_EXT%/lib*static*.dylib"]); + } +} + +sub walk_addincpath_list +{ + my (@addincpath_headers); + return if $#addincpath_list == -1; + + # create hash with all addincpath header names + for (my $i = 0; $i <= $#addincpath_list; $i++) { + my @field = split('/', $addincpath_list[$i][0]); + push (@addincpath_headers, $field[-1]); + } + + # now stream all addincpath headers through addincpath filter + for (my $i = 0; $i <= $#addincpath_list; $i++) { + add_incpath_if_newer($addincpath_list[$i][0], $addincpath_list[$i][1], \@addincpath_headers) + ? $files_copied++ : $files_unchanged++; + } +} + +sub add_incpath_if_newer +{ + my $from = shift; + my $to = shift; + my $modify_headers_ref = shift; + my ($from_stat_ref, $header); + + push_on_ziplist($to) if $opt_zip; + push_on_loglist("ADDINCPATH", "$from", "$to") if $opt_log; + + if ( $opt_delete ) { + print "REMOVE: $to\n" if $opt_verbose; + my $rc = unlink($to); + return 1 if $rc; + return 0; + } + + if ( $from_stat_ref = is_newer($from, $to) ) { + print "ADDINCPATH: $from -> $to\n" if $opt_verbose; + + return 1 if $opt_check; + + my $save = $/; + undef $/; + open(FROM, "<$from"); + # slurp whole file in one big string + my $content = <FROM>; + close(FROM); + $/ = $save; + + foreach $header (@$modify_headers_ref) { + $content =~ s/#include [<"]$header[>"]/#include <$module\/$header>/g; + } + + open(TO, ">$to"); + print TO $content; + close(TO); + + utime($$from_stat_ref[9], $$from_stat_ref[9], $to); + fix_file_permissions($$from_stat_ref[2], $to); + return 1; + } + return 0; +} + +sub push_on_ziplist +{ + my $file = shift; + return if ( $opt_check ); + # strip $dest from path since we don't want to record it in zip file + if ( $file =~ s#^\Q$dest\E/##o ) { + if ( $opt_minor ){ + # strip minor from path + my $ext = "%_EXT%"; + $ext = expand_macros($ext); + $file =~ s#^$ext##o; + } + push(@zip_list, $file); + } elsif ( $file =~ s#^\Q$common_dest\E/##o ) { + if ( $opt_minor ){ + # strip minor from path + my $ext = "%_EXT%"; + $ext = expand_macros($ext); + $file =~ s#^$ext##o; + } + push(@common_zip_list, $file); + } +} + +sub push_on_loglist +{ + my @entry = @_; + return 0 if ( $opt_check ); + return -1 if ( $#entry != 2 ); + if (( $entry[0] eq "COPY" ) || ( $entry[0] eq "ADDINCPATH" )) { + return 0 if ( ! -e $entry[1].$maybedot ); + # make 'from' relative to source root + $entry[1] = $module . "/prj/" . $entry[1]; + $entry[1] =~ s/^$module\/prj\/\.\./$module/; + } + # platform or common tree? + my $common; + if ( $entry[2] =~ /^\Q$dest\E/ ) { + $common = 0; + } elsif ( $common_build && ( $entry[2] =~ /^\Q$common_dest\E/ )) { + $common = 1; + } else { + warn "Neither common nor platform tree?"; + return; + } + # make 'to' relative to SOLARVERSION + my $solarversion = $ENV{'SOLARVERSION'}; + $solarversion =~ s#\\#/#g; + $entry[2] =~ s/^\Q$solarversion\E\///; + # strip minor from 'to' + my $ext = "%_EXT%"; + $ext = expand_macros($ext); + $entry[2] =~ s#$ext([\\\/])#$1#o; + + if ( $common ) { + push @common_log_list, [@entry]; + } else { + push @log_list, [@entry]; + } + return 1; +} + +sub zip_files +{ + my $zipexe = 'zip'; + $zipexe .= ' -y' unless $^O eq 'MSWin32'; + + my ($platform_zip_file, $common_zip_file); + $platform_zip_file = "%_DEST%/zip%_EXT%/$module.zip"; + $platform_zip_file = expand_macros($platform_zip_file); + my (%dest_dir, %list_ref); + $dest_dir{$platform_zip_file} = $dest; + $list_ref{$platform_zip_file} = \@zip_list; + if ( $common_build ) { + $common_zip_file = "%COMMON_DEST%/zip%_EXT%/$module.zip"; + $common_zip_file = expand_macros($common_zip_file); + $dest_dir{$common_zip_file} = $common_dest; + $list_ref{$common_zip_file} = \@common_zip_list; + } + + my $ext = "%_EXT%"; + $ext = expand_macros($ext); + + my @zipfiles; + $zipfiles[0] = $platform_zip_file; + if ( $common_build ) { + push @zipfiles, ($common_zip_file); + } + foreach my $zip_file ( @zipfiles ) { + print "ZIP: updating $zip_file\n" if $opt_verbose; + next if ( $opt_check ); + + local $work_file = ""; + if ( $ext) { + # We are delivering into a minor. Zip files must not contain the + # minor extension, so we have to pre and post process it. + # + # Pre process: add minor extension to path, create working copy in + # temp directory. + $work_file = get_tempfilename() . ".zip"; + die "Error: temp file $work_file already exists" if ( -e $work_file); + zipped_path_extension($zip_file, $work_file, $ext, 1) if ( -e $zip_file ); + } elsif ( $zip_file eq $common_zip_file) { + # Zip file in common tree: work on uniq copy to avoid collisions + $work_file = $zip_file; + $work_file =~ s/\.zip$//; + $work_file .= (sprintf('.%d-%d', $$, time())) . ".zip"; + die "Error: temp file $work_file already exists" if ( -e $work_file); + copy($zip_file, $work_file) if ( -e $zip_file ); + } else { + # No pre processing necessary, working directly on solver. + $work_file = $zip_file; + } + + # zip content has to be relative to $dest_dir + chdir($dest_dir{$zip_file}) or die "Error: cannot chdir into $dest_dir{$zip_file}"; + my $this_ref = $list_ref{$zip_file}; + if ( $opt_delete ) { + if ( -e $work_file ) { + open(UNZIP, "unzip -t $work_file 2>&1 |") or die "error opening zip file"; + if ( grep /empty/, (<UNZIP>)) { + close(UNZIP); + unlink $work_file; + next; + } + close(UNZIP); + open(ZIP, "| $zipexe -q -o -d -@ $work_file") or die "error opening zip file"; + foreach $file ( @$this_ref ) { + print "ZIP: removing $file from $platform_zip_file\n" if $is_debug; + print ZIP "$file\n"; + } + close(ZIP); + } + } else { + open(ZIP, "| $zipexe -q -o -u -@ $work_file") or die "error opening zip file"; + foreach $file ( @$this_ref ) { + print "ZIP: adding $file to $zip_file\n" if $is_debug; + print ZIP "$file\n"; + } + close(ZIP); + } + if ( $ext ) { + # Post process: strip minor from stored path again + zipped_path_extension($work_file, $zip_file, $ext, 0); + if (( -e $work_file ) && ($work_file ne $zip_file)) { + unlink $work_file; + } + } elsif ( $zip_file eq $common_zip_file) { + # rename work file back + if ( -e $work_file ) { + if (! rename($work_file, $zip_file)) { + print_error("can't rename temporary file to $zip_file: $!",0); + unlink $work_file; + } + } + } + } +} + +sub zipped_path_extension +# add given extension to or strip it from stored path +{ + require Archive::Zip; import Archive::Zip; + my ($from, $to, $extension, $with_ext) = @_; + + $zip = Archive::Zip->new(); + if ( -e $from) { + die 'Error: zip read error' unless $zip->read( $from) == 0; + my $name; + my $newmember; + my $DateTime = 0; + foreach my $member ( $zip->members() ) { + $name = $member->fileName(); + if ( $with_ext ) { + if ( $name !~ m#$extension/# ) { + $name =~ s#^(.*?)/#$1$extension/#o; + } + } else { + $name =~ s#^(.*?)$extension/#$1/#o; + } + $member->fileName( $name ); + if ( $member->lastModTime() ) { + if ( $DateTime < $member->lastModTime() ) { + $DateTime = $member->lastModTime(); + } + } + } + if ( -e $to ) { + die 'Error: zip write error' unless $zip->overwrite( ) == 0; + File::Copy::move( $from, $to) or die "Error $!: cannot move $from $to"; + } else { + die 'Error: zip write error' unless $zip->writeToFileNamed( $to ) == 0; + } + utime $DateTime, $DateTime, $to; + } else { + die "Error: file $from does not exist" if ( ! $opt_delete); + } + return; +} + +sub get_tempfilename +{ + my $temp_dir = shift; + $temp_dir = ( -d '/tmp' ? '/tmp' : $ENV{TMPDIR} || $ENV{TEMP} || '.' ) + unless defined($temp_dir); + if ( ! -d $temp_dir ) { + die "no temp directory $temp_dir\n"; + } + my $base_name = sprintf( "%d-%di-%d", $$, time(), $tempcounter++ ); + return "$temp_dir/$base_name"; +} + +sub write_log +{ + my (%log_file, %file_date); + $log_file{\@log_list} = "%_DEST%/inc%_EXT%/$module/deliver.log"; + $log_file{\@common_log_list} = "%COMMON_DEST%/inc%_EXT%/$module/deliver.log"; + $file_date{\@log_list} = $logfiledate; + $file_date{\@common_log_list} = $commonlogfiledate; + + my @logs = ( \@log_list ); + push @logs, ( \@common_log_list ) if ( $common_build ); + foreach my $log ( @logs ) { + $log_file{$log} = expand_macros( $log_file{$log} ); + if ( $opt_delete ) { + print "LOG: removing $log_file{$log}\n" if $opt_verbose; + next if ( $opt_check ); + unlink $log_file{$log}; + } else { + print "LOG: writing $log_file{$log}\n" if $opt_verbose; + next if ( $opt_check ); + open( LOGFILE, "> $log_file{$log}" ) or warn "Error: could not open log file."; + foreach my $item ( @$log ) { + print LOGFILE "@$item\n"; + } + close( LOGFILE ); + utime($file_date{$log}, $file_date{$log}, $log_file{$log}); + } + push_on_ziplist( $log_file{$log} ) if $opt_zip; + } + return; +} + +sub check_dlst +{ + my %createddir; + my %destdir; + my %destfile; + # get all checkable actions to perform + foreach my $action ( @action_data ) { + my $path = expand_macros( $$action[1] ); + if ( $$action[0] eq 'mkdir' ) { + $createddir{$path} ++; + } elsif (( $$action[0] eq 'copy' ) || ( $$action[0] eq 'addincpath' )) { + my ($from, $to) = split(' ', $path); + my ($to_fname, $to_dir); + my $withwildcard = 0; + if ( $from =~ /[\*\?\[\]]/ ) { + $withwildcard = 1; + } + ($to_fname, $to_dir) = fileparse($to); + if ( $withwildcard ) { + if ( $to !~ /[\*\?\[\]]/ ) { + $to_dir = $to; + $to_fname =''; + } + } + $to_dir =~ s/[\\\/\s]$//; + $destdir{$to_dir} ++; + # Check: copy into non existing directory? + if ( ! $createddir{$to_dir} ) { + # unfortunately it is not so easy: it's OK if a subdirectory of $to_dir + # gets created, because mkpath creates the whole tree + foreach my $directory ( keys %createddir ) { + if ( $directory =~ /^\Q$to_dir\E[\\\/]/ ) { + $createddir{$to_dir} ++; + last; + } + } + print_warning("Possibly copying into directory without creating in before: '$to_dir'") + unless $createddir{$to_dir}; + } + # Check: overwrite file? + if ( ! $to ) { + if ( $destfile{$to} ) { + print_warning("Multiple entries copying to '$to'"); + } + $destfile{$to} ++; + } + } + } +} + +sub cleanup +{ + # remove empty directories + foreach my $path ( @dirlist ) { + $path = expand_macros($path); + if ( $opt_check ) { + print "RMDIR: $path\n" if $opt_verbose; + } else { + rmdir $path; + } + } +} + +sub delete_output +{ + my $output_path = expand_macros("../%__SRC%"); + if ( "$output_path" ne "../" ) { + if ( rmtree([$output_path], 0, 1) ) { + print "Deleted output tree.\n" if $opt_verbose; + } + else { + print_error("Error deleting output tree $output_path: $!",0); + } + } + else { + print_error("Output not deleted - INPATH is not set"); + } +} + +sub print_warning +{ + my $message = shift; + my $line = shift; + + print STDERR "$script_name: "; + if ( $dlst_file ) { + print STDERR "$dlst_file: "; + } + if ( $line ) { + print STDERR "line $line: "; + } + print STDERR "WARNING: $message\n"; +} + +sub print_error +{ + my $message = shift; + my $line = shift; + + print STDERR "$script_name: "; + if ( $dlst_file ) { + print STDERR "$dlst_file: "; + } + if ( $line ) { + print STDERR "line $line: "; + } + print STDERR "ERROR: $message\n"; + $error ++; +} + +sub print_stats +{ + print "Module '$module' delivered "; + if ( $error ) { + print "with errors\n"; + } else { + print "successfully."; + if ( $opt_delete ) { + print " $files_copied files removed,"; + } + else { + print " $files_copied files copied,"; + } + print " $files_unchanged files unchanged\n"; + } +} + +sub cleanup_and_die +{ + # clean up on unexpected termination + my $sig = shift; + if ( defined($temp_file) && -e $temp_file ) { + unlink($temp_file); + } + if ( defined($work_file) && -e $work_file ) { + unlink($work_file); + print STDERR "$work_file removed\n"; + } + + die "caught unexpected signal $sig, terminating ..."; +} + +sub usage +{ + my $exit_code = shift; + print STDERR "Usage:\ndeliver [OPTION]... [DESTINATION-PATH]\n"; + print STDERR "Options:\n"; + print STDERR " -check just print what would happen, no actual copying of files\n"; + print STDERR " -checkdlst be verbose about (possible) d.lst bugs\n"; + print STDERR " -delete delete files (undeliver), use with care\n"; + print STDERR " -deloutput remove the output tree after copying\n"; + print STDERR " -force copy even if not newer\n"; + print STDERR " -dontdeletecommon do not delete common files (for -delete option)\n"; + print STDERR " -help print this message\n"; + if ( !defined($ENV{GUI}) || $ENV{GUI} ne 'WNT' ) { + print STDERR " -link hard link files into the solver to save disk space\n"; + } + print STDERR " -minor deliver into minor (milestone)\n"; + print STDERR " -quiet be quiet, only report errors\n"; + print STDERR " -verbose be verbose\n"; + print STDERR " -zip additionally create zip files of delivered content\n"; + print STDERR "Option '-zip' and a destination-path are mutually exclusive.\n"; + print STDERR "Options '-check' and '-quiet' are mutually exclusive.\n"; + exit($exit_code); +} + +# vim: set ts=4 shiftwidth=4 expandtab syntax=perl: diff --git a/solenv/bin/diffmv.pl b/solenv/bin/diffmv.pl new file mode 100755 index 000000000000..3bd1065b9569 --- /dev/null +++ b/solenv/bin/diffmv.pl @@ -0,0 +1,80 @@ +: + eval 'exec perl -S $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: diffmv.pl,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +my ( $srcfile, $destfile ) = @ARGV; +my ( @srclines, @destlines ); +my $dest_existing = 0; +@destlines = (); + +usage() if ( ! defined $srcfile || ! defined $destfile); + +open(SRCFILE, "$srcfile") or die "ERROR: Can't open $srcfile\n"; +@srclines = <SRCFILE>; +close SRCFILE; + +if ( -f $destfile ) { + open(DESTFILE, "$destfile") or die "ERROR: Can't open $destfile\n"; + @destlines = <DESTFILE>; + close DESTFILE; + $dest_existing = 1; +} + +if ( ! check_if_lists_equal(\@srclines, \@destlines) ) { + print STDERR "Updating \"$destfile\".\n"; + unlink "$destfile" or die "ERROR: Can't remove old $destfile\n" if ( $dest_existing ); + rename "$srcfile", "$destfile" or die "ERROR: Can't rename $srcfile to $destfile\n"; +} else { + print STDERR "\"$destfile\" unchanged.\n"; +} + +sub check_if_lists_equal +{ + my ( $srclist_ref, $destlist_ref ) = @_; + my @srclist = @{ $srclist_ref }; + my @destlist = @{ $destlist_ref }; + return 0 if ( $#srclist != $#destlist ); + for ( my $i = 0; $i < $#srclist; $i++ ) { + return 0 if ( $srclist[$i] ne $destlist[$i]); + } + return 1; +} + +sub usage +{ + print STDERR "Usage: diffmv sourcefile destfile\n"; + print STDERR "Do move diffing file only\n"; + exit 1; +} + diff --git a/solenv/bin/exectest.pl b/solenv/bin/exectest.pl new file mode 100644 index 000000000000..552935eb5b6b --- /dev/null +++ b/solenv/bin/exectest.pl @@ -0,0 +1,102 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: exectest.pl,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +$#ARGV >= 1 + or die "Usage: $0 <input file>|-SUCCESS|-FAILURE <command> <arguments...>"; +if ($ARGV[0] eq "-SUCCESS") +{ + $expect = "SUCCESS"; + $input = 0; +} +elsif ($ARGV[0] eq "-FAILURE") +{ + $expect = "FAILURE"; + $input = 0; +} +else +{ + open INPUT, $ARGV[0] or die "cannot open $ARGV[0]: $!"; + $input = 1; +} +shift @ARGV; +$failed = 0; +$open = 0; +while (1) { + $eof = $input ? eof INPUT : $open; + $in = <INPUT> if $input && !$eof; + if (!$input || $eof + || $in =~ /^EXPECT (SUCCESS|FAILURE|\d+)( "([^"]*)")?:\n$/) + { + if ($open) + { + close PIPE; + if ($? % 256 == 0) + { + $exit = $? / 256; + $ok = $expect eq "SUCCESS" ? $exit == 0 + : $expect eq "FAILURE" ? $exit != 0 : $exit == $expect; + } + else + { + $exit = "signal"; + $ok = 0; + } + print "\"$title\", " if defined $title; + print "expected $expect, got $exit ($?): "; + if ($ok) + { + print "ok\n"; + } + else + { + print "FAILED!\n"; + $failed = 1; + } + } + last if $eof; + $expect = $1 if $input; + if (defined $3) + { + $title = $3; + } + else + { + undef $title; + } + open PIPE, "| @ARGV" or die "cannot start process: $!"; + $open = 1; + } + elsif ($open && $input) + { + print PIPE $in or die "cannot write to pipe: $!"; + } +} +exit $failed; diff --git a/solenv/bin/fix_def_file.cmd b/solenv/bin/fix_def_file.cmd new file mode 100644 index 000000000000..4db97f8ce435 --- /dev/null +++ b/solenv/bin/fix_def_file.cmd @@ -0,0 +1,52 @@ +/* os2 build scripts
+
+this script is used to process def results
+
+*/
+
+lmax = 0
+smax = ''
+ordinal = 1
+
+do while( lines())
+
+ l = strip(linein())
+ l = strip(l,,X2C(9))
+ l = strip(l,,";")
+ if LEFT( l,4) \= 'Java' THEN l = '_'l
+
+ /* remove comments */
+ if POS(';', l) > 0 then l = LEFT( l, POS(';', l)-1)
+ if POS('#', l) > 0 then l = LEFT( l, POS('#', l)-1)
+ /* remove wildcards */
+ if POS('*', l) > 0 then l = ''
+
+ /* remove empty lines */
+ if l = '_' then l = ''
+
+ /* remove component_getDescriptionFunc, since it is already added by tg_def */
+ if l = '_component_getDescriptionFunc' then l = ''
+ if l = '_GetVersionInfo' then l = ''
+
+ /* remove GLOBAL symbols */
+/*
+ if POS('_GLOBAL_', l) > 0 then l = ';'l
+ if POS('_ZN4_STL', l) > 0 then l = ';'l
+ if POS('_ZNK4_STL', l) > 0 then l = ';'l
+*/
+ /* if LENGTH(l) > 254 then l = ';(>254)'left(l,100)*/
+
+ IF LENGTH(l)>0 THEN DO
+ say l
+ ordinal = ordinal + 1
+ END
+
+ if LENGTH(l)>lmax then do
+ lmax = LENGTH(l)
+ smax = l
+ end
+
+end
+
+say ';lmax='lmax
+say ';smax='smax
diff --git a/solenv/bin/fix_def_ord.cmd b/solenv/bin/fix_def_ord.cmd new file mode 100644 index 000000000000..eaeb666626db --- /dev/null +++ b/solenv/bin/fix_def_ord.cmd @@ -0,0 +1,19 @@ +/* os2 build scripts
+
+this script is used to process def results.
+Adds ordinal number to every line.
+
+*/
+
+lmax = 0
+smax = ''
+
+ord = 1
+do while( lines())
+
+ l = linein()
+ IF LENGTH(l)>0 THEN DO
+ say l /* ' @'ord ' RESIDENTNAME' */
+ ord = ord + 1
+ END
+end
diff --git a/solenv/bin/fix_dxp_file.cmd b/solenv/bin/fix_dxp_file.cmd new file mode 100644 index 000000000000..66149c1207ea --- /dev/null +++ b/solenv/bin/fix_dxp_file.cmd @@ -0,0 +1,30 @@ +/* os2 build scripts
+
+this script is used to process dxp files produced from .map
+
+*/
+
+do while( lines())
+
+ l = linein()
+
+ l = strip(l)
+ l = strip(l,,X2C(9))
+ l = strip(l,,";")
+ if LEFT( l,4) \= 'Java' THEN l = '_'l
+
+ /* remove empty lines */
+ if l = '_' then l = ''
+
+ /* remove component_getDescriptionFunc, since it is already added by tg_def */
+ if l = '_component_getDescriptionFunc' then l = ''
+ if l = '_GetVersionInfo' then l = ''
+
+ /* remove GLOBAL symbols */
+/*
+ if WORDPOS( l, '_GLOBAL_') > 0 then l = ''
+*/
+
+ say l
+
+end
diff --git a/solenv/bin/fix_exp_file.cmd b/solenv/bin/fix_exp_file.cmd new file mode 100644 index 000000000000..bec416c06e05 --- /dev/null +++ b/solenv/bin/fix_exp_file.cmd @@ -0,0 +1,54 @@ +/* os2 build scripts
+
+this script is used to process emxexp results
+
+*/
+
+lmax = 0
+ordinal = 1
+
+do while( lines())
+
+ l = strip(linein())
+ if POS(';', l) > 0 then l = LEFT(l,POS(';', l)-1)
+
+ l = strip(translate(l,'','"'))
+ l = strip(l,,X2C(9))
+
+ /* remove empty lines */
+ if l = '_' then l = ''
+
+ /* remove component_getDescriptionFunc, since it is already added by tg_def */
+ if l = '_component_getDescriptionFunc' then l = ''
+ if l = '_GetVersionInfo' then l = ''
+
+
+ /* remove GLOBAL symbols */
+ if POS('_GLOBAL_', l) > 0 then l = ';'l
+/*
+ if POS('!', l) > 0 then l = ';'l
+ if POS('_ZN4_STL', l) > 0 then l = ';'l
+ if POS('_ZNK4_STL', l) > 0 then l = ';'l
+ if POS('ImplClass', l) > 0 then l = ';'l
+ if POS('ImplHelper', l) > 0 then l = ';'l
+ if POS('UsageHelper', l) > 0 then l = ';'l
+ if POS('com3sun4star3', l) > 0 then l = ';'l
+*/
+ /* if LENGTH(l) > 254 then l = ';(>254)'left(l,100) */
+
+ if POS(';', l) > 0 then l = LEFT(l,POS(';', l)-1)
+
+ IF LENGTH(l)>0 THEN DO
+ say l
+ ordinal = ordinal + 1
+ END
+
+ if LENGTH(l)>lmax then do
+ lmax = LENGTH(l)
+ smax = l
+ end
+
+end
+
+say ';lmax='lmax
+say ';smax='smax
diff --git a/solenv/bin/fix_lin_file.cmd b/solenv/bin/fix_lin_file.cmd new file mode 100644 index 000000000000..0d074ce9f706 --- /dev/null +++ b/solenv/bin/fix_lin_file.cmd @@ -0,0 +1,13 @@ +/* os2 build scripts
+*/
+
+parse arg dir
+
+do while( lines())
+
+ l = linein()
+
+ /* skip empty lines */
+ if l \= '' then say dir || '\' || l
+
+end
diff --git a/solenv/bin/fix_shl.cmd b/solenv/bin/fix_shl.cmd new file mode 100644 index 000000000000..ca13abb2074e --- /dev/null +++ b/solenv/bin/fix_shl.cmd @@ -0,0 +1,11 @@ +/* os2 build scripts
+
+will return a 8.3 conformant name for modname.
+
+21/02/2006 Actually this is a simple truncation, seems nothing more needed.
+
+*/
+
+parse arg modname
+if pos('.',modname)>0 then modname = left(modname, pos('.',modname)-1)
+say strip(left(modname,8))
diff --git a/solenv/bin/gccinstlib.pl b/solenv/bin/gccinstlib.pl new file mode 100644 index 000000000000..6b2ec3170641 --- /dev/null +++ b/solenv/bin/gccinstlib.pl @@ -0,0 +1,60 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: gccinstlib.pl,v $ +# +# $Revision: 1.8 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +$ENV{'LC_MESSAGES'} = 'C'; + +$Dest = pop(@ARGV) || die "No destination to copy to"; + +$cc = $ENV{'CC'} || die "No CC environment set"; + +if ($Dest =~ /--help/ || @ARGV < 1) { + print "Syntax:\n gcc-instlib <library-in-libpath ...> <destination-dir>\n"; + exit (0); +} +foreach $File (@ARGV) { + my $string; + + open (GCCOut, "LANGUAGE=C LC_ALL=C $cc -print-file-name=$File|") || die "Failed to exec $cc -print-file-name=$File $!"; + $string=<GCCOut>; + chomp ($string); + push (@CopySrc, $string); + close (GCCOut); +} + +foreach $Src (@CopySrc) { + printf "copy $Src to $Dest\n"; + system ("/bin/cp $Src $Dest") && die "copy failed: $!"; +} + +exit (0); diff --git a/solenv/bin/gen_update_info.pl b/solenv/bin/gen_update_info.pl new file mode 100644 index 000000000000..fe543cf75405 --- /dev/null +++ b/solenv/bin/gen_update_info.pl @@ -0,0 +1,152 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; + +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: gen_update_info.pl,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +#********************************************************************* +# +# main +# + +my($product, $buildid, $id, $os, $arch, $lstfile, $languages, $productname, $productversion, $productedition); + +while ($_ = $ARGV[0], /^-/) { + shift; + last if /^--$/; + if (/^--product/) { + $product= $ARGV[0]; + shift; + } + if (/^--buildid/) { + $buildid = $ARGV[0]; + shift; + } + if (/^--os/) { + $os = $ARGV[0]; + shift; + } + if (/^--arch/) { + $arch = $ARGV[0]; + shift; + } + if (/^--lstfile/) { + $lstfile = $ARGV[0]; + shift; + } + if (/^--languages/) { + $languages = $ARGV[0]; + shift; + } +} + +$sourcefile = $ARGV[0]; + +if( $^O =~ /cygwin/i ) { + # We might get paths with backslashes, fix that. + $lstfile =~ s/\\/\//g; + $sourcefile =~ s/\\/\//g; +} + +# read openoffice.lst +### may be hierarchical ... +if(open(LSTFILE, "sed -n \"/^$product:/,/^}\$/ p\" $lstfile |")) { + while (<LSTFILE>) { + if ( /^$product\s?:\s?(\w+)$/ ) { + $product = $1; + } + if( /\bPRODUCTEDITION / ) { + chomp; + s/.*PRODUCTEDITION //; + $productedition = $_; + } + } +} +close(LSTFILE); + +unless(open(LSTFILE, "sed -n \"/^$product\$/,/^}\$/ p\" $lstfile |")) { + print STDERR "Can't open $lstfile file: $!\n"; + return; +} + +while (<LSTFILE>) { + if( /\bPRODUCTNAME / ) { + chomp; + s/.*PRODUCTNAME //; + $productname = $_; + } + if( /\bPRODUCTVERSION / ) { + chomp; + s/.*PRODUCTVERSION //; + $productversion = $_; + } + if( /\bPRODUCTEDITION / ) { + chomp; + s/.*PRODUCTEDITION //; + $productedition = $_; + } +} + +close(LSTFILE); + +# simulate the behavior of make_installer.pl when writing versionrc +unless( "$os" eq "Windows" ) { + $languages =~ s/_.*//; +} + +$id = $productversion; +$id =~ s/\..*//; +$id = $productname . "_" . $id . "_" . $languages; + +# open input file +unless (open(SOURCE, $sourcefile)) { + print STDERR "Can't open $sourcefile file: $!\n"; + return; +} + +while (<SOURCE>) { + s/:id></:id>$id</; + s/buildid></buildid>$buildid</; + s/os></os>$os</; + s/arch></arch>$arch</; + if ( $productedition ) { + s/edition></edition>$productedition</; + } else { + next if ( /edition></ ); + } + s/version></version>$productversion</; + s/name></name>$productname</; + print; +} + +close(SOURCE); diff --git a/solenv/bin/gen_userfeedback_VCL_names.pl b/solenv/bin/gen_userfeedback_VCL_names.pl new file mode 100755 index 000000000000..2e5ed3cf2588 --- /dev/null +++ b/solenv/bin/gen_userfeedback_VCL_names.pl @@ -0,0 +1,200 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: ,v $ +# +# $Revision: $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +# +# pushids - push HID.LST and *.win files for userexperience feedback +# + +use lib ("$ENV{SOLARENV}/bin/modules", "$ENV{COMMON_ENV_TOOLS}/modules"); + +use Carp; + +sub parse_info($$); + +if ( @ARGV != 3 ) +{ + print "usage: $ARGV[0] <path tp hid.lst> <path to *.win files> <output file>\n"; + print "example: $ARGV[0] ./hid.lst global/win common/misc/UserFeedbackNames.csv\n\n"; + die "invalid params"; +} + +my ($hid, $winpath, $outfile) = @ARGV; + +my @names; + +open HID, "<$hid" or die "can't open file $filename $! $^E"; +for (<HID>) { + chop; + my ($longname, $ID) = split " +"; + next if ( ! $ID ); + $upperlongname = $longname; + $upperlongname =~ tr/a-z/A-Z/; + $undeclared_hids{$upperlongname} = $longname; + + if ( exists $hids{$upperlongname} && ( $hids{$upperlongname} != $ID ) ) + { + print STDERR "errror: unclear definition of longname: $longname = $hids{$upperlongname} or $ID\n"; + } + $hids{$upperlongname} = $ID; + + if ( exists $revhids{ $ID } && ( $revhids{ $ID } ne $upperlongname ) ) + { + print STDERR "warn: two longnames have the same ID: $longname and $revhids{$ID} share ID $ID\n"; + } + $revhids{$ID} = $upperlongname; +} + +close HID; + +undef @revhids; + +#Add Active +$hids{"ACTIVE"} = 0; + +my %dialogs = (); + +foreach ( glob("$winpath/*win") ) { + $filename = $_; + open WIN, "< $filename" or die "can't open file $filename $! $^E"; + my $parentinfo = ""; + my @dialog = (); + my $parentshortname = ""; + + for ( <WIN> ) { + chop; + + s/^ +//; + s/ +/ /g; + + next if /^ *'/; + next if /^ *$/; + + my $ID = ""; + my $iteminfo; + my ($shortname, $longname) = split " +"; + + $shortname = "" if ( !$shortname ); + $longname = "" if ( !$longname ); + + # fake a correct entry if only *active is given and overwrite the attempt to declare it differently + if ( $shortname =~ /\*active/i ) + { + $longname = "Active"; + } + + +# find UNO Names + if ( $longname =~ /^(.uno:|http|private:factory|service:|macro:|.HelpId:)/i || $longname =~ s/^sym://i ) + { + $ID = $longname; + $longname = ""; + } + else + { + my $upperlongname = $longname; + $upperlongname =~ tr/a-z/A-Z/; + if ( $shortname !~ /^[\+\*]/ && !exists $hids{$upperlongname} ) + { + print STDERR "errror: Longname not in hid.lst: $filename $longname\n"; + } + if ( exists $hids{$upperlongname} ) + { + $ID = $hids{$upperlongname}; + } + delete $undeclared_hids{$upperlongname}; + } + + $iteminfo = "$shortname $longname $ID"; +# print "$iteminfo\n" if ( ! ( $shortname && $longname && $ID )); + $iteminfo =~ s/^\*//; + $iteminfo =~ s/^\+//; + +# find start of deklaration + if ( $shortname =~ s/^\+// ) + { + # copy existing dialog + if ( exists $dialogs{ $longname } ) + { + my @old = @{$dialogs{ $longname }}; + my ($oldshort, $oldlong, $oldID ) = split ( " ", shift @old ); + $iteminfo = "$shortname $oldlong $oldID"; + + $parentinfo = $iteminfo; + $parentshortname = $shortname; + $dialogs{ $parentshortname } = \@dialog; + @dialog = (); # break the link + push ( @{$dialogs{ $parentshortname }}, $iteminfo ); + push @names, " $parentinfo"; + + for ( @old ) + { + push @names, "$parentinfo $_"; + } + } + else + { # fake new dialog instead + $shortname = "*".$shortname; + } + } + if ( $shortname =~ s/^\*// ) + { + $parentinfo = $iteminfo; + $parentshortname = $shortname; + $dialogs{ $parentshortname } = \@dialog; + @dialog = (); # break the link + push ( @{$dialogs{ $parentshortname }}, $iteminfo ); + push @names, " $parentinfo"; + } + else + { + push ( @{$dialogs{ $parentshortname }}, $iteminfo ); + push @names, "$parentinfo $iteminfo"; + } + + } + close WIN; +} + +for ( keys %undeclared_hids ) { + $iteminfo = "$undeclared_hids{$_} $undeclared_hids{$_} $hids{$_}"; + push @names, " $iteminfo"; +} + +#---------------------------------------------------------------------------- +# write to files + +open HIDS, ">$outfile" or die "can't open file $filename $! $^E"; +print HIDS join "\n", @names; +print HIDS "\n"; +close HIDS; + diff --git a/solenv/bin/genmap b/solenv/bin/genmap new file mode 100755 index 000000000000..78d67bf6f06f --- /dev/null +++ b/solenv/bin/genmap @@ -0,0 +1 @@ +less $2 diff --git a/solenv/bin/getcompver.awk b/solenv/bin/getcompver.awk new file mode 100644 index 000000000000..7b471294180c --- /dev/null +++ b/solenv/bin/getcompver.awk @@ -0,0 +1,83 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: header.hxx,v $ +# +# $Revision: 1.1 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +BEGIN { + CCversion = 0 + compiler_matched = 0 +} +# Sun c++ compiler +/Sun WorkShop/ || /Forte Developer/ || /Sun/{ + compiler_matched = 1 + # version number right after "C++" + x = match( $0, /C\+\+ .*/ ) + btwn = substr( $0, RSTART, RLENGTH) + # extract version, whitespaces get striped later + x = match( btwn, / .*\..*[ $\t]/) + CCversion = substr( btwn, RSTART, RLENGTH) +} +# Microsoft c++ compiler +/Microsoft/ && /..\...\...../ { + compiler_matched = 1 + # match on the format of the ms versions ( dd.dd.dddd ) + x = match( $0, /..\...\...../ ) + CCversion = substr( $0, RSTART, RLENGTH) +} +# Java +/java version/ || /openjdk version/ { + compiler_matched = 1 + # match on the format of the java versions ( d[d].d[d].d[d] ) + x = match( $0, /[0-9]*\.[0-9]*\.[0-9]*/ ) + CCversion = substr( $0, RSTART, RLENGTH) +} +/^[0-9]*[.][0-9]*\x0d*$/ { + if ( compiler_matched == 0 ) { +# need to blow to x.xx.xx for comparing + CCversion = $0 ".0" + } +} +/^[0-9]*[.][0-9]*[.][0-9]*\x0d*$/ { + if ( compiler_matched == 0 ) { + CCversion = $0 + } +} +/^[0-9]*[.][0-9]*[.][0-9]*-[0-9a-z]*$/ { + if ( compiler_matched == 0 ) { + CCversion = substr($0, 0, index($0, "-") - 1) + } +} +END { + if ( num == "true" ) { + tokencount = split (CCversion,vertoken,".") + for ( i = 1 ; i <= tokencount ; i++ ) { + printf ("%04d",vertoken[i] ) + } + } else + print CCversion +} diff --git a/solenv/bin/getcsym.awk b/solenv/bin/getcsym.awk new file mode 100644 index 000000000000..daa3a81fad60 --- /dev/null +++ b/solenv/bin/getcsym.awk @@ -0,0 +1,38 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: getcsym.awk,v $ +# +# $Revision: 1.6 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +BEGIN { global_found = "false" } +/[ \t]*#/ { sub( substr( $0, index($0, "#")),"" ) } +/[ \t]*local:/ { global_found = "false" } +/[ \t]*}/ { global_found = "false" } +/^[ \t]*$/ { next } +global_found == "true" { print $0 } +/[ \t]*global:/ { global_found = "true" } diff --git a/solenv/bin/guw.pl b/solenv/bin/guw.pl new file mode 100755 index 000000000000..9839a5d637d7 --- /dev/null +++ b/solenv/bin/guw.pl @@ -0,0 +1,351 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: guw.pl,v $ +# +# $Revision: 1.28 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +# Description: ?? + +#--------------------------------------------------------------------------- +# external modules +use Text::ParseWords; + +# global vars +@params = (); + +# set debug mode here: +#$debug="true"; +#$debug_light="true"; + +#--------------------------------------------------------------------------- +# Define known parameter exceptions +%knownpara = ( 'echo', [ '/TEST', 'QQQ', 'CCC', 'uno:' ], + 'cl', [ '-clr:', '-Z' ], + 'csc', [ '-target:' ], + 'lib', [ 'OUT:', 'EXTRACT:','out:', 'def:', 'machine:' ], + 'link', [ 'BASE:', 'DEBUG', 'DLL', 'LIBPATH', 'MACHINE:', + 'MAP', 'NODEFAULTLIB', 'OPT', 'PDB', 'RELEASE', + 'SUBSYSTEM', 'STACK', 'out:', 'map:', 'ENTRY:', + 'implib:', 'delayload:', 'def', 'COMMENT:' ], + 'regcomp', [ '-env:', 'vnd.sun.star.expand:' , 'vnd.openoffice.pymodule' ], + 'regmerge', [ '/UCR' ], + 'rc', [ '-D' ], + 'rsc', [ '-DOOO_' ] ); + +#--------------------------------------------------------------------------- +# procedures + + +#---------------------------------------------------------- +# Function name: myCygpath +# Description: Transform POSIX path to DOS path +# Arguments: 1. Variable (string) with one token +# 2. optional - if set remove spaces and shorten to 8.3 +# representation. +# Return value: Reformatted String +#---------------------------------------------------------- +sub myCygpath { + my $posixpath = shift; + my $shortenpath = shift || ''; + + my $dospath; + + if ( $posixpath =~ / / and $shortenpath ) { + chomp( $dospath = qx{cygpath -d "$posixpath"} ); + # "cygpath -d" returns "" if the file doesn't exist. + if ($dospath eq "") { + $dospath = "."; + print(STDERR "Error: guw.pl: Path: $posixpath:\nhas a problem! Probably nonexistent filename with space.\n"); + if ( (defined $debug_light) or (defined $debug) ) { + die "exiting ...\n"; + } + } + } else { + if ( $posixpath =~ /^\// ) { + chomp( $dospath = qx{cygpath -w "$posixpath"} ); + } else { + $dospath = $posixpath; + $dospath =~ s/\//\\/g; + } + } + return $dospath; +} + +#---------------------------------------------------------- +# Function name: WinFormat +# Description: Format variables to Windows Format. +# Arguments: 1. Variable (string) with one token +# Return value: Reformatted String +#---------------------------------------------------------- +sub WinFormat { + my $variable = shift @_; + my( $d1, $d1_prefix, $d2 ); + + $variable =~ s/(\$\w+)/$1/eeg ; # expand the variables + $variable =~ s/(\$\w+)/$1/eeg ; # expand the variables twice! + + # Include paths or parameters with filenames + if ( $variable =~ /\A(-D[\w\.]*=)[\'\"]?((?:\/?[\w\.\-\+ ~]+)+\/?)[\'\"]?\Z/ ) { + # This regex evaluates -D<something>=<path>, sometimes with quotes or "/" at the end + # option -> $1, filename without quotes -> $2 + if ( defined $debug ) { print(STDERR "WinFormat:\ninclude (-D<something>=<path>) path:\n$variable\n"); } + $d1_prefix = $1; + $d1 = $2; + $d2 = myCygpath($2,1); + if ( $d2 ne "" ) { + $d2 =~ s/\\/\\\\/g ; + } + } elsif ( $variable =~ /\A(-?\w[\w\.]*=)[\'\"]?((?:\/?[\w\.\-\+ ~]+)+\/?)[\'\"]?\Z/ ) { + # This regex evaluates [-]X<something>=<path>, sometimes with quotes or "/" at the end + # option -> $1, filename without quotes -> $2 + if ( defined $debug ) { print(STDERR "WinFormat:\ninclude ([-]<something>=<path>) path:\n$variable\n"); } + $d1_prefix = $1; + $d1 = $2; + $d2 = myCygpath($2,1); + } elsif ( $variable =~ /\A(--\w[\w\.\-]*=)[\'\"]?((?:\/?[\w\.\-\+ ~]+)+\/?)[\'\"]?\Z/ ) { + # This regex evaluates --<something>=<path>, sometimes with quotes or "/" at the end + # option -> $1, filename without quotes -> $2 + if ( defined $debug ) { print(STDERR "WinFormat:\ninclude (--<something>=<path>) path:\n$variable\n"); } + $d1_prefix = $1; + $d1 = $2; + $d2 = myCygpath($2,1); + } elsif ( $variable =~ /\A(-\w[\w\.]*:)[\'\"]?((?:\/?[\w\.\-\+ ~]+)+\/?)[\'\"]?\Z/ ) { + # This regex evaluates -X<something>:<path>, sometimes with quotes or "/" at the end + # option -> $1, filename without quotes -> $2 + if ( defined $debug ) { print(STDERR "WinFormat:\nFound (-<something>:<path>):\n$variable\n"); } + $d1_prefix = $1; + $d1 = $2; + $d2 = myCygpath($2,1); + } elsif ( $variable =~ /\A(-\w+:)(.*)\Z/ ) { + # This regex evaluates -X<something>:<NO-path>, and prevents translating of these. + # option -> $1, rest -> $2 + if ( defined $debug ) { print(STDERR "WinFormat:\nFound (-<something>:<no-path>):\n$variable\n"); } + $d1_prefix = $1; + $d1 = $2; + $d2 = myCygpath($2,1); + } elsif ( $variable =~ /\A(\w+:)[\'\"]?\/\/\/((?:\/?[\w\.\-\+ ~]+)+\/?)[\'\"]?\Z/ ) { + # See iz35982 for the reason for the special treatment of this switch. + # This regex evaluates <something>:///<path>, sometimes with quotes or "/" at the end + # option -> $1, filename without quotes -> $2 + if ( defined $debug ) { print(STDERR "WinFormat:\nFound (<something>:///<path>):\n$variable\n"); } + $d1_prefix = $1."///"; + $d1 = $2; + $d2 = myCygpath($2,1); + $d2 =~ s/\\/\//g ; + } elsif ( $variable =~ /\A(-\w)[\'\"]?((?:\/[\w\.\-\+ ~]+)+\/?)[\'\"]?\Z/ ) { + # This regex evaluates -X<path>, sometimes with quotes or "/" at the end + # option -> $1, filename without quotes -> $2 + if ( defined $debug ) { print(STDERR "WinFormat:\ninclude (-X<absolute path>) path:\n$variable\n"); } + $d1_prefix = $1; + $d1 = $2; + $d2 = myCygpath($2,1); + } elsif ( $variable =~ /\A(-F[ARdemopr])[\'\"]?((?:\/[\w\.\-\+ ~]+)+\/?)[\'\"]?\Z/ ) { + # This regex evaluates -FX<path> (MSVC switches for output naming), sometimes with quotes or "/" at the end + # option -> $1, filename without quotes -> $2 + if ( defined $debug ) { print(STDERR "WinFormat:\ncompiler naming (-FX<absolute path>) path:\n$variable\n"); } + $d1_prefix = $1; + $d1 = $2; + $d2 = myCygpath($2,1); + } else { + $d2 = ""; + } + if ( $d2 ne "" ) { + # Found a parameter + $d1 =~ s/\+/\\\+/ ; + $d1 =~ s/\./\\\./ ; + $variable =~ s/$d1/$d2/ ; + } else { + # Found no parameter, assume a path + $variable =~ s/:/;/g; + $variable =~ s/([;]|\A)(\w);/$1$2:/g; # get back the drives + + # Search for posix path ;entry; (The regex accepts valid paths with at least one /) + # and replace with DOS path, accept quotes. + # iz28717 Accept ',' as path seperator. + while ( $variable =~ /(?:[;,]|\A)[\'\"]?([\w\.\-\+ ~]*(?:\/[\w\.\-\+ ~]+)+\/?)[\'\"]?(?:[;,]|\Z)/ ) { + # Normal paths + $d1 = $1; + $d2 = myCygpath($d1); + if ( defined $debug ) { + print(STDERR "WinFormat:\nFull path:\n$variable\nTranslated part:$d2\n"); + } + $d1 =~ s/\+/\\\+/ ; + $variable =~ s/$d1/$d2/ ; + } + } + + # Sanity check for -X<path> + if ( $variable =~ /-\w[\'\"]?(?:(?:\/[\w\.\-\+ ~]+)+)/ ) { + print(STDERR "Error: guw.pl: WinFormat: Not converted -X/... type switch in :$variable:.\n"); + if ( (defined $debug_light) or (defined $debug) ) { die "\nNot processed -X/...\n"; } + } + # Sanity check for [-]X<something>(:|=)<path> case + if ( $variable =~ /\A-?\w[\w\.]*[=:][\'\"]?(?:\/[\w\.\-\+ ~]+)+/ ) { + print(STDERR "Error: guw.pl: WinFormat: Not converted [-]X<something>(=|:)/<path> type switch in :$variable:.\n"); + if ( (defined $debug_light) or (defined $debug) ) { die "\nNot processed [-]X<something>(=|:)/...\n"; } + } + + if ( defined $debug ) { print(STDERR "WinFormat:\nresult:$variable\n");}; + return $variable; +} + +#---------------------------------------------------------- +# Function name: replace_cyg +# Description: Process all arguments and change them to Windows Format. +# Arguments: Reference to array with arguments +# Return value: - +#---------------------------------------------------------- +sub replace_cyg { + my $args = shift; + my( @cmd_file, @cmd_temp ); + my $atchars; + foreach my $para ( @$args ) + { + if ( $para =~ "^@" ) { + # it's a command file + if ( defined $debug ) { print(STDERR "----------------------------\n");}; + # Workaround, iz28717, keep number of @'s. + $para =~ s/(^\@+)//; + $atchars = $1; + $filename = $para; + if ( defined $debug ) { print(STDERR "filename = $filename \n");}; + # open this command file for reading + open(CMD, "$filename"); + while ( <CMD> ) { + # Remove DOS lineendings. Bug in Cygwin / Perl? + $_ =~ s/\r//g; + # Remove lineendings and trailing spaces. ( Needed by &parse_line ) + $_ =~ s/\n$//g; + $_ =~ s/\s+$//g; + # Fill all tokens into array + @cmd_temp = &parse_line('\s+', 1, $_ ); + if ( $#cmd_temp > -1 ) { + push( @cmd_file, @cmd_temp); + } + } + close(CMD); + # reformat all tokens + replace_cyg(\@cmd_file); + if ( defined $debug ) { print(STDERR "Tokens processed:\n");}; + foreach $i (@cmd_file) { + if ( defined $debug ) { print(STDERR "!".$i."!\n");}; + } + # open this filename for writing (truncate) Textmode? + open(CMD, '>', $filename); + # write all tokens back into this file + print(CMD join(' ', @cmd_file)); + close(CMD); + # convert '@filename' to dos style + $para = WinFormat( $para ); + if ( defined $debug ) { print(STDERR "----------------------------\n");}; + if ( (defined $debug_light) or (defined $debug) ) { print(STDERR "\nParameter in File:".join(' ', @cmd_file).":\n");} + $para = $atchars.$para; + } else { + # it's just a parameter + if ( defined $debug ) { print(STDERR "\nParameter:---${para}---\n");}; + # If $tmp1 is empty then $para is a parameter. + my $is_no_para = 1; + # remove .exe and convert to lower case + $shortcommand = lc $command ; + $shortcommand =~ s/\.exe$//; + $shortcommand =~ /([^\/]+$)/; + $shortcommand = $1; + foreach $i (@{$knownpara{$shortcommand}}) { + if( $para =~ /$i/ ) { + $is_no_para = 0; + if ( defined $debug ) { print(STDERR "Is parameter exception for ${shortcommand}: ${para}:\n" );}; + last; + } + } + if( $is_no_para ) { + $para = WinFormat($para); + } + if ( defined $debug ) { print(STDERR "Converted line:${para}:\n" );}; + } # else + } # foreach loop +} + +#---------------------------------------------------------- +# Function name: replace_cyg_env +# Description: Process selected environment variables and change +# them to Windows Format. +# Arguments: - +# Return value: - +#---------------------------------------------------------- +sub replace_cyg_env { + @affected_vars = ( + 'SOLAR_VERSION', + 'SOLARVERSION', + 'SOLARVER', + 'SRC_ROOT', + 'LOCALINI', + 'GLOBALINI', + 'SOLARENV', + 'STAR_INSTPATH', + 'STAR_SOLARPATH', + 'STAR_PACKMISC', + 'STAR_SOLARENVPATH', + 'STAR_INITROOT', + 'STAR_STANDLST', + 'CLASSPATH', + 'JAVA_HOME' + ); + foreach my $one_var ( @affected_vars ) + { + my $this_var = $ENV{ $one_var }; + if ( defined $this_var ) + { + if ( defined $debug ) { print(STDERR "ENV $one_var before: ".$ENV{ $one_var}."\n" );}; + $ENV{ $one_var } = WinFormat( $this_var ); + if ( defined $debug ) { print(STDERR "ENV $one_var after : ".$ENV{ $one_var}."\n" );}; + } + } + +} +#--------------------------------------------------------------------------- +# main +@params = @ARGV; + +$command = shift(@params); +while ( $command =~ /^-/ ) +{ + if ( $command eq "-env" ) + { + replace_cyg_env; + } + + $command = shift(@params); +} +if ( (defined $debug_light) or (defined $debug) ) { print( STDERR "Command: $command\n" ); } + +replace_cyg(\@params); +if ( (defined $debug_light) or (defined $debug) ) { print(STDERR "\n---------------------\nExecute: $command @params\n----------------\n");}; +exec( "$command", @params) or die( "\nError: guw.pl: executing $command failed!\n" ); + diff --git a/solenv/bin/hicontrast-to-theme.pl b/solenv/bin/hicontrast-to-theme.pl new file mode 100644 index 000000000000..531762889914 --- /dev/null +++ b/solenv/bin/hicontrast-to-theme.pl @@ -0,0 +1,129 @@ +: + eval 'exec perl -S $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: hicontrast-to-theme.pl,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +# +# Create ordinary theme from HiContrast images. +# + +use File::Copy; +use File::Find; +use File::Path; +use File::Spec; + +( $src, $dst ) = @ARGV; + +if ( $src eq "" || $dst eq "" ) { + print STDERR "Usage: hicontrast-to-theme.pl src dest\n\n"; + print STDERR "Create ordinary theme from HiContrast images.\n"; + exit 1; +} + +$dst = File::Spec->rel2abs( $dst ); + +@hc_table = ( + [ ".*_h.png", "_h.png", ".png" ], + [ ".*_sch.png", "_sch.png", ".png" ], + [ ".*_hc.png", "_hc.png", ".png" ], + [ "lch_.*.png", "lch_", "lc_" ], + [ "sch_.*.png", "sch_", "sc_" ], + [ "lch[0-9].*.png", "lch", "lc" ], + [ "sch[0-9].*.png", "sch", "sc" ], + [ "loh[0-9].*.png", "loh", "lo" ], + [ "lxh[0-9].*.png", "lxh", "lx" ], + [ "sxh[0-9].*.png", "sxh", "sx" ], + [ "avh[0-9].*.png", "avh", "av" ], + [ "avlh[0-9].*.png", "avlh", "avl" ], + [ "idh[0-9].*.png", "idh", "id" ], + [ "imh[0-9].*.png", "imh", "im" ], + [ "mih[0-9].*.png", "mih", "mi" ], + [ "tbh[0-9].*.png", "tbh", "tb" ], + [ "nah[0-9].*.png", "nah", "na" ], + [ "nch[0-9].*.png", "nch", "nc" ], + [ "nvh[0-9].*.png", "nvh", "nv" ], + [ "ouh[0-9].*.png", "ouh", "ou" ], + [ "ddh[0-9].*.png", "ddh", "dd" ], + [ "sfh[0-9].*.png", "sfh", "sf" ], + [ "srh[0-9].*.png", "srh", "sr" ], + [ "wrh[0-9].*.png", "wrh", "wr" ], + [ "alh[0-9].*.png", "alh", "al" ], + [ "ath[0-9].*.png", "ath", "at" ], + [ "bih[0-9].*.png", "bih", "bi" ], + [ "coh[0-9].*.png", "coh", "co" ], + [ "foh[0-9].*.png", "foh", "fo" ], + [ "fuh[0-9].*.png", "fuh", "fu" ], + [ "oph[0-9].*.png", "oph", "op" ], + [ "unh[0-9].*.png", "unh", "un" ], + [ "edh[0-9].*.png", "edh", "ed" ], + [ "cdh[0-9].*.png", "cdh", "cd" ], + [ "frh[0-9].*.png", "frh", "fr" ], + [ "fwh[0-9].*.png", "fwh", "fw" ], + [ "nuh[0-9].*.png", "nuh", "nu" ], + [ "prh[0-9].*.png", "prh", "pr" ], + [ "shh[0-9].*.png", "shh", "sh" ], + [ "trh[0-9].*.png", "trh", "tr" ], + [ "reh[0-9].*.png", "reh", "re" ], + [ "joh[0-9].*.png", "joh", "jo" ], + [ "fph[0-9].*.png", "fph", "fp" ], + [ "dah[0-9].*.png", "dah", "da" ] +); + +my (@from_stat, @to_stat); + +sub copy_normalized { + $file = $_; + for $hc ( @hc_table ) { + ( $what, $from, $to ) = @$hc; + if ( $file =~ /$what/&&!($file=~/\.svn/) ) { + my $dir = File::Spec->catdir( $dst, $File::Find::dir ); + + if ( ! -d $dir ) { + mkpath( $dir ); + } + + ( my $copy = $file ) =~ s/$from/$to/; + $copy = File::Spec->catfile( $dir, $copy ); + + @from_stat = stat($file); + @to_stat = stat($copy); + if ( $from_stat[9] > $to_stat[9] ) { + copy( $file, $copy ) || die $!; + utime( $from_stat[9], $from_stat[9], $copy ); + } + + last; + } + } +} + +chdir( $src ); +find( \©_normalized, '.' ); diff --git a/solenv/bin/image-sort.pl b/solenv/bin/image-sort.pl new file mode 100755 index 000000000000..16c792608c66 --- /dev/null +++ b/solenv/bin/image-sort.pl @@ -0,0 +1,149 @@ +#!/usr/bin/perl -w + +my @global_list = (); +my %global_hash = (); +my $base_path; + +sub read_icons($) +{ + my $fname = shift; + my $fileh; + my @images; + open ($fileh, "$base_path/$fname") || die "Can't open $base_path/$fname: $!"; + while (<$fileh>) { + m/xlink:href=\"\.uno:(\S+)\"\s+/ || next; + push @images, lc($1); + } + close ($fileh); + + return @images; +} + +# filter out already seen icons & do prefixing +sub read_new_icons($$) +{ + my $fname = shift; + my $prefix = shift; + my @images = read_icons ($fname); + my @new_icons; + my %new_icons; + for my $icon (@images) { + my $iname = "res/commandimagelist/" . $prefix . $icon . ".png"; + if (!defined $global_hash{$iname} && + !defined $new_icons{$iname}) { + push @new_icons, $iname; + $new_icons{$iname} = 1; + } + } + return @new_icons; +} + +sub process_group($@) +{ + my $prefix = shift; + my @uiconfigs = @_; + my %group; + my $cur_max = 1.0; + +# a very noddy sorting algorithm + for my $uiconfig (@uiconfigs) { + my @images = read_new_icons ($uiconfig, $prefix); + my $prev = ''; + for my $icon (@images) { + if (!defined $group{$icon}) { + if (!defined $group{$prev}) { + $group{$icon} = $cur_max; + $cur_max += 1.0; + } else { + $group{$icon} = $group{$prev} + (1.0 - 0.5 / $cur_max); + } + } # else a duplicate + } + } + for my $icon (sort { $group{$a} <=> $group{$b} } keys %group) { + push @global_list, $icon; + $global_hash{$icon} = 1; + } +} + +sub process_file($$) +{ + my @images = read_new_icons (shift, shift); + + for my $icon (@images) { + push @global_list, $icon; + $global_hash{$icon} = 1; + } +} + +sub chew_controlfile($) +{ + my $fname = shift; + my $fileh; + my @list; + open ($fileh, $fname) || die "Can't open $fname: $!"; + while (<$fileh>) { + /^\#/ && next; + s/[\r\n]*$//; + /^\s*$/ && next; + + my $line = $_; + if ($line =~ s/^-- (\S+)\s*//) { + # control code + my $code = $1; + my $small = (lc ($line) eq 'small'); + if (lc($code) eq 'group') { + if (!$small) { process_group ("lc_", @list); } + process_group ("sc_", @list); + } elsif (lc ($code) eq 'ordered') { + if (!$small) { + for my $file (@list) { process_file ($file, "lc_"); } + } + for my $file (@list) { process_file ($file, "sc_"); } + } elsif (lc ($code) eq 'literal') { + for my $file (@list) { + if (!defined $global_hash{$file}) { + push @global_list, $file; + $global_hash{$file} = 1; + } + } + } else { + die ("Unknown code '$code'"); + } + @list = (); + } else { + push @list, $line; + } + } + close ($fileh); +} + +if (!@ARGV) { + print "image-sort <image-sort.lst> /path/to/OOOo/source/root\n"; + exit 1; +} + +# where the control file lives +my $control = shift @ARGV; +# where the uiconfigs live +$base_path = shift @ARGV; +# output +if (@ARGV) { + my $outf = shift @ARGV; + open ($output, ">$outf") || die "Can't open $outf: $!"; + $stdout_out = 0; +} else { + $output = STDOUT; + $stdout_out = 1; +} + +chew_controlfile ($control); + +for my $icon (@global_list) { + print $output $icon . "\n" if (!($icon =~ /^sc_/)); +} +for my $icon (@global_list) { + print $output $icon . "\n" if ($icon =~ /^sc_/); +} + +close $output if (!$stdout_out); diff --git a/solenv/bin/installoffice b/solenv/bin/installoffice new file mode 100755 index 000000000000..602934958b53 --- /dev/null +++ b/solenv/bin/installoffice @@ -0,0 +1,102 @@ +#************************************************************************* +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: installoffice,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +#***********************************************************************/ + +#!/bin/bash +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_ERROR=2 +EXIT_BUG=10 + +if [ x${SOLARENV}x = xx ]; then + echo No environment found, please use 'configure' or 'setsolar' + exit $EXIT_FAILURE +fi +usage() { + echo "Usage: $SCRIPTNAME [-t DESTPATH] [-o] [-d] [-a]" >&2 + echo "" >&2 + echo "[-t] target path: path wehre tho office should installed to. The default is '$DESTPATH'" >&2 + echo "" >&2 + echo "[-o] force OpenOffice.org installation instead of StarOffice" >&2 + echo "" >&2 + echo "[-d] installation with debug output" >&2 + echo "" >&2 + echo "[-a] the office will be patched to run without FirstStartWizard" >&2 + exit $EXIT_FAILURE +} + +if [ x${USER}x = xx ]; then + if [ x${LOGNAME}x = xx ]; then + echo "ERROR: could not determine username. Please export variable USER" >&2 + exit $EXIT_FAILURE + else + USER=$LOGNAME + export USER + fi +fi + +DESTPATH=/tmp/$USER +PARAM="" + +while getopts ':mt:acdhot' OPTION ; do + case $OPTION in + d) PARAM="$PARAM -debug true" + ;; + c) PARAM="$PARAM -cwscheckapi true" + ;; + o) PARAM="$PARAM -ooo true" + ;; + a) PARAM="$PARAM -autorun true" + ;; + t) DESTPATH="$OPTARG" + ;; + h) usage $EXIT_SUCCESS + ;; + \?) echo "unkown option \"-$OPTARG\"." >&2 + usage $EXIT_ERROR + ;; + *) echo "this is not possible...">&2 + usage $EXIT_BUG + ;; + esac +done + +shift `expr $OPTIND - 1` + +LOCALINSTALLDIR=$DESTPATH/office +LOCALUNPACKDIR=$DESTPATH/unpack + +export LOCALINSTALLDIR +export LOCALUNPACKDIR + +unset FORCE2ARCHIVE + +echo "### $SOLARENV/bin/installoffice.pl $PARAM -cleanup true $@" +exec perl -w $SOLARENV/bin/installoffice.pl $PARAM -cleanup true $@ + +exit $? diff --git a/solenv/bin/installoffice.btm b/solenv/bin/installoffice.btm new file mode 100755 index 000000000000..983ee9e3df02 --- /dev/null +++ b/solenv/bin/installoffice.btm @@ -0,0 +1,82 @@ +@echo off +REM ************************************************************************** +REM * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +REM * +REM * Copyright 2008 by Sun Microsystems, Inc. +REM * +REM * OpenOffice.org - a multi-platform office productivity suite +REM * +REM * $RCSfile: installoffice.btm,v $ +REM * +REM * $Revision: 1.3.6.1 $ +REM * +REM * This file is part of OpenOffice.org. +REM * +REM * OpenOffice.org is free software: you can redistribute it and/or modify +REM * it under the terms of the GNU Lesser General Public License version 3 +REM * only, as published by the Free Software Foundation. +REM * +REM * OpenOffice.org is distributed in the hope that it will be useful, +REM * but WITHOUT ANY WARRANTY; without even the implied warranty of +REM * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +REM * GNU Lesser General Public License version 3 for more details +REM * (a copy is included in the LICENSE file that accompanied this code). +REM * +REM * You should have received a copy of the GNU Lesser General Public License +REM * version 3 along with OpenOffice.org. If not, see +REM * <http://www.openoffice.org/license.html> +REM * for a copy of the LGPLv3 License. +REM ************************************************************************/ + +iff EXIST e:\ then + iff EXIST e:\temp then + set temppath=e:\temp + elseiff EXIST e:\tmp then + set temppath=c:\tmp + else + mkdir e:\temp + set tmppath=c:\temp + endiff +elseiff EXIST c:\tmp then + set temppath=c:\tmp +elseiff EXIST c:\temp then + set temppath=c:\temp +else + set temppath=%TMP% +endiff + +SET DESTPATH=%temppath%\%USERNAME% +SET DEBUG=false +SET OOO=false +SET PARAM= + +for %opt in (%&%) DO ( + if "%opt%" == "-d" (SET PARAM=%PARAM% -debug true ^ shift) + if "%opt%" == "-o" (SET PARAM=%PARAM% -ooo true ^ shift) + if "%opt%" == "-c" (SET PARAM=%PARAM% -cwscheckapi true ^ shift) + if "%opt%" == "-a" (SET PARAM=%PARAM% -autorun true ^ shift) + if "%opt%" == "-t" (SET DESTPATH=%2 ^ shift ^ shift) + if "%opt%" == "-h" goto usage + if "%opt%" == "/h" goto usage +) + +SET LOCALINSTALLDIR=%DESTPATH%\office +SET LOCALUNPACKDIR=%DESTPATH%\unpack + +call perl5 %SOLARENV%\bin\installoffice.pl -dest %LOCALINSTALLDIR% %PARAM% -cleanup true %& + +quit %? + +:usage + echo. + echo Usage: %0% [-t DESTPATH] [-o] [-d] >&2 + echo. + echo [-d] installation with debug output>&2 + echo. + echo [-o] force OpenOffice.org installation instead of StarOffice>&2 + echo. + echo [-t] target path: path wehre tho office should installed to. The default is '%DESTPATH%'>&2 + echo. + echo [-a] the office will be patched to run without FirstStartWizard >&2 + echo. + quit 1 diff --git a/solenv/bin/installoffice.oxt b/solenv/bin/installoffice.oxt Binary files differnew file mode 100644 index 000000000000..feb1d8723078 --- /dev/null +++ b/solenv/bin/installoffice.oxt diff --git a/solenv/bin/installoffice.pl b/solenv/bin/installoffice.pl new file mode 100755 index 000000000000..a8ef48e53df6 --- /dev/null +++ b/solenv/bin/installoffice.pl @@ -0,0 +1,906 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; + +#************************************************************************* +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: installoffice.pl,v $ +# +# $Revision: 1.2.24.1 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +#***********************************************************************/ + +use strict; +use File::Find; +use File::Path; +my $script = $0; + +( our $script_name = $script ) =~ s/^.*\b(\w+)\.pl$/$1/; +( our $script_path = $script ) =~ s/$script_name.*//; + +our $debug = 0; # run without executing commands + +our $is_command_infos = 1; # print command details before exec +our $show_NoMessage = 0; +our $show_Message = 1; + +# special handling for cwschackapi +our $cwsCheckApi = 0; + +# remove existant office installation +our $cleanup = 0; + +# should the office be startable without user interaction +our $autorun = 0; + +# force openOffice.org installation if StarOffice is available +our $is_ooo = 0; + +parseArgs(); + +our $is_admin_installation = 1; + +our $gui = $ENV{GUI}; +our $temp_path = $ENV{TEMP}; +if (!defined($temp_path)) { + $temp_path = $ENV{TMP}; +} + +our $vcsid = $ENV{VCSID}; +our $sversion_saved = 0; +our $FileURLPrefix = "file:///"; +our $userinstalldir = "UserInstallation"; +our $cygwin = "cygwin"; +our $prefered_lang = "en-US"; +our $global_instset_mask = ""; +#$smoketest_install = $ENV{SMOKETESTINSTALLSET}; + +if (!defined($gui)) { + print "The workstamp is missing. Please use setsolar\n"; + exit(1); +} + +our $OfficeDestinationPath; +our $is_do_deinstall; +our $CygwinLineends; +our $WinLineends; +our $PS ; +our $NewPathSeparator ; +our $shell ; +our $shellSetEnvVar; +our $shellCommandSep; +our $cdCommand; +our $PERL ; +our $REMOVE_DIR ; +our $REMOVE_FILE ; +our $LIST_DIR ; +our $COPY_FILE ; +our $COPY_DIR ; +our $MK_DIR ; +our $RENAME_FILE ; +our $nul ; +our $RESPFILE; +our $SVERSION_INI ; +our $SOFFICEBIN ; +our $UNOPKGBIN; +our $bootstrapini ; +our $bootstrapiniTemp ; +our $packpackage ; +our $user; + +if (($gui eq "WNT") and ($ENV{USE_SHELL} ne "4nt")) { + $gui = $cygwin; +} + +if ($gui eq "WNT") { + $user = $ENV{USERNAME}; + $PS = '\\'; + $NewPathSeparator = ';'; + $shell = "$ENV{COMSPEC} -c "; + $shellSetEnvVar = "set "; + $shellCommandSep = "& "; + $cdCommand="cd /d "; + $PERL = "$shell $ENV{PERL}"; + $REMOVE_DIR = "$shell del /qsxyz"; + $REMOVE_FILE = "$shell del /q"; + $LIST_DIR = "$shell ls"; + $COPY_FILE = "$shell copy"; + $COPY_DIR = "$shell copy /s"; + $MK_DIR = "md"; + $RENAME_FILE = "ren"; + $nul = '> NUL'; + $RESPFILE="response_fat_wnt"; + $SVERSION_INI = $ENV{USERPROFILE} . $PS . "Anwendungsdaten" . $PS . "sversion.ini"; + $SOFFICEBIN = "soffice.exe"; + $bootstrapini = "bootstrap.ini"; + $UNOPKGBIN="unopkg.exe"; + $bootstrapiniTemp = $bootstrapini . "_"; + $packpackage = "msi"; + if (!defined($temp_path)) { + print "temp value is missing. Please set temp-variable\n"; + exit(1); + } +} +elsif ($gui eq "UNX") { + $user = $ENV{USER}; + $is_do_deinstall = 0; + $PS = '/'; + $shell = "/bin/sh -c "; + $shellSetEnvVar = "export "; + $shellCommandSep = ";"; + $cdCommand="cd "; + $NewPathSeparator = ':'; + $shell = ""; + $PERL = "$ENV{PERL}"; + $REMOVE_DIR = "rm -rf"; + $REMOVE_FILE = "rm -f"; + $LIST_DIR = "ls"; + $COPY_FILE = "cp -f"; + $COPY_DIR = "cp -rf"; + $MK_DIR = "mkdir"; + $RENAME_FILE = "mv"; + $nul = '> /dev/null'; + $RESPFILE="response_fat_unx"; + $SVERSION_INI = $ENV{HOME} . $PS . ".sversionrc"; + $SOFFICEBIN = "soffice"; + $bootstrapini = "bootstraprc"; + $UNOPKGBIN="unopkg"; + $bootstrapiniTemp = $bootstrapini . "_"; + $packpackage = $ENV{PKGFORMAT}; + if (!defined($temp_path)) { + $temp_path="/tmp"; + if (! -e $temp_path){ + print "temp value is missing. Please set temp-variable\n"; + exit(1); + } + } +} +elsif ($gui eq $cygwin) { + + $PS = '/'; + $NewPathSeparator = ':'; + $shell = "/bin/sh -c "; + $shellSetEnvVar = "export "; + $shellCommandSep = ";"; + $cdCommand = "cd "; + $PERL = "$ENV{PERL}"; + $REMOVE_DIR = "rm -rf"; + $REMOVE_FILE = "rm -f"; + $LIST_DIR = "ls"; + $COPY_FILE = "cp -f"; + $COPY_DIR = "cp -rf"; + $MK_DIR = "mkdir"; + $RENAME_FILE = "mv"; + $nul = '> /dev/null'; + $RESPFILE="response_fat_wnt"; + $SVERSION_INI = $ENV{USERPROFILE} . $PS . "Anwendungsdaten" . $PS . "sversion.ini"; + $SOFFICEBIN = "soffice"; + $bootstrapini = "bootstrap.ini"; + $bootstrapiniTemp = $bootstrapini . "_"; + $CygwinLineends = $/; + $WinLineends = "\r\n"; + &SetWinLineends(); + $packpackage = "msi"; + if (!defined($temp_path)) { + $temp_path="/tmp"; + if (! -e $temp_path){ + print "temp value is missing. Please set temp-variable\n"; + exit(1); + } + } +} +else { + print_error ("not supported system\n",1); +} + +my %PRODUCT1 = (Name => "StarOffice", instset => "instset_native"); +my %PRODUCT2 = (Name => "OpenOffice", instset => "instsetoo_native"); +our @PRODUCT = (\%PRODUCT1, \%PRODUCT2); + +our $SHIP = defined $ENV{SHIPDRIVE} ? $ENV{SHIPDRIVE} . $PS : "shipdrive_not_set"; + +if (defined($ENV{CWS_WORK_STAMP})){ + print " found CWS\n"; +} +elsif (isLocalEnv()){ + print " local environment\n"; +} +elsif (defined $ENV{SHIPDRIVE}) { + print " master version\n"; +} +elsif (defined $ENV{SOLARSRC}) { + print " OpenOffice master version\n"; +} +else { + print "Could not determine environment. Exit\n"; + exit 1 +} + + +our @error_messages = ( '', + 'lock flag for pkgadd still exist. Installation not possible!', + 'Error during installation!', + 'Error: patching configuration failed!', + 'Error: starting office failed or office crashed!', + 'Error during testing', + 'can not copy extension', + 'Error in setup log', + 'installationsset is not complete', + 'can not copy all basic scripts', + 'can not patch bottstrapini', + 'msiexec failed. Maybe you have got an installed version', + 'deinstallation is incomplete' +); + + +my $success = 0; +$success = installOffice(); + +if ($success != 0){ + exit(1); +} +exit(0); + +sub installOffice(){ + + # <DISABLED> + # my ($officeVersion, $instsetPath)= getInstset(); + # print "OFFICEVERSION:$officeVersion INSTSETPATH:$instsetPath\n" if $debug; + # my $sourcePath=$instsetPath.$PS.$officeVersion; + # </DISABLED> + # + # currently this installer does not install an office, it do pack a runnable office. + # Therefore we do not need to search for an instSet + my $sourcePath="dummy"; + my $officeVersion="dummy"; + + my $destinationPath = getDestinationPath($officeVersion); + print "destinationPath: $destinationPath\n" if $debug; + + removeOffice($destinationPath); + mkdirs($destinationPath); + + my $installCommand = getInstallCommand($sourcePath, $destinationPath, $officeVersion); + print "installCommand: $installCommand\n" if $debug; + + my $success=0; + $success = system($installCommand); + print "installoofice.pl::installoffice::success $success\n" if ($debug); + + if ($autorun) { + makeAutoRun($destinationPath); + } + + return $success; +} + +sub makeAutoRun(){ + + my $destinationPath = shift; + + patchBootstraprc($destinationPath); + + + if (patchXCU ($destinationPath) != 0) { + print_error("could not patch XCU files", "1"); + } + return 0; +} + + +sub patchBootstraprc(){ + my $destinationPath = shift; + my $bootstraprc=""; + + find sub { $bootstraprc=$File::Find::name if -e _ && /$bootstrapini$/ }, $destinationPath; + + print_error("could not find $bootstrapini", "1") if ( ! -e $bootstraprc ); + + open(BSRC, "<$bootstraprc") or errorFromOpen(" for reading " .$bootstraprc); + my @content = <BSRC>; + close(BSRC); + my @newContent; + foreach(@content) { + if ( /UserInstallation=./ ) { + push(@newContent, "UserInstallation=\$ORIGIN/../UserInstallation\n"); + } + else { + push(@newContent,$_); + } + } + + chmod(0755,$bootstraprc); + + open OUTFILE, ">$bootstraprc" or return errorFromOpen (" for writing " . $bootstraprc); + print OUTFILE @newContent; + close OUTFILE; + +} + +sub patchXCU(){ + my $destinationPath = shift; + my $unopkg=""; + + find sub { $unopkg=$File::Find::name if -e _ && /$UNOPKGBIN$/ }, $destinationPath; + + print_error("could not find $UNOPKGBIN", "1") if ( !-e $unopkg ); + print "unopkg: '$unopkg'\n" if $debug; + + if ($gui eq "WNT") { + $unopkg = "\"$unopkg\""; + } + + my $unopkgCommand = "$unopkg add $script_path".$script_name.".oxt"; + print "patch xcu files for automatic office start...\n" if $debug; + print "call $unopkgCommand\n" if $debug; + my $success=0; + $success = system($unopkgCommand); + + return $success; +} + +sub writeFile(){ + my $fileName = shift; + my @content = @_; + + open OUTFILE, ">$fileName" or return errorFromOpen (" for writing " . $fileName); + + my $lf; + if ($packpackage eq "msi"){ + $lf = "\r\n"; + } else { + $lf = "\n"; + } + + my $line; + foreach $line(@content) { + print "LINE: $line\n" if $debug; + print OUTFILE $line.$lf; + } + close(OUTFILE); + return 0; +} + +sub mkdirs(){ + my $directory = shift; + my $splitter=$PS; + if ( $PS eq "\\" ){ + $splitter="\\\\"; + } + my @aFolder=split($splitter,$directory); + + my $dir; + my $folder; + foreach $folder(@aFolder){ + if ( (! defined($dir)) && ($PS eq "\\")){ + $dir=$folder; + } else { + $dir=$dir.$PS.$folder; + } + if (! -e $dir ){ + print "try to create $dir\n" if $debug; + mkdir($dir); + } + } +} + +sub removeOffice(){ + + my $destPath=shift; + + if ($cleanup){ + print "remove old office installation...\n"; + + print "remove $destPath...\n" if $debug; + rmtree($destPath); + + } +} + +sub getInstallCommand() { + my $command; + $command = getDmakeInstalledCommand(@_); + # if ($packpackage eq "msi"){ + # $command = getWindowsInallCommand(@_); + # } else { + # $command = getUnixInstallCommand(@_); + # } + return $command; +} + +sub getDmakeInstalledCommand(){ + my ($sourcePath, $destPath, $officeVersion) = @_; + my $RootDir=$ENV{SRC_ROOT}; + + my $ProductName; + my $instset; + + # check if instset_native could be found + foreach my $pointer (@PRODUCT) { + $instset = $pointer->{'instset'}; + $ProductName = $pointer->{'Name'}; + my $instsetDir = "$RootDir$PS$instset"; + print "instsetDir: $instsetDir \n" if $debug; + + last if ($is_ooo && $ProductName eq "OpenOffice"); + last if ( ! $is_ooo && -e "$instsetDir"); + } + print "Product: $ProductName\n" if $debug;; + + my $dmakeTarget=lc($ProductName)."_en-US"; + + my $utilFolder = getInstsetUtilFolder($instset, $destPath, $RootDir); + my $dmakeCommand = " $cdCommand \"$utilFolder\" $shellCommandSep dmake $dmakeTarget PKGFORMAT=installed -vt"; + my $envset; + if ($gui eq "WNT") { + $envset="set LOCALINSTALLDIR=$destPath & set LOCALUNPACKDIR=$destPath &"; + }else { + $envset="LOCALINSTALLDIR=$destPath ; LOCALUNPACKDIR=$destPath ; export LOCALINSTALLDIR ; export LOCALUNPACKDIR ; "; + } + #my $command=$envset.$dmakeCommand; + my $command=$dmakeCommand; + return $command; +} + +sub getInstsetUtilFolder(){ + my $instset = shift; + my $destPath = shift; + my $RootDir = shift; + + my $instsetFolder = $RootDir.$PS.$instset; + my $utilFolder=""; + + if(-w $instsetFolder) { + print "$instsetFolder is writable \n" if $debug; + $utilFolder = $RootDir.$PS.$instset.$PS."util"; + } else { + print "$instsetFolder is NOT writable \n" if $debug; + print "copy $instset to $destPath$PS..n" if $debug; + my $prjPath=$destPath.$PS.".."; + + my $command = "$ENV{COPYPRJ} -x $instset $prjPath"; + print $command if $debug; + system($command); + $utilFolder=$prjPath.$PS.$ENV{WORK_STAMP}.$PS.$instset.$PS."util"; + } + print "utilFolder: $utilFolder\n" if $debug; + return $utilFolder; +} + +# sub getInstsetFomInstsetNative(){ +# my (@DirArray, $TestDir1, $TestDir2); +# my $instset; +# my $ProductName; +# my $instDir=""; +# my $lang; +# my $RootDir=$ENV{SRC_ROOT}; +# my $StandDir = $ENV{SOLARSRC} . $PS; +# #$RootDir=~s/\w+$//; + +# foreach my $pointer (@PRODUCT) { +# $instset = $pointer->{'instset'}; +# $ProductName = $pointer->{'Name'}; +# @DirArray=(); +# $TestDir1 = "$RootDir$PS$instset$PS$ENV{INPATH}$PS$ProductName$PS$packpackage$PS" . "install$PS"; +# $TestDir2 = "$StandDir$instset$PS$ENV{INPATH}$PS$ProductName$PS$packpackage$PS" . "install$PS"; +# print "TestDir1: $TestDir1 \n"; +# print "TestDir2: $TestDir2 \n"; +# if (-e "$TestDir1") { +# $instDir= $TestDir1; +# } +# elsif (-e "$TestDir2") { +# $instDir="$TestDir2"; +# } +# if ($instDir eq "") { +# next; +# } + +# getSubDirs ("$instDir", \@DirArray); +# $lang = findSubDir (\@DirArray); +# print "Lang-Sel: $lang\n" if $is_command_infos; +# ; +# if (($instDir ne "") and (-e $instDir)) { +# return ($lang, $instDir, $ProductName, $instset); +# } +# } +# print_error ("no installationset found\n",2); + +# } + +sub getWindowsInallCommand(){ + my ($sourcePath, $destPath) = @_; + my $mask = "\\.msi\$"; + #my $DirArray; + my @DirArray = (); + getSubFiles ("$sourcePath", \@DirArray, $mask); + if ($#DirArray == -1) { + print_error ("Installationset in $sourcePath is incomplete", 2); + } + if ($#DirArray >= 1) { + print_error ("Installationset in $sourcePath hat too many msi-files", 2); + print "found the following msi-files: @DirArray\n" if $debug; + } + my $command = "msiexec.exe /a $sourcePath$PS$DirArray[0] -qn ALLUSERS=2 INSTALLLOCATION=$destPath"; + + return $command; +} + +sub getUnixInstallCommand() { + my ($sourcePath, $destPath, $officeVersion) = @_; + + my $userland="unknown"; + + if (defined($ENV{CWS_WORK_STAMP})){ + print " found CWS\n"; + $userland=$ENV{SOLARVERSION}.$PS.$ENV{INPATH}.$PS."bin".$ENV{UPDMINOREXT}.$PS."userscripts".$PS."install"; + } + elsif (isLocalEnv()){ + print " local environment\n"; + } + elsif (defined $ENV{SHIPDRIVE}) { + print " master version\n"; + $userland=$ENV{SHIPDRIVE}.$PS.$ENV{INPATH}.$PS."UserScripts".$PS.$ENV{PKGFORMAT}.$PS.$officeVersion.$PS."install"; + } + elsif (defined $ENV{SOLARSRC}) { + print " OpenOffice master version\n"; + print " command to install Office not implementet yet\n"; + exit(1); + } + else { + print "Could not determine environment. Exit\n"; + exit(1); + } + return "$userland $sourcePath $destPath"; +; + +} + +sub getDestinationPath { + # if (defined $ENV{SOLARROOT}){ + # # seems to be a Sun environment + # if (! -e $OfficeDestinationPath){ + + # } + # } + my $officeVersion = shift; + my $officename; + + if (defined($ENV{LOCALINSTALLDIR})){ + $OfficeDestinationPath=$ENV{LOCALINSTALLDIR}; + if(index($OfficeDestinationPath," ") >= 0) { + my $msg="You environemt variable '\$LOCALINSTALLDIR=$OfficeDestinationPath' contains white spaces."; + $msg = $msg." This is not allowed!"; + print_error($msg, "1"); + } + } + if (!defined($OfficeDestinationPath)){ + $officename = $officeVersion; + if (defined($ENV{CWS_WORK_STAMP})){ + $officename=$ENV{CWS_WORK_STAMP}; + } + $OfficeDestinationPath=$temp_path.$PS.$user.$PS."office".$PS.$officename; + } + + return $OfficeDestinationPath; +} + +# sub getInstset { + +# my ($INSTSET, $NEWINSTSET, $ProductName); + +# if (defined ($ENV{EPM}) && ($ENV{EPM} eq 'NO') && ($gui eq "UNX")) { # we do the install ourselves ... +# return (); +# } + +# print "get Instset\n" if $debug; +# $NEWINSTSET = ""; + +# if (!isLocalEnv() and !defined($ENV{CWS_WORK_STAMP}) and (-e $SHIP) and ($gui ne $cygwin)) { +# ($NEWINSTSET, $INSTSET) = getSetFromServer(); +# } +# else { +# ($NEWINSTSET, $INSTSET, $ProductName) = getInstsetFomInstsetNative(); +# } +# return ($NEWINSTSET, $INSTSET); +# } + +# sub getSetFromServer { +# my ($DirName, $SetupFullPath); +# my $workspace = $ENV{WORK_STAMP}; +# my $platform = $ENV{INPATH}; +# my $latestset; +# my (@DirArray, $mask, $buildid, $milestone); + +# foreach my $pointer (@PRODUCT) { +# my $ProductName = $pointer->{'Name'}; + +# print "##PRODUCT: $ProductName\n"; +# my $SetupFullPath = "$SHIP$ENV{INPATH}$PS$ProductName$PS$packpackage$PS"; +# if ( ! ( $workspace && $platform ) ) { +# print_error ( "Error: environment not set correctly.", 1); +# } +# # get latest broadcastet milestone and pack number +# ($milestone, $buildid) = get_milestoneAndBuildID( $workspace, $platform ); + +# if (defined $ENV{CWS_WORK_STAMP}) { +# # /unxlngi6.pro/StarOffice/rpm/ SRC680_m245_native_packed-2_en-US.9267/ +# $mask = "^$workspace" . "_" . $milestone . "_native_packed-(\\d+)_en-US\\.$buildid"; +# } else { +# # cws03/os110/OOH680/src.m4/instset_native/unxlngi6.pro/StarOffice/rpm install/en-US/RPMS +# $mask = "^$workspace" . "_" . $milestone . "_native_packed-(\\d+)_en-US\\.$buildid"; +# } +# print "MASK: $mask\n"; +# $global_instset_mask = $mask; +# getSubFiles ($SetupFullPath, \@DirArray, $mask); +# @DirArray = sort InstsetSort @DirArray; + +# if ($#DirArray > -1) { +# $latestset = $DirArray [$#DirArray]; +# $DirName = $latestset; +# } +# else { +# print_error ("Cannot find install set $SetupFullPath for $workspace $milestone", 2); +# } + +# print "Latest install sets: $latestset\n" if $debug; + +# print "$DirName\t $SetupFullPath\n" if $debug; +# # compare with file system +# # at the moment just the existence is checked. For security reasons it might be +# # better to additionally check whether there are newer sets (this must not happen, +# # but who knows ...) +# if ( -d $SetupFullPath ) { +# # if found => return and don't continue searching +# # this is usefull to set a priority to find installsets in @PRODUCT +# # first comes, first wins +# return ($DirName, $SetupFullPath); +# } +# } + +# # compare with file system +# # at the moment just the existence is checked. For security reasons it might be +# # better to additionally check whether there are newer sets (this must not happen, +# # but who knows ...) +# if ( -d $SetupFullPath ) { +# return ($DirName, $SetupFullPath); +# } else { +# print_error ("Cannot find install set $SetupFullPath for $workspace $milestone", 2); +# } +# } + +# sub get_milestoneAndBuildID { +# my ( $ws, $pf ) = @_; +# my ($milestone, $buildid, $upd, $path, $updext, $line); + +# if ( $ws =~ /^\D+(\d+)$/) { +# $upd = $1; +# } + +# if (defined ($ENV{UPDMINOREXT})) { +# $updext = $ENV{UPDMINOREXT}; +# } +# else { +# $updext = ""; +# } + +# $path = "$ENV{SOLARVER}$PS$pf$PS" . "inc$updext$PS$upd" . "minor.mk"; +# print "$path\n" if $debug; +# local *MINORMK; + +# if ( !open(MINORMK,$path) ) { +# print "FATAL: can't open $path\n"; +# return (0,0); +# } + +# if (!eof(MINORMK)) { +# while ($line = <MINORMK>) { +# chomp($line); +# if ( $line =~ /LAST_MINOR=(\w+)/ ) { +# $milestone = $1; +# } +# elsif ( $line =~ /BUILD=(\d+)/ ) { +# $buildid = $1; +# } +# } + +# close(MINORMK); +# } +# if (!defined($milestone)) { +# print_error ("Milestone ist not defined!", 2); +# } +# if (!defined($buildid)) { +# print_error ("Build-ID ist not defined!", 2); +# } + +# return ($milestone, $buildid); +# } + +sub print_error +{ + my $message = shift; + my $error_code = shift; + + print STDERR "ERROR: $message\n"; + doExit($error_code); +} + +sub getSubFiles { + my ($startDir, $DirArray_ref, $mask) = @_; + my ($dir); + local *DIR; + opendir(DIR,"$startDir"); + while($dir = readdir(DIR)) { + if (($dir =~ /\.$/) or ($dir !~ /$mask/)) { + next; + } + push (@{$DirArray_ref}, "$dir"); + } + closedir(DIR); + +} + +sub InstsetSort { + my ($a1, $b1); + if ($a =~ /$global_instset_mask/) { + $a1 = $1; + } + if ($b =~ /$global_instset_mask/) { + $b1 = $1; + } + $a1 <=> $b1; +} + +sub isLocalEnv { + my $returnvalue = 0; + if (defined ($ENV{SOL_TMP}) && defined ($ENV{SOLARVERSION})) { + my $mask = $ENV{SOL_TMP}; + $mask =~ s/\\/\\\\/; + print "Mask: $mask\n" if $debug; + if ($ENV{SOLARVERSION}=~ /$mask/) { + $returnvalue = 1; + } + } + return $returnvalue; +} + +sub getSubDirs { + my ($startDir, $DirArray_ref) = @_; + my ($dir); + opendir(DIR,"$startDir"); + while($dir = readdir(DIR)) { + if (($dir !~ /\.$/) and ( -d "$startDir$dir") ) { + push (@{$DirArray_ref}, "$dir"); + } + } + closedir(DIR); + +} + +sub findSubDir { + my ($DirArray_ref) = @_; + my (@sortedArray, $dir, $instdir); + @sortedArray = sort langsort @{$DirArray_ref}; + print "Langs: @sortedArray\n" if $is_command_infos; + foreach $dir (@sortedArray) { + if ($dir =~ /log$/) { + next; + } + $instdir = "$dir"; + return $instdir; + } + return ""; +} + +sub langsort { + if ($a eq $prefered_lang) { + return -1; + } + elsif ($b eq $prefered_lang) { + return 1; + } + else { + $a cmp $b; + } +} + +sub doExit +{ + my $error_code = shift; + # if ($sversion_saved) { + # restore_sversion ($SVERSION_INI); + # } + # if ($is_remove_on_error) { + # if ($is_do_deinstall) { + # deinstallInstallation ($installpath); + # } + # removeInstallation($installpath); + # } + # else { + # print_notRemoved ($installpath); + # } + if ( $error_code ) { + print STDERR "\nFAILURE: $script_name aborted.\n"; + } + exit($error_code); + +} + + +sub parseArgs +{ + for (my $i=0; $i<=$#ARGV; $i++) { + if ( $ARGV[$i] =~ /^-cwscheckapi$/ ) { + my $value = $ARGV[++$i]; + if ($value =~ /^true$/ || ($value =~ /^1$/) ) { + $cwsCheckApi = 1; + $cleanup = 1; + $autorun = 1; + }; + + } + + if ( $ARGV[$i] =~ /^-dest$/ ) { + $OfficeDestinationPath = $ARGV[++$i]; + } + + if ( $ARGV[$i] =~ /^-cleanup$/ ) { + my $value = $ARGV[++$i]; + if ($value =~ /^true$/ || ($value =~ /^1$/ )) { $cleanup = 1 }; + } + + if ( $ARGV[$i] =~ /^-autorun$/ ) { + my $value = $ARGV[++$i]; + if ($value =~ /^true$/ || ($value =~ /^1$/ )) { $autorun = 1 }; + } + + if ( $ARGV[$i] =~ /^-debug$/ ) { + my $value = $ARGV[++$i]; + if ($value =~ /^true$/ || ($value =~ /^1$/ )) { $debug = 1 }; + } + + if ( $ARGV[$i] =~ /^-ooo$/ ) { + my $value = $ARGV[++$i]; + if ($value =~ /^true$/ || ($value =~ /^1$/ )) { $is_ooo = 1 }; + } + } + +} + +sub getSubDirsFullPath { + my ($startDir, $DirArray_ref) = @_; + my ($dir); + opendir(DIR,"$startDir"); + while($dir = readdir(DIR)) { + if (($dir !~ /\.$/) and ( -d "$startDir$dir") ) { + push (@{$DirArray_ref}, "$startDir$dir"); + } + } + closedir(DIR); +} + +sub errorFromOpen { + my ($file) = @_; + print_error( "can not open $file", "1"); +} + diff --git a/solenv/bin/langwrap b/solenv/bin/langwrap new file mode 100755 index 000000000000..97a50f1762ee --- /dev/null +++ b/solenv/bin/langwrap @@ -0,0 +1,131 @@ +#!/usr/bin/perl -w +# +# langwrap - language wrapper for building resources +# +# $Id: langwrap,v 1.2 2008-08-18 13:10:41 vg Exp $ + +use Getopt::Std; + +###### globals ###### + +$is_debug = 0; +$nfield = 0; +@LoL = (); +@command = (); + +###### main ###### + +# Version +$idStr = ' $Revision: 1.2 $ '; +$idStr =~ /Revision:\s+(\S+)\s+\$/ + ? ($langwrapRev = $1) : ($langwrapRev = "-"); + +print "langwrap -- Version: $langwrapRev\n"; + +# Options +&check_options(); + +# parse command file +&parse_commandfile($opt_c); + +# create list with command lines +&create_commands(); + +# finally execute commands +foreach $cmd (@command) { + if ($is_debug) { + print $cmd . "\n"; + } else { + system($cmd); + $res = $? >> 8; + if ($res) { + print "langwrap: command execution failed with exitcode $res.\n"; + exit($res); + } + } +} + +exit(0); + +###### routines ###### + +### parse_commandfile() +sub parse_commandfile { + my($file) = shift; + my(@field); + + open(COMMAND, "<$file") or die "can´t open $file"; + + while (<COMMAND>) { + $line = $_; + chomp($line); + if ( ($line =~ //) || ($line =~ /^\r/) || ($line =~ /^#/) ) { + next; + } + + @field = split " ", $line; + push @LoL, [@field]; + if (!$nfield) { + $nfield = $#field + 1; + } else { + if ( $nfield != ($#field + 1) ) { + print "langwrap: error in <cmdfile>: every row must "; + print "have the same # of columns.\n"; + exit(3); + } + } + } + + close(COMMAND); +} + +### create_command() +sub create_commands() { + my($cmd, $cmdline, $arg_string, $ntempl); + + $cmd = shift @ARGV; + $arg_string = join(" ", @ARGV); + # just count the number of templates + $ntempl = ($arg_string =~ s/@\d+@/$&/eg); + if ( $ntempl >= $nfield ) { + print "lnagwrap: # of templates > # of fields in <cmdfile>.\n"; + exit(4); + } + + # create command lines + for $i (0..$#LoL) { + $cmdline = $arg_string; + $cmdline =~ s/@(\d+)@/$LoL[$i][$1]/eg; + push @command, $cmd . " " . $cmdline; + } +} + +### check_options() +sub check_options { + + if ( !getopts('c:') ) { + &usage(); + } + + if ( !$opt_c ) { + &usage(); + } + + if ( ! -r $opt_c ) { + print "langwrap: $opt_c is not a readable file.\n"; + exit(2); + } + + if ( $#ARGV < 1 ) { + print "langwrap: empty <template_string>.\n"; + &usage(); + } +} + +### usage() +sub usage { + print "Usage: langwrap -c cmdfile tool <template_string>\n"; + print "<template_string> is of form: ...\@1\@ .... \@2\@...\n"; + print "with \@<n>\@ template #n\n"; + exit(1); +} diff --git a/solenv/bin/leconvert.pl b/solenv/bin/leconvert.pl new file mode 100755 index 000000000000..48723c1d79f0 --- /dev/null +++ b/solenv/bin/leconvert.pl @@ -0,0 +1,95 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: leconvert.pl,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +my $target_format = ""; +my @filelist; +#my $debug=1; +my $debug=0; + +parameter_parse(@ARGV); +print "@filelist\n" if ( $debug ); +foreach my $onefile ( @filelist ) { + convert_file( $onefile ); +} + + +sub convert_file +{ + my $filename = shift; + if ( $target_format eq "dos" ) { + $lineend = "\r\n"; + } else { + $lineend = "\n"; + } + open INFILE, "$filename"or die "ERROR: Couldn\'t open $filename for reading.\n"; + my @lines = <INFILE>; + close INFILE; + + foreach my $oneline ( @lines ) { + $oneline =~ s/\r*\n*$/$lineend/; + } + + open OUTFILE, ">$filename" or die "ERROR: Couldn\'t open $filename for writing.\n"; + syswrite OUTFILE, join "", @lines; + close OUTFILE; + +} + +sub parameter_parse +{ + if ( $target_format eq "" ) { + $target_format = shift ; + usage() if ( $target_format ne "unix" && $target_format ne "dos" ); + usage() if ( $#_ == -1 ); + } + foreach my $param ( @_ ) { + if ( $param =~ "^@" ) { + my $filename = $param; + $filename =~ s/^@//; + open CMDFILE, "$filename" or die "ERROR: Couldn\'t open $filename for reading.\n"; + my @filelist = <CMDFILE>; + close CMDFILE; + parameter_parse( @filelist ); + } else { + push @filelist, $param; + } + } +} + +sub usage +{ + print "Convert text files to the desired lineend convention:\n"; + print "$0 <unix|dos> <FILE|\@filelist> [more files/lists]\n"; + exit 1; +} + diff --git a/solenv/bin/licinserter.pl b/solenv/bin/licinserter.pl new file mode 100644 index 000000000000..b01a85b75731 --- /dev/null +++ b/solenv/bin/licinserter.pl @@ -0,0 +1,142 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: licinserter.pl,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +# +# licinserter.pl - create license entries in extension description.xml +# + +use File::Basename; + +my $langswitch; + +sub usage() +{ + print STDERR "\nCreate extension descriptions with license-text entries\n"; + print STDERR "matching the language activated.\n"; + print STDERR "\nUsage:\n"; + print STDERR "\t$0 [--langsplit] infile \"naming pattern\" destination\n\n"; + print STDERR "\nExample:\n\n"; + print STDERR "$0 description.xml dir/license_xxx.txt outdir/description.xml\n\n"; + print STDERR "Creates \"someoutdir/description.xml\" with the license file entries like\n\"dir/license_en.US.txt\" "; + print STDERR "for all languages found in the WITH_LANG environment\nvariable\n\n\n"; + print STDERR "Example2:\n\n"; + print STDERR "$0 --langsplit description.xml dir/license_xxx.txt someoutdir\n\n"; + print STDERR "Creates \"someoutdir/<language>/description.xml\" with one license file entry\n\"somedir/license_<language>.txt\" "; + print STDERR "for all languages found in the WITH_LANG\nenvironment variable.\n\nNOTE: when using --langsplit \"destination\" needs to be a directory\n"; +} + +if ( $ARGV[0] =~ /^-/ ) { + $langswitch = shift @ARGV; + if ( $langswitch ne "--langsplit" ) { + usage(); + exit 1; + } + if ( ! -d $ARGV[2] ) { + print STDERR "\nERROR - $ARGV[2] is not directory\n"; + usage(); + exit 2; + } +} + +if ( $#ARGV != 2 ) { + print "zzz\n"; + usage(); + exit 1; +} + +open INFILE,$ARGV[0] or die "oops - no such file $ARGV[0]!\n"; + +my @inlines = <INFILE>; +close INFILE; + +chomp @inlines; + +# Empty or unset WITH_LANG environment variable is set to default en-US. +# When WITH_LANG is set but does not contain en-US then that is prepended. +my $WithLang = $ENV{WITH_LANG}; +if ( ! defined $WithLang || $WithLang eq "") +{ + $WithLang = "en-US"; +} +elsif ($WithLang !~ /\ben-US\b/) +{ + $WithLang = "en-US " . $WithLang; +} + + +if ( $langswitch eq "" ) { + my @outlines; + foreach my $i (@inlines) { + if ( $i =~ /license-text/ ) { + my $ii; + my $name; + foreach my $code ( split(/\s+/,$WithLang) ) { + $ii = $i; + $name = $ARGV[1]; + $name =~ s/xxx/$code/; + $ii =~ s/isocode/$code/g; + $ii =~ s?licensefile?$name?g; + push @outlines, "$ii\n"; + } + } else { + push @outlines, "$i\n"; + } + } + open OUTFILE, ">$ARGV[2]" or die "ooops - can't open $ARGV[2] for writing\n"; + print OUTFILE @outlines; + close OUTFILE or die "ooops - can't write to $ARGV[2]\n"; +} else { + my @outlines; + my $outname = basename($ARGV[0],()); + foreach my $code ( split(/\s+/,$ENV{WITH_LANG}) ) { + @outlines=(); + foreach my $i (@inlines) { + if ( $i =~ /license-text/ ) { + my $name; + my $ii = $i; + $name = $ARGV[1]; + $name =~ s/xxx/$code/; + $ii =~ s/isocode/$code/g; + $ii =~ s?licensefile?$name?g; + push @outlines, "$ii\n"; + } else { + push @outlines, "$i\n"; + } + } + mkdir "$ARGV[2]/$code"; + open OUTFILE, ">$ARGV[2]/$code/$outname" or die "ooops - can't open $ARGV[2]/$code/$outname for writing\n"; + print OUTFILE @outlines; + close OUTFILE or die "ooops - can't write to $ARGV[2]/$code/$outname\n"; + } +} diff --git a/solenv/bin/linkoo b/solenv/bin/linkoo new file mode 100755 index 000000000000..a413e485b30a --- /dev/null +++ b/solenv/bin/linkoo @@ -0,0 +1,367 @@ +: + eval 'exec perl -S $0 ${1+"$@"}' + if 0; + +#************************************************************************* +# +# This app makes it easy to link a live build +# set into an install set. Then your devel iteration +# is: 'build', execute. +# +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: linkoo,v $ +# +# $Revision: 1.17 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +# ends up in program/ooenv +( $moz_lib = `pkg-config --variable=libdir mozilla-nss` ) =~ tr/\n/:/; +$env_script = ' +java_path=`./javaldx` +export LD_LIBRARY_PATH=".:$java_path:' . $moz_lib . '$LD_LIBRARY_PATH" +ulimit -c unlimited +export PATH=".:$PATH" +export GNOME_DISABLE_CRASH_DIALOG=1 +export STAR_RESOURCEPATH=`pwd`/resource +# debugging assistance +export OOO_FORCE_SYSALLOC=1 +export MALLOC_CHECK_=2 +export OOO_DISABLE_RECOVERY=1 +'; + +$program_dir = 'program'; +$program_dir = 'MacOS' if ($ENV{OS} eq 'MACOSX'); + +my @exceptions = ( 'cppuhelper', 'configmgr2', 'sunjavaplugin', 'libjvmfwk' ); + +%replaceable = ( + $program_dir => '\.so', + $program_dir . '/resource' => '\.res$', + $program_dir . '/classes' => '\.jar$', + 'share/config' => '\.zip$', +# 'share/uno_packages' => '\.zip$' +); + +# strangely enough, OSX has those small differences... +$replaceable{$program_dir} = '\.dylib$' if ($ENV{OS} eq 'MACOSX'); + +@search_dirs = ( 'lib', 'bin', 'class' ); + +@known_duplicates = ( 'db.jar', 'libi18n' ); + +sub sniff_target($) +{ + my $build_dir = shift; + my ($dirhandle, $fname); + my ($target, $libver, $lang) = ( 'unxlngi4.pro', '680', 'en-US' ); # defaults + + opendir ($dirhandle, $build_dir) || die "Can't open $build_dir"; + while ($fname = readdir ($dirhandle)) { + $fname =~ /Set.sh$/ || next; + + my $file; + open ($file, "$build_dir/$fname") || die "Can't open $build_dir/$fname"; + while (<$file>) { + /\s*(\S+)\s*=\s*\"(\S+)\"/ || next; + if ($1 eq 'INPATH') { + $target = $2; + } + if ($1 eq 'UPD') { + $libver = $2; + } + } + close ($file); + } + + closedir ($dirhandle); + + print "Sniffed target: $target, $libver\n"; + + return ($target, $libver, $lang); +} + +sub build_installed_list($) +{ + my $path = shift; + my %files = (); + + for my $suffix (keys %replaceable) { + my $dirname = "$path/$suffix"; + my $dirhandle; + my $pattern = $replaceable{$suffix}; + if (opendir ($dirhandle, $dirname)) { + while (my $fname = readdir ($dirhandle)) { + $fname =~ m/$pattern/ || next; + + my $skip = 0; + for $pattern (@exceptions) { + $fname =~ /$pattern/ || next; + $skip = 1; + } + $files{$fname} = $dirname if !$skip; + } + closedir ($dirhandle); + } else { + print "Couldn't find '$dirname': skipping\n"; + } + } + return \%files; +} + +sub check_create_linked($) +{ + my $path = shift; + my $linked_dir = "$path/linked"; + if (! -d $linked_dir) { + mkdir $linked_dir || die "Can't make $linked_dir: $!"; + } +} + +sub do_link($$$$@) +{ + my $src = shift; + my $dest = shift; + my $src_name = shift; + my $dest_name = shift; + my $dont_check_link = shift; + + if (-l "$dest/$dest_name" ) { + my $link = readlink ("$dest/$dest_name"); + if ($link =~ /^\//) { # Absolute path + if (!$dry_run) { + # re-write the link + unlink ("$dest/$dest_name"); + symlink ("$src/$src_name", "$dest/$dest_name") || die "Failed to symlink: $!"; + print " [$dest_name]"; + } else { + print "re-make link $src/$src_name => $dest/$dest_name\n"; + } + } elsif ($dry_run) { + print "skipping symbolic link $dest/$dest_name -> $link\n"; + } + } else { + check_create_linked ($dest); + if (!$dry_run) { + # move / write the link + rename ("$dest/$dest_name", "$dest/linked/$dest_name") || + defined $dont_check_link || die "Failed rename of $dest/$dest_name: $!"; + + symlink ("$src/$src_name", "$dest/$dest_name") || die "Failed to symlink: $!"; + print " $dest_name"; + } else { + print "move / symlink $src/$src_name => $dest/$dest_name\n"; + } + } +} + +sub scan_and_link_files($$$) +{ + my $build_path = shift; + my $installed_files = shift; + my $target = shift; + + my @modules = (); + my $dirh_toplevel; + opendir ($dirh_toplevel, $build_path) || die "Can't open '$build_path': $!"; + while (my $subdir = readdir ($dirh_toplevel)) { + $subdir =~ m/\./ && next; # eg. vcl.old, + my $test = "$build_path/$subdir/$target"; + -d $test || next; + push @modules, $test; + } + closedir ($dirh_toplevel); + +# FIXME: re-implement the $product functionality + my $module; + my %build_files; + for $module (@modules) { + for $elem (@search_dirs) { + my $dirh_module; + my $module_path = "$module/$elem"; + if (opendir ($dirh_module, $module_path)) { + while (my $file = readdir($dirh_module)) { + if (defined $installed_files->{$file}) { + if (defined $build_files{$file}) { + my $known = 0; + for my $regexp (@known_duplicates) { + if ($file =~ m/$regexp/) { + $known = 1; + } + } + if (!$known) { + print "Unknown duplicate file '$file' in: '" . + $build_files{$file} . "' vs '" . + $module_path . "' in module $module\n"; + exit (1); + } + } + $build_files{$file} = $module_path; + } + } + } + closedir ($dirh_module); + } + } + + for my $file (keys %build_files) { + my $src = $build_files{$file}; + my $dest = $installed_files->{$file}; + + do_link ($src, $dest, $file, $file); + } + print "\n"; +} + +sub evilness($) +{ + my $doit = shift; + my $name = 'librecentfile.so'; + my $src = "$OOO_BUILD/shell/$TARGET/lib/$name"; + my $dest = "$OOO_BUILD/sfx2/$TARGET/lib/$name"; + + if ($doit eq 'undo') { + if (-l $dest) { + print " unlink $name\n"; + unlink $dest; + } + } else { + $doit eq 'do' || die; + if (-f $src) { + print " link $name\n"; + symlink $src, $dest; + } + } +} + +sub link_iso_res() +{ + print "Special iso.res case: "; + my $ooo_res="$OOO_INSTALL/" . $program_dir . "/resource/ooo".$LIBVER.$LANG.".res"; + my $star_res="$OOO_INSTALL/" . $program_dir . "/resource/iso".$LIBVER.$LANG.".res"; + if (-l $ooo_res && -l $star_res) { + if ($dry_run) { + print "link $ooo_res to $star_res"; + } else { + unlink ($star_res); + symlink ($ooo_res, $star_res); + print "clobbered"; + } + } + print "\n"; +} + +# Hack for (renamed) types.rdb (types.db) +sub link_types_rdb() +{ + print "Types.rdb case:"; + my $src = "$OOO_BUILD/offapi/$TARGET/ucr"; + my $dest = "$OOO_INSTALL/" . $program_dir; + do_link ($src, $dest, 'types.db', 'types.rdb'); + print "\n"; +} + +# link installed files back into src tree: +sub link_soffice_bin_files() +{ + my $dest; + my $src = "$OOO_INSTALL/" . $program_dir; + + print "soffice files"; + $dest = "$OOO_BUILD/desktop/$TARGET/bin"; + do_link ($src, $dest, 'soffice', 'soffice.bin', 1); + do_link ($src, $dest, 'bootstraprc', 'bootstraprc', 1); + do_link ($src, $dest, 'intro.bmp', 'intro.bmp', 1); + do_link ("$OOO_INSTALL", "$OOO_BUILD/desktop/$TARGET", 'share', 'share', 1); + + $dest = "$OOO_BUILD/configmgr/$TARGET/lib"; + do_link ($src, $dest, 'configmgrrc', 'configmgrrc', 1); + + print "\n"; +} + +my $a; +my $usage = 0; +for $a (@ARGV) { + +# options + if ($a =~ /--product/) { + $product = 1; + } elsif ($a =~ /--dry-run/) { + $dry_run = 1; + } elsif (($a eq '--help') || ($a eq '-h')) { + $usage = 1; + +# ordered arguments + } elsif (!defined $OOO_INSTALL) { + $OOO_INSTALL = $a; + } elsif (!defined $OOO_BUILD) { + $OOO_BUILD = $a; + } else { + print "Unknown argument '$a'\n"; + $usage = 1; + } +} + +if (!defined $OOO_BUILD && defined $ENV{SRC_ROOT}) { + $OOO_BUILD = $ENV{SRC_ROOT}; +} + +if ($usage || !defined $OOO_INSTALL || !defined $OOO_BUILD) { + printf "Usage: linkoo </path/to/ooo/install> [</path/to/ooo/build/tree>] [--product] [--dry-run]\n"; + exit (1); +} + +substr ($OOO_INSTALL, 0, 1) eq '/' || die "linkoo requires absolute paths ($OOO_INSTALL does not qualify)"; +substr ($OOO_BUILD, 0, 1) eq '/' || die "linkoo requires absolute paths ($OOO_BUILD does not qualify)"; + +-d $OOO_INSTALL || die "No such directory $OOO_INSTALL"; +-w $OOO_INSTALL || die "You need write access to $OOO_INSTALL"; +-d $OOO_BUILD || die "No such directory $OOO_BUILD"; +-d "$OOO_INSTALL/" . $program_dir . "/resource" || die "$OOO_INSTALL doesn't look like an OO install"; + +($TARGET, $LIBVER, $LANG) = sniff_target ($OOO_BUILD); + +evilness ('undo'); + +my $installed_files = build_installed_list ($OOO_INSTALL); + +scan_and_link_files ($OOO_BUILD, $installed_files, $TARGET); +link_iso_res(); +link_types_rdb(); +link_soffice_bin_files(); + +if (!-f "$OOO_INSTALL/" . $program_dir . "/ooenv") { + print "Creating '$OOO_INSTALL/", $program_dir, "/ooenv'\n"; + open ($ooenv, ">$OOO_INSTALL/" . $program_dir . "/ooenv") || die "Can't open $OOO_INSTALL/" . $program_dir . "/ooenv: $!"; + print $ooenv $env_script; + close ($ooenv); +} + +evilness ('do'); + +print "\nlinkoo finished, please don't forget to source ooenv before ./soffice.\n"; diff --git a/solenv/bin/macosx-change-install-names.pl b/solenv/bin/macosx-change-install-names.pl new file mode 100644 index 000000000000..fcda2621abc5 --- /dev/null +++ b/solenv/bin/macosx-change-install-names.pl @@ -0,0 +1,93 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: macosx-change-install-names.pl,v $ +# +# $Revision: 1.6 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +use lib ("$ENV{SOLARENV}/bin/modules"); +use macosxotoolhelper; + +sub action($$$) +{ + my %action = + ('app/UREBIN/URELIB' => '@executable_path/../lib', + 'app/OOO/URELIB' => '@executable_path/../ure-link/lib', + 'app/OOO/OOO' => '@executable_path', + 'app/SDK/URELIB' => '@executable_path/../../ure-link/lib', + 'app/BRAND/URELIB' => '@executable_path/../basis-link/ure-link/lib', + 'app/BRAND/OOO' => '@executable_path/../basis-link/program', + 'app/NONE/URELIB' => '@__VIA_LIBRARY_PATH__', + 'app/NONE/OOO' => '@__VIA_LIBRARY_PATH__', + 'shl/URELIB/URELIB' => '@loader_path', + 'shl/OOO/URELIB' => '@loader_path/../ure-link/lib', + 'shl/OOO/OOO' => '@loader_path', + 'shl/OXT/URELIB' => '@executable_path/urelibs'); + my ($type, $loc1, $loc2) = @_; + my $act = $action{"$type/$loc1/$loc2"}; + die "illegal combination $type/$loc/$2" unless defined $act; + return $act; +} + +@ARGV == 3 || @ARGV >= 2 && $ARGV[0] eq "extshl" or die + 'Usage: app|shl|extshl UREBIN|URELIB|OOO|SDK|BRAND|OXT|NONE <filepath>*'; +$type = shift @ARGV; +$loc = shift @ARGV; +if ($type eq "extshl") +{ + $type = "shl"; + my $change = ""; + foreach $file (@ARGV) + { + otoolD($file) =~ m'^(.*?([^/]+))\n$' or + die "unexpected otool -D output"; + $change .= " -change $1 " . action($type, $loc, $loc) . "/$2"; + $iname{$file} = $2; + } + foreach $file (@ARGV) + { + my $call = "install_name_tool$change -id \@__________________________________________________$loc/$iname{$file} $file"; + system($call) == 0 or die "cannot $call"; + } +} +foreach $file (@ARGV) +{ + my $call = "otool -L $file"; + open(IN, "-|", $call) or die "cannot $call"; + my $change = ""; + while (<IN>) + { + $change .= " -change $1 " . action($type, $loc, $2) . "$3" + if m'^\s*(@_{50}([^/]+)(/.+)) \(compatibility version \d+\.\d+\.\d+, current version \d+\.\d+\.\d+\)\n$'; + } + close(IN); + if ($change ne "") + { + $call = "install_name_tool$change $file"; + system($call) == 0 or die "cannot $call"; + } +} diff --git a/solenv/bin/macosx-create-bundle b/solenv/bin/macosx-create-bundle new file mode 100755 index 000000000000..f4cbeacc20f1 --- /dev/null +++ b/solenv/bin/macosx-create-bundle @@ -0,0 +1,109 @@ +#!/bin/sh +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: macosx-create-bundle,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +# Documentation +# ------------- +# +# The purpose of this script to take Mac OS X executables and shared libraries +# and package them into the required Mac OS X bundle format. +# +# This script has the following usage: +# macosx-create-bundle file1 [file2] ... [fileN] +# +# Note that file1 through fileN can in either of the following formats: +# - A file name +# - A file name and a directory to look for missing files. To use this option, +# use the following format: +# filename=directory +# +# The file argument is the file that you want to package into a Mac OS X +# bundle. Currently, this script will only package executables and shared +# libraries. +# +# The output for each executable will be a bundle named <file>.app and +# the output for each shared library will be a symlink from libfoo.jnilib +# back to libfoo.dylib. +# These output directories will be in the same directory as the executable or +# shared library. + +# Code +# ---- + +# Parse command line arguments +if [ $# = 0 ]; then + printf "macosx-create-bundle: error: incorrect number of arguments\n" >&2 + printf "Usage: macosx-create-bundle file1 [file2] ... [fileN]\n" >&2 + exit 1 +fi + +while [ $# != 0 ]; do + inputfile=`echo "$1" | awk -F= '{print $1}'` + sourcedir=`echo "$1" | awk -F= '{print $2}'` + + shift + + inputfilename=`basename "$inputfile"` + outputdir=`dirname "$inputfile"` + + solverlibdir="$SOLARVERSION/$INPATH/lib" + locallibdir="../../../../lib" + + solverbindir="$SOLARVERSION/$INPATH/bin" + localbindir="../../.." + + # Determine file type + filetype=`file -L "$inputfile"` + + # Create bundle based on file type + if printf "$filetype" | grep -q 'Mach-O executable'; then + + # Do nothing as this step is obsolete + : + + elif printf "$filetype" | grep -q 'Mach-O dynamically linked shared library'; then + # Screen out lib\w+static libraries as they are not used directly + if ! printf "$inputfilename" | grep -q -x -E 'lib\w+static.*\.dylib'; then + # Create jnilib link + inputjnilibname="`basename $inputfilename .dylib`.jnilib" + if [ ! -L "$outputdir/$inputjnilibname" ]; then + rm -Rf "$outputdir/$inputjnilibname" + fi + # Link jnilib + ln -sf "$inputfilename" "$outputdir/$inputjnilibname" + + printf "macosx-create-bundle: $outputdir/$inputjnilibname successfully created\n" + fi + else + printf "macosx-create-bundle: error: file is not an executable or shared library.\n" >&2 + exit 1 + fi +done diff --git a/solenv/bin/macosx-dylib-link-list.pl b/solenv/bin/macosx-dylib-link-list.pl new file mode 100644 index 000000000000..159eb66d782d --- /dev/null +++ b/solenv/bin/macosx-dylib-link-list.pl @@ -0,0 +1,95 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: macosx-dylib-link-list.pl,v $ +# +# $Revision: 1.3 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +use lib ("$ENV{SOLARENV}/bin/modules"); +use macosxotoolhelper; + +sub locate($) +{ + my ($lib) = @_; + my $dir; + foreach $dir (@dirs) + { + my $path = "$dir/$lib"; + if (-e $path) + { + return $path; + } + } + return; +} + +sub handle($$) +{ + my ($from, $to) = @_; + # wrap -dylib_file in -Wl so that hopefully any used tool whatsoever (e.g., + # libtool generated from xmlsec1-1.2.6/configure included in + # libxmlsec/download/xmlsec1-1.2.6.tar.gz:1.3) passes it through to the + # linker: + !($from =~ /,/ || $to =~ /,/) or + die "$from:$to contains commas and cannot go into -Wl"; + print " -Wl,-dylib_file,$from:$to"; + $done{$from} = 1; + push(@todo, $to) if (grep {$_ eq $to} @todo) == 0; +} + +foreach (@ARGV) { push(@dirs, $1) if /^-L(.*)$/; } +foreach (@ARGV) +{ + if (/^-l(.*)$/) + { + my $loc = locate("lib$1.dylib"); + handle($1, $loc) if defined $loc && otoolD($loc) =~ m'^(@.+/.+)\n$'; + } +} +foreach $file (@todo) +{ + my $call = "otool -L $file"; + open(IN, "-|", $call) or die "cannot $call"; + while (<IN>) + { + if (m'^\s*(@.+/([^/]+)) \(compatibility version \d+\.\d+\.\d+, current version \d+\.\d+\.\d+\)\n$') + { + my $full = $1; + my $loc = locate($2); + if (defined $loc) + { + handle($full, $loc) unless defined $done{$full}; + } + else + { + die "unknown $full (from $file)"; + } + } + } + close(IN); +} +print "\n"; diff --git a/solenv/bin/make_download.pl b/solenv/bin/make_download.pl new file mode 100644 index 000000000000..4db9bcb8d0f7 --- /dev/null +++ b/solenv/bin/make_download.pl @@ -0,0 +1,122 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: make_installer.pl,v $ +# +# $Revision: 1.121 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +################# +# use +################# + +use lib ("$ENV{SOLARENV}/bin/modules"); + +use Cwd; +use File::Copy; +use installer::download; +use installer::downloadsigner; +use installer::exiter; +use installer::followme; +use installer::globals; +use installer::logger; +use installer::windows::sign; + +################################################# +# Main program +################################################# + +installer::downloadsigner::getparameter(); +installer::downloadsigner::checkparameter(); + +my $infofilelist = installer::downloadsigner::createproductlist(); +installer::downloadsigner::publishproductlist($infofilelist); + +foreach my $infofilename ( @{$infofilelist} ) +{ + installer::logger::starttime(); + + my $success = 1; + my $do_copy = 1; + my $followmeinfohash = installer::followme::read_followme_info($infofilename); + installer::downloadsigner::setlogfilename(); + + if (( ! $installer::globals::iswindowsbuild ) && ( $installer::globals::dosign )) + { + installer::logger::print_message( "... WARNING: Signing only for Windows platforms active ...\n" ); + } + + installer::logger::include_header_into_logfile("Reading include pathes"); + installer::worker::collect_all_files_from_includepathes($followmeinfohash->{'includepatharray'}); + + if (( $installer::globals::iswindowsbuild ) && ( $installer::globals::dosign )) + { + $followmeinfohash->{'finalinstalldir'} = installer::windows::sign::sign_install_set($followmeinfohash, $do_copy); + + ($success, $followmeinfohash->{'finalinstalldir'}) = installer::worker::analyze_and_save_logfile($followmeinfohash->{'loggingdir'}, + $followmeinfohash->{'finalinstalldir'}, + $followmeinfohash->{'installlogdir'}, + "", + \$followmeinfohash->{'languagestring'}, + $followmeinfohash->{'currentinstallnumber'}); + + if ( ! $success ) { installer::exiter::exit_program("ERROR: Signing installation set failed: $followmeinfohash->{'finalinstalldir'}", "Main"); } + } + + $followmeinfohash->{'finalinstalldir'} = installer::download::create_download_sets($followmeinfohash->{'finalinstalldir'}, + $followmeinfohash->{'includepatharray'}, + $followmeinfohash->{'allvariableshash'}, + $followmeinfohash->{'downloadname'}, + \$followmeinfohash->{'languagestring'}, + $followmeinfohash->{'languagesarray'}); + + ($success, $followmeinfohash->{'finalinstalldir'}) = installer::worker::analyze_and_save_logfile($followmeinfohash->{'loggingdir'}, + $followmeinfohash->{'finalinstalldir'}, + $followmeinfohash->{'installlogdir'}, + "", + \$followmeinfohash->{'languagestring'}, + $followmeinfohash->{'currentinstallnumber'}); + + if (( $success ) && ( $installer::globals::iswindowsbuild ) && ( $installer::globals::dosign )) + { + $do_copy = 0; + $followmeinfohash->{'finalinstalldir'} = installer::windows::sign::sign_install_set($followmeinfohash, $do_copy); + + $followmeinfohash->{'finalinstalldir'} = installer::worker::analyze_and_save_logfile($followmeinfohash->{'loggingdir'}, + $followmeinfohash->{'finalinstalldir'}, + $followmeinfohash->{'installlogdir'}, + "", + \$followmeinfohash->{'languagestring'}, + $followmeinfohash->{'currentinstallnumber'}); + } + + installer::logger::stoptime(); +} + + +#################################### +# Main program end +#################################### diff --git a/solenv/bin/make_ext_update_info.pl b/solenv/bin/make_ext_update_info.pl new file mode 100755 index 000000000000..e3dac8a95cbe --- /dev/null +++ b/solenv/bin/make_ext_update_info.pl @@ -0,0 +1,617 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: make_ext_update_info.pl,v $ +# +# $Revision: 1.3 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +#here the definition for d would be written into dependencies. The reason is that when the event handler +#for the element is called, we can only find out the namespace but not the prefix. So we cannot +#distinguish if the namespace is used because the element was prefixed or because it uses the default +#namespace. +use warnings; +use strict; + +use XML::Parser; +use Getopt::Long; +use Carp; + +sub getUpdateInfoFileName($); +sub writeUpdateInformationData($); +sub findAttribute($$); +sub getNotDefPrefs($$$); +sub collectPrefixes($$$$); +sub determineNsDefinitions($$$); +sub determineNsDefinitionForItem($$$); + +my $inDescription = 0; +my $inDependencies = 0; +my $inIdentifier = 0; +my $inVersion = 0; +my $descNS = "http://openoffice.org/extensions/description/2006"; + my $indent; +my $identifier; +my $version; + +#contains prefixes and the corresponding namespaces which are used in the <dependencies> +#element and all children of the description.xml +my @usedNsInDependencies; + +#Maps prefix to namespaces which are valid in <dependencies>. That is, they are +#either defined in <dependencies> or in the hirarchy above <dependencies> +my %validPrefsInDep; +#Contains the prefixes which are defined in <dependencies> +my @newPrefsInDep; +#Contains the prefixes/namespaces which need to be defined in <dependencies> but which are currently +#not. For example a prefix is defined in the parent and is used in a child of <dependencies> +my %notDefInDep; + +#prefix used in start and end element +my $prefix; + +#The default namespace valid in <dependencies> +my $defNsInDep; +#The prefix which we use for the default namespace used in <dependencies> +my $generatedPrefix; + +my $helptext = +"make_ext_update_info.pl produces an update information file for an extension. ". +"It will use a dummy URL as URL for the extension update unless a URL has been ". +"provided with the --update_url option. The name of the update ". +"information file, which must be provided with the --out switch, should be formed ". +"according to this scheme: \n\n". +"extension_identifier.update.xml\n\n". +"extension_identifier should correspond to the extension identifier. In some cases ". +"this may not be possible because the identifier may contain characters which are not ". +"allowd in file names.\n\n". +"usage:\n". +"perl make_ext_update_info.pl [--help][--update_url url] --out update_information_file description.xml \n\n". +"Options: \n". +"--help - prints the help message and exits \n". +"--out file - the update information file to be written including the path \n". +"--update-url url - inserts the url under the <update-download> element. It may be necessary to enclose the urls in quotes in case they contain characters such as \"?\". ". +"It can be used multiple times\n\n"; + +#handling of arguments +my $help = 0; +my $out; +my @update_urls; +if (!GetOptions('help|?' => \$help, + 'out=s' => \$out, + 'update-url=s'=> \@update_urls)) +{ + print $helptext; + exit -1; +} +my $cArgs = scalar @ARGV; +die "You need to provide a description.xml\n\n$helptext" if $cArgs ==0; +die "You need to provide the name of the update information file ". + "with the --out switch.\n" unless ($out); +die "Too many arguments. \n\n$helptext" if $cArgs > 1; +print $helptext if $help; + + +#open the update information file for writing +my $FH; +open $FH, "> $out" or die $!; + +#write the xml header and root element +print $FH '<?xml version="1.0" encoding="UTF-8"?>', "\n"; +print $FH '<description xmlns="http://openoffice.org/extensions/update/2006"', "\n"; +print $FH ' xmlns:xlink="http://www.w3.org/1999/xlink">', "\n"; + +#obtain from description.xml the data for the update information +writeUpdateInformationData($ARGV[0]); +#We will die if there is no <version> or <identifier> in the description.xml +die "Error: The description.xml does not contain a <identifier> element.\n" unless $identifier; +die "Error: The description.xml does not contain a <version> element. \n" unless $version; + +#write the write the update-download element and the children. +#the indention of <update-download> corresponds to that of <version> +print $FH ' 'x$indent, '<update-download>', "\n"; +#check if update-urls have been provided through --update-url option +if (scalar @update_urls) +{ + my $urlIndent = $indent > 8 ? 8 : 2 * $indent; + #use provided urls + for (@update_urls) + { + print $FH ' 'x$urlIndent, '<src xlink:href="'.$_.'" />', "\n"; + } +} +else +{ + #use dummy update url + print $FH ' 'x8, '<src xlink:href="http://extensions.openoffice.org/testarea/dummy.oxt" />', "\n"; +} +print $FH ' 'x$indent, '</update-download>', "\n"; + +print $FH '</description>', "\n"; +close $FH; + +exit 0; + + + +sub start_handler +{ + my $parser = shift; + my $name = shift; + + if ($name eq "description" + && $descNS eq $parser->namespace($name)) + { + $inDescription = 1; + } + elsif ($inDescription + && $name eq "version" + && $descNS eq $parser->namespace($name)) + { + $inVersion = 1; + $version = 1; + $indent = $parser->current_column(); + print $FH " "x$indent, $parser->original_string(); + } + elsif ($inDescription + && $name eq "identifier" + && $descNS eq $parser->namespace($name)) + { + $inIdentifier = 1; + $identifier = 1; + print $FH " "x$parser->current_column(), $parser->original_string(); + } + elsif ($inDescription + && $name eq "dependencies" + && $descNS eq $parser->namespace($name)) + { + $inDependencies = 1; + my $dep = $parser->original_string(); + #add the additional namespace definitions, which we have discovered during the first + #parsing + #cut of the closing > or /> from the start element, so we can append the namespace definitions + $dep =~ /(\s*<.*) ((\s*\/>)|(\s*>))/x; + my $dep1 = $1; + $dep1.= " xmlns:".$_.'="'.$notDefInDep{$_}.'"' for (keys %notDefInDep); + $dep1.= $2; + print $FH " "x$parser->current_column(), $dep1; + } + elsif ($inDependencies) + { + #$prefix is global because we need to use it in the end element as well. + $prefix = ""; + my $fullString; + my $orig = $parser->original_string(); + #Split up the string so we can insert the prefix for the element. + # <OpenOffice.org-minimal-version> + # <d:OpenOffice.org-minimal-version> + $orig=~/(\s*<)(.*?)\s/x; + #in $2 is the element name, look for the prefix + if ($2 !~/(.*?):/ && $parser->namespace($name)) { + #no prefix, that is element uses default namespace. + #Now check if the default namespace in <dependencies> is the same as the one in this + #element. If not, then the default ns was defined "after" <dependencies>. Because all + #children of <dependencies> are copied into the update information, so will this default + #namespace definition. Hence this element will have the same default namespace in the + #update information. + my $defNsDep = $validPrefsInDep{"#default"}; + #we must have #default, see the if statement above + my $defNsCur = $parser->expand_ns_prefix("#default"); + + if ($defNsDep eq $defNsCur) { + #Determine if there is in <dependency> a prefix defined (only valid there and need not + #directly defined in this element). If there is no prefix defined then we will + #add a new definition to <dependencies>. + for (keys %validPrefsInDep) { + if (($validPrefsInDep{$_} eq $defNsDep) && $_ ne "#default") { + $prefix = $_; last; + } + } + if (! $prefix) { + #If there was no prefix, we will add new prefix definition to <dependency> + #Which prefix this is has been determined during the first parsing. + for (keys %notDefInDep) { + if (($notDefInDep{$_} eq $defNsCur) && $_ ne "#default") { + $prefix = $_; last; + } + } + } + #die if we have no prefix + confess "No prefix defined for default namespace " unless $prefix; + #get the full part after < + $orig=~/(\s*<)(.*)/x; + $fullString= $1.$prefix.":".$2; + } + + } + $fullString = $orig unless $fullString; + + # We record anything within <dependencies> </dependencies>. + print $FH $fullString; + } +} + +sub end_handler +{ + my $parser = shift; + my $name = shift; + + if ($name eq "description" + && $descNS eq $parser->namespace($name)) + { + $inDescription = 0; + } + elsif ($inDescription + && $name eq "version" + && $descNS eq $parser->namespace($name)) + { + $inVersion = 0; + print $FH $parser->original_string(), "\n"; + } + elsif ($inDescription + && $name eq "identifier" + && $descNS eq $parser->namespace($name)) + { + $inIdentifier = 0; + print $FH $parser->original_string(), "\n"; + } + elsif($inDescription + && $name eq "dependencies" + && $descNS eq $parser->namespace($name)) + { + $inDependencies = 0; + print $FH $parser->original_string(), "\n"; + } + elsif ($inDependencies) + { + my $orig = $parser->original_string(); + #$orig is empty if we have tags like this: <name /> + if ($orig && $prefix) { + $orig=~/(\s*<\/)(.*)/x; + $orig= $1.$prefix.":".$2; + } + print $FH $orig; + } +} + +#We write the complete content between start and end tags of +# <identifier>, <version>, <dependencies> +sub default_handler +{ + my $parser = shift; + my $name = shift; + if ($inIdentifier || $inVersion) { + print $FH $parser->original_string(); + } elsif ($inDependencies) { + print $FH $parser->original_string(); + } + +} # End of default_handler + +#sax handler used for the first parsing to recognize the used prefixes in <dependencies > and its +#children and to find out if we need to define a new prefix for the current default namespace. +sub start_handler_infos +{ + my $parser = shift; + my $name = shift; + if ($name eq "description" + && $descNS eq $parser->namespace($name)) { + $inDescription = 1; + } + elsif ($inDescription + && $name eq "dependencies" + && $descNS eq $parser->namespace($name)) { + $inDependencies = 1; + #build the map of prefix/namespace which are valid in <dependencies> + my @cur = $parser->current_ns_prefixes(); + for (@cur) { + $validPrefsInDep{$_} = $parser->expand_ns_prefix($_); + } + #remember the prefixes defined in <dependencies> + @newPrefsInDep = $parser->new_ns_prefixes(); + + collectPrefixes($parser, $name, \@_, \@usedNsInDependencies); + return if $generatedPrefix; + + #determine if need to create a new prefix for the current element if it uses a default ns. + #Split up the string so we can see if there is a prefix used + # <OpenOffice.org-minimal-version> + # <d:OpenOffice.org-minimal-version> + my $orig = $parser->original_string(); + $orig=~/(\s*<)(.*?)\s/x; + #in $2 is the element name, look for the prefix + if ($2 !~/(.*?):/ && $parser->namespace($name)) { + #no prefix, that is element uses default namespace. + #Now check if the default namespace in <dependencies> is the same as the one in this + #element. If not, then the default ns was defined "after" <dependencies>. Because all + #children of <dependencies> are copied into the update information, so will this default + #namespace definition. Hence this element will have the same default namespace in the + #update information. + my $defNsDep = $validPrefsInDep{"#default"}; + #we must have #default, see the if statement above + my $defNsCur = $parser->expand_ns_prefix("#default"); + + if ($defNsDep eq $defNsCur) { + #Determine if there is in <dependency> a prefix defined (only valid there and need not + #directly defined in this element). If there is no prefix defined then we will + #add a new definition to <dependencies>. + for (keys %validPrefsInDep) { + if (($validPrefsInDep{$_} eq $defNsDep) && $_ ne "#default") { + $prefix = $_; last; + } + } + + if (! $prefix) { + + #define a new prefix + #actually there can be only onle prefix, which is the case when the element + #uses the same default namespace as <dependencies> otherwise, the default + #namespace was redefined by the children of <dependencies>. These are completely + #copied and still valid in the update information file + $generatedPrefix = "a"; + $defNsInDep = $defNsDep; + } + } + } + + } + elsif ($inDependencies) { + determineNsDefinitions($parser, $name, \@_); + collectPrefixes($parser, $name, \@_, \@usedNsInDependencies); + } +} +#sax handler used for the first parsing to recognize the used prefixes in <dependencies > and its +#children +sub end_handler_infos +{ + my $parser = shift; + my $name = shift; + + if ($name eq "description" + && $descNS eq $parser->namespace($name)) { + $inDescription = 0; + } + elsif($inDescription + && $name eq "dependencies" + && $descNS eq $parser->namespace($name)) { + $inDependencies = 0; + } +} + +sub writeUpdateInformationData($) +{ + my $desc = shift; + { + #parse description xml to collect information about all used + #prefixes and names within <dependencies> + + my $parser = new XML::Parser(ErrorContext => 2, + Namespaces => 1); + $parser->setHandlers(Start => \&start_handler_infos, + End => \&end_handler_infos); + + $parser->parsefile($desc); + + + } + #remove duplicates in the array containing the prefixes + if ($generatedPrefix) { + my %hashtmp; + @usedNsInDependencies = grep(!$hashtmp{$_}++, @usedNsInDependencies); + + #check that the prefix for the default namespace in <dependencies> does not clash + #with any other prefixes + my $clash; + do { + $clash = 0; + for (@usedNsInDependencies) { + if ($_ eq $generatedPrefix) { + $generatedPrefix++; + $clash = 1; last; + } + } + } while ($clash); + $notDefInDep{$generatedPrefix} = $defNsInDep; + } + #if $notDefInDep contains the prefix #default then we need to add the generated prefix as well + + #add the special prefix for the default namespace into the map of prefixes that will be + #added to the <dependencies> element in the update information file + + + ($inDependencies, $inDescription) = (0,0); + { + my $parser = new XML::Parser(ErrorContext => 2, + Namespaces => 1); + $parser->setHandlers( + Start => \&start_handler, + End => \&end_handler, + Default => \&default_handler); + $parser->parsefile($desc); + } +} + +# param 1: name of the attribute we look for +# param 2: array of name value pairs, the first subscript is the attribute and the second +# is the value. +sub findAttribute($$) +{ + my ($name, $args_r) = @_; + my @args = @{$args_r}; + my $value; + while (my $attr = shift(@args)) + { + if ($attr eq $name) { + $value = shift(@args); + die "href attribut has no valid URL" unless $value; + last; + } else { # shift away the following value for the attribute + shift(@args); + } + } + return $value; +} + +#collect the prefixes used in an xml element +#param 1: parser, +#param 2: element name, +#param 3: array of name and values of attributes +#param 4: out parameter, the array containing the prefixes +sub collectPrefixes($$$$) +{ + my $parser = shift; + my $name = shift; + my $attr_r = shift; + my $out_r = shift; + #get the prefixes which are currently valid + my @cur = $parser->current_ns_prefixes(); + my %map_ns; + #get the namespaces for the prefixes + for (@cur) { + if ($_ eq '#default') { + next; + } + my $ns = $parser->expand_ns_prefix($_); + $map_ns{$ns} = $_; + } + #investigat ns of element + my $pref = $map_ns{$parser->namespace($name)}; + push(@{$out_r}, $pref) if $pref; + #now go over the attributes + + while (my $attr = shift(@{$attr_r})) { + my $ns = $parser->namespace($attr); + if (! $ns) { + shift(@{$attr_r}); + next; + } + $pref = $map_ns{$ns}; + push( @{$out_r}, $pref) if $pref; + shift(@{$attr_r}); + } + #also add newly defined prefixes + my @newNs = $parser->new_ns_prefixes(); + for (@newNs) { + if ($_ eq '#default') { + next; + } + push (@{$out_r}, $_); + } +} + +#The function is called for each child element of dependencies. It finds out the prefixes +#which are used by the children and which are defined by the parents of <dependencies>. These +#would be lost when copying the children of <dependencies> into the update information file. +#Therefore these definitions are collected so that they then can be written in the <dependencies> +#element of the update information file. +#param 1: parser +#param 2: namsepace +#param 3: the @_ received in the start handler +sub determineNsDefinitions($$$) +{ + my ($parser, $name, $attr_r) = @_; + my @attr = @{$attr_r}; + + determineNsDefinitionForItem($parser, $name, 1); + + while (my $attr = shift(@attr)) { + determineNsDefinitionForItem($parser, $attr, 0); + shift @attr; + } +} + +#do not call this function for the element that does not use a prefix +#param 1: parser +#param 2: name of the element or attribute +#param 3: 1 if called for an elment name and 0 when called for attribue +sub determineNsDefinitionForItem($$$) +{ + my ($parser, $name) = @_; + my $ns = $parser->namespace($name); + if (! $ns) { + return; + } + #If the namespace was not kwown in <dependencies> then it was defined in one of its children + #or in this element. Then we are done since this namespace definition is copied into the + #update information. + my $bNsKnownInDep; + for ( keys %validPrefsInDep) { + if ( $validPrefsInDep{$_} eq $ns) { + $bNsKnownInDep = 1; + last; + } + } + #If the namespace of the current element is known in <dependencies> then check if the same + #prefix is used. If not, then the prefix was defined in one of the children of <dependencies> + #and was assigned the same namespace. Because we copy of children into the update information, + #this definition is also copied. + if ($bNsKnownInDep) { + #create a map of currently valid prefix/namespace + my %curPrefToNs; + my @curNs = $parser->current_ns_prefixes(); + for (@curNs) { + $curPrefToNs{$_} = $parser->expand_ns_prefix($_); + } + #find the prefix used in <dependencies> to define the namespace of the current element + my $validDepPref; + for (keys %validPrefsInDep) { + if ($validPrefsInDep{$_} eq $ns) { + #ignore #default + next if $_ eq "#default"; + $validDepPref = $_; + last; + } + } + #find the prefix defined in the current element used for the namespace of the element + my $curPref; + for (keys %curPrefToNs) { + if ($curPrefToNs{$_} eq $ns) { + #ignore #default + next if $_ eq "#default"; + $curPref = $_; + last; + } + } + if ($curPref && $validDepPref && ($curPref eq $validDepPref)) { + #If the prefixes and ns are the same, then the prefix definition of <dependencies> or its + #parent can be used. However, we need to find out which prefixed are NOT defined in + #<dependencies> so we can add them to it when we write the update information. + my $bDefined = 0; + for (@newPrefsInDep) { + if ($curPref eq $_) { + $bDefined = 1; + last; + } + } + if (! $bDefined) { + $notDefInDep{$curPref} = $ns; + } + } + } +} diff --git a/solenv/bin/make_installer.pl b/solenv/bin/make_installer.pl new file mode 100644 index 000000000000..69fccd60e1a7 --- /dev/null +++ b/solenv/bin/make_installer.pl @@ -0,0 +1,2353 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: make_installer.pl,v $ +# +# $Revision: 1.121 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +################# +# use +################# + +use lib ("$ENV{SOLARENV}/bin/modules"); + +use Cwd; +use File::Copy; +use installer::archivefiles; +use installer::control; +use installer::converter; +use installer::copyproject; +use installer::download; +use installer::environment; +use installer::epmfile; +use installer::exiter; +use installer::files; +use installer::followme; +use installer::globals; +use installer::javainstaller; +use installer::languagepack; +use installer::languages; +use installer::logger; +use installer::mail; +use installer::packagelist; +use installer::packagepool; +use installer::parameter; +use installer::pathanalyzer; +use installer::profiles; +use installer::regmerge; +use installer::scppatchsoname; +use installer::scpzipfiles; +use installer::scriptitems; +use installer::servicesfile; +use installer::setupscript; +use installer::simplepackage; +use installer::sorter; +use installer::strip; +use installer::substfilenamefiles; +use installer::upx; +use installer::systemactions; +use installer::windows::assembly; +use installer::windows::binary; +use installer::windows::component; +use installer::windows::createfolder; +use installer::windows::directory; +use installer::windows::feature; +use installer::windows::featurecomponent; +use installer::windows::file; +use installer::windows::font; +use installer::windows::icon; +use installer::windows::idtglobal; +use installer::windows::inifile; +use installer::windows::java; +use installer::windows::media; +use installer::windows::mergemodule; +use installer::windows::msiglobal; +use installer::windows::msp; +use installer::windows::patch; +use installer::windows::property; +use installer::windows::removefile; +use installer::windows::registry; +use installer::windows::selfreg; +use installer::windows::shortcut; +use installer::windows::strip; +use installer::windows::update; +use installer::windows::upgrade; +use installer::worker; +use installer::xpdinstaller; +use installer::ziplist; + +################################################# +# Main program +################################################# + +################################################# +# Part 1: The platform independent part +################################################# + +################################################# +# Part 1a: The language independent part +################################################# + +installer::logger::starttime(); + +######################################### +# Checking the environment and setting +# most important variables +######################################### + +installer::logger::print_message( "... checking environment variables ...\n" ); +my $environmentvariableshashref = installer::control::check_system_environment(); + +installer::environment::set_global_environment_variables($environmentvariableshashref); + +################################# +# Check and output of parameter +################################# + +installer::parameter::saveparameter(); +installer::parameter::getparameter(); + +# debugging can start after function "getparameter" +if ( $installer::globals::debug ) { installer::logger::debuginfo("\nPart 1: The platform independent part\n"); } +if ( $installer::globals::debug ) { installer::logger::debuginfo("\nPart 1a: The language independent part\n"); } + +installer::parameter::control_fundamental_parameter(); +installer::parameter::setglobalvariables(); +installer::parameter::control_required_parameter(); + +if (!($installer::globals::languages_defined_in_productlist)) { installer::languages::analyze_languagelist(); } +installer::parameter::outputparameter(); + +installer::control::check_updatepack(); + +$installer::globals::build = uc($installer::globals::build); # using "SRC680" instead of "src680" + +###################################### +# Creating the log directory +###################################### + +my $loggingdir = installer::systemactions::create_directories("logging", ""); +$loggingdir = $loggingdir . $installer::globals::separator; +$installer::globals::exitlog = $loggingdir; + +my $installdir = ""; +my $currentdir = cwd(); +my $shipinstalldir = ""; +my $current_install_number = ""; + +###################################### +# Checking the system requirements +###################################### + +installer::logger::print_message( "... checking required files ...\n" ); +installer::control::check_system_path(); + +my $pathvariableshashref = installer::environment::create_pathvariables($environmentvariableshashref); + +############################################### +# Checking saved setting for Windows patches +############################################### + +if (( $installer::globals::iswindowsbuild ) && ( $installer::globals::prepare_winpatch )) { installer::windows::msiglobal::read_saved_mappings(); } + +################################################### +# Analyzing the settings and variables in zip.lst +################################################### + +installer::logger::globallog("zip list file: $installer::globals::ziplistname"); + +my $ziplistref = installer::files::read_file($installer::globals::ziplistname); + +installer::logger::print_message( "... analyzing $installer::globals::ziplistname ... \n" ); + +my ($productblockref, $parent) = installer::ziplist::getproductblock($ziplistref, $installer::globals::product, 1); # product block from zip.lst +if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "productblock.log" ,$productblockref); } + +my ($settingsblockref, undef) = installer::ziplist::getproductblock($productblockref, "Settings", 0); # settings block from zip.lst +if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "settingsblock1.log" ,$settingsblockref); } + +$settingsblockref = installer::ziplist::analyze_settings_block($settingsblockref); # select data from settings block in zip.lst +if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "settingsblock2.log" ,$settingsblockref); } + +my $allsettingsarrayref = installer::ziplist::get_settings_from_ziplist($settingsblockref); +if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "allsettings1.log" ,$allsettingsarrayref); } + +my $allvariablesarrayref = installer::ziplist::get_variables_from_ziplist($settingsblockref); +if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "allvariables1.log" ,$allvariablesarrayref); } + +my ($globalproductblockref, undef) = installer::ziplist::getproductblock($ziplistref, $installer::globals::globalblock, 0); # global product block from zip.lst +if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "globalproductblock.log" ,$globalproductblockref); } + +while (defined $parent) +{ + my $parentproductblockref; + ($parentproductblockref, $parent) = installer::ziplist::getproductblock( + $ziplistref, $parent, 1); + my ($parentsettingsblockref, undef) = installer::ziplist::getproductblock( + $parentproductblockref, "Settings", 0); + $parentsettingsblockref = installer::ziplist::analyze_settings_block( + $parentsettingsblockref); + my $allparentsettingsarrayref = + installer::ziplist::get_settings_from_ziplist($parentsettingsblockref); + my $allparentvariablesarrayref = + installer::ziplist::get_variables_from_ziplist($parentsettingsblockref); + $allsettingsarrayref = + installer::converter::combine_arrays_from_references_first_win( + $allsettingsarrayref, $allparentsettingsarrayref) + if $#{$allparentsettingsarrayref} > -1; + $allvariablesarrayref = + installer::converter::combine_arrays_from_references_first_win( + $allvariablesarrayref, $allparentvariablesarrayref) + if $#{$allparentvariablesarrayref} > -1; +} + +if ( $#{$globalproductblockref} > -1 ) +{ + my ($globalsettingsblockref, undef) = installer::ziplist::getproductblock($globalproductblockref, "Settings", 0); # settings block from zip.lst + if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "globalsettingsblock1.log" ,$globalsettingsblockref); } + + $globalsettingsblockref = installer::ziplist::analyze_settings_block($globalsettingsblockref); # select data from settings block in zip.lst + if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "globalsettingsblock2.log" ,$globalsettingsblockref); } + + my $allglobalsettingsarrayref = installer::ziplist::get_settings_from_ziplist($globalsettingsblockref); + if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "allglobalsettings1.log" ,$allglobalsettingsarrayref); } + + my $allglobalvariablesarrayref = installer::ziplist::get_variables_from_ziplist($globalsettingsblockref); + if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "allglobalvariables1.log" ,$allglobalvariablesarrayref); } + + if ( $#{$allglobalsettingsarrayref} > -1 ) { $allsettingsarrayref = installer::converter::combine_arrays_from_references_first_win($allsettingsarrayref, $allglobalsettingsarrayref); } + if ( $#{$allglobalvariablesarrayref} > -1 ) { $allvariablesarrayref = installer::converter::combine_arrays_from_references_first_win($allvariablesarrayref, $allglobalvariablesarrayref); } +} + +$allsettingsarrayref = installer::ziplist::remove_multiples_from_ziplist($allsettingsarrayref); # the settings from the zip.lst +if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "allsettings2.log" ,$allsettingsarrayref); } + +$allvariablesarrayref = installer::ziplist::remove_multiples_from_ziplist($allvariablesarrayref); +if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "allvariables2.log" ,$allvariablesarrayref); } + +installer::ziplist::replace_variables_in_ziplist_variables($allvariablesarrayref); +if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "allvariables2a.log" ,$allvariablesarrayref); } + +my $allvariableshashref = installer::converter::convert_array_to_hash($allvariablesarrayref); # the variables from the zip.lst +if ( $installer::globals::globallogging ) { installer::files::save_hash($loggingdir . "allvariables3.log", $allvariableshashref); } + +installer::ziplist::set_default_productversion_if_required($allvariableshashref); +if ( $installer::globals::globallogging ) { installer::files::save_hash($loggingdir . "allvariables3a.log", $allvariableshashref); } + +installer::ziplist::add_variables_to_allvariableshashref($allvariableshashref); +if ( $installer::globals::globallogging ) { installer::files::save_hash($loggingdir . "allvariables3b.log", $allvariableshashref); } + +######################################################## +# Check if this is simple packaging mechanism +######################################################## + +installer::simplepackage::check_simple_packager_project($allvariableshashref); + +#################################################################### +# setting global variables +#################################################################### + +installer::control::set_addchildprojects($allvariableshashref); +installer::control::set_addjavainstaller($allvariableshashref); +installer::control::set_addsystemintegration($allvariableshashref); + +######################################################## +# Re-define logging dir, after all variables are set +######################################################## + +my $oldloggingdir = $loggingdir; +installer::systemactions::remove_empty_directory($oldloggingdir); +$loggingdir = installer::systemactions::create_directories("logging", ""); +$loggingdir = $loggingdir . $installer::globals::separator; +$installer::globals::exitlog = $loggingdir; + +# checking, whether this is an opensource product + +if (!($installer::globals::is_copy_only_project)) { installer::ziplist::set_manufacturer($allvariableshashref); } + +############################################## +# Checking version of makecab.exe +############################################## + +if ( $installer::globals::iswindowsbuild ) { installer::control::check_makecab_version(); } + +########################################################## +# Getting the include path from the settings in zip list +########################################################## + +my $includepathref = installer::ziplist::getinfofromziplist($allsettingsarrayref, "include"); +if ( $$includepathref eq "" ) +{ + installer::exiter::exit_program("ERROR: Definition for \"include\" not found in $installer::globals::ziplistname", "Main"); +} + +my $includepatharrayref = installer::converter::convert_stringlist_into_array($includepathref, ","); +if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "allpatharray1.log" ,$includepatharrayref); } + +installer::ziplist::replace_all_variables_in_pathes($includepatharrayref, $pathvariableshashref); +if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "allpatharray2.log" ,$includepatharrayref); } + +installer::ziplist::replace_minor_in_pathes($includepatharrayref); +if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "allpatharray3.log" ,$includepatharrayref); } + +installer::ziplist::replace_packagetype_in_pathes($includepatharrayref); +if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "allpatharray3a.log" ,$includepatharrayref); } + +installer::ziplist::resolve_relative_pathes($includepatharrayref); +if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "allpatharray3b.log" ,$includepatharrayref); } + +installer::ziplist::remove_ending_separator($includepatharrayref); +if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "allpatharray3c.log" ,$includepatharrayref); } + +############################################## +# Collecting all files from all include +# pathes in global hashes. +############################################## + +installer::worker::collect_all_files_from_includepathes($includepatharrayref); + +############################################## +# Analyzing languages in zip.lst if required +# Probably no longer used. +############################################## + +if ($installer::globals::languages_defined_in_productlist) { installer::languages::get_info_about_languages($allsettingsarrayref); } + +##################################### +# Windows requires the encoding list +##################################### + +if ( $installer::globals::iswindowsbuild ) { installer::control::read_encodinglist($includepatharrayref); } + +##################################################################### +# Including additional inc files for variable settings, if defined +##################################################################### + +if ( $allvariableshashref->{'ADD_INCLUDE_FILES'} ) { installer::worker::add_variables_from_inc_to_hashref($allvariableshashref, $includepatharrayref); } + +################################################ +# Disable xpd installer, if SOLAR_JAVA not set +################################################ + +installer::control::check_java_for_xpd($allvariableshashref); + +##################################### +# Analyzing the setup script +##################################### + +if ($installer::globals::setupscript_defined_in_productlist) { installer::setupscript::set_setupscript_name($allsettingsarrayref, $includepatharrayref); } + +installer::logger::globallog("setup script file: $installer::globals::setupscriptname"); + +installer::logger::print_message( "... analyzing script: $installer::globals::setupscriptname ... \n" ); + +my $setupscriptref = installer::files::read_file($installer::globals::setupscriptname); # Reading the setup script file + +# Resolving variables defined in the zip list file into setup script +# All the variables are defined in $allvariablesarrayref + +installer::scpzipfiles::replace_all_ziplistvariables_in_file($setupscriptref, $allvariableshashref); +if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "setupscript1.log" ,$setupscriptref); } + +# Resolving %variables defined in the installation object + +my $allscriptvariablesref = installer::setupscript::get_all_scriptvariables_from_installation_object($setupscriptref); +if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "setupscriptvariables1.log" ,$allscriptvariablesref); } + +installer::setupscript::add_lowercase_productname_setupscriptvariable($allscriptvariablesref); +if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "setupscriptvariables2.log" ,$allscriptvariablesref); } + +installer::setupscript::resolve_lowercase_productname_setupscriptvariable($allscriptvariablesref); +if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "setupscriptvariables3.log" ,$allscriptvariablesref); } + +$setupscriptref = installer::setupscript::replace_all_setupscriptvariables_in_script($setupscriptref, $allscriptvariablesref); +if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "setupscript2.log" ,$setupscriptref); } + +# Adding all variables defined in the installation object into the hash of all variables. +# This is needed if variables are defined in the installation object, but not in the zip list file. +# If there is a definition in the zip list file and in the installation object, the installation object is more important + +installer::setupscript::add_installationobject_to_variables($allvariableshashref, $allscriptvariablesref); +if ( $installer::globals::globallogging ) { installer::files::save_hash($loggingdir . "allvariables4.log", $allvariableshashref); } + +# Adding also all variables, that must be included into the $allvariableshashref. +installer::setupscript::add_forced_properties($allvariableshashref); +if ( $installer::globals::globallogging ) { installer::files::save_hash($loggingdir . "allvariables5.log", $allvariableshashref); } + +installer::scpzipfiles::replace_all_ziplistvariables_in_file($setupscriptref, $allvariableshashref); +if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "setupscript3.log" ,$setupscriptref); } + +installer::logger::log_hashref($allvariableshashref); + +installer::logger::print_message( "... analyzing directories ... \n" ); + +# Collect all directories in the script to get the destination dirs + +my $dirsinproductarrayref = installer::setupscript::get_all_items_from_script($setupscriptref, "Directory"); +if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productdirectories1.log", $dirsinproductarrayref); } + +if ( $allvariableshashref->{'SHIFT_BASIS_INTO_BRAND_LAYER'} ) { $dirsinproductarrayref = installer::scriptitems::shift_basis_directory_parents($dirsinproductarrayref); } +if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productdirectories1a.log", $dirsinproductarrayref); } + +installer::scriptitems::resolve_all_directory_names($dirsinproductarrayref); +if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productdirectories2.log", $dirsinproductarrayref); } + +installer::logger::print_message( "... analyzing files ... \n" ); + +my $filesinproductarrayref = installer::setupscript::get_all_items_from_script($setupscriptref, "File"); +if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles1.log", $filesinproductarrayref); } + +$filesinproductarrayref = installer::scriptitems::remove_delete_only_files_from_productlists($filesinproductarrayref); +if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles2.log", $filesinproductarrayref); } + +if (( ! $installer::globals::iswindowsbuild ) && + ( ! $installer::globals::islinuxrpmbuild ) && + ( ! $installer::globals::islinuxdebbuild ) && + ( ! $installer::globals::issolarispkgbuild ) && + ( $installer::globals::packageformat ne "installed" ) && + ( $installer::globals::packageformat ne "dmg" ) && + ( $installer::globals::packageformat ne "archive" )) + { installer::control::check_oxtfiles($filesinproductarrayref); } + +if ($installer::globals::product =~ /suite/i ) { $filesinproductarrayref = installer::scriptitems::remove_notinsuite_files_from_productlists($filesinproductarrayref); } +if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles2aa.log", $filesinproductarrayref); } + +if (! $installer::globals::languagepack) +{ + $filesinproductarrayref = installer::scriptitems::remove_Languagepacklibraries_from_Installset($filesinproductarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles2b.log", $filesinproductarrayref); } +} + +if (! $installer::globals::patch) +{ + $filesinproductarrayref = installer::scriptitems::remove_patchonlyfiles_from_Installset($filesinproductarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles2c.log", $filesinproductarrayref); } +} + +if (! $installer::globals::tab) +{ + $filesinproductarrayref = installer::scriptitems::remove_tabonlyfiles_from_Installset($filesinproductarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles2c.log", $filesinproductarrayref); } +} + +if (( $installer::globals::packageformat ne "installed" ) && ( $installer::globals::packageformat ne "archive" )) +{ + $filesinproductarrayref = installer::scriptitems::remove_installedproductonlyfiles_from_Installset($filesinproductarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles2cc.log", $filesinproductarrayref); } +} + +installer::logger::print_message( "... analyzing scpactions ... \n" ); + +my $scpactionsinproductarrayref = installer::setupscript::get_all_items_from_script($setupscriptref, "ScpAction"); +if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productscpactions1.log", $scpactionsinproductarrayref); } + +if (( ! $allvariableshashref->{'XPDINSTALLER'} ) || ( ! $installer::globals::isxpdplatform )) +{ + $scpactionsinproductarrayref = installer::scriptitems::remove_Xpdonly_Items($scpactionsinproductarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productscpactions1a.log", $scpactionsinproductarrayref); } +} + +# $scpactionsinproductarrayref = installer::scriptitems::remove_scpactions_without_name($scpactionsinproductarrayref); +# if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productscpactions2.log", $scpactionsinproductarrayref); } + +installer::scriptitems::change_keys_of_scpactions($scpactionsinproductarrayref); +if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productscpactions2.log", $scpactionsinproductarrayref); } + +installer::logger::print_message( "... analyzing shortcuts ... \n" ); + +my $linksinproductarrayref = installer::setupscript::get_all_items_from_script($setupscriptref, "Shortcut"); +if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productlinks1.log", $linksinproductarrayref); } + +installer::logger::print_message( "... analyzing unix links ... \n" ); + +my $unixlinksinproductarrayref = installer::setupscript::get_all_items_from_script($setupscriptref, "Unixlink"); +if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "unixlinks1.log", $unixlinksinproductarrayref); } + +# $unixlinksinproductarrayref = installer::scriptitems::filter_layerlinks_from_unixlinks($unixlinksinproductarrayref); +# if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "unixlinks1b.log", $unixlinksinproductarrayref); } + +installer::logger::print_message( "... analyzing profile ... \n" ); + +my $profilesinproductarrayref = installer::setupscript::get_all_items_from_script($setupscriptref, "Profile"); +if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "profiles1.log", $profilesinproductarrayref); } + +installer::logger::print_message( "... analyzing profileitems ... \n" ); + +my $profileitemsinproductarrayref = installer::setupscript::get_all_items_from_script($setupscriptref, "ProfileItem"); +if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "profileitems1.log", $profileitemsinproductarrayref); } + +my $folderinproductarrayref; +my $folderitemsinproductarrayref; +my $registryitemsinproductarrayref; +my $windowscustomactionsarrayref; +my $mergemodulesarrayref; + +if ( $installer::globals::iswindowsbuild ) # Windows specific items: Folder, FolderItem, RegistryItem, WindowsCustomAction +{ + installer::logger::print_message( "... analyzing folders ... \n" ); + + $folderinproductarrayref = installer::setupscript::get_all_items_from_script($setupscriptref, "Folder"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "folder1.log", $folderinproductarrayref); } + + installer::logger::print_message( "... analyzing folderitems ... \n" ); + + $folderitemsinproductarrayref = installer::setupscript::get_all_items_from_script($setupscriptref, "FolderItem"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "folderitems1.log", $folderitemsinproductarrayref); } + + installer::setupscript::add_predefined_folder($folderitemsinproductarrayref, $folderinproductarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "folder1b.log", $folderinproductarrayref); } + + installer::setupscript::prepare_non_advertised_files($folderitemsinproductarrayref, $filesinproductarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles2d.log", $filesinproductarrayref); } + + installer::logger::print_message( "... analyzing registryitems ... \n" ); + + $registryitemsinproductarrayref = installer::setupscript::get_all_items_from_script($setupscriptref, "RegistryItem"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "registryitems1.log", $registryitemsinproductarrayref); } + + $registryitemsinproductarrayref = installer::scriptitems::remove_uninstall_regitems_from_script($registryitemsinproductarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "registryitems1b.log", $registryitemsinproductarrayref); } + + installer::logger::print_message( "... analyzing Windows custom actions ... \n" ); + + $windowscustomactionsarrayref = installer::setupscript::get_all_items_from_script($setupscriptref, "WindowsCustomAction"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "windowscustomactions1.log", $windowscustomactionsarrayref); } + + installer::logger::print_message( "... analyzing Windows merge modules ... \n" ); + + $mergemodulesarrayref = installer::setupscript::get_all_items_from_script($setupscriptref, "MergeModule"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "mergemodules1.log", $mergemodulesarrayref); } +} + +my $modulesinproductarrayref; + +if (!($installer::globals::is_copy_only_project)) +{ + installer::logger::print_message( "... analyzing modules ... \n" ); + + $modulesinproductarrayref = installer::setupscript::get_all_items_from_script($setupscriptref, "Module"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "modules1.log", $modulesinproductarrayref); } + + if (( ! $allvariableshashref->{'XPDINSTALLER'} ) || ( ! $installer::globals::isxpdplatform )) + { + $modulesinproductarrayref = installer::scriptitems::remove_Xpdonly_Items($modulesinproductarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "modules1a.log", $modulesinproductarrayref); } + } + + installer::scriptitems::resolve_assigned_modules($modulesinproductarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "modules1b.log", $modulesinproductarrayref); } + + $modulesinproductarrayref = installer::scriptitems::remove_template_modules($modulesinproductarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "modules1c.log", $modulesinproductarrayref); } + + installer::scriptitems::set_children_flag($modulesinproductarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "modules1d.log", $modulesinproductarrayref); } + + installer::scriptitems::collect_all_languagemodules($modulesinproductarrayref); + + # Assigning the modules to the items + + installer::scriptitems::assigning_modules_to_items($modulesinproductarrayref, $filesinproductarrayref, "Files"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles3.log", $filesinproductarrayref); } + + installer::scriptitems::assigning_modules_to_items($modulesinproductarrayref, $unixlinksinproductarrayref, "Unixlinks"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "unixlinks2.log", $unixlinksinproductarrayref); } + + installer::scriptitems::assigning_modules_to_items($modulesinproductarrayref, $dirsinproductarrayref, "Dirs"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productdirectories2aa.log", $dirsinproductarrayref); } +} + +if ( $installer::globals::debug ) { installer::logger::debuginfo("\nEnd of part 1a: The language independent part\n"); } + +# saving debug info, before staring part 1b +if ( $installer::globals::debug ) { installer::logger::savedebug($installer::globals::exitlog); } + +################################################# +# Part 1b: The language dependent part +# (still platform independent) +################################################# + +# Now starts the language dependent part, if more than one product is defined on the command line +# Example -l en-US,de#es,fr,it defines two multilingual products + +############################################################################### +# Beginning of language dependent part +# The for iterates over all products, separated by an # in the language list +############################################################################### + +if ( $installer::globals::debug ) { installer::logger::debuginfo("\nPart 1b: The language dependent part\n"); } + +for ( my $n = 0; $n <= $#installer::globals::languageproducts; $n++ ) +{ + my $languagesarrayref = installer::languages::get_all_languages_for_one_product($installer::globals::languageproducts[$n], $allvariableshashref); + if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "languages.log" ,$languagesarrayref); } + + $installer::globals::alllanguagesinproductarrayref = $languagesarrayref; + my $languagestringref = installer::languages::get_language_string($languagesarrayref); + installer::logger::print_message( "------------------------------------\n" ); + installer::logger::print_message( "... languages $$languagestringref ... \n" ); + + if ( $installer::globals::patch ) + { + $installer::globals::addlicensefile = 0; # no license files for patches + $installer::globals::makedownload = 0; + $installer::globals::makejds = 0; + } + + if ( $installer::globals::languagepack ) + { + $installer::globals::addchildprojects = 0; + $installer::globals::addsystemintegration = 0; + $installer::globals::makejds = 0; + $installer::globals::addlicensefile = 0; + + if ( $allvariableshashref->{'OPENSOURCE'} ) { $installer::globals::makedownload = 1; } + else { $installer::globals::makedownload = 0; } + } + + ############################################################ + # Beginning of language specific logging mechanism + # Until now only global logging into default: logfile.txt + ############################################################ + + @installer::globals::logfileinfo = (); # new logfile array and new logfile name + installer::logger::copy_globalinfo_into_logfile(); + $installer::globals::globalinfo_copied = 1; + + my $logminor = ""; + my $avoidlanginlog = 0; + if ( $installer::globals::updatepack ) { $logminor = $installer::globals::lastminor; } + else { $logminor = $installer::globals::minor; } + + my $loglanguagestring = $$languagestringref; + my $loglanguagestring_orig = $loglanguagestring; + if (length($loglanguagestring) > $installer::globals::max_lang_length) + { + chomp(my $shorter = `echo $loglanguagestring | md5sum | sed -e "s/ .*//g"`); + $loglanguagestring = $shorter; + $avoidlanginlog = 1; + } + + $installer::globals::logfilename = "log_" . $installer::globals::build; + if ( $logminor ne "" ) { $installer::globals::logfilename .= "_" . $logminor; } + if ( ! $avoidlanginlog ) { $installer::globals::logfilename .= "_" . $loglanguagestring; } + $installer::globals::logfilename .= ".log"; + $loggingdir = $loggingdir . $loglanguagestring . $installer::globals::separator; + installer::systemactions::create_directory($loggingdir); + + if ($loglanguagestring ne $loglanguagestring_orig) { + (my $dir = $loggingdir) =~ s!/$!!; + open(my $F1, "> $dir.dir"); + open(my $F2, "> " . $loggingdir . $installer::globals::logfilename . '.file'); + my @s = map { "$_\n" } split('_', $loglanguagestring_orig); + print $F1 @s; + print $F2 @s; + } + + $installer::globals::exitlog = $loggingdir; + + ############################################################## + # Determining the ship location, if this is an update pack + ############################################################## + + if ( $installer::globals::updatepack ) { $shipinstalldir = installer::control::determine_ship_directory($languagestringref); } + + ################################################################### + # Reading an existing msi database, to prepare update and patch + ################################################################### + + my $refdatabase = ""; + my $uniquefilename = ""; + my $revuniquefilename = ""; + my $revshortfilename = ""; + my $allupdatesequences = ""; + my $allupdatecomponents = ""; + my $allupdatefileorder = ""; + my $allupdatecomponentorder = ""; + my $shortdirname = ""; + my $componentid = ""; + my $componentidkeypath = ""; + my $alloldproperties = ""; + my $allupdatelastsequences = ""; + my $allupdatediskids = ""; + + if ( $installer::globals::iswindowsbuild ) + { + if ( $allvariableshashref->{'UPDATE_DATABASE'} ) + { + installer::logger::print_message( "... analyzing update database ...\n" ); + $refdatabase = installer::windows::update::readdatabase($allvariableshashref, $languagestringref, $includepatharrayref); + + if ( $installer::globals::updatedatabase ) + { + ($uniquefilename, $revuniquefilename, $revshortfilename, $allupdatesequences, $allupdatecomponents, $allupdatefileorder, $allupdatecomponentorder, $shortdirname, $componentid, $componentidkeypath, $alloldproperties, $allupdatelastsequences, $allupdatediskids) = installer::windows::update::create_database_hashes($refdatabase); + if ( $mergemodulesarrayref > -1 ) { installer::windows::update::readmergedatabase($mergemodulesarrayref, $languagestringref, $includepatharrayref); } + } + } + } + + ############################################## + # Setting global code variables for Windows + ############################################## + + if (!($installer::globals::is_copy_only_project)) + { + if ( $installer::globals::iswindowsbuild ) + { + installer::windows::msiglobal::set_global_code_variables($languagesarrayref, $languagestringref, $allvariableshashref, $alloldproperties); + } + } + + ################################################ + # Resolving include paths (language dependent) + ################################################ + + $includepatharrayref_lang = installer::ziplist::replace_languages_in_pathes($includepatharrayref, $languagesarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "allpatharray4.log" ,$includepatharrayref_lang); } + + if ( $installer::globals::refresh_includepathes ) { installer::worker::collect_all_files_from_includepathes($includepatharrayref_lang); } + + installer::ziplist::list_all_files_from_include_path($includepatharrayref_lang); + + ############################################## + # Analyzing spellchecker languages + ############################################## + + if ( $allvariableshashref->{'SPELLCHECKERFILE'} ) { installer::worker::set_spellcheckerlanguages($languagesarrayref, $allvariableshashref); } + + ##################################### + # Language dependent directory part + ##################################### + + my $dirsinproductlanguageresolvedarrayref = installer::scriptitems::resolving_all_languages_in_productlists($dirsinproductarrayref, $languagesarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productdirectories3.log", $dirsinproductlanguageresolvedarrayref); } + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productdirectories2a.log", $dirsinproductarrayref); } + + # A new directory array is needed ($dirsinproductlanguageresolvedarrayref instead of $dirsinproductarrayref) + # because $dirsinproductarrayref is needed in get_Destination_Directory_For_Item_From_Directorylist + + installer::scriptitems::changing_name_of_language_dependent_keys($dirsinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productdirectories4.log", $dirsinproductlanguageresolvedarrayref); } + + installer::scriptitems::checking_directories_with_corrupt_hostname($dirsinproductlanguageresolvedarrayref, $languagesarrayref); + + installer::scriptitems::set_global_directory_hostnames($dirsinproductlanguageresolvedarrayref, $allvariableshashref); + + ##################################### + # files part, language dependent + ##################################### + + installer::logger::print_message( "... analyzing files ...\n" ); + + my $filesinproductlanguageresolvedarrayref = installer::scriptitems::resolving_all_languages_in_productlists($filesinproductarrayref, $languagesarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles4.log", $filesinproductlanguageresolvedarrayref); } + + if ( ! $installer::globals::set_office_start_language ) + { + $filesinproductlanguageresolvedarrayref = installer::scriptitems::remove_office_start_language_files($filesinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles4b.log", $filesinproductlanguageresolvedarrayref); } + } + + installer::scriptitems::changing_name_of_language_dependent_keys($filesinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles5.log", $filesinproductlanguageresolvedarrayref); } + + if ( $installer::globals::iswin and $^O =~ /MSWin/i ) { installer::converter::convert_slash_to_backslash($filesinproductlanguageresolvedarrayref); } + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles6.log", $filesinproductlanguageresolvedarrayref); } + + $filesinproductlanguageresolvedarrayref = installer::scriptitems::remove_non_existent_languages_in_productlists($filesinproductlanguageresolvedarrayref, $languagestringref, "Name", "file"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles7.log", $filesinproductlanguageresolvedarrayref); } + + installer::scriptitems::get_Destination_Directory_For_Item_From_Directorylist($filesinproductlanguageresolvedarrayref, $dirsinproductarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles8.log", $filesinproductlanguageresolvedarrayref); } + + installer::scriptitems::get_Source_Directory_For_Files_From_Includepathlist($filesinproductlanguageresolvedarrayref, $includepatharrayref_lang, $dirsinproductlanguageresolvedarrayref, "Files"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles9.log", $filesinproductlanguageresolvedarrayref); } + + $filesinproductlanguageresolvedarrayref = installer::scriptitems::remove_Files_Without_Sourcedirectory($filesinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles10.log", $filesinproductlanguageresolvedarrayref); } + + if ($installer::globals::languagepack) + { + $filesinproductlanguageresolvedarrayref = installer::scriptitems::remove_Files_For_Languagepacks($filesinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles10c.log", $filesinproductlanguageresolvedarrayref); } + } + + + if ( ! $allvariableshashref->{'NO_README_IN_ROOTDIR'} ) + { + $filesinproductlanguageresolvedarrayref = installer::scriptitems::add_License_Files_into_Installdir($filesinproductlanguageresolvedarrayref, $dirsinproductlanguageresolvedarrayref, $languagesarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles10b.log", $filesinproductlanguageresolvedarrayref); } + } + + $filesinproductlanguageresolvedarrayref = installer::scriptitems::remove_onlyasialanguage_files_from_productlists($filesinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles10d.log", $filesinproductlanguageresolvedarrayref); } + + $filesinproductlanguageresolvedarrayref = installer::scriptitems::remove_onlywesternlanguage_files_from_productlists($filesinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles10e.log", $filesinproductlanguageresolvedarrayref); } + + installer::scriptitems::make_filename_language_specific($filesinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles10f.log", $filesinproductlanguageresolvedarrayref); } + + # print "... calculating checksums ...\n"; + # my $checksumfile = installer::worker::make_checksum_file($filesinproductlanguageresolvedarrayref, $includepatharrayref); + # if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . $installer::globals::checksumfilename, $checksumfile); } + + ###################################################################################### + # Unzipping files with flag ARCHIVE and putting all included files into the file list + ###################################################################################### + + installer::logger::print_message( "... analyzing files with flag ARCHIVE ...\n" ); + + my @additional_paths_from_zipfiles = (); + + $filesinproductlanguageresolvedarrayref = installer::archivefiles::resolving_archive_flag($filesinproductlanguageresolvedarrayref, \@additional_paths_from_zipfiles, $languagestringref, $loggingdir); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles11.log", $filesinproductlanguageresolvedarrayref); } + if ( $installer::globals::globallogging ) { installer::files::save_file($loggingdir . "additional_paths.log" ,\@additional_paths_from_zipfiles); } + + # packed files sometimes contain a "$" in their name: HighlightText$1.class. For epm the "$" has to be quoted by "$$" + + if (!( $installer::globals::iswindowsbuild || $installer::globals::simple ) ) + { + installer::scriptitems::quoting_illegal_filenames($filesinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles12.log", $filesinproductlanguageresolvedarrayref); } + } + + ##################################### + # Files with flag SUBST_FILENAME + ##################################### + + installer::logger::print_message( "... analyzing files with flag SUBST_FILENAME ...\n" ); + + installer::substfilenamefiles::resolving_subst_filename_flag($filesinproductlanguageresolvedarrayref, $allvariableshashref, $languagestringref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles12d.log", $filesinproductlanguageresolvedarrayref); } + + ##################################### + # Files with flag SCPZIP_REPLACE + ##################################### + + installer::logger::print_message( "... analyzing files with flag SCPZIP_REPLACE ...\n" ); + + # Editing files with flag SCPZIP_REPLACE. + + installer::scpzipfiles::resolving_scpzip_replace_flag($filesinproductlanguageresolvedarrayref, $allvariableshashref, "File", $languagestringref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles13.log", $filesinproductlanguageresolvedarrayref); } + + ##################################### + # Files with flag PATCH_SO_NAME + ##################################### + + installer::logger::print_message( "... analyzing files with flag PATCH_SO_NAME ...\n" ); + + # Editing files with flag PATCH_SO_NAME. + + installer::scppatchsoname::resolving_patchsoname_flag($filesinproductlanguageresolvedarrayref, $allvariableshashref, "File", $languagestringref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles13b.log", $filesinproductlanguageresolvedarrayref); } + + ##################################### + # Files with flag HIDDEN + ##################################### + + installer::logger::print_message( "... analyzing files with flag HIDDEN ...\n" ); + + installer::worker::resolving_hidden_flag($filesinproductlanguageresolvedarrayref, $allvariableshashref, "File", $languagestringref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles13c.log", $filesinproductlanguageresolvedarrayref); } + + ##################################### + # Creating services.rdb + ##################################### + + if ( $allvariableshashref->{'SERVICESPROJEKT'} ) + { + if (! $installer::globals::languagepack) + { + # ATTENTION: For creating the services.rdb it is necessary to execute the native file + # "regcomp" or "regcomp.exe". Therefore this function can only be executed on the + # corresponding platform. + + if ( $installer::globals::servicesrdb_can_be_created ) + { + installer::logger::print_message( "... creating preregistered services.rdb ...\n" ); + + installer::servicesfile::create_services_rdb($allvariableshashref, $filesinproductlanguageresolvedarrayref, $includepatharrayref, $languagestringref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles14.log", $filesinproductlanguageresolvedarrayref); } + } + } + } + + ##################################### + # Calls of regmerge + ##################################### + + if (!($installer::globals::is_copy_only_project)) + { + if (! $installer::globals::languagepack) + { + installer::logger::print_message( "... merging files into registry database ...\n" ); + + installer::regmerge::merge_registration_files($filesinproductlanguageresolvedarrayref, $includepatharrayref, $languagestringref, $allvariableshashref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles14b.log", $filesinproductlanguageresolvedarrayref); } + } + } + + ############################################ + # Collecting directories for epm list file + ############################################ + + installer::logger::print_message( "... analyzing all directories for this product ...\n" ); + + # There are two ways for a directory to be included into the epm directory list: + # 1. Looking for all destination paths in the files array + # 2. Looking for directories with CREATE flag in the directory array + # Advantage: Many pathes are hidden in zip files, they are not defined in the setup script. + # It will be possible, that in the setup script only those directoies have to be defined, + # that have a CREATE flag. All other directories are created, if they contain at least one file. + + my ($directoriesforepmarrayref, $alldirectoryhash) = installer::scriptitems::collect_directories_from_filesarray($filesinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforepmlist1.log", $directoriesforepmarrayref); } + + ($directoriesforepmarrayref, $alldirectoryhash) = installer::scriptitems::collect_directories_with_create_flag_from_directoryarray($dirsinproductlanguageresolvedarrayref, $alldirectoryhash); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforepmlist2.log", $directoriesforepmarrayref); } + + # installer::sorter::sorting_array_of_hashes($directoriesforepmarrayref, "HostName"); + # if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforepmlist3.log", $directoriesforepmarrayref); } + + ######################################################### + # language dependent scpactions part + ######################################################### + + my $scpactionsinproductlanguageresolvedarrayref = installer::scriptitems::resolving_all_languages_in_productlists($scpactionsinproductarrayref, $languagesarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productscpactions3.log", $scpactionsinproductlanguageresolvedarrayref); } + + installer::scriptitems::changing_name_of_language_dependent_keys($scpactionsinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productscpactions4.log", $scpactionsinproductlanguageresolvedarrayref); } + + installer::scriptitems::get_Source_Directory_For_Files_From_Includepathlist($scpactionsinproductlanguageresolvedarrayref, $includepatharrayref_lang, $dirsinproductlanguageresolvedarrayref, "ScpActions"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productscpactions5.log", $scpactionsinproductlanguageresolvedarrayref); } + + # Editing scpactions with flag SCPZIP_REPLACE. + + installer::scpzipfiles::resolving_scpzip_replace_flag($scpactionsinproductlanguageresolvedarrayref, $allvariableshashref, "ScpAction", $languagestringref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productscpactions6.log", $scpactionsinproductlanguageresolvedarrayref); } + + ######################################################### + # language dependent links part + ######################################################### + + installer::logger::print_message( "... analyzing links ...\n" ); + + my $linksinproductlanguageresolvedarrayref = installer::scriptitems::resolving_all_languages_in_productlists($linksinproductarrayref, $languagesarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productlinks2.log", $linksinproductlanguageresolvedarrayref); } + + installer::scriptitems::changing_name_of_language_dependent_keys($linksinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productlinks3.log", $linksinproductlanguageresolvedarrayref); } + + installer::scriptitems::get_destination_file_path_for_links($linksinproductlanguageresolvedarrayref, $filesinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productlinks4.log", $linksinproductlanguageresolvedarrayref); } + + installer::scriptitems::get_Destination_Directory_For_Item_From_Directorylist($linksinproductlanguageresolvedarrayref, $dirsinproductarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productlinks5.log", $linksinproductlanguageresolvedarrayref); } + + # Now taking all links that have no FileID but a ShortcutID, linking to another link + + installer::scriptitems::get_destination_link_path_for_links($linksinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productlinks6.log", $linksinproductlanguageresolvedarrayref); } + + $linksinproductlanguageresolvedarrayref = installer::scriptitems::remove_workstation_only_items($linksinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productlinks7.log", $linksinproductlanguageresolvedarrayref); } + + installer::scriptitems::resolve_links_with_flag_relative($linksinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productlinks8.log", $linksinproductlanguageresolvedarrayref); } + + ######################################################### + # language dependent unix links part + ######################################################### + + installer::logger::print_message( "... analyzing unix links ...\n" ); + + my $unixlinksinproductlanguageresolvedarrayref = installer::scriptitems::resolving_all_languages_in_productlists($unixlinksinproductarrayref, $languagesarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "unixlinks3.log", $unixlinksinproductlanguageresolvedarrayref); } + + installer::scriptitems::changing_name_of_language_dependent_keys($unixlinksinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "unixlinks4.log", $unixlinksinproductlanguageresolvedarrayref); } + + installer::scriptitems::get_Destination_Directory_For_Item_From_Directorylist($unixlinksinproductlanguageresolvedarrayref, $dirsinproductarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "unixlinks5.log", $unixlinksinproductlanguageresolvedarrayref); } + + ######################################################### + # language dependent part for profiles and profileitems + ######################################################### + + my $profilesinproductlanguageresolvedarrayref; + my $profileitemsinproductlanguageresolvedarrayref; + + if ((!($installer::globals::is_copy_only_project)) && (!($installer::globals::product =~ /ada/i ))) + { + installer::logger::print_message( "... creating profiles ...\n" ); + + $profilesinproductlanguageresolvedarrayref = installer::scriptitems::resolving_all_languages_in_productlists($profilesinproductarrayref, $languagesarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "profiles2.log", $profilesinproductlanguageresolvedarrayref); } + + $profileitemsinproductlanguageresolvedarrayref = installer::scriptitems::resolving_all_languages_in_productlists($profileitemsinproductarrayref, $languagesarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "profileitems2.log", $profilesinproductlanguageresolvedarrayref); } + + installer::scriptitems::changing_name_of_language_dependent_keys($profilesinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "profiles3.log", $profilesinproductlanguageresolvedarrayref); } + + installer::scriptitems::changing_name_of_language_dependent_keys($profileitemsinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "profileitems3.log", $profileitemsinproductlanguageresolvedarrayref); } + + installer::scriptitems::replace_setup_variables($profileitemsinproductlanguageresolvedarrayref, $languagestringref, $allvariableshashref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "profileitems4.log", $profileitemsinproductlanguageresolvedarrayref); } + + if ( $installer::globals::patch_user_dir ) + { + installer::scriptitems::replace_userdir_variable($profileitemsinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "profileitems4a.log", $profileitemsinproductlanguageresolvedarrayref); } + } + + installer::scriptitems::get_Destination_Directory_For_Item_From_Directorylist($profilesinproductlanguageresolvedarrayref, $dirsinproductarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "profiles4.log", $profilesinproductlanguageresolvedarrayref); } + + # Now the Profiles can be created + + installer::profiles::create_profiles($profilesinproductlanguageresolvedarrayref, $profileitemsinproductlanguageresolvedarrayref, $filesinproductlanguageresolvedarrayref, $languagestringref, $allvariableshashref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles15.log", $filesinproductlanguageresolvedarrayref); } + } + + my $registryitemsinproductlanguageresolvedarrayref; # cannot be defined in the following "if ( $installer::globals::iswindowsbuild )" + my $folderinproductlanguageresolvedarrayref; # cannot be defined in the following "if ( $installer::globals::iswindowsbuild )" + my $folderitemsinproductlanguageresolvedarrayref; # cannot be defined in the following "if ( $installer::globals::iswindowsbuild )" + + if ( $installer::globals::iswindowsbuild ) # Windows specific items: Folder, FolderItem, RegistryItem + { + ######################################################### + # language dependent part for folder + ######################################################### + + installer::logger::print_message( "... analyzing folder ...\n" ); + + $folderinproductlanguageresolvedarrayref = installer::scriptitems::resolving_all_languages_in_productlists($folderinproductarrayref, $languagesarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "folder2.log", $folderinproductlanguageresolvedarrayref); } + + installer::scriptitems::changing_name_of_language_dependent_keys($folderinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "folder3.log", $folderinproductlanguageresolvedarrayref); } + + ######################################################### + # language dependent part for folderitems + ######################################################### + + installer::logger::print_message( "... analyzing folderitems ...\n" ); + + $folderitemsinproductlanguageresolvedarrayref = installer::scriptitems::resolving_all_languages_in_productlists($folderitemsinproductarrayref, $languagesarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "folderitems2.log", $folderitemsinproductlanguageresolvedarrayref); } + + installer::scriptitems::changing_name_of_language_dependent_keys($folderitemsinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "folderitems3.log", $folderitemsinproductlanguageresolvedarrayref); } + + ######################################################### + # language dependent part for registryitems + ######################################################### + + installer::logger::print_message( "... analyzing registryitems ...\n" ); + + $registryitemsinproductlanguageresolvedarrayref = installer::scriptitems::resolving_all_languages_in_productlists($registryitemsinproductarrayref, $languagesarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "registryitems2.log", $registryitemsinproductlanguageresolvedarrayref); } + + installer::scriptitems::changing_name_of_language_dependent_keys($registryitemsinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "registryitems3.log", $registryitemsinproductlanguageresolvedarrayref); } + } + + ######################################################### + # language dependent part for modules + ######################################################### + + my $modulesinproductlanguageresolvedarrayref; + + if (!($installer::globals::is_copy_only_project)) + { + installer::logger::print_message( "... analyzing modules ...\n" ); + + $modulesinproductlanguageresolvedarrayref = installer::scriptitems::resolving_all_languages_in_productlists($modulesinproductarrayref, $languagesarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes_modules($loggingdir . "modules2.log", $modulesinproductlanguageresolvedarrayref); } + + $modulesinproductlanguageresolvedarrayref = installer::scriptitems::remove_not_required_language_modules($modulesinproductlanguageresolvedarrayref, $languagesarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes_modules($loggingdir . "modules2a.log", $modulesinproductlanguageresolvedarrayref); } + + if ( $installer::globals::analyze_spellcheckerlanguage ) + { + $modulesinproductlanguageresolvedarrayref = installer::scriptitems::remove_not_required_spellcheckerlanguage_modules($modulesinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes_modules($loggingdir . "modules3.log", $modulesinproductlanguageresolvedarrayref); } + + $filesinproductlanguageresolvedarrayref = installer::scriptitems::remove_not_required_spellcheckerlanguage_files($filesinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles15b.log", $filesinproductlanguageresolvedarrayref); } + } + + installer::scriptitems::changing_name_of_language_dependent_keys($modulesinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes_modules($loggingdir . "modules3a.log", $modulesinproductlanguageresolvedarrayref); } + + # installer::scriptitems::collect_language_specific_names($modulesinproductlanguageresolvedarrayref); + installer::scriptitems::select_required_language_strings($modulesinproductlanguageresolvedarrayref); # using english strings + + } + + # Copy-only projects can now start to copy all items File and ScpAction + if ( $installer::globals::is_copy_only_project ) { installer::copyproject::copy_project($filesinproductlanguageresolvedarrayref, $scpactionsinproductlanguageresolvedarrayref, $loggingdir, $languagestringref, $shipinstalldir, $allsettingsarrayref); } + + # Language pack projects can now start to select the required information + if ( $installer::globals::languagepack ) + { + $filesinproductlanguageresolvedarrayref = installer::languagepack::select_language_items($filesinproductlanguageresolvedarrayref, $languagesarrayref, "File"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles16b.log", $filesinproductlanguageresolvedarrayref); } + $scpactionsinproductlanguageresolvedarrayref = installer::languagepack::select_language_items($scpactionsinproductlanguageresolvedarrayref, $languagesarrayref, "ScpAction"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productscpactions6b.log", $scpactionsinproductlanguageresolvedarrayref); } + $linksinproductlanguageresolvedarrayref = installer::languagepack::select_language_items($linksinproductlanguageresolvedarrayref, $languagesarrayref, "Shortcut"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productlinks8b.log", $linksinproductlanguageresolvedarrayref); } + $unixlinksinproductlanguageresolvedarrayref = installer::languagepack::select_language_items($unixlinksinproductlanguageresolvedarrayref, $languagesarrayref, "Unixlink"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "unixlinks5.log", $unixlinksinproductlanguageresolvedarrayref); } + @{$folderitemsinproductlanguageresolvedarrayref} = (); # no folderitems in languagepacks + + # Collecting the directories again, to include only the language specific directories + ($directoriesforepmarrayref, $alldirectoryhash) = installer::scriptitems::collect_directories_from_filesarray($filesinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforepmlist3alangpack.log", $directoriesforepmarrayref); } + ($directoriesforepmarrayref, $alldirectoryhash) = installer::scriptitems::collect_directories_with_create_flag_from_directoryarray($dirsinproductlanguageresolvedarrayref, $alldirectoryhash); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforepmlist3blangpack.log", $directoriesforepmarrayref); } + installer::sorter::sorting_array_of_hashes($directoriesforepmarrayref, "HostName"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforepmlist3clangpack.log", $directoriesforepmarrayref); } + + if ( $installer::globals::iswindowsbuild ) + { + $registryitemsinproductlanguageresolvedarrayref = installer::worker::select_langpack_items($registryitemsinproductlanguageresolvedarrayref, "RegistryItem"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "registryitems3aa.log", $registryitemsinproductlanguageresolvedarrayref); } + } + + } + + # Collecting all files without flag PATCH (for maintenance reasons) + if ( $installer::globals::patch ) { installer::worker::collect_all_files_without_patch_flag($filesinproductlanguageresolvedarrayref); } + + # Patch projects can now start to select the required information + if (( $installer::globals::patch ) && (( $installer::globals::issolarispkgbuild ) || ( $installer::globals::iswindowsbuild ))) + { + $filesinproductlanguageresolvedarrayref = installer::worker::select_patch_items($filesinproductlanguageresolvedarrayref, "File"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles16patch.log", $filesinproductlanguageresolvedarrayref); } + $scpactionsinproductlanguageresolvedarrayref = installer::worker::select_patch_items($scpactionsinproductlanguageresolvedarrayref, "ScpAction"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productscpactions6patch.log", $scpactionsinproductlanguageresolvedarrayref); } + $linksinproductlanguageresolvedarrayref = installer::worker::select_patch_items($linksinproductlanguageresolvedarrayref, "Shortcut"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productlinks8patch.log", $linksinproductlanguageresolvedarrayref); } + $unixlinksinproductlanguageresolvedarrayref = installer::worker::select_patch_items($unixlinksinproductlanguageresolvedarrayref, "Unixlink"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "unixlinks6patch.log", $unixlinksinproductlanguageresolvedarrayref); } + $folderitemsinproductlanguageresolvedarrayref = installer::worker::select_patch_items($folderitemsinproductlanguageresolvedarrayref, "FolderItem"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfolderitems1patch.log", $folderitemsinproductlanguageresolvedarrayref); } + # @{$folderitemsinproductlanguageresolvedarrayref} = (); # no folderitems in languagepacks + + if ( $installer::globals::iswindowsbuild ) + { + $registryitemsinproductlanguageresolvedarrayref = installer::worker::select_patch_items_without_name($registryitemsinproductlanguageresolvedarrayref, "RegistryItem"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "registryitems3a.log", $registryitemsinproductlanguageresolvedarrayref); } + + installer::worker::prepare_windows_patchfiles($filesinproductlanguageresolvedarrayref, $languagestringref, $allvariableshashref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles16bpatch.log", $filesinproductlanguageresolvedarrayref); } + + # For Windows patches, the directories can now be collected again + ($directoriesforepmarrayref, $alldirectoryhash) = installer::scriptitems::collect_directories_from_filesarray($filesinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforepmlist4_patch.log", $directoriesforepmarrayref); } + + installer::sorter::sorting_array_of_hashes($directoriesforepmarrayref, "HostName"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforepmlist5_patch.log", $directoriesforepmarrayref); } + } + } + + ######################################################### + # Collecting all scp actions + ######################################################### + + installer::worker::collect_scpactions($scpactionsinproductlanguageresolvedarrayref); + + ######################################################### + # creating inf files for user system integration + ######################################################### + + if (( $installer::globals::iswindowsbuild ) && ( ! $installer::globals::patch )) # Windows specific items: Folder, FolderItem, RegistryItem + { + installer::logger::print_message( "... creating inf files ...\n" ); + installer::worker::create_inf_file($filesinproductlanguageresolvedarrayref, $registryitemsinproductlanguageresolvedarrayref, $folderinproductlanguageresolvedarrayref, $folderitemsinproductlanguageresolvedarrayref, $modulesinproductlanguageresolvedarrayref, $languagesarrayref, $languagestringref, $allvariableshashref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles16c.log", $filesinproductlanguageresolvedarrayref); } + } + + ########################################### + # Using upx, to decrease file size + # Currently only for Windows. + ########################################### + + if ( $allvariableshashref->{'UPXPRODUCT'} ) + { + installer::upx::upx_on_libraries($filesinproductlanguageresolvedarrayref, $languagestringref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles16d.log", $filesinproductlanguageresolvedarrayref); } + } + + ########################################################### + # Simple package projects can now start to create the + # installation structure by creating Directories, Files + # Links and ScpActions. This is the last platform + # independent part. + ########################################################### + + if ( $installer::globals::is_simple_packager_project ) + { + installer::simplepackage::create_simple_package($filesinproductlanguageresolvedarrayref, $directoriesforepmarrayref, $scpactionsinproductlanguageresolvedarrayref, $linksinproductlanguageresolvedarrayref, $unixlinksinproductlanguageresolvedarrayref, $loggingdir, $languagestringref, $shipinstalldir, $allsettingsarrayref, $allvariableshashref, $includepatharrayref); + next; # ! leaving the current loop, because no further packaging required. + } + + ########################################################### + # Analyzing the package structure + ########################################################### + + installer::logger::print_message( "... analyzing package list ...\n" ); + + my $packages = installer::packagelist::collectpackages($modulesinproductlanguageresolvedarrayref, $languagesarrayref); + installer::packagelist::check_packagelist($packages); + + $packages = installer::packagelist::analyze_list($packages, $modulesinproductlanguageresolvedarrayref); + installer::packagelist::remove_multiple_modules_packages($packages); + + # printing packages content: + installer::packagelist::log_packages_content($packages); + installer::packagelist::create_module_destination_hash($packages, $allvariableshashref); + + if ( $installer::globals::debug ) { installer::logger::debuginfo("\nEnd of part 1b: The language dependent part\n"); } + + # saving debug info, before starting part 2 + if ( $installer::globals::debug ) { installer::logger::savedebug($installer::globals::exitlog); } + + ################################################# + # Part 2: The platform dependent part + ################################################# + + if ( $installer::globals::debug ) { installer::logger::debuginfo("\nPart 2: The platform dependent part\n"); } + + ################################################# + # Part 2a: All non-Windows platforms + ################################################# + + if ( $installer::globals::debug ) { installer::logger::debuginfo("\nPart 2a: All non-Windows platforms\n"); } + + ######################################################### + # ... creating epm list file ... + # Only for non-Windows platforms + ######################################################### + + if (!( $installer::globals::iswindowsbuild )) + { + #################################################### + # Writing log file before packages are packed + #################################################### + + installer::logger::print_message( "... creating log file " . $loggingdir . $installer::globals::logfilename . "\n" ); + installer::files::save_file($loggingdir . $installer::globals::logfilename, \@installer::globals::logfileinfo); + + #################################################### + # Creating directories + #################################################### + + $installdir = installer::worker::create_installation_directory($shipinstalldir, $languagestringref, \$current_install_number); + + my $listfiledir = installer::systemactions::create_directories("listfile", $languagestringref); + my $installlogdir = installer::systemactions::create_directory_next_to_directory($installdir, "log"); + # installer::packagelist::add_defaultpathes_into_filescollector($filesinproductlanguageresolvedarrayref); + # my $installchecksumdir = installer::systemactions::create_directory_next_to_directory($installdir, "checksum"); + + #################################################### + # Reading for Solaris all package descriptions + # from file defined in property PACKAGEMAP + #################################################### + + if ( $installer::globals::issolarisbuild ) { installer::epmfile::read_packagemap($allvariableshashref, $includepatharrayref, $languagesarrayref); } + + my $epmexecutable = ""; + my $found_epm = 0; + + # shuffle array to reduce parallel packaging process in pool + installer::worker::shuffle_array($packages); + + # iterating over all packages + for ( my $k = 0; $k <= $#{$packages}; $k++ ) + { + my $onepackage = ${$packages}[$k]; + + # checking, if this is a language pack or a project pack. + # Creating language packs only, if $installer::globals::languagepack is set. Parameter: -languagepack + + if ( $installer::globals::languagepack ) { installer::languagepack::replace_languagestring_variable($onepackage, $languagestringref); } + + my $onepackagename = $onepackage->{'module'}; # name of the top module (required) + + my $shellscriptsfilename = ""; + if ( $onepackage->{'script'} ) { $shellscriptsfilename = $onepackage->{'script'}; } + # no scripts for Solaris patches! + if (( $installer::globals::patch ) && ( $installer::globals::issolarispkgbuild )) { $shellscriptsfilename = ""; } + + ########################### + # package name + ########################### + + my $packagename = ""; + + if ( $installer::globals::issolarisbuild ) # only for Solaris + { + if ( $onepackage->{'solarispackagename'} ) { $packagename = $onepackage->{'solarispackagename'}; } + } + else # not Solaris + { + if ( $onepackage->{'packagename'} ) { $packagename = $onepackage->{'packagename'}; } + } + + if (!($packagename eq "")) + { + installer::packagelist::resolve_packagevariables(\$packagename, $allvariableshashref, 0); + } + + my $linkaddon = ""; + my $linkpackage = 0; + $installer::globals::add_required_package = ""; + $installer::globals::linuxlinkrpmprocess = 0; + + if ( $installer::globals::makelinuxlinkrpm ) + { + my $oldpackagename = $packagename; + $installer::globals::add_required_package = $oldpackagename; # the link rpm requires the non-linked version + if ( $installer::globals::languagepack ) { $packagename = $packagename . "_u"; } + else { $packagename = $packagename . "u"; } + my $savestring = $oldpackagename . "\t" . $packagename; + push(@installer::globals::linkrpms, $savestring); + $linkaddon = "_links"; + $installer::globals::linuxlinkrpmprocess = 1; + $linkpackage = 1; + } + + #################################################### + # Header for this package into log file + #################################################### + + installer::logger::include_header_into_logfile("Creating package: $packagename ($k)"); + + #################################################### + # Pool check: If package is created at the moment + # try it again later. + #################################################### + + if (( $installer::globals::patch ) || ( $installer::globals::languagepack ) || ( $installer::globals::packageformat eq "native" )) { $allvariableshashref->{'POOLPRODUCT'} = 0; } + + if ( $allvariableshashref->{'POOLPRODUCT'} ) + { + if ( ! $installer::globals::sessionidset ) { installer::packagepool::set_sessionid(); } + if ( ! $installer::globals::poolpathset ) { installer::packagepool::set_pool_path(); } + if (( ! $installer::globals::getuidpathset ) && ( $installer::globals::issolarisbuild )) { installer::worker::set_getuid_path($includepatharrayref); } + + my $package_is_creatable = installer::packagepool::check_package_availability($packagename); + + if (( ! $package_is_creatable ) && ( ! exists($installer::globals::poolshiftedpackages{$packagename}) )) + { + splice(@{$packages}, $k, 1); # removing package ... + push(@{$packages}, $onepackage); # ... and adding it to the end + $installer::globals::poolshiftedpackages{$packagename} = 1; # only shifting each package once + $k--; # decreasing the counter + my $localinfoline = "Pool: Package \"$packagename\" cannot be created at the moment. Trying again later (1).\n"; + installer::logger::print_message($localinfoline); + push( @installer::globals::logfileinfo, $localinfoline); + next; # repeating this iteration with new package + } + } + + ########################################### + # Root path, can be defined as parameter + ########################################### + + my $packagerootpath = ""; + + if ($installer::globals::rootpath eq "") + { + $packagerootpath = $onepackage->{'destpath'}; + installer::packagelist::resolve_packagevariables(\$packagerootpath, $allvariableshashref, 1); + if ( $^O =~ /darwin/i ) { $packagerootpath =~ s/\/opt\//\/Applications\//; } + } + else + { + $packagerootpath = $installer::globals::rootpath; + } + + ############################################# + # copying the collectors for each package + ############################################# + + my $filesinpackage = installer::converter::copy_collector($filesinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "files1_" . $packagename . ".log", $filesinpackage); } + my $linksinpackage = installer::converter::copy_collector($linksinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "links1_" . $packagename . ".log", $linksinpackage); } + my $unixlinksinpackage = installer::converter::copy_collector($unixlinksinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "unixlinks1_" . $packagename . ".log", $unixlinksinpackage); } + my $dirsinpackage = installer::converter::copy_collector($directoriesforepmarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "dirs1_" . $packagename . ".log", $dirsinpackage); } + + ########################################### + # setting the root path for the packages + ########################################### + + installer::scriptitems::add_rootpath_to_directories($dirsinpackage, $packagerootpath); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "dirs2_" . $packagename . ".log", $dirsinpackage); } + installer::scriptitems::add_rootpath_to_files($filesinpackage, $packagerootpath); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "files2_" . $packagename . ".log", $filesinpackage); } + installer::scriptitems::add_rootpath_to_links($linksinpackage, $packagerootpath); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "links2_" . $packagename . ".log", $linksinpackage); } + installer::scriptitems::add_rootpath_to_files($unixlinksinpackage, $packagerootpath); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "unixlinks2_" . $packagename . ".log", $unixlinksinpackage); } + + ################################# + # collecting items for package + ################################# + + $filesinpackage = installer::packagelist::find_files_for_package($filesinpackage, $onepackage); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "files3_" . $packagename . ".log", $filesinpackage); } + $unixlinksinpackage = installer::packagelist::find_files_for_package($unixlinksinpackage, $onepackage); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "unixlinks3_" . $packagename . ".log", $unixlinksinpackage); } + $linksinpackage = installer::packagelist::find_links_for_package($linksinpackage, $filesinpackage); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "links3_" . $packagename . ".log", $linksinpackage); } + $dirsinpackage = installer::packagelist::find_dirs_for_package($dirsinpackage, $onepackage); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "dirs3_" . $packagename . ".log", $dirsinpackage); } + + ############################################### + # nothing to do, if $filesinpackage is empty + ############################################### + + if ( ! ( $#{$filesinpackage} > -1 )) + { + push(@installer::globals::emptypackages, $packagename); + $infoline = "\n\nNo file in package: $packagename \-\> Skipping\n\n"; + push(@installer::globals::logfileinfo, $infoline); + next; # next package, end of loop ! + } + + ################################################################# + # nothing to do for Linux patches, if no file has flag PATCH + ################################################################# + + # Linux Patch: The complete RPM has to be built, if one file in the RPM has the flag PATCH (also for DEBs) + if (( $installer::globals::patch ) && (( $installer::globals::islinuxrpmbuild ) || ( $installer::globals::islinuxdebbuild ))) + { + my $patchfiles = installer::worker::collect_all_items_with_special_flag($filesinpackage ,"PATCH"); + if ( ! ( $#{$patchfiles} > -1 )) + { + $infoline = "\n\nLinux Patch: No patch file in package: $packagename \-\> Skipping\n\n"; + push(@installer::globals::logfileinfo, $infoline); + next; + } + } + + ########################################### + # Stripping libraries + ########################################### + + # Building for non Windows platforms in cws requires, that all files are stripped before packaging: + # 1. copy all files that need to be stripped locally + # 2. strip all these files + + if ( $installer::globals::strip ) + { + installer::strip::strip_libraries($filesinpackage, $languagestringref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . $packagename ."_files.log", $filesinpackage); } + } + + ############################################################### + # Searching for files in $filesinpackage with flag LINUXLINK + ############################################################### + + if (( $installer::globals::islinuxbuild ) && ( ! $installer::globals::simple )) # for rpms and debian packages + { + # special handling for all RPMs in $installer::globals::linuxlinkrpms + + # if (( $installer::globals::linuxlinkrpms =~ /\b$onepackagename\b/ ) || ( $installer::globals::languagepack )) + if ( $installer::globals::linuxlinkrpms =~ /\b$onepackagename\b/ ) + { + my $run = 0; + + if (( $installer::globals::makelinuxlinkrpm ) && ( ! $run )) + { + $filesinpackage = \@installer::globals::linuxpatchfiles; + $linksinpackage = \@installer::globals::linuxlinks; + $installer::globals::makelinuxlinkrpm = 0; + if ( $installer::globals::patch ) { $installer::globals::call_epm = 1; } # enabling packing again + $run = 1; + + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "files3b_" . $packagename . ".log", $filesinpackage); } + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "links3b_" . $packagename . ".log", $linksinpackage); } + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "dirs3b_" . $packagename . ".log", $dirsinpackage); } + } + + if (( ! $installer::globals::makelinuxlinkrpm ) && ( ! $run )) + { + $filesinpackage = installer::worker::prepare_linuxlinkfiles($filesinpackage); + $linksinpackage = installer::worker::prepare_forced_linuxlinkfiles($linksinpackage); + $installer::globals::makelinuxlinkrpm = 1; + if ( $allvariableshashref->{'OPENSOURCE'} ) { $installer::globals::add_required_package = $packagename . "u"; } + if ( $installer::globals::patch ) { $installer::globals::call_epm = 0; } # no packing of core module in patch + $shellscriptsfilename = ""; # shell scripts only need to be included into the link rpm + $run = 1; + + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "files3a_" . $packagename . ".log", $filesinpackage); } + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "links3a_" . $packagename . ".log", $linksinpackage); } + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "dirs3a_" . $packagename . ".log", $dirsinpackage); } + } + } + } + + ########################################### + # Simple installation mechanism + ########################################### + + if ( $installer::globals::simple ) { installer::worker::install_simple($onepackagename, $$languagestringref, $dirsinpackage, $filesinpackage, $linksinpackage, $unixlinksinpackage); } + + ########################################### + # Checking epm state + ########################################### + + if (( $installer::globals::call_epm ) && ( ! $found_epm )) + { + $epmexecutable = installer::epmfile::find_epm_on_system($includepatharrayref); + installer::epmfile::set_patch_state($epmexecutable); # setting $installer::globals::is_special_epm + $found_epm = 1; # searching only once + } + + ########################################### + # Creating epm list file + ########################################### + + if ( ! $installer::globals::simple ) + { + # epm list file format: + # type mode owner group destination source options + # Example for a file: f 755 root sys /usr/bin/foo foo + # Example for a directory: d 755 root sys /var/spool/foo - + # Example for a link: l 000 root sys /usr/bin/linkname filename + # The source field specifies the file to link to + + my $epmfilename = "epm_" . $onepackagename . $linkaddon . ".lst"; + + installer::logger::print_message( "... creating epm list file $epmfilename ... \n" ); + + my $completeepmfilename = $listfiledir . $installer::globals::separator . $epmfilename; + + my @epmfile = (); + + my $epmheaderref = installer::epmfile::create_epm_header($allvariableshashref, $filesinproductlanguageresolvedarrayref, $languagesarrayref, $onepackage); + installer::epmfile::adding_header_to_epm_file(\@epmfile, $epmheaderref); + + if (( $installer::globals::patch ) && ( $installer::globals::issolarispkgbuild )) + { + $filesinpackage = installer::worker::analyze_patch_files($filesinpackage); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "files4_" . $packagename . ".log", $filesinpackage); } + + if ( ! ( $#{$filesinpackage} > -1 )) + { + push(@installer::globals::emptypackages, $packagename); + $infoline = "\nNo file in package: $packagename \-\> Skipping\n"; + push(@installer::globals::logfileinfo, $infoline); + next; # next package, end of loop ! + } + } + + # adding directories, files and links into epm file + + installer::epmfile::put_directories_into_epmfile($dirsinpackage, \@epmfile, $allvariableshashref, $packagerootpath); + installer::epmfile::put_files_into_epmfile($filesinpackage, \@epmfile ); + installer::epmfile::put_links_into_epmfile($linksinpackage, \@epmfile ); + installer::epmfile::put_unixlinks_into_epmfile($unixlinksinpackage, \@epmfile ); + + if ((!( $shellscriptsfilename eq "" )) && (!($installer::globals::iswindowsbuild))) { installer::epmfile::adding_shellscripts_to_epm_file(\@epmfile, $shellscriptsfilename, $packagerootpath, $allvariableshashref, $filesinpackage); } + + installer::files::save_file($completeepmfilename ,\@epmfile); + + # ... splitting the rootpath into a relocatable part and a static part, if possible + + my $staticpath = ""; + my $relocatablepath = ""; + # relocatable path can be defined in package list + if ( $onepackage->{'relocatablepath'} ) { $relocatablepath = $onepackage->{'relocatablepath'}; } + # setting fix part and variable part of destination path + installer::epmfile::analyze_rootpath($packagerootpath, \$staticpath, \$relocatablepath, $allvariableshashref); + + # ... replacing the variable PRODUCTDIRECTORYNAME in the shellscriptfile by $staticpath + + installer::epmfile::resolve_path_in_epm_list_before_packaging(\@epmfile, $completeepmfilename, "PRODUCTDIRECTORYNAME", $staticpath); + installer::epmfile::resolve_path_in_epm_list_before_packaging(\@epmfile, $completeepmfilename, "SOLSUREPACKAGEPREFIX", $allvariableshashref->{'SOLSUREPACKAGEPREFIX'}); + installer::epmfile::resolve_path_in_epm_list_before_packaging(\@epmfile, $completeepmfilename, "UREPACKAGEPREFIX", $allvariableshashref->{'UREPACKAGEPREFIX'}); + # installer::epmfile::resolve_path_in_epm_list_before_packaging(\@epmfile, $completeepmfilename, "BASISDIRECTORYVERSION", $allvariableshashref->{'OOOBASEVERSION'}); + installer::files::save_file($completeepmfilename ,\@epmfile); + + ####################################################### + # Now the complete content of the package is known, + # including variables and shell scripts. + # Create the package or using the package pool? + ####################################################### + + my $use_package_from_pool = 0; + if ( $allvariableshashref->{'POOLPRODUCT'} ) { $use_package_from_pool = installer::packagepool::package_is_up_to_date($allvariableshashref, $onepackage, $packagename, \@epmfile, $filesinpackage, $installdir, $installer::globals::epmoutpath, $languagestringref); } + + if ( $use_package_from_pool == 3 ) # repeat this package later + { + my $package_is_creatable = installer::packagepool::check_package_availability($packagename); + + if (( ! $package_is_creatable ) && ( ! exists($installer::globals::poolshiftedpackages{$packagename}) )) + { + splice(@{$packages}, $k, 1); # removing package ... + push(@{$packages}, $onepackage); # ... and adding it to the end + $installer::globals::poolshiftedpackages{$packagename} = 1; # only shifting each package once + $k--; # decreasing the counter + my $localinfoline = "\nPool: Package \"$packagename\" cannot be created at the moment. Trying again later (2).\n"; + installer::logger::print_message($localinfoline); + push( @installer::globals::logfileinfo, $localinfoline); + next; # repeating this iteration with new package + } + } + + if ( $use_package_from_pool == 4 ) # There was a problem with pooling. Repeat this package immediately. + { + $k--; # decreasing the counter + my $localinfoline = "\nPool: Package \"$packagename\" had pooling problems. Repeating packaging immediately (3).\n"; + installer::logger::print_message($localinfoline); + push( @installer::globals::logfileinfo, $localinfoline); + next; # repeating this iteration + } + + if ( $use_package_from_pool == 0 ) + { + # changing into the "install" directory to create installation sets + + $currentdir = cwd(); # $currentdir is global in this file + + chdir($installdir); # changing into install directory ($installdir is global in this file) + + ########################################### + # Starting epm + ########################################### + + # With a patched epm, it is now possible to set the relocatable directory, change + # the directory in which the packages are created, setting "requires" and "provides" + # (Linux) or creating the "depend" file (Solaris) and finally to begin + # the packaging process with standard tooling and standard parameter + # Linux: Adding into the spec file: Prefix: /opt + # Solaris: Adding into the pkginfo file: BASEDIR=/opt + # Attention: Changing of the path can influence the shell scripts + + if (( $installer::globals::is_special_epm ) && ( ($installer::globals::islinuxrpmbuild) || ($installer::globals::issolarispkgbuild) )) # special handling only for Linux RPMs and Solaris Packages + { + if ( $installer::globals::call_epm ) # only do something, if epm is really executed + { + # ... now epm can be started, to create the installation sets + + installer::logger::print_message( "... starting patched epm ... \n" ); + + installer::epmfile::call_epm($epmexecutable, $completeepmfilename, $packagename, $includepatharrayref); + + my $newepmdir = installer::epmfile::prepare_packages($loggingdir, $packagename, $staticpath, $relocatablepath, $onepackage, $allvariableshashref, $filesinpackage, $languagestringref); # adding the line for Prefix / Basedir, include rpmdir + + installer::epmfile::create_packages_without_epm($newepmdir, $packagename, $includepatharrayref, $allvariableshashref, $languagestringref); # start to package + + # finally removing all temporary files + + installer::epmfile::remove_temporary_epm_files($newepmdir, $loggingdir, $packagename); + + # Installation: + # Install: pkgadd -a myAdminfile -d ./SUNWso8m34.pkg + # Install: rpm -i --prefix=/opt/special --nodeps so8m35.rpm + + installer::epmfile::create_new_directory_structure($newepmdir); + $installer::globals::postprocess_specialepm = 1; + + if (( $installer::globals::patch ) && ( $installer::globals::issolarisx86build )) { installer::worker::fix2_solaris_x86_patch($packagename, $installer::globals::epmoutpath); } + } + } + else # this is the standard epm (not relocatable) or ( nonlinux and nonsolaris ) + { + installer::epmfile::resolve_path_in_epm_list_before_packaging(\@epmfile, $completeepmfilename, "\$\$PRODUCTINSTALLLOCATION", $relocatablepath); + installer::files::save_file($completeepmfilename ,\@epmfile); # Warning for pool, content of epm file is changed. + + if ( $installer::globals::call_epm ) + { + # ... now epm can be started, to create the installation sets + + installer::logger::print_message( "... starting unpatched epm ... \n" ); + + if ( $installer::globals::call_epm ) { installer::epmfile::call_epm($epmexecutable, $completeepmfilename, $packagename, $includepatharrayref); } + + if (($installer::globals::islinuxrpmbuild) || ($installer::globals::issolarispkgbuild) || ($installer::globals::debian)) + { + $installer::globals::postprocess_standardepm = 1; + } + } + } + + if ( $allvariableshashref->{'POOLPRODUCT'} ) { installer::packagepool::put_content_into_pool($packagename, $installdir, $installer::globals::epmoutpath, $filesinpackage, \@epmfile); } + + chdir($currentdir); # changing back into start directory + + } # end of "if ( ! $use_package_from_pool ) + + } # end of "if ( ! $installer::globals::simple ) + + ########################################### + # xpd installation mechanism + ########################################### + + # Creating the xpd file for the package. This has to happen always, not determined by $use_package_from_pool + + if ( $installer::globals::isxpdplatform ) + { + if (( ! $installer::globals::languagepack ) && ( ! $installer::globals::patch )) + { + if (( $allvariableshashref->{'XPDINSTALLER'} ) && ( $installer::globals::call_epm != 0 )) + { + installer::xpdinstaller::create_xpd_file($onepackage, $packages, $languagestringref, $allvariableshashref, $modulesinproductarrayref, $installdir, $installer::globals::epmoutpath, $linkpackage, \%installer::globals::xpdpackageinfo); + $installer::globals::xpd_files_prepared = 1; + %installer::globals::xpdpackageinfo = (); + } + } + } + + if ( $installer::globals::makelinuxlinkrpm ) { $k--; } # decreasing the counter to create the link rpm! + + } # end of "for ( my $k = 0; $k <= $#{$packages}; $k++ )" + + installer::packagepool::log_pool_statistics(); + + ############################################################## + # Post epm functionality, after the last package is packed + ############################################################## + + if ( $installer::globals::postprocess_specialepm ) + { + installer::logger::include_header_into_logfile("Post EPM processes (Patched EPM):"); + + chdir($installdir); + + # Copying the cde, kde and gnome packages into the installation set + if ( $installer::globals::addsystemintegration ) { installer::epmfile::put_systemintegration_into_installset($installer::globals::epmoutpath, $includepatharrayref, $allvariableshashref, $modulesinproductarrayref); } + + # Adding license and readme into installation set + # if ($installer::globals::addlicensefile) { installer::epmfile::put_installsetfiles_into_installset($installer::globals::epmoutpath); } + if ($installer::globals::addlicensefile) { installer::worker::put_scpactions_into_installset("."); } + + # Adding child projects to installation dynamically + if ($installer::globals::addchildprojects) { installer::epmfile::put_childprojects_into_installset($installer::globals::epmoutpath, $allvariableshashref, $modulesinproductarrayref, $includepatharrayref); } + + # Adding license file into setup + if ( $allvariableshashref->{'PUT_LICENSE_INTO_SETUP'} ) { installer::worker::put_license_into_setup(".", $includepatharrayref); } + + # Creating installation set for Unix language packs, that are not part of multi lingual installation sets + if ( ( $installer::globals::languagepack ) && ( ! $installer::globals::debian ) && ( ! $installer::globals::makedownload ) ) { installer::languagepack::build_installer_for_languagepack($installer::globals::epmoutpath, $allvariableshashref, $includepatharrayref, $languagesarrayref, $languagestringref); } + + # Finalizing patch installation sets + if (( $installer::globals::patch ) && ( $installer::globals::issolarispkgbuild )) { installer::epmfile::finalize_patch($installer::globals::epmoutpath, $allvariableshashref); } + if (( $installer::globals::patch ) && ( $installer::globals::islinuxrpmbuild )) { installer::epmfile::finalize_linux_patch($installer::globals::epmoutpath, $allvariableshashref, $includepatharrayref); } + + # Copying the xpd installer into the installation set + if (( $allvariableshashref->{'XPDINSTALLER'} ) && ( $installer::globals::isxpdplatform ) && ( $installer::globals::xpd_files_prepared )) + { + installer::xpdinstaller::create_xpd_installer($installdir, $allvariableshashref, $languagestringref); + $installer::globals::addjavainstaller = 0; # only one java installer possible + } + + # Copying the java installer into the installation set + chdir($currentdir); # changing back into start directory + if ( $installer::globals::addjavainstaller ) { installer::javainstaller::create_java_installer($installdir, $installer::globals::epmoutpath, $languagestringref, $languagesarrayref, $allvariableshashref, $includepatharrayref, $modulesinproductarrayref); } + } + + if ( $installer::globals::postprocess_standardepm ) + { + installer::logger::include_header_into_logfile("Post EPM processes (Standard EPM):"); + + chdir($installdir); + + # determine the destination directory + my $newepmdir = installer::epmfile::determine_installdir_ooo(); + + # Copying the cde, kde and gnome packages into the installation set + if ( $installer::globals::addsystemintegration ) { installer::epmfile::put_systemintegration_into_installset($newepmdir, $includepatharrayref, $allvariableshashref, $modulesinproductarrayref); } + + # Adding license and readme into installation set + # if ($installer::globals::addlicensefile) { installer::epmfile::put_installsetfiles_into_installset($newepmdir); } + if ($installer::globals::addlicensefile) { installer::worker::put_scpactions_into_installset("."); } + + # Adding license file into setup + if ( $allvariableshashref->{'PUT_LICENSE_INTO_SETUP'} ) { installer::worker::put_license_into_setup(".", $includepatharrayref); } + + # Creating installation set for Unix language packs, that are not part of multi lingual installation sets + if ( ( $installer::globals::languagepack ) && ( ! $installer::globals::debian ) && ( ! $installer::globals::makedownload ) ) { installer::languagepack::build_installer_for_languagepack($newepmdir, $allvariableshashref, $includepatharrayref, $languagesarrayref, $languagestringref); } + + chdir($currentdir); # changing back into start directory + } + + if (( $installer::globals::issolarispkgbuild ) && ( $allvariableshashref->{'COLLECT_PKGMAP'} )) { installer::worker::collectpackagemaps($installdir, $languagestringref, $allvariableshashref); } + + ####################################################### + # Analyzing the log file + ####################################################### + + my $is_success = 0; + my $finalinstalldir = ""; + + installer::worker::clean_output_tree(); # removing directories created in the output tree + ($is_success, $finalinstalldir) = installer::worker::analyze_and_save_logfile($loggingdir, $installdir, $installlogdir, $allsettingsarrayref, $languagestringref, $current_install_number); + my $downloadname = installer::ziplist::getinfofromziplist($allsettingsarrayref, "downloadname"); + if ( $is_success ) { installer::followme::save_followme_info($finalinstalldir, $includepatharrayref, $allvariableshashref, $$downloadname, $languagestringref, $languagesarrayref, $current_install_number, $loggingdir, $installlogdir); } + + ####################################################### + # Creating download installation set + ####################################################### + + if ( $installer::globals::makedownload ) + { + my $create_download = 0; + if ( $$downloadname ne "" ) { $create_download = 1; } + if (( $is_success ) && ( $create_download ) && ( $ENV{'ENABLE_DOWNLOADSETS'} )) + { + my $downloaddir = installer::download::create_download_sets($finalinstalldir, $includepatharrayref, $allvariableshashref, $$downloadname, $languagestringref, $languagesarrayref); + installer::worker::analyze_and_save_logfile($loggingdir, $downloaddir, $installlogdir, $allsettingsarrayref, $languagestringref, $current_install_number); + } + } + + ####################################################### + # Creating jds installation set + ####################################################### + + if ( $installer::globals::makejds ) + { + my $create_jds = 0; + + if ( $allvariableshashref->{'JDSBUILD'} ) { $create_jds = 1; } + if (! $installer::globals::issolarispkgbuild ) { $create_jds = 0; } + + if (( $is_success ) && ( $create_jds )) + { + if ( ! $installer::globals::jds_language_controlled ) + { + my $correct_language = installer::worker::check_jds_language($allvariableshashref, $languagestringref); + $installer::globals::correct_jds_language = $correct_language; + $installer::globals::jds_language_controlled = 1; + } + + if ( $installer::globals::correct_jds_language ) + { + my $jdsdir = installer::worker::create_jds_sets($finalinstalldir, $allvariableshashref, $languagestringref, $languagesarrayref, $includepatharrayref); + installer::worker::clean_jds_temp_dirs(); + installer::worker::analyze_and_save_logfile($loggingdir, $jdsdir, $installlogdir, $allsettingsarrayref, $languagestringref, $current_install_number); + } + } + } + + } # end of "if (!( $installer::globals::iswindowsbuild ))" + + if ( $installer::globals::debug ) { installer::logger::debuginfo("\nEnd of part 2a: All non-Windows platforms\n"); } + + ################################################# + # Part 2b: The Windows platform + ################################################# + + if ( $installer::globals::debug ) { installer::logger::debuginfo("\nPart 2b: The Windows platform\n"); } + + ##################################################################### + # ... creating idt files ... + # Only for Windows builds ($installer::globals::compiler is wntmsci) + ##################################################################### + + if ( $installer::globals::iswindowsbuild ) + { + ########################################### + # Stripping libraries + ########################################### + + # Building for gcc build in cws requires, that all files are stripped before packaging: + # 1. copy all files that need to be stripped locally + # 2. strip all these files + + if ( $installer::globals::compiler =~ /wntgcci/ ) + { + installer::windows::strip::strip_binaries($filesinproductlanguageresolvedarrayref, $languagestringref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles16e.log", $filesinproductlanguageresolvedarrayref); } + } + + $installdir = installer::worker::create_installation_directory($shipinstalldir, $languagestringref, \$current_install_number); + + my $idtdirbase = installer::systemactions::create_directories("idt_files", $languagestringref); + $installer::globals::infodirectory = installer::systemactions::create_directories("info_files", $languagestringref); + my $installlogdir = installer::systemactions::create_directory_next_to_directory($installdir, "log"); + # my $installchecksumdir = installer::systemactions::create_directory_next_to_directory($installdir, "checksum"); + + ################################################################################# + # Preparing cabinet files from package definitions + ################################################################################# + + # installer::packagelist::prepare_cabinet_files($packages, $allvariableshashref, $$languagestringref); + installer::packagelist::prepare_cabinet_files($packages, $allvariableshashref); + # printing packages content: + installer::packagelist::log_cabinet_assignments(); + + ################################################################################# + # Begin of functions that are used for the creation of idt files (Windows only) + ################################################################################# + + installer::logger::print_message( "... creating idt files ...\n" ); + + installer::logger::include_header_into_logfile("Creating idt files:"); + + my $newidtdir = $idtdirbase . $installer::globals::separator . "00"; # new files into language independent directory "00" + installer::systemactions::create_directory($newidtdir); + + my @allfilecomponents = (); + my @allregistrycomponents = (); + + # Collecting all files with flag "BINARYTABLE" + my $binarytablefiles = installer::worker::collect_all_items_with_special_flag($filesinproductlanguageresolvedarrayref ,"BINARYTABLE"); + + # Removing all files with flag "BINARYTABLE_ONLY" + @installer::globals::binarytableonlyfiles = (); + $filesinproductlanguageresolvedarrayref = installer::worker::remove_all_items_with_special_flag($filesinproductlanguageresolvedarrayref ,"BINARYTABLE_ONLY"); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles17.log", $filesinproductlanguageresolvedarrayref); } + + # Collecting all profileitems with flag "INIFILETABLE" for table "IniFile" + my $inifiletableentries = installer::worker::collect_all_items_with_special_flag($profileitemsinproductlanguageresolvedarrayref ,"INIFILETABLE"); + + # Creating the important dynamic idt files + installer::windows::msiglobal::set_msiproductversion($allvariableshashref); + installer::windows::msiglobal::put_msiproductversion_into_bootstrapfile($filesinproductlanguageresolvedarrayref); + + # Add cabinet assignments to files + installer::windows::file::assign_cab_to_files($filesinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles17a.log", $filesinproductlanguageresolvedarrayref); } + installer::windows::file::assign_sequencenumbers_to_files($filesinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles17b.log", $filesinproductlanguageresolvedarrayref); } + + # Collection all available directory trees + installer::windows::directory::collectdirectorytrees($directoriesforepmarrayref); + + $filesinproductlanguageresolvedarrayref = installer::windows::file::create_files_table($filesinproductlanguageresolvedarrayref, \@allfilecomponents, $newidtdir, $allvariableshashref, $uniquefilename, $allupdatesequences, $allupdatecomponents, $allupdatefileorder); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles17c.log", $filesinproductlanguageresolvedarrayref); } + if ( $installer::globals::updatedatabase ) { installer::windows::file::check_file_sequences($allupdatefileorder, $allupdatecomponentorder); } + + installer::windows::directory::create_directory_table($directoriesforepmarrayref, $newidtdir, $allvariableshashref, $shortdirname); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles18.log", $filesinproductlanguageresolvedarrayref); } + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforidt1.log", $directoriesforepmarrayref); } + + # Attention: The table "Registry.idt" contains language specific strings -> parameter: $languagesarrayref ! + installer::windows::registry::create_registry_table($registryitemsinproductlanguageresolvedarrayref, \@allregistrycomponents, $newidtdir, $languagesarrayref, $allvariableshashref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "registryitems4.log", $registryitemsinproductlanguageresolvedarrayref); } + + installer::windows::component::create_component_table($filesinproductlanguageresolvedarrayref, $registryitemsinproductlanguageresolvedarrayref, $directoriesforepmarrayref, \@allfilecomponents, \@allregistrycomponents, $newidtdir, $componentid, $componentidkeypath); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles19.log", $filesinproductlanguageresolvedarrayref); } + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "registryitems5.log", $registryitemsinproductlanguageresolvedarrayref); } + + # Attention: The table "Feature.idt" contains language specific strings -> parameter: $languagesarrayref ! + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "modules4.log", $modulesinproductlanguageresolvedarrayref); } + installer::windows::feature::add_uniquekey($modulesinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "modules4a.log", $modulesinproductlanguageresolvedarrayref); } + $modulesinproductlanguageresolvedarrayref = installer::windows::feature::sort_feature($modulesinproductlanguageresolvedarrayref); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "modules4b.log", $modulesinproductlanguageresolvedarrayref); } + installer::windows::feature::create_feature_table($modulesinproductlanguageresolvedarrayref, $newidtdir, $languagesarrayref, $allvariableshashref); + + installer::windows::featurecomponent::create_featurecomponent_table($filesinproductlanguageresolvedarrayref, $registryitemsinproductlanguageresolvedarrayref, $newidtdir); + + installer::windows::media::create_media_table($filesinproductlanguageresolvedarrayref, $newidtdir, $allvariableshashref, $allupdatelastsequences, $allupdatediskids); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "productfiles20.log", $filesinproductlanguageresolvedarrayref); } + + installer::windows::font::create_font_table($filesinproductlanguageresolvedarrayref, $newidtdir); + + # Attention: The table "Shortcut.idt" contains language specific strings -> parameter: $languagesarrayref ! + # Attention: Shortcuts (Folderitems) have icon files, that have to be copied into the Icon directory (last parameter) + my @iconfilecollector = (); + + installer::windows::shortcut::create_shortcut_table($filesinproductlanguageresolvedarrayref, $linksinproductlanguageresolvedarrayref, $folderinproductlanguageresolvedarrayref, $folderitemsinproductlanguageresolvedarrayref, $directoriesforepmarrayref, $newidtdir, $languagesarrayref, $includepatharrayref, \@iconfilecollector); + if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "folderitems4.log", $folderitemsinproductlanguageresolvedarrayref); } + + installer::windows::inifile::create_inifile_table($inifiletableentries, $filesinproductlanguageresolvedarrayref, $newidtdir); + + installer::windows::icon::create_icon_table(\@iconfilecollector, $newidtdir); # creating the icon table with all iconfiles used as shortcuts (FolderItems) + + installer::windows::createfolder::create_createfolder_table($directoriesforepmarrayref, $filesinproductlanguageresolvedarrayref, $newidtdir, $allvariableshashref); + + installer::windows::upgrade::create_upgrade_table($newidtdir, $allvariableshashref); + + if ( ! $installer::globals::languagepack ) # the following tables not for language packs + { + installer::windows::removefile::create_removefile_table($folderitemsinproductlanguageresolvedarrayref, $newidtdir); + + installer::windows::selfreg::create_selfreg_table($filesinproductlanguageresolvedarrayref, $newidtdir); + + # Adding Assemblies into the tables MsiAssembly and MsiAssemblyName dynamically + installer::windows::assembly::create_msiassembly_table($filesinproductlanguageresolvedarrayref, $newidtdir); + installer::windows::assembly::create_msiassemblyname_table($filesinproductlanguageresolvedarrayref, $newidtdir); + installer::windows::assembly::add_assembly_condition_into_component_table($filesinproductlanguageresolvedarrayref, $newidtdir); + } + + $infoline = "\n"; + push(@installer::globals::logfileinfo, $infoline); + + # Localizing the language dependent idt files + # For every language there will be a localized msi database + # For multilingual installation sets, the differences of this + # databases have to be stored in transforms. + + for ( my $m = 0; $m <= $#{$languagesarrayref}; $m++ ) + { + my $onelanguage = ${$languagesarrayref}[$m]; + + my $is_bidi = 0; + if ( installer::existence::exists_in_array($onelanguage, \@installer::globals::bidilanguages) ) { $is_bidi = 1; } + + my $languageidtdir = $idtdirbase . $installer::globals::separator . $onelanguage; + if ( -d $languageidtdir ) { installer::systemactions::remove_complete_directory($languageidtdir, 1); } + installer::systemactions::create_directory($languageidtdir); + + # Copy the template idt files and the new created idt files into this language directory + + installer::logger::print_message( "... copying idt files ...\n" ); + + installer::logger::include_header_into_logfile("Copying idt files to $languageidtdir:"); + + installer::windows::idtglobal::prepare_language_idt_directory($languageidtdir, $newidtdir, $onelanguage, $filesinproductlanguageresolvedarrayref, \@iconfilecollector, $binarytablefiles, $allvariableshashref); + + if ( ! $installer::globals::languagepack ) + { + # For multilingual installation sets, the dialog for the language selection can now be prepared, with + # a checkbox for each available language. This has to happen before the following translation. + # The new controls have to be added into the Control.idt + + my $controlidttablename = $languageidtdir . $installer::globals::separator . "Control.idt"; + my $controlidttable = installer::files::read_file($controlidttablename); + installer::windows::idtglobal::add_language_checkboxes_to_database($controlidttable, $languagesarrayref); + installer::files::save_file($controlidttablename, $controlidttable); + $infoline = "Added checkboxes for language selection dialog into table $controlidttablename\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + # Now all files are copied into a language specific directory + # The template idt files can be translated + + installer::logger::print_message( "... localizing idt files (language: $onelanguage) ...\n" ); + + installer::logger::include_header_into_logfile("Localizing idt files (Language: $onelanguage):"); + + my @translationfiles = (); # all idt files, that need a translation + push(@translationfiles, "ActionTe.idt"); + push(@translationfiles, "Control.idt"); + push(@translationfiles, "CustomAc.idt"); + push(@translationfiles, "Error.idt"); + push(@translationfiles, "LaunchCo.idt"); + push(@translationfiles, "RadioBut.idt"); + push(@translationfiles, "Property.idt"); + push(@translationfiles, "UIText.idt"); + + my $oneidtfilename; + my $oneidtfile; + + foreach $oneidtfilename (@translationfiles) + { + my $languagefilename = installer::windows::idtglobal::get_languagefilename($oneidtfilename, $installer::globals::idtlanguagepath); + my $languagefile = installer::files::read_file($languagefilename); + + $oneidtfilename = $languageidtdir . $installer::globals::separator . $oneidtfilename; + $oneidtfile = installer::files::read_file($oneidtfilename); + + # Now the substitution can start + installer::windows::idtglobal::translate_idtfile($oneidtfile, $languagefile, $onelanguage); + + installer::files::save_file($oneidtfilename, $oneidtfile); + + $infoline = "Translated idt file: $oneidtfilename into language $onelanguage\n"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = "Used languagefile: $languagefilename\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + # setting the encoding in every table (replacing WINDOWSENCODINGTEMPLATE) + + installer::windows::idtglobal::setencoding($languageidtdir, $onelanguage); + + # setting bidi attributes, if required + + if ( $is_bidi ) { installer::windows::idtglobal::setbidiattributes($languageidtdir, $onelanguage); } + + # setting the encoding in every table (replacing WINDOWSENCODINGTEMPLATE) + installer::windows::idtglobal::set_multilanguageonly_condition($languageidtdir); + + # include the license text into the table Control.idt + + # my $licensefilesource = installer::windows::idtglobal::get_licensefilesource($onelanguage, $filesinproductlanguageresolvedarrayref); + my $licensefilesource = installer::windows::idtglobal::get_rtflicensefilesource($onelanguage, $includepatharrayref_lang); + my $licensefile = installer::files::read_file($licensefilesource); + installer::scpzipfiles::replace_all_ziplistvariables_in_rtffile($licensefile, $allvariablesarrayref, $onelanguage, $loggingdir); + my $controltablename = $languageidtdir . $installer::globals::separator . "Control.idt"; + my $controltable = installer::files::read_file($controltablename); + installer::windows::idtglobal::add_licensefile_to_database($licensefile, $controltable); + installer::files::save_file($controltablename, $controltable); + + $infoline = "Added licensefile $licensefilesource into database $controltablename\n"; + push(@installer::globals::logfileinfo, $infoline); + + # include office directory in CustomAction table + + installer::windows::idtglobal::add_officedir_to_database($languageidtdir, $allvariableshashref); + + # include a component into environment table if required + + installer::windows::component::set_component_in_environment_table($languageidtdir, $filesinproductlanguageresolvedarrayref); + + # include the ProductCode and the UpgradeCode from codes-file into the Property.idt + + installer::windows::property::set_codes_in_property_table($languageidtdir); + + # the language specific properties can now be set in the Property.idt + + installer::windows::property::update_property_table($languageidtdir, $onelanguage, $allvariableshashref, $languagestringref); + + # replacing variables in RegLocat.idt + + installer::windows::msiglobal::update_reglocat_table($languageidtdir, $allvariableshashref); + + # replacing variables in RemoveRe.idt (RemoveRegistry.idt) + + installer::windows::msiglobal::update_removere_table($languageidtdir); + + # adding language specific properties for multilingual installation sets + + installer::windows::property::set_languages_in_property_table($languageidtdir, $languagesarrayref); + + # adding settings into CheckBox.idt + installer::windows::property::update_checkbox_table($languageidtdir, $allvariableshashref); + + # adding the files from the binary directory into the binary table + installer::windows::binary::update_binary_table($languageidtdir, $filesinproductlanguageresolvedarrayref, $binarytablefiles); + + # setting patch codes to detect installed products + + if (( $installer::globals::patch ) || ( $installer::globals::languagepack ) || ( $allvariableshashref->{'PDFCONVERTER'} )) { installer::windows::patch::update_patch_tables($languageidtdir, $allvariableshashref); } + + # Adding Windows Installer CustomActions + + installer::windows::idtglobal::addcustomactions($languageidtdir, $windowscustomactionsarrayref, $filesinproductlanguageresolvedarrayref); + + # Adding child projects if specified + + if ($installer::globals::addchildprojects) + { + # Adding child projects to installation dynamically (also in feature table) + installer::windows::idtglobal::add_childprojects($languageidtdir, $filesinproductlanguageresolvedarrayref, $allvariableshashref); + # setting Java variables for Java products + if ( $allvariableshashref->{'JAVAPRODUCT'} ) { installer::windows::java::update_java_tables($languageidtdir, $allvariableshashref); } + } + + # Then the language specific msi database can be created + + if ( $installer::globals::iswin ) # only possible on a Windows platform + { + my $msidatabasename = installer::windows::msiglobal::get_msidatabasename($allvariableshashref, $onelanguage); + my $msifilename = $languageidtdir . $installer::globals::separator . $msidatabasename; + + installer::logger::print_message( "... creating msi database (language $onelanguage) ... \n" ); + + installer::windows::msiglobal::set_uuid_into_component_table($languageidtdir, $allvariableshashref); # setting new GUID for the components using the tool uuidgen.exe + installer::windows::msiglobal::create_msi_database($languageidtdir ,$msifilename); + + # validating the database # ToDo + + my $languagefile = installer::files::read_file($installer::globals::idtlanguagepath . $installer::globals::separator . "SIS.mlf"); + # my $languagefile = installer::files::read_file($installer::globals::idtlanguagepath . $installer::globals::separator . "SIS.ulf"); + + installer::windows::msiglobal::write_summary_into_msi_database($msifilename, $onelanguage, $languagefile, $allvariableshashref); + + # if there are Merge Modules, they have to be integrated now + $filesinproductlanguageresolvedarrayref = installer::windows::mergemodule::merge_mergemodules_into_msi_database($mergemodulesarrayref, $filesinproductlanguageresolvedarrayref, $msifilename, $languagestringref, $onelanguage, $languagefile, $allvariableshashref, $includepatharrayref, $allupdatesequences, $allupdatelastsequences, $allupdatediskids); + if (( $installer::globals::globallogging ) && ($installer::globals::globalloggingform21)) { installer::files::save_array_of_hashes($loggingdir . "productfiles21_" . $onelanguage . ".log", $filesinproductlanguageresolvedarrayref); } + $installer::globals::globalloggingform21 = 0; + if ( $installer::globals::use_packages_for_cabs ) { installer::windows::media::create_media_table($filesinproductlanguageresolvedarrayref, $newidtdir, $allvariableshashref, $allupdatelastsequences, $allupdatediskids); } + + # copy msi database into installation directory + + my $msidestfilename = $installdir . $installer::globals::separator . $msidatabasename; + installer::systemactions::copy_one_file($msifilename, $msidestfilename); + } + } + + # Creating transforms, if the installation set has more than one language + # renaming the msi database and generating the setup.ini file + + my $defaultlanguage = installer::languages::get_default_language($languagesarrayref); + + if ( $installer::globals::iswin ) # only possible on a Windows platform + { + if ( $#{$languagesarrayref} > 0 ) + { + installer::windows::msiglobal::create_transforms($languagesarrayref, $defaultlanguage, $installdir, $allvariableshashref); + } + + installer::windows::msiglobal::rename_msi_database_in_installset($defaultlanguage, $installdir, $allvariableshashref); + + if ( $allvariableshashref->{'ADDLANGUAGEINDATABASENAME'} ) { installer::windows::msiglobal::add_language_to_msi_database($defaultlanguage, $installdir, $allvariableshashref); } + + installer::logger::print_message( "... generating setup.ini ...\n" ); + + if ( ! $allvariableshashref->{'NOLOADERREQUIRED'} ) { installer::windows::msiglobal::create_setup_ini($languagesarrayref, $defaultlanguage, $installdir, $allvariableshashref); } + } + + # Analyzing the ScpActions and copying the files into the installation set + # At least the loader, instmsia.exe and instmsiw.exe + + installer::logger::print_message( "... copying files into installation set ...\n" ); + + # installer::windows::msiglobal::copy_scpactions_into_installset($defaultlanguage, $installdir, $scpactionsinproductlanguageresolvedarrayref); + installer::worker::put_scpactions_into_installset($installdir); + + # ... copying the setup.exe, instmsia.exe and instmsiw.exe + + installer::windows::msiglobal::copy_windows_installer_files_into_installset($installdir, $includepatharrayref, $allvariableshashref); + + # ... copying MergeModules into installation set + + if ( ! $installer::globals::fix_number_of_cab_files ) { installer::windows::msiglobal::copy_merge_modules_into_installset($installdir); } + + # ... copying the child projects + + if ($installer::globals::addchildprojects) + { + installer::windows::msiglobal::copy_child_projects_into_installset($installdir, $allvariableshashref); + } + + installer::logger::print_message( "... creating ddf files ...\n" ); + + # Creating all needed ddf files and generating a list + # for the package process containing all system calls + + my $ddfdir = installer::systemactions::create_directories("ddf", $languagestringref); + + $installer::globals::packjobref = installer::windows::msiglobal::generate_cab_file_list($filesinproductlanguageresolvedarrayref, $installdir, $ddfdir, $allvariableshashref); + + # Update and patch reasons the pack order needs to be saved + installer::windows::msiglobal::save_packorder(); + + $infoline = "\n"; + push(@installer::globals::logfileinfo, $infoline); + + #################################### + # Writing log file + # before cab files are packed + #################################### + + installer::logger::print_message( "... creating log file $installer::globals::logfilename \n" ); + + installer::files::save_file($loggingdir . $installer::globals::logfilename, \@installer::globals::logfileinfo); + + ####################################################### + # Finally really create the installation packages, + # Only for Windows and only on a windows platform. + ####################################################### + + if ( $installer::globals::iswin ) # only possible on a Windows platform + { + installer::logger::print_message( "... packaging installation set ... \n" ); + installer::windows::msiglobal::execute_packaging($installer::globals::packjobref, $loggingdir, $allvariableshashref); + if ( $installer::globals::include_cab_in_msi ) { installer::windows::msiglobal::include_cabs_into_msi($installdir); } + + #################################### + # Writing log file + # after cab files are packed + #################################### + + installer::logger::print_message( "\n... creating log file $installer::globals::logfilename \n" ); + installer::files::save_file($loggingdir . $installer::globals::logfilename, \@installer::globals::logfileinfo); + } + + ####################################################### + # Analyzing the log file + ####################################################### + + my $is_success = 0; + my $finalinstalldir = ""; + installer::worker::clean_output_tree(); # removing directories created in the output tree + ($is_success, $finalinstalldir) = installer::worker::analyze_and_save_logfile($loggingdir, $installdir, $installlogdir, $allsettingsarrayref, $languagestringref, $current_install_number); + + ####################################################### + # Creating Windows msp patches + ####################################################### + + if (( $is_success ) && ( $installer::globals::updatedatabase ) && ( $allvariableshashref->{'CREATE_MSP_INSTALLSET'} ) && ( ! ( $^O =~ /cygwin/i ))) # not supported for cygwin yet + { + # Required: + # Temp path for administrative installations: $installer::globals::temppath + # Path of new installation set: $finalinstalldir + # Path of old installation set: $installer::globals::updatedatabasepath + my $mspdir = installer::windows::msp::create_msp_patch($finalinstalldir, $includepatharrayref, $allvariableshashref, $languagestringref, $filesinproductlanguageresolvedarrayref); + ($is_success, $finalinstalldir) = installer::worker::analyze_and_save_logfile($loggingdir, $mspdir, $installlogdir, $allsettingsarrayref, $languagestringref, $current_install_number); + installer::worker::clean_output_tree(); # removing directories created in the output tree + } + + ####################################################### + # Creating download installation set + ####################################################### + + my $create_download = 0; + my $downloadname = installer::ziplist::getinfofromziplist($allsettingsarrayref, "downloadname"); + if ( $installer::globals::languagepack ) { $downloadname = installer::ziplist::getinfofromziplist($allsettingsarrayref, "langpackdownloadname"); } + if ( $installer::globals::patch ) { $downloadname = installer::ziplist::getinfofromziplist($allsettingsarrayref, "patchdownloadname"); } + + if ( $is_success ) { installer::followme::save_followme_info($finalinstalldir, $includepatharrayref, $allvariableshashref, $$downloadname, $languagestringref, $languagesarrayref, $current_install_number, $loggingdir, $installlogdir); } + + if ( $$downloadname ne "" ) { $create_download = 1; } + if (( $is_success ) && ( $create_download ) && ( $ENV{'ENABLE_DOWNLOADSETS'} )) + { + my $downloaddir = installer::download::create_download_sets($finalinstalldir, $includepatharrayref, $allvariableshashref, $$downloadname, $languagestringref, $languagesarrayref); + installer::worker::analyze_and_save_logfile($loggingdir, $downloaddir, $installlogdir, $allsettingsarrayref, $languagestringref, $current_install_number); + } + + } # end of "if ( $installer::globals::iswindowsbuild )" + + if ( $installer::globals::debug ) { installer::logger::debuginfo("\nEnd of part 2b: The Windows platform\n"); } + + # saving file_info file for later analysis + my $speciallogfilename = "fileinfo_" . $installer::globals::product . "\.log"; + installer::files::save_array_of_hashes($loggingdir . $speciallogfilename, $filesinproductlanguageresolvedarrayref); + +} # end of iteration for one language group + +# saving debug info at end +if ( $installer::globals::debug ) { installer::logger::savedebug($installer::globals::exitlog); } + +####################################################### +# Stopping time +####################################################### + +installer::logger::stoptime(); + +#################################### +# Main program end +#################################### diff --git a/solenv/bin/makedepn b/solenv/bin/makedepn new file mode 100755 index 000000000000..c08ea38d0f30 --- /dev/null +++ b/solenv/bin/makedepn @@ -0,0 +1,13 @@ +#!/bin/sh -e +if [ -z "$1" ]; then + exit 1; +fi +infile=`echo "$1" | sed 's/^@//'` +for i in `cat "$infile"`; do + i=`echo "$i" | fgrep -- "-O:" | awk -F: '{print $2}'` + if [ ! -z "$i" ]; then + echo "#" > "$i" + exit 0; + fi; +done +exit 1 diff --git a/solenv/bin/makemani.pl b/solenv/bin/makemani.pl new file mode 100644 index 000000000000..df11a50c7e17 --- /dev/null +++ b/solenv/bin/makemani.pl @@ -0,0 +1,116 @@ +#! /usr/bin/perl -w + eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' + if 0; #$running_under_some_shell +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makemani.pl,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +use strict; +use File::Find (); +use Cwd qw (cwd); + +my @findlist; + +# Set the variable $File::Find::dont_use_nlink if you're using AFS, +# since AFS cheats. + +# for the convenience of &wanted calls, including -eval statements: +use vars qw/*name *dir *prune/; +*name = *File::Find::name; +*dir = *File::Find::dir; +*prune = *File::Find::prune; + +sub wanted; + + + +sub wanted { + /^.*\.xc(s|u)\z/s + && ( push @findlist, $name ); +# && ( push @findlist, $name ) && print("$name\n"); +} + +sub usage +{ + print STDERR "\n$0 - append *.xcu file entries to .oxt manifest.xml\n\n"; + print STDERR "usage: $0 <static_part> <start dir> <search dir> <destination dir>\n\n"; + print STDERR " static part - file containig all other content for mainfest.xml\n"; + print STDERR " start dir - directory to change to before starting search\n"; + print STDERR " out dir - destination directory to write manifes.xml to\n\n"; + exit 1; +} + +if ( $#ARGV != 3 ) { usage(); }; + +my $manifest_head = $ARGV[0]; +my $start_dir = $ARGV[1]; +my $dynamic_dir = $ARGV[2]; +my $out_dir = $ARGV[3]; + +print "################################################\n"; +print "# #\n"; +print "# just a prototype - for testing purpose only! #\n"; +print "# #\n"; +print "################################################\n\n"; + + +# Traverse desired filesystems +my $work_dir = cwd(); +chdir $start_dir or die "$0: ERROR - cannot change directory to \"$start_dir\"\n"; +File::Find::find({wanted => \&wanted}, $dynamic_dir); +chdir $work_dir or die "$0: ERROR - oops... cannot change dir to where i came from!\n"; + +open (HEAD, "$manifest_head") or die "$0: ERROR - Cannot open $manifest_head\n"; +my @headlines = <HEAD>; +close HEAD; +chomp @headlines; +chomp @findlist; + +my @bodylines; +my @taillines = ("</manifest:manifest>"); + +foreach my $i (@findlist) { + if ($i =~ m/^.*\.xcu\z/s) { + push @bodylines, " <manifest:file-entry manifest:media-type=\"application/vnd.sun.star.configuration-data\""; + } else { + push @bodylines, " <manifest:file-entry manifest:media-type=\"application/vnd.sun.star.configuration-schema\""; + } + push @bodylines, " manifest:full-path=\"$i\"/>"; +} + +open (MANIOUT,">$out_dir/manifest.xml") or die "$0: ERROR - cannot open \"$out_dir/manifest.xml\" for writing.\n"; +binmode MANIOUT; + +foreach my $j (@headlines, @bodylines, @taillines) { + print MANIOUT "$j\n"; +} + +close MANIOUT; + diff --git a/solenv/bin/mapgen.pl b/solenv/bin/mapgen.pl new file mode 100644 index 000000000000..9d1c837377b6 --- /dev/null +++ b/solenv/bin/mapgen.pl @@ -0,0 +1,211 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: mapgen.pl,v $ +# +# $Revision: 1.6 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +# +# mapgen - generate a map file for Unix libraries +# + +#use File::Path; +#use File::Copy; + +#### script id ##### + +( $script_name = $0 ) =~ s/^.*\b(\w+)\.pl$/$1/; + +$id_str = ' $Revision: 1.6 $ '; +$id_str =~ /Revision:\s+(\S+)\s+\$/ + ? ($script_rev = $1) : ($script_rev = "-"); + +print "$script_name -- version: $script_rev\n"; +print "Multi Platform Enabled Edition\n"; + +######################### +# # +# Globale Variablen # +# # +######################### + +$dump_file = ''; +$flt_file = ''; +$map_file = ''; +$first_string = ''; +$tab = ' '; + +#### main #### + +&get_options; +if (!(open (DUMP_FILE, $dump_file))) { + &print_error("Unable open $dump_file"); +}; +if (!(open (FLT_FILE, $flt_file))) { + close DUMP_FILE; + &print_error("Unable open $flt_file"); +}; +unlink $map_file; +if (!(open (MAP_FILE, ">>$map_file"))) { + close DUMP_FILE; + close FLT_FILE; + &print_error("Unable open $map_file"); +}; + +if ($ENV{OS} eq 'SOLARIS') { + &gen_sol; +} elsif ($ENV{OS} eq 'LINUX') { + &gen_lnx; +} else { + &print_error ('Environment not set!!'); +}; + +close DUMP_FILE; +close FLT_FILE; +close MAP_FILE; + +#### end of main procedure #### + +######################### +# # +# Procedures # +# # +######################### + +# +# Generate a map file for solaris +# +sub gen_sol { + my %symbols = (); + foreach (<DUMP_FILE>) { + next if (!(/\s*(\S+)\s*\|\s*(\S+)\s*\|\s*(\S+)\s*\|\s*(\S+)\s*\|\s*(\S+)\s*\|\s*(\S+)\s*\|\s*(\S+)\s*\|\s*(\S+)\s*/)); + next if (($7 =~ /UNDEF/) || ($7 =~ /ABS/)); + next if ($5 eq 'LOCL'); + $symbols{$8}++; + }; + &filter_symbols(\%symbols); +}; + +# +# Generate a map file for linux +# +sub gen_lnx { + my %symbols = (); + foreach (<DUMP_FILE>) { + next if (!(/^\S+ [A|B|C|D|G|I|N|R|S|T|U|V|W|-|\?|-] (\S+)/)); + $symbols{$1}++; + }; + &filter_symbols(\%symbols); +} + +# +# Filter symbols with filters from $flt_file +# +sub filter_symbols { + my $symbols = shift; + my $env_section = ''; + my @filters = (); + my @filtered_symbols = (); + while (<FLT_FILE>) { + s/\r//; + s/\n//; + $env_section = '1' and next if ((/^# SOLARIS #$/) && ($ENV{OS} eq 'SOLARIS')); + $env_section = '1' and next if ((/^# LINUX #$/) && ($ENV{OS} eq 'LINUX')); + $env_section = '1' and next if ((/^# FREEBSD #$/) && ($ENV{OS} eq 'FREEBSD')); + last if ($env_section && ((/^# SOLARIS #$/) || (/^# FREEBSD #$/) || (/^# LINUX #$/))); + next if (!$_ || /^#/); + push(@filters, $_); + }; + foreach my $symbol (keys %$symbols) { + my $export = '-'; + foreach my $filter_str (@filters) { + my $add = substr ($filter_str, 0, 1); + my $filter = substr($filter_str, 1); + if ($symbol =~ /$filter/) { + $export = $add; + }; + }; + if ($export eq '+') { + push(@filtered_symbols, $symbol); + }; + }; + &write_mapfile(\@filtered_symbols); +}; + +# +# Write a map file +# +sub write_mapfile { + my $symbols = shift; + print MAP_FILE $first_string . " {\n$tab" . "global:\n"; + foreach (@$symbols) { + print MAP_FILE "$tab$tab$_\;\n"; + }; + print MAP_FILE "$tab" . "local:\n$tab\*\;\n}\;"; +}; + +# +# Get all options passed +# +sub get_options { + +$dump_file = ''; +$flt_file = ''; +$map_file = ''; + my ($arg); + &usage() && exit(0) if ($#ARGV == -1); + while ($arg = shift @ARGV) { + $arg =~ /^-d$/ and $dump_file = shift @ARGV and next; + $arg =~ /^-f$/ and $flt_file = shift @ARGV and next; + $arg =~ /^-m$/ and $map_file = shift @ARGV and next; + $arg =~ /^-h$/ and &usage and exit(0); + $arg =~ /^--help$/ and &usage and exit(0); + $arg =~ /^-s$/ and $first_string = shift @ARGV and next; + }; + if (!$dump_file || + !$flt_file || + !$first_string || + !$map_file) { + &usage; + exit(1); + }; +}; + +sub print_error { + my $message = shift; + print STDERR "\nERROR: $message\n"; + exit(1) +}; + +sub usage { + print STDERR "\nmapgen:\n"; + print STDERR "Syntax: mapgen -d dump_file -s first_string -f filter_file -m map_file [-h|--help]\n"; +}; + diff --git a/solenv/bin/mhids.pl b/solenv/bin/mhids.pl new file mode 100644 index 000000000000..97650a35011b --- /dev/null +++ b/solenv/bin/mhids.pl @@ -0,0 +1,370 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: mhids.pl,v $ +# +# $Revision: 1.11 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +my $filename; +my $srs; +my $prjname; +my $defs; +my $solarincludes; + +my $debug = 0; +my $filebase; +my $workfile; +my $shell_workfile; +my @cleanuplist = (); + +# variables to setup the compiler line +my $appext; +my $compiler; +my $outbin_flag; +my $outobj_flag; +my $objext; +my $preprocess_flag; # preprocess to stdout + +my $no_hid_files; + +sub cleandie +{ + my $errstring = shift @_; + my $erroreval = $@; + + print STDERR "$errstring\n"; + if ( not $debug ) { + foreach my $i (@cleanuplist) { + unlink "$workfile$i" if -f "$workfile$i" or print STDERR "ERROR - couldn't remove $workfile$i\n"; + } + } + die "$erroreval\n"; +} + +sub setcompiler +{ + my $whichcom = $ENV{COM}; + if ( "$whichcom" eq "GCC" ) { + $appext = ""; # windows for now + $compiler = "gcc -x c"; + $outbin_flag = "-o "; + $outobj_flag = ""; + $objext = ".o"; + $preprocess_flag = "-E"; # preprocess to stdout + } elsif ( "$whichcom" eq "MSC" ) { + $appext = ".exe"; # windows for now + $compiler = "cl"; + $outbin_flag = "-Fe"; + $outobj_flag = "-Fo"; + $objext = ".obj"; + $preprocess_flag = "-EP"; # preprocess to stdout + } elsif ( "$whichcom" eq "C52" ) { + $appext = ""; # windows for now + $compiler = "cc"; + $outbin_flag = "-o "; + $outobj_flag = ""; + $objext = ".o"; + $preprocess_flag = "-E"; # preprocess to stdout + + # hack for SO cc wrapper + $ENV{wrapper_override_cc_wrapper} = "TRUE"; + $solarincludes =~ s/stl/xstlx/g; + $defs =~ s/\/stl/\/xstlx/g; + } else { + print STDERR "----------------------------------------------------------------------\n"; + print STDERR "OOops... looks like your compiler isn't known to \n$0\n"; + print STDERR "please edit the \"setcompiler\" section of this script to make it work.\n"; + print STDERR "----------------------------------------------------------------------\n"; + die "ERROR - compiler (or \$COM settings) unknown!\n"; + } +} + +#--------------------------------------------------- +$filename = shift @ARGV; +$srs = shift @ARGV; +$prjname = shift @ARGV; +$defs = join " ",@ARGV if ($#ARGV); + +if ( !defined $prjname ) { die "ERROR - check usage\n"; } + +if ( $ENV{NO_HID_FILES} ) { + $no_hid_files = $ENV{"NO_HID_FILES"}; +} +$solarincludes = $ENV{SOLARINCLUDES}; +$tmpdir = $ENV{TMP}; +die "ERROR - \"TMP\" environment variable not set\n" if ( !defined $tmpdir ); +die "ERROR - \"$tmpdir\" doesn't exist\n" if ( ! -d $tmpdir ); + +setcompiler(); + +# convert windows only? +$srs =~ s/\\/\//g; +$filename =~ s/\\/\//g; + +$filebase = $filename; +$filebase =~ s/.*[\\\/]//; +$filebase =~ s/\..*?$//; +$workfile = "$tmpdir/${filebase}_".$$; + +# now get $workfile ready for shell usage... +$shell_workfile = $workfile; +$shell_workfile =~ s/\//\\/g if ( "$ENV{USE_SHELL}" eq "4nt" ); +if (( "$ENV{USE_SHELL}" eq "4nt" ) && ( "$^O" eq "cygwin" )) { + $shell_workfile =~ s/\//\\\\/; +} + +print "workfile: $workfile\n"; + +#remove old objects which remained in place by a former bug +unlink "$workfile.obj"; + +# can't do this for modules with mixed case! +#$prjname =~ lc $prjname; + +if ( -f "$workfile.hid" ) +{ + unlink "$workfile.hid" or die "ERRROR - cannot remove $workfile.hid\n";; +} + +# hack to quit for files which cannot be handled +if ( defined $ENV{"NO_HID_FILES"} ) { + foreach $fname ( split / /, $ENV{"NO_HID_FILES"} ) + { + if ( $fname eq $filename ) + { + print "No hid generation for $filename due to NO_HID_FILES\n"; + print "Touching $srs/$filebase.hid anyways\n"; + open TOUCH, ">$srs/$filebase.hid" or die "ERRROR - cannot open $srs/$filebase.hid for writing\n"; + close TOUCH; + exit 0; + } + } +} + +#echo "perl5 -p -e "s/=[ \t]*\".*\"/=\"\"/go; s/\".*\"[ \t]*;/\"\" ;/go ; s/(\".*)\/\/(.*\")/$1\/\\\/$2/go ;" < %filename% > %srs%\%workfile%.c0" +#call perl5 -p -e "s/=[ \t]*\".*\"/=\"\"/go; s/\".*\"[ \t]*;/\"\" ;/go ; s/(\".*)\/\/(.*\")/$1\/\\\/$2/go ;" < %filename% > %srs%\%workfile%.c0 + +print "hidc $filename ${shell_workfile}.c1 $prjname \n"; +$ret = system "hidc $filename ${shell_workfile}.c1 $prjname"; +if ( $ret ) { + push @cleanuplist, ".c1"; + cleandie("ERROR - calling \"hidc\" failed"); +} +push @cleanuplist, ".c1"; + +print "$compiler $solarincludes $defs $preprocess_flag ${shell_workfile}.c1 > ${shell_workfile}.c2\n"; +$ret = system "$compiler $solarincludes $defs $preprocess_flag ${shell_workfile}.c1 > ${shell_workfile}.c2"; +if ( $ret ) { + push @cleanuplist, ".c2"; + cleandie("ERROR - calling compiler for preprocessing failed"); +} +push @cleanuplist, ".c2"; + +if (!open C_PROG, ">$workfile.c") { + push @cleanuplist, ".c"; + cleandie("ERROR - open $workfile.c\n for writing failed"); +} +push @cleanuplist, ".c"; +print C_PROG "#include <stdio.h>\n"; +print C_PROG "#include <wctype.h>\n"; + +if ( !open PRE, "<$workfile.c2" ) { + cleandie("ERROR - open $workfile.c2\n for reading failed"); +} + +$InMain = 0; +while (<PRE>) +{ + if ( /int\s*main/ ) + { + $InMain = 1; + } + + if ( $InMain && !/^\s*$/ ) + { + print C_PROG; + } +} + +close PRE; +close C_PROG; + +#cl %SOLARINCLUDES% %_srs%\%_workfile%.c /Fe%_srs%\%_workfile%$appext +my $outobj_param = ""; +if ( $outobj_flag ne "" ) +{ + $outobj_param = "$outobj_flag${shell_workfile}$objext"; +} +print "$compiler $solarincludes $defs ${shell_workfile}.c $outobj_param $outbin_flag${shell_workfile}$appext \n"; +$ret = system "$compiler $solarincludes $defs ${shell_workfile}.c $outobj_param $outbin_flag${shell_workfile}$appext"; +if ( $ret ) { + push @cleanuplist, "$appext"; + cleandie("ERROR - compiling $workfile.c failed"); +} +push @cleanuplist, "$objext"; +push @cleanuplist, "$appext"; + +#awk -f %ENV_TOOLS%\hidcode.awk < %srs%\%workfile%.c3 > %srs%\%workfile%.hid +if ( !open C3,"$workfile$appext|" ) { + cleandie("ERROR - executing $workfile$appext failed"); +} +if ( !open HID,">$srs/$filebase.hid.$ENV{INPATH}" ) { + cleandie("ERROR - open $srs/$filebase.hid.$ENV{INPATH} for writing failed"); +} + +while (<C3>) +{ + @fields = split /\s+/; + + if ( $fields[1] eq "HelpID" ) + { + print HID "$fields[0] $fields[2]\n"; + next; + } + + @arr = split /:/, $fields[0]; + if( $arr[1] =~ /^leer$|^bitmap$|^font$|^color$|^image$|^imagelist$|^date$|^brush$|^fixedtext$|^keycode$|^time$|^mapmode$/i ) + { + #print "skipping $arr[1]\n"; + next; + } + + if ( $fields[1] eq "Norm" ) + { + # Felder der Zeile auf Variable verteilen + $helpIDString = $fields[0]; + $GClass = lc($fields[2]); + $GID = $fields[3]; + $LClass = lc($fields[4]); + $LID = $fields[5] || 0; + + #print $LID + #print $LClass + #print $GID + #print $GClass + + $nHID=0; + + $VAL1 = 536870912; #2 hoch 29 + if ( $GClass eq "workwindow" ) { $nHID= $VAL1 *5; } + elsif( $GClass eq "modelessdialog" ) { $nHID= $VAL1 *4; } + elsif( $GClass eq "floatingwindow" ) { $nHID= $VAL1 *3; } + elsif( $GClass eq "modaldialog" ) { $nHID= $VAL1 *2; } + elsif( $GClass eq "tabpage" ) { $nHID= $VAL1 *1; } + elsif( $GClass eq "dockingwindow" ) { $nHID= $VAL1 *6; } + #Maximal bis 7 dann sind 32Bit ausgeschoepft + else { + $nHID=0; + $outline = "No GClass ".$helpIDString." ".$nHID." ".$GClass; + #print "$outline\n"; + next; + } + if( $LID != 0 ) { + if ( $LClass eq "tabcontrol" ) { $nHID += 0; } + elsif( $LClass eq "radiobutton" ) { $nHID += 2*256; } + elsif( $LClass eq "checkbox" ) { $nHID += 4*256; } + elsif( $LClass eq "tristatebox" ) { $nHID += 6*256; } + elsif( $LClass eq "edit" ) { $nHID += 8*256; } + elsif( $LClass eq "multilineedit" ) { $nHID += 10*256; } + elsif( $LClass eq "multilistbox" ) { $nHID += 12*256; } + elsif( $LClass eq "listbox" ) { $nHID += 14*256; } + elsif( $LClass eq "combobox" ) { $nHID += 16*256; } + elsif( $LClass eq "pushbutton" ) { $nHID += 18*256; } + elsif( $LClass eq "spinfield" ) { $nHID += 20*256; } + elsif( $LClass eq "patternfield" ) { $nHID += 22*256; } + elsif( $LClass eq "numericfield" ) { $nHID += 24*256; } + elsif( $LClass eq "metricfield" ) { $nHID += 26*256; } + elsif( $LClass eq "currencyfield" ) { $nHID += 28*256; } + elsif( $LClass eq "datefield" ) { $nHID += 30*256; } + elsif( $LClass eq "timefield" ) { $nHID += 32*256; } + elsif( $LClass eq "imageradiobutton" ) { $nHID += 34*256; } + elsif( $LClass eq "numericbox" ) { $nHID += 36*256; } + elsif( $LClass eq "metricbox" ) { $nHID += 38*256; } + elsif( $LClass eq "currencybox" ) { $nHID += 40*256; } + elsif( $LClass eq "datebox" ) { $nHID += 42*256; } + elsif( $LClass eq "timebox" ) { $nHID += 44*256; } + elsif( $LClass eq "imagebutton" ) { $nHID += 46*256; } + elsif( $LClass eq "menubutton" ) { $nHID += 48*256; } + elsif( $LClass eq "morebutton" ) { $nHID += 50*256; } + else { + $nHID=0; + $outline = "No LClass ".$helpIDString." ".$nHID; + #print "$outline\n"; + next; + } + + #GID und LID auch beruecksichtigen + $nHID += $LID; + } + $nHID += $GID * 16384; #14 Bit nach links shiften + + # check here and not above to avoid warnings for restypes not generated anyways + if( $GID == 0 || $GID >32767 || $LID > 511 ) + { + #GID & LID ungueltig + print STDERR "Invalid Global or Local ID: 0 < GID <= 32767 ; LID <= 511\n"; + print STDERR "$helpIDString GID = $GID; LID = $LID\n"; + next; + } + + # + # 1. Stelle selber ausgeben, falls groesser als 2^21 + # wg. problemen von awk/gawk bei printf mit %u + # + $x=0; + if( $nHID >= 4000000000 ) { + $nHID -= 4000000000; + $x=4; + }elsif( $nHID >= 3000000000) { + $nHID -= 3000000000; + $x=3; + }elsif( $nHID >= 2000000000) { + $nHID -= 2000000000; + $x=2; + } + if( $x != 0) + { printf HID "%s %d%u \n",$helpIDString,$x, $nHID; } + else + { printf HID "%s %u \n",$helpIDString, $nHID; } + } +} + +close C3; +close HID; + +rename("$srs/$filebase.hid.$ENV{INPATH}", "$srs/$filebase.hid") or cleandie("ERROR - couldn't rename tmp file to final for $filebase"); + +if ( not $debug ) { + foreach my $i (@cleanuplist) { + if ( -f "$workfile$i" ) { + unlink "$workfile$i" or cleandie(""); + } + } +} diff --git a/solenv/bin/mkdir.btm b/solenv/bin/mkdir.btm new file mode 100644 index 000000000000..5b610c829e52 --- /dev/null +++ b/solenv/bin/mkdir.btm @@ -0,0 +1,6 @@ +rem @echo off +iff "%PERL%" == "" then + call perl5 %SOLARENV%\bin\mkdir.pl %1& +else + call %PERL% %SOLARENV%\bin\mkdir.pl %1& +endiff diff --git a/solenv/bin/mkdir.pl b/solenv/bin/mkdir.pl new file mode 100755 index 000000000000..d2a374adfc67 --- /dev/null +++ b/solenv/bin/mkdir.pl @@ -0,0 +1,65 @@ +: # -*- perl -*- +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +# +# mkdir - a perl script to substitute mkdir -p +# accepts "/", ":", and "\" as delimiters of subdirectories +# options -p (for compatibility) +# -mode mode +# +# Copyright (c) 2000 Sun Microsystems, Inc. + +use Cwd; + +$currdir = cwd; + +$MODE = 00777 ; + +while ( $#ARGV >= 0 ) { + if ( $ARGV[0] eq "-mode" ) { + $MODE = oct $ARGV[1] ; + shift @ARGV ; + shift @ARGV ; + } + elsif ( $ARGV[0] eq "-p" ) { + shift @ARGV ; + # -p does not do anything, it's supported just for compatibility + } + else { + + $ARGV[0] =~ s?\\|:?/?g ; + @SUBDIRS = split "/", $ARGV[0] ; + + # absolute path UNIX + if ( $SUBDIRS[0] eq "" ) { + chdir '/' ; + shift @SUBDIRS ; + } + # absolute path WINDOWS + if ( $#SUBDIRS > 1 ) { + if ( $SUBDIRS[1] eq "" ) { + if ( $SUBDIRS[0] =~ /\w/ ) { + chdir "$SUBDIRS[0]:\\" ; + shift @SUBDIRS ; + shift @SUBDIRS ; + } ; + } ; + } + + while (@SUBDIRS) { + if ( -e $SUBDIRS[0] ) { + if ( ! -d $SUBDIRS[0] ) { + die "file exists\n" + } + } + else { + mkdir $SUBDIRS[0], $MODE or die "Can't create directory $SUBDIRS[0]" + } + chdir $SUBDIRS[0] or die "Can't cd to $SUBDIRS[0]" ; + shift @SUBDIRS ; + } ; + + shift @ARGV ; + } ; + chdir $currdir; +} diff --git a/solenv/bin/mkout.pl b/solenv/bin/mkout.pl new file mode 100755 index 000000000000..d803e83bf991 --- /dev/null +++ b/solenv/bin/mkout.pl @@ -0,0 +1,166 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: mkout.pl,v $ +# +# $Revision: 1.8 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +# +# mkout.pl - create output tree +# + +use Cwd; +use Getopt::Std; +use File::Path; + +#### script id ##### + +( $script_name = $0 ) =~ s/^.*\b(\w+)\.pl$/$1/; + +$id_str = ' $Revision: 1.8 $ '; +$id_str =~ /Revision:\s+(\S+)\s+\$/ + ? ($script_rev = $1) : ($script_rev = "-"); + +print "$script_name -- version: $script_rev\n"; + +#### globals #### + +$is_debug = 0; + +$base_dir = 0; # path to module base directory +$dir_mode = 0755; # default directory creation mode + +$envpath = 0; # platform/product combination +$opt_r = 0; # create 'remote' subdirs + +%sub_dirs = ( +# dirname remote(yes/no) + 'bin' => 1, + 'class' => 0, + 'inc' => 0, + 'lib' => 1, + 'misc/logs' => 1, + 'obj' => 1, + 'res' => 1, + 'slb' => 1, + 'slo' => 1, + 'srs' => 1 + ); + +#### main #### + +parse_options(); +init_globals(); +create_dirs(); + +exit(0); + +#### subroutines ##### + +sub parse_options { + my $rc; + + $rc = getopts('r'); + + if ( !$rc || $#ARGV > 0 ) { + usage(); + exit(1); + } + $envpath = $ARGV[0] if defined($ARGV[0]); +} + +sub init_globals { + my $umask; + $base_dir = get_base(); + print "Base_Diri=$base_dir\n" if $is_debug; + + $umask = umask(); + if ( defined($umask) ) { + $dir_mode = 0777 - $umask; + } + $envpath = $ENV{INPATH} unless $envpath; + + if ( !$envpath ) { + print_error("can't determine platform/environment"); + exit(3); + } + print "Platform/Environment: $envpath\n" if $is_debug; +} + +sub get_base { + # a module base dir contains a subdir 'prj' + # which in turn contains a file 'd.lst' + my (@field, $base, $dlst); + my $path = cwd(); + + @field = split(/\//, $path); + + while ( $#field != -1 ) { + $base = join('/', @field); + $dlst = $base . '/prj/d.lst'; + last if -e $dlst; + pop @field; + } + + if ( $#field == -1 ) { + print_error("can't determine module"); + exit(2); + } + else { + return $base; + } +} + +sub create_dirs { + foreach $dir ( keys %sub_dirs ) { + $path = $base_dir . '/' . $envpath . '/' . $dir; + if ( $opt_r && $sub_dirs{$dir} ) { + $path .= "/remote"; + } + eval { mkpath($path, 0, $dir_mode) }; + if ( $@ ) { + print_error( "$@" ); + } + print "Create path: $path\n" if $is_debug; + } +} + +sub print_error { + my $message = shift; + + print STDERR "$script_name: ERROR: $message\n"; +} + +sub usage { + print STDERR "Usage:\n$script_name [-r] [platform/environment]\n"; + print STDERR "Options:\n -r create 'remote' directories\n"; +} + +# vim: set ts=4 shiftwidth=4 expandtab syntax=perl: diff --git a/solenv/bin/modules/CreatePDBRelocators.pm b/solenv/bin/modules/CreatePDBRelocators.pm new file mode 100644 index 000000000000..e279cf7daeb9 --- /dev/null +++ b/solenv/bin/modules/CreatePDBRelocators.pm @@ -0,0 +1,166 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: CreatePDBRelocators.pm,v $ +# +# $Revision: 1.8 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +#************************************************************************* +# +# createPDBRelocators - create for pdb relocator files +# PDB relocator files are used to find debug infos +# for analysis of creash reports +# +# usage: create_pdb_relocators($inpath, $milestone, $pre); +# +#************************************************************************* + +package CreatePDBRelocators; + +use strict; +use File::Basename; + +sub create_pdb_relocators +{ + my $inpath = shift; + my $milestone = shift; + my $pre = shift; + + my $solarversion = $ENV{SOLARVERSION}; + if ( !$solarversion ) { + print STDERR "can't determine SOLARVERSION.\n"; + return undef; + } + + my $o = $ENV{SRC_ROOT}; + if ( !$o ) { + print STDERR "can't determine SOLAR_SRC.\n"; + return undef; + } + + my $root_dir = "$solarversion/$inpath"; + + # sanitize path + $root_dir =~ s/\\/\//g; + $o =~ s/\\/\//g; + my $pdb_dir = $root_dir . "/pdb.$pre$milestone"; + my $pdb_so_dir = $root_dir . "/pdb.$pre$milestone/so"; + + # create pdb directories if necessary + if ( ! -d $pdb_dir ) { + if ( !mkdir($pdb_dir, 0775) ) { + print STDERR "can't create directory '$pdb_dir'\n"; + return undef; + } + } + if ( ! -d $pdb_so_dir ) { + if ( !mkdir($pdb_so_dir, 0775) ) { + print STDERR "can't create directory '$pdb_so_dir'\n"; + return undef; + } + } + + # collect files + my @pdb_files; + collect_files( $o, $inpath, \@pdb_files); + + foreach (@pdb_files) { + my $relocator = basename($_) . ".location"; + /$o\/(.*)/i; + + my $src_location = $1; + + my $location = ""; + my $target = ""; + if ( $src_location =~ /\/so\// ) + { + $location = "../../../src.$milestone/" . $src_location; + $target = "$pdb_dir/so/$relocator"; + } + else + { + $location = "../../src.$milestone/" . $src_location; + $target = "$pdb_dir/$relocator"; + } + + if ( !open(RELOCATOR, ">$target") ) { + print STDERR "can't write file '$target'\n"; + return undef; + } + print RELOCATOR "$location\n"; + close(RELOCATOR); + } + return 1; +} + +sub collect_files +{ + my ($srcdir, $platform, $filesref) = @_; + my $template = "$srcdir/*/$platform"; + if ( $^O eq 'MSWin32' ) { + # collect all pdb files on o: + # regular glob does not work with two wildcard on WNT + my @bin = glob("$template/bin/*.pdb"); + my @bin_so = glob("$template/bin/so/*.pdb"); + # we are only interested in pdb files which are accompanied by + # .exe or .dll which the same name + foreach (@bin, @bin_so) { + my $dir = dirname($_); + my $base = basename($_, ".pdb"); + my $exe = "$dir/$base.exe"; + my $dll = "$dir/$base.dll"; + if ( -e $exe || -e $dll ) { + push(@$filesref, $_); + } + } + } + else { + # collect all shared libraries on o: + my @lib = glob("$template/lib/*.so*"); + my @lib_so = glob("$template/lib/so/*.so*"); + my @mac_lib = glob("$template/lib/*.dylib*"); + my @mac_lib_so = glob("$template/lib/so/*.dylib*"); + # collect all binary executables on o: + my @bin = find_binary_execs("$template/bin"); + my @bin_so = find_binary_execs("$template/bin/so"); + @$filesref = (@lib, @lib_so, @mac_lib, @mac_lib_so, @bin, @bin_so); + } + return 1; +} + +sub find_binary_execs +{ + my $path = shift; + my @files = glob("$path/*"); + my @execs = grep(-x $_, @files); + my @elf_files = grep(`file $_` =~ /ELF/, @execs); + my @MachO_files = grep(`file $_` =~ /Mach\-O/, @execs); + return ( @elf_files, @MachO_files ); +} + +1; # required + diff --git a/solenv/bin/modules/Cws.pm b/solenv/bin/modules/Cws.pm new file mode 100755 index 000000000000..c40a2ceb673f --- /dev/null +++ b/solenv/bin/modules/Cws.pm @@ -0,0 +1,2103 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: Cws.pm,v $ +# +# $Revision: 1.26 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +# +# Cws.pm - package for accessing/manipulating child workspaces +# + +# TODO: needs some cleanup + +package Cws; +use strict; + +use Eis; +use CwsConfig; +use Carp; +use URI::Escape; + +my $config = CwsConfig::get_config(); + +##### class data ##### + +my %CwsClassData = ( + # EIS database connectivity + EIS_URI => 'urn:ChildWorkspaceDataService', + EIS_PROXY_LIST => $config->cws_db_url_list_ref(), + NET_PROXY => $config->net_proxy(), + EIS => undef +); + +##### ctor ##### + +sub new +{ + my $invocant = shift; + my $class = ref($invocant) || $invocant; + my $self = {}; + # instance data + # initialize CWS name from environment + $self->{CHILD} = undef; # name of child workspace + $self->{MASTER} = undef; # name of master workspace + $self->{EIS_ID} = undef; # id of child workspace in EIS + $self->{FILES} = undef; # list of files registered with child + # any file can be registered multiple times + $self->{PATCH_FILES} = undef # list of product patch files registered with + # child, each file can be added only once + $self->{MILESTONE} = undef; # master milestone to which child is related + $self->{MODULES} = undef; # list of modules belonging to child + $self->{INCOMPATIBLE_MODULES} = undef; # list of modules belonging to child + $self->{NEW_MODULES} = undef; # list of public new modules belonging to child + $self->{NEW_MODULES_PRIV} = undef; # list of private new modules belonging to child + $self->{TASKIDS} = undef; # list of tasks registered with child + $self->{_CACHED_TAGS} = undef; # list of cached tags (tags are looked up frequently) + bless($self, $class); + return $self; +} + +#### methods to access instance data #### + +# Get the EIS ID for child workspace, +# return value: undef => not yet asked EIS for ID +# or connection failed +# 0 => queried EIS but didn't find such +# a child workspace for this master +# silently ignore any parameter, only the EIS database, +# hands out EIS IDs. +sub eis_id +{ + my $self = shift; + if ( !defined($self->{EIS_ID} ) ) { + $self->{EIS_ID} = $self->get_eis_id(); + } + return $self->{EIS_ID}; +} + +# Generate remaining instance data accessor methods; +# if this looks strange see 'perldoc perltootc' + +# Accessor methods for single value instance data +for my $datum (qw(master milestone)) { + no strict "refs"; + *$datum = sub { + my $self = shift; + my $ucdatum = uc($datum); + if ( @_ ) { + # set item in database + my $item = shift; + # if we already have a valid EIS registered CWS then reset EIS value + # otherwise just set member to the given value + if ( !$self->{uc($datum)} # keep order of evaluation + || !$self->eis_id() + || $self->set_item_in_eis($datum, $item) ) + { + $self->{uc($datum)} = $item; + + } + } + else { + if ( !defined($self->{$ucdatum} ) ) { + # fetch item from database + $self->{$ucdatum} = $self->fetch_item_from_eis($datum); + } + } + return $self->{uc($datum)}; + } +} + +# Accessor methods for instance data consisting of item lists +# like modules and taskids +for my $datum (qw(files patch_files modules incompatible_modules new_modules new_modules_priv taskids)) { + no strict "refs"; + *$datum = sub { + # get current item list + # fetch list from EIS database if called the first time + my $self = shift; + my $ucdatum = uc($datum); + if ( !defined($self->{$ucdatum}) ) { + # fetch item list from databse + $self->{$ucdatum} = $self->fetch_items_from_eis($datum); + return undef if !defined($self->{$ucdatum}); + } + return wantarray ? @{$self->{$ucdatum}} : $self->{$ucdatum} + } +} + +for my $datum (qw(child)) { + no strict "refs"; + *$datum = sub { + my $self = shift; + $self->{uc($datum)} = shift if @_; + return $self->{uc($datum)}; + } +} + + +#### additional public methods #### + +# For resync: Sets master and milestone simultaneously +# In case of a cross master resync it does not make sense to +# change both items separately +sub set_master_and_milestone +{ + my $self = shift; + my $master = shift or return undef; + my $milestone = shift or return undef; + + # if we do not yet have a valid EIS registered CWS use the above more basic methods + if ( !$self->master() + || !$self->milestone() + || !$self->eis_id() ) + { + $self->master($master); + $self->milestone($milestone); + } else { + if ( $self->set_master_and_milestone_in_eis($master, $milestone) ) { + $self->{'MASTER'} = $self->fetch_item_from_eis('master'); + $self->{'MILESTONE'} = $self->fetch_item_from_eis('milestone'); + } + } + my @retarray = ($self->{'MASTER'}, $self->{'MILESTONE'}); + return wantarray ? @retarray : \@retarray; +} + +# Query if CWS name is still available. Does not yet register +# anything with EIS. +sub is_cws_name_available +{ + my $self = shift; + + my $is_available = $self->is_cws_name_available_in_eis(); + return $is_available; +} + +# Register new child workspace with the EIS database. +sub register +{ + my $self = shift; + my $vcsid = shift; + my $location = shift; + + my $child_id = $self->register_child_with_eis($vcsid, $location); + return $child_id; +} + +# Promote a child workspace with status 'planned' to a full CWS +sub promote +{ + my $self = shift; + my $vcsid = shift; + my $location = shift; + + my $rc = $self->promote_child_in_eis($vcsid, $location); + return $rc; +} + +# New style add_module method. Takes an additional bool indicating if +# a module is public or private. Obsoletes add_modules() +sub add_module +{ + my $self = shift; + my $module = shift; + my $public = shift; + + my $items_ref = $self->add_items('modules', $public, $module); + if (defined ($items_ref->[0]) && ($items_ref->[0] eq $module)) { + return 1; # module has been added + } + elsif ( defined($items_ref) ) { + return 0; # module was already add + } + return undef; # something went wrong +} + +# Add module to modules list. +sub add_modules +{ + my $self = shift; + + my $items_ref = $self->add_items('modules', undef, @_); + return undef unless defined($items_ref); + return wantarray ? @{$items_ref} : $items_ref; +} + +# Add tasksids to taskids list. +sub add_taskids +{ + my $self = shift; + my $vcsid = shift; + + my $items_ref = $self->add_items('taskids', $vcsid, @_); + return undef unless defined($items_ref); + return wantarray ? @{$items_ref} : $items_ref; +} + +# Add a file to the files list. +sub add_file +{ + my $self = shift; + my $module = shift; + my $file = shift; + my $revision = shift; + my $authors_ref = shift; + my $taskids_ref = shift; + my $archive_path = shift; + + my $files_ref = $self->files(); + + if ( $self->add_file_to_eis($module, $file, $revision, + $authors_ref, $taskids_ref, $archive_path) ) + { + push(@{$files_ref}, $file); + return 1; + } + return 0; +} + +# Add a file to the patch file list. +sub add_patch_file +{ + my $self = shift; + my $file = shift; + + my $patch_files_ref = $self->patch_files(); + + foreach (@{$patch_files_ref}) { + return 0 if $file eq $_; + } + + if ( $self->add_patch_file_to_eis($file) ) + { + push(@{$patch_files_ref}, $file); + return 1; + } + return 0; +} + +# +# Procedure retrieves the workspace which +# is based on cvs head (not branch) +# +sub get_cvs_head { + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->getCVSHead() }; + if ( $@ ) { + carp("ERROR: get_eis_id(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +}; + +#### public class methods #### + +sub get_master_tag { + my ($self, $master, $milestone) = @_; + $master = $self->master() if (!defined $master); + $milestone = $self->milestone() if (!defined $milestone); + return uc($master) . '_' . lc($milestone); +}; + +sub get_master_branch_tag { + my ($self, $master) = @_; + $master = $self->master() if (!defined $master); + # check in environment if master is on the the HEAD branch + my $cvs_head = get_cvs_head(); + if ( $master eq $cvs_head ) { + return undef; + } + else { + return 'mws_' . lc($master); + } +}; + +sub get_mws { + my $self = shift; + my $eis = Cws::eis(); + my $masters; + my $child = Eis::to_string($self->child()); + eval { $masters = $eis->getMastersForCWS($child) }; + if ( $@ ) { + carp("ERROR: get_eis_id(): EIS database transaction failed. Reason:\n$@\n"); + } + return $$masters[0]; +}; + +# Returns the branch and root tags for child workspace. +sub get_tags +{ + my $self = shift; + + # look up if tags have already been retrieved + if ( defined($self->{_CACHED_TAGS}) ) { + return @{$self->{_CACHED_TAGS}}; + } + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $childws = $self->child(); + # check if child workspace is a clone, + if ( $childws =~ /(\w+)_[[:upper:]]{3}\d{3}/ ) { + $childws = $1; + } + + # check in environment if master is on the the HEAD branch + my $cvs_head = get_cvs_head(); + my $current_master = $self->master(); + my $creation_master = $self->get_creation_master(); + if ( !$creation_master ) { + carp("ERROR: Can't determine creation MWS.\n"); + return undef; + } + my $milestone = $self->milestone(); + + my $master_branch_tag + = (lc($current_master) eq lc($cvs_head)) ? '' : 'mws_' . lc($current_master); + my $cws_branch_tag = 'cws_' . lc($creation_master) . '_' . lc($childws); + my $cws_root_tag = uc($cws_branch_tag) . "_ANCHOR"; + my $master_milestone_tag = uc($current_master) . "_" . $milestone; + + $self->{_CACHED_TAGS} = [$master_branch_tag, $cws_branch_tag, $cws_root_tag, $master_milestone_tag]; + return @{$self->{_CACHED_TAGS}}; +} + +# Get childworkspace owner +sub get_owner +{ + my $self = shift; + + return $self->get_owner_from_eis(); +} + +# get childworkspace qarep +sub get_qarep +{ + my $self = shift; + + return $self->get_qarep_from_eis(); +} + +# store an Attachment to a given CWS +sub save_attachment +{ + my $self = shift; + my $name = shift; + my $mediatype = shift; + my $data = shift; + + return $self->save_attachment_in_eis($name, $mediatype, $data); +} + +# Get child workspace approval status, +# return values can be: +# 'planned', 'new', 'nominated', 'integrated' +# and undef in case of error. +sub get_approval +{ + my $self = shift; + + return $self->get_status_from_eis(); +} + +# Set child workspace approval status +# to 'integrated'. Return true if successful +# or undef in case of error +sub set_integrated +{ + my $self = shift; + + return $self->set_status_in_eis(); +} + +# Set child workspace integration milestone +# Return true if successful or undef in case of error +sub set_integration_milestone +{ + my $self = shift; + my $milestone = shift; + my $buildid = shift; + + return $self->set_integration_milestone_in_eis($milestone, $buildid); +} + +# Get the MWS on which a CWS was created +sub get_creation_master +{ + my $self = shift; + + return $self->get_creation_master_from_eis(); +} + +# Get the 'public' flag indicating whether a CWS is visible on OOo +sub get_public_flag +{ + my $self = shift; + + return $self->get_public_flag_from_eis(); +} + + +# Get the 'publicmaster' flag indicating whether a MWS is visible on OOo +sub get_publicmaster_flag +{ + my $self = shift; + + return $self->get_publicmaster_flag_from_eis(); +} + + +sub get_subversion_flag { + + my $self = shift; + + return $self->get_subversion_flag_from_eis(); +} + +sub set_subversion_flag { + + my $self = shift; + my $value = shift; + + return $self->set_subversion_flag_in_eis($value); +} + + +# Check if milestone exists +sub is_milestone +{ + my $self = shift; + my $master = shift; + my $milestone = shift; + + return $self->is_milestone_registered_with_eis($master, $milestone); +} + +# Check if this cws contains new ui +sub is_uirelevant +{ + my $self = shift; + + return $self->is_uirelevant_from_eis(); +} + +# Check if this cws contains new online help +sub is_helprelevant +{ + my $self = shift; + + return $self->is_helprelevant_from_eis(); +} + +# Set the l10n status +sub set_l10n_status +{ + my $self = shift; + my $status = shift; + + return $self->set_l10n_status_in_eis( $status ); +} + +# Get the l10n status +sub get_l10n_status +{ + my $self = shift; + + return $self->get_l10n_status_from_eis(); +} +sub set_word_count +{ + my $self = shift; + my $language = shift; + my $wordcount = shift; + + return $self->set_word_count_in_eis( $language , $wordcount ); +} + + +# Get target release for CWS +sub get_release +{ + my $self = shift; + + return $self->get_release_from_eis(); +} + +# Get due date +sub get_due_date +{ + my $self = shift; + + return $self->get_due_date_from_eis(); +} + +# Get due date QA +sub get_due_date_qa +{ + my $self = shift; + + return $self->get_due_date_qa_from_eis(); +} + +# Query master milestone combination for being used by an +# active CWS +sub is_milestone_used +{ + my $self = shift; + my $master = shift; + my $milestone = shift; + + return $self->get_is_milestone_used_from_eis($master, $milestone); +} + +# Set current milestone for MWS. +sub set_current_milestone +{ + my $self = shift; + my $master = shift; + my $milestone = shift; + + return $self->set_current_milestone_in_eis($master, $milestone); +} + +# Get current milestone for MWS. +sub get_current_milestone +{ + my $self = shift; + my $master = shift; + + return $self->get_current_milestone_from_eis($master); +} + +sub get_milestone_integrated +{ + my $self = shift; + + return $self->get_milestone_integrated_from_eis(); +} + +# Get masters +sub get_masters +{ + + my $self = shift; + + return $self->get_masters_from_eis(); +} + +# Get milestones for MWS. +sub get_milestones +{ + my $self = shift; + my $master = shift; + + return $self->get_milestones_from_eis($master); +} +# get build string for CWS + +sub get_build +{ + my $self = shift; + my $master = $self->master(); + my $milestone = $self->milestone(); + if ( ! defined($milestone) ) { + return undef; + } + my $bid=$self->get_buildid($master,$milestone); + if ( ! defined($bid) ) { + return undef; + } + return $self->expand_buildid($bid); +} + + + +# expand build for given cwsname +sub expand_buildid +{ + my $self = shift; + my $bid = shift; + return $self->expand_buildid_in_eis($bid); +} + + +# Set BuildID of milestone +sub set_milestone_buildid +{ + my $self = shift; + my $master = shift; + my $milestone = shift; + my $buildid = shift; + + return $self->set_milestone_buildid_in_eis($master, $milestone, $buildid); +} + +# Declare milestone 'removed' +# This triggers EIS to send emails to all (SO-internal) CWS owners +# with living CWSs based on that milestone. +sub milestone_removed +{ + my $self = shift; + my $master = shift; + my $milestone = shift; + + return $self->set_milestone_removed_in_eis($master, $milestone); +} + + +# Get all child workspaces which have been integrated on a +# given master and milestone. +sub get_integrated_cws +{ + my $self = shift; + my $master = shift; + my $milestone = shift; + + my $childworkspaces_arrref = $self->get_childworkspaces_for_milestone($master, $milestone); + if ( !$childworkspaces_arrref ) { + $childworkspaces_arrref = []; + } + return wantarray ? @$childworkspaces_arrref : $childworkspaces_arrref; +} + + +# Get builid for given master and milestone. +sub get_buildid +{ + my $self = shift; + my $master = shift; + my $milestone = shift; + + return $self->get_buildid_for_milestone($master, $milestone); +} + +# +# Get all cws' with a status passed +# +sub get_cws_with_state +{ + my $self = shift; + my $mws = shift; + my $status = shift; + + return wantarray ? @{$self->get_cws_with_state_from_eis($mws, $status)} + : $self->get_cws_with_state_from_eis($mws, $status); +} + +sub get_task_prio_cws +{ + my $self = shift; + my $ref_taskids = shift; + return @{$self->get_task_prios_of_tasks($ref_taskids)}; +} + +# Check is CWS is cloneable for specified master +sub is_cws_cloneable +{ + my $self = shift; + my $master = shift; + + return $self->get_is_cws_cloneable_from_eis($master); +} + +# Clone CWS for specified master +sub clone_cws +{ + my $self = shift; + my $master = shift; + + return $self->clone_cws_in_eis($master); +} + +sub set_log_entry +{ + my $self = shift; + my $commandline = shift; + my $vcsid = shift; + my $start = shift; + my $stop = shift; + my $comment = shift; + return $self->set_log_entry_in_eis($commandline, $vcsid, $start, $stop, $comment); +} + +sub set_log_entry_extended +{ + my $self = shift; + my $commandname = shift; + my $parameter = shift; + my $vcsid = shift; + my $start = shift; + my $stop = shift; + my $comment = shift; + my $mastername = shift; + my $childname = shift; +#set_log_entry_extended_in_eis($commandname, $parameter, $vcsid, $start, $stop, $comment, $mastername, $childname); + return $self->set_log_entry_extended_in_eis($commandname, $parameter, $vcsid, $start, $stop, $comment, $mastername, $childname); +} + + +#### private #### + +# class data accessor methods +sub eis +{ + shift; # ignore calling class/object + $CwsClassData{EIS} = shift if @_; + if ( !defined($CwsClassData{EIS}) ) { + $CwsClassData{EIS} = init_eis_connector(); + } + return $CwsClassData{EIS}; +} + +# generate remaining class data accessor methods +# if this looks strange see 'perldoc perltootc' +for my $datum (qw(eis_uri eis_proxy_list net_proxy)) { + no strict "refs"; + *$datum = sub { + shift; # ignore calling class/object + return $CwsClassData{uc($datum)}; + } +} + +#### helper methods #### + +# instance methods + +# Add item to items list, +# update eis database, +# returns a list of newly added items, +# specifying an existing item is not an +# error, but it want appear in the return list. +sub add_items +{ + my $self = shift; + my $type = shift; + my $optional_data = shift; + + my $items_ref; + if ( $type eq 'modules' ) { + $items_ref = $self->modules(); + } + elsif ( $type eq 'taskids' ) { + $items_ref = $self->taskids(); + } + else { + # fall through, can't happen + carp("ERROR: wrong item type\n"); + return undef; + } + + my $item; + my @new_items = (); + return undef if !defined($items_ref); + # find which items which are not already in items list + ITEM: while ( $item = shift ) { + foreach ( @{$items_ref} ) { + next ITEM if $_ eq $item; + } + push(@new_items, $item); + } + if ( $#new_items > -1 ) { + # add items to database + if ( $self->add_items_to_eis($type, $optional_data, \@new_items) ) { + push(@{$items_ref}, @new_items); + } + else { + # something went wrong + return undef; + } + } + return \@new_items; +} + +# Get EIS id for workspace from EIS database +sub get_eis_id +{ + my $self = shift; + my $eis = Cws::eis(); + + # It's not an error if one of these is unset, so don't carp(). + if ( !$self->master() || !$self->child() ) { + return undef; + } + + my $master = Eis::to_string($self->master()); + my $child = Eis::to_string($self->child()); + + my $result; + eval { $result = int($eis->getChildWorkspaceId($master, $child)) }; + if ( $@ ) { + carp("ERROR: get_eis_id(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +sub fetch_item_from_eis +{ + my $self = shift; + my $type = shift; + + my $eis = Cws::eis(); + my $id = $self->eis_id(); + + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $result; + if ( $type eq 'milestone' ) { + eval { $result = $eis->getMilestone($id) }; + } + elsif ( $type eq 'master' ) { + # master can't be queried from the EIS database, + # just return what already in member + return $self->{MASTER} + } + else { + # fall through, can't happen + carp("ERROR: wrong item type\n"); + return undef; + } + if ( $@ ) { + carp("ERROR: fetch_item(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +sub set_item_in_eis +{ + my $self = shift; + my $type = shift; + my $item = shift; + + my $eis = Cws::eis(); + my $id = $self->eis_id(); + + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + # make certain that the item is a string, otherwise + # autotyping will occasionally choose the wrong type + $item = Eis::to_string($item); + + my $result; + if ( $type eq 'milestone' ) { + # this operation invalidates the cached tags list + $self->{_CACHED_TAGS} = undef; + eval { $result = $eis->setMilestone($id, $item) }; + } + elsif ( $type eq 'master' ) { + # this operation invalidates the cached tags list + $self->{_CACHED_TAGS} = undef; + eval { $result = $eis->setMasterWorkspace($id, $item) }; + } + else { + # fall through, can't happen + carp("ERROR: wrong item type\n"); + return 0; + } + + if ( $@ ) { + carp("ERROR: set_item(): EIS database transaction failed. Reason:\n$@\n"); + return undef; + } + return 1 if $result; + return 0; +} + +sub set_master_and_milestone_in_eis +{ + my $self = shift; + my $master = shift; + my $milestone = shift; + + my $eis = Cws::eis(); + my $id = $self->eis_id(); + + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + # make certain that the item is a string, otherwise + # autotyping will occasionally choose the wrong type + $master = Eis::to_string($master); + $milestone = Eis::to_string($milestone); + + my $result; + # this operation invalidates the cached tags list + $self->{_CACHED_TAGS} = undef; + eval { $result = $eis->setMasterWorkspaceAndMilestone($id, $master, $milestone) }; + + if ( $@ ) { + carp("ERROR: set_master_and_milestone(): EIS database transaction failed. Reason:\n$@\n"); + return undef; + } + return 1 if $result; + return 0; +} + +sub fetch_items_from_eis +{ + my $self = shift; + my $type = shift; + + my $eis = Cws::eis(); + my $id = $self->eis_id(); + + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $result; + if ( $type eq 'modules' ) { + eval { $result = $eis->getModules($id) }; + } + elsif ( $type eq 'incompatible_modules' ) { + eval { $result = $eis->getIncompatibleModules($id) }; + } + elsif ( $type eq 'new_modules' ) { + eval { $result = $eis->getNewModules($id) }; + } + elsif ( $type eq 'new_modules_priv' ) { + eval { $result = $eis->getNewModulesPriv($id) }; + } + elsif ( $type eq 'taskids' ) { + eval { $result = $eis->getTaskIds($id) }; + } + elsif ( $type eq 'files' ) { + eval { $result = $eis->getFiles($id) }; + } + elsif ( $type eq 'patch_files' ) { + eval { $result = $eis->getOutputFiles($id) }; + } + else { + # fall through, can't happen + carp("ERROR: wrong item type\n"); + return undef; + } + if ( $@ ) { + carp("ERROR: fetch_item(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +sub add_items_to_eis +{ + my $self = shift; + my $type = shift; + my $optional_data = shift; + my $item_ref = shift; + + my $eis = Cws::eis(); + my $id = $self->eis_id(); + + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + # make certain that all items are strings, otherwise + # autotyping will occasionally choose the wrong type + my @items = (); + foreach ( @{$item_ref} ) { + push(@items, Eis::to_string($_)); + } + + my $result; + if ( $type eq 'modules' ) { + if ( defined($optional_data) ) { + # add a module new style, with public attribute + eval { $result = $eis->addModule($id, $items[0], $optional_data) }; + } + else { + # old style, add a list of modules + eval { $result = $eis->addModules($id, \@items) }; + } + } + elsif ( $type eq 'taskids' ) { + eval { $result = $eis->addTaskIds($id, \@items, $optional_data) }; + } + else { + # fall through, can't happen + carp("ERROR: wrong item type\n"); + return 0; + } + + if ( $@ ) { + carp("ERROR: add_item(): EIS database transaction failed. Reason:\n$@\n"); + return undef; + } + return 1 if $result; + return 0; +} + +sub add_file_to_eis +{ + my $self = shift; + my $module = shift; + my $file = shift; + my $revision = shift; + my $authors_ref = shift; + my $taskids_ref = shift; + my $archive_path = shift; + + + my $eis = Cws::eis(); + my $id = $self->eis_id(); + + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + # make certain that all task_ids are strings, otherwise + # autotyping will choose the wrong type + # Note: I think typing just the first element should suffice, but ... + my @taskids = (); + foreach ( @{$taskids_ref} ) { + push(@taskids, Eis::to_string($_)); + } + # HACK Its possible that we get no valid taskid. + # Autotyping will fail for a list without elements; + if ( !@taskids ) { + push(@taskids, Eis::to_string('')); + } + + # same for revision + $revision = Eis::to_string($revision); + + if ( !$archive_path ) { + $archive_path = Eis::to_string(''); + } + + my $result; + eval { + $result = $eis->addFile($id, $module, $file, $archive_path, + $revision, $authors_ref, \@taskids) + }; + if ( $@ ) { + carp("ERROR: add_file(): EIS database transaction failed. Reason:\n$@\n"); + return undef; + } + return 1 if $result; + return 0; +} + +sub add_patch_file_to_eis +{ + my $self = shift; + my $file = shift; + + my $eis = Cws::eis(); + my $id = $self->eis_id(); + + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $result; + eval { $result = $eis->addOutputFile($id, $file) }; + if ( $@ ) { + carp("ERROR: add_patch_file(): EIS database transaction failed. Reason:\n$@\n"); + return undef; + } + return $1;# appOutputFile has void as return value ... +} + +sub is_cws_name_available_in_eis +{ + my $self = shift; + + if ( !$self->master() ) { + carp("ERROR: master workspace name not set\n"); + return undef; + } + + if ( !$self->child() ) { + carp("ERROR: child workspace name not set\n"); + return undef; + } + + my $eis = Cws::eis(); + my $master = Eis::to_string($self->master()); + my $child = Eis::to_string($self->child()); + + my $result; + eval { $result = $eis->isChildWorkspaceUnique($master, $child) }; + if ( $@ ) { + carp("ERROR: is_cws_name_available(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +sub register_child_with_eis +{ + my $self = shift; + my $vcsid = shift; + my $location = shift; + + if ( !$self->master() ) { + carp("ERROR: master workspace name not set\n"); + return undef; + } + + if ( !$self->milestone() ) { + carp("ERROR: master milestone not set\n"); + return undef; + } + + if ( !$self->child() ) { + carp("ERROR: child workspace name not set\n"); + return undef; + } + + $vcsid = '' unless $vcsid; + $location = '' unless $location; + + my $eis = Cws::eis(); + my $master = Eis::to_string($self->master()); + my $milestone = Eis::to_string($self->milestone()); + my $child = Eis::to_string($self->child()); + + $vcsid = Eis::to_string($vcsid); + $location = Eis::to_string($location); + + my $result; + eval { + $result = $eis->createChildWorkspace($master, $milestone, $child, + $vcsid, $location) + }; + + if ( $@ ) { + carp("ERROR: create_child_wortkspace(): EIS database transaction failed. Reason:\n$@\n"); + return undef; + } + # set EIS_ID directly, since $self->eis_id() is not + # supposed to take parameters. + $self->{EIS_ID} = $result; + return $result; +} + +sub promote_child_in_eis +{ + my $self = shift; + my $vcsid = shift; + my $location = shift; + + my $eis = Cws::eis(); + my $id = $self->eis_id(); + + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + if ( !$self->milestone() ) { + carp("ERROR: master milestone not set\n"); + return undef; + } + + my $milestone = Eis::to_string($self->milestone()); + + $vcsid = '' unless $vcsid; + $location = '' unless $location; + + $vcsid = Eis::to_string($vcsid); + $location = Eis::to_string($location); + + my $result; + eval { + $result = $eis->initializeChildWorkspace($id, $milestone, $vcsid, $location) + }; + + eval { $result = $eis->getStatus($id) }; + if ( $@ ) { + carp("ERROR: promote(): EIS database transaction failed. Reason:\n$@\n"); + return 0; + } + return 1; +} + +# Get child workspace owner from EIS, +# return undef in case of error. +sub get_owner_from_eis +{ + my $self = shift; + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->getOwnerEmail($id) }; + if ( $@ ) { + carp("ERROR: get_OwnerEmail(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +# Get child workspace qarep from EIS, +# return undef in case of error. +sub get_qarep_from_eis +{ + my $self = shift; + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->getQARepresentativeEmail($id) }; + if ( $@ ) { + carp("ERROR: get_qarep(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +# store an attachment to a given CWS +# return undef in case of error. +sub save_attachment_in_eis +{ + my $self = shift; + my $name = shift; + my $mediatype = shift; + my $text = shift; + + # check if child workspace is valid + my $eisid = $self->eis_id(); + if ( !$eisid ) + { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $eisname = Eis::to_string($name); + my $eismediatype = Eis::to_string($mediatype); + my $eistextstring = Eis::to_string($text); + + my $eis = Cws::eis(); + my $result; + + eval { $result = $eis->saveAttachment($eisid, $eisname, $eismediatype, $eistextstring ) }; + if ( $@ ) { + carp("ERROR: save_attachment_in_eis(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +# Get child workspace approval status from EIS, +# return undef in case of error. +sub get_status_from_eis +{ + my $self = shift; + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->getStatus($id) }; + if ( $@ ) { + carp("ERROR: get_status(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +# Get child workspace approval status from EIS, +# return undef in case of error. +sub set_status_in_eis +{ + my $self = shift; + my $status = shift; + my $method = 'set'; + $method .= (defined $status) ? $status : 'Integrated'; + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + my $eis = Cws::eis(); + my $result; + if (defined $status) { + eval { $result = $eis->setFixedOnMaster($id) }; + } else { + eval { $result = $eis->setIntegrated($id) }; + } + if ( $@ ) { + carp("ERROR: $method(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +# Get child workspace approval status from EIS, +# return undef in case of error. +sub set_integration_milestone_in_eis +{ + my $self = shift; + my $milestone = shift; + my $buildid = shift; + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $eis = Cws::eis(); + + # just in case ... + if ( !defined($milestone) ) { + $milestone = Eis::to_string(''); + } + # $buildid must be transfered as string + if ( !defined($buildid) ) { + $buildid = Eis::to_string(''); + } + else { + $buildid = Eis::to_string($buildid); + } + + my $result; + eval { $result = $eis->setIntegrationMilestone($id, $milestone, $buildid) }; + if ( $@ ) { + carp("ERROR: set_integration_milestone(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +sub set_milestone_buildid_in_eis +{ + my $self = shift; + my $master = shift; + my $milestone = shift; + my $buildid = shift; + + $master = Eis::to_string($master); + $milestone = Eis::to_string($milestone); + $buildid = Eis::to_string($buildid); + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->setMilestoneBuild( $master, $milestone, $buildid ) }; + if ( $@ ) { + carp("ERROR: set_milestone_buildid(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +sub set_current_milestone_in_eis +{ + my $self = shift; + my $master = shift; + my $milestone = shift; + + $master = Eis::to_string($master); + $milestone = Eis::to_string($milestone); + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->setCurrentMilestone( $master, $milestone ) }; + if ( $@ ) { + carp("ERROR: set_current_milestone(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +sub get_current_milestone_from_eis +{ + my $self = shift; + my $master = shift; + + $master = Eis::to_string($master); + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->getCurrentMilestone( $master ) }; + if ( $@ ) { + carp("ERROR: get_current_milestone(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +sub get_masters_from_eis +{ + my $self = shift; + + my $eis = Cws::eis(); + my @result; + eval { @result = $eis->getMasterWorkspaces() }; + if ( $@ ) { + carp("ERROR: get_masters(): EIS database transaction failed. Reason:\n$@\n"); + } + + my @result2=(); + my $i=0; + while ( defined($result[0][$i]) ) { + push @result2,$result[0][$i]; + $i++; + } + return @result2; +} + + +sub get_milestones_from_eis +{ + my $self = shift; + my $master = shift; + + $master = Eis::to_string($master); + + my $eis = Cws::eis(); + my @result; + eval { @result = $eis->getMilestones( $master ) }; + if ( $@ ) { + carp("ERROR: get_milestones(): EIS database transaction failed. Reason:\n$@\n"); + } + my @result2=(); + my $i=0; + while ( defined($result[0][$i]) ) { + push @result2,$result[0][$i]; + $i++; + } + return @result2; +} + +# Get child workspace owner from EIS, +# return undef in case of error. +sub expand_buildid_in_eis +{ + my $self = shift; + my $bid = shift; + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $name = $self->child(); + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->expandBuildId($bid, $name) }; + if ( $@ ) { + carp("ERROR: expand_builid(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +sub set_milestone_removed_in_eis +{ + my $self = shift; + my $master = shift; + my $milestone = shift; + + $master = Eis::to_string($master); + $milestone = Eis::to_string($milestone); + + my $eis = Cws::eis(); + eval { $eis->minorRemoved( $master, $milestone ) }; + if ( $@ ) { + carp("ERROR: set_current_milestone(): EIS database transaction failed. Reason:\n$@\n"); + } + return; +} + +sub is_milestone_registered_with_eis +{ + my $self = shift; + my $master = shift; + my $milestone = shift; + + $master = Eis::to_string($master); + $milestone = Eis::to_string($milestone); + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->isMilestoneValid($master, $milestone) }; + if ( $@ ) { + carp("ERROR: is_milestone(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +sub get_is_milestone_used_from_eis +{ + my $self = shift; + my $master = shift; + my $milestone = shift; + + $master = Eis::to_string($master); + $milestone = Eis::to_string($milestone); + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->isMilestoneInUse($master, $milestone) }; + if ( $@ ) { + carp("ERROR: is_milestone_used(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +sub get_buildid_for_milestone +{ + my $self = shift; + my $master = shift; + my $milestone = shift; + + $master = Eis::to_string($master); + $milestone = Eis::to_string($milestone); + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->getMilestoneBuild($master, $milestone) }; + if ( $@ ) { + carp("ERROR: get_buildid_for_milestone(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +sub get_childworkspaces_for_milestone +{ + my $self = shift; + my $master = shift; + my $milestone = shift; + + $master = Eis::to_string($master); + $milestone = Eis::to_string($milestone); + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->searchChildWorkspacesForMilestone($master, $milestone) }; + if ( $@ ) { + carp("ERROR: get_childworkspaces_for_milestone(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +sub get_cws_with_state_from_eis { + my $self = shift; + my $mws = shift; + my $status = shift; + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->getCWSWithState($mws, $status) }; + if ( $@ ) { + carp("ERROR: get_cws_with_state_from_eis(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +sub get_task_prios_of_tasks +{ + my $self = shift; + my $ref_taskids = shift; + + my $eis = Cws::eis(); + my $result; + my @items = (); + foreach ( @{$ref_taskids} ) { + push(@items, Eis::to_string($_)); + } + + eval { $result = $eis->getTasksPriorities( \@items ) }; + if ( $@ ) { + carp("ERROR: get_task_prios_of_tasks(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +sub get_creation_master_from_eis +{ + my $self = shift; + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->getCreationMasterWorkspace($id) }; + if ( $@ ) { + carp("ERROR: get_creation_master(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; + +} + +sub get_milestone_integrated_from_eis +{ + my $self = shift; + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->getMilestoneIntegrated($id) }; + if ( $@ ) { + carp("ERROR: get_milestone_integrated(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; + +} + +# get isPublic flag from eis +sub get_public_flag_from_eis +{ + my $self = shift; + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->isPublic($id) }; + if ( $@ ) { + carp("ERROR: get_public_flag(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +# get isPublicMaster flag from eis +sub get_publicmaster_flag_from_eis +{ + my $self = shift; + + # check if child workspace is valid + my $master = $self->master(); + if ( !$master ) { + carp("ERROR: MasterWorkspace not defined.\n"); + return undef; + } + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->isPublicMaster($master) }; + if ( $@ ) { + carp("ERROR: get_publicmaster_flag(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +# get isSubVersion flag from eis +sub get_subversion_flag_from_eis +{ + my $self = shift; + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->isSubVersion($id) }; + if ( $@ ) { + carp("ERROR: get_subversion_flag(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + +# set isSubVersion flag in eis +sub set_subversion_flag_in_eis +{ + my $self=shift; + my $status=shift; + + my $bool_status=SOAP::Data->type(boolean => $status); + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->setSubVersion($id,$bool_status) }; + if ( $@ ) { + carp("ERROR: get_subversion_flag(): EIS database transaction failed. Reason:\n$@\n"); + } + return $result; +} + + +sub is_uirelevant_from_eis +{ + my $self = shift; + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->isUIRelevant($id) }; + if ( $@ ) { + carp("ERROR: is_uirelevant_from_eis(): EIS database transaction failed. Reason:\n$@\n"); + } + + return $result; +} + +sub is_helprelevant_from_eis +{ + my $self = shift; + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->isHelpRelevant( $id ) }; + if ( $@ ) { + carp("ERROR: is_helprelevant_from_eis(): EIS database transaction failed. Reason:\n$@\n"); + } + + return $result; +} +sub set_word_count_in_eis +{ + my $self = shift; + my $language = shift; + my $wordcount = shift; + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->setWordCount( $id , $language , $wordcount ) }; + if ( $@ ) { + carp("ERROR: set_word_count_from_eis(): EIS database transaction failed. Reason:\n$@\n"); + } + + return $result; +} + + +sub get_l10n_status_from_eis +{ + my $self = shift; + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->getL10n( $id ) }; + if ( $@ ) { + carp("ERROR: get_l10n_status_from_eis(): EIS database transaction failed. Reason:\n$@\n"); + } + + return $result; +} + +sub set_l10n_status_in_eis +{ + my $self = shift; + my $status = Eis::to_string( shift ); + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $eis = Cws::eis(); + my $result; + + eval { $result = $eis->setL10n( $id , $status ) }; + if ( $@ ) { + carp("ERROR: set_l10n_status_in_eis(): EIS database transaction failed. Reason:\n$@\n"); + } + + return $result; +} + +sub get_is_cws_cloneable_from_eis +{ + my $self = shift; + my $master = Eis::to_string( shift ); + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $eis = Cws::eis(); + my $result; + + eval { $result = $eis->isClonableForMaster($id, $master) }; + if ( $@ ) { + carp("ERROR: get_is_cws_cloneable_from_eis(): EIS database transaction failed. Reason:\n$@\n"); + } + + return $result; +} + +sub clone_cws_in_eis +{ + my $self = shift; + my $master = Eis::to_string( shift ); + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $eis = Cws::eis(); + my $result; + + eval { $eis->cloneForMaster($id, $master) }; + if ( $@ ) { + carp("ERROR: clone_cws_in_eis(): EIS database transaction failed. Reason:\n$@\n"); + return 0; + } + + return 1; +} + +sub get_release_from_eis +{ + my $self = shift; + my $master = Eis::to_string( shift ); + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $eis = Cws::eis(); + my $result; + + eval { $result = $eis->getRelease($id) }; + if ( $@ ) { + carp("ERROR: get_release_from_eis(): EIS database transaction failed. Reason:\n$@\n"); + } + + return $result; +} + +sub get_due_date_from_eis +{ + my $self = shift; + my $master = Eis::to_string( shift ); + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $eis = Cws::eis(); + my $result; + + eval { $result = $eis->getDueDate($id) }; + if ( $@ ) { + carp("ERROR: get_due_date_from_eis(): EIS database transaction failed. Reason:\n$@\n"); + } + + return $result; +} + +sub get_due_date_qa_from_eis +{ + my $self = shift; + my $master = Eis::to_string( shift ); + + # check if child workspace is valid + my $id = $self->eis_id(); + if ( !$id ) { + carp("ERROR: Childworkspace not (yet) registered with EIS.\n"); + return undef; + } + + my $eis = Cws::eis(); + my $result; + + eval { $result = $eis->getDueDateQA($id) }; + if ( $@ ) { + carp("ERROR: get_due_date_qa_from_eis(): EIS database transaction failed. Reason:\n$@\n"); + } + + return $result; +} + + +#logging +sub set_log_entry_in_eis +{ + my $self = shift; + my $commandline = shift; + my $vcsid = shift; + my $start = shift; + my $end = shift; + my $comment = shift; + + $commandline = SOAP::Data->type(string => $commandline); + $comment = SOAP::Data->type(string => $comment); + + # *format* for $start and $end = "2003-05-28 12:34:59"; + +#===================================================== + #TO DO: + #experimenell für saubere schnittstelle + #$start = SOAP::Data->type(dateTime => $start); + #$end = SOAP::Data->type(dateTime => $end); +#===================================================== + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->storeCommandLogEntry( $commandline, $vcsid, $start, $end, $comment ) }; + if ( $@ ) { + carp("ERROR: set_log_entry(): Logging failed. Reason:\n$@\n"); + } + return $result; +} + +#set_log_entry_extended_in_eis($commandname, $parameter, $vcsid, $start, $stop, $comment, $mastername, $childname); +sub set_log_entry_extended_in_eis +{ + my $self = shift; + my $commandname = shift; + my $parameter = shift; + my $vcsid = shift; + my $start = shift; + my $end = shift; + my $comment = shift; + my $mastername = shift; + my $childname = shift; + + $commandname = SOAP::Data->type(string => $commandname); + $parameter = SOAP::Data->type(string => $parameter); + $comment = SOAP::Data->type(string => $comment); + $mastername = SOAP::Data->type(string => $mastername); + $childname = SOAP::Data->type(string => $childname); + + # *format* for $start and $end = "2003-05-28 12:34:59"; + +#===================================================== + #TO DO: + #experimenell für saubere schnittstelle + #$start = SOAP::Data->type(dateTime => $start); + #$end = SOAP::Data->type(dateTime => $end); +#===================================================== + + my $eis = Cws::eis(); + my $result; + eval { $result = $eis->storeCommandLogEntry($commandname, $parameter, $vcsid, $start, $end, $comment, $mastername, $childname) }; + if ( $@ ) { + carp("ERROR: set_log_entry_extended(): Logging failed. Reason:\n$@\n"); + } + return $result; +} + + +#### class methods #### + +sub init_eis_connector +{ + my $eis = Eis->new( uri => Cws::eis_uri(), + proxy_list => Cws::eis_proxy_list(), + net_proxy => Cws::net_proxy() + ); + return $eis; +} + +#### + +1; # needed by "use" or "require" +# vim: set ts=4 shiftwidth=4 expandtab syntax=perl: diff --git a/solenv/bin/modules/CwsConfig.pm b/solenv/bin/modules/CwsConfig.pm new file mode 100644 index 000000000000..a346ba7d4d50 --- /dev/null +++ b/solenv/bin/modules/CwsConfig.pm @@ -0,0 +1,488 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: CwsConfig.pm,v $ +# +# $Revision: 1.11.44.2 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +# +# CwsConfig.pm - package for read CWS config data +# + +package CwsConfig; +use strict; + +use Carp; +use URI::Escape; + +##### ctor #### + +sub new +{ + my $invocant = shift; + my $class = ref($invocant) || $invocant; + my $self = {}; + $self->{_CONFIG_FILE} = undef; # config file + $self->{_GLOBAL} = undef; # is it a global config file? + $self->{VCSID} = undef; # VCSID + $self->{CWS_DB_URL_LIST_REF} = undef; # list of CWS DB servers + $self->{NET_PROXY} = undef; # network proxy + $self->{CWS_SERVER_ROOT} = undef; # cvs server + $self->{CWS_MIRROR_ROOT} = undef; # mirror of cvs server + $self->{CWS_LOCAL_ROOT} = undef; # local cvs server + $self->{PUBLIC_SVN_SERVER} = undef; # public svn server + $self->{PRIVATE_SVN_SERVER} = undef; # private svn server + bless ($self, $class); + return $self; +} + +sub vcsid +{ + my $self = shift; + + if ( !defined($self->{VCSID}) ) { + # environment overrides config file + my $vcsid = $ENV{VCSID}; + if ( !defined($vcsid) ) { + # check config file + my $config_file = $self->get_config_file(); + $vcsid = $config_file->{CWS_CONFIG}->{'CVS_ID'}; + if ( !defined($vcsid) ) { + # give up + croak("ERROR: no CVS_ID entry found in '\$HOME/.cwsrc'.\n" ); + } + } + $self->{VCSID} = $vcsid; + } + return $self->{VCSID}; +} + +sub cws_db_url_list_ref +{ + my $self = shift; + + if ( !defined($self->{CWS_DB_URL_LIST_REF}) ) { + my $config_file = $self->get_config_file(); + + my $i = 1; + my @cws_db_servers; + + while ( 1 ) { + my $val = $config_file->{CWS_CONFIG}->{"CWS_DB_SERVER_$i"}; + last if !defined($val); + push(@cws_db_servers, $val); + $i++; + } + + if ( !@cws_db_servers) { + croak("ERROR: no CWS_DB_SERVER_* entry found in '\$HOME/.cwsrc'.\n" ); + } + + if ( $cws_db_servers[0] =~ /^https:\/\// ) { + my $id = $self->vcsid(); + my $password = $config_file->{CWS_CONFIG}->{'CVS_PASSWORD'}; + + if ( !defined($password) ) { + croak("ERROR: no CVS_PASSWORD entry found in '\$HOME/.cwsrc'.\n" ); + } + + # *i49473* - do not accept scrambled passwords ending with a space + if ( $password =~ / $/) { + croak("ERROR: The (scrambled) CVS_PASSWORD ends with a space. This is known to cause problems when connecting to the OpenOffice.org EIS database. Please change your OOo account's password" ); + } + + # We are going to stuff $id and $password in an URL, do proper escaping. + $id = uri_escape($id); + $password = uri_escape($password); + + foreach ( @cws_db_servers ) { + s/^https:\/\//https:\/\/$id:$password@/; + } + } + + $self->{CWS_DB_URL_LIST_REF} = \@cws_db_servers; + } + return $self->{CWS_DB_URL_LIST_REF}; +} + +sub net_proxy +{ + my $self = shift; + + if ( !defined($self->{NET_PROXY}) ) { + my $config_file = $self->get_config_file(); + my $net_proxy = $config_file->{CWS_CONFIG}->{'PROXY'}; + if ( !defined($net_proxy) ) { + $net_proxy = ""; + } + $self->{NET_PROXY} = $net_proxy; + } + return $self->{NET_PROXY} ? $self->{NET_PROXY} : undef; +} + +sub cvs_binary +{ + my $self = shift; + + if ( !defined($self->{CVS_BINARY}) ) { + my $config_file = $self->get_config_file(); + my $cvs_binary = $config_file->{CWS_CONFIG}->{'CVS_BINARY'}; + if ( !defined($cvs_binary) ) { + # defaults + $cvs_binary = ($^O eq 'MSWin32') ? 'cvs.exe' : 'cvs'; + } + # special case, don't ask + if ( $self->{_GLOBAL} && $cvs_binary =~ /cvs.clt2/ && $^O eq 'MSWin32' ) { + $cvs_binary = 'cvsclt2.exe'; + } + $self->{CVS_BINARY} = $cvs_binary; + } + return $self->{CVS_BINARY}; +} + +sub cvs_server_root +{ + my $self = shift; + + if ( !defined($self->{CVS_SERVER_ROOT}) ) { + my $config_file = $self->get_config_file(); + my $cvs_server_root = $config_file->{CWS_CONFIG}->{'CVS_SERVER_ROOT'}; + if ( !defined($cvs_server_root) ) { + # give up, this is a mandatory entry + croak("ERROR: can't parse CVS_SERVER_ROOT entry in '\$HOME/.cwsrc'.\n"); + } + if ( $self->{_GLOBAL} ) { + # a global config file will almost always have the wrong vcsid in + # the cvsroot -> substitute vcsid + my $id = $self->vcsid(); + $cvs_server_root =~ s/:pserver:\w+@/:pserver:$id@/; + } + $self->{CVS_SERVER_ROOT} = $cvs_server_root; + } + return $self->{CVS_SERVER_ROOT}; +} + +sub cvs_mirror_root +{ + my $self = shift; + + if ( !defined($self->{CVS_MIRROR_ROOT}) ) { + my $config_file = $self->get_config_file(); + my $cvs_mirror_root = $config_file->{CWS_CONFIG}->{'CVS_MIRROR_ROOT'}; + if ( !defined($cvs_mirror_root) ) { + $cvs_mirror_root = ""; + } + $self->{CVS_MIRROR_ROOT} = $cvs_mirror_root; + } + return $self->{CVS_MIRROR_ROOT} ? $self->{CVS_MIRROR_ROOT} : undef; +} + +sub cvs_local_root +{ + my $self = shift; + + if ( !defined($self->{CVS_LOCAL_ROOT}) ) { + my $config_file = $self->get_config_file(); + my $cvs_local_root = $config_file->{CWS_CONFIG}->{'CVS_LOCAL_ROOT'}; + if ( !defined($cvs_local_root) ) { + $cvs_local_root = ""; + } + $self->{CVS_LOCAL_ROOT} = $cvs_local_root; + } + return $self->{CVS_LOCAL_ROOT} ? $self->{CVS_LOCAL_ROOT} : undef; +} + +sub get_cvs_server +{ + my $self = shift; + + my ($method, $id, $server, $repository) = CwsConfig::split_root($self->cvs_server_root(), 'SERVER'); + return $server; +} + +sub get_cvs_mirror +{ + my $self = shift; + + my ($method, $id, $server, $repository) = CwsConfig::split_root($self->cvs_mirror_root(), 'MIRROR'); + return $server; +} + +sub get_cvs_local +{ + my $self = shift; + + my ($method, $id, $server, $repository) = CwsConfig::split_root($self->cvs_local_root(), 'LOCAL'); + return $server; +} + +sub get_cvs_server_method +{ + my $self = shift; + + my ($method, $id, $server, $repository) = CwsConfig::split_root($self->cvs_server_root(), 'SERVER'); + return $method; +} + +sub get_cvs_mirror_method +{ + my $self = shift; + + my ($method, $id, $server, $repository) = CwsConfig::split_root($self->cvs_mirror_root(), 'MIRROR'); + return $method; +} + +sub get_cvs_local_method +{ + my $self = shift; + + my ($method, $id, $server, $repository) = CwsConfig::split_root($self->cvs_local_root(), 'LOCAL'); + return $method; +} + +sub get_cvs_server_repository +{ + my $self = shift; + + my ($method, $id, $server, $repository) = CwsConfig::split_root($self->cvs_server_root(), 'SERVER'); + return $repository; +} + +sub get_cvs_mirror_repository +{ + my $self = shift; + + my ($method, $id, $server, $repository) = CwsConfig::split_root($self->cvs_mirror_root(), 'MIRROR'); + return $repository; +} + +sub get_cvs_local_repository +{ + my $self = shift; + + my ($method, $id, $server, $repository) = CwsConfig::split_root($self->cvs_local_root(), 'LOCAL'); + return $repository; +} + +sub get_cvs_server_id +{ + my $self = shift; + + my ($method, $id, $server, $repository) = CwsConfig::split_root($self->cvs_server_root(), 'SERVER'); + return $id; +} + +sub get_cvs_mirror_id +{ + my $self = shift; + + my ($method, $id, $server, $repository) = CwsConfig::split_root($self->cvs_mirror_root(), 'MIRROR'); + return $id; +} + +sub get_cvs_local_id +{ + my $self = shift; + + my ($method, $id, $server, $repository) = CwsConfig::split_root($self->cvs_local_root(), 'LOCAL'); + return $id; +} + +#### SVN methods #### + +sub get_ooo_svn_server +{ + my $self = shift; + + if ( !defined($self->{SVN_SERVER}) ) { + my $config_file = $self->get_config_file(); + my $ooo_svn_server = $config_file->{CWS_CONFIG}->{'SVN_SERVER'}; + if ( !defined($ooo_svn_server) ) { + $ooo_svn_server = ""; + } + $self->{SVN_SERVER} = $ooo_svn_server; + } + return $self->{SVN_SERVER} ? $self->{SVN_SERVER} : undef; +} + +sub get_so_svn_server +{ + my $self = shift; + + if ( !defined($self->{SO_SVN_SERVER}) ) { + my $config_file = $self->get_config_file(); + my $so_svn_server = $config_file->{CWS_CONFIG}->{'SO_SVN_SERVER'}; + if ( !defined($so_svn_server) ) { + $so_svn_server = ""; + } + $self->{SO_SVN_SERVER} = $so_svn_server; + } + return $self->{SO_SVN_SERVER} ? $self->{SO_SVN_SERVER} : undef; +} + +#### Prebuild binaries configuration #### + +sub get_prebuild_binaries_location +{ + my $self = shift; + + if ( !defined($self->{PREBUILD_BINARIES}) ) { + my $config_file = $self->get_config_file(); + my $pre_build_binaries = $config_file->{CWS_CONFIG}->{'PREBUILD_BINARIES'}; + if ( !defined($pre_build_binaries) ) { + $pre_build_binaries = ""; + } + $self->{PREBUILD_BINARIES} = $pre_build_binaries; + } + return $self->{PREBUILD_BINARIES} ? $self->{PREBUILD_BINARIES} : undef; +} + + + +#### class methods ##### +sub get_config +{ + my $config = CwsConfig->new(); + return $config; +} + +sub split_root +{ + my $root = shift; + my $type = shift; + + if ( !defined($root) ) { + return (undef, undef, undef, undef); + } + + my ($dummy, $method, $id_at_host, $repository) = split(/:/, $root); + $repository =~ s/^\d*//; + my ($id, $server); + if ( $id_at_host ) { + ($id, $server) = split(/@/, $id_at_host); + } + if ( !defined($method) || !defined($id) || !defined($server) || !defined($repository) ) { + # give up + print "$method, $id, $server, $repository\n"; + croak("ERROR: can't parse CVS_".$type."_ROOT entry in '\$HOME/.cwsrc'.\n"); + } + return ($method, $id, $server, $repository); +} + +#### private helper methods #### + +sub get_config_file +{ + my $self = shift; + + if ( !defined $self->{_CONFIG_FILE} ) { + $self->parse_config_file(); + } + return $self->{_CONFIG_FILE}; +} + +sub read_config +{ + my $self = shift; + my $fname = shift; + my $fhandle; + my $section = ''; + my %config; + + open ($fhandle, $fname) || croak("ERROR: Can't open '$fname': $!"); + while ( <$fhandle> ) { + tr/\r\n//d; # win32 pain + # Issue #i62815#: Scrambled CVS passwords may contain one or more '#'. + # Ugly special case needed: still allow in-line (perl style) comments + # elsewhere because existing configuration files may depend on them. + if ( !/^\s*CVS_PASSWORD/ ) { + s/\#.*//; # kill comments + } + /^\s*$/ && next; + + if (/\[\s*(\S+)\s*\]/) { + $section = $1; + if (!defined $config{$section}) { + $config{$section} = {}; + } + } + defined $config{$section} || croak("ERROR: unknown / no section '$section'\n"); + if ( m/(\w[\w\d]*)=(.*)/ ) { + my $var = $1; + my $val = $2; + # New style value strings may be surrounded by quotes + if ( $val =~ s/\s*(['"])(.*)\1\s*$/$2/ ) { + my $quote = $1; + # If and only if the value string is surrounded by quotes we + # can expect that \" or \' are escaped characters. In an unquoted + # old style value string they could mean exactly what is standing there + # + # Actually the RE above works without quoting the quote character + # (either " or ') inside the value string but users will probably + # expect that they need to be escaped if quotes are used. + # + # This is still not completly correct for all thinkable situations but + # should be good enough for all practical use cases. + $val =~ s/\\($quote)/$1/g; + } + $config{$section}->{$var} = $val; + # print "Set '$var' to '$val'\n"; + } + } + close ($fhandle) || croak("ERROR: Failed to close: $!"); + + $self->{_CONFIG_FILE} = \%config; +} + +sub parse_config_file +{ + my $self = shift; + + my $config_file; + # check for config files + if ( -e "$ENV{HOME}/.cwsrc" ) { + $self->read_config("$ENV{HOME}/.cwsrc"); + $self->{_GLOBAL} = 0; + } + elsif ( -e "$ENV{COMMON_ENV_TOOLS}/cwsrc" ) { + $self->read_config("$ENV{COMMON_ENV_TOOLS}/cwsrc"); + $self->{_GLOBAL} = 1; + } + else { + croak("ERROR: can't find CWS config file '\$HOME/.cwsrc'.\n"); + } +} + +sub sointernal +{ + my $self = shift; + my $config_file = $self->get_config_file(); + my $val = ($config_file->{CWS_CONFIG}->{"SO_INTERNAL"}) ? 1 : 0; + return $val; +} +1; # needed by "use" or "require" diff --git a/solenv/bin/modules/Eis.pm b/solenv/bin/modules/Eis.pm new file mode 100755 index 000000000000..f06c0387d64f --- /dev/null +++ b/solenv/bin/modules/Eis.pm @@ -0,0 +1,224 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: Eis.pm,v $ +# +# $Revision: 1.7 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +# +# Eis.pm - package for accessing/manipulating the EIS database via SOAP +# + +package Eis; +use strict; + +use SOAP::Lite; +use Class::Struct; +use Carp; + +# Declaration of class Eis together with ctor and accessors. +# See 'perldoc Class::Struct' for details + +struct Eis => [ + # public members + uri => '$', # name of webservice + proxy_list => '@', # list of proxy URLs + current_proxy => '$', # current proxy (index in proxy_list) + net_proxy => '$', # network proxy to pass through firewall + # private members + eis_connector => '$' # SOAP connector to EIS database +]; + +#### public methods #### + +# Any not predeclared method call to this package is +# interpreted as a SOAP method call. We use the AUTOLOAD +# mechanism to intercept these calls and delgate them +# to the eis_connector. +# See the 'Camel Book', 3rd edition, page 337 for an +# explanation of the AUTOLOAD mechanism. +sub AUTOLOAD +{ + my $self = shift; + my $callee = $Eis::AUTOLOAD; # $callee now holds the name of + # called subroutine + # + return if $callee =~ /::DESTROY$/; + $callee = substr($callee, 5); + + my $sl = $self->eis_connector(); + if ( !$sl ) { + $sl = $self->init_eis_connector(); + $self->eis_connector($sl); + } + + my $response; + while ( 1 ) { + # Call callee() on web service. + eval { $response = $sl->$callee(@_) }; + if ( $@ ) { + # Transport error (server not available, timeout, etc). + # Use backup server. + print STDERR ("Warning: web service unavailable. Trying backup server.\n"); + if ( !$self->set_next_proxy() ) { + # All proxies tried, out of luck + carp("ERROR: Connection to EIS database failed.\n"); + return undef; + } + } + else { + last; + } + } + + if ( $response->fault() ) { + my $fault_msg = get_soap_fault_message($response); + die $fault_msg; # throw $fault_msg as exception + } + else { + return $response->result(); + } +} + +#### public class methods #### + +# Turn scalar into SOAP string. +sub to_string +{ + my $value = shift; + + return SOAP::Data->type(string => $value); +} + +#### non public instance methods #### + +# Initialize SOAP connection to EIS. +sub init_eis_connector +{ + my $self = shift; + + # Init current_proxy with first element of the proxy list. + my $current = $self->current_proxy(0); + + if ( !$self->uri() ) { + carp("ERROR: web service URI not set."); + return undef; + } + + if ( !$self->proxy_list->[$current] ) { + carp("ERROR: proxy list not proper initialized."); + return undef; + } + + # might be needed to get through a firewall + if ( defined($self->net_proxy()) ) { + $ENV{HTTPS_PROXY}=$self->net_proxy(); + } + + my $proxy = $self->proxy_list()->[$current]; + if ( $proxy =~ /^\s*https\:\/\// ) { + # SOAP::Lite does not complain if Crypt::SSLeay is not available, + # but crypted connections will just not work. Force the detection of + # Crypt::SSLeay for https connections and fail with a meaningful + # message if it's not available. + require Crypt::SSLeay; + } + return create_eis_connector($self->uri(), $proxy); +} + +# Advance one entry in proxy list. +sub set_next_proxy +{ + my $self = shift; + + my @proxies = @{$self->proxy_list()}; + my $current = $self->current_proxy(); + + if ( $current == $#proxies ) { + return 0; + } + else { + $self->current_proxy(++$current); + my $next_proxy = $self->proxy_list()->[$current]; + $self->eis_connector()->proxy($next_proxy); + return 1; + } +} + +#### misc #### + +# Create new SOAP EIS conector. +sub create_eis_connector +{ + my $uri = shift; + my $proxy = shift; + + my $sl; + + # With version 0.66 of SOAP::Lite the uri() method + # has been deprecated in favour of ns(). There + # seems to be no way to switch of the deprecation warning + # (which may be a bug in this version of SOAP::Lite). + # Since older versions do not support the ns() method we + # either force everyone to upgrade now, or make the following + # dependent on the SOAP::Lite version. + my ($vmaj, $vmin) = (0, 0); + if( $SOAP::Lite::VERSION =~ m/([0-9]*)\.([0-9]*)/ ) { + $vmaj = $1; + $vmin = $2; + if ( $vmaj > 0 || ( $vmaj == 0 && $vmin >= 66 ) ) { + $sl = SOAP::Lite + -> ns($uri) + -> proxy($proxy); + } + else { + $sl = SOAP::Lite + -> uri($uri) + -> proxy($proxy); + } + } + else { + carp("ERROR: Can't determine SOAP::Lite version."); + } + + return $sl; +} + +# Retrieve SOAP fault message. +sub get_soap_fault_message +{ + my $faulty_response = shift; + my $fault_msg = join(', ', $faulty_response->faultcode(), + $faulty_response->faultstring(), + $faulty_response->faultdetail()); + return $fault_msg; +} + +#### + +1; # needed by "use" or "require" diff --git a/solenv/bin/modules/GenInfoParser.pm b/solenv/bin/modules/GenInfoParser.pm new file mode 100644 index 000000000000..c211c0c82a28 --- /dev/null +++ b/solenv/bin/modules/GenInfoParser.pm @@ -0,0 +1,300 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: GenInfoParser.pm,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +#************************************************************************* +# +# GenInfoParser - Perl extension for parsing general info databases +# +# usage: see below +# +#************************************************************************* + +package GenInfoParser; + +use strict; + +use Carp; + +##### profiling ##### +# use Benchmark; + +##### ctor ##### + +sub new { + my $proto = shift; + my $class = ref($proto) || $proto; + my $self = {}; + $self->{'LIST'} = undef; + $self->{'DATA'} = {}; + bless ($self, $class); + return $self; +} + +##### methods ##### + +sub load_list +{ + # load list into memory + my $self = shift; + my $list_file = shift; + + if ( $self->parse_list($list_file) ) { + return 1; + } + return 0; +} + +sub get_keys +{ + # return a sorted list of keys, the sorting is case insensitive + my $self = shift; + my $access_path = shift; + + my ($key, $value, $sub_data_ref) = $self->walk_accesspath($access_path); + + my @keys = (); + if ( $sub_data_ref ) { + my @normalized_keys = keys %$sub_data_ref; + foreach my $normalized_key (sort keys %$sub_data_ref) { + push(@keys, $$sub_data_ref{$normalized_key}[0]); + } + } elsif ( $value ) { + chomp $value; + push @keys, ($value); + } + return @keys; +} + +sub get_key +{ + # returns the key corresponding to the access_path + my $self = shift; + my $access_path = shift; + + my ($key, $value, $sub_data_ref) = $self->walk_accesspath($access_path); + return undef if !$key; + return $key; +} + +sub get_value +{ + # returns the value corresponding to the access_path + my $self = shift; + my $access_path = shift; + + my ($key, $value, $sub_data_ref) = $self->walk_accesspath($access_path); + return undef if !$key; + $value = "" if !defined($value); + # trim line ends + $value =~ tr/\r\n//d; + # trim trailing whitespace + $value =~ s/\s+$//; + return $value; +} + +##### private methods ##### + +sub parse_list +{ + # parse complete list + my $self = shift; + my $list_file = shift; + my @list_data; + + return 0 if ! -r $list_file; + + open(FILE, "<$list_file") or croak("can't open $list_file: $!"); + # my $t0 = new Benchmark; + $self->parse_block(\*FILE, $self->{'DATA'}); + # my $t1 = new Benchmark; + # print STDERR "parsing $list_file took: ", timestr(timediff($t1, $t0)), "\n"; + close(FILE); +} + +sub parse_block +{ + # parse each sub block and place it in a hash + # used data structure: + # $hash{$normalized_key} = [ $key, $value, 0 | $sub_hash_ref ] + my $self = shift; + my $glob_ref = shift; + my $data_ref = shift; + + my $current_key = 0; + my $line; + while( $line = <$glob_ref> ) { + # this is the inner loop, any additional pattern matching will + # have a notable affect on runtime behavior + # clean up of $value is done in get_value() + my ($key, $value) = split(' ', $line, 2); + next if !$key; # skip empty lines + my $chr = substr($key, 0, 1); + next if $chr eq '#'; # skip comment lines + last if $chr eq '}'; # return from block; + if ( $chr eq '{' ) { + if ( !$current_key ) { + croak("unexpected block start"); + } + else { + # create empty hash and start sub block parse + $$data_ref{$current_key}[2] = {}; + $self->parse_block($glob_ref, $$data_ref{$current_key}[2]); + next; + } + } + # sanity check + croak("key $key is not well formed") if $key =~ /\//; + # normalize key for hash lookup + $current_key = lc($key); + # but we have to keep the original - not normalized - key, too + $$data_ref{($current_key)} = [$key, $value, 0]; + } +} + +sub walk_accesspath +{ + # returns the key, value and sub_data_ref which + # corresponds to the access_path + + my $self = shift; + my $access_path = shift; + + my $sub_data_ref = $self->{'DATA'}; + + if ( $access_path ) { + my $lookup_ref = 0; + # normalize key + $access_path = lc($access_path); + my @key_sequence = split(/\//, $access_path); + foreach my $key_element (@key_sequence) { + # at least one more key element, but no sub_hash, accesspath invalid + return () if !$sub_data_ref; + $lookup_ref = $$sub_data_ref{$key_element}; + # lookup failed, accesspath invalid + return () if !defined($lookup_ref); + # we've got a valid key + $sub_data_ref = $$lookup_ref[2]; + } + return ($$lookup_ref[0], $$lookup_ref[1], $sub_data_ref); + } + else { + # empty access path is only vlaid for getting top level key list + return ( undef, undef, $sub_data_ref ); + } +} + +##### finish ##### + +1; # needed by use or require + +__END__ + +=head1 NAME + +GenInfoParser - Perl extension for parsing general info databases + +=head1 SYNOPSIS + + # example that will load a general info database called 'stand.lst' + + use GenInfoParser; + + # Create a new instance of the parser: + $a = GenInfoParser->new(); + + # Load the database into the parser: + $a->load_list('ssrc633.ini'); + + # get top level keys from database + @top_level_keys = $a->get_keys(); + + # get sub list keys + @sub_list_keys = $a->get_keys('src633/Drives/o:/Projects'); + + # get key/value pair + $key = $a->get_key('src633/Comment/build'); + $value = $a->get_value('src633/Comment/build'); + +=head1 DESCRIPTION + +GenInfoParser is a perl extension to load and parse General Info Databses. +It uses a simple object oriented interface to retrieve the information stored +in the database. + +Methods: + +GenInfoParser::new() + +Creates a new instance of the parser. Can't fail. + + +GenInfoParser::load_list($database) + +Loads and parses $database. Returns 1 on success and 0 on failure + + +GenInfoParser::get_keys($path) + +Returns a sorted list of keys from the path $path. Returns an emtpy list if $path +has no sublist. If there is no $path spcified, the method will return the +primary key list. $path can be specified case insensitive. Sorting is done case +insensitive. + +GenInfoParser::get_key($path) + +Returns the key to $path or 'undef' if an invalid path is given. +Example: $path = 'src633/comment/build' will return 'Build' as key. +Note: $path can be specified case insensitive, but the returned key will +have the exact case as in the database. + +GenInfoParser::get_value($path) + +Returns the value to $path or 'undef' is invalid path is given. + + +=head2 EXPORT + +GenInfoParser::new() +GenInfoParser::load_list($database) +GenInfoParser::get_keys($path) +GenInfoParser::get_key($path) +GenInfoParser::get_value($path) + + +=head1 AUTHOR + +Jens-Heiner Rechtien, rechtien@sun.com + +=head1 SEE ALSO + +perl(1). + +=cut diff --git a/solenv/bin/modules/installer/archivefiles.pm b/solenv/bin/modules/installer/archivefiles.pm new file mode 100644 index 000000000000..8d969c79df93 --- /dev/null +++ b/solenv/bin/modules/installer/archivefiles.pm @@ -0,0 +1,507 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: archivefiles.pm,v $ +# +# $Revision: 1.18 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::archivefiles; + +use installer::converter; +use installer::existence; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::logger; +use installer::pathanalyzer; +use installer::systemactions; + +################################################################# +# Changing the name for files with flag RENAME_TO_LANGUAGE +################################################################# + +sub put_language_into_name +{ + my ( $oldname, $onelanguage ) = @_; + + my $newname = ""; + + my $filename = ""; + my $extension = ""; + + if ( $oldname =~ /^\s*(.*)(\..*?)\s*$/ ) # files with extension + { + $filename = $1; + $extension = $2; + } + else + { + $filename = $oldname; + $extension = ""; + } + + $newname = $1 . "_" . $onelanguage . $2; + + return $newname; +} + +################################################################# +# Converting patchfiles string into array +################################################################# + +sub get_patch_file_list +{ + my ( $patchfilestring ) = @_; + + $patchfilestring =~ s/^\s*\(?//; + $patchfilestring =~ s/\)?\s*$//; + $patchfilestring =~ s/^\s*\///; + $patchfilestring =~ s/^\s*\\//; + + my $patchfilesarray = installer::converter::convert_stringlist_into_array_without_linebreak_and_quotes(\$patchfilestring, ","); + + return $patchfilesarray; +} + +################################################################# +# Analyzing files with flag ARCHIVE +################################################################# + +sub resolving_archive_flag +{ + my ($filesarrayref, $additionalpathsref, $languagestringref, $loggingdir) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::archivefiles::resolving_archive_flag : $#{$filesarrayref} : $#{$additionalpathsref} : $$languagestringref : $loggingdir"); } + + my @newallfilesarray = (); + + my ($systemcall, $returnvalue, $infoline); + + my $unziplistfile = $loggingdir . "unziplist_" . $installer::globals::build . "_" . $installer::globals::compiler . "_" . $$languagestringref . ".txt"; + + my $platformunzipdirbase = installer::systemactions::create_directories("zip", $languagestringref); + push(@installer::globals::removedirs, $platformunzipdirbase); + + installer::logger::include_header_into_logfile("Files with flag ARCHIVE:"); + + my $repeat_unzip = 0; + my $maxcounter = 0; + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + if ( $repeat_unzip ) { $i--; } # decreasing the counter + + my $onefile = ${$filesarrayref}[$i]; + my $styles = ""; + + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } + + if ( $styles =~ /\bARCHIVE\b/ ) # copying, unzipping and changing the file list + { + my $iscommonfile = 0; + my $sourcepath = $onefile->{'sourcepath'}; + + if ( $sourcepath =~ /\Q$installer::globals::separator\E\bcommon$installer::globals::productextension\Q$installer::globals::separator\E/ ) # /common/ or /common.pro/ + { + $iscommonfile = 1; + } + + my $use_internal_rights = 0; + if ( $styles =~ /\bUSE_INTERNAL_RIGHTS\b/ ) { $use_internal_rights = 1; } # using the rights used inside the zip file + + my $rename_to_language = 0; + if ( $styles =~ /\bRENAME_TO_LANGUAGE\b/ ) { $rename_to_language = 1; } # special handling for renamed files (scriptitems.pm) + + # mechanism to select files from an archive files + my $select_files = 0; + my $selectlistfiles = ""; + my @keptfiles = (); + if ( $onefile->{'Selectfiles'} ) + { + $select_files = 1; + $selectlistfiles = get_patch_file_list( $onefile->{'Selectfiles'} ); + $infoline = "Selected file list defined at file: $onefile->{'Name'} :\n"; + push( @installer::globals::logfileinfo, $infoline); + for ( my $k = 0; $k <= $#{$selectlistfiles}; $k++ ) + { + $infoline = "\"${$selectlistfiles}[$k]\"\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + + if ( $onefile->{'Selectfiles'} ) { $onefile->{'Selectfiles'} = ""; } # Selected files list no longer required + + # mechanism to define patch files inside an archive files + my $select_patch_files = 0; + my $patchlistfiles = ""; + my @keptpatchflags = (); + if (( $styles =~ /\bPATCH\b/ ) && ( $onefile->{'Patchfiles'} ) && ( $installer::globals::patch )) + { + $select_patch_files = 1; # special handling if a Patchlist is defined + $patchlistfiles = get_patch_file_list( $onefile->{'Patchfiles'} ); + $infoline = "Patch file list defined at file: $onefile->{'Name'} :\n"; + push( @installer::globals::logfileinfo, $infoline); + for ( my $k = 0; $k <= $#{$patchlistfiles}; $k++ ) + { + $infoline = "\"${$patchlistfiles}[$k]\"\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + + if ( $onefile->{'Patchfiles'} ) { $onefile->{'Patchfiles'} = ""; } # Patch file list no longer required + + # creating directories + + my $onelanguage = $onefile->{'specificlanguage'}; + + # files without language into directory "00" + + if ($onelanguage eq "") { $onelanguage = "00"; } + + my $unzipdir; + + # if ($iscommonfile) { $unzipdir = $commonunzipdirbase . $installer::globals::separator . $onelanguage . $installer::globals::separator; } + # else { $unzipdir = $platformunzipdirbase . $installer::globals::separator . $onelanguage . $installer::globals::separator; } + + $unzipdir = $platformunzipdirbase . $installer::globals::separator . $onelanguage . $installer::globals::separator; + + installer::systemactions::create_directory($unzipdir); # creating language specific subdirectories + + my $onefilename = $onefile->{'Name'}; + $onefilename =~ s/\./\_/g; # creating new directory name + $onefilename =~ s/\//\_/g; # only because of /letter/fontunxpsprint.zip, the only zip file with path + $unzipdir = $unzipdir . $onefilename . $installer::globals::separator; + + if ( $installer::globals::dounzip ) { installer::systemactions::create_directory($unzipdir); } # creating subdirectories with the names of the zipfiles + + $systemcall = "$installer::globals::unzippath -l $sourcepath |"; + open (UNZIP, "$systemcall"); + my @zipfile = <UNZIP>; + close (UNZIP); + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if (!( $#zipfile > -1 )) # the zipfile is empty + { + $infoline = "ERROR: Could not unzip $sourcepath\n"; + push( @installer::globals::logfileinfo, $infoline); + + } + else + { + # now really unpacking the files + # Parameter -o : overwrite files without prompting + # Parameter -q : quiet mode + + if ( $installer::globals::dounzip ) # really unpacking the files + { + $returnvalue = 1; + $systemcall = "$installer::globals::unzippath -o -q $sourcepath -d $unzipdir"; + $returnvalue = system($systemcall); + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) { installer::exiter::exit_program("ERROR: $infoline", "resolving_archive_flag"); } + + if ( $^O =~ /cygwin/i ) + { + # Make dll's executable + $systemcall = "cd $unzipdir; find . -name \\*.dll -exec chmod 775 \{\} \\\;"; + $returnvalue = system($systemcall); + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + + if ( ! $installer::globals::iswindowsbuild ) + { + # Setting unix rights to "775" for all created directories inside the package + + $systemcall = "cd $unzipdir; find . -type d -exec chmod 775 \{\} \\\;"; + $returnvalue = system($systemcall); + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + } + + my $zipfileref = \@zipfile; + my $unziperror = 0; + + # Format: Length, Date, Time, Name + # This includes new destination directories! + + for ( my $j = 0; $j <= $#{$zipfileref}; $j++ ) + { + my $line = ${$zipfileref}[$j]; + + # Format: + # 0 07-25-03 18:21 dir1/ + # 1241 07-25-03 18:21 dir1/so7drawing.desktop + + if ( $line =~ /^\s*(\d+)\s+(\S+)\s+(\S+)\s+(\S+.*\S+?)\s*$/ ) + { + my $zipsize = $1; + my $zipdate = $2; + my $ziptime = $3; + my $zipname = $4; + + # some directories and files (from the help) start with "./simpress.idx" + + $zipname =~ s/^\s*\.\///; + + if ($installer::globals::iswin and $^O =~ /MSWin/i) { $zipname =~ s/\//\\/g; } + + # if ( $zipsize == 0 ) # also files can have a size of 0 + if ( $zipname =~ /\Q$installer::globals::separator\E\s*$/ ) # slash or backslash at the end characterizes a directory + { + $zipname = $zipname . "\n"; + push(@{$additionalpathsref}, $zipname); + + # Also needed here: + # Name + # Language + # ismultilingual + # Basedirectory + + # This is not needed, because the list of all directories for the + # epm list file is generated from the destination directories of the + # files included in the product! + } + else + { + my %newfile = (); + %newfile = %{$onefile}; + $newfile{'Name'} = $zipname; + my $destination = $onefile->{'destination'}; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$destination); + $newfile{'destination'} = $destination . $zipname; + $newfile{'sourcepath'} = $unzipdir . $zipname; + $newfile{'zipfilename'} = $onefile->{'Name'}; + $newfile{'zipfilesource'} = $onefile->{'sourcepath'}; + $newfile{'zipfiledestination'} = $onefile->{'destination'}; + + if (( $use_internal_rights ) && ( ! $installer::globals::iswin )) + { + my $value = sprintf("%o", (stat($newfile{'sourcepath'}))[2]); + $newfile{'UnixRights'} = substr($value, 3); + $infoline = "Setting unix rights for \"$newfile{'sourcepath'}\" to \"$newfile{'UnixRights'}\"\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + if ( $select_files ) + { + if ( ! installer::existence::exists_in_array($zipname,$selectlistfiles) ) + { + $infoline = "Removing from ARCHIVE file $onefilename: $zipname\n"; + push( @installer::globals::logfileinfo, $infoline); + next; # ignoring files, that are not included in $selectlistfiles + } + else + { + $infoline = "Keeping from ARCHIVE file $onefilename: $zipname\n"; + push( @installer::globals::logfileinfo, $infoline); + push( @keptfiles, $zipname); # collecting all kept files + } + } + + if ( $select_patch_files ) + { + # Is this file listed in the Patchfile list? + # $zipname (filename including path in zip file has to be listed in patchfile list + + if ( ! installer::existence::exists_in_array($zipname,$patchlistfiles) ) + { + $newfile{'Styles'} =~ s/\bPATCH\b//; # removing the flag PATCH + $newfile{'Styles'} =~ s/\,\s*\,/\,/; + $newfile{'Styles'} =~ s/\(\s*\,/\(/; + $newfile{'Styles'} =~ s/\,\s*\)/\)/; + # $infoline = "Removing PATCH flag from: $zipname\n"; + # push( @installer::globals::logfileinfo, $infoline); + } + else + { + # $infoline = "Keeping PATCH flag at: $zipname\n"; + # push( @installer::globals::logfileinfo, $infoline); + push( @keptpatchflags, $zipname); # collecting all PATCH flags + } + } + + if ( $rename_to_language ) + { + my $newzipname = put_language_into_name($zipname, $onelanguage); + my $oldfilename = $unzipdir . $zipname; + my $newfilename = $unzipdir . $newzipname; + + installer::systemactions::copy_one_file($oldfilename, $newfilename); + + $newfile{'Name'} = $newzipname; + $newfile{'destination'} = $destination . $newzipname; + $newfile{'sourcepath'} = $unzipdir . $newzipname; + + $infoline = "RENAME_TO_LANGUAGE: Using $newzipname instead of $zipname!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + my $sourcefiletest = $unzipdir . $zipname; + if ( ! -f $sourcefiletest ) + { + $infoline = "ATTENTION: Unzip failed for $sourcefiletest!\n"; + push( @installer::globals::logfileinfo, $infoline); + $unziperror = 1; + } + + # only adding the new line into the files array, if not in repeat modus + + if ( ! $repeat_unzip ) { push(@newallfilesarray, \%newfile); } + } + } + } + + # Comparing the content of @keptfiles and $selectlistfiles + # Do all files from the list of selected files are stored in @keptfiles ? + # @keptfiles contains only files included in $selectlistfiles. But are all + # files from $selectlistfiles included in @keptfiles? + + if ( $select_files ) + { + my $number = $#{$selectlistfiles} + 1; + $infoline = "SELECTLIST: Number of files in file selection list: $number\n"; + push( @installer::globals::logfileinfo, $infoline); + $number = $#keptfiles + 1; + $infoline = "SELECTLIST: Number of kept files: $number\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $k = 0; $k <= $#keptfiles; $k++ ) + { + $infoline = "KEPT FILES: $keptfiles[$k]\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + my @warningfiles = (); + + for ( my $k = 0; $k <= $#{$selectlistfiles}; $k++ ) + { + if ( ! installer::existence::exists_in_array(${$selectlistfiles}[$k],\@keptfiles) ) + { + push(@warningfiles, ${$selectlistfiles}[$k]); + } + } + + for ( my $k = 0; $k <= $#warningfiles; $k++ ) + { + $infoline = "WARNING: $warningfiles[$k] not included in install set (does not exist in zip file)!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + } + + # Comparing the content of @keptpatchflags and $patchlistfiles + # Do all files from the patch list have a PATCH flag ? + # @keptpatchflags contains only files included in $patchlistfiles. But are all + # files from $patchlistfiles included in @keptpatchflags? + + if ( $select_patch_files ) + { + my $number = $#{$patchlistfiles} + 1; + $infoline = "PATCHLIST: Number of files in patch list: $number\n"; + push( @installer::globals::logfileinfo, $infoline); + $number = $#keptpatchflags + 1; + $infoline = "PATCHLIST: Number of kept PATCH flags: $number\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $k = 0; $k <= $#keptpatchflags; $k++ ) + { + $infoline = "KEPT PATCH FLAGS: $keptpatchflags[$k]\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + my @warningfiles = (); + + for ( my $k = 0; $k <= $#{$patchlistfiles}; $k++ ) + { + if ( ! installer::existence::exists_in_array(${$patchlistfiles}[$k],\@keptpatchflags) ) + { + push(@warningfiles, ${$patchlistfiles}[$k]); + } + } + + for ( my $k = 0; $k <= $#warningfiles; $k++ ) + { + $infoline = "WARNING: $warningfiles[$k] did not keep PATCH flag (does not exist in zip file)!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + + if ( $unziperror ) + { + installer::logger::print_warning( "Repeating to unpack $sourcepath! \n" ); + $infoline = "ATTENTION: Repeating to unpack $sourcepath !\n"; + push( @installer::globals::logfileinfo, $infoline); + $repeat_unzip = 1; + $maxcounter++; + + if ( $maxcounter == 5 ) # exiting the program + { + installer::exiter::exit_program("ERROR: Failed to unzip $sourcepath !", "resolving_archive_flag"); + } + } + else + { + $infoline = "Info: $sourcepath unpacked without problems !\n"; + push( @installer::globals::logfileinfo, $infoline); + $repeat_unzip = 0; + $maxcounter = 0; + } + } + } + else # nothing to do here, no zipped file (no ARCHIVE flag) + { + push(@newallfilesarray, $onefile); + } + } + + $infoline = "\n"; + push( @installer::globals::logfileinfo, $infoline); + + return \@newallfilesarray; +} + + +1; diff --git a/solenv/bin/modules/installer/configuration.pm b/solenv/bin/modules/installer/configuration.pm new file mode 100644 index 000000000000..ed6a5b4b2707 --- /dev/null +++ b/solenv/bin/modules/installer/configuration.pm @@ -0,0 +1,905 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: configuration.pm,v $ +# +# $Revision: 1.7 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::configuration; + +use Cwd; +use installer::converter; +use installer::existence; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::logger; +use installer::remover; +use installer::systemactions; + +################################################################################ +# Getting package from configurationitem (for instance: org.openoffice.Office) +# Getting name from configurationitem (for instance: Common) +################################################################################ + +sub analyze_path_of_configurationitem +{ + my ($configurationitemsref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::configuration::analyze_path_of_configurationitem : $#{$configurationitemsref}"); } + + my ($startpath, $nodes, $name, $packagename, $onenode, $first, $second, $third, $bracketnode); + + for ( my $i = 0; $i <= $#{$configurationitemsref}; $i++ ) + { + my $oneconfig = ${$configurationitemsref}[$i]; + my $path = $oneconfig->{'Path'}; + + installer::remover::remove_leading_and_ending_slashes(\$path); # in scp are some path beginning with "/" + + if ( $path =~ /^\s*(.*?)\/(.*)\s*$/ ) + { + $startpath = $1; + $nodes = $2; + } + else + { + installer::exiter::exit_program("ERROR: Unknown format of ConfigurationItem path: $path", "analyze_path_of_configurationitem"); + } + + # Startpath is now: org.openoffice.Setup + # Nodes is now: Office/Factories/com.sun.star.chart.ChartDocument + + # Dividing the startpath into package (org.openoffic) and name (Setup). + + $oneconfig->{'startpath'} = $startpath; # saving the startpath into the hash + + if ( $startpath =~ /^\s*(\S*)\.(\S*?)\s*$/ ) + { + $packagename = $1; + $name = $2; + $oneconfig->{'name'} = $name; + $oneconfig->{'packagename'} = $packagename; + } + else + { + installer::exiter::exit_program("ERROR: Unknown format of ConfigurationItem startpath: $startpath", "analyze_path_of_configurationitem"); + } + + # Collecting all nodes + + installer::remover::remove_leading_and_ending_slashes(\$nodes); + + my $counter = 1; + + # Attention: Do not trust the slash + # Filters/Filter['StarWriter 5.0 Vorlage/Template'] + # Menus/New/*['m10']/Title + + if ( $nodes =~ /^(.*\[\')(.*\/.*)(\'\].*)$/ ) + { + $first = $1; + $second = $2; + $third = $3; + + $second =~ s/\//SUBSTITUTEDSLASH/g; # substituting "/" to "SUBSTITUTEDSLASH" + $nodes = $first . $second . $third; + } + + while ( $nodes =~ /\// ) + { + if ($nodes =~ /^\s*(.*?)\/(.*)\s*$/ ) + { + $onenode = $1; + $nodes = $2; + $nodename = "node". $counter; + + # Special handling for filters. Difference between: + # Filter['StarWriter 5.0 Vorlage/Template'] without oor:op="replace" + # *['m10'] with oor:op="replace" + + if ( $onenode =~ /^\s*Filter\[\'(.*)\'\].*$/ ) { $oneconfig->{'isfilter'} = 1; } + + # Changing the nodes with brackets: + # Filter['StarWriter 5.0 Vorlage/Template'] + # *['m10'] + + if ( $onenode =~ /^.*\[\'(.*)\'\].*$/ ) + { + $onenode = $1; + $bracketnode = "bracket_" . $nodename; + $oneconfig->{$bracketnode} = 1; + } + + $onenode =~ s/SUBSTITUTEDSLASH/\//g; # substituting "SUBSTITUTEDSLASH" to "/" + $oneconfig->{$nodename} = $onenode; + + # special handling for nodes "Factories" + + if ( $onenode eq "Factories" ) { $oneconfig->{'factoriesnode'} = $counter; } + else { $oneconfig->{'factoriesnode'} = -99; } + } + + $counter++ + } + + # and the final node + + if ( $nodes =~ /^\s*Filter\[\'(.*)\'\].*$/ ) { $oneconfig->{'isfilter'} = 1; } + + $nodename = "node". $counter; + + if ( $nodes =~ /^.*\[\'(.*)\'\].*$/ ) + { + $nodes = $1; + $bracketnode = "bracket_" . $nodename; + $oneconfig->{$bracketnode} = 1; + } + + $nodes =~ s/SUBSTITUTEDSLASH/\//g; # substituting "SUBSTITUTEDSLASH" to "/" + + if (($nodes eq "Name") || ($nodes eq "Title")) # isocodes below "Name" or "Title" + { + # if the last node $nodes is "Name" or "Title", it is a Property, not a name! See Common.xcu + + $oneconfig->{'isisocode'} = 1; + + if ( $nodes eq "Name" ) { $oneconfig->{'isname'} = 1; } + if ( $nodes eq "Title" ) { $oneconfig->{'istitle'} = 1; } + $counter--; # decreasing the counter, because "Name" and "Title" are no nodes + } + else + { + $oneconfig->{$nodename} = $nodes; + $oneconfig->{'isisocode'} = 0; + } + + # special handling for nodes "Factories" + + if ( $onenode eq "Factories" ) { $oneconfig->{'factoriesnode'} = $counter; } + else { $oneconfig->{'factoriesnode'} = -99; } + + # saving the number of nodes + + $oneconfig->{'nodenumber'} = $counter; + } +} + +#################################################################### +# Inserting the start block into a configuration file +#################################################################### + +sub insert_start_block_into_configfile +{ + my ($configfileref, $oneconfig) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::configuration::insert_start_block_into_configfile : $#{$configfileref} : $oneconfig->{'name'}"); } + + my $line = '<?xml version="1.0" encoding="UTF-8"?>' . "\n"; + push( @{$configfileref}, $line); + + $line = '<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:install="http://openoffice.org/2004/installation" oor:name="FILENAME" oor:package="PACKAGENAME">' . "\n"; + my $packagename = $oneconfig->{'packagename'}; + my $name = $oneconfig->{'name'}; + $line =~ s/PACKAGENAME/$packagename/g; + $line =~ s/FILENAME/$name/g; + push( @{$configfileref}, $line); + + $line = "\n"; + push( @{$configfileref}, $line); +} + +#################################################################### +# Inserting the end block into a configuration file +#################################################################### + +sub insert_end_block_into_configfile +{ + my ($configfileref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::configuration::insert_end_block_into_configfile : $#{$configfileref}"); } + + my $line = "\n" . '</oor:component-data>' . "\n"; + push( @{$configfileref}, $line); +} + +############################################################## +# Getting the content of a node +############################################################## + +sub get_node_content +{ + my ($nodeline) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::configuration::get_node_content : $nodeline"); } + + my $content = ""; + + if ( $nodeline =~ /name\=\"(.*?)\"/ ) + { + $content = $1; + } + else + { + installer::exiter::exit_program("ERROR: Impossible error in function get_node_content!", "get_node_content"); + } + + return \$content; +} + +############################################################## +# Getting the line number of an existing node +# Return "-1" if node does not exist +############################################################## + +sub get_node_line_number +{ + my ($nodecount, $oneconfig, $oneconfigfileref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::configuration::get_node_line_number : $nodecount : $oneconfig->{'name'} : $#{$oneconfigfileref}"); } + + my $linenumber = -1; # the node does not exists, if returnvalue is "-1" + + # Attention: Take care of the two title nodes: + # Path=org.openoffice.Office.Common/Menus/Wizard/*['m14']/Title + # Path=org.openoffice.Office.Common/Menus/Wizard/*['m15']/Title + # -> every subnode has to be identical + + # creating the allnodes string from $oneconfig + + my $allnodes = ""; + + for ( my $i = 1; $i <= $nodecount; $i++ ) + { + my $nodename = "node" . $i; + $allnodes .= $oneconfig->{$nodename} . "/"; + } + + installer::remover::remove_leading_and_ending_slashes(\$allnodes); # exactly this string has to be found in the following iteration + + # Iterating over the already built configuration file + + my @allnodes = (); + + for ( my $i = 0; $i <= $#{$oneconfigfileref}; $i++ ) + { + my $line = ${$oneconfigfileref}[$i]; + installer::remover::remove_leading_and_ending_whitespaces(\$line); + my $nodechanged = 0; + + if ( $line =~ /^\s*\<node/ ) # opening node + { + $nodechanged = 1; + my $nodecontentref = get_node_content($line); + push(@allnodes, $$nodecontentref); # collecting all nodes in an array + } + + if ( $line =~ /^\s*\<\/node/ ) # ending node + { + $nodechanged = 1; + pop(@allnodes); # removing the last node from the array + } + + if (( $nodechanged ) && ($#allnodes > -1)) # a node was found and the node array is not empty + { + # creating the string to compare with the string $allnodes + + my $nodestring = ""; + + for ( my $j = 0; $j <= $#allnodes; $j++ ) + { + $nodestring .= $allnodes[$j] . "/"; + } + + installer::remover::remove_leading_and_ending_slashes(\$nodestring); + + if ( $nodestring eq $allnodes ) + { + # that is exactly the same node + + $linenumber = $i; + $linenumber++; # increasing the linenumber + last; + + } + } + } + + return $linenumber; +} + +############################################################## +# Inserting one configurationitem into the configurationfile +############################################################## + +sub insert_into_config_file +{ + my ($oneconfig, $oneconfigfileref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::configuration::insert_into_config_file : $oneconfig->{'nodenumber'} : $#{$oneconfigfileref}"); } + + my ($nodename, $nodecontent, $newnodeline, $bracketkey, $line, $insertline); + + # interpreting the nodes, keys and values + + my $nodeline = '<node oor:name="NODECONTENT" REPLACEPART >' . "\n"; + my $propline = '<prop oor:name="KEYCONTENT" REPLACEPART TYPEPART>' . "\n"; + my $valueline = '<value SEPARATORPART>VALUECONTENT</value>' . "\n"; + my $langvalueline = '<value xml:lang="SAVEDLANGUAGE">VALUECONTENT</value>' . "\n"; + my $propendline = '</prop>' . "\n"; + my $nodeendline = '</node>' . "\n"; + + my $replacepart = 'oor:op="replace"'; + my $typepart = 'oor:type="xs:VALUETYPE"'; # VALUETYPE can be "string", "boolean", ... + + my $nodecount = $oneconfig->{'nodenumber'}; + my $styles = $oneconfig->{'Styles'}; + + for ( my $i = 1; $i <= $nodecount; $i++ ) + { + $insertline = get_node_line_number($i, $oneconfig, $oneconfigfileref); + + if ( $insertline == -1) # if true, the node does not exist + { + $nodename = "node" . $i; + $nodecontent = $oneconfig->{$nodename}; + $newnodeline = $nodeline; + + $newnodeline =~ s/NODECONTENT/$nodecontent/g; + + # Case1: + # Nodes with brackets, need the replacepart 'oor:op="replace"' + # Bracket node is set for each node with: bracket_node1=1, bracket_node2=1, ... + # Case a: <node oor:name="m0" oor:op="replace"> (Common.xcu needs oor:op="replace") + # Case b: <node oor:name="Ami Pro 1.x-3.1 (W4W)"> (TypeDetection.xcu does not need oor:op="replace") + # For case b introducting a special case for Filters + + $bracketkey = "bracket_" . $nodename; + + my $localbracketkey = 0; + + if ( $oneconfig->{$bracketkey} ) { $localbracketkey = $oneconfig->{$bracketkey}; } + + if ( $localbracketkey == 1 ) # 'oor:op="replace"' is needed + { + my $isfilter = 0; + if ( $oneconfig->{'isfilter'} ) { $isfilter = $oneconfig->{'isfilter'}; } + + if ( $isfilter == 1 ) # this is a filter + { + $newnodeline =~ s/REPLACEPART//; + } + else + { + $newnodeline =~ s/REPLACEPART/$replacepart/; + } + + $newnodeline =~ s/\s*\>/\>/; # removing resulting whitespaces + } + + # Case2: + # Nodes below a Node "Factories", also need the replacepart 'oor:op="replace"' + # This is saved in $oneconfig->{'factoriesnode'}. If not set, the value is "-99" + + if ( $i == $oneconfig->{'factoriesnode'} ) + { + $newnodeline =~ s/REPLACEPART/$replacepart/; + $newnodeline =~ s/\s*\>/\>/; # removing resulting whitespaces + } + + # Case3: + # In all other cases, REPLACEPART in nodes can be removed + + $newnodeline =~ s/REPLACEPART//; + $newnodeline =~ s/\s*\>/\>/; # removing resulting whitespaces + + # Finding the correct place for inserting the node + + if ( $i == 1 ) # this is a toplevel node + { + push(@{$oneconfigfileref}, $newnodeline); + push(@{$oneconfigfileref}, $nodeendline); + } + else + { + # searching for the parent node + + my $parentnumber = $i-1; + $insertline = get_node_line_number($parentnumber, $oneconfig, $oneconfigfileref); + splice(@{$oneconfigfileref}, $insertline, 0, ($newnodeline, $nodeendline)); + } + } + } + + # Setting variables $isbracketnode and $isfactorynode for the properties + + + my $isbracketnode = 0; + my $isfactorynode = 0; + + for ( my $i = 1; $i <= $nodecount; $i++ ) + { + $nodename = "node" . $i; + $bracketkey = "bracket_" . $nodename; + + my $localbracketkey = 0; + if ( $oneconfig->{$bracketkey} ) { $localbracketkey = $oneconfig->{$bracketkey}; } + + if ( $localbracketkey == 1 ) { $isbracketnode = 1; } + if ( $i == $oneconfig->{'factoriesnode'} ) { $isfactorynode = 1; } + } + + # now all nodes exist, and the key and value can be inserted into the configfile + # the next line contains the key, for instance: <prop oor:name="UseDefaultMailer" oor:type="xs:boolean"> + # my $propline = '<prop oor:name="KEYCONTENT" REPLACEPART TYPEPART>' . "\n"; + # The type is only needed, if a replace is set. + + my $newpropline = $propline; + + # Replacement of KEYCONTENT, REPLACEPART and TYPEPART + + # Case 1: + # Properties with oor:name="Name" (Common.xcu) are simply <prop oor:name="Name"> + # The information about such a property is stored in $oneconfig->{'isisocode'} + + if ( $oneconfig->{'isisocode'} ) + { + if ( $oneconfig->{'isname'} ) { $newpropline =~ s/KEYCONTENT/Name/; } # The property name is always "Name" + if ( $oneconfig->{'istitle'} ) { $newpropline =~ s/KEYCONTENT/Title/; } # The property name is always "Title" + $newpropline =~ s/REPLACEPART//; + $newpropline =~ s/TYPEPART//; + $newpropline =~ s/\s*\>/\>/; # removing resulting whitespaces + } + + # Begin of all other cases + + my $key = $oneconfig->{'Key'}; + $newpropline =~ s/KEYCONTENT/$key/; + + my $valuetype; + + if ( $styles =~ /CFG_STRING\b/ ) { $valuetype = "string"; } + elsif ( $styles =~ /CFG_NUMERIC/ ) { $valuetype = "int"; } + elsif ( $styles =~ /CFG_BOOLEAN/ ) { $valuetype = "boolean"; } + elsif ( $styles =~ /CFG_STRINGLIST/ ) { $valuetype = "string-list"; } +# elsif ( $styles =~ /CFG_STRINGLIST/ ) { $valuetype = "string-list oor:separator=\"\|\""; } + else + { + installer::exiter::exit_program("ERROR: Unknown configuration value type: $styles", "insert_into_config_file"); + } + + # Case 2: + # Properties below a node "Factories" do not need a 'oor:op="replace"' and a 'oor:type="xs:VALUETYPE"' + + if ( $isfactorynode ) + { + $newpropline =~ s/REPLACEPART//; + $newpropline =~ s/TYPEPART//; + $newpropline =~ s/\s*\>/\>/; # removing resulting whitespaces + } + + # Case 3: + # Properties below a "bracket" node do not need a 'oor:op="replace"', except they are iso-codes + # Assumption here: They are multilingual + + if ( $isbracketnode ) + { + my $localtypepart = $typepart; + $localtypepart =~ s/VALUETYPE/$valuetype/; + $newpropline =~ s/TYPEPART/$localtypepart/; + + if ( $oneconfig->{'ismultilingual'} ) # This is solved by "Name" and "Title" + { + $newpropline =~ s/REPLACEPART/$replacepart/; + } + else + { + $newpropline =~ s/REPLACEPART//; + } + + $newpropline =~ s/\s*\>/\>/; # removing resulting whitespaces + } + + # Case 4: + # if the flag CREATE is set, the properties get 'oor:op="replace"' and 'oor:type="xs:VALUETYPE"' + + if (( $styles =~ /\bCREATE\b/ ) && (!($isbracketnode))) + { + # my $typepart = 'oor:type="xs:VALUETYPE"'; # VALUETYPE can be "string", "boolean", ... + + my $localtypepart = $typepart; + $localtypepart =~ s/VALUETYPE/$valuetype/; + + $newpropline =~ s/TYPEPART/$localtypepart/; + $newpropline =~ s/REPLACEPART/$replacepart/; + $newpropline =~ s/\s*\>/\>/; # removing resulting whitespaces + } + + # Case 5: + # all other ConfigurationItems do not need 'oor:op="replace"' and 'oor:type="xs:VALUETYPE"' + + $newpropline =~ s/REPLACEPART//; + $newpropline =~ s/TYPEPART//; + $newpropline =~ s/\s*\>/\>/; # removing resulting whitespaces + + # finally the value can be set + + my $value = $oneconfig->{'Value'}; + + # Some values in setup script are written during installation process by the setup. These + # have values like "<title>". This will lead to an error, because of the brackets. Therefore the + # brackets have to be removed. + + # ToDo: Substituting the setup replace variables + + # replace_setting_variables(); + + $value =~ s/^\s*\<//; + $value =~ s/\>\s*$//; + + # Deal with list separators + my $separatorpart = ''; + if ( ($valuetype eq "string-list") && ($value =~ /\|/) ) + { + $separatorpart = 'oor:separator="|"'; + } + + # Fake: substituting german umlauts + + $value =~ s/\ä/ae/; + $value =~ s/\ö/oe/; + $value =~ s/\ü/ue/; + $value =~ s/\Ä/AE/; + $value =~ s/\Ö/OE/; + $value =~ s/\Ü/UE/; + + my $newvalueline; + + if (!($oneconfig->{'isisocode'} )) # this is the simpe case + { + # my $valueline = '<value SEPARATORPART>VALUECONTENT</value>' . "\n"; + $newvalueline = $valueline; + $newvalueline =~ s/VALUECONTENT/$value/g; + $newvalueline =~ s/SEPARATORPART/$separatorpart/; + } + else + { + # my $langvalueline = '<value xml:lang="SAVEDLANGUAGE">VALUECONTENT</value>' . "\n"; + $newvalueline = $langvalueline; + $newvalueline =~ s/VALUECONTENT/$value/; + my $savedlanguage = $oneconfig->{'Key'}; + $newvalueline =~ s/SAVEDLANGUAGE/$savedlanguage/; + } + + # For language dependent values, it is possible, that the property already exist. + # In this case the prop must not be created again and only the value has to be included: + # <prop oor:name="Name"> + # <value xml:lang="de">OpenOffice.org 2.0 Diagramm</value> + # <value xml:lang="en-US">OpenOffice.org 2.0 Chart</value> + # </prop> + + # The key has to be written after the line, containing the complete node + + $insertline = get_node_line_number($nodecount, $oneconfig, $oneconfigfileref); + + if ( $oneconfig->{'ismultilingual'} ) + { + if ( $newpropline eq ${$oneconfigfileref}[$insertline] ) + { + if (!($newvalueline eq ${$oneconfigfileref}[$insertline+1])) # only include, if the value not already exists (example: value="FALSE" for many languages) + { + splice(@{$oneconfigfileref}, $insertline+1, 0, ($newvalueline)); # only the value needs to be added + } + } + else + { + splice(@{$oneconfigfileref}, $insertline, 0, ($newpropline, $newvalueline, $propendline)); + } + } + else + { + splice(@{$oneconfigfileref}, $insertline, 0, ($newpropline, $newvalueline, $propendline)); + } + + return $oneconfigfileref; +} + +########################################################## +# Inserting tabs for better view into configuration file +########################################################## + +sub insert_tabs_into_configfile +{ + my ($configfileref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::configuration::insert_tabs_into_configfile : $#{$configfileref}"); } + + my $counter = 0; + + for ( my $i = 0; $i <= $#{$configfileref}; $i++ ) + { + my $line = ${$configfileref}[$i]; + my $linebefore = ${$configfileref}[$i-1]; + + if (( $line =~ /^\s*\<node/ ) || ( $line =~ /^\s*\<prop/ )) + { + if ((!( $linebefore =~ /^\s*\<\/node/ )) && (!( $linebefore =~ /^\s*\<\/prop/ ))) # do not increase after "</node" and after "</prop" + { + $counter++; + } + } + + if ( $line =~ /^\s*\<value/ ) + { + if (!($linebefore =~ /^\s*\<value/ )) # do not increase counter with "<value>" after "<value>" (multilingual configitems) + { + $counter++; + } + } + + if (( $line =~ /^\s*\<\/node\>/ ) || ( $line =~ /^\s*\<\/prop\>/ )) + { + if ((!( $linebefore =~ /^\s*\<node/ )) && (!( $linebefore =~ /^\s*\<prop/ ))) # do not decrease after "<node" and after "<prop" + { + $counter--; + } + } + + if ($counter > 0) + { + for ( my $j = 0; $j < $counter; $j++ ) + { + $line = "\t" . $line; + } + } + + ${$configfileref}[$i] = $line; + } +} + +###################################################################### +# Collecting all different configuration items (Files and Modules) +###################################################################### + +sub collect_all_configuration_items +{ + my ($configurationitemsref, $item) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::configuration::collect_all_configuration_items : $#{$configurationitemsref} : $item"); } + + my @allitems = (); + + for ( my $i = 0; $i <= $#{$configurationitemsref}; $i++ ) + { + my $oneconfig = ${$configurationitemsref}[$i]; + + if (! installer::existence::exists_in_array($oneconfig->{$item}, \@allitems)) + { + push(@allitems, $oneconfig->{$item}); + } + } + + return \@allitems; +} + +###################################################################### +# Collecting all module specific configuration items +###################################################################### + +sub get_all_configitems_at_module +{ + my ($moduleid, $configurationitemsref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::configuration::get_all_configitems_at_module : $moduleid : $#{$configurationitemsref}"); } + + my @moduleconfigurationitems = (); + + for ( my $i = 0; $i <= $#{$configurationitemsref}; $i++ ) + { + my $oneconfig = ${$configurationitemsref}[$i]; + + if ( $oneconfig->{'ModuleID'} eq $moduleid ) + { + push(@moduleconfigurationitems, $oneconfig); + } + } + + return \@moduleconfigurationitems; +} + +####################################################### +# Saving and zipping the created configurationfile +####################################################### + +sub save_and_zip_configfile +{ + my ($oneconfigfileref, $onefile, $onemodule, $configdir) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::configuration::save_and_zip_configfile : $#{$oneconfigfileref} : $onefile : $onemodule : $configdir"); } + + my $savefilename = $onefile; + $savefilename =~ s/\./\_/g; + $savefilename = $savefilename . "_" . $onemodule; + $savefilename = $savefilename . ".xcu"; + my $shortsavefilename = $savefilename; + + $savefilename = $configdir . $installer::globals::separator . $savefilename; + + installer::files::save_file($savefilename, $oneconfigfileref); + + # zipping the configfile + + my $returnvalue = 1; + + my $zipfilename = $shortsavefilename; + $zipfilename =~ s/\.xcu/\.zip/; + + my $currentdir = cwd(); + if ( $installer::globals::iswin ) { $currentdir =~ s/\//\\/g; } + + chdir($configdir); + + my $systemcall = "$installer::globals::zippath -q -m $zipfilename $shortsavefilename"; + $returnvalue = system($systemcall); + + chdir($currentdir); + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not zip $savefilename to $zipfilename\n"; + } + else + { + $infoline = "SUCCESS: Zipped file $savefilename to $zipfilename\n"; + } + push( @installer::globals::logfileinfo, $infoline); + + return $zipfilename; +} + +##################################################################### +# Adding the newly created configuration file into the file list +##################################################################### + +sub add_zipfile_into_filelist +{ + my ($zipfilename, $configdir, $filesarrayref, $onemodule) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::configuration::add_zipfile_into_filelist: $zipfilename : $configdir : $#{$filesarrayref} : $onemodule"); } + + my $longzipfilename = $configdir . $installer::globals::separator . $zipfilename; + my $gid = "gid_" . $zipfilename; + $gid =~ s/\./\_/g; + + my %configfile = (); + + # Taking the base data from the "gid_File_Lib_Vcl" + + my $vclgid = "gid_File_Lib_Vcl"; + my $vclfile = installer::existence::get_specified_file($filesarrayref, $vclgid); + + # copying all base data + installer::converter::copy_item_object($vclfile, \%configfile); + + # and overriding all new data + $configfile{'ismultilingual'} = 0; + $configfile{'sourcepath'} = $longzipfilename; + $configfile{'Name'} = $zipfilename; + $configfile{'UnixRights'} = "644"; + $configfile{'gid'} = $gid; + $configfile{'Dir'} = "gid_Dir_Share_Uno_Packages"; + $configfile{'destination'} = "share" . $installer::globals::separator . "uno_packages" . $installer::globals::separator . $zipfilename; + $configfile{'modules'} = $onemodule; # assigning the file to the correct module! + + push(@{$filesarrayref}, \%configfile); +} + +####################################################### +# Creating configuration files from configurationitems +####################################################### + +sub create_configuration_files +{ + my ($configurationitemsref, $filesarrayref, $languagestringref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::configuration::create_configuration_files: $#{$configurationitemsref} : $#{$filesarrayref} : $$languagestringref"); } + + installer::logger::include_header_into_logfile("Creating configuration files:"); + + # creating the directory + + my $configdir = installer::systemactions::create_directories("configfiles", $languagestringref); + + $configdir = installer::converter::make_path_conform($configdir); + + # collecting an array of all modules + my $allmodules = collect_all_configuration_items($configurationitemsref, "ModuleID"); + + # iterating over all modules + + for ( my $i = 0; $i <= $#{$allmodules}; $i++ ) + { + my $onemodule = ${$allmodules}[$i]; + + my $moduleconfigitems = get_all_configitems_at_module($onemodule, $configurationitemsref); + + # collecting an array of all "startpath". This are all different files (org.openoffice.Office.Common). + my $allfiles = collect_all_configuration_items($moduleconfigitems, "startpath"); + + # iteration over all files + + for ( my $j = 0; $j <= $#{$allfiles}; $j++ ) + { + my $onefile = ${$allfiles}[$j]; + + my @oneconfigfile = (); + my $oneconfigfileref = \@oneconfigfile; + + my $startblockwritten = 0; + + for ( my $k = 0; $k <= $#{$moduleconfigitems}; $k++ ) + { + my $oneconfig = ${$moduleconfigitems}[$k]; + + my $startpath = $oneconfig->{'startpath'}; + + if ($startpath eq $onefile) + { + if (!($startblockwritten)) # writing some global lines into the xcu file + { + insert_start_block_into_configfile($oneconfigfileref, $oneconfig); + $startblockwritten = 1; + } + + $oneconfigfileref = insert_into_config_file($oneconfig, $oneconfigfileref); + } + } + + insert_end_block_into_configfile($oneconfigfileref); + + # inserting tabs for nice appearance + insert_tabs_into_configfile($oneconfigfileref); + + # saving the configfile + my $zipfilename = save_and_zip_configfile($oneconfigfileref, $onefile, $onemodule, $configdir); + + # adding the zipped configfile to the list of installed files + # Some data are set now, others are taken from the file "soffice.exe" ("soffice.bin") + + add_zipfile_into_filelist($zipfilename, $configdir, $filesarrayref, $onemodule); + } + } + + my $infoline = "\n"; + push( @installer::globals::logfileinfo, $infoline); + +} + +1; diff --git a/solenv/bin/modules/installer/control.pm b/solenv/bin/modules/installer/control.pm new file mode 100644 index 000000000000..0b03b9f0b86a --- /dev/null +++ b/solenv/bin/modules/installer/control.pm @@ -0,0 +1,722 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: control.pm,v $ +# +# $Revision: 1.42 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::control; + +use Cwd; +use installer::converter; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::pathanalyzer; +use installer::scriptitems; +use installer::systemactions; + +######################################################### +# Function that can be used for additional controls. +# Search happens in $installer::globals::patharray. +######################################################### + +sub check_needed_files_in_path +{ + my ( $filesref ) = @_; + + foreach $onefile ( @{$filesref} ) + { + installer::logger::print_message( "...... searching $onefile ..." ); + + my $fileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath_classic(\$onefile, $installer::globals::patharray , 0); + + if ( $$fileref eq "" ) + { + $error = 1; + installer::logger::print_error( "$onefile not found\n" ); + } + else + { + installer::logger::print_message( "\tFound: $$fileref\n" ); + } + } + + if ( $error ) + { + installer::exiter::exit_program("ERROR: Could not find all needed files in path!", "check_needed_files_in_path"); + } +} + +######################################################### +# Checking the local system +# Checking existence of needed files in include path +######################################################### + +sub check_system_path +{ + # The following files have to be found in the environment variable PATH + # All platforms: zip, unzip + # Windows only: msvcp70.dll, msvcr70.dll for regcomp.exe + # Windows only: "msiinfo.exe", "msidb.exe", "uuidgen.exe", "makecab.exe", "msitran.exe", "expand.exe" for msi database and packaging + + my $onefile; + my $error = 0; + my $pathvariable = $ENV{'PATH'}; + my $local_pathseparator = $installer::globals::pathseparator; + + if( $^O =~ /cygwin/i ) + { # When using cygwin's perl the PATH variable is POSIX style and ... + $pathvariable = qx{cygpath -mp "$pathvariable"} ; + # has to be converted to DOS style for further use. + $local_pathseparator = ';'; + } + my $patharrayref = installer::converter::convert_stringlist_into_array(\$pathvariable, $local_pathseparator); + + $installer::globals::patharray = $patharrayref; + + my @needed_files_in_path = (); + + if (($installer::globals::iswin) && ($installer::globals::iswindowsbuild)) + { + @needed_files_in_path = ("zip.exe", "unzip.exe", "msiinfo.exe", "msidb.exe", "uuidgen.exe", "makecab.exe", "msitran.exe", "expand.exe"); + + if ( $installer::globals::compiler eq "wntmsci8" ) + { + push(@needed_files_in_path, "msvcp70.dll"); + push(@needed_files_in_path, "msvcr70.dll"); + } + + if ( $installer::globals::compiler eq "wntmsci10" ) + { + push(@needed_files_in_path, "msvcp71.dll"); + push(@needed_files_in_path, "msvcr71.dll"); + } + + } + elsif ($installer::globals::iswin) + { + @needed_files_in_path = ("zip.exe", "unzip.exe"); + } + else + { + @needed_files_in_path = ("zip", "unzip"); + } + + foreach $onefile ( @needed_files_in_path ) + { + installer::logger::print_message( "...... searching $onefile ..." ); + + my $fileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath_classic(\$onefile, $patharrayref , 0); + + if ( $$fileref eq "" ) + { + $error = 1; + installer::logger::print_error( "$onefile not found\n" ); + } + else + { + installer::logger::print_message( "\tFound: $$fileref\n" ); + # Saving the absolut path for msitran.exe. This is required for the determination of the checksum. + if ( $onefile eq "msitran.exe" ) { $installer::globals::msitranpath = $$fileref; } + } + } + + if ( $error ) + { + installer::exiter::exit_program("ERROR: Could not find all needed files in path!", "check_system_path"); + } + + # checking for epm, which has to be in the path or in the solver + + if (( $installer::globals::call_epm ) && (!($installer::globals::iswindowsbuild))) + { + my $onefile = "epm"; + my $fileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$onefile, $patharrayref , 0); + if (!( $$fileref eq "" )) + { + $installer::globals::epm_in_path = 1; + + if ( $$fileref =~ /^\s*\.\/epm\s*$/ ) + { + my $currentdir = cwd(); + $$fileref =~ s/\./$currentdir/; + } + + $installer::globals::epm_path = $$fileref; + } + } + + # checking, if upx can be found in path + + if ( $installer::globals::iswindowsbuild ) { $installer::globals::upxfile = "upx.exe"; } + else { $installer::globals::upxfile = "upx"; } + + my $upxfilename = $installer::globals::upxfile; + my $upxfileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath_classic(\$upxfilename, $patharrayref , 0); + + if (!( $$upxfileref eq "" )) + { + $installer::globals::upx_in_path = 1; + $installer::globals::upxfile = $$upxfileref; + installer::logger::print_message( "\tFound: $$upxfileref\n" ); + } + +} + +###################################################################### +# Determining the version of file makecab.exe +###################################################################### + +sub get_makecab_version +{ + my $makecabversion = -1; + + my $systemcall = "makecab.exe |"; + my @makecaboutput = (); + + open (CAB, $systemcall); + while (<CAB>) { push(@makecaboutput, $_); } + close (CAB); + + my $returnvalue = $?; # $? contains the return value of the systemcall + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::globallogfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::globallogfileinfo, $infoline); + + my $versionline = ""; + + for ( my $i = 0; $i <= $#makecaboutput; $i++ ) + { + if ( $makecaboutput[$i] =~ /\bVersion\b/i ) + { + $versionline = $makecaboutput[$i]; + last; + } + } + + $infoline = $versionline; + push( @installer::globals::globallogfileinfo, $infoline); + + if ( $versionline =~ /\bVersion\b\s+(\d+[\d\.]+\d+)\s+/ ) + { + $makecabversion = $1; + } + + # Only using the first number + + if ( $makecabversion =~ /^\s*(\d+?)\D*/ ) + { + $makecabversion = $1; + } + + $infoline = "Using version: " . $makecabversion . "\n"; + push( @installer::globals::globallogfileinfo, $infoline); + } + + return $makecabversion; +} + +###################################################################### +# Checking the version of file makecab.exe +###################################################################### + +sub check_makecab_version +{ + # checking version of makecab.exe + # Now it is guaranteed, that makecab.exe is in the path + + my $do_check = 1; + + my $makecabversion = get_makecab_version(); + + my $infoline = "Tested version: " . $installer::globals::controlledmakecabversion . "\n"; + push( @installer::globals::globallogfileinfo, $infoline); + + if ( $makecabversion < 0 ) { $do_check = 0; } # version could not be determined + + if ( $do_check ) + { + if ( $makecabversion < $installer::globals::controlledmakecabversion ) + { + # warning for OOo, error for inhouse products + if ( $installer::globals::isopensourceproduct ) + { + installer::logger::print_warning("Old version of makecab.exe. Found version: \"$makecabversion\", tested version: \"$installer::globals::controlledmakecabversion\"!\n"); + } + else + { + installer::exiter::exit_program("makecab.exe too old. Found version: \"$makecabversion\", required version: \"$installer::globals::controlledmakecabversion\"!", "check_makecab_version"); + } + } + } + else + { + $infoline = "Warning: No version check of makecab.exe\n"; + push( @installer::globals::globallogfileinfo, $infoline); + } +} + +###################################################################### +# Reading the environment variables for the pathes in ziplist. +# solarpath, solarenvpath, solarcommonpath, os, osdef, pmiscpath +###################################################################### + +sub check_system_environment +{ + my %variables = (); + my $key; + my $error = 0; + + foreach $key ( @installer::globals::environmentvariables ) + { + my $value = ""; + if ( $ENV{$key} ) { $value = $ENV{$key}; } + $variables{$key} = $value; + + if ( $value eq "" ) + { + installer::logger::print_error( "$key not set in environment\n" ); + $error = 1; + } + } + + if ( $error ) + { + installer::exiter::exit_program("ERROR: Environment variable not set!", "check_system_environment"); + } + + return \%variables; +} + +############################################################# +# Controlling the log file at the end of the +# packaging process +############################################################# + +sub check_logfile +{ + my ($logfile) = @_; + + my @errors = (); + my @output = (); + my $contains_error = 0; + + for ( my $i = 0; $i <= $#{$logfile}; $i++ ) + { + my $line = ${$logfile}[$i]; + + # Errors are all errors, but not the Windows installer table "Error.idt" + + my $compareline = $line; + $compareline =~ s/Error\.idt//g; # removing all occurences of "Error.idt" + $compareline =~ s/Error\.mlf//g; # removing all occurences of "Error.mlf" + $compareline =~ s/Error\.ulf//g; # removing all occurences of "Error.ulf" + $compareline =~ s/Error\.idl//g; # removing all occurences of "Error.idl" + $compareline =~ s/Error\.html//g; # removing all occurences of "Error.html" + + if ( $compareline =~ /\bError\b/i ) + { + $contains_error = 1; + push(@errors, $line); + } + } + + if ($contains_error) + { + my $line = "\n*********************************************************************\n"; + push(@output, $line); + $line = "ERROR: The following errors occured in packaging process:\n\n"; + push(@output, $line); + + for ( my $i = 0; $i <= $#errors; $i++ ) + { + $line = "$errors[$i]"; + push(@output, $line); + } + + $line = "*********************************************************************\n"; + push(@output, $line); +# exit(-1); + } + else + { + my $line = "\n***********************************************************\n"; + push(@output, $line); + $line = "Successful packaging process!\n"; + push(@output, $line); + $line = "***********************************************************\n"; + push(@output, $line); + } + + # printing the output file and adding it to the logfile + + installer::logger::include_header_into_logfile("Summary:"); + + my $force = 1; # print this message even in 'quiet' mode + for ( my $i = 0; $i <= $#output; $i++ ) + { + my $line = "$output[$i]"; + installer::logger::print_message( "$line", $force ); + push( @installer::globals::logfileinfo, $line); + push( @installer::globals::errorlogfileinfo, $line); + } + + return $contains_error; +} + +############################################################# +# Determining the ship installation directory +############################################################# + +sub determine_ship_directory +{ + my ($languagesref) = @_; + + if (!( $ENV{'SHIPDRIVE'} )) { installer::exiter::exit_program("ERROR: SHIPDRIVE must be set for updater!", "determine_ship_directory"); } + + my $shipdrive = $ENV{'SHIPDRIVE'}; + + my $languagestring = $$languagesref; + my $productstring = $installer::globals::product; + my $productsubdir = ""; + + if ( $productstring =~ /^\s*(.+?)\_\_(.+?)\s*$/ ) + { + $productstring = $1; + $productsubdir = $2; + } + + if ( $installer::globals::languagepack ) { $productstring = $productstring . "_languagepack"; } + if ( $installer::globals::patch ) { $productstring = $productstring . "_patch"; } + + my $destdir = $shipdrive . $installer::globals::separator . $installer::globals::compiler . + $installer::globals::productextension . $installer::globals::separator . + $productstring . $installer::globals::separator; + + if ( $productsubdir ) { $destdir = $destdir . $productsubdir . $installer::globals::separator; } + + $destdir = $destdir . $installer::globals::installertypedir . $installer::globals::separator . + $installer::globals::build . "_" . $installer::globals::lastminor . "_" . + "native_inprogress-number_" . $languagestring . "\." . $installer::globals::buildid; + + my $infoline = "\nSetting ship directory: $destdir\n"; + push(@installer::globals::globallogfileinfo, $infoline); + + return $destdir; +} + +############################################################# +# Controlling if this is an official RE pack process +############################################################# + +sub check_updatepack +{ + my $shipdrive = ""; + my $filename = ""; + my $infoline = ""; + + if ( $ENV{'UPDATER'} ) # the environment variable UPDATER has to be set + { + $infoline = "\nEnvironment variable UPDATER set\n"; + push(@installer::globals::globallogfileinfo, $infoline); + + if ( ! $ENV{'CWS_WORK_STAMP'} ) # the environment variable CWS_WORK_STAMP must not be set (set only in CWS) + { + $infoline = "Environment variable CWS_WORK_STAMP not set\n"; + push(@installer::globals::globallogfileinfo, $infoline); + + if ( $ENV{'SHIPDRIVE'} ) # the environment variable SHIPDRIVE must be set + { + $shipdrive = $ENV{'SHIPDRIVE'}; + $infoline = "Ship drive defined: $shipdrive\n"; + push(@installer::globals::globallogfileinfo, $infoline); + + if ( -d $shipdrive ) # SHIPDRIVE must be a directory + { + $infoline = "Ship drive exists\n"; + push(@installer::globals::globallogfileinfo, $infoline); + + # try to write into $shipdrive + + $directory = $installer::globals::product . "_" . $installer::globals::compiler . "_" . $installer::globals::buildid . "_" . $installer::globals::languageproducts[0] . "_test_$$"; + $directory =~ s/\,/\_/g; # for the list of languages + $directory =~ s/\-/\_/g; # for en-US, pt-BR, ... + $directory = $shipdrive . $installer::globals::separator . $directory; + + $infoline = "Try to create directory: $directory\n"; + push(@installer::globals::globallogfileinfo, $infoline); + + # saving this directory for later removal + $installer::globals::shiptestdirectory = $directory; + + if ( installer::systemactions::try_to_create_directory($directory)) + { + $infoline = "Write access on Ship drive\n"; + push(@installer::globals::globallogfileinfo, $infoline); + $infoline = "Ship test directory $installer::globals::shiptestdirectory was successfully created\n"; + push(@installer::globals::globallogfileinfo, $infoline); + my $systemcall = "rmdir $directory"; + my $returnvalue = system($systemcall); + + # 5th condition: No local build environment. + # In this case the content of SOLARENV starts with the content of SOL_TMP + + my $solarenv = ""; + my $sol_tmp; + if ( $ENV{'SOLARENV'} ) { $solarenv = $ENV{'SOLARENV'}; } + + $infoline = "Environment variable SOLARENV: $solarenv\n"; + push(@installer::globals::globallogfileinfo, $infoline); + + if ( $ENV{'SOL_TMP'} ) + { + $sol_tmp = $ENV{'SOL_TMP'}; + $infoline = "Environment variable SOL_TMP: $sol_tmp\n"; + } else { + $infoline = "Environment variable SOL_TMP not set\n"; + } + push(@installer::globals::globallogfileinfo, $infoline); + + if ( defined $sol_tmp && ( $solarenv =~ /^\s*\Q$sol_tmp\E/ )) + { + $infoline = "Content of SOLARENV starts with the content of SOL_TMP\: Local environment -\> No Updatepack\n"; + push(@installer::globals::globallogfileinfo, $infoline); + } + else + { + $infoline = "Content of SOLARENV does not start with the content of SOL_TMP: No local environment\n"; + push(@installer::globals::globallogfileinfo, $infoline); + + $installer::globals::updatepack = 1; # That's it + } + + # Additional logging information for the temporary ship directory + + if ( -d $installer::globals::shiptestdirectory ) + { + $infoline = "Ship test directory $installer::globals::shiptestdirectory still exists. Trying removal later again.\n"; + push(@installer::globals::globallogfileinfo, $infoline); + } + else + { + $infoline = "Ship test directory $installer::globals::shiptestdirectory was successfully removed.\n"; + push(@installer::globals::globallogfileinfo, $infoline); + } + } + else + { + $infoline = "No write access on Ship drive\n"; + push(@installer::globals::globallogfileinfo, $infoline); + $infoline = "Failed to create directory $directory\n"; + push(@installer::globals::globallogfileinfo, $infoline); + if ( defined $ENV{'BSCLIENT'} && ( uc $ENV{'BSCLIENT'} eq 'TRUE' ) ) { + installer::exiter::exit_program("ERROR: No write access to SHIPDRIVE allthough BSCLIENT is set.", "check_updatepack"); + } + } + } + else + { + $infoline = "Ship drive not found: No updatepack\n"; + push(@installer::globals::globallogfileinfo, $infoline); + } + } + else + { + $infoline = "Environment variable SHIPDRIVE not set: No updatepack\n"; + push(@installer::globals::globallogfileinfo, $infoline); + } + } + else + { + $infoline = "Environment variable CWS_WORK_STAMP defined: No updatepack\n"; + push(@installer::globals::globallogfileinfo, $infoline); + } + } + + if ( $installer::globals::updatepack ) { $infoline = "Setting updatepack true\n\n"; } + else { $infoline = "\nNo updatepack\n"; } + push(@installer::globals::globallogfileinfo, $infoline); + +} + +############################################################# +# Reading the Windows list file for language encodings +############################################################# + +sub read_encodinglist +{ + my ($patharrayref) = @_; + + my $fileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$installer::globals::encodinglistname, $patharrayref , 0); + + if ( $$fileref eq "" ) { installer::exiter::exit_program("ERROR: Did not find Windows encoding list $installer::globals::encodinglistname!", "read_encodinglist"); } + + my $infoline = "Found encoding file: $$fileref\n"; + push(@installer::globals::globallogfileinfo, $infoline); + + my $encodinglist = installer::files::read_file($$fileref); + + my %msiencoding = (); + my %msilanguage = (); + + # Controlling the encoding list + + for ( my $i = 0; $i <= $#{$encodinglist}; $i++ ) + { + my $line = ${$encodinglist}[$i]; + + if ( $line =~ /^\s*\#/ ) { next; } # this is a comment line + + if ( $line =~ /^(.*?)(\#.*)$/ ) { $line = $1; } # removing comments after "#" + + if ( $line =~ /^\s*([\w-]+)\s*(\d+)\s*(\d+)\s*$/ ) + { + my $onelanguage = $1; + my $codepage = $2; + my $windowslanguage = $3; + + $msiencoding{$onelanguage} = $codepage; + $msilanguage{$onelanguage} = $windowslanguage; + } + else + { + installer::exiter::exit_program("ERROR: Wrong syntax in Windows encoding list $installer::globals::encodinglistname : en-US 1252 1033 !", "read_encodinglist"); + } + } + + $installer::globals::msiencoding = \%msiencoding; + $installer::globals::msilanguage = \%msilanguage; + + # my $key; + # foreach $key (keys %{$installer::globals::msiencoding}) { print "A Key: $key : Value: $installer::globals::msiencoding->{$key}\n"; } + # foreach $key (keys %{$installer::globals::msilanguage}) { print "B Key: $key : Value: $installer::globals::msilanguage->{$key}\n"; } + +} + +############################################################# +# Only for Windows and Linux (RPM)there is currently +# a reliable mechanism to register extensions during +# installation process. Therefore it is for all other +# platforms forbidden to install oxt files into that +# directory, in which they are searched for registration. +############################################################# + +sub check_oxtfiles +{ + my ( $filesarray ) = @_; + + for ( my $i = 0; $i <= $#{$filesarray}; $i++ ) + { + my $onefile = ${$filesarray}[$i]; + + if (( $onefile->{'Name'} ) && ( $onefile->{'Dir'} )) + { + if (( $onefile->{'Name'} =~ /\.oxt\s*$/ ) && ( $onefile->{'Dir'} eq $installer::globals::extensioninstalldir )) + { + installer::exiter::exit_program("There is currently only for Linux (RPM) and Windows a reliable mechanism to register extensions during installation.\nPlease remove file \"$onefile->{'gid'}\" from your installation set!\nYou can use \"\#ifdef WNT\" and \"\#ifdef LINUX\" in scp.", "check_oxtfiles"); + } + } + } +} + +############################################################# +# Check if Java is available to create xpd installer +############################################################# + +sub check_java_for_xpd +{ + my ( $allvariables ) = @_; + + if ( ! $installer::globals::solarjavaset ) { $allvariables->{'XPDINSTALLER'} = 0; } +} + +#################################################################### +# Setting global variable "$installer::globals::addchildprojects" +#################################################################### + +sub set_addchildprojects +{ + my ($allvariables) = @_; + + if (( $allvariables->{'JAVAPRODUCT'} ) || + ( $allvariables->{'ADAPRODUCT'} ) || + ( $allvariables->{'UREPRODUCT'} ) || + ( $allvariables->{'ADDREQUIREDPACKAGES'} )) { $installer::globals::addchildprojects = 1; } + + if ( $installer::globals::patch ) + { + $installer::globals::addchildprojects = 0; # no child projects for patches + } + + my $infoline = "Value of \$installer::globals::addchildprojects: $installer::globals::addchildprojects\n"; + push( @installer::globals::globallogfileinfo, $infoline); +} + +#################################################################### +# Setting global variable "$installer::globals::addjavainstaller" +#################################################################### + +sub set_addjavainstaller +{ + my ($allvariables) = @_; + + if ( $allvariables->{'JAVAINSTALLER'} ) { $installer::globals::addjavainstaller = 1; } + + if ( $installer::globals::patch ) { $installer::globals::addjavainstaller = 0; } + if ( $installer::globals::languagepack ) { $installer::globals::addjavainstaller = 0; } + if ( $allvariableshashref->{'XPDINSTALLER'} ) { $installer::globals::addjavainstaller = 0; } + + my $infoline = "Value of \$installer::globals::addjavainstaller: $installer::globals::addjavainstaller\n"; + push( @installer::globals::globallogfileinfo, $infoline); +} + +####################################################################### +# Setting global variable "$installer::globals::addsystemintegration" +####################################################################### + +sub set_addsystemintegration +{ + my ($allvariables) = @_; + + if ( $allvariables->{'ADDSYSTEMINTEGRATION'} ) { $installer::globals::addsystemintegration = 1; } + + if ( $installer::globals::patch ) { $installer::globals::addsystemintegration = 0; } + if ( $installer::globals::languagepack ) { $installer::globals::addsystemintegration = 0; } + + my $infoline = "Value of \$installer::globals::addsystemintegration: $installer::globals::addsystemintegration\n"; + push( @installer::globals::globallogfileinfo, $infoline); +} + +1; diff --git a/solenv/bin/modules/installer/converter.pm b/solenv/bin/modules/installer/converter.pm new file mode 100644 index 000000000000..814b8f6abd27 --- /dev/null +++ b/solenv/bin/modules/installer/converter.pm @@ -0,0 +1,476 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: converter.pm,v $ +# +# $Revision: 1.18 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::converter; + +use installer::globals; + +############################# +# Converter +############################# + +sub convert_array_to_hash +{ + my ($arrayref) = @_; + + my %newhash = (); + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + my $line = ${$arrayref}[$i]; + + if ( $line =~ /^\s*([\w-]+?)\s+(.*?)\s*$/ ) + { + my $key = $1; + my $value = $2; + $newhash{$key} = $value; + } + } + + return \%newhash; +} + +sub convert_hash_into_array +{ + my ($hashref) = @_; + + my @array = (); + my $key; + + foreach $key (keys %{$hashref}) + { + my $value = $hashref->{$key}; + my $input = "$key = $value\n"; + push(@array ,$input); + } + + return \@array +} + +############################################################################# +# Converting a string list with separator $listseparator +# into an array +############################################################################# + +sub convert_stringlist_into_array_without_linebreak_and_quotes +{ + my ( $includestringref, $listseparator ) = @_; + + my @newarray = (); + my $first; + my $last = ${$includestringref}; + + while ( $last =~ /^\s*(.+?)\Q$listseparator\E(.+)\s*$/) # "$" for minimal matching + { + $first = $1; + $last = $2; + if ( defined($ENV{'USE_SHELL'}) && $ENV{'USE_SHELL'} eq "4nt" ) { $first =~ s/\//\\/g; } + $first =~ s/\"//g; + push(@newarray, $first); + } + + if ( defined($ENV{'USE_SHELL'}) && $ENV{'USE_SHELL'} eq "4nt" ) { $last =~ s/\//\\/g; } + $last =~ s/\"//g; + push(@newarray, $last); + + return \@newarray; +} + +############################################################################# +# Converting a string list with separator $listseparator +# into an array +############################################################################# + +sub convert_stringlist_into_array +{ + my ( $includestringref, $listseparator ) = @_; + + my @newarray = (); + my $first; + my $last = ${$includestringref}; + + while ( $last =~ /^\s*(.+?)\Q$listseparator\E(.+)\s*$/) # "$" for minimal matching + { + $first = $1; + $last = $2; + if ( defined($ENV{'USE_SHELL'}) && $ENV{'USE_SHELL'} eq "4nt" ) { $first =~ s/\//\\/g; } + # Problem with two directly following listseparators. For example a path with two ";;" directly behind each other + $first =~ s/^$listseparator//; + push(@newarray, "$first\n"); + } + + if ( defined($ENV{'USE_SHELL'}) && $ENV{'USE_SHELL'} eq "4nt" ) { $last =~ s/\//\\/g; } + push(@newarray, "$last\n"); + + return \@newarray; +} + +############################################################################# +# Converting a string list with separator $listseparator +# into an array +############################################################################# + +sub convert_stringlist_into_array_without_newline +{ + my ( $includestringref, $listseparator ) = @_; + + my @newarray = (); + my $first; + my $last = ${$includestringref}; + + while ( $last =~ /^\s*(.+?)\Q$listseparator\E(.+)\s*$/) # "$" for minimal matching + { + $first = $1; + $last = $2; + if ( defined($ENV{'USE_SHELL'}) && $ENV{'USE_SHELL'} eq "4nt" ) { $first =~ s/\//\\/g; } + push(@newarray, "$first"); + } + + if ( defined($ENV{'USE_SHELL'}) && $ENV{'USE_SHELL'} eq "4nt" ) { $last =~ s/\//\\/g; } + push(@newarray, "$last"); + + return \@newarray; +} + +############################################################################# +# Converting a string list with separator $listseparator +# into a hash with values 1. +############################################################################# + +sub convert_stringlist_into_hash +{ + my ( $includestringref, $listseparator ) = @_; + + my %newhash = (); + my $first; + my $last = ${$includestringref}; + + while ( $last =~ /^\s*(.+?)\Q$listseparator\E(.+)\s*$/) # "$" for minimal matching + { + $first = $1; + $last = $2; + if ( defined($ENV{'USE_SHELL'}) && $ENV{'USE_SHELL'} eq "4nt" ) { $first =~ s/\//\\/g; } + $newhash{$first} = 1; + } + + if ( defined($ENV{'USE_SHELL'}) && $ENV{'USE_SHELL'} eq "4nt" ) { $last =~ s/\//\\/g; } + $newhash{$last} = 1; + + return \%newhash; +} + +############################################################################# +# Converting a string list with separator $listseparator +# into an array +############################################################################# + +sub convert_whitespace_stringlist_into_array +{ + my ( $includestringref ) = @_; + + my @newarray = (); + my $first; + my $last = ${$includestringref}; + + while ( $last =~ /^\s*(\S+?)\s+(\S+)\s*$/) # "$" for minimal matching + { + $first = $1; + $last = $2; + if ( defined($ENV{'USE_SHELL'}) && $ENV{'USE_SHELL'} eq "4nt" ) { $first =~ s/\//\\/g; } + push(@newarray, "$first\n"); + } + + if ( defined($ENV{'USE_SHELL'}) && $ENV{'USE_SHELL'} eq "4nt" ) { $last =~ s/\//\\/g; } + push(@newarray, "$last\n"); + + return \@newarray; +} + +############################################################################# +# Converting an array into a comma separated string +############################################################################# + +sub convert_array_to_comma_separated_string +{ + my ( $arrayref ) = @_; + + my $newstring = ""; + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + my $arrayentry = ${$arrayref}[$i]; + $arrayentry =~ s/\s*$//; + $newstring = $newstring . $arrayentry . ","; + } + + $newstring =~ s/\,\s*$//; + + return $newstring; +} + +############################################################################# +# Converting an array into a space separated string +############################################################################# + +sub convert_array_to_space_separated_string +{ + my ( $arrayref ) = @_; + + my $newstring = ""; + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + my $arrayentry = ${$arrayref}[$i]; + $arrayentry =~ s/\s*$//; + $newstring = $newstring . $arrayentry . " "; + } + + $newstring =~ s/\s*$//; + + return $newstring; +} + +############################################################################# +# The file name contains for some files "/". If this programs runs on +# a windows platform, this has to be converted to "\". +############################################################################# + +sub convert_slash_to_backslash +{ + my ($filesarrayref) = @_; + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + if ( $onefile->{'Name'} ) { $onefile->{'Name'} =~ s/\//\\/g; } + } +} + +############################################################################ +# Creating a copy of an existing file object +# No converter +############################################################################ + +sub copy_item_object +{ + my ($olditemhashref, $newitemhashref) = @_; + + foreach $key (keys %{$olditemhashref}) + { + my $value = $olditemhashref->{$key}; + $newitemhashref->{$key} = $value; + } +} + +################################################################# +# Windows pathes must not contain the following structure: +# c:\dirA\dirB\..\dirC +# This has to be exchanged to +# c:\dirA\dirC +################################################################# + +sub make_path_conform +{ + my ( $path ) = @_; + + my $oldpath = $path; + + while ( $path =~ /(^.*)(\Q$installer::globals::separator\E.*?[^\.])(\Q$installer::globals::separator\E\.\.)(\Q$installer::globals::separator\E.*$)/ ) + { + my $part1 = $1; + my $part2 = $4; + + # $2 must not end with a "." ! Problem with "..\.." + + $path = $part1 . $part2; + } + + return $path; +} + +################################################################# +# Copying an item collector +# A reference to an array consisting of references to hashes. +################################################################# + +sub copy_collector +{ + my ( $oldcollector ) = @_; + + my @newcollector = (); + + for ( my $i = 0; $i <= $#{$oldcollector}; $i++ ) + { + my %newhash = (); + my $key; + + foreach $key (keys %{${$oldcollector}[$i]}) + { + $newhash{$key} = ${$oldcollector}[$i]->{$key}; + } + + push(@newcollector, \%newhash); + } + + return \@newcollector; +} + +################################################################# +# Copying an array +################################################################# + +sub copy_array_from_references +{ + my ( $arrayref ) = @_; + + my @newarray = (); + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + push(@newarray, ${$arrayref}[$i]); + } + + return \@newarray; +} + +########################################################### +# Copying a hash +########################################################### + +sub copy_hash_from_references +{ + my ($hashref) = @_; + + my %newhash = (); + my $key; + + foreach $key (keys %{$hashref}) + { + $newhash{$key} = $hashref->{$key}; + } + + return \%newhash; +} + +################################################################# +# Combining two arrays, first wins +################################################################# + +sub combine_arrays_from_references_first_win +{ + my ( $arrayref1, $arrayref2 ) = @_; + + my $hashref1 = convert_array_to_hash($arrayref1); + my $hashref2 = convert_array_to_hash($arrayref2); + my %commonhash = (); + my @newarray = (); + + # starting with second hash + foreach my $key ( keys %{$hashref2} ) { $commonhash{$key} = $hashref2->{$key}; } + # overwriting with first hash + foreach my $key ( keys %{$hashref1} ) { $commonhash{$key} = $hashref1->{$key}; } + + # Creating the new array + foreach my $key ( keys %commonhash ) { push(@newarray, "$key $commonhash{$key}\n"); } + + return \@newarray; +} + +################################################################# +# Combining two arrays +################################################################# + +sub combine_arrays_from_references +{ + my ( $arrayref1, $arrayref2 ) = @_; + + my @newarray = (); + + for ( my $i = 0; $i <= $#{$arrayref1}; $i++ ) + { + push(@newarray, ${$arrayref1}[$i]); + } + + for ( my $i = 0; $i <= $#{$arrayref2}; $i++ ) + { + push(@newarray, ${$arrayref2}[$i]); + } + + return \@newarray; +} + +################################################################# +# Returning the current ending number of a directory +################################################################# + +sub get_number_from_directory +{ + my ( $directory ) = @_; + + my $number = 0; + + if ( $directory =~ /\_(\d+)\s*$/ ) + { + $number = $1; + } + + return $number; +} + +################################################################# +# Replacing separators, that are included into quotes +################################################################# + +sub replace_masked_separator +{ + my ($string, $separator, $replacementstring) = @_; + + $string =~ s/\\\Q$separator\E/$replacementstring/g; + + return $string; +} + +################################################################# +# Resolving separators, that were replaced +# in function mask_separator_in_quotes +################################################################# + +sub resolve_masked_separator +{ + my ($arrayref, $separator, $replacementstring) = @_; + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + ${$arrayref}[$i] =~ s/$replacementstring/$separator/g + } +} + +1; diff --git a/solenv/bin/modules/installer/copyproject.pm b/solenv/bin/modules/installer/copyproject.pm new file mode 100644 index 000000000000..ed826d692df5 --- /dev/null +++ b/solenv/bin/modules/installer/copyproject.pm @@ -0,0 +1,122 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: copyproject.pm,v $ +# +# $Revision: 1.9 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::copyproject; + +use installer::control; +use installer::converter; +use installer::files; +use installer::globals; +use installer::logger; +use installer::mail; +use installer::systemactions; +use installer::worker; + +#################################################### +# Including header files into the logfile +#################################################### + +sub copy_project +{ + my ( $filesref, $scpactionsref, $loggingdir, $languagestringref, $shipinstalldir, $allsettingsarrayref ) = @_; + + # Creating directories + + installer::logger::include_header_into_logfile("Creating installation directory"); + + my $current_install_number = ""; + + my $installdir = installer::worker::create_installation_directory($shipinstalldir, $languagestringref, \$current_install_number); + + my $installlogdir = installer::systemactions::create_directory_next_to_directory($installdir, "log"); + + # Copy files and ScpActions + + installer::logger::include_header_into_logfile("Copying files:"); + + # copy Files + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + + my $source = $onefile->{'sourcepath'}; + my $destination = $installdir . $installer::globals::separator . $onefile->{'Name'}; + + installer::systemactions::copy_one_file($source, $destination); + + if ( $destination =~ /install\s*$/ ) + { + my $localcall = "chmod 775 $destination \>\/dev\/null 2\>\&1"; + system($localcall); + } + + if ( $onefile->{'UnixRights'} ) + { + my $localcall = "chmod $onefile->{'UnixRights'} $destination \>\/dev\/null 2\>\&1"; + system($localcall); + } + } + + # copy ScpActions + + for ( my $i = 0; $i <= $#{$scpactionsref}; $i++ ) + { + my $onefile = ${$scpactionsref}[$i]; + + my $source = $onefile->{'sourcepath'}; + my $destination = $installdir . $installer::globals::separator . $onefile->{'DestinationName'}; + + installer::systemactions::copy_one_file($source, $destination); + + if ( $destination =~ /install\s*$/ ) + { + my $localcall = "chmod 775 $destination \>\/dev\/null 2\>\&1"; + system($localcall); + } + + if ( $onefile->{'UnixRights'} ) + { + my $localcall = "chmod $onefile->{'UnixRights'} $destination \>\/dev\/null 2\>\&1"; + system($localcall); + } + } + + # Analyzing the log file + + installer::worker::analyze_and_save_logfile($loggingdir, $installdir, $installlogdir, $allsettingsarrayref, $languagestringref, $current_install_number); + + # That's all + + exit(0); +} + +1; diff --git a/solenv/bin/modules/installer/download.pm b/solenv/bin/modules/installer/download.pm new file mode 100644 index 000000000000..5691272893dd --- /dev/null +++ b/solenv/bin/modules/installer/download.pm @@ -0,0 +1,1902 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: download.pm,v $ +# +# $Revision: 1.47 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::download; + +use File::Spec; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::logger; +use installer::pathanalyzer; +use installer::remover; +use installer::systemactions; + +BEGIN { # This is needed so that cygwin's perl evaluates ACLs + # (needed for correctly evaluating the -x test.) + if( $^O =~ /cygwin/i ) { + require filetest; import filetest "access"; + } +} + +################################################################## +# Including the lowercase product name into the script template +################################################################## + +sub put_productname_into_script +{ + my ($scriptfile, $variableshashref) = @_; + + my $productname = $variableshashref->{'PRODUCTNAME'}; + $productname = lc($productname); + $productname =~ s/\.//g; # openoffice.org -> openofficeorg + $productname =~ s/\s*//g; + + my $infoline = "Adding productname $productname into download shell script\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $i = 0; $i <= $#{$scriptfile}; $i++ ) + { + ${$scriptfile}[$i] =~ s/PRODUCTNAMEPLACEHOLDER/$productname/; + } +} + +######################################################### +# Including the linenumber into the script template +######################################################### + +sub put_linenumber_into_script +{ + my ( $scriptfile ) = @_; + + my $linenumber = $#{$scriptfile} + 2; + + my $infoline = "Adding linenumber $linenumber into download shell script\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $i = 0; $i <= $#{$scriptfile}; $i++ ) + { + ${$scriptfile}[$i] =~ s/LINENUMBERPLACEHOLDER/$linenumber/; + } +} + +######################################################### +# Determining the name of the new scriptfile +######################################################### + +sub determine_scriptfile_name +{ + my ( $filename ) = @_; + + $installer::globals::downloadfileextension = ".sh"; + $filename = $filename . $installer::globals::downloadfileextension; + $installer::globals::downloadfilename = $filename; + + my $infoline = "Setting download shell script file name to $filename\n"; + push( @installer::globals::logfileinfo, $infoline); + + return $filename; +} + +######################################################### +# Saving the script file in the installation directory +######################################################### + +sub save_script_file +{ + my ($directory, $newscriptfilename, $scriptfile) = @_; + + $newscriptfilename = $directory . $installer::globals::separator . $newscriptfilename; + installer::files::save_file($newscriptfilename, $scriptfile); + + my $infoline = "Saving script file $newscriptfilename\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ( ! $installer::globals::iswindowsbuild ) + { + my $localcall = "chmod 775 $newscriptfilename \>\/dev\/null 2\>\&1"; + system($localcall); + } + + return $newscriptfilename; +} + +######################################################### +# Including checksum and size into script file +######################################################### + +sub put_checksum_and_size_into_script +{ + my ($scriptfile, $sumout) = @_; + + my $checksum = ""; + my $size = ""; + + if ( $sumout =~ /^\s*(\d+)\s+(\d+)\s*$/ ) + { + $checksum = $1; + $size = $2; + } + else + { + installer::exiter::exit_program("ERROR: Incorrect return value from /usr/bin/sum: $sumout", "put_checksum_and_size_into_script"); + } + + my $infoline = "Adding checksum $checksum and size $size into download shell script\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $i = 0; $i <= $#{$scriptfile}; $i++ ) + { + ${$scriptfile}[$i] =~ s/CHECKSUMPLACEHOLDER/$checksum/; + ${$scriptfile}[$i] =~ s/DISCSPACEPLACEHOLDER/$size/; + } + +} + +######################################################### +# Calling md5sum +######################################################### + +sub call_md5sum +{ + my ($filename) = @_; + + $md5sumfile = "/usr/bin/md5sum"; + + if ( ! -f $md5sumfile ) { installer::exiter::exit_program("ERROR: No file /usr/bin/md5sum", "call_md5sum"); } + + my $systemcall = "$md5sumfile $filename |"; + + my $md5sumoutput = ""; + + open (SUM, "$systemcall"); + $md5sumoutput = <SUM>; + close (SUM); + + my $returnvalue = $?; # $? contains the return value of the systemcall + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + return $md5sumoutput; +} + +######################################################### +# Calling md5sum +######################################################### + +sub get_md5sum +{ + ($md5sumoutput) = @_; + + my $md5sum; + + if ( $md5sumoutput =~ /^\s*(\w+?)\s+/ ) + { + $md5sum = $1; + } + else + { + installer::exiter::exit_program("ERROR: Incorrect return value from /usr/bin/md5sum: $md5sumoutput", "get_md5sum"); + } + + my $infoline = "Setting md5sum: $md5sum\n"; + push( @installer::globals::logfileinfo, $infoline); + + return $md5sum; +} + +######################################################### +# Determining checksum and size of tar file +######################################################### + +sub call_sum +{ + my ($filename, $getuidlibrary) = @_; + + my $systemcall = "/usr/bin/sum $filename |"; + + my $sumoutput = ""; + + open (SUM, "$systemcall"); + $sumoutput = <SUM>; + close (SUM); + + my $returnvalue = $?; # $? contains the return value of the systemcall + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + $sumoutput =~ s/\s+$filename\s$//; + return $sumoutput; +} + +######################################################### +# Searching for the getuid.so in the solver +######################################################### + +sub get_path_for_library +{ + my ($includepatharrayref) = @_; + + my $getuidlibraryname = "getuid.so"; + my $getuidlibraryref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$getuidlibraryname, $includepatharrayref, 0); + if ($$getuidlibraryref eq "") { installer::exiter::exit_program("ERROR: Could not find $getuidlibraryname!", "get_path_for_library"); } + + return $$getuidlibraryref; +} + +######################################################### +# Include the tar file into the script +######################################################### + +sub include_tar_into_script +{ + my ($scriptfile, $temporary_tarfile) = @_; + + my $systemcall = "cat $temporary_tarfile >> $scriptfile && rm $temporary_tarfile"; + my $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + return $returnvalue; +} + +######################################################### +# Create a tar file from the binary package +######################################################### + +sub tar_package +{ + my ( $installdir, $tarfilename, $getuidlibrary) = @_; + + my $ldpreloadstring = ""; + if ( $getuidlibrary ne "" ) { $ldpreloadstring = "LD_PRELOAD=" . $getuidlibrary; } + + my $systemcall = "cd $installdir; $ldpreloadstring tar -cf - * > $tarfilename"; + + my $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + my $localcall = "chmod 775 $tarfilename \>\/dev\/null 2\>\&1"; + $returnvalue = system($localcall); + + return ( -s $tarfilename ); +} + +######################################################### +# Creating a tar.gz file +######################################################### + +sub create_tar_gz_file_from_package +{ + my ($installdir, $getuidlibrary) = @_; + + my $infoline = ""; + my $alldirs = installer::systemactions::get_all_directories($installdir); + my $onedir = ${$alldirs}[0]; + $installdir = $onedir; + + my $allfiles = installer::systemactions::get_all_files_from_one_directory($installdir); + + for ( my $i = 0; $i <= $#{$allfiles}; $i++ ) + { + my $onefile = ${$allfiles}[$i]; + my $systemcall = "cd $installdir; rm $onefile"; + my $returnvalue = system($systemcall); + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + + $alldirs = installer::systemactions::get_all_directories($installdir); + $packagename = ${$alldirs}[0]; # only taking the first Solaris package + if ( $packagename eq "" ) { installer::exiter::exit_program("ERROR: Could not find package in directory $installdir!", "determine_packagename"); } + + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$packagename); + + $installer::globals::downloadfileextension = ".tar.gz"; + my $targzname = $packagename . $installer::globals::downloadfileextension; + $installer::globals::downloadfilename = $targzname; + my $ldpreloadstring = ""; + if ( $getuidlibrary ne "" ) { $ldpreloadstring = "LD_PRELOAD=" . $getuidlibrary; } + + $systemcall = "cd $installdir; $ldpreloadstring tar -cf - $packagename | gzip > $targzname"; + print "... $systemcall ...\n"; + + my $returnvalue = system($systemcall); + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +######################################################### +# Setting type of installation +######################################################### + +sub get_installation_type +{ + my $type = ""; + + if ( $installer::globals::languagepack ) { $type = "langpack"; } + else { $type = "install"; } + + return $type; +} + +######################################################### +# Setting installation languages +######################################################### + +sub get_downloadname_language +{ + my ($languagestringref) = @_; + + my $languages = $$languagestringref; + + if ( $installer::globals::added_english ) + { + $languages =~ s/en-US_//; + $languages =~ s/_en-US//; + } + + # en-US is default language and can be removed therefore + # for one-language installation sets + + if ( $languages =~ /^\s*en-US\s*$/ ) + { + $languages = ""; + } + + + if ( length ($languages) > $installer::globals::max_lang_length ) + { + $languages = 'multi'; + } + + return $languages; +} + +######################################################### +# Setting download name, first part +######################################################### + +sub get_downloadname_start +{ + my ($allvariables) = @_; + + my $start = "OOo"; + if ( $allvariables->{'PRODUCTNAME'} eq "BrOffice.org" ) { $start = "BrOo"; } + + return $start; +} + +######################################################### +# Setting installation addons +######################################################### + +sub get_downloadname_addon +{ + my $addon = ""; + + if ( $installer::globals::islinuxdebbuild ) { $addon = $addon . "_deb"; } + + if ( $installer::globals::product =~ /_wJRE\s*$/ ) { $addon = "_wJRE"; } + + return $addon; +} + +######################################################### +# Looking for versionstring in version.info +# This has to be the only content of this file. +######################################################### + +sub get_versionstring +{ + my ( $versionfile ) = @_; + + my $versionstring = ""; + + for ( my $i = 0; $i <= $#{$versionfile}; $i++ ) + { + my $oneline = ${$versionfile}[$i]; + + if ( $oneline =~ /^\s*\#/ ) { next; } # comment line + if ( $oneline =~ /^\s*\"\s*(.*?)\s*\"\s*$/ ) + { + $versionstring = $1; + last; + } + } + + return $versionstring; +} + +######################################################### +# Returning the current product version +# This has to be defined in file "version.info" +# in directory $installer::globals::ooouploaddir +######################################################### + +sub get_current_version +{ + my $infoline = ""; + my $versionstring = ""; + my $filename = "version.info"; + # $filename = $installer::globals::ooouploaddir . $installer::globals::separator . $filename; + + if ( -f $filename ) + { + $infoline = "File $filename exists. Trying to find current version.\n"; + push( @installer::globals::logfileinfo, $infoline); + my $versionfile = installer::files::read_file($filename); + $versionstring = get_versionstring($versionfile); + $infoline = "Setting version string: $versionstring\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "File $filename does not exist. No version setting in download file name.\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + $installer::globals::oooversionstring = $versionstring; + + return $versionstring; +} + +######################################################### +# Determining the download file name +# Samples: +# OOo_2.0.2rc1_060213_Solarisx86_install_de +# OOo_2.0.2rc1_060213_LinuxIntel_langpack_zh-TW +# OOo_2.0.2rc1_060213_SolarisSparc_install_zh-TW_wJRE +# OOo_2.0.2rc1_060213_Win32Intel_install_zh-TW_wJRE +# OOo_2.0.157_LinuxIntel_install_de +# +######################################################### + +sub set_download_filename +{ + my ($languagestringref, $allvariables) = @_; + + my $start = get_downloadname_start($allvariables); + # my $versionstring = get_current_version(); + my $versionstring = ""; + my $date = installer::logger::set_installation_date(); + if ( $installer::globals::product =~ /_Dev\s*$/ ) { $date = ""; } + my $platform = installer::worker::get_platform_name(); + my $type = get_installation_type(); + my $language = get_downloadname_language($languagestringref); + my $addon = get_downloadname_addon(); + if ( $installer::globals::product =~ /_Dev\s*$/ ) + { + my $localminor = ""; + if ( $installer::globals::minor ne "" ) { $localminor = $installer::globals::minor; } + else { $localminor = $installer::globals::lastminor; } + if ( $localminor =~ /^\s*\w(\d+)\w*\s*$/ ) { $localminor = $1; } + $versionstring = $allvariables->{'PRODUCTVERSION'} . "." . $localminor; + } + else + { + if ( $allvariables->{'PACKAGEVERSION'} ) + { + $versionstring = $allvariables->{'PACKAGEVERSION'}; + } + } + + my $filename = $start . "_" . $versionstring . "_" . $date . "_" . $platform . "_" . $type . "_" . $language . $addon; + + $filename =~ s/\_\_/\_/g; # necessary, if $versionstring or $platform or $language are empty + $filename =~ s/\_\s*$//; # necessary, if $language and $addon are empty + + $installer::globals::ooodownloadfilename = $filename; + + return $filename; +} + +######################################################### +# Creating a tar.gz file +######################################################### + +sub create_tar_gz_file_from_directory +{ + my ($installdir, $getuidlibrary, $downloaddir, $downloadfilename) = @_; + + my $infoline = ""; + + my $packdir = $installdir; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$packdir); + my $changedir = $installdir; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$changedir); + + my $ldpreloadstring = ""; + if ( $getuidlibrary ne "" ) { $ldpreloadstring = "LD_PRELOAD=" . $getuidlibrary; } + + $installer::globals::downloadfileextension = ".tar.gz"; + $installer::globals::downloadfilename = $downloadfilename . $installer::globals::downloadfileextension; + my $targzname = $downloaddir . $installer::globals::separator . $installer::globals::downloadfilename; + + $systemcall = "cd $changedir; $ldpreloadstring tar -cf - $packdir | gzip > $targzname"; + + my $returnvalue = system($systemcall); + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + return $targzname; +} + +######################################################### +# Setting the variables in the download name +######################################################### + +sub resolve_variables_in_downloadname +{ + my ($allvariables, $downloadname, $languagestringref) = @_; + + # Typical name: soa-{productversion}-{extension}-bin-{os}-{languages} + + my $productversion = ""; + if ( $allvariables->{'PRODUCTVERSION'} ) { $productversion = $allvariables->{'PRODUCTVERSION'}; } + $downloadname =~ s/\{productversion\}/$productversion/; + + my $extension = ""; + if ( $allvariables->{'SHORT_PRODUCTEXTENSION'} ) { $extension = $allvariables->{'SHORT_PRODUCTEXTENSION'}; } + $extension = lc($extension); + $downloadname =~ s/\{extension\}/$extension/; + + my $os = ""; + if ( $installer::globals::iswindowsbuild ) { $os = "windows"; } + elsif ( $installer::globals::issolarissparcbuild ) { $os = "solsparc"; } + elsif ( $installer::globals::issolarisx86build ) { $os = "solia"; } + elsif ( $installer::globals::islinuxbuild ) { $os = "linux"; } + elsif ( $installer::globals::compiler =~ /unxmacxi/ ) { $os = "macosxi"; } + elsif ( $installer::globals::compiler =~ /unxmacxp/ ) { $os = "macosxp"; } + else { $os = ""; } + $downloadname =~ s/\{os\}/$os/; + + my $languages = $$languagestringref; + $downloadname =~ s/\{languages\}/$languages/; + + $downloadname =~ s/\-\-\-/\-/g; + $downloadname =~ s/\-\-/\-/g; + $downloadname =~ s/\-\s*$//; + + return $downloadname; +} + +################################################################## +# Windows: Replacing one placeholder with the specified value +################################################################## + +sub replace_one_variable +{ + my ($templatefile, $placeholder, $value) = @_; + + my $infoline = "Replacing $placeholder by $value in nsi file\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $i = 0; $i <= $#{$templatefile}; $i++ ) + { + ${$templatefile}[$i] =~ s/$placeholder/$value/g; + } + +} + +######################################################################################## +# Converting a string to a unicode string +######################################################################################## + +sub convert_to_unicode +{ + my ($string) = @_; + + my $unicodestring = ""; + + my $stringlength = length($string); + + for ( my $i = 0; $i < $stringlength; $i++ ) + { + $unicodestring = $unicodestring . substr($string, $i, 1); + $unicodestring = $unicodestring . chr(0); + } + + return $unicodestring; +} + +################################################################## +# Windows: Setting nsis version is necessary because of small +# changes in nsis from version 2.0.4 to 2.3.1 +################################################################## + +sub set_nsis_version +{ + my ($nshfile) = @_; + + my $searchstring = "\$\{LangFileString\}"; # occurs only in nsis 2.3.1 or similar + + for ( my $i = 0; $i <= $#{$nshfile}; $i++ ) + { + if ( ${$nshfile}[$i] =~ /\Q$searchstring\E/ ) + { + # this is nsis 2.3.1 or similar + $installer::globals::nsis231 = 1; + $installer::globals::unicodensis = 0; + last; + } + } + + # checking unicode version + $searchstring = convert_to_unicode($searchstring); + + for ( my $i = 0; $i <= $#{$nshfile}; $i++ ) + { + if ( ${$nshfile}[$i] =~ /\Q$searchstring\E/ ) + { + # this is nsis 2.3.1 or similar + $installer::globals::nsis231 = 1; + $installer::globals::unicodensis = 1; + last; + } + } + + if ( ! $installer::globals::nsis231 ) { $installer::globals::nsis204 = 1; } +} + +################################################################## +# Windows: Including the product name into nsi template +################################################################## + +sub put_windows_productname_into_template +{ + my ($templatefile, $variableshashref) = @_; + + my $productname = $variableshashref->{'PRODUCTNAME'}; + $productname =~ s/\.//g; # OpenOffice.org -> OpenOfficeorg + + replace_one_variable($templatefile, "PRODUCTNAMEPLACEHOLDER", $productname); +} + +################################################################## +# Windows: Including the path to the banner.bmp into nsi template +################################################################## + +sub put_banner_bmp_into_template +{ + my ($templatefile, $includepatharrayref, $allvariables) = @_; + + # my $filename = "downloadbanner.bmp"; + if ( ! $allvariables->{'DOWNLOADBANNER'} ) { installer::exiter::exit_program("ERROR: DOWNLOADBANNER not defined in product definition!", "put_banner_bmp_into_template"); } + my $filename = $allvariables->{'DOWNLOADBANNER'}; + + my $completefilenameref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$filename, $includepatharrayref, 0); + + if ( $^O =~ /cygwin/i ) { $$completefilenameref =~ s/\//\\/g; } + + if ($$completefilenameref eq "") { installer::exiter::exit_program("ERROR: Could not find download file $filename!", "put_banner_bmp_into_template"); } + + replace_one_variable($templatefile, "BANNERBMPPLACEHOLDER", $$completefilenameref); +} + +################################################################## +# Windows: Including the path to the welcome.bmp into nsi template +################################################################## + +sub put_welcome_bmp_into_template +{ + my ($templatefile, $includepatharrayref, $allvariables) = @_; + + # my $filename = "downloadbitmap.bmp"; + if ( ! $allvariables->{'DOWNLOADBITMAP'} ) { installer::exiter::exit_program("ERROR: DOWNLOADBITMAP not defined in product definition!", "put_welcome_bmp_into_template"); } + my $filename = $allvariables->{'DOWNLOADBITMAP'}; + + my $completefilenameref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$filename, $includepatharrayref, 0); + + if ( $^O =~ /cygwin/i ) { $$completefilenameref =~ s/\//\\/g; } + + if ($$completefilenameref eq "") { installer::exiter::exit_program("ERROR: Could not find download file $filename!", "put_welcome_bmp_into_template"); } + + replace_one_variable($templatefile, "WELCOMEBMPPLACEHOLDER", $$completefilenameref); +} + +################################################################## +# Windows: Including the path to the setup.ico into nsi template +################################################################## + +sub put_setup_ico_into_template +{ + my ($templatefile, $includepatharrayref, $allvariables) = @_; + + # my $filename = "downloadsetup.ico"; + if ( ! $allvariables->{'DOWNLOADSETUPICO'} ) { installer::exiter::exit_program("ERROR: DOWNLOADSETUPICO not defined in product definition!", "put_setup_ico_into_template"); } + my $filename = $allvariables->{'DOWNLOADSETUPICO'}; + + my $completefilenameref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$filename, $includepatharrayref, 0); + + if ( $^O =~ /cygwin/i ) { $$completefilenameref =~ s/\//\\/g; } + + if ($$completefilenameref eq "") { installer::exiter::exit_program("ERROR: Could not find download file $filename!", "put_setup_ico_into_template"); } + + replace_one_variable($templatefile, "SETUPICOPLACEHOLDER", $$completefilenameref); +} + +################################################################## +# Windows: Including the publisher into nsi template +################################################################## + +sub put_publisher_into_template +{ + my ($templatefile) = @_; + + my $publisher = "Sun Microsystems, Inc."; + + replace_one_variable($templatefile, "PUBLISHERPLACEHOLDER", $publisher); +} + +################################################################## +# Windows: Including the web site into nsi template +################################################################## + +sub put_website_into_template +{ + my ($templatefile) = @_; + + my $website = "http\:\/\/www\.sun\.com\/staroffice"; + + replace_one_variable($templatefile, "WEBSITEPLACEHOLDER", $website); +} + +################################################################## +# Windows: Including the Java file name into nsi template +################################################################## + +sub put_javafilename_into_template +{ + my ($templatefile, $variableshashref) = @_; + + my $javaversion = ""; + + if ( $variableshashref->{'WINDOWSJAVAFILENAME'} ) { $javaversion = $variableshashref->{'WINDOWSJAVAFILENAME'}; } + + replace_one_variable($templatefile, "WINDOWSJAVAFILENAMEPLACEHOLDER", $javaversion); +} + +################################################################## +# Windows: Including the product version into nsi template +################################################################## + +sub put_windows_productversion_into_template +{ + my ($templatefile, $variableshashref) = @_; + + my $productversion = $variableshashref->{'PRODUCTVERSION'}; + + replace_one_variable($templatefile, "PRODUCTVERSIONPLACEHOLDER", $productversion); +} + +################################################################## +# Windows: Including the product version into nsi template +################################################################## + +sub put_windows_productpath_into_template +{ + my ($templatefile, $variableshashref, $languagestringref, $localnsisdir) = @_; + + my $productpath = $variableshashref->{'PROPERTYTABLEPRODUCTNAME'}; + + my $locallangs = $$languagestringref; + $locallangs =~ s/_/ /g; + if (length($locallangs) > $installer::globals::max_lang_length) { $locallangs = "multi lingual"; } + + if ( ! $installer::globals::languagepack ) { $productpath = $productpath . " (" . $locallangs . ")"; } + + # if (( $installer::globals::languagepack ) && ( $installer::globals::unicodensis )) { $productpath = convert_textstring_to_utf16($productpath, $localnsisdir, "stringhelper.txt"); } + + replace_one_variable($templatefile, "PRODUCTPATHPLACEHOLDER", $productpath); +} + +################################################################## +# Windows: Including download file name into nsi template +################################################################## + +sub put_outputfilename_into_template +{ + my ($templatefile, $downloadname) = @_; + + $installer::globals::downloadfileextension = ".exe"; + $downloadname = $downloadname . $installer::globals::downloadfileextension; + $installer::globals::downloadfilename = $downloadname; + + replace_one_variable($templatefile, "DOWNLOADNAMEPLACEHOLDER", $downloadname); +} + +################################################################## +# Windows: Generating the file list in nsi file format +################################################################## + +sub get_file_list +{ + my ( $basedir ) = @_; + + my @filelist = (); + + my $alldirs = installer::systemactions::get_all_directories($basedir); + unshift(@{$alldirs}, $basedir); # $basedir is the first directory in $alldirs + + for ( my $i = 0; $i <= $#{$alldirs}; $i++ ) + { + my $onedir = ${$alldirs}[$i]; + + # Syntax: + # SetOutPath "$INSTDIR" + + my $relativedir = $onedir; + $relativedir =~ s/\Q$basedir\E//; + + my $oneline = " " . "SetOutPath" . " " . "\"\$INSTDIR" . $relativedir . "\"" . "\n"; + + if ( $^O =~ /cygwin/i ) { + $oneline =~ s/\//\\/g; + } + push(@filelist, $oneline); + + # Collecting all files in the specific directory + + my $files = installer::systemactions::get_all_files_from_one_directory($onedir); + + for ( my $j = 0; $j <= $#{$files}; $j++ ) + { + my $onefile = ${$files}[$j]; + + my $fileline = " " . "File" . " " . "\"" . $onefile . "\"" . "\n"; + if ( $^O =~ /cygwin/i ) { + $fileline =~ s/\//\\/g; + } + push(@filelist, $fileline); + } + } + + return \@filelist; +} + +################################################################## +# Windows: Including list of all files into nsi template +################################################################## + +sub put_filelist_into_template +{ + my ($templatefile, $installationdir) = @_; + + my $filelist = get_file_list($installationdir); + + my $filestring = ""; + + for ( my $i = 0; $i <= $#{$filelist}; $i++ ) + { + $filestring = $filestring . ${$filelist}[$i]; + } + + $filestring =~ s/\s*$//; + + replace_one_variable($templatefile, "ALLFILESPLACEHOLDER", $filestring); +} + +################################################################## +# Windows: NSIS uses specific language names +################################################################## + +sub nsis_language_converter +{ + my ($language) = @_; + + my $nsislanguage = ""; + + if ( $language eq "en-US" ) { $nsislanguage = "English"; } + elsif ( $language eq "sq" ) { $nsislanguage = "Albanian"; } + elsif ( $language eq "ar" ) { $nsislanguage = "Arabic"; } + elsif ( $language eq "bg" ) { $nsislanguage = "Bulgarian"; } + elsif ( $language eq "ca" ) { $nsislanguage = "Catalan"; } + elsif ( $language eq "hr" ) { $nsislanguage = "Croatian"; } + elsif ( $language eq "cs" ) { $nsislanguage = "Czech"; } + elsif ( $language eq "da" ) { $nsislanguage = "Danish"; } + elsif ( $language eq "nl" ) { $nsislanguage = "Dutch"; } + elsif ( $language eq "de" ) { $nsislanguage = "German"; } + elsif ( $language eq "de-LU" ) { $nsislanguage = "Luxembourgish"; } + elsif ( $language eq "et" ) { $nsislanguage = "Estonian"; } + elsif ( $language eq "fa" ) { $nsislanguage = "Farsi"; } + elsif ( $language eq "el" ) { $nsislanguage = "Greek"; } + elsif ( $language eq "fi" ) { $nsislanguage = "Finnish"; } + elsif ( $language eq "fr" ) { $nsislanguage = "French"; } + elsif ( $language eq "hu" ) { $nsislanguage = "Hungarian"; } + elsif ( $language eq "he" ) { $nsislanguage = "Hebrew"; } + elsif ( $language eq "id" ) { $nsislanguage = "Indonesian"; } + elsif ( $language eq "it" ) { $nsislanguage = "Italian"; } + elsif ( $language eq "lv" ) { $nsislanguage = "Latvian"; } + elsif ( $language eq "lt" ) { $nsislanguage = "Lithuanian"; } + elsif ( $language eq "mk" ) { $nsislanguage = "Macedonian"; } + elsif ( $language eq "mn" ) { $nsislanguage = "Mongolian"; } + elsif ( $language eq "no" ) { $nsislanguage = "Norwegian"; } + elsif ( $language eq "no-NO" ) { $nsislanguage = "Norwegian"; } + elsif ( $language eq "es" ) { $nsislanguage = "Spanish"; } + elsif ( $language eq "sl" ) { $nsislanguage = "Slovenian"; } + elsif ( $language eq "sv" ) { $nsislanguage = "Swedish"; } + elsif ( $language eq "sk" ) { $nsislanguage = "Slovak"; } + elsif ( $language eq "pl" ) { $nsislanguage = "Polish"; } + elsif ( $language eq "pt-BR" ) { $nsislanguage = "PortugueseBR"; } + elsif ( $language eq "pt" ) { $nsislanguage = "Portuguese"; } + elsif ( $language eq "ro" ) { $nsislanguage = "Romanian"; } + elsif ( $language eq "ru" ) { $nsislanguage = "Russian"; } + elsif ( $language eq "sh" ) { $nsislanguage = "SerbianLatin"; } + elsif ( $language eq "sr" ) { $nsislanguage = "Serbian"; } + elsif ( $language eq "sr-SP" ) { $nsislanguage = "Serbian"; } + elsif ( $language eq "uk" ) { $nsislanguage = "Ukrainian"; } + elsif ( $language eq "tr" ) { $nsislanguage = "Turkish"; } + elsif ( $language eq "ja" ) { $nsislanguage = "Japanese"; } + elsif ( $language eq "ko" ) { $nsislanguage = "Korean"; } + elsif ( $language eq "th" ) { $nsislanguage = "Thai"; } + elsif ( $language eq "vi" ) { $nsislanguage = "Vietnamese"; } + elsif ( $language eq "zh-CN" ) { $nsislanguage = "SimpChinese"; } + elsif ( $language eq "zh-TW" ) { $nsislanguage = "TradChinese"; } + else { + my $infoline = "NSIS language_converter : Could not find nsis language for $language!\n"; + push( @installer::globals::logfileinfo, $infoline); + $nsislanguage = "English"; + # installer::exiter::exit_program("ERROR: Could not find nsis language for $language!", "nsis_language_converter"); + } + + return $nsislanguage; +} + +################################################################## +# Windows: Including list of all languages into nsi template +################################################################## + +sub put_language_list_into_template +{ + my ($templatefile, $languagesarrayref) = @_; + + my $alllangstring = ""; + my %nsislangs; + + for ( my $i = 0; $i <= $#{$languagesarrayref}; $i++ ) + { + my $onelanguage = ${$languagesarrayref}[$i]; + my $nsislanguage = nsis_language_converter($onelanguage); + $nsislangs{$nsislanguage}++; + } + + foreach my $nsislanguage ( keys(%nsislangs) ) + { + # Syntax: !insertmacro MUI_LANGUAGE "English" + my $langstring = "\!insertmacro MUI_LANGUAGE_PACK " . $nsislanguage . "\n"; + if ( $nsislanguage eq "English" ) + { + $alllangstring = $langstring . $alllangstring; + } + else + { + $alllangstring = $alllangstring . $langstring; + } + } + + $alllangstring =~ s/\s*$//; + + replace_one_variable($templatefile, "ALLLANGUAGESPLACEHOLDER", $alllangstring); +} + +################################################################## +# Windows: Collecting all identifier from mlf file +################################################################## + +sub get_identifier +{ + my ( $mlffile ) = @_; + + my @identifier = (); + + for ( my $i = 0; $i <= $#{$mlffile}; $i++ ) + { + my $oneline = ${$mlffile}[$i]; + + if ( $oneline =~ /^\s*\[(.+)\]\s*$/ ) + { + my $identifier = $1; + push(@identifier, $identifier); + } + } + + return \@identifier; +} + +############################################################## +# Returning the complete block in all languages +# for a specified string +############################################################## + +sub get_language_block_from_language_file +{ + my ($searchstring, $languagefile) = @_; + + my @language_block = (); + + for ( my $i = 0; $i <= $#{$languagefile}; $i++ ) + { + if ( ${$languagefile}[$i] =~ /^\s*\[\s*$searchstring\s*\]\s*$/ ) + { + my $counter = $i; + + push(@language_block, ${$languagefile}[$counter]); + $counter++; + + while (( $counter <= $#{$languagefile} ) && (!( ${$languagefile}[$counter] =~ /^\s*\[/ ))) + { + push(@language_block, ${$languagefile}[$counter]); + $counter++; + } + + last; + } + } + + return \@language_block; +} + +############################################################## +# Returning a specific language string from the block +# of all translations +############################################################## + +sub get_language_string_from_language_block +{ + my ($language_block, $language) = @_; + + my $newstring = ""; + + for ( my $i = 0; $i <= $#{$language_block}; $i++ ) + { + if ( ${$language_block}[$i] =~ /^\s*$language\s*\=\s*\"(.*)\"\s*$/ ) + { + $newstring = $1; + last; + } + } + + if ( $newstring eq "" ) + { + $language = "en-US"; # defaulting to english + + for ( my $i = 0; $i <= $#{$language_block}; $i++ ) + { + if ( ${$language_block}[$i] =~ /^\s*$language\s*\=\s*\"(.*)\"\s*$/ ) + { + $newstring = $1; + last; + } + } + } + + return $newstring; +} + +################################################################## +# Windows: Replacing strings in NSIS nsh file +# nsh file syntax: +# !define MUI_TEXT_DIRECTORY_TITLE "Zielverzeichnis auswählen" +################################################################## + +sub replace_identifier_in_nshfile +{ + my ( $nshfile, $identifier, $newstring, $nshfilename, $onelanguage ) = @_; + + if ( $installer::globals::nsis231 ) + { + $newstring =~ s/\\r/\$\\r/g; # \r -> $\r in modern nsis versions + $newstring =~ s/\\n/\$\\n/g; # \n -> $\n in modern nsis versions + } + + for ( my $i = 0; $i <= $#{$nshfile}; $i++ ) + { + if ( ${$nshfile}[$i] =~ /\s+\Q$identifier\E\s+\"(.+)\"\s*$/ ) + { + my $oldstring = $1; + ${$nshfile}[$i] =~ s/\Q$oldstring\E/$newstring/; + my $infoline = "NSIS replacement in $nshfilename ($onelanguage): $oldstring \-\> $newstring\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } +} + +################################################################## +# Windows: Replacing strings in NSIS nlf file +# nlf file syntax (2 lines): +# # ^DirSubText +# Zielverzeichnis +################################################################## + +sub replace_identifier_in_nlffile +{ + my ( $nlffile, $identifier, $newstring, $nlffilename, $onelanguage ) = @_; + + for ( my $i = 0; $i <= $#{$nlffile}; $i++ ) + { + if ( ${$nlffile}[$i] =~ /^\s*\#\s+\^\s*\Q$identifier\E\s*$/ ) + { + my $next = $i+1; + my $oldstring = ${$nlffile}[$next]; + ${$nlffile}[$next] = $newstring . "\n"; + $oldstring =~ s/\s*$//; + my $infoline = "NSIS replacement in $nlffilename ($onelanguage): $oldstring \-\> $newstring\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } +} + +################################################################## +# Windows: Translating the NSIS nsh and nlf file +################################################################## + +sub translate_nsh_nlf_file +{ + my ($nshfile, $nlffile, $mlffile, $onelanguage, $nshfilename, $nlffilename, $nsislanguage) = @_; + + # Analyzing the mlf file, collecting all Identifier + my $allidentifier = get_identifier($mlffile); + + $onelanguage = "en-US" if ( $nsislanguage eq "English" && $onelanguage ne "en-US"); + for ( my $i = 0; $i <= $#{$allidentifier}; $i++ ) + { + my $identifier = ${$allidentifier}[$i]; + my $language_block = get_language_block_from_language_file($identifier, $mlffile); + my $newstring = get_language_string_from_language_block($language_block, $onelanguage); + + # removing mask + $newstring =~ s/\\\'/\'/g; + + replace_identifier_in_nshfile($nshfile, $identifier, $newstring, $nshfilename, $onelanguage); + replace_identifier_in_nlffile($nlffile, $identifier, $newstring, $nlffilename, $onelanguage); + } +} + +################################################################## +# Converting utf 16 file to utf 8 +################################################################## + +sub convert_utf16_to_utf8 +{ + my ( $filename ) = @_; + + my @localfile = (); + + my $savfilename = $filename . "_before.utf16"; + installer::systemactions::copy_one_file($filename, $savfilename); + +# open( IN, "<:utf16", $filename ) || installer::exiter::exit_program("ERROR: Cannot open file $filename for reading", "convert_utf16_to_utf8"); +# open( IN, "<:para:crlf:uni", $filename ) || installer::exiter::exit_program("ERROR: Cannot open file $filename for reading", "convert_utf16_to_utf8"); + open( IN, "<:encoding(UTF16-LE)", $filename ) || installer::exiter::exit_program("ERROR: Cannot open file $filename for reading", "convert_utf16_to_utf8"); + while ( $line = <IN> ) { + push @localfile, $line; + } + close( IN ); + + if ( open( OUT, ">:utf8", $filename ) ) + { + print OUT @localfile; + close(OUT); + } + + $savfilename = $filename . "_before.utf8"; + installer::systemactions::copy_one_file($filename, $savfilename); +} + +################################################################## +# Converting utf 8 file to utf 16 +################################################################## + +sub convert_utf8_to_utf16 +{ + my ( $filename ) = @_; + + my @localfile = (); + + my $savfilename = $filename . "_after.utf8"; + installer::systemactions::copy_one_file($filename, $savfilename); + + open( IN, "<:utf8", $filename ) || installer::exiter::exit_program("ERROR: Cannot open file $filename for reading", "convert_utf8_to_utf16"); + while ( $line = <IN> ) { + push @localfile, $line; + } + close( IN ); + + if ( open( OUT, ">:raw:encoding(UTF16-LE):crlf:utf8", $filename ) ) + { + print OUT @localfile; + close(OUT); + } + + $savfilename = $filename . "_after.utf16"; + installer::systemactions::copy_one_file($filename, $savfilename); +} + +################################################################## +# Converting text string to utf 16 +################################################################## + +sub convert_textstring_to_utf16 +{ + my ( $textstring, $localnsisdir, $shortfilename ) = @_; + + my $filename = $localnsisdir . $installer::globals::separator . $shortfilename; + my @filecontent = (); + push(@filecontent, $textstring); + installer::files::save_file($filename, \@filecontent); + convert_utf8_to_utf16($filename); + my $newfile = installer::files::read_file($filename); + my $utf16string = ""; + if ( ${$newfile}[0] ne "" ) { $utf16string = ${$newfile}[0]; } + + return $utf16string; +} + +################################################################## +# Windows: Copying NSIS language files to local nsis directory +################################################################## + +sub copy_and_translate_nsis_language_files +{ + my ($nsispath, $localnsisdir, $languagesarrayref, $allvariables) = @_; + + my $nlffilepath = $nsispath . $installer::globals::separator . "Contrib" . $installer::globals::separator . "Language\ files" . $installer::globals::separator; + my $nshfilepath = $nsispath . $installer::globals::separator . "Contrib" . $installer::globals::separator . "Modern\ UI" . $installer::globals::separator . "Language files" . $installer::globals::separator; + + my $infoline = ""; + + for ( my $i = 0; $i <= $#{$languagesarrayref}; $i++ ) + { + my $onelanguage = ${$languagesarrayref}[$i]; + my $nsislanguage = nsis_language_converter($onelanguage); + + # Copying the nlf file + my $sourcepath = $nlffilepath . $nsislanguage . "\.nlf"; + if ( ! -f $sourcepath ) { installer::exiter::exit_program("ERROR: Could not find nsis file: $sourcepath!", "copy_and_translate_nsis_language_files"); } + my $nlffilename = $localnsisdir . $installer::globals::separator . $nsislanguage . "_pack.nlf"; + if ( $^O =~ /cygwin/i ) { $nlffilename =~ s/\//\\/g; } + installer::systemactions::copy_one_file($sourcepath, $nlffilename); + + # Copying the nsh file + # In newer nsis versions, the nsh file is located next to the nlf file + $sourcepath = $nshfilepath . $nsislanguage . "\.nsh"; + if ( ! -f $sourcepath ) + { + # trying to find the nsh file next to the nlf file + $sourcepath = $nlffilepath . $nsislanguage . "\.nsh"; + if ( ! -f $sourcepath ) + { + installer::exiter::exit_program("ERROR: Could not find nsis file: $sourcepath!", "copy_and_translate_nsis_language_files"); + } + } + my $nshfilename = $localnsisdir . $installer::globals::separator . $nsislanguage . "_pack.nsh"; + if ( $^O =~ /cygwin/i ) { $nshfilename =~ s/\//\\/g; } + installer::systemactions::copy_one_file($sourcepath, $nshfilename); + + # Changing the macro name in nsh file: MUI_LANGUAGEFILE_BEGIN -> MUI_LANGUAGEFILE_PACK_BEGIN + my $nshfile = installer::files::read_file($nshfilename); + set_nsis_version($nshfile); + + if ( $installer::globals::unicodensis ) + { + $infoline = "This is Unicode NSIS!\n"; + push( @installer::globals::logfileinfo, $infoline); + convert_utf16_to_utf8($nshfilename); + convert_utf16_to_utf8($nlffilename); + $nshfile = installer::files::read_file($nshfilename); # read nsh file again + } + + replace_one_variable($nshfile, "MUI_LANGUAGEFILE_BEGIN", "MUI_LANGUAGEFILE_PACK_BEGIN"); + + # find the ulf file for translation + my $mlffile = get_translation_file($allvariables); + + # Translate the files + my $nlffile = installer::files::read_file($nlffilename); + translate_nsh_nlf_file($nshfile, $nlffile, $mlffile, $onelanguage, $nshfilename, $nlffilename, $nsislanguage); + + installer::files::save_file($nshfilename, $nshfile); + installer::files::save_file($nlffilename, $nlffile); + + if ( $installer::globals::unicodensis ) + { + convert_utf8_to_utf16($nshfilename); + convert_utf8_to_utf16($nlffilename); + } + } + +} + +################################################################## +# Windows: Including the nsis path into the nsi template +################################################################## + +sub put_nsis_path_into_template +{ + my ($templatefile, $nsisdir) = @_; + + replace_one_variable($templatefile, "NSISPATHPLACEHOLDER", $nsisdir); +} + +################################################################## +# Windows: Including the output path into the nsi template +################################################################## + +sub put_output_path_into_template +{ + my ($templatefile, $downloaddir) = @_; + + if ( $^O =~ /cygwin/i ) { $downloaddir =~ s/\//\\/g; } + + replace_one_variable($templatefile, "OUTPUTDIRPLACEHOLDER", $downloaddir); +} + +################################################################## +# Windows: Only allow specific code for nsis 2.0.4 or nsis 2.3.1 +################################################################## + +sub put_version_specific_code_into_template +{ + my ($templatefile) = @_; + + my $subst204 = ""; + my $subst231 = ""; + + if ( $installer::globals::nsis204 ) + { + $subst231 = ";"; + } + else + { + $subst204 = ";"; + } + + replace_one_variable($templatefile, "\#204\#", $subst204); + replace_one_variable($templatefile, "\#231\#", $subst231); +} + +################################################################## +# Windows: Finding the path to the nsis SDK +################################################################## + +sub get_path_to_nsis_sdk +{ + my $vol; + my $dir; + my $file; + my $nsispath = ""; + + if ( $ENV{'NSIS_PATH'} ) { + $nsispath = $ENV{'NSIS_PATH'}; + } elsif ( $ENV{'SOLARROOT'} ) { + $nsispath = $ENV{'SOLARROOT'} . $installer::globals::separator . "NSIS"; + } else { + # do we have nsis already in path ? + @paths = split(/:/, $ENV{'PATH'}); + foreach $paths (@paths) { + $path =~ s/[\/\\]+$//; # remove trailing slashes; + $nsispath = $paths . "/nsis"; + + if ( -x $nsispath ) { + $nsispath = $paths; + last; + } + else { + $nsispath = ""; + } + } + } + if ( $ENV{'NSISSDK_SOURCE'} ) { + installer::logger::print_warning( "NSISSDK_SOURCE is deprecated. use NSIS_PATH instead.\n" ); + $nsispath = $ENV{'NSISSDK_SOURCE'}; # overriding the NSIS SDK with NSISSDK_SOURCE + } + + if( ($^O =~ /cygwin/i) and $nsispath =~ /\\/ ) { + # We need a POSIX path for W32-4nt-cygwin-perl + $nsispath =~ s/\\/\\\\/g; + chomp( $nsispath = qx{cygpath -u "$nsispath"} ); + } + + if ( $nsispath eq "" ) + { + installer::logger::print_message( "... no Environment variable \"SOLARROOT\", \"NSIS_PATH\" or \"NSISSDK_SOURCE\" found and NSIS not found in path!", "get_path_to_nsis_sdk"); + } elsif ( ! -d $nsispath ) + { + installer::exiter::exit_program("ERROR: NSIS path $nsispath does not exist!", "get_path_to_nsis_sdk"); + } + + return $nsispath; +} + +################################################################## +# Windows: Executing NSIS to create the installation set +################################################################## + +sub call_nsis +{ + my ( $nsispath, $nsifile ) = @_; + + my $makensisexe = $nsispath . $installer::globals::separator . "makensis.exe"; + + installer::logger::print_message( "... starting $makensisexe ... \n" ); + + my $systemcall = "$makensisexe $nsifile |"; + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + my @nsisoutput = (); + + open (NSI, "$systemcall"); + while (<NSI>) {push(@nsisoutput, $_); } + close (NSI); + + my $returnvalue = $?; # $? contains the return value of the systemcall + + if ($returnvalue) + { + $infoline = "ERROR: $systemcall !\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + for ( my $i = 0; $i <= $#nsisoutput; $i++ ) { push( @installer::globals::logfileinfo, "$nsisoutput[$i]"); } + +} + +################################################################################# +# Replacing one variable in one files +################################################################################# + +sub replace_one_variable_in_translationfile +{ + my ($translationfile, $variable, $searchstring) = @_; + + for ( my $i = 0; $i <= $#{$translationfile}; $i++ ) + { + ${$translationfile}[$i] =~ s/\%$searchstring/$variable/g; + } +} + +################################################################################# +# Replacing the variables in the translation file +################################################################################# + +sub replace_variables +{ + my ($translationfile, $variableshashref) = @_; + + foreach $key (keys %{$variableshashref}) + { + my $value = $variableshashref->{$key}; + + # special handling for PRODUCTVERSION, if $allvariables->{'POSTVERSIONEXTENSION'} + if (( $key eq "PRODUCTVERSION" ) && ( $variableshashref->{'POSTVERSIONEXTENSION'} )) { $value = $value . " " . $variableshashref->{'POSTVERSIONEXTENSION'}; } + + replace_one_variable_in_translationfile($translationfile, $value, $key); + } +} + +######################################################### +# Getting the translation file for the nsis installer +######################################################### + +sub get_translation_file +{ + my ($allvariableshashref) = @_; + my $translationfilename = $installer::globals::idtlanguagepath . $installer::globals::separator . $installer::globals::nsisfilename; + if ( $installer::globals::unicodensis ) { $translationfilename = $translationfilename . ".uulf"; } + else { $translationfilename = $translationfilename . ".mlf"; } + if ( ! -f $translationfilename ) { installer::exiter::exit_program("ERROR: Could not find language file $translationfilename!", "get_translation_file"); } + my $translationfile = installer::files::read_file($translationfilename); + replace_variables($translationfile, $allvariableshashref); + + my $infoline = "Reading translation file: $translationfilename\n"; + push( @installer::globals::logfileinfo, $infoline); + + return $translationfile; +} + +#################################################### +# Removing english, if it was added before +#################################################### + +sub remove_english_for_nsis_installer +{ + my ($languagestringref, $languagesarrayref) = @_; + + # $$languagestringref =~ s/en-US_//; + # shift(@{$languagesarrayref}); + + @{$languagesarrayref} = ("en-US"); # only english for NSIS installer! +} + +#################################################### +# Creating link tree for upload +#################################################### + +sub create_link_tree +{ + my ($sourcedownloadfile, $destfilename, $versionstring) = @_; + + if ( ! $installer::globals::ooouploaddir ) { installer::exiter::exit_program("ERROR: Directory for OOo upload not defined!", "create_link_tree"); } + my $versiondir = $installer::globals::ooouploaddir . $installer::globals::separator . $versionstring; + my $infoline = "Directory for the link: $versiondir\n"; + push(@installer::globals::logfileinfo, $infoline); + + if ( ! -d $versiondir ) { installer::systemactions::create_directory_structure($versiondir); } + + # inside directory $versiondir all links have to be created + my $linkdestination = $versiondir . $installer::globals::separator . $destfilename; + + # If there is an older version of this file (link), it has to be removed + if ( -f $linkdestination ) { unlink($linkdestination); } + + $infoline = "Creating hard link from $sourcedownloadfile to $linkdestination\n"; + push(@installer::globals::logfileinfo, $infoline); + installer::systemactions::hardlink_one_file($sourcedownloadfile, $linkdestination); +} + +####################################################### +# Setting supported platform for Sun OpenOffice.org +# builds +####################################################### + +sub is_supported_platform +{ + my $is_supported = 0; + + if (( $installer::globals::islinuxrpmbuild ) || + ( $installer::globals::issolarissparcbuild ) || + ( $installer::globals::issolarisx86build ) || + ( $installer::globals::iswindowsbuild )) + { + $is_supported = 1; + } + + return $is_supported; +} + +#################################################### +# Creating download installation sets +#################################################### + +sub create_download_sets +{ + my ($installationdir, $includepatharrayref, $allvariableshashref, $downloadname, $languagestringref, $languagesarrayref) = @_; + + my $infoline = ""; + + my $force = 1; # print this message even in 'quiet' mode + installer::logger::print_message( "\n******************************************\n" ); + installer::logger::print_message( "... creating download installation set ...\n", $force ); + installer::logger::print_message( "******************************************\n" ); + + installer::logger::include_header_into_logfile("Creating download installation sets:"); + + # special handling for installation sets, to which english was added automatically + if ( $installer::globals::added_english ) { remove_english_for_nsis_installer($languagestringref, $languagesarrayref); } + + my $firstdir = $installationdir; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$firstdir); + + my $lastdir = $installationdir; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$lastdir); + + if ( $lastdir =~ /\./ ) { $lastdir =~ s/\./_download_inprogress\./ } + else { $lastdir = $lastdir . "_download_inprogress"; } + + # removing existing directory "_native_packed_inprogress" and "_native_packed_witherror" and "_native_packed" + + my $downloaddir = $firstdir . $lastdir; + if ( -d $downloaddir ) { installer::systemactions::remove_complete_directory($downloaddir); } + + my $olddir = $downloaddir; + $olddir =~ s/_inprogress/_witherror/; + if ( -d $olddir ) { installer::systemactions::remove_complete_directory($olddir); } + + $olddir = $downloaddir; + $olddir =~ s/_inprogress//; + if ( -d $olddir ) { installer::systemactions::remove_complete_directory($olddir); } + + # creating the new directory + + installer::systemactions::create_directory($downloaddir); + + $installer::globals::saveinstalldir = $downloaddir; + + # evaluating the name of the download file + + if ( $allvariableshashref->{'OOODOWNLOADNAME'} ) { $downloadname = set_download_filename($languagestringref, $allvariableshashref); } + else { $downloadname = resolve_variables_in_downloadname($allvariableshashref, $downloadname, $languagestringref); } + + if ( ! $installer::globals::iswindowsbuild ) # Unix specific part + { + + # getting the path of the getuid.so (only required for Solaris and Linux) + my $getuidlibrary = ""; + if (( $installer::globals::issolarisbuild ) || ( $installer::globals::islinuxbuild )) { $getuidlibrary = get_path_for_library($includepatharrayref); } + + if ( $allvariableshashref->{'OOODOWNLOADNAME'} ) + { + my $downloadfile = create_tar_gz_file_from_directory($installationdir, $getuidlibrary, $downloaddir, $downloadname); + } + else + { + # find and read setup script template + my $scriptfilename = "downloadscript.sh"; + my $scriptref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$scriptfilename, $includepatharrayref, 0); + if ($$scriptref eq "") { installer::exiter::exit_program("ERROR: Could not find script file $scriptfilename!", "create_download_sets"); } + my $scriptfile = installer::files::read_file($$scriptref); + + $infoline = "Found script file $scriptfilename: $$scriptref \n"; + push( @installer::globals::logfileinfo, $infoline); + + # add product name into script template + put_productname_into_script($scriptfile, $allvariableshashref); + + # replace linenumber in script template + put_linenumber_into_script($scriptfile); + + # create tar file + my $temporary_tarfile_name = $downloaddir . $installer::globals::separator . 'installset.tar'; + my $size = tar_package($installationdir, $temporary_tarfile_name, $getuidlibrary); + installer::exiter::exit_program("ERROR: Could not create tar file $temporary_tarfile_name!", "create_download_sets") unless $size; + + # calling sum to determine checksum and size of the tar file + my $sumout = call_sum($temporary_tarfile_name); + + # writing checksum and size into scriptfile + put_checksum_and_size_into_script($scriptfile, $sumout); + + # saving the script file + my $newscriptfilename = determine_scriptfile_name($downloadname); + $newscriptfilename = save_script_file($downloaddir, $newscriptfilename, $scriptfile); + + installer::logger::print_message( "... including installation set into $newscriptfilename ... \n" ); + # Append tar file to script + include_tar_into_script($newscriptfilename, $temporary_tarfile_name); + } + } + else # Windows specific part + { + my $localnsisdir = installer::systemactions::create_directories("nsis", $languagestringref); + # push(@installer::globals::removedirs, $localnsisdir); + + # find nsis in the system + my $nsispath = get_path_to_nsis_sdk(); + + if ( $nsispath eq "" ) { + # If nsis is not found just skip the rest of this function + # and do not create the NSIS file. + $infoline = "\nNo NSIS SDK found. Skipping the generation of NSIS file.\n"; + push(@installer::globals::logfileinfo, $infoline); + installer::logger::print_message( "... no NSIS SDK found. Skipping the generation of NSIS file ... \n" ); + return $downloaddir; + } + + # copy language files into nsis directory and translate them + copy_and_translate_nsis_language_files($nsispath, $localnsisdir, $languagesarrayref, $allvariableshashref); + + # find and read the nsi file template + my $templatefilename = "downloadtemplate.nsi"; + my $templateref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$templatefilename, $includepatharrayref, 0); + if ($$templateref eq "") { installer::exiter::exit_program("ERROR: Could not find nsi template file $templatefilename!", "create_download_sets"); } + my $templatefile = installer::files::read_file($$templateref); + + # add product name into script template + put_windows_productname_into_template($templatefile, $allvariableshashref); + put_banner_bmp_into_template($templatefile, $includepatharrayref, $allvariableshashref); + put_welcome_bmp_into_template($templatefile, $includepatharrayref, $allvariableshashref); + put_setup_ico_into_template($templatefile, $includepatharrayref, $allvariableshashref); + put_publisher_into_template($templatefile); + put_website_into_template($templatefile); + put_javafilename_into_template($templatefile, $allvariableshashref); + put_windows_productversion_into_template($templatefile, $allvariableshashref); + put_windows_productpath_into_template($templatefile, $allvariableshashref, $languagestringref, $localnsisdir); + put_outputfilename_into_template($templatefile, $downloadname); + put_filelist_into_template($templatefile, $installationdir); + put_language_list_into_template($templatefile, $languagesarrayref); + put_nsis_path_into_template($templatefile, $localnsisdir); + put_output_path_into_template($templatefile, $downloaddir); + put_version_specific_code_into_template($templatefile); + + my $nsifilename = save_script_file($localnsisdir, $templatefilename, $templatefile); + + installer::logger::print_message( "... created NSIS file $nsifilename ... \n" ); + + # starting the NSIS SDK to create the download file + call_nsis($nsispath, $nsifilename); + } + + return $downloaddir; +} + +#################################################### +# Creating OOo upload tree +#################################################### + +sub create_download_link_tree +{ + my ($downloaddir, $languagestringref, $allvariableshashref) = @_; + + my $infoline; + + installer::logger::print_message( "\n******************************************\n" ); + installer::logger::print_message( "... creating download hard link ...\n" ); + installer::logger::print_message( "******************************************\n" ); + + installer::logger::include_header_into_logfile("Creating download hard link:"); + installer::logger::include_timestamp_into_logfile("\nPerformance Info: Creating hard link, start"); + + if ( is_supported_platform() ) + { + my $versionstring = ""; + # Already defined $installer::globals::oooversionstring and $installer::globals::ooodownloadfilename ? + + if ( ! $installer::globals::oooversionstring ) { $versionstring = get_current_version(); } + else { $versionstring = $installer::globals::oooversionstring; } + + # Is $versionstring empty? If yes, there is nothing to do now. + + $infoline = "Version string is set to: $versionstring\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ( $versionstring ) + { + # Now the downloadfilename has to be set (if not already done) + my $destdownloadfilename = ""; + if ( ! $installer::globals::ooodownloadfilename ) { $destdownloadfilename = set_download_filename($languagestringref, $versionstring, $allvariableshashref); } + else { $destdownloadfilename = $installer::globals::ooodownloadfilename; } + + if ( $destdownloadfilename ) + { + $destdownloadfilename = $destdownloadfilename . $installer::globals::downloadfileextension; + + $infoline = "Setting destination download file name: $destdownloadfilename\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $sourcedownloadfile = $downloaddir . $installer::globals::separator . $installer::globals::downloadfilename; + + $infoline = "Setting source download file name: $sourcedownloadfile\n"; + push( @installer::globals::logfileinfo, $infoline); + + create_link_tree($sourcedownloadfile, $destdownloadfilename, $versionstring); + # my $md5sumoutput = call_md5sum($downloadfile); + # my $md5sum = get_md5sum($md5sumoutput); + + } + } + else + { + $infoline = "Version string is empty. Nothing to do!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + else + { + $infoline = "Platform not used for hard linking. Nothing to do!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + installer::logger::include_timestamp_into_logfile("Performance Info: Creating hard link, stop"); +} + +1; diff --git a/solenv/bin/modules/installer/downloadsigner.pm b/solenv/bin/modules/installer/downloadsigner.pm new file mode 100644 index 000000000000..d08a245f7a36 --- /dev/null +++ b/solenv/bin/modules/installer/downloadsigner.pm @@ -0,0 +1,377 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: remover.pm,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::downloadsigner; + +use installer::exiter; +use installer::files; +use installer::globals; +use installer::logger; +use installer::pathanalyzer; + +############################################ +# Parameter Operations +############################################ + +sub usage +{ + print <<Ende; +-------------------------------------------------------------------------------- +make_download V1.0 (c) Ingo Schmidt-Rosbiegal 2009 +The following parameter are needed: +-d: Full path to the file containing the follow-me info or to a directory + containing the follow-me info files. In the latter case, all follow-me + info files are evaluated. +The following parameter are optional: +-sign: Uses signing mechanism to sign installation sets +If \"-sign\" is set, the following two parameter are required: +-pfx: Full path to the pfx file +-pw: Full path to the file, containing the pfx password. + +Examples: + +Specifying an installation set (with "-d"): + +perl make_sign_and_download.pl -d <followmeinfofilename> +perl make_sign_and_download.pl -d <followmeinfofilename> + -sign + -pfx <pfxfilename> + -pw <passwordfilename> + +or without specifying an installation set: + +perl make_sign_and_download.pl -sign + -pfx <pfxfilename> + -pw <passwordfilename> +-------------------------------------------------------------------------------- +Ende + exit(-1); +} + +##################################### +# Reading parameter +##################################### + +sub getparameter +{ + # installer::logger::print_message("Checking parameter"); + + while ( $#ARGV >= 0 ) + { + my $param = shift(@ARGV); + + if ($param eq "-d") { $installer::globals::followmeinfofilename = shift(@ARGV); } + elsif ($param eq "-pw") { $installer::globals::pwfile = shift(@ARGV); } + elsif ($param eq "-pfx") { $installer::globals::pfxfile = shift(@ARGV); } + elsif ($param eq "-sign") { $installer::globals::dosign = 1; } + else + { + installer::logger::print_error( "unknown parameter: $param" ); + usage(); + exit(-1); + } + } +} + +##################################### +# Controlling required parameter +##################################### + +sub checkparameter +{ + if ( $installer::globals::followmeinfofilename eq "" ) + { + installer::logger::print_error( "Error: Required parameter is missing: -d\n" ); + usage(); + exit(-1); + } + + if ( $installer::globals::dosign ) + { + # -pfx and -pw have to be set + if ( $installer::globals::pfxfile eq "" ) + { + installer::logger::print_error( "Error: If \"-sign\" is set, a pfx file has to be specified: -pfx\n" ); + usage(); + exit(-1); + } + + # -pfx and -pw have to be set + if ( $installer::globals::pwfile eq "" ) + { + installer::logger::print_error( "Error: If \"-sign\" is set, a password file has to be specified: -pw\n" ); + usage(); + exit(-1); + } + + # and both files have to exist + if ( ! -f $installer::globals::pfxfile ) + { + installer::logger::print_error( "Error: pfx file \"$installer::globals::pfxfile\" does not exist.\n" ); + usage(); + exit(-1); + } + + if ( ! -f $installer::globals::pwfile ) + { + installer::logger::print_error( "Error: Password file \"$installer::globals::pwfile\" does not exist (-pw).\n" ); + usage(); + exit(-1); + } + } +} + +############################################# +# Setting the name of the log file +############################################# + +sub setlogfilename +{ + if ( $installer::globals::dosign ) { $installer::globals::logfilename = "sign_and_download_" . $installer::globals::logfilename; } + else { $installer::globals::logfilename = "download_" . $installer::globals::logfilename; } + # reset the log file + @installer::globals::logfileinfo = (); +} + +######################################################### +# Checking, if this is a task in a cws or +# on the master. Simple check of naming schema: +# CWS: follow_me_DEV300_m40_de.log +# Master: follow_me_4_DEV300_m40_en-US.log +######################################################### + +sub check_cws_build +{ + my ( $filename ) = @_; + + my $iscws = 1; + + if ( $filename =~ /follow_me_\d+_/ ) { $iscws = 0; } + # if ( $filename =~ /log_\d+_/ ) { $iscws = 0; } + + return $iscws; +} + +######################################################### +# Reading a specific key from a follow-me file +######################################################### + +sub get_property_from_file +{ + my ($followmefile, $key) = @_; + + my $value = ""; + + my $filecontent = installer::files::read_file($followmefile); + + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if ( ${$filecontent}[$i] =~ /^\s*\Q$key\E\s*\:\s*(.*?)\s*$/ ) + { + $value = $1; + last; + } + } + + return $value; +} + +######################################################### +# Publishing the content of the product list +######################################################### + +sub publishproductlist +{ + my ($infofilelist) = @_; + + installer::logger::print_message( "\n... found products: ...\n" ); + + for ( my $i = 0; $i <= $#{$infofilelist}; $i++ ) + { + my $onefile = ${$infofilelist}[$i]; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$onefile); + installer::logger::print_message( "...... $onefile ...\n" ); + } + + installer::logger::print_message( "\n" ); +} + +######################################################### +# Filtering all files, that have correct minor +# and work stamp. +# Master: follow_me_4_DEV300_m40_en-US.log +######################################################### + +sub filter_all_files_with_correct_settings +{ + my ($allfollowmefiles) = @_; + + my @allfiles = (); + my @allfiles2 = (); + my $maxhash = (); + + my $minor = ""; + my $workstamp = ""; + + if ( $ENV{'WORK_STAMP'} ) { $workstamp = $ENV{'WORK_STAMP'}; } + if ( $ENV{'UPDMINOR'} ) { $minor = $ENV{'UPDMINOR'}; } + + if ( $minor eq "" ) { installer::exiter::exit_program("ERROR: Environment variable \"UPDMINOR\" not set!", "filter_all_files_with_correct_settings"); } + if ( $workstamp eq "" ) { installer::exiter::exit_program("ERROR: Environment variable \"WORK_STAMP\" not set!", "filter_all_files_with_correct_settings"); } + + foreach my $onefile ( @{$allfollowmefiles} ) + { + if (( $onefile =~ /_\Q$minor\E_/i ) && ( $onefile =~ /_\Q$workstamp\E_/i )) + { + push(@allfiles, $onefile); + + # also collecting maximum hash + + if ( $onefile =~ /follow_me_(\d+)_\Q$workstamp\E_\Q$minor\E_([-\w]+)\.log\s*$/i ) + { + my $sequence = $1; + my $lang = $2; + + if (( ! exists($maxhash{$lang})) || ( $maxhash{$lang} < $sequence )) { $maxhash{$lang} = $sequence; } + } + } + } + + # second run, because of sequence numbers + + foreach my $onefile ( @allfiles ) + { + if ( $onefile =~ /follow_me_(\d+)_\Q$workstamp\E_\Q$minor\E_([-\w]+)\.log\s*$/i ) + { + my $sequence = $1; + my $lang = $2; + + if ( $sequence == $maxhash{$lang} ) { push(@allfiles2, $onefile); } + } + } + + return ( \@allfiles2 ); +} + +######################################################### +# Creating a list of products, that need to be signed +# or for which download sets need to be created. +######################################################### + +sub createproductlist +{ + # If "-d" specifies an installation set, there is only one product + + my @infofilelist = (); + + if ( -f $installer::globals::followmeinfofilename ) + { + push(@infofilelist, $installer::globals::followmeinfofilename); + } + elsif ( -d $installer::globals::followmeinfofilename ) + { + installer::logger::print_message( "\n... reading directory: $installer::globals::followmeinfofilename ...\n" ); + $installer::globals::followmeinfofilename =~ s/$installer::globals::separator\s*$//; + my $allfollowmefiles = installer::systemactions::find_file_with_file_extension("log", $installer::globals::followmeinfofilename); + + if ( ! ( $#{$allfollowmefiles} > -1 )) + { + installer::logger::print_error( "Error: Nothing to do! No follow-me file in directory \"$installer::globals::followmeinfofilename\"!.\n" ); + usage(); + exit(-1); + } + + # Collect all possible installation sets + # CWS: All installation sets + # Master: All installation sets with same major, minor and buildid. Additionally using the highest number. + + my $iscws = check_cws_build(${$allfollowmefiles}[0]); + + if ( $iscws ) + { + # Simply read all follow-me files and check existence of installation sets + foreach my $onefile ( @{$allfollowmefiles} ) + { + my $fullfilename = $installer::globals::followmeinfofilename . $installer::globals::separator . $onefile; + my $installdir = get_property_from_file($fullfilename, "finalinstalldir"); + if (( $installdir ne "" ) && ( -d $installdir )) { push(@infofilelist, $fullfilename); } + } + } + else + { + $allfollowmefiles = filter_all_files_with_correct_settings($allfollowmefiles); + + foreach my $onefile ( @{$allfollowmefiles} ) + { + my $fullfilename = $installer::globals::followmeinfofilename . $installer::globals::separator . $onefile; + # Check, if installation set still exists + my $installdir = get_property_from_file($fullfilename, "finalinstalldir"); + if (( $installdir ne "" ) && ( -d $installdir )) { push(@infofilelist, $fullfilename); } + } + } + + # Checking, if there is content in the list + if ( ! ( $#infofilelist > -1 )) + { + installer::logger::print_error( "Error: Nothing to do! No installation set found for follow-me files in directory \"$installer::globals::followmeinfofilename\"!.\n" ); + usage(); + exit(-1); + } + } + else + { + installer::logger::print_error( "Error: Nothing to do! \"$installer::globals::followmeinfofilename\" is no file and no directory (-d).\n" ); + usage(); + exit(-1); + } + + return \@infofilelist; +} + +############################################# +# Logging the content of the download hash +############################################# + +sub logfollowmeinfohash +{ + my ( $followmehash ) = @_; + + print "\n*****************************************\n"; + print "Content of follow-me info file:\n"; + print "finalinstalldir: $followmehash->{'finalinstalldir'}\n"; + print "downloadname: $followmehash->{'downloadname'}\n"; + print "languagestring: $followmehash->{'languagestring'}\n"; + foreach my $lang ( @{$followmehash->{'languagesarray'}} ) { print "languagesarray: $lang\n"; } + foreach my $path ( @{$followmehash->{'includepatharray'}} ) { print "includepatharray: $path"; } + foreach my $key ( sort keys %{$followmehash->{'allvariableshash'}} ) { print "allvariableshash: $key : $followmehash->{'allvariableshash'}->{$key}\n"; } +} + +1; diff --git a/solenv/bin/modules/installer/environment.pm b/solenv/bin/modules/installer/environment.pm new file mode 100644 index 000000000000..9073226ad277 --- /dev/null +++ b/solenv/bin/modules/installer/environment.pm @@ -0,0 +1,116 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: environment.pm,v $ +# +# $Revision: 1.14 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::environment; + +use installer::exiter; +use installer::globals; + +###################################################### +# Create path variables from environment variables +###################################################### + +sub create_pathvariables +{ + my ($environment) = @_; + + my %variables = (); + + # The following variables are needed in the path file list + # solarpath, solarenvpath, solarcommonpath, os, osdef, pmiscpath + + my $solarpath = $environment->{'SOLARVERSION'} . $installer::globals::separator . $installer::globals::compiler . $installer::globals::productextension; + $variables{'solarpath'} = $solarpath; + + my $solarcommonpath = $environment->{'SOLARVERSION'} . $installer::globals::separator . "common" . $installer::globals::productextension; + # my $solarcommonpath = $environment->{'SOLARVERSION'} . $installer::globals::separator . $environment->{'COMMON_OUTDIR'} . $installer::globals::productextension; + $variables{'solarcommonpath'} = $solarcommonpath; + + my $osdef = lc($environment->{'GUI'}); + $variables{'osdef'} = $osdef; + + $variables{'os'} = $installer::globals::compiler; + + my $solarenvpath = ""; + + if ( $ENV{'SO_PACK'} ) { $solarenvpath = $ENV{'SO_PACK'}; } + # overriding with STAR_INSTPATH, if set + if ( $ENV{'STAR_INSTPATH'} ) { $solarenvpath = $ENV{'STAR_INSTPATH'}; } + + $variables{'solarenvpath'} = $solarenvpath; + + my $localpath = $environment->{'LOCAL_OUT'}; + $variables{'localpath'} = $localpath; + + my $localcommonpath = $environment->{'LOCAL_COMMON_OUT'}; + $variables{'localcommonpath'} = $localcommonpath; + + my $platformname = $environment->{'OUTPATH'}; + $variables{'platformname'} = $platformname; + + return \%variables; +} + +################################################## +# Setting some fundamental global variables. +# All these variables can be overwritten +# by parameters. +################################################## + +sub set_global_environment_variables +{ + my ( $environment ) = @_; + + $installer::globals::build = $environment->{'WORK_STAMP'}; + # $installer::globals::minor = $environment->{'UPDMINOR'}; + $installer::globals::compiler = $environment->{'OUTPATH'}; + + if ( $ENV{'UPDMINOR'} ) { $installer::globals::minor = $ENV{'UPDMINOR'}; } + if ( $ENV{'LAST_MINOR'} ) { $installer::globals::lastminor = $ENV{'LAST_MINOR'}; } + + if ( $ENV{'PROEXT'} ) { $installer::globals::pro = 1; } + if ( $ENV{'SOLAR_JAVA'} ) { $installer::globals::solarjava = 1; } + if ( $ENV{'JDKLIB'} ) { $installer::globals::jdklib = $ENV{'JDKLIB'}; } + if ( $ENV{'JREPATH'} ) { $installer::globals::jrepath = $ENV{'JREPATH'}; } + + if ( $ENV{'VERBOSE'} && ( (lc $ENV{'VERBOSE'}) eq "false" ) ) { $installer::globals::quiet = 1; } + if ( $ENV{'PREPARE_WINPATCH'} ) { $installer::globals::prepare_winpatch = 1; } + if ( $ENV{'PREVIOUS_IDT_DIR'} ) { $installer::globals::previous_idt_dir = $ENV{'PREVIOUS_IDT_DIR'}; } + if ( $ENV{'LOCALINSTALLDIR'} ) { $installer::globals::localinstalldir = $ENV{'LOCALINSTALLDIR'}; } + if ( $ENV{'LOCALUNPACKDIR'} ) { $installer::globals::localunpackdir = $ENV{'LOCALUNPACKDIR'}; } + if ( $ENV{'MAX_LANG_LENGTH'} ) { $installer::globals::max_lang_length = $ENV{'MAX_LANG_LENGTH'}; } + + if ( $ENV{'SOLAR_JAVA'} ) { $installer::globals::solarjavaset = 1; } + + if ( $ENV{'RPM'} ) { $installer::globals::rpm = $ENV{'RPM'}; } +} + +1; diff --git a/solenv/bin/modules/installer/epmfile.pm b/solenv/bin/modules/installer/epmfile.pm new file mode 100644 index 000000000000..497479380331 --- /dev/null +++ b/solenv/bin/modules/installer/epmfile.pm @@ -0,0 +1,3323 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: epmfile.pm,v $ +# +# $Revision: 1.87 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::epmfile; + +use Cwd; +use installer::converter; +use installer::existence; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::logger; +use installer::packagelist; +use installer::pathanalyzer; +use installer::remover; +use installer::scriptitems; +use installer::systemactions; +use installer::worker; +use POSIX; + +############################################################################ +# Reading the package map to find Solaris package names for +# the corresponding abbreviations +############################################################################ + +sub read_packagemap +{ + my ($allvariables, $includepatharrayref, $languagesarrayref) = @_; + + my $packagemapname = ""; + if ( $allvariables->{'PACKAGEMAP'} ) { $packagemapname = $allvariables->{'PACKAGEMAP'}; } + if ( $packagemapname eq "" ) { installer::exiter::exit_program("ERROR: Property PACKAGEMAP must be defined!", "read_packagemap"); } + + my $infoline = "\n\nCollected abbreviations and package names:\n"; + push(@installer::globals::logfileinfo, $infoline); + + # Can be a comma separated list. All files have to be found in include pathes + my $allpackagemapnames = installer::converter::convert_stringlist_into_hash(\$packagemapname, ","); + foreach my $onepackagemapname ( keys %{$allpackagemapnames} ) + { + my $packagemapref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$onepackagemapname, $includepatharrayref, 0); + + if ( $$packagemapref eq "" ) { installer::exiter::exit_program("ERROR: Could not find package map file \"$onepackagemapname\" (propery PACKAGEMAP)!", "read_packagemap"); } + + my $packagemapcontent = installer::files::read_file($$packagemapref); + + for ( my $i = 0; $i <= $#{$packagemapcontent}; $i++ ) + { + my $line = ${$packagemapcontent}[$i]; + + if ( $line =~ /^\s*\#/ ) { next; } # comment line + if ( $line =~ /^\s*$/ ) { next; } # empty line + + if ( $line =~ /^\s*(.*?)\t(.*?)\s*$/ ) + { + my $abbreviation = $1; + my $packagename = $2; + installer::packagelist::resolve_packagevariables(\$abbreviation, $allvariables, 0); + installer::packagelist::resolve_packagevariables(\$packagename, $allvariables, 0); + + # Special handling for language strings %LANGUAGESTRING + + if (( $abbreviation =~ /\%LANGUAGESTRING/ ) || ( $packagename =~ /\%LANGUAGESTRING/ )) + { + foreach my $onelang ( @{$languagesarrayref} ) + { + my $local_abbreviation = $abbreviation; + my $local_packagename = $packagename; + $local_abbreviation =~ s/\%LANGUAGESTRING/$onelang/g; + $local_packagename =~ s/\%LANGUAGESTRING/$onelang/g; + + # Logging all abbreviations and packagenames + $infoline = "$onelang : $local_abbreviation : $local_packagename\n"; + push(@installer::globals::logfileinfo, $infoline); + + if ( exists($installer::globals::dependfilenames{$local_abbreviation}) ) + { + installer::exiter::exit_program("ERROR: Packagename for Solaris package $local_abbreviation already defined ($installer::globals::dependfilenames{$local_abbreviation})!", "read_packagemap"); + } + else + { + $installer::globals::dependfilenames{$local_abbreviation} = $local_packagename; + } + } + } + else + { + # Logging all abbreviations and packagenames + $infoline = "$abbreviation : $packagename\n"; + push(@installer::globals::logfileinfo, $infoline); + + if ( exists($installer::globals::dependfilenames{$abbreviation}) ) + { + installer::exiter::exit_program("ERROR: Packagename for Solaris package $abbreviation already defined ($installer::globals::dependfilenames{$abbreviation})!", "read_packagemap"); + } + else + { + $installer::globals::dependfilenames{$abbreviation} = $packagename; + } + } + } + else + { + my $errorline = $i + 1; + installer::exiter::exit_program("ERROR: Wrong syntax in file \"$onepackagemapname\" (line $errorline)!", "read_packagemap"); + } + } + } + + $infoline = "\n\n"; + push(@installer::globals::logfileinfo, $infoline); + +} + +############################################################################ +# The header file contains the strings for the epm header in all languages +############################################################################ + +sub get_string_from_headerfile +{ + my ($searchstring, $language, $fileref) = @_; + + my $returnstring = ""; + my $onestring = ""; + my $englishstring = ""; + my $foundblock = 0; + my $foundstring = 0; + my $foundenglishstring = 0; + my $englishidentifier = "01"; + + $searchstring = "[" . $searchstring . "]"; + + for ( my $i = 0; $i <= $#{$fileref}; $i++ ) + { + my $line = ${$fileref}[$i]; + + if ( $line =~ /^\s*\Q$searchstring\E\s*$/ ) + { + $foundblock = 1; + my $counter = $i + 1; + + $line = ${$fileref}[$counter]; + + # Beginning of the next block oder Dateiende + + while ((!($line =~ /^\s*\[\s*\w+\s*\]\s*$/ )) && ( $counter <= $#{$fileref} )) + { + if ( $line =~ /^\s*\Q$language\E\s+\=\s*\"(.*)\"\s*$/ ) + { + $onestring = $1; + $foundstring = 1; + last; + } + + if ( $line =~ /^\s*\Q$englishidentifier\E\s+\=\s*\"(.*)\"\s*$/ ) + { + $englishstring = $1; + $foundenglishstring = 1; + } + + $counter++; + $line = ${$fileref}[$counter]; + } + } + } + + if ( $foundstring ) + { + $returnstring = $onestring; + } + else + { + if ( $foundenglishstring ) + { + $returnstring = $englishstring; + } + else + { + installer::exiter::exit_program("ERROR: No string found for $searchstring in epm header file (-h)", "get_string_from_headerfile"); + } + } + + return \$returnstring; +} + +########################################################## +# Filling the epm file with directories, files and links +########################################################## + +sub put_directories_into_epmfile +{ + my ($directoriesarrayref, $epmfileref, $allvariables, $packagerootpath) = @_; + my $group = "bin"; + + if ( $installer::globals::islinuxbuild ) + { + $group = "root"; + } + + for ( my $i = 0; $i <= $#{$directoriesarrayref}; $i++ ) + { + my $onedir = ${$directoriesarrayref}[$i]; + my $dir = ""; + + if ( $onedir->{'Dir'} ) { $dir = $onedir->{'Dir'}; } + + # if (!($dir =~ /\bPREDEFINED_/ )) + if ((!($dir =~ /\bPREDEFINED_/ )) || ( $dir =~ /\bPREDEFINED_PROGDIR\b/ )) + { + my $hostname = $onedir->{'HostName'}; + + # not including simple directory "/opt" + # if (( $allvariables->{'SETSTATICPATH'} ) && ( $hostname eq $packagerootpath )) { next; } + + my $line = "d 755 root $group $hostname -\n"; + + push(@{$epmfileref}, $line) + } + } +} + +sub put_files_into_epmfile +{ + my ($filesinproductarrayref, $epmfileref) = @_; + + for ( my $i = 0; $i <= $#{$filesinproductarrayref}; $i++ ) + { + my $onefile = ${$filesinproductarrayref}[$i]; + + my $unixrights = $onefile->{'UnixRights'}; + my $destination = $onefile->{'destination'}; + my $sourcepath = $onefile->{'sourcepath'}; + + my $filetype = "f"; + my $styles = ""; + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } + if ( $styles =~ /\bCONFIGFILE\b/ ) { $filetype = "c"; } + + my $group = "bin"; + if ( $installer::globals::islinuxbuild ) { $group = "root"; } + if (( $installer::globals::issolarisbuild ) && ( $onefile->{'SolarisGroup'} )) { $group = $onefile->{'SolarisGroup'}; } + + my $line = "$filetype $unixrights root $group $destination $sourcepath\n"; + + push(@{$epmfileref}, $line); + } +} + +sub put_links_into_epmfile +{ + my ($linksinproductarrayref, $epmfileref) = @_; + my $group = "bin"; + + if ( $installer::globals::islinuxbuild ) + { + $group = "root"; + } + + + for ( my $i = 0; $i <= $#{$linksinproductarrayref}; $i++ ) + { + my $onelink = ${$linksinproductarrayref}[$i]; + my $destination = $onelink->{'destination'}; + my $destinationfile = $onelink->{'destinationfile'}; + + my $line = "l 000 root $group $destination $destinationfile\n"; + + push(@{$epmfileref}, $line) + } +} + +sub put_unixlinks_into_epmfile +{ + my ($unixlinksinproductarrayref, $epmfileref) = @_; + my $group = "bin"; + + if ( $installer::globals::islinuxbuild ) { $group = "root"; } + + for ( my $i = 0; $i <= $#{$unixlinksinproductarrayref}; $i++ ) + { + my $onelink = ${$unixlinksinproductarrayref}[$i]; + my $destination = $onelink->{'destination'}; + my $target = $onelink->{'Target'}; + + my $line = "l 000 root $group $destination $target\n"; + + push(@{$epmfileref}, $line) + } +} + +############################################### +# Creating epm header file +############################################### + +sub create_epm_header +{ + my ($variableshashref, $filesinproduct, $languagesref, $onepackage) = @_; + + my @epmheader = (); + + my ($licensefilename, $readmefilename); + + my $foundlicensefile = 0; + my $foundreadmefile = 0; + + my $line = ""; + my $infoline = ""; + + # %product OpenOffice.org Software + # %version 2.0 + # %description A really great software + # %copyright 1999-2003 by OOo + # %vendor OpenOffice.org + # %license /test/replace/01/LICENSE01 + # %readme /test/replace/01/README01 + # %requires foo + # %provides bar + + # The first language in the languages array determines the language of license and readme file + + my $searchlanguage = ${$languagesref}[0]; + + # using the description for the %product line in the epm list file + + my $productnamestring = $onepackage->{'description'}; + installer::packagelist::resolve_packagevariables(\$productnamestring, $variableshashref, 0); + if ( $variableshashref->{'PRODUCTEXTENSION'} ) { $productnamestring = $productnamestring . " " . $variableshashref->{'PRODUCTEXTENSION'}; } + + $line = "%product" . " " . $productnamestring . "\n"; + push(@epmheader, $line); + + # Determining the release version + # This release version has to be listed in the line %version : %version versionnumber releasenumber + + # if ( $variableshashref->{'PACKAGEVERSION'} ) { $installer::globals::packageversion = $variableshashref->{'PACKAGEVERSION'}; } + if ( ! $onepackage->{'packageversion'} ) { installer::exiter::exit_program("ERROR: No packageversion defined for package: $onepackage->{'module'}!", "create_epm_header"); } + $installer::globals::packageversion = $onepackage->{'packageversion'}; + installer::packagelist::resolve_packagevariables(\$installer::globals::packageversion, $variableshashref, 0); + if ( $variableshashref->{'PACKAGEREVISION'} ) { $installer::globals::packagerevision = $variableshashref->{'PACKAGEREVISION'}; } + + $line = "%version" . " " . $installer::globals::packageversion . "\n"; + push(@epmheader, $line); + + $line = "%release" . " " . $installer::globals::packagerevision . "\n"; + if ( $installer::globals::islinuxrpmbuild ) { $line = "%release" . " " . $installer::globals::buildid . "\n"; } + push(@epmheader, $line); + + # Description, Copyright and Vendor are multilingual and are defined in + # the string file for the header file ($headerfileref) + + my $descriptionstring = $onepackage->{'description'}; + installer::packagelist::resolve_packagevariables(\$descriptionstring, $variableshashref, 0); + $line = "%description" . " " . $descriptionstring . "\n"; + push(@epmheader, $line); + + my $copyrightstring = $onepackage->{'copyright'}; + installer::packagelist::resolve_packagevariables(\$copyrightstring, $variableshashref, 0); + $line = "%copyright" . " " . $copyrightstring . "\n"; + push(@epmheader, $line); + + my $vendorstring = $onepackage->{'vendor'}; + installer::packagelist::resolve_packagevariables(\$vendorstring, $variableshashref, 0); + $line = "%vendor" . " " . $vendorstring . "\n"; + push(@epmheader, $line); + + # License and Readme file can be included automatically from the file list + + if ( $installer::globals::iswindowsbuild ) + { + $licensefilename = "license.txt"; + $readmefilename = "readme.txt"; + } + else + { + $licensefilename = "LICENSE"; + $readmefilename = "README"; + } + + if (( $installer::globals::languagepack ) # in language packs the files LICENSE and README are removed, because they are not language specific + || ( $variableshashref->{'NO_README_IN_ROOTDIR'} )) + { + if ( $installer::globals::iswindowsbuild ) + { + $licensefilename = "license_$searchlanguage.txt"; + $readmefilename = "readme_$searchlanguage.txt"; + } + else + { + $licensefilename = "LICENSE_$searchlanguage"; + $readmefilename = "README_$searchlanguage"; + } + } + + my $license_in_package_defined = 0; + + if ( $installer::globals::issolarisbuild ) + { + if ( $onepackage->{'solariscopyright'} ) + { + $licensefilename = $onepackage->{'solariscopyright'}; + $license_in_package_defined = 1; + } + } + + # searching for and readme file + + for ( my $i = 0; $i <= $#{$filesinproduct}; $i++ ) + { + my $onefile = ${$filesinproduct}[$i]; + my $filename = $onefile->{'Name'}; + if ( $filename eq $readmefilename ) + { + $foundreadmefile = 1; + $line = "%readme" . " " . $onefile->{'sourcepath'} . "\n"; + push(@epmheader, $line); + last; + } + } + + # searching for and license file + + if ( $license_in_package_defined ) + { + my $fileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$licensefilename, "" , 0); + + if ( $$fileref eq "" ) { installer::exiter::exit_program("ERROR: Could not find license file $licensefilename!", "create_epm_header"); } + + # Special handling to add the content of the file "license_en-US" to the solaris copyrightfile + if ( $installer::globals::issolarispkgbuild ) + { + if ( ! $installer::globals::englishlicenseset ) { installer::worker::set_english_license() } + + # The location for the new file + my $languagestring = ""; + for ( my $i = 0; $i <= $#{$languagesref}; $i++ ) { $languagestring = $languagestring . "_" . ${$languagesref}[$i]; } + $languagestring =~ s/^\s*_//; + + my $copyrightdir = installer::systemactions::create_directories("copyright", \$languagestring); + + my $copyrightfile = installer::files::read_file($$fileref); + + # Adding license content to copyright file + push(@{$copyrightfile}, "\n"); + for ( my $i = 0; $i <= $#{$installer::globals::englishlicense}; $i++ ) { push(@{$copyrightfile}, ${$installer::globals::englishlicense}[$i]); } + + # New destination for $$fileref + $$fileref = $copyrightdir . $installer::globals::separator . "solariscopyrightfile_" . $onepackage->{'module'}; + if ( -f $$fileref ) { unlink $$fileref; } + installer::files::save_file($$fileref, $copyrightfile); + } + + $infoline = "Using license file: \"$$fileref\"!\n"; + push(@installer::globals::logfileinfo, $infoline); + + $foundlicensefile = 1; + $line = "%license" . " " . $$fileref . "\n"; + push(@epmheader, $line); + } + else + { + for ( my $i = 0; $i <= $#{$filesinproduct}; $i++ ) + { + my $onefile = ${$filesinproduct}[$i]; + my $filename = $onefile->{'Name'}; + + if ( $filename eq $licensefilename ) + { + $foundlicensefile = 1; + $line = "%license" . " " . $onefile->{'sourcepath'} . "\n"; + push(@epmheader, $line); + last; + } + } + } + + if (!($foundlicensefile)) + { + installer::exiter::exit_program("ERROR: Could not find license file $licensefilename", "create_epm_header"); + } + + if (!($foundreadmefile)) + { + installer::exiter::exit_program("ERROR: Could not find readme file $readmefilename", "create_epm_header"); + } + + # including %replaces + + my $replaces = ""; + + if (( $installer::globals::issolarispkgbuild ) && ( ! $installer::globals::patch )) + { + $replaces = "solarisreplaces"; # the name in the packagelist + } + elsif (( $installer::globals::islinuxbuild ) && ( ! $installer::globals::patch )) + { + $replaces = "linuxreplaces"; # the name in the packagelist + } + + if (( $replaces ) && ( ! $installer::globals::patch )) + { + if ( $onepackage->{$replaces} ) + { + my $replacesstring = $onepackage->{$replaces}; + + my $allreplaces = installer::converter::convert_stringlist_into_array(\$replacesstring, ","); + + for ( my $i = 0; $i <= $#{$allreplaces}; $i++ ) + { + my $onereplaces = ${$allreplaces}[$i]; + $onereplaces =~ s/\s*$//; + installer::packagelist::resolve_packagevariables(\$onereplaces, $variableshashref, 1); + if ( $installer::globals::linuxlinkrpmprocess ) { $onereplaces = $onereplaces . "u"; } + $line = "%replaces" . " " . $onereplaces . "\n"; + push(@epmheader, $line); + + # Force the openofficeorg packages to get removed, + # see http://www.debian.org/doc/debian-policy/ch-relationships.html + # 7.5.2 Replacing whole packages, forcing their removal + + if ( $installer::globals::debian ) + { + $line = "%incompat" . " " . $onereplaces . "\n"; + push(@epmheader, $line); + } + } + + if ( $installer::globals::debian && $variableshashref->{'UNIXPRODUCTNAME'} eq 'openoffice.org' ) + { + $line = "%provides" . " openoffice.org-unbundled\n"; + push(@epmheader, $line); + $line = "%incompat" . " openoffice.org-bundled\n"; + push(@epmheader, $line); + } + } + } + + # including the directives for %requires and %provides + + my $provides = ""; + my $requires = ""; + + if ( $installer::globals::issolarispkgbuild ) + { + $provides = "solarisprovides"; # the name in the packagelist + $requires = "solarisrequires"; # the name in the packagelist + } + elsif ( $installer::globals::isfreebsdpkgbuild ) + { + $provides = "freebsdprovides"; # the name in the packagelist + $requires = "freebsdrequires"; # the name in the packagelist + } + elsif (( $installer::globals::islinuxrpmbuild ) && + ( $installer::globals::patch ) && + ( exists($onepackage->{'linuxpatchrequires'}) )) + { + $provides = "provides"; # the name in the packagelist + $requires = "linuxpatchrequires"; # the name in the packagelist + } + else + { + $provides = "provides"; # the name in the packagelist + $requires = "requires"; # the name in the packagelist + } + + # if ( $installer::globals::patch ) + # { + # $onepackage->{$provides} = ""; + # $onepackage->{$requires} = ""; + # } + + if ( $onepackage->{$provides} ) + { + my $providesstring = $onepackage->{$provides}; + + my $allprovides = installer::converter::convert_stringlist_into_array(\$providesstring, ","); + + for ( my $i = 0; $i <= $#{$allprovides}; $i++ ) + { + my $oneprovides = ${$allprovides}[$i]; + $oneprovides =~ s/\s*$//; + installer::packagelist::resolve_packagevariables(\$oneprovides, $variableshashref, 1); + if ( $installer::globals::linuxlinkrpmprocess ) { $oneprovides = $oneprovides . "u"; } + $line = "%provides" . " " . $oneprovides . "\n"; + push(@epmheader, $line); + } + } + + if ( $onepackage->{$requires} ) + { + my $requiresstring = $onepackage->{$requires}; + + if ( $installer::globals::add_required_package ) { $requiresstring = $requiresstring . "," . $installer::globals::add_required_package; } + + # The requires string can contain the separator "," in the names (descriptions) of the packages + # (that are required for Solaris depend files). Therefore "," inside such a description has to + # masked with a backslash. + # This masked separator need to be found and replaced, before the stringlist is converted into an array. + # This replacement has to be turned back after the array is created. + + my $replacementstring = "COMMAREPLACEMENT"; + $requiresstring = installer::converter::replace_masked_separator($requiresstring, ",", "$replacementstring"); + + my $allrequires = installer::converter::convert_stringlist_into_array(\$requiresstring, ","); + + installer::converter::resolve_masked_separator($allrequires, ",", $replacementstring); + + for ( my $i = 0; $i <= $#{$allrequires}; $i++ ) + { + my $onerequires = ${$allrequires}[$i]; + $onerequires =~ s/\s*$//; + installer::packagelist::resolve_packagevariables(\$onerequires, $variableshashref, 0); + + # Special handling for Solaris. In depend files, the names of the packages are required, not + # only the abbreviation. Therefore there is a special syntax for names in packagelist: + # solarisrequires = "SUNWcar (Name="Package name of SUNWcar"),SUNWkvm (Name="Package name of SUNWcar"), ... + # if ( $installer::globals::issolarispkgbuild ) + # { + # if ( $onerequires =~ /^\s*(.*?)\s+\(\s*Name\s*=\s*\"(.*?)\"\s*\)\s*$/ ) + # { + # $onerequires = $1; + # $packagename = $2; + # $installer::globals::dependfilenames{$onerequires} = $packagename; + # } + # } + + $line = "%requires" . " " . $onerequires . "\n"; + push(@epmheader, $line); + } + } + else + { + if ( $installer::globals::add_required_package ) + { + my $requiresstring = $installer::globals::add_required_package; + + my $replacementstring = "COMMAREPLACEMENT"; + $requiresstring = installer::converter::replace_masked_separator($requiresstring, ",", "$replacementstring"); + my $allrequires = installer::converter::convert_stringlist_into_array(\$requiresstring, ","); + installer::converter::resolve_masked_separator($allrequires, ",", $replacementstring); + + for ( my $i = 0; $i <= $#{$allrequires}; $i++ ) + { + my $onerequires = ${$allrequires}[$i]; + $onerequires =~ s/\s*$//; + installer::packagelist::resolve_packagevariables(\$onerequires, $variableshashref, 0); + + # Special handling for Solaris. In depend files, the names of the packages are required, not + # only the abbreviation. Therefore there is a special syntax for names in packagelist: + # solarisrequires = "SUNWcar (Name="Package name of SUNWcar"),SUNWkvm (Name="Package name of SUNWcar"), ... + # if ( $installer::globals::issolarispkgbuild ) + # { + # if ( $onerequires =~ /^\s*(.*?)\s+\(\s*Name\s*=\s*\"(.*?)\"\s*\)\s*$/ ) + # { + # $onerequires = $1; + # $packagename = $2; + # $installer::globals::dependfilenames{$onerequires} = $packagename; + # } + # } + + $line = "%requires" . " " . $onerequires . "\n"; + push(@epmheader, $line); + } + } + } + + return \@epmheader; +} + +####################################### +# Adding header to epm file +####################################### + +sub adding_header_to_epm_file +{ + my ($epmfileref, $epmheaderref) = @_; + + for ( my $i = 0; $i <= $#{$epmheaderref}; $i++ ) + { + push( @{$epmfileref}, ${$epmheaderref}[$i] ); + } + + push( @{$epmfileref}, "\n\n" ); +} + +##################################################### +# Replace one in shell scripts ( ${VARIABLENAME} ) +##################################################### + +sub replace_variable_in_shellscripts +{ + my ($scriptref, $variable, $searchstring) = @_; + + for ( my $i = 0; $i <= $#{$scriptref}; $i++ ) + { + ${$scriptref}[$i] =~ s/\$\{$searchstring\}/$variable/g; + } +} + +################################################### +# Replace one in shell scripts ( %VARIABLENAME ) +################################################### + +sub replace_percent_variable_in_shellscripts +{ + my ($scriptref, $variable, $searchstring) = @_; + + for ( my $i = 0; $i <= $#{$scriptref}; $i++ ) + { + ${$scriptref}[$i] =~ s/\%$searchstring/$variable/g; + } +} + +################################################ +# Replacing many variables in shell scripts +################################################ + +sub replace_many_variables_in_shellscripts +{ + my ($scriptref, $variableshashref) = @_; + + my $key; + + foreach $key (keys %{$variableshashref}) + { + my $value = $variableshashref->{$key}; + if ( ! $value =~ /.oxt/ ) { $value = lc($value); } # lowercase ! + if ( $installer::globals::issolarisbuild) { $value =~ s/\.org/org/g; } # openofficeorg instead of openoffice.org + replace_variable_in_shellscripts($scriptref, $value, $key); + } +} + +####################################### +# Setting oxt file name variable +####################################### + +sub set_oxt_filename +{ + my ($filesinpackage, $allvariables) = @_; + + for ( my $i = 0; $i <= $#{$filesinpackage}; $i++ ) + { + my $onefile = ${$filesinpackage}[$i]; + if ( $onefile->{'Name'} =~ /.oxt\s*$/ ) + { + $allvariables->{'OXTFILENAME'} = $onefile->{'Name'}; + # $allvariables->{'FULLOXTFILENAME'} = $onefile->{'destination'}; + last; # only one oxt file for each rpm! + } + } +} + +####################################### +# Adding shell scripts to epm file +####################################### + +sub adding_shellscripts_to_epm_file +{ + my ($epmfileref, $shellscriptsfilename, $localrootpath, $allvariableshashref, $filesinpackage) = @_; + + # Setting variable for ${OXTFILENAME} into $allvariableshashref, if this is a RPM with an extension + set_oxt_filename($filesinpackage, $allvariableshashref); + + # $installer::globals::shellscriptsfilename + + push( @{$epmfileref}, "\n\n" ); + + my $shellscriptsfileref = installer::files::read_file($shellscriptsfilename); + + replace_variable_in_shellscripts($shellscriptsfileref, $localrootpath, "rootpath"); + + replace_many_variables_in_shellscripts($shellscriptsfileref, $allvariableshashref); + + for ( my $i = 0; $i <= $#{$shellscriptsfileref}; $i++ ) + { + push( @{$epmfileref}, ${$shellscriptsfileref}[$i] ); + } + + push( @{$epmfileref}, "\n" ); +} + +################################################# +# Determining the epm on the system +################################################# + +sub find_epm_on_system +{ + my ($includepatharrayref) = @_; + + installer::logger::include_header_into_logfile("Check epm on system"); + + my $epmname = "epm"; + + # epm should be defined through the configure script but we need to + # check for it to be defined because of the Sun environment. + # Check the environment variable first and if it is not defined, + # or if it is but the location is not executable, search further. + # It has to be found in the solver or it has to be in the path + # (saved in $installer::globals::epm_in_path) or we get the specified + # one through the environment (i.e. when --with-epm=... is specified) + + if ($ENV{'EPM'}) + { + if (($ENV{'EPM'} ne "") && (-x "$ENV{'EPM'}")) + { + $epmname = $ENV{'EPM'}; + } + elsif ( ($ENV{'EPM'} eq "no") || ($ENV{'EPM'} eq "internal") ) + { + $epmname = "epm"; + } + else + { + installer::exiter::exit_program("Environment variable EPM set (\"$ENV{'EPM'}\"), but file does not exist or is not executable!", "find_epm_on_system"); + } + } + else + { + my $epmfileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$epmname, $includepatharrayref, 0); + + if (($$epmfileref eq "") && (!($installer::globals::epm_in_path))) { installer::exiter::exit_program("ERROR: Could not find program $epmname!", "find_epm_on_system"); } + if (($$epmfileref eq "") && ($installer::globals::epm_in_path)) { $epmname = $installer::globals::epm_path; } + if (!($$epmfileref eq "")) { $epmname = $$epmfileref; } + } + + my $infoline = "Using epmfile: $epmname\n"; + push( @installer::globals::logfileinfo, $infoline); + + return $epmname; +} + +################################################# +# Determining the epm patch state +# saved in $installer::globals::is_special_epm +################################################# + +sub set_patch_state +{ + my ($epmexecutable) = @_; + + my $infoline = ""; + + my $systemcall = "$epmexecutable |"; + open (EPMPATCH, "$systemcall"); + + while (<EPMPATCH>) + { + chop; + if ( $_ =~ /Patched for OpenOffice.org/ ) { $installer::globals::is_special_epm = 1; } + } + + close (EPMPATCH); + + if ( $installer::globals::is_special_epm ) + { + $infoline = "\nPatch state: This is a patched version of epm!\n\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "\nPatch state: This is an unpatched version of epm!\n\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + if ( ( $installer::globals::is_special_epm ) && (($installer::globals::islinuxrpmbuild) || ($installer::globals::issolarispkgbuild)) ) + { + # Special postprocess handling only for Linux RPM and Solaris packages + $installer::globals::postprocess_specialepm = 1; + $installer::globals::postprocess_standardepm = 0; + } + else + { + $installer::globals::postprocess_specialepm = 0; + $installer::globals::postprocess_standardepm = 1; + } +} + +################################################# +# LD_PRELOAD string for Debian packages +################################################# + +sub get_ld_preload_string +{ + my ($includepatharrayref) = @_; + + my $getuidlibraryname = "getuid.so"; + + my $getuidlibraryref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$getuidlibraryname, $includepatharrayref, 0); + if ($$getuidlibraryref eq "") { installer::exiter::exit_program("ERROR: Could not find $getuidlibraryname!", "get_ld_preload_string"); } + + my $ldpreloadstring = "LD_PRELOAD=" . $$getuidlibraryref; + + return $ldpreloadstring; +} + +################################################# +# Calling epm to create the installation sets +################################################# + +sub call_epm +{ + my ($epmname, $epmlistfilename, $packagename, $includepatharrayref) = @_; + + installer::logger::include_header_into_logfile("epm call for $packagename"); + + my $packageformat = $installer::globals::packageformat; + + my $localpackagename = $packagename; + # Debian allows only lowercase letters in package name + if ( $installer::globals::debian ) { $localpackagename = lc($localpackagename); } + + my $outdirstring = ""; + if ( $installer::globals::epmoutpath ne "" ) { $outdirstring = " --output-dir $installer::globals::epmoutpath"; } + + # Debian package build needs a LD_PRELOAD for correct rights + + my $ldpreloadstring = ""; + + if ( $installer::globals::debian ) { $ldpreloadstring = get_ld_preload_string($includepatharrayref) . " "; } + + my $extraflags = ""; + if ($ENV{'EPM_FLAGS'}) { $extraflags = $ENV{'EPM_FLAGS'}; } + + my $systemcall = $ldpreloadstring . $epmname . " -f " . $packageformat . " " . $extraflags . " " . $localpackagename . " " . $epmlistfilename . $outdirstring . " -v " . " 2\>\&1 |"; + + installer::logger::print_message( "... $systemcall ...\n" ); + + my $maxepmcalls = 3; + + for ( my $i = 1; $i <= $maxepmcalls; $i++ ) + { + my @epmoutput = (); + + open (EPM, "$systemcall"); + while (<EPM>) {push(@epmoutput, $_); } + close (EPM); + + my $returnvalue = $?; # $? contains the return value of the systemcall + + my $infoline = "Systemcall (Try $i): $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $j = 0; $j <= $#epmoutput; $j++ ) + { + if ( $i < $maxepmcalls ) { $epmoutput[$j] =~ s/\bERROR\b/PROBLEM/ig; } + push( @installer::globals::logfileinfo, "$epmoutput[$j]"); + } + + if ($returnvalue) + { + $infoline = "Try $i : Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + if ( $i == $maxepmcalls ) { installer::exiter::exit_program("ERROR: \"$systemcall\"!", "call_epm"); } + } + else + { + installer::logger::print_message( "Success (Try $i): \"$systemcall\"\n" ); + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + last; + } + } +} + +##################################################################### +# Adding the new line for relocatables into pkginfo file (Solaris) +# or spec file (Linux) created by epm +##################################################################### + +sub add_one_line_into_file +{ + my ($file, $insertline, $filename) = @_; + + if ( $installer::globals::issolarispkgbuild ) + { + push(@{$file}, $insertline); # simply adding at the end of pkginfo file + } + + if ( $installer::globals::islinuxrpmbuild ) + { + # Adding behind the line beginning with: Group: + + my $inserted_line = 0; + + for ( my $i = 0; $i <= $#{$file}; $i++ ) + { + if ( ${$file}[$i] =~ /^\s*Group\:\s*/ ) + { + splice(@{$file},$i+1,0,$insertline); + $inserted_line = 1; + last; + } + } + + if (! $inserted_line) { installer::exiter::exit_program("ERROR: Did not find string \"Group:\" in file: $filename", "add_one_line_into_file"); } + } + + $insertline =~ s/\s*$//; # removing line end for correct logging + my $infoline = "Success: Added line $insertline into file $filename!\n"; + push( @installer::globals::logfileinfo, $infoline); +} + +##################################################################### +# Setting the revision VERSION=1.9,REV=66 . +# Also adding the new line: "AutoReqProv: no" +##################################################################### + +sub set_revision_in_pkginfo +{ + my ($file, $filename, $variables, $packagename) = @_; + + my $revisionstring = "\,REV\=" . $installer::globals::packagerevision; + + # Adding also a time string to the revision. Syntax: VERSION=8.0.0,REV=66.2005.01.24 + + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); + + $mday = $mday; + $mon = $mon + 1; + $year = $year + 1900; + + if ( $mday < 10 ) { $mday = "0" . $mday; } + if ( $mon < 10 ) { $mon = "0" . $mon; } + $datestring = $year . "." . $mon . "." . $mday; + $revisionstring = $revisionstring . "." . $datestring; + + for ( my $i = 0; $i <= $#{$file}; $i++ ) + { + if ( ${$file}[$i] =~ /^\s*(VERSION\=.*?)\s*$/ ) + { + my $oldstring = $1; + my $newstring = $oldstring . $revisionstring; # also adding the date string + ${$file}[$i] =~ s/$oldstring/$newstring/; + my $infoline = "Info: Changed in $filename file: \"$oldstring\" to \"$newstring\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + last; + } + } + + # For Update and Patch reasons, this string can also be kept constant + + my $pkgversion = "SOLSPARCPKGVERSION"; + if ( $installer::globals::issolarisx86build ) { $pkgversion = "SOLIAPKGVERSION"; } + + if (( $variables->{$pkgversion} ) && ( $variables->{$pkgversion} ne "" )) + { + if ( $variables->{$pkgversion} ne "FINALVERSION" ) + { + # In OOo 3.x timeframe, this string is no longer unique for all packages, because of the three layer. + # In the string: "3.0.0,REV=9.2008.09.30" only the part "REV=9.2008.09.30" can be unique for all packages + # and therefore be set as $pkgversion. + # The first part "3.0.0" has to be derived from the + + my $version = $installer::globals::packageversion; + if ( $version =~ /^\s*(\d+)\.(\d+)\.(\d+)\s*$/ ) + { + my $major = $1; + my $minor = $2; + my $micro = $3; + + my $finalmajor = $major; + my $finalminor = 0; + my $finalmicro = 0; + + if (( $packagename =~ /-ure\s*$/ ) && ( $finalmajor == 1 )) { $finalminor = 4; } + + $version = "$finalmajor.$finalminor.$finalmicro"; + } + + my $versionstring = "$version,$variables->{$pkgversion}"; + + for ( my $i = 0; $i <= $#{$file}; $i++ ) + { + if ( ${$file}[$i] =~ /^\s*(VERSION\=).*?\s*$/ ) + { + my $start = $1; + my $newstring = $start . $versionstring . "\n"; # setting the complete new string + my $oldstring = ${$file}[$i]; + ${$file}[$i] = $newstring; + $oldstring =~ s/\s*$//; + $newstring =~ s/\s*$//; + my $infoline = "Info: Changed in $filename file: \"$oldstring\" to \"$newstring\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + last; + } + } + } + } +} + +######################################################## +# Setting Patch information for Respin versions +# into pkginfo file. This prevents Respin versions +# from patching. +######################################################## + +sub set_patchlist_in_pkginfo_for_respin +{ + my ($changefile, $filename, $allvariables, $packagename) = @_; + + my $patchlistname = "SOLSPARCPATCHLISTFORRESPIN"; + if ( $installer::globals::issolarisx86build ) { $patchlistname = "SOLIAPATCHLISTFORRESPIN"; } + + if ( $allvariables->{$patchlistname} ) + { + # patchlist separator is a blank + my $allpatchesstring = $allvariables->{$patchlistname}; + my @usedpatches = (); + + # Analyzing the patchlist + # Syntax: 120186-10 126411-01(+core-01) -> use 126411-01 only for core-01 + # Syntax: 120186-10 126411-01(-core-01) -> use 126411-01 for all packages except for core-01 + my $allpatches = installer::converter::convert_whitespace_stringlist_into_array(\$allpatchesstring); + + for ( my $i = 0; $i <= $#{$allpatches}; $i++ ) + { + my $patchdefinition = ${$allpatches}[$i]; + + my $patchid = ""; + my $symbol = ""; + my $constraint = ""; + my $isusedpatch = 0; + + if ( $patchdefinition =~ /^\s*(.+)\(([+-])(.+)\)\s*$/ ) + { + $patchid = $1; + $symbol = $2; + $constraint = $3; + } + elsif (( $patchdefinition =~ /\(/ ) || ( $patchdefinition =~ /\)/ )) # small syntax check + { + # if there is a bracket in the $patchdefinition, but it does not + # match the if-condition, this is an erroneous definition. + installer::exiter::exit_program("ERROR: Unknown patch string: $patchdefinition", "set_patchlist_in_pkginfo_for_respin"); + } + else + { + $patchid = $patchdefinition; + $isusedpatch = 1; # patches without constraint are always included + } + + if ( $symbol ne "" ) + { + if ( $symbol eq "+" ) + { + if ( $packagename =~ /^.*\Q$constraint\E\s*$/ ) { $isusedpatch = 1; } + } + + if ( $symbol eq "-" ) + { + if ( ! ( $packagename =~ /^.*\Q$constraint\E\s*$/ )) { $isusedpatch = 1; } + } + } + + if ( $isusedpatch ) { push(@usedpatches, $patchid); } + } + + if ( $#usedpatches > -1 ) + { + my $patchstring = installer::converter::convert_array_to_space_separated_string(\@usedpatches); + + my $newline = "PATCHLIST=" . $patchstring . "\n"; + add_one_line_into_file($changefile, $newline, $filename); + + # Adding patch info for each used patch in the patchlist + + for ( my $i = 0; $i <= $#usedpatches; $i++ ) + { + my $patchid = $usedpatches[$i]; + my $key = "PATCH_INFO_" . $patchid; + $key =~ s/\s*$//; + + if ( ! $allvariables->{$key} ) { installer::exiter::exit_program("ERROR: No Patch info available in zip list file for $key", "set_patchlist_in_pkginfo"); } + my $value = set_timestamp_in_patchinfo($allvariables->{$key}); + $newline = $key . "=" . $value . "\n"; + + add_one_line_into_file($changefile, $newline, $filename); + } + } + } +} + +######################################################## +# Solaris requires, that the time of patch installation +# must not be empty. +# Format: Mon Mar 24 11:20:56 PDT 2008 +# Log file: Tue Apr 29 23:26:19 2008 (04:31 min.) +# Replace string: ${TIMESTAMP} +######################################################## + +sub set_timestamp_in_patchinfo +{ + my ($value) = @_; + + my $currenttime = localtime(); + + if ( $currenttime =~ /^\s*(.+?)(\d\d\d\d)\s*$/ ) + { + my $start = $1; + my $year = $2; + $currenttime = $start . "CET " . $year; + } + + $value =~ s/\$\{TIMESTAMP\}/$currenttime/; + + return $value; +} + +######################################################## +# Setting MAXINST=1000 into the pkginfo file. +######################################################## + +sub set_maxinst_in_pkginfo +{ + my ($changefile, $filename) = @_; + + my $newline = "MAXINST\=1000\n"; + + add_one_line_into_file($changefile, $newline, $filename); +} + +############################################################# +# Setting several Solaris variables into the pkginfo file. +############################################################# + +sub set_solaris_parameter_in_pkginfo +{ + my ($changefile, $filename, $allvariables) = @_; + + my $newline = ""; + + # SUNW_PRODNAME + # SUNW_PRODVERS + # SUNW_PKGVERS + # Not: SUNW_PKGTYPE + # HOTLINE + # EMAIL + + my $productname = $allvariables->{'PRODUCTNAME'}; + $newline = "SUNW_PRODNAME=$productname\n"; + add_one_line_into_file($changefile, $newline, $filename); + + my $productversion = ""; + if ( $allvariables->{'PRODUCTVERSION'} ) + { + $productversion = $allvariables->{'PRODUCTVERSION'}; + if ( $allvariables->{'PRODUCTEXTENSION'} ) { $productversion = $productversion . "/" . $allvariables->{'PRODUCTEXTENSION'}; } + } + $newline = "SUNW_PRODVERS=$productversion\n"; + add_one_line_into_file($changefile, $newline, $filename); + + $newline = "SUNW_PKGVERS=1\.0\n"; + add_one_line_into_file($changefile, $newline, $filename); + + if ( $allvariables->{'SUNW_PKGTYPE'} ) + { + $newline = "SUNW_PKGTYPE=$allvariables->{'SUNW_PKGTYPE'}\n"; + add_one_line_into_file($changefile, $newline, $filename); + } + else + { + $newline = "SUNW_PKGTYPE=\n"; + add_one_line_into_file($changefile, $newline, $filename); + } + + $newline = "HOTLINE=Please contact your local service provider\n"; + add_one_line_into_file($changefile, $newline, $filename); + + $newline = "EMAIL=\n"; + add_one_line_into_file($changefile, $newline, $filename); + +} + +##################################################################### +# epm uses as archtecture for Solaris x86 "i86pc". This has to be +# changed to "i386". +##################################################################### + +sub fix_architecture_setting +{ + my ($changefile) = @_; + + for ( my $i = 0; $i <= $#{$changefile}; $i++ ) + { + if ( ${$changefile}[$i] =~ /^\s*ARCH=i86pc\s*$/ ) + { + ${$changefile}[$i] =~ s/i86pc/i386/; + last; + } + + } +} + +##################################################################### +# Adding a new line for topdir into specfile, removing old +# topdir if set. +##################################################################### + +sub set_topdir_in_specfile +{ + my ($changefile, $filename, $newepmdir) = @_; + + # $newepmdir =~ s/^\s*\.//; # removing leading "." + $newepmdir = cwd() . $installer::globals::separator . $newepmdir; # only absolute path allowed + + # removing "%define _topdir", if existing + + for ( my $i = 0; $i <= $#{$changefile}; $i++ ) + { + if ( ${$changefile}[$i] =~ /^\s*\%define _topdir\s+/ ) + { + my $removeline = ${$changefile}[$i]; + $removeline =~ s/\s*$//; + splice(@{$changefile},$i,1); + my $infoline = "Info: Removed line \"$removeline\" from file $filename!\n"; + push( @installer::globals::logfileinfo, $infoline); + last; + } + } + + # Adding "topdir" behind the line beginning with: Group: + + my $inserted_line = 0; + + my $topdirline = "\%define _topdir $newepmdir\n"; + + for ( my $i = 0; $i <= $#{$changefile}; $i++ ) + { + if ( ${$changefile}[$i] =~ /^\s*Group\:\s*/ ) + { + splice(@{$changefile},$i+1,0,$topdirline); + $inserted_line = 1; + $topdirline =~ s/\s*$//; + my $infoline = "Success: Added line $topdirline into file $filename!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + + if (! $inserted_line) { installer::exiter::exit_program("ERROR: Did not find string \"Group:\" in file: $filename", "set_topdir_in_specfile"); } + +} + +##################################################################### +# Setting the packager in the spec file +# Syntax: Packager: abc@def +##################################################################### + +sub set_packager_in_specfile +{ + my ($changefile) = @_; + + my $packager = $installer::globals::longmanufacturer; + + for ( my $i = 0; $i <= $#{$changefile}; $i++ ) + { + if ( ${$changefile}[$i] =~ /^\s*Packager\s*:\s*(.+?)\s*$/ ) + { + my $oldstring = $1; + ${$changefile}[$i] =~ s/\Q$oldstring\E/$packager/; + my $infoline = "Info: Changed Packager in spec file from $oldstring to $packager!\n"; + push( @installer::globals::logfileinfo, $infoline); + last; + } + } +} + +##################################################################### +# Setting the requirements in the spec file (i81494) +# Syntax: PreReq: "requirements" (only for shared extensions) +##################################################################### + +sub set_prereq_in_specfile +{ + my ($changefile) = @_; + + my $prereq = "PreReq:"; + + for ( my $i = 0; $i <= $#{$changefile}; $i++ ) + { + if ( ${$changefile}[$i] =~ /^\s*Requires:\s*(.+?)\s*$/ ) + { + my $oldstring = ${$changefile}[$i]; + ${$changefile}[$i] =~ s/Requires:/$prereq/; + my $infoline = "Info: Changed requirements in spec file from $oldstring to ${$changefile}[$i]!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } +} + +##################################################################### +# Setting the Auto[Req]Prov line and __find_requires +##################################################################### + +sub set_autoprovreq_in_specfile +{ + my ($changefile, $findrequires, $bindir) = @_; + + my $autoreqprovline; + + if ( $findrequires ) + { + $autoreqprovline = "AutoProv\: no\n%define __find_requires $bindir/$findrequires\n"; + } + else + { + $autoreqprovline = "AutoReqProv\: no\n"; + } + + for ( my $i = 0; $i <= $#{$changefile}; $i++ ) + { + # Adding "autoreqprov" behind the line beginning with: Group: + if ( ${$changefile}[$i] =~ /^\s*Group\:\s*/ ) + { + splice(@{$changefile},$i+1,0,$autoreqprovline); + $autoreqprovline =~ s/\s*$//; + $infoline = "Success: Added line $autoreqprovline into spec file!\n"; + push( @installer::globals::logfileinfo, $infoline); + + last; + } + } +} + +##################################################################### +# Replacing Copyright with License in the spec file +# Syntax: License: LGPL, SISSL +##################################################################### + +sub set_license_in_specfile +{ + my ($changefile, $variableshashref) = @_; + + my $license = $variableshashref->{'LICENSENAME'}; + + for ( my $i = 0; $i <= $#{$changefile}; $i++ ) + { + if ( ${$changefile}[$i] =~ /^\s*Copyright\s*:\s*(.+?)\s*$/ ) + { + ${$changefile}[$i] = "License: $license\n"; + my $infoline = "Info: Replaced Copyright with License: $license !\n"; + push( @installer::globals::logfileinfo, $infoline); + last; + } + } +} + +######################################################### +# Building relocatable Solaris packages means: +# 1. Add "BASEDIR=/opt" into pkginfo +# 2. Remove "/opt/" from all objects in prototype file +# For step2 this function exists +# Sample: d none /opt/openofficeorg20/help 0755 root other +# -> d none openofficeorg20/help 0755 root other +######################################################### + +sub make_prototypefile_relocatable +{ + my ($prototypefile, $relocatablepath) = @_; + + for ( my $i = 0; $i <= $#{$prototypefile}; $i++ ) + { + if ( ${$prototypefile}[$i] =~ /^\s*\w\s+\w+\s+\/\w+/ ) # this is an object line + { + ${$prototypefile}[$i] =~ s/$relocatablepath//; # Important: $relocatablepath has a "/" at the end. Example "/opt/" + } + } + + # If the $relocatablepath is "/opt/openoffice20/" the line "d none /opt/openoffice20" was not changed. + # This line has to be removed now + + if ( $relocatablepath ne "/" ) { $relocatablepath =~ s/\/\s*$//; } # removing the ending slash + + for ( my $i = 0; $i <= $#{$prototypefile}; $i++ ) + { + if ( ${$prototypefile}[$i] =~ /^\s*d\s+\w+\s+\Q$relocatablepath\E/ ) + { + my $line = ${$prototypefile}[$i]; + splice(@{$prototypefile},$i,1); # removing the line + $line =~ s/\s*$//; + my $infoline = "Info: Removed line \"$line\" from prototype file!\n"; + push( @installer::globals::logfileinfo, $infoline); + last; + } + } + + # Making "\$" to "$" in prototype file. "\$" was created by epm. + + for ( my $i = 0; $i <= $#{$prototypefile}; $i++ ) + { + if ( ${$prototypefile}[$i] =~ /\\\$/ ) + { + ${$prototypefile}[$i] =~ s/\\\$/\$/g; + my $infoline2 = "Info: Changed line in prototype file: ${$prototypefile}[$i] !\n"; + push( @installer::globals::logfileinfo, $infoline2); + } + } +} + + +######################################################################### +# In scp the flag VOLATEFILE can be used. This shall lead to style "v" +# in Solaris prototype file. This is not supported by epm and has +# therefore to be included in prototypefile, not in epm list file. +######################################################################### + +sub set_volatilefile_into_prototypefile +{ + my ($prototypefile, $filesref) = @_; + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + + my $styles = ""; + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } + + if ( $styles =~ /\bVOLATILEFILE\b/ ) + { + my $sourcepath = $onefile->{'sourcepath'}; + + for ( my $j = 0; $j <= $#{$prototypefile}; $j++ ) + { + if (( ${$prototypefile}[$j] =~ /^\s*f\s+none\s+/ ) && ( ${$prototypefile}[$j] =~ /\=\Q$sourcepath\E\s+/ )) + { + my $oldline = ${$prototypefile}[$j]; + ${$prototypefile}[$j] =~ s/^\s*f/v/; + my $newline = ${$prototypefile}[$j]; + $oldline =~ s/\s*$//; + $newline =~ s/\s*$//; + my $infoline = "Volatile file: Changing content from \"$oldline\" to \"$newline\" .\n"; + push(@installer::globals::logfileinfo, $infoline); + last; + } + } + } + } +} + +######################################################################### +# Replacing the variables in the Solaris patch shell scripts. +# Taking care, that multiple slashes are not always removed. +######################################################################### + +sub replace_variables_in_shellscripts_for_patch +{ + my ($scriptfile, $scriptfilename, $oldstring, $newstring) = @_; + + for ( my $i = 0; $i <= $#{$scriptfile}; $i++ ) + { + if ( ${$scriptfile}[$i] =~ /\Q$oldstring\E/ ) + { + my $oldline = ${$scriptfile}[$i]; + if (( $oldstring eq "PRODUCTDIRECTORYNAME" ) && ( $newstring eq "" )) { $oldstring = $oldstring . "/"; } + ${$scriptfile}[$i] =~ s/\Q$oldstring\E/$newstring/g; + my $infoline = "Info: Substituting in $scriptfilename $oldstring by $newstring\n"; + push(@installer::globals::logfileinfo, $infoline); + } + } +} + +######################################################################### +# Replacing the variables in the shell scripts or in the epm list file +# Linux: spec file +# Solaris: preinstall, postinstall, preremove, postremove +# If epm is used in the original version (not relocatable) +# the variables have to be exchanged in the list file, +# created for epm. +######################################################################### + +sub replace_variables_in_shellscripts +{ + my ($scriptfile, $scriptfilename, $oldstring, $newstring) = @_; + + my $debug = 0; + if ( $oldstring eq "PRODUCTDIRECTORYNAME" ) { $debug = 1; } + + for ( my $i = 0; $i <= $#{$scriptfile}; $i++ ) + { + if ( ${$scriptfile}[$i] =~ /\Q$oldstring\E/ ) + { + my $oldline = ${$scriptfile}[$i]; + ${$scriptfile}[$i] =~ s/\Q$oldstring\E/$newstring/g; + ${$scriptfile}[$i] =~ s/\/\//\//g; # replacing "//" by "/" , if path $newstring is empty! + my $infoline = "Info: Substituting in $scriptfilename $oldstring by $newstring\n"; + push(@installer::globals::logfileinfo, $infoline); + if ( $debug ) + { + $infoline = "Old Line: $oldline"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = "New Line: ${$scriptfile}[$i]"; + push(@installer::globals::logfileinfo, $infoline); + } + } + } +} + +############################################################ +# Determinig the directory created by epm, in which the +# RPMS or Solaris packages are created. +############################################################ + +sub determine_installdir_ooo +{ + # A simple "ls" command returns the directory name + + my $dirname = ""; + + my $systemcall = "ls |"; + open (LS, "$systemcall"); + $dirname = <LS>; + close (LS); + + $dirname =~ s/\s*$//; + + my $infoline = "Info: Directory created by epm: $dirname\n"; + push(@installer::globals::logfileinfo, $infoline); + + return $dirname; +} + +############################################################ +# Setting the tab content into the file container +############################################################ + +sub set_tab_into_datafile +{ + my ($changefile, $filesref) = @_; + + my @newclasses = (); + my $newclassesstring = ""; + + if ( $installer::globals::issolarispkgbuild ) + { + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + + if ( $onefile->{'SolarisClass'} ) + { + my $sourcepath = $onefile->{'sourcepath'}; + + for ( my $j = 0; $j <= $#{$changefile}; $j++ ) + { + if (( ${$changefile}[$j] =~ /^\s*f\s+none\s+/ ) && ( ${$changefile}[$j] =~ /\=\Q$sourcepath\E\s+/ )) + { + my $oldline = ${$changefile}[$j]; + ${$changefile}[$j] =~ s/f\s+none/e $onefile->{'SolarisClass'}/; + my $newline = ${$changefile}[$j]; + $oldline =~ s/\s*$//; + $newline =~ s/\s*$//; + + my $infoline = "TAB: Changing content from \"$oldline\" to \"$newline\" .\n"; + push(@installer::globals::logfileinfo, $infoline); + + # collecting all new classes + if (! installer::existence::exists_in_array($onefile->{'SolarisClass'}, \@newclasses)) + { + push(@newclasses, $onefile->{'SolarisClass'}); + } + + last; + } + } + } + } + + $newclassesstring = installer::converter::convert_array_to_space_separated_string(\@newclasses); + } + + if ( $installer::globals::islinuxrpmbuild ) + { + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + + if ( $onefile->{'SpecFileContent'} ) + { + my $destination = $onefile->{'destination'}; + + for ( my $j = 0; $j <= $#{$changefile}; $j++ ) + { + if ( ${$changefile}[$j] =~ /^\s*(\%attr\(.*\))\s+(\".*?\Q$destination\E\"\s*)$/ ) + { + my $begin = $1; + my $end = $2; + + my $oldline = ${$changefile}[$j]; + ${$changefile}[$j] = $begin . " " . $onefile->{'SpecFileContent'} . " " . $end; + my $newline = ${$changefile}[$j]; + + $oldline =~ s/\s*$//; + $newline =~ s/\s*$//; + + my $infoline = "TAB: Changing content from \"$oldline\" to \"$newline\" .\n"; + push(@installer::globals::logfileinfo, $infoline); + + last; + } + } + } + } + } + + return $newclassesstring; +} + +############################################################ +# Including additional classes into the pkginfo file +############################################################ + +sub include_classes_into_pkginfo +{ + my ($changefile, $classesstring) = @_; + + for ( my $i = 0; $i <= $#{$changefile}; $i++ ) + { + if ( ${$changefile}[$i] =~ /^\s*CLASSES\=none/ ) + { + ${$changefile}[$i] =~ s/\s*$//; + my $oldline = ${$changefile}[$i]; + ${$changefile}[$i] = ${$changefile}[$i] . " " . $classesstring . "\n"; + my $newline = ${$changefile}[$i]; + $newline =~ s/\s*$//; + + my $infoline = "pkginfo file: Changing content from \"$oldline\" to \"$newline\" .\n"; + push(@installer::globals::logfileinfo, $infoline); + } + } +} + +########################################################################################## +# Checking, if an extension is included into the package (Linux). +# All extension files have to be installed into directory +# share/extension/install +# %attr(0444,root,root) "/opt/staroffice8/share/extension/install/SunSearchToolbar.oxt" +########################################################################################## + +sub is_extension_package +{ + my ($specfile) = @_; + + my $is_extension_package = 0; + + for ( my $i = 0; $i <= $#{$specfile}; $i++ ) + { + my $line = ${$specfile}[$i]; + if ( $line =~ /share\/extension\/install\/.*?\.oxt\"\s*$/ ) + { + $is_extension_package = 1; + last; + } + } + + return $is_extension_package; +} + +###################################################################### +# Checking, if an extension is included into the package (Solaris). +# All extension files have to be installed into directory +# share/extension/install +###################################################################### + +sub get_extension_name +{ + my ($prototypefile) = @_; + + my $extensionName = ""; + + for ( my $i = 0; $i <= $#{$prototypefile}; $i++ ) + { + my $line = ${$prototypefile}[$i]; + if ( $line =~ /^\s*f\s+none\s+share\/extension\/install\/(\w+?\.oxt)\s*\=/ ) + { + $extensionName = $1; + last; + } + } + + return $extensionName; +} + + +############################################################ +# A Solaris patch contains 7 specific scripts +############################################################ + +sub add_scripts_into_prototypefile +{ + my ($prototypefile, $prototypefilename, $languagestringref, $staticpath) = @_; + + # The files are stored in the directory $installer::globals::patchincludepath + # The file names are available via @installer::globals::solarispatchscripts + + my $path = $installer::globals::patchincludepath; + $path =~ s/\/\s*$//; + $path = $path . $installer::globals::separator; + + my @newlines = (); + my $extensionname = get_extension_name($prototypefile); + + if ( $extensionname ne "" ) + { + for ( my $i = 0; $i <= $#installer::globals::solarispatchscriptsforextensions; $i++ ) + { + my $sourcefilename = $path . $installer::globals::solarispatchscriptsforextensions[$i]; + my $destfile = $installer::globals::solarispatchscriptsforextensions[$i]; + + # If the sourcepath has "_extension" in its name, this has to be removed + $destfile =~ s/_extensions\s*$//; # hard coded renaming of script name + + # Creating unique directory name with $prototypefilename + my $extensiondir = installer::systemactions::create_directories("extensionscripts", $languagestringref); + + if ( $prototypefilename =~ /\/(\S*?)\s*$/ ) { $prototypefilename = $1; } + $prototypefilename =~ s/\./_/g; + my $destdir = $extensiondir . $installer::globals::separator . $prototypefilename; + if ( ! -d $destdir ) { installer::systemactions::create_directory($destdir); } + my $destpath = $destdir . $installer::globals::separator . $destfile; + if ( -f $destpath ) { unlink($destpath); } + + # Reading file + my $scriptfile = installer::files::read_file($sourcefilename); + + # Replacing variables + my $oldstring = "\$\{OXTFILENAME\}"; + replace_variables_in_shellscripts_for_patch($scriptfile, $destpath, $oldstring, $extensionname); + $oldstring = "PRODUCTDIRECTORYNAME"; + replace_variables_in_shellscripts_for_patch($scriptfile, $destpath, $oldstring, $staticpath); + + # Saving file + installer::files::save_file($destpath, $scriptfile); + + # Writing file destination into prototype file + my $line = "i $destfile=" . $destpath . "\n"; + push(@newlines, $line); + } + } + else + { + for ( my $i = 0; $i <= $#installer::globals::solarispatchscripts; $i++ ) + { + my $line = "i $installer::globals::solarispatchscripts[$i]=" . $path . $installer::globals::solarispatchscripts[$i] . "\n"; + push(@newlines, $line); + } + } + + # Including the new lines after the last line starting with "i" + + for ( my $i = 0; $i <= $#{$prototypefile}; $i++ ) + { + if ( ${$prototypefile}[$i] =~ /^\s*i\s+copyright/ ) + { + splice(@{$prototypefile}, $i, 1); # ignoring old copyright text, using patch standard + next; + } + if ( ${$prototypefile}[$i] =~ /^\s*i\s+/ ) { next; } + splice(@{$prototypefile}, $i, 0, @newlines); + last; + } +} + +############################################################ +# Adding patch infos in pkginfo file +############################################################ + +sub include_patchinfos_into_pkginfo +{ + my ( $changefile, $filename, $variableshashref ) = @_; + + # SUNW_PATCHID=101998-10 + # SUNW_OBSOLETES=114999-01 113999-01 + # SUNW_PKGTYPE=usr + # SUNW_PKGVERS=1.0 + # SUNW_REQUIRES=126411-01 + + my $patchidname = "SOLSPARCPATCHID"; + if ( $installer::globals::issolarisx86build ) { $patchidname = "SOLIAPATCHID"; } + + if ( ! $variableshashref->{$patchidname} ) { installer::exiter::exit_program("ERROR: Variable $patchidname not defined in zip list file!", "include_patchinfos_into_pkginfo"); } + + my $newline = "SUNW_PATCHID=" . $variableshashref->{$patchidname} . "\n"; + add_one_line_into_file($changefile, $newline, $filename); + + my $patchobsoletesname = "SOLSPARCPATCHOBSOLETES"; + if ( $installer::globals::issolarisx86build ) { $patchobsoletesname = "SOLIAPATCHOBSOLETES"; } + + my $obsoletes = ""; + if ( $variableshashref->{$patchobsoletesname} ) { $obsoletes = $variableshashref->{$patchobsoletesname}; } + $newline = "SUNW_OBSOLETES=" . $obsoletes . "\n"; + add_one_line_into_file($changefile, $newline, $filename); + + my $patchrequiresname = "SOLSPARCPATCHREQUIRES"; + if ( $installer::globals::issolarisx86build ) { $patchrequiresname = "SOLIAPATCHREQUIRES"; } + + if ( $variableshashref->{$patchrequiresname} ) + { + my $requires = $variableshashref->{$patchrequiresname}; + $newline = "SUNW_REQUIRES=" . $requires . "\n"; + add_one_line_into_file($changefile, $newline, $filename); + } + + $newline = "SUNW_PATCH_PROPERTIES=\n"; + add_one_line_into_file($changefile, $newline, $filename); + + # $newline = "SUNW_PKGTYPE=usr\n"; + # add_one_line_into_file($changefile, $newline, $filename); + + # $newline = "SUNW_PKGVERS=1.0\n"; + # add_one_line_into_file($changefile, $newline, $filename); +} + +############################################################ +# Setting the correct Solaris locales +############################################################ + +sub get_solaris_language_for_langpack +{ + my ( $onelanguage ) = @_; + + my $sollanguage = $onelanguage; + $sollanguage =~ s/\-/\_/; + + if ( $sollanguage eq "de" ) { $sollanguage = "de"; } + elsif ( $sollanguage eq "es" ) { $sollanguage = "es"; } + elsif ( $sollanguage eq "fr" ) { $sollanguage = "fr"; } + elsif ( $sollanguage eq "it" ) { $sollanguage = "it"; } + elsif ( $sollanguage eq "sv" ) { $sollanguage = "sv"; } + elsif ( $sollanguage eq "pt_BR" ) { $sollanguage = "pt_BR"; } + elsif ( $sollanguage eq "ja" ) { $sollanguage = "ja,ja_JP,ja_JP.PCK,ja_JP.UTF-8"; } + elsif ( $sollanguage eq "ko" ) { $sollanguage = "ko,ko.UTF-8"; } + elsif ( $sollanguage eq "zh_CN" ) { $sollanguage = "zh,zh.GBK,zh_CN,zh_CN.GB18030,zh.UTF-8"; } + elsif ( $sollanguage eq "zh_TW" ) { $sollanguage = "zh_TW,zh_TW.BIG5,zh_TW.UTF-8,zh_HK.BIG5HK,zh_HK.UTF-8"; } + + return $sollanguage; +} + +############################################################ +# Adding language infos in pkginfo file +############################################################ + +sub include_languageinfos_into_pkginfo +{ + my ( $changefile, $filename, $languagestringref, $onepackage, $variableshashref ) = @_; + + # SUNWPKG_LIST=core01 + # SUNW_LOC=de + + my $locallang = $onepackage->{'language'}; + my $solarislanguage = get_solaris_language_for_langpack($locallang); + + my $newline = "SUNW_LOC=" . $solarislanguage . "\n"; + add_one_line_into_file($changefile, $newline, $filename); + + # SUNW_PKGLIST is required, if SUNW_LOC is defined. + if ( $onepackage->{'pkg_list_entry'} ) + { + my $packagelistentry = $onepackage->{'pkg_list_entry'}; + installer::packagelist::resolve_packagevariables(\$packagelistentry, $variableshashref, 1); + $newline = "SUNW_PKGLIST=" . $packagelistentry . "\n"; + add_one_line_into_file($changefile, $newline, $filename); + } + else + { + # Using default package ooobasis30-core01. + my $packagelistentry = "%BASISPACKAGEPREFIX%WITHOUTDOTOOOBASEVERSION-core01"; + installer::packagelist::resolve_packagevariables(\$packagelistentry, $variableshashref, 1); + $newline = "SUNW_PKGLIST=" . $packagelistentry . "\n"; + add_one_line_into_file($changefile, $newline, $filename); + } +} + +############################################################ +# Collecting all files included in patch in +# @installer::globals::patchfilecollector +############################################################ + +sub collect_patch_files +{ + my ($file, $packagename, $prefix) = @_; + + # $file is the spec file or the prototypefile + + $prefix = $prefix . "/"; + my $packagenamestring = "Package " . $packagename . " \:\n"; + push(@installer::globals::patchfilecollector, $packagenamestring); + + for ( my $i = 0; $i <= $#{$file}; $i++ ) + { + my $line = ${$file}[$i]; + + if ( $installer::globals::islinuxrpmbuild ) + { + # %attr(0444,root,root) "/opt/openofficeorg20/program/about.bmp" + + if ( $line =~ /^\s*\%attr\(.*\)\s*\"(.*?)\"\s*$/ ) + { + my $filename = $1 . "\n"; + $filename =~ s/^\s*\Q$prefix\E//; + push(@installer::globals::patchfilecollector, $filename); + } + } + + if ( $installer::globals::issolarispkgbuild ) + { + # f none program/msomrl.rdb=/ab/SRC680/unxsols4.pro/bin/msomrl.rdb 0444 root bin + + if ( $line =~ /^\s*f\s+\w+\s+(.*?)\=/ ) + { + my $filename = $1 . "\n"; + push(@installer::globals::patchfilecollector, $filename); + } + } + } + + push(@installer::globals::patchfilecollector, "\n"); + +} + +############################################################ +# Including package names into the depend files. +# The package names have to be included into +# packagelist. They are already saved in +# %installer::globals::dependfilenames. +############################################################ + +sub put_packagenames_into_dependfile +{ + my ( $file ) = @_; + + for ( my $i = 0; $i <= $#{$file}; $i++ ) + { + my $line = ${$file}[$i]; + if ( $line =~ /^\s*\w\s+(.*?)\s*$/ ) + { + my $abbreviation = $1; + + if ( $abbreviation =~ /\%/ ) { installer::exiter::exit_program("ERROR: Could not resolve all properties in Solaris package abbreviation \"$abbreviation\"!", "read_packagemap"); } + + if ( exists($installer::globals::dependfilenames{$abbreviation}) ) + { + my $packagename = $installer::globals::dependfilenames{$abbreviation}; + if ( $packagename =~ /\%/ ) { installer::exiter::exit_program("ERROR: Could not resolve all properties in Solaris package name \"$packagename\"!", "read_packagemap"); } + + $line =~ s/\s*$//; + ${$file}[$i] = $line . "\t" . $packagename . "\n"; + } + else + { + installer::exiter::exit_program("ERROR: Missing packagename for Solaris package \"$abbreviation\"!", "put_packagenames_into_dependfile"); + } + } + } +} + +############################################################ +# Including the relocatable directory into +# spec file and pkginfo file +# Linux: set topdir in specfile +# Solaris: remove $relocatablepath (/opt/) +# for all objects in prototype file +# and changing "topdir" for Linux +############################################################ + +sub prepare_packages +{ + my ($loggingdir, $packagename, $staticpath, $relocatablepath, $onepackage, $variableshashref, $filesref, $languagestringref) = @_; + + my $filename = ""; + my $newline = ""; + my $newepmdir = $installer::globals::epmoutpath . $installer::globals::separator; + + my $localrelocatablepath = $relocatablepath; + if ( $localrelocatablepath ne "/" ) { $localrelocatablepath =~ s/\/\s*$//; } + + if ( $installer::globals::issolarispkgbuild ) + { + $filename = $packagename . ".pkginfo"; + $newline = "BASEDIR\=" . $localrelocatablepath . "\n"; + } + + if ( $installer::globals::islinuxrpmbuild ) + { + # if ( $localrelocatablepath =~ /^\s*$/ ) { $localrelocatablepath = "/"; }; # at least the "/" + $filename = $packagename . ".spec"; + $newline = "Prefix\:\ " . $localrelocatablepath . "\n"; + } + + my $completefilename = $newepmdir . $filename; + + if ( ! -f $completefilename) { installer::exiter::exit_program("ERROR: Did not find file: $completefilename", "prepare_packages"); } + my $changefile = installer::files::read_file($completefilename); + if ( $newline ne "" ) + { + add_one_line_into_file($changefile, $newline, $filename); + installer::files::save_file($completefilename, $changefile); + } + + # my $newepmdir = $completefilename; + # installer::pathanalyzer::get_path_from_fullqualifiedname(\$newepmdir); + + # adding new "topdir" and removing old "topdir" in specfile + + if ( $installer::globals::islinuxrpmbuild ) + { + set_topdir_in_specfile($changefile, $filename, $newepmdir); + set_autoprovreq_in_specfile($changefile, $onepackage->{'findrequires'}, "$installer::globals::unpackpath" . "/bin"); + set_packager_in_specfile($changefile); + if ( is_extension_package($changefile) ) { set_prereq_in_specfile($changefile); } + set_license_in_specfile($changefile, $variableshashref); + set_tab_into_datafile($changefile, $filesref); + # check_requirements_in_specfile($changefile); + installer::files::save_file($completefilename, $changefile); + if ( $installer::globals::patch ) { collect_patch_files($changefile, $packagename, $localrelocatablepath); } + } + + # removing the relocatable path in prototype file + + if ( $installer::globals::issolarispkgbuild ) + { + set_revision_in_pkginfo($changefile, $filename, $variableshashref, $packagename); + set_maxinst_in_pkginfo($changefile, $filename); + set_solaris_parameter_in_pkginfo($changefile, $filename, $variableshashref); + if ( $installer::globals::issolarisx86build ) { fix_architecture_setting($changefile); } + if ( ! $installer::globals::patch ) { set_patchlist_in_pkginfo_for_respin($changefile, $filename, $variableshashref, $packagename); } + if ( $installer::globals::patch ) { include_patchinfos_into_pkginfo($changefile, $filename, $variableshashref); } + if (( $onepackage->{'language'} ) && ( $onepackage->{'language'} ne "" )) { include_languageinfos_into_pkginfo($changefile, $filename, $languagestringref, $onepackage, $variableshashref); } + installer::files::save_file($completefilename, $changefile); + + my $prototypefilename = $packagename . ".prototype"; + $prototypefilename = $newepmdir . $prototypefilename; + if (! -f $prototypefilename) { installer::exiter::exit_program("ERROR: Did not find prototype file: $prototypefilename", "prepare_packages"); } + + my $prototypefile = installer::files::read_file($prototypefilename); + make_prototypefile_relocatable($prototypefile, $relocatablepath); + set_volatilefile_into_prototypefile($prototypefile, $filesref); + my $classesstring = set_tab_into_datafile($prototypefile, $filesref); + if ($classesstring) + { + include_classes_into_pkginfo($changefile, $classesstring); + installer::files::save_file($completefilename, $changefile); + } + + if ( $installer::globals::patch ) { add_scripts_into_prototypefile($prototypefile, $prototypefilename, $languagestringref, $staticpath); } + + installer::files::save_file($prototypefilename, $prototypefile); + if ( $installer::globals::patch ) { collect_patch_files($prototypefile, $packagename, ""); } + + # Adding package names into depend files for Solaris (not supported by epm) + my $dependfilename = $packagename . ".depend"; + $dependfilename = $newepmdir . $dependfilename; + if ( -f $dependfilename) + { + my $dependfile = installer::files::read_file($dependfilename); + put_packagenames_into_dependfile($dependfile); + installer::files::save_file($dependfilename, $dependfile); + } + } + + return $newepmdir; +} + +############################################################ +# Linux requirement for perl is changed by epm from +# /usr/bin/perl to perl . +# Requires: perl +############################################################ + +sub check_requirements_in_specfile +{ + my ( $specfile ) = @_; + + for ( my $i = 0; $i <= $#{$specfile}; $i++ ) + { + if (( ${$specfile}[$i] =~ /^\s*Requires/ ) && ( ${$specfile}[$i] =~ /\bperl\b/ ) && ( ! ( ${$specfile}[$i] =~ /\/usr\/bin\/perl\b/ ))) + { + my $oldline = ${$specfile}[$i]; + ${$specfile}[$i] =~ s/perl/\/usr\/bin\/perl/; + my $newline = ${$specfile}[$i]; + + $oldline =~ s/\s*$//; + $newline =~ s/\s*$//; + my $infoline = "Spec File: Changing content from \"$oldline\" to \"$newline\".\n"; + push(@installer::globals::logfileinfo, $infoline); + } + } +} + +############################################################################### +# Replacement of PRODUCTINSTALLLOCATION and PRODUCTDIRECTORYNAME in the +# epm list file. +# The complete rootpath is stored in $installer::globals::rootpath +# or for each package in $onepackage->{'destpath'} +# The static rootpath is stored in $staticpath +# The relocatable path is stored in $relocatablepath +# PRODUCTINSTALLLOCATION is the relocatable part ("/opt") and +# PRODUCTDIRECTORYNAME the static path ("openofficeorg20"). +# In standard epm process: +# No usage of package specific variables like $BASEDIR, because +# 1. These variables would be replaced in epm process +# 2. epm version 3.7 does not support relocatable packages +############################################################################### + +sub resolve_path_in_epm_list_before_packaging +{ + my ($listfile, $listfilename, $variable, $path) = @_; + + installer::logger::include_header_into_logfile("Replacing variables in epm list file:"); + + $path =~ s/\/\s*$//; + replace_variables_in_shellscripts($listfile, $listfilename, $variable, $path); + +} + +################################################################# +# Determining the rpm version. Beginning with rpm version 4.0 +# the tool to create RPMs is "rpmbuild" and no longer "rpm" +################################################################# + +sub determine_rpm_version +{ + my $rpmversion = 0; + my $rpmout = ""; + + my $systemcall = "rpm --version |"; + open (RPM, "$systemcall"); + $rpmout = <RPM>; + close (RPM); + + $rpmout =~ s/\s*$//g; + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ( $rpmout eq "" ) { $infoline = "ERROR: Could not find file \"rpm\" !\n"; } + else { $infoline = "Success: rpm version: $rpmout\n"; } + + push( @installer::globals::logfileinfo, $infoline); + + if ( $rpmout =~ /(\d+)\.(\d+)\.(\d+)/ ) { $rpmversion = $1; } + elsif ( $rpmout =~ /(\d+)\.(\d+)/ ) { $rpmversion = $1; } + elsif ( $rpmout =~ /(\d+)/ ) { $rpmversion = $1; } + else { installer::exiter::exit_program("ERROR: Unknown format: $rpmout ! Expected: \"a.b.c\", or \"a.b\", or \"a\"", "determine_rpm_version"); } + + return $rpmversion; +} + +################################################# +# Systemcall to start the packaging process +################################################# + +sub create_packages_without_epm +{ + my ($epmdir, $packagename, $includepatharrayref, $allvariables, $languagestringref) = @_; + + # Solaris: pkgmk -o -f solaris-2.8-sparc/SUNWso8m34.prototype -d solaris-2.8-sparc + # Solaris: pkgtrans solaris-2.8-sparc SUNWso8m34.pkg SUNWso8m34 + # Solaris: tar -cf - SUNWso8m34 | gzip > SUNWso8m34.tar.gz + + if ( $installer::globals::issolarispkgbuild ) + { + my $prototypefile = $epmdir . $packagename . ".prototype"; + if (! -f $prototypefile) { installer::exiter::exit_program("ERROR: Did not find file: $prototypefile", "create_packages_without_epm"); } + + my $destinationdir = $prototypefile; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$destinationdir); + $destinationdir =~ s/\/\s*$//; # removing ending slashes + + # my $systemcall = "pkgmk -o -f $prototypefile -d $destinationdir \> /dev/null 2\>\&1"; + my $systemcall = "pkgmk -l 1073741824 -o -f $prototypefile -d $destinationdir 2\>\&1 |"; + installer::logger::print_message( "... $systemcall ...\n" ); + + my $maxpkgmkcalls = 3; + + for ( my $i = 1; $i <= $maxpkgmkcalls; $i++ ) + { + my @pkgmkoutput = (); + + open (PKGMK, "$systemcall"); + while (<PKGMK>) {push(@pkgmkoutput, $_); } + close (PKGMK); + + my $returnvalue = $?; # $? contains the return value of the systemcall + + my $infoline = "Systemcall (Try $i): $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $j = 0; $j <= $#pkgmkoutput; $j++ ) + { + if ( $i < $maxpkgmkcalls ) { $pkgmkoutput[$j] =~ s/\bERROR\b/PROBLEM/ig; } + push( @installer::globals::logfileinfo, "$pkgmkoutput[$j]"); + } + + if ($returnvalue) + { + $infoline = "Try $i : Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + if ( $i == $maxpkgmkcalls ) { installer::exiter::exit_program("ERROR: \"$systemcall\"!", "create_packages_without_epm"); } + } + else + { + installer::logger::print_message( "Success (Try $i): \"$systemcall\"\n" ); + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + last; + } + } + + # It might be necessary to save uncompressed Solaris packages + + if ( $allvariables->{'JDSBUILD'} ) + { + if ( ! $installer::globals::jds_language_controlled ) + { + my $correct_language = installer::worker::check_jds_language($allvariables, $languagestringref); + $installer::globals::correct_jds_language = $correct_language; + $installer::globals::jds_language_controlled = 1; + } + + if ( $installer::globals::correct_jds_language ) + { + if ( $installer::globals::saved_packages_path eq "" ) + { + $packagestempdir = installer::systemactions::create_directories("jds", $languagestringref); + $installer::globals::saved_packages_path = $packagestempdir; + push(@installer::globals::jdsremovedirs, $packagestempdir); + } + + $systemcall = "cd $destinationdir; cp -p -R $packagename $installer::globals::saved_packages_path;"; + make_systemcall($systemcall); + installer::logger::print_message( "... $systemcall ...\n" ); + + # Setting unix rights to "775" for all created directories inside the package, + # that is saved in temp directory + + $systemcall = "cd $packagestempdir; find $packagename -type d -exec chmod 775 \{\} \\\;"; + installer::logger::print_message( "... $systemcall ...\n" ); + + $returnvalue = system($systemcall); + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + } + + # compressing packages + + my $faspac = "faspac-so.sh"; + + my $compressorref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$faspac, $includepatharrayref, 0); + if ($$compressorref ne "") + { + # Saving original pkginfo, to set time stamp later + my $pkginfoorig = "$destinationdir/$packagename/pkginfo"; + my $pkginfotmp = "$destinationdir/$packagename" . ".pkginfo.tmp"; + $systemcall = "cp -p $pkginfoorig $pkginfotmp"; + make_systemcall($systemcall); + + $faspac = $$compressorref; + $infoline = "Found compressor: $faspac\n"; + push( @installer::globals::logfileinfo, $infoline); + + installer::logger::print_message( "... $faspac ...\n" ); + installer::logger::include_timestamp_into_logfile("Starting $faspac"); + + $systemcall = "/bin/sh $faspac -a -q -d $destinationdir $packagename"; # $faspac has to be the absolute path! + make_systemcall($systemcall); + + # Setting time stamp for pkginfo, because faspac-so.sh changed the pkginfo file, + # updated the size and checksum, but not the time stamp. + $systemcall = "touch -r $pkginfotmp $pkginfoorig"; + make_systemcall($systemcall); + if ( -f $pkginfotmp ) { unlink($pkginfotmp); } + + installer::logger::include_timestamp_into_logfile("End of $faspac"); + } + else + { + $infoline = "Not found: $faspac\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + # Setting unix rights to "775" for all created directories inside the package + + $systemcall = "cd $destinationdir; find $packagename -type d -exec chmod 775 \{\} \\\;"; + installer::logger::print_message( "... $systemcall ...\n" ); + + $returnvalue = system($systemcall); + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + ###################### + # making pkg files + ###################### + + # my $streamname = $packagename . ".pkg"; + # $systemcall = "pkgtrans $destinationdir $streamname $packagename"; + # print "... $systemcall ...\n"; + + # $returnvalue = system($systemcall); + + # $infoline = "Systemcall: $systemcall\n"; + # push( @installer::globals::logfileinfo, $infoline); + + # if ($returnvalue) + # { + # $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + # push( @installer::globals::logfileinfo, $infoline); + # } + # else + # { + # $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + # push( @installer::globals::logfileinfo, $infoline); + # } + + ######################### + # making tar.gz files + ######################### + + # my $targzname = $packagename . ".tar.gz"; + # $systemcall = "cd $destinationdir; tar -cf - $packagename | gzip > $targzname"; + # print "... $systemcall ...\n"; + + # $returnvalue = system($systemcall); + + # $infoline = "Systemcall: $systemcall\n"; + # push( @installer::globals::logfileinfo, $infoline); + + # if ($returnvalue) + # { + # $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + # push( @installer::globals::logfileinfo, $infoline); + # } + # else + # { + # $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + # push( @installer::globals::logfileinfo, $infoline); + # } + } + + # Linux: rpm -bb so8m35.spec ( -> dependency check abklemmen? ) + + if ( $installer::globals::islinuxrpmbuild ) + { + my $specfilename = $epmdir . $packagename . ".spec"; + if (! -f $specfilename) { installer::exiter::exit_program("ERROR: Did not find file: $specfilename", "create_packages_without_epm"); } + + # my $rpmcommand = "rpm"; + my $rpmcommand = $installer::globals::rpm; + my $rpmversion = determine_rpm_version(); + + # if ( $rpmversion >= 4 ) { $rpmcommand = "rpmbuild"; } + + # saving globally for later usage + $installer::globals::rpmcommand = $rpmcommand; + $installer::globals::rpmquerycommand = "rpm"; # For queries "rpm" is used, not "rpmbuild" (for this call the LD_LIBRARY_PATH is not required!) + + my $target = ""; + if ( $installer::globals::compiler =~ /unxlngi/) { $target = "i586"; } + elsif ( $installer::globals::compiler =~ /unxlng/) {$target = (POSIX::uname())[4]; } + + # rpm 4.6 ignores buildroot tag in spec file + + my $buildrootstring = ""; + + if ( $rpmversion >= 4 ) + { + my $dir = getcwd; + my $buildroot = $dir . "/" . $epmdir . "buildroot/"; + $buildrootstring = "--buildroot=$buildroot"; + } + + my $systemcall = "$rpmcommand -bb $specfilename --target $target $buildrootstring 2\>\&1 |"; + + installer::logger::print_message( "... $systemcall ...\n" ); + + my $maxrpmcalls = 3; + + for ( my $i = 1; $i <= $maxrpmcalls; $i++ ) + { + my @rpmoutput = (); + + open (RPM, "$systemcall"); + while (<RPM>) {push(@rpmoutput, $_); } + close (RPM); + + my $returnvalue = $?; # $? contains the return value of the systemcall + + my $infoline = "Systemcall (Try $i): $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $j = 0; $j <= $#rpmoutput; $j++ ) + { + if ( $i < $maxrpmcalls ) { $rpmoutput[$j] =~ s/\bERROR\b/PROBLEM/ig; } + push( @installer::globals::logfileinfo, "$rpmoutput[$j]"); + } + + if ($returnvalue) + { + $infoline = "Try $i : Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + if ( $i == $maxrpmcalls ) { installer::exiter::exit_program("ERROR: \"$systemcall\"!", "create_packages_without_epm"); } + } + else + { + installer::logger::print_message( "Success (Try $i): \"$systemcall\"\n" ); + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + last; + } + } + } +} + +################################################# +# Removing all temporary files created by epm +################################################# + +sub remove_temporary_epm_files +{ + my ($epmdir, $loggingdir, $packagename) = @_; + + # saving the files into the loggingdir + + if ( $installer::globals::issolarispkgbuild ) + { + my @extensions = (); + push(@extensions, ".pkginfo"); + push(@extensions, ".prototype"); + push(@extensions, ".postinstall"); + push(@extensions, ".postremove"); + push(@extensions, ".preinstall"); + push(@extensions, ".preremove"); + push(@extensions, ".depend"); + + for ( my $i = 0; $i <= $#extensions; $i++ ) + { + my $removefile = $epmdir . $packagename . $extensions[$i]; + my $destfile = $loggingdir . $packagename . $extensions[$i] . ".log"; + + if (! -f $removefile) { next; } + + my $systemcall = "mv -f $removefile $destfile"; + system($systemcall); # ignoring the return value + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + # removing the package + +# my $removedir = $epmdir . $packagename; +# +# my $systemcall = "rm -rf $removedir"; +# +# print "... $systemcall ...\n"; +# +# my $returnvalue = system($systemcall); +# +# my $infoline = "Systemcall: $systemcall\n"; +# push( @installer::globals::logfileinfo, $infoline); +# +# if ($returnvalue) +# { +# $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; +# push( @installer::globals::logfileinfo, $infoline); +# } +# else +# { +# $infoline = "Success: Executed \"$systemcall\" successfully!\n"; +# push( @installer::globals::logfileinfo, $infoline); +# } + } + + if ( $installer::globals::islinuxrpmbuild ) + { + my $removefile = $epmdir . $packagename . ".spec"; + my $destfile = $loggingdir . $packagename . ".spec.log"; + + # if (! -f $removefile) { next; } + + my $systemcall = "mv -f $removefile $destfile"; + system($systemcall); # ignoring the return value + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + # removing the directory "buildroot" + + my $removedir = $epmdir . "buildroot"; + + $systemcall = "rm -rf $removedir"; + + installer::logger::print_message( "... $systemcall ...\n" ); + + my $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } +} + +###################################################### +# Making the systemcall +###################################################### + +sub make_systemcall +{ + my ($systemcall) = @_; + + my $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +########################################################### +# Creating a better directory structure in the solver. +########################################################### + +sub create_new_directory_structure +{ + my ($newepmdir) = @_; + + my $newdir = $installer::globals::epmoutpath; + + if ( $installer::globals::islinuxrpmbuild ) + { + my $rpmdir; + my $machine = ""; + if ( $installer::globals::compiler =~ /unxlngi/) { + $rpmdir = "$installer::globals::epmoutpath/RPMS/i586"; + } + elsif ( $installer::globals::compiler =~ /unxlng/) { + $machine = (POSIX::uname())[4]; + $rpmdir = "$installer::globals::epmoutpath/RPMS/$machine"; + } + else { installer::exiter::exit_program("ERROR: rpmdir undefined !", "create_new_directory_structure"); } + + my $systemcall = "mv $rpmdir/* $newdir"; # moving the rpms into the directory "RPMS" + + my $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not move content of \"$rpmdir\" to \"$newdir\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Moved content of \"$rpmdir\" to \"$newdir\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + # and removing the empty directory + + if ( $machine ne "" ) + { + installer::systemactions::remove_empty_directory("$installer::globals::epmoutpath/RPMS/$machine"); + } + installer::systemactions::remove_empty_directory("$installer::globals::epmoutpath/RPMS/x86_64"); + installer::systemactions::remove_empty_directory("$installer::globals::epmoutpath/RPMS/i586"); + installer::systemactions::remove_empty_directory("$installer::globals::epmoutpath/RPMS/i386"); + installer::systemactions::remove_empty_directory("$installer::globals::epmoutpath/RPMS"); + + } + + # Setting unix rights to "775" for $newdir ("RPMS" or "packages") + + my $localcall = "chmod 775 $newdir \>\/dev\/null 2\>\&1"; + my $callreturnvalue = system($localcall); + + my $callinfoline = "Systemcall: $localcall\n"; + push( @installer::globals::logfileinfo, $callinfoline); + + if ($callreturnvalue) + { + $callinfoline = "ERROR: Could not execute \"$localcall\"!\n"; + push( @installer::globals::logfileinfo, $callinfoline); + } + else + { + $callinfoline = "Success: Executed \"$localcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $callinfoline); + } +} + +###################################################### +# Collect modules with product specific styles. +###################################################### + +sub collect_modules_with_style +{ + my ($style, $modulesarrayref) = @_; + + my @allmodules = (); + + for ( my $i = 0; $i <= $#{$modulesarrayref}; $i++ ) + { + my $onemodule = ${$modulesarrayref}[$i]; + my $styles = ""; + if ( $onemodule->{'Styles'} ) { $styles = $onemodule->{'Styles'}; } + if ( $styles =~ /\b\Q$style\E\b/ ) + { + push(@allmodules, $onemodule); + } + } + + return \@allmodules; +} + +###################################################### +# Remove modules without packagecontent. +###################################################### + +sub remove_modules_without_package +{ + my ($allmodules) = @_; + + my @allmodules = (); + + for ( my $i = 0; $i <= $#{$allmodules}; $i++ ) + { + my $onemodule = ${$allmodules}[$i]; + my $packagename = ""; + if ( $onemodule->{'PackageName'} ) { $packagename = $onemodule->{'PackageName'}; } + if ( $packagename ne "" ) + { + push(@allmodules, $onemodule); + } + } + + return \@allmodules; +} + +###################################################### +# Unpacking tar.gz file and setting new packagename. +###################################################### + +sub unpack_tar_gz_file +{ + my ($packagename, $destdir) = @_; + + my $newpackagename = ""; + + if ( $packagename =~ /\.tar\.gz\s*$/ ) + { + # Collecting all packages in directory "packages" + my $oldcontent = installer::systemactions::read_directory($destdir); + + # unpacking gunzip + my $systemcall = "cd $destdir; cat $packagename | gunzip | tar -xf -"; + make_systemcall($systemcall); + + # deleting the tar.gz files + $systemcall = "cd $destdir; rm -f $packagename"; + make_systemcall($systemcall); + + # Finding new content -> that is the package name + my ($newcontent, $allcontent ) = installer::systemactions::find_new_content_in_directory($destdir, $oldcontent); + $newpackagename = ${$newcontent}[0]; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$newpackagename); + } + + if ( $newpackagename ne "" ) { $packagename = $newpackagename; } + + return $packagename; +} + +###################################################### +# Copying files of child projects. +###################################################### + +sub copy_childproject_files +{ + my ($allmodules, $sopackpath, $destdir, $modulesarrayref, $allvariables, $subdir, $includepatharrayref, $use_sopackpath) = @_; + + for ( my $i = 0; $i <= $#{$allmodules}; $i++ ) + { + my $localdestdir = $destdir; + my $onemodule = ${$allmodules}[$i]; + my $packagename = $onemodule->{'PackageName'}; + my $sourcefile = ""; + if ( $use_sopackpath ) + { + $sourcefile = $sopackpath . $installer::globals::separator . $installer::globals::compiler . $installer::globals::separator . $subdir . $installer::globals::separator . $packagename; + } + else + { + my $sourcepathref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$packagename, $includepatharrayref, 1); + $sourcefile = $$sourcepathref; + } + + if ( ! -f $sourcefile ) { installer::exiter::exit_program("ERROR: File not found: $sourcefile ($packagename) !", "copy_childproject_files"); } + if ( $onemodule->{'Subdir'} ) + { + $localdestdir = $localdestdir . $installer::globals::separator . $onemodule->{'Subdir'}; + if ( ! -d $localdestdir ) { installer::systemactions::create_directory($localdestdir); } + } + installer::systemactions::copy_one_file($sourcefile, $localdestdir); + # Solaris: unpacking tar.gz files and setting new packagename + if ( $installer::globals::issolarispkgbuild ) { $packagename = unpack_tar_gz_file($packagename, $localdestdir); } + + if (( $installer::globals::isxpdplatform ) && ( $allvariables->{'XPDINSTALLER'} )) + { + installer::xpdinstaller::create_xpd_file_for_childproject($onemodule, $localdestdir, $packagename, $allvariableshashref, $modulesarrayref); + } + } + +} + +###################################################### +# Copying files for system integration. +###################################################### + +sub copy_and_unpack_tar_gz_files +{ + my ($sourcefile, $destdir) = @_; + + my $systemcall = "cd $destdir; cat $sourcefile | gunzip | tar -xf -"; + make_systemcall($systemcall); +} + +###################################################### +# Including child packages into the +# installation set. +###################################################### + +sub put_childprojects_into_installset +{ + my ($newdir, $allvariables, $modulesarrayref, $includepatharrayref) = @_; + + my $infoline = ""; + + my $sopackpath = ""; + if ( $ENV{'SO_PACK'} ) { $sopackpath = $ENV{'SO_PACK'}; } + else { installer::exiter::exit_program("ERROR: Environment variable SO_PACK not set!", "put_childprojects_into_installset"); } + + my $destdir = "$newdir"; + + # adding Java + + my $sourcefile = ""; + + # Finding the modules defined in scp (with flag JAVAMODULE, ADAMODULE, ...) + # Getting name of package from scp-Module + # Copy file into installation set + # Create xpd file and put it into xpd directory + # xpd file has to be created completely from module and package itself (-> no packagelist!) + + if ( $allvariables->{'JAVAPRODUCT'} ) + { + # Collect all modules with flag "JAVAMODULE" + my $allmodules = collect_modules_with_style("JAVAMODULE", $modulesarrayref); + $allmodules = remove_modules_without_package($allmodules); + copy_childproject_files($allmodules, $sopackpath, $destdir, $modulesarrayref, $allvariables, "jre", $includepatharrayref, 1); + } + + # Adding additional required packages (freetype). + # This package names are stored in global array @installer::globals::requiredpackages + + if ( $allvariables->{'ADDREQUIREDPACKAGES'} ) + { + # Collect all modules with flag "REQUIREDPACKAGEMODULE" + my $allmodules = collect_modules_with_style("REQUIREDPACKAGEMODULE", $modulesarrayref); + $allmodules = remove_modules_without_package($allmodules); + copy_childproject_files($allmodules, $sopackpath, $destdir, $modulesarrayref, $allvariables, "requiredpackages", $includepatharrayref, 1); + } + + # Collect all modules with flag "USERLANDMODULE" + my $alluserlandmodules = collect_modules_with_style("USERLANDMODULE", $modulesarrayref); + $alluserlandmodules = remove_modules_without_package($alluserlandmodules); + copy_childproject_files($alluserlandmodules, $sopackpath, $destdir, $modulesarrayref, $allvariables, "", $includepatharrayref, 0); + +} + +###################################################### +# Checking whether the new content is a directory and +# not a package. If it is a directory, the complete +# content of the directory has to be added to the +# array newcontent. +###################################################### + +sub control_subdirectories +{ + my ($content, $subdir) = @_; + + my @newcontent = (); + + for ( my $i = 0; $i <= $#{$content}; $i++ ) + { + if ( -d ${$content}[$i] ) + { + $subdir = ${$content}[$i]; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$subdir); + my $allpackages = installer::systemactions::read_directory(${$content}[$i]); + for ( my $j = 0; $j <= $#{$allpackages}; $j++ ) + { + # Currently only Linux rpm is supported, debian packages cannot be installed via xpd installer + if (( $installer::globals::islinuxbuild ) && ( ! ( ${$allpackages}[$j] =~ /\.rpm\s*$/ ))) { next; } + push(@newcontent, ${$allpackages}[$j]); + } + } + else + { + push(@newcontent, ${$content}[$i]); + } + } + + return (\@newcontent, $subdir); +} + +###################################################### +# Including the system integration files into the +# installation sets. +###################################################### + +sub put_systemintegration_into_installset +{ + my ($newdir, $includepatharrayref, $allvariables, $modulesarrayref) = @_; + + my $destdir = $newdir; + + # adding System integration files + + my $sourcefile = ""; + + # Finding the modules defined in scp (with flag SYSTEMMODULE) + # Getting name of package from scp-Module + # Search package in list off all include files + # Copy file into installation set and unpack it (always tar.gz) + # Create xpd file and put it into xpd directory + # tar.gz can contain a different number of packages -> automatically create hidden sub modules + # xpd file has to be created completely from module and package itself (-> no packagelist!) + + # Collect all modules with flag "SYSTEMMODULE" + my $allmodules = collect_modules_with_style("SYSTEMMODULE", $modulesarrayref); + $allmodules = remove_modules_without_package($allmodules); + + for ( my $i = 0; $i <= $#{$allmodules}; $i++ ) + { + my $onemodule = ${$allmodules}[$i]; + my $packagetarfilename = $onemodule->{'PackageName'}; + + my $infoline = "Including into installation set: $packagetarfilename\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $sourcepathref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$packagetarfilename, $includepatharrayref, 1); + if ( $$sourcepathref eq "" ) { installer::exiter::exit_program("ERROR: Source path not found for $packagetarfilename!", "copy_systemintegration_files"); } + + # Collecting all packages in directory "packages" or "RPMS" + my $oldcontent = installer::systemactions::read_directory($destdir); + + copy_and_unpack_tar_gz_files($$sourcepathref, $destdir); + + # Finding new content -> that is the package name + my ($newcontent, $allcontent ) = installer::systemactions::find_new_content_in_directory($destdir, $oldcontent); + + # special handling, if new content is a directory + my $subdir = ""; + if ( ! $installer::globals::issolarispkgbuild ) { ($newcontent, $subdir) = control_subdirectories($newcontent); } + + # Adding license content into Solaris packages + if (( $installer::globals::issolarispkgbuild ) && ( $installer::globals::englishlicenseset )) { installer::worker::add_license_into_systemintegrationpackages($destdir, $newcontent); } + + if (( $installer::globals::isxpdplatform ) && ( $allvariables->{'XPDINSTALLER'} )) + { + installer::xpdinstaller::create_xpd_file_for_systemintegration($onemodule, $newcontent, $modulesarrayref, $subdir); + } + } +} + +###################################################### +# Analyzing the Unix installation path. +# From the installation path /opt/openofficeorg20 +# is the part /opt relocatable and the part +# openofficeorg20 static. +###################################################### + +sub analyze_rootpath +{ + my ($rootpath, $staticpathref, $relocatablepathref, $allvariables) = @_; + + $rootpath =~ s/\/\s*$//; # removing ending slash + + ############################################################## + # Version 1: "/opt" is variable and "openofficeorg20" fixed + ############################################################## + + # my $staticpath = $rootpath; + # installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$staticpath); + # $$staticpathref = $staticpath; # will be "openofficeorg20" + + # my $relocatablepath = $rootpath; + # installer::pathanalyzer::get_path_from_fullqualifiedname(\$relocatablepath); + # $$relocatablepathref = $relocatablepath; # will be "/opt/" + + ############################################################## + # Version 2: "/opt/openofficeorg20" is variable and "" fixed + ############################################################## + + # if ( $$relocatablepathref eq "" ) # relocatablepath is not defined in package list + # { + # $$staticpathref = ""; # will be "" + # $$relocatablepathref = $rootpath . "\/"; # relocatable path must end with "/", will be "/opt/openofficeorg20/" + # # setting the static path to the hostname of the directory with style OFFICEDIRECTORY + # if ( $allvariables->{'SETSTATICPATH'} ) { $$staticpathref = $installer::globals::officedirhostname; } + # + # } + # else # relocatablepath is defined in package list + # { + # $$relocatablepathref =~ s/\/\s*$//; # removing ending slash + # $$relocatablepathref = $$relocatablepathref . "\/"; # relocatable path must end with "/" + # my $staticpath = $rootpath; + # $staticpath =~ s/\Q$$relocatablepathref\E//; + # $staticpath =~ s/\/\s*$//; + # $$staticpathref = $staticpath; + # } + + ############################################################## + # Version 3: "/" is variable and "/opt/openofficeorg20" fixed + ############################################################## + + $$relocatablepathref = "/"; + # Static path has to contain the office directory name. This is replaced in shellscripts. + $$staticpathref = $rootpath . $installer::globals::separator . $installer::globals::officedirhostname; + # For RPM version 3.x it is required, that Prefix is not "/" in spec file. In this case --relocate will not work, + # because RPM 3.x says, that the package is not relocatable. Therefore we have to use Prefix=/opt and for + # all usages of --relocate this path has to be on both sides of the "=": --relocate /opt=<myselectdir>/opt . + if ( $installer::globals::islinuxrpmbuild ) + { + $$relocatablepathref = $rootpath . "\/"; # relocatable path must end with "/", will be "/opt/" + $$staticpathref = $installer::globals::officedirhostname; # to be used as replacement in shell scripts + } + + if ( $installer::globals::islinuxdebbuild ) + { + $$relocatablepathref = ""; + # $$staticpathref is already "/opt/openoffice.org3", no additional $rootpath required. + # $$staticpathref = $rootpath . $installer::globals::separator . $$staticpathref; # no relocatibility for Debian + } + +} + +###################################################### +# Including license and readme into +# Unix installation sets. +###################################################### + +sub put_installsetfiles_into_installset +{ + my ($destdir) = @_; + + # All files for the installation set are saved in the global + # array @installer::globals::installsetfiles + + for ( my $i = 0; $i <= $#installer::globals::installsetfiles; $i++ ) + { + my $onefile = $installer::globals::installsetfiles[$i]; + my $sourcefile = $onefile->{'sourcepath'}; + my $destfile = ""; + if ( $installer::globals::addjavainstaller ) { $destfile = $onefile->{'Name'}; } + else { $destfile = $destdir . $installer::globals::separator . $onefile->{'Name'}; } + installer::systemactions::copy_one_file($sourcefile, $destfile); + + my $infoline = "Adding to installation set \"$destfile\" from source \"$sourcefile\".\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +###################################################### +# Replacing one variable in patchinfo file +###################################################### + +sub replace_one_variable_in_file +{ + my ( $file, $placeholder, $value ) = @_; + + for ( my $i = 0; $i <= $#{$file}; $i++ ) + { + ${$file}[$i] =~ s/$placeholder/$value/g; + } +} + +###################################################### +# Setting variables in the patchinfo file +###################################################### + +sub set_patchinfo +{ + my ( $patchinfofile, $patchid, $allvariables ) = @_; + + # Setting: PATCHIDPLACEHOLDER and ARCHITECTUREPLACEHOLDER and PATCHCORRECTSPLACEHOLDER + + replace_one_variable_in_file($patchinfofile, "PATCHIDPLACEHOLDER", $patchid); + + my $architecture = ""; + if ( $installer::globals::issolarissparcbuild ) { $architecture = "sparc"; } + if ( $installer::globals::issolarisx86build ) { $architecture = "i386"; } + + replace_one_variable_in_file($patchinfofile, "ARCHITECTUREPLACEHOLDER", $architecture); + + if ( ! $allvariables->{'SOLARISPATCHCORRECTS'} ) { installer::exiter::exit_program("ERROR: No setting for PATCH_CORRECTS in zip list file!", "set_patchinfo"); } + my $patchcorrects = $allvariables->{'SOLARISPATCHCORRECTS'}; + + replace_one_variable_in_file($patchinfofile, "PATCHCORRECTSPLACEHOLDER", $patchcorrects); + + # Setting also PATCH_REQUIRES in patch info file, if entry in zip list file exists + my $requiresstring = ""; + if ( $installer::globals::issolarissparcbuild ) { $requiresstring = "SOLSPARCPATCHREQUIRES"; } + if ( $installer::globals::issolarisx86build ) { $requiresstring = "SOLIAPATCHREQUIRES"; } + + if ( $allvariables->{$requiresstring} ) + { + my $newline = "PATCH_REQUIRES=\"" . $allvariables->{$requiresstring} . "\"" . "\n"; + push(@{$patchinfofile}, $newline); + } +} + +###################################################### +# Finalizing patch: Renaming directory and +# including additional patch files. +###################################################### + +sub finalize_patch +{ + my ( $newepmdir, $allvariables ) = @_; + + my $patchidname = "SOLSPARCPATCHID"; + if ( $installer::globals::issolarisx86build ) { $patchidname = "SOLIAPATCHID"; } + + if ( ! $allvariables->{$patchidname} ) { installer::exiter::exit_program("ERROR: Variable $patchidname not defined in zip list file!", "finalize_patch"); } + my $patchid = $allvariables->{$patchidname}; + installer::systemactions::rename_directory($newepmdir, $patchid); + + # Copying all typical patch files into the patch directory + # All patch file names are stored in @installer::globals::solarispatchfiles + # Location of the file is $installer::globals::patchincludepath + + my $sourcepath = $installer::globals::patchincludepath; + $sourcepath =~ s/\/\s*$//; + + for ( my $i = 0; $i <= $#installer::globals::solarispatchfiles; $i++ ) + { + my $sourcefile = $sourcepath . $installer::globals::separator . $installer::globals::solarispatchfiles[$i]; + my $destfile = $patchid . $installer::globals::separator . $installer::globals::solarispatchfiles[$i]; + installer::systemactions::copy_one_file($sourcefile, $destfile); + } + + # And editing the patchinfo file + + my $patchinfofilename = $patchid . $installer::globals::separator . "patchinfo"; + my $patchinfofile = installer::files::read_file($patchinfofilename); + set_patchinfo($patchinfofile, $patchid, $allvariables); + installer::files::save_file($patchinfofilename, $patchinfofile); +} + +###################################################### +# Finalizing Linux patch: Renaming directory and +# including additional patch files. +###################################################### + +sub finalize_linux_patch +{ + my ( $newepmdir, $allvariables, $includepatharrayref ) = @_; + + # Copying the setup into the patch directory + # and including the list of RPMs into it + + print "... creating patch setup ...\n"; + + installer::logger::include_header_into_logfile("Creating Linux patch setup:"); + + # find and read setup script template + + my $scriptfilename = "linuxpatchscript.sh"; + my $scriptref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$scriptfilename, $includepatharrayref, 0); + if ($$scriptref eq "") { installer::exiter::exit_program("ERROR: Could not find patch script template $scriptfilename!", "finalize_linux_patch"); } + my $scriptfile = installer::files::read_file($$scriptref); + + my $infoline = "Found script file $scriptfilename: $$scriptref \n"; + push( @installer::globals::logfileinfo, $infoline); + + # Collecting all RPMs in the patch directory + + my $fileextension = "rpm"; + my $rpmfiles = installer::systemactions::find_file_with_file_extension($fileextension, $newepmdir); + if ( ! ( $#{$rpmfiles} > -1 )) { installer::exiter::exit_program("ERROR: Could not find rpm in directory $newepmdir!", "finalize_linux_patch"); } + for ( my $i = 0; $i <= $#{$rpmfiles}; $i++ ) { installer::pathanalyzer::make_absolute_filename_to_relative_filename(\${$rpmfiles}[$i]); } + +# my $installline = ""; +# +# for ( my $i = 0; $i <= $#{$rpmfiles}; $i++ ) +# { +# $installline = $installline . " rpm --prefix \$PRODUCTINSTALLLOCATION -U $newepmdir/${$rpmfiles}[$i]\n"; +# } +# +# $installline =~ s/\s*$//; +# +# for ( my $j = 0; $j <= $#{$scriptfile}; $j++ ) +# { +# ${$scriptfile}[$j] =~ s/INSTALLLINES/$installline/; +# } + + # Searching packagename containing -core01 + my $found_package = 0; + my $searchpackagename = ""; + for ( my $i = 0; $i <= $#{$rpmfiles}; $i++ ) + { + if ( ${$rpmfiles}[$i] =~ /-core01-/ ) + { + $searchpackagename = ${$rpmfiles}[$i]; + $found_package = 1; + if ( $searchpackagename =~ /^\s*(.*?-core01)-.*/ ) { $searchpackagename = $1; } + last; + } + } + + if ( ! $found_package ) { installer::exiter::exit_program("ERROR: No package containing \"-core01\" found in directory \"$newepmdir\"", "finalize_linux_patch"); } + + # Replacing the searchpackagename + for ( my $j = 0; $j <= $#{$scriptfile}; $j++ ) { ${$scriptfile}[$j] =~ s/SEARCHPACKAGENAMEPLACEHOLDER/$searchpackagename/; } + + # Setting the PRODUCTDIRECTORYNAME to $installer::globals::officedirhostname + for ( my $j = 0; $j <= $#{$scriptfile}; $j++ ) { ${$scriptfile}[$j] =~ s/PRODUCTDIRECTORYNAME/$installer::globals::officedirhostname/; } + + # Replacing the productname + my $productname = $allvariables->{'PRODUCTNAME'}; + $productname = lc($productname); + $productname =~ s/ /_/g; # abc office -> abc_office +# $productname =~ s/\.//g; # openoffice.org -> openofficeorg + + $infoline = "Adding productname $productname into Linux patch script\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $j = 0; $j <= $#{$scriptfile}; $j++ ) { ${$scriptfile}[$j] =~ s/PRODUCTNAMEPLACEHOLDER/$productname/; } + + # Saving the file + + my $newscriptfilename = "setup"; # $newepmdir . $installer::globals::separator . "setup"; + installer::files::save_file($newscriptfilename, $scriptfile); + + $infoline = "Saved Linux patch setup $newscriptfilename \n"; + push( @installer::globals::logfileinfo, $infoline); + + # Setting unix rights 755 + my $localcall = "chmod 775 $newscriptfilename \>\/dev\/null 2\>\&1"; + system($localcall); +} + +1; diff --git a/solenv/bin/modules/installer/existence.pm b/solenv/bin/modules/installer/existence.pm new file mode 100644 index 000000000000..bcdcfa478a78 --- /dev/null +++ b/solenv/bin/modules/installer/existence.pm @@ -0,0 +1,194 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: existence.pm,v $ +# +# $Revision: 1.6 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::existence; + +############################# +# Test of existence +############################# + +sub exists_in_array +{ + my ($searchstring, $arrayref) = @_; + + my $alreadyexists = 0; + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + if ( ${$arrayref}[$i] eq $searchstring) + { + $alreadyexists = 1; + last; + } + } + + return $alreadyexists; +} + +sub exists_in_array_of_hashes +{ + my ($searchkey, $searchvalue, $arrayref) = @_; + + my $valueexists = 0; + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + my $hashref = ${$arrayref}[$i]; + + if ( $hashref->{$searchkey} eq $searchvalue ) + { + $valueexists = 1; + last; + } + } + + return $valueexists; +} + +##################################################################### +# Returning a specified file as base for the new +# configuration file, defined by its "gid" +##################################################################### + +sub get_specified_file +{ + my ($filesarrayref, $searchgid) = @_; + + my $foundfile = 0; + my $onefile; + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + $onefile = ${$filesarrayref}[$i]; + my $filegid = $onefile->{'gid'}; + + if ( $filegid eq $searchgid ) + { + $foundfile = 1; + last; + } + } + + my $errorline = "ERROR: Could not find file $searchgid in list of files!"; + + if ( $installer::globals::patch) { $errorline = "ERROR: Could not find file $searchgid in list of files! intro.bmp must be part of every patch. Please assign the flag PATCH in scp2 project."; } + + if (!($foundfile)) + { + installer::exiter::exit_program($errorline, "get_specified_file"); + } + + return $onefile; +} + +##################################################################### +# Returning a specified file as base for a new file, +# defined by its "Name" +##################################################################### + +sub get_specified_file_by_name +{ + my ($filesarrayref, $searchname) = @_; + + my $foundfile = 0; + my $onefile; + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + $onefile = ${$filesarrayref}[$i]; + my $filename = $onefile->{'Name'}; + + if ( $filename eq $searchname ) + { + $foundfile = 1; + last; + } + } + + if (!($foundfile)) + { + installer::exiter::exit_program("ERROR: Could not find file $searchname in list of files!", "get_specified_file_by_name"); + } + + return $onefile; +} + +##################################################################### +# Checking existence of a specific file, defined by its "Name" +##################################################################### + +sub filename_exists_in_filesarray +{ + my ($filesarrayref, $searchname) = @_; + + my $foundfile = 0; + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + my $filename = $onefile->{'Name'}; + + if ( $filename eq $searchname ) + { + $foundfile = 1; + last; + } + } + + return $foundfile; +} + +##################################################################### +# Checking existence of a specific file, defined by its "gid" +##################################################################### + +sub filegid_exists_in_filesarray +{ + my ($filesarrayref, $searchgid) = @_; + + my $foundfile = 0; + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + my $filegid = $onefile->{'gid'}; + + if ( $filegid eq $searchgid ) + { + $foundfile = 1; + last; + } + } + + return $foundfile; +} + +1; diff --git a/solenv/bin/modules/installer/exiter.pm b/solenv/bin/modules/installer/exiter.pm new file mode 100644 index 000000000000..005e0375e803 --- /dev/null +++ b/solenv/bin/modules/installer/exiter.pm @@ -0,0 +1,113 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: exiter.pm,v $ +# +# $Revision: 1.8 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::exiter; + +use installer::files; +use installer::globals; +use installer::logger; +use installer::systemactions; +use installer::worker; + +############################################ +# Exiting the program with an error +# This function is used instead of "die" +############################################ + +sub exit_program +{ + my ($message, $function) = @_; + + # If an installation set is currently created, the directory name is saved in $installer::globals::saveinstalldir + # If this directory name matches with "_inprogress", it has to be renamed into "_witherror" + + if ( $installer::globals::saveinstalldir =~ /_inprogress/ ) { installer::systemactions::rename_string_in_directory($installer::globals::saveinstalldir, "_inprogress", "_witherror"); } + + # Cleaning files from pool tooling + if ( $installer::globals::processhaspoolcheckfile ) { unlink $installer::globals::poolcheckfilename; } + if ( $installer::globals::processhaspoollockfile ) { unlink $installer::globals::poollockfilename; } + + installer::worker::clean_output_tree(); # removing directories created in the output tree + + # If @installer::globals::logfileinfo is not empty, it can be used. + # Otherwise the content of @installer::globals::globallogfileinfo has to be used. + + my $infoline; + + $installer::globals::logfilename = $installer::globals::exitlog . $installer::globals::logfilename; + + if ( ! $installer::globals::globalinfo_copied ) { installer::logger::copy_globalinfo_into_logfile(); } + + if ( $#installer::globals::logfileinfo > -1 ) + { + $infoline = "\n***************************************************************\n"; + push(@installer::globals::logfileinfo, $infoline); + + $infoline = "$message\n"; + push(@installer::globals::logfileinfo, $infoline); + + $infoline = "in function: $function\n"; + push(@installer::globals::logfileinfo, $infoline); + + $infoline = "***************************************************************\n"; + push(@installer::globals::logfileinfo, $infoline); + + installer::files::save_file($installer::globals::logfilename ,\@installer::globals::logfileinfo); + } + else + { + $infoline = "\n***************************************************************\n"; + push(@installer::globals::globallogfileinfo, $infoline); + + $infoline = "$message\n"; + push(@installer::globals::globallogfileinfo, $infoline); + + $infoline = "in function: $function\n"; + push(@installer::globals::globallogfileinfo, $infoline); + + $infoline = "***************************************************************\n"; + push(@installer::globals::globallogfileinfo, $infoline); + + installer::files::save_file($installer::globals::logfilename ,\@installer::globals::globallogfileinfo); + } + installer::logger::print_error("$message\nin function: $function"); + installer::logger::print_error("Saved logfile: $installer::globals::logfilename\n"); + + # Saving the debug info + + if ( $installer::globals::debug ) { installer::logger::savedebug($installer::globals::exitlog); } + + installer::logger::stoptime(); + + exit(-1); +} + +1; diff --git a/solenv/bin/modules/installer/files.pm b/solenv/bin/modules/installer/files.pm new file mode 100644 index 000000000000..db869ad7906a --- /dev/null +++ b/solenv/bin/modules/installer/files.pm @@ -0,0 +1,223 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: files.pm,v $ +# +# $Revision: 1.9 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::files; + +use installer::exiter; +use installer::logger; + +############################################ +# File Operations +############################################ + +sub check_file +{ + my ($arg) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::files::check_file : $arg"); } + + if(!( -f $arg )) + { + installer::exiter::exit_program("ERROR: Cannot find file $arg", "check_file"); + } +} + +sub read_file +{ + my ($localfile) = @_; + my @localfile = (); + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::files::read_file : $localfile"); } + + open( IN, "<$localfile" ) || installer::exiter::exit_program("ERROR: Cannot open file $localfile for reading", "read_file"); + +# Don't use "my @localfile = <IN>" here, because +# perl has a problem with the internal "large_and_huge_malloc" function +# when calling perl using MacOS 10.5 with a perl built with MacOS 10.4 + while ( $line = <IN> ) { + push @localfile, $line; + } + + close( IN ); + + return \@localfile; +} + +########################################### +# Saving files, arrays and hashes +########################################### + +sub save_file +{ + my ($savefile, $savecontent) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::files::save_file : $savefile : $#{$savecontent}"); } + + if ( open( OUT, ">$savefile" ) ) + { + print OUT @{$savecontent}; + close( OUT); + } + else + { + # it is useless to save a log file, if there is no write access + + if ( $savefile =~ /\.log/ ) + { + print "\n*************************************************\n"; + print "ERROR: Cannot write log file: $savefile"; + print "\n*************************************************\n"; + exit(-1); # exiting the program to avoid endless loops + } + + installer::exiter::exit_program("ERROR: Cannot open file $savefile for writing", "save_file"); + } +} + +sub save_hash +{ + my ($savefile, $hashref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::files::save_hash : $savefile"); } + + my @printcontent = (); + + my $itemkey; + + foreach $itemkey ( keys %{$hashref} ) + { + my $line = ""; + my $itemvalue = $hashref->{$itemkey}; + $line = $itemkey . "=" . $itemvalue . "\n"; + push(@printcontent, $line); + } + + open( OUT, ">$savefile" ) || installer::exiter::exit_program("ERROR: Cannot open file $savefile for writing", "save_hash"); + print OUT @printcontent; + close( OUT); +} + +sub save_array_of_hashes +{ + my ($savefile, $arrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::files::save_array_of_hashes : $savefile : $#{$arrayref}"); } + + my @printcontent = (); + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + my $line = ""; + my $hashref = ${$arrayref}[$i]; + my $itemkey; + + foreach $itemkey ( keys %{$hashref} ) + { + my $itemvalue = $hashref->{$itemkey}; + $line = $line . $itemkey . "=" . $itemvalue . "\t"; + } + + $line = $line . "\n"; + + push(@printcontent, $line); + } + + open( OUT, ">$savefile" ) || installer::exiter::exit_program("ERROR: Cannot open file $savefile for writing", "save_array_of_hashes"); + print OUT @printcontent; + close( OUT); +} + +sub save_array_of_hashes_modules +{ + my ($savefile, $arrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::files::save_array_of_hashes : $savefile : $#{$arrayref}"); } + + my @printcontent = (); + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + my $line = "***************************************************\n"; + my $hashref = ${$arrayref}[$i]; + my $itemkey; + + foreach $itemkey ( keys %{$hashref} ) + { + my $itemvalue = $hashref->{$itemkey}; + $line = $line . $itemkey . "=" . $itemvalue . "\n"; + } + + $line = $line . "\n"; + + push(@printcontent, $line); + } + + open( OUT, ">$savefile" ) || installer::exiter::exit_program("ERROR: Cannot open file $savefile for writing", "save_array_of_hashes"); + print OUT @printcontent; + close( OUT); +} + +########################################### +# Binary file operations +########################################### + +sub read_binary_file +{ + my ($filename) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::files::read_binary_file : $filename"); } + + my $file; + + open( IN, "<$filename" ) || installer::exiter::exit_program("ERROR: Cannot open file $filename for reading", "read_binary_file"); + binmode IN; + seek IN, 0, 2; + my $length = tell IN; + seek IN, 0, 0; + read IN, $file, $length; + close IN; + + return $file; +} + +sub save_binary_file +{ + my ($file, $filename) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::files::save_binary_file : $filename"); } + + open( OUT, ">$filename" ) || installer::exiter::exit_program("ERROR: Cannot open file $filename for writing", "save_binary_file"); + binmode OUT; + print OUT $file; + close OUT; +} + +1; diff --git a/solenv/bin/modules/installer/followme.pm b/solenv/bin/modules/installer/followme.pm new file mode 100644 index 000000000000..fe61f10b023d --- /dev/null +++ b/solenv/bin/modules/installer/followme.pm @@ -0,0 +1,208 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: environment.pm,v $ +# +# $Revision: 1.14 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::followme; + +use File::Spec; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::logger; +use installer::systemactions; + +#################################################### +# Creating a file, that contains all information +# to create a follow up process. +#################################################### + +sub save_followme_info +{ + my ($finalinstalldir, $includepatharrayref, $allvariableshashref, $downloadname, $languagestringref, $languagesarrayref, $current_install_number, $loggingdir, $installlogdir) = @_; + + my $downloadinfofilename = $installer::globals::logfilename; + if ( $installer::globals::updatepack ) { $downloadinfofilename =~ s/log_/log_$current_install_number\_/; } + $downloadinfofilename =~ s/log_/follow_me_/; + + # Creating directory + my $downloadinfodir = installer::systemactions::create_directory_next_to_directory($finalinstalldir, "follow_me"); + + my @filecontent = (); + + push(@filecontent, "finalinstalldir: $finalinstalldir\n"); + push(@filecontent, "downloadname: $downloadname\n"); + push(@filecontent, "currentinstallnumber: $current_install_number\n"); + push(@filecontent, "loggingdir: $loggingdir\n"); + push(@filecontent, "installlogdir: $installlogdir\n"); + push(@filecontent, "languagestring: $$languagestringref\n"); + foreach my $element ( @{$languagesarrayref} ) { push(@filecontent, "languagesarray: $element\n"); } + foreach my $path ( @{$includepatharrayref} ) { push(@filecontent, "includepatharray: $path"); } + foreach my $key ( sort keys %{$allvariableshashref} ) { push(@filecontent, "allvariableshash: $key : $allvariableshashref->{$key}\n"); } + push(@filecontent, "globals:updatepack: $installer::globals::updatepack\n"); + push(@filecontent, "globals:added_english: $installer::globals::added_english\n"); + push(@filecontent, "globals:iswindowsbuild: $installer::globals::iswindowsbuild\n"); + push(@filecontent, "globals:issolarisbuild: $installer::globals::issolarisbuild\n"); + push(@filecontent, "globals:issolarispkgbuild: $installer::globals::issolarispkgbuild\n"); + push(@filecontent, "globals:issolarissparcbuild: $installer::globals::issolarissparcbuild\n"); + push(@filecontent, "globals:issolarisx86build: $installer::globals::issolarisx86build\n"); + push(@filecontent, "globals:isfreebsdpkgbuild: $installer::globals::isfreebsdpkgbuild\n"); + push(@filecontent, "globals:islinuxbuild: $installer::globals::islinuxbuild\n"); + push(@filecontent, "globals:islinuxrpmbuild: $installer::globals::islinuxrpmbuild\n"); + push(@filecontent, "globals:islinuxintelrpmbuild: $installer::globals::islinuxintelrpmbuild\n"); + push(@filecontent, "globals:islinuxppcrpmbuild: $installer::globals::islinuxppcrpmbuild\n"); + push(@filecontent, "globals:islinuxx86_64rpmbuild: $installer::globals::islinuxx86_64rpmbuild\n"); + push(@filecontent, "globals:islinuxdebbuild: $installer::globals::islinuxdebbuild\n"); + push(@filecontent, "globals:islinuxinteldebbuild: $installer::globals::islinuxinteldebbuild\n"); + push(@filecontent, "globals:islinuxppcdebbuild: $installer::globals::islinuxppcdebbuild\n"); + push(@filecontent, "globals:islinuxx86_64debbuild: $installer::globals::islinuxx86_64debbuild\n"); + push(@filecontent, "globals:issolaris: $installer::globals::issolaris\n"); + push(@filecontent, "globals:islinux: $installer::globals::islinux\n"); + push(@filecontent, "globals:unpackpath: $installer::globals::unpackpath\n"); + push(@filecontent, "globals:idttemplatepath: $installer::globals::idttemplatepath\n"); + push(@filecontent, "globals:idtlanguagepath: $installer::globals::idtlanguagepath\n"); + push(@filecontent, "globals:logfilename: $installer::globals::logfilename\n"); + push(@filecontent, "globals:product: $installer::globals::product\n"); + push(@filecontent, "globals:patch: $installer::globals::patch\n"); + push(@filecontent, "globals:languagepack: $installer::globals::languagepack\n"); + push(@filecontent, "globals:installertypedir: $installer::globals::installertypedir\n"); + push(@filecontent, "globals:max_lang_length: $installer::globals::max_lang_length\n"); + push(@filecontent, "globals:compiler: $installer::globals::compiler\n"); + push(@filecontent, "globals:product: $installer::globals::product\n"); + push(@filecontent, "globals:minor: $installer::globals::minor\n"); + push(@filecontent, "globals:lastminor: $installer::globals::lastminor\n"); + push(@filecontent, "globals:nsisfilename: $installer::globals::nsisfilename\n"); + + # Saving file + installer::files::save_file($downloadinfodir . $installer::globals::separator . $downloadinfofilename, \@filecontent); + installer::logger::print_message( "... creating \"follow me\" info file $downloadinfofilename.\n" ); +} + +#################################################### +# Reading the file, that contains all information +# to create a follow up process. +#################################################### + +sub read_followme_info +{ + my ( $filename ) = @_; + + if ( ! -f $filename ) { installer::exiter::exit_program("ERROR: Could not find file: $filename", "read_download_info"); } + + installer::logger::print_message( "\n... reading \"follow me\" info file $filename\n" ); + + my %contenthash = (); + + my $finalinstalldir = ""; + my $downloadname = ""; + my $currentinstallnumber = ""; + my $loggingdir = ""; + my $installlogdir = ""; + my $languagestring = ""; + my @includepatharray = (); + my @languagesarray = (); + my %allvariableshash = (); + + # Global variables can be set directly + + my $filecontent = installer::files::read_file($filename); + + # First line has to contain the string "finalinstalldir:". + # Otherwise this is not a correct file. + + + if ( ! ( ${$filecontent}[0] =~ /s*finalinstalldir:\s*(.*?)\s*$/ )) { installer::exiter::exit_program("ERROR: Not a correct download info file: $filename", "read_download_info"); } + + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + my $line = ${$filecontent}[$i]; + + if ( $line =~ /^\s*finalinstalldir:\s*(.*?)\s*$/ ) { $finalinstalldir = $1; } + if ( $line =~ /^\s*downloadname:\s*(.*?)\s*$/ ) { $downloadname = $1; } + if ( $line =~ /^\s*currentinstallnumber:\s*(.*?)\s*$/ ) { $currentinstallnumber = $1; } + if ( $line =~ /^\s*loggingdir:\s*(.*?)\s*$/ ) { $loggingdir = $1; } + if ( $line =~ /^\s*installlogdir:\s*(.*?)\s*$/ ) { $installlogdir = $1; } + if ( $line =~ /^\s*languagestring:\s*(.*?)\s*$/ ) { $languagestring = $1; } + if ( $line =~ /^\s*languagesarray:\s*(.*?)\s*$/ ) { push(@languagesarray, $1); } + if ( $line =~ /^\s*includepatharray:\s*(.*?)\s*$/ ) { push(@includepatharray, $1 . "\n"); } + if ( $line =~ /^\s*allvariableshash:\s*(.*?)\s*:\s*(.*?)\s*$/ ) { $allvariableshash{$1} = $2; } + if ( $line =~ /^\s*globals:(.*?)\s*:\s*(.*?)\s*$/ ) + { + my $name = $1; + my $value = $2; + if ( $name eq "updatepack" ) { $installer::globals::updatepack = $value; } + if ( $name eq "added_english" ) { $installer::globals::added_english = $value; } + if ( $name eq "iswindowsbuild" ) { $installer::globals::iswindowsbuild = $value; } + if ( $name eq "issolarisbuild" ) { $installer::globals::issolarisbuild = $value; } + if ( $name eq "issolarispkgbuild" ) { $installer::globals::issolarispkgbuild = $value; } + if ( $name eq "issolarissparcbuild" ) { $installer::globals::issolarissparcbuild = $value; } + if ( $name eq "issolarisx86build" ) { $installer::globals::issolarisx86build = $value; } + if ( $name eq "isfreebsdpkgbuild" ) { $installer::globals::isfreebsdpkgbuild = $value; } + if ( $name eq "islinuxbuild" ) { $installer::globals::islinuxbuild = $value; } + if ( $name eq "islinuxrpmbuild" ) { $installer::globals::islinuxrpmbuild = $value; } + if ( $name eq "islinuxintelrpmbuild" ) { $installer::globals::islinuxintelrpmbuild = $value; } + if ( $name eq "islinuxppcrpmbuild" ) { $installer::globals::islinuxppcrpmbuild = $value; } + if ( $name eq "islinuxx86_64rpmbuild" ) { $installer::globals::islinuxx86_64rpmbuild = $value; } + if ( $name eq "islinuxdebbuild" ) { $installer::globals::islinuxdebbuild = $value; } + if ( $name eq "islinuxinteldebbuild" ) { $installer::globals::islinuxinteldebbuild = $value; } + if ( $name eq "islinuxppcdebbuild" ) { $installer::globals::islinuxppcdebbuild = $value; } + if ( $name eq "islinuxx86_64debbuild" ) { $installer::globals::islinuxx86_64debbuild = $value; } + if ( $name eq "issolaris" ) { $installer::globals::issolaris = $value; } + if ( $name eq "islinux" ) { $installer::globals::islinux = $value; } + if ( $name eq "unpackpath" ) { $installer::globals::unpackpath = $value; } + if ( $name eq "idttemplatepath" ) { $installer::globals::idttemplatepath = $value; } + if ( $name eq "idtlanguagepath" ) { $installer::globals::idtlanguagepath = $value; } + if ( $name eq "logfilename" ) { $installer::globals::logfilename = $value; } + if ( $name eq "product" ) { $installer::globals::product = $value; } + if ( $name eq "patch" ) { $installer::globals::patch = $value; } + if ( $name eq "languagepack" ) { $installer::globals::languagepack = $value; } + if ( $name eq "installertypedir" ) { $installer::globals::installertypedir = $value; } + if ( $name eq "max_lang_length" ) { $installer::globals::max_lang_length = $value; } + if ( $name eq "compiler" ) { $installer::globals::compiler = $value; } + if ( $name eq "product" ) { $installer::globals::product = $value; } + if ( $name eq "minor" ) { $installer::globals::minor = $value; } + if ( $name eq "lastminor" ) { $installer::globals::lastminor = $value; } + if ( $name eq "nsisfilename" ) { $installer::globals::nsisfilename = $value; } + } + } + + $contenthash{'finalinstalldir'} = $finalinstalldir; + $contenthash{'downloadname'} = $downloadname; + $contenthash{'currentinstallnumber'} = $currentinstallnumber; + $contenthash{'loggingdir'} = $loggingdir; + $contenthash{'installlogdir'} = $installlogdir; + $contenthash{'languagestring'} = $languagestring; + $contenthash{'languagesarray'} = \@languagesarray; + $contenthash{'includepatharray'} = \@includepatharray; + $contenthash{'allvariableshash'} = \%allvariableshash; + + return \%contenthash; +} + +1; diff --git a/solenv/bin/modules/installer/globals.pm b/solenv/bin/modules/installer/globals.pm new file mode 100644 index 000000000000..38fae7ff2fe0 --- /dev/null +++ b/solenv/bin/modules/installer/globals.pm @@ -0,0 +1,553 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: globals.pm,v $ +# +# $Revision: 1.103.16.2 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::globals; + +############################################ +# Global settings +############################################ + +BEGIN +{ + $prog="make_installer.pl"; + + @noMSLocaleLangs = ( + "br", + "bs", + "dz", + "gu", + "km", + "nr", + "ns", + "rw", + "ss", + "st", + "tg", + "ts", + "tn", + "ve", + "xh", + "zu", + "ne", + "bn", + "bn-BD", + "bn-IN", + "lo", + "cy", + "ku", + "as-IN", + "te-IN", + "ml-IN", + "mr-IN", + "ur-IN", + "ta-IN", + "or-IN", + "ti-ER", + "eo", + "ka", + "ga", + "uk", + "gd", + "my", + "mai", + "brx", + "dgo", + "kok", + "mni", + "sat" + + ); + @items_at_modules = ("Files", "Dirs", "Unixlinks"); + @asianlanguages = ("ja", "ko", "zh-CN", "zh-TW"); + @bidilanguages = ("ar", "he"); + + $ziplistname = ""; + $pathfilename = ""; + $setupscriptname = ""; + $headerfilename = ""; + $shellscriptsfilename = ""; + $product = ""; + $languagelist = ""; + $added_english = 0; + $set_office_start_language = 0; + $solarjavaset = 0; + + $destdir = ""; + $rootpath = ""; + + $required_dotnet_version = "2.0.0.0"; + $productextension = ""; + @languageproducts = (); + $build = ""; + $minor = ""; + $lastminor = ""; + $compiler = ""; + $pro = 0; + $dounzip = 1; + $languages_defined_in_productlist = 0; + $setupscript_defined_in_productlist = 0; + $services_rdb_created = 0; + $servicesrdb_can_be_created = 0; + $islinux = 0; + $issolaris = 0; + $ismacosx = 0; + $iswindowsbuild = 0; + $islinuxbuild = 0; + $islinuxrpmbuild = 0; + $islinuxdebbuild = 0; + $islinuxintelrpmbuild = 0; + $islinuxppcrpmbuild = 0; + $islinuxinteldebbuild = 0; + $islinuxppcdebbuild = 0; + $islinuxx86_64rpmbuild = 0; + $islinuxx86_64debbuild = 0; + $issolarisbuild = 0; + $issolarispkgbuild = 0; + $issolarissparcbuild = 0; + $issolarisx86build = 0; + $isfreebsdpkgbuild = 0; + $unpackpath = ""; + $idttemplatepath = ""; + $idtlanguagepath = ""; + $packjobref = ""; + $buildid = "Not set"; + $guidcounter = 1000; # for uniqueness of guids + $fontsfolder = "FontsFolder"; + $fontsfoldername = "Fonts"; + $fontsdirparent = ""; + $fontsdirname = ""; + $fontsdirhostname = "truetype"; + $officefolder = "OfficeFolder"; + $officemenufolder = "OfficeMenuFolder"; + $startupfolder = "StartupFolder"; + $startmenufolder = "StartMenuFolder"; + $desktopfolder = "DesktopFolder"; + $programfilesfolder = "ProgramFilesFolder"; + $commonfilesfolder = "CommonFilesFolder"; + $commonappdatafolder = "CommonAppDataFolder"; + $localappdatafolder = "LocalAppDataFolder"; + $templatefolder = "TemplateFolder"; + $templatefoldername = "Templates"; + $programmenufolder = "ProgramMenuFolder"; + $systemfolder = "SystemFolder"; + $encodinglistname = "msi-encodinglist.txt"; + $msiencoding = ""; # hash reference for msi encodings + $msilanguage = ""; # hash reference for msi languages LCID + $sofficeiconadded = 0; + $temppath = ""; + $globaltempdirname = "ooopackaging"; + $cyg_temppath = ""; + $temppathdefined = 0; + $jdstemppathdefined = 0; + $packageversion = 1; + $packagerevision = 1; + $rpm = ""; + $rpmcommand = ""; + $rpmquerycommand = ""; + $debian = ""; + $installertypedir = ""; + $controlledmakecabversion = "5"; + $saved_packages_path = ""; + $max_lang_length = 50; + $globalblock = "Globals"; + $rootmodulegid = ""; + %alllangmodules = (); + $englishlicenseset = 0; + $englishlicense = ""; + $englishsolarislicensename = "LICENSE_en-US"; + $patharray = ""; + + $is_special_epm = 0; + $epm_in_path = 0; + $epm_path = ""; + $epmoutpath = ""; + $upx_in_path = 0; + $upxfile = ""; + $simple = 0; + $simpledefaultuserdir = "\$ORIGIN/.."; + $call_epm = 1; + $packageformat = ""; + $packagename = ""; + $packagelist = ""; + $addpackagelist = ""; + $is_unix_multi = 0; + $unixmultipath = ""; + $unixmultipath_orig = ""; + $alllanguagesinproductarrayref = ""; + $shiptestdirectory = ""; + $makelinuxlinkrpm = 0; + $linuxlinkrpmprocess = 0; + $add_required_package = ""; + $linuxrespin = 0; + @linuxpatchfiles = (); + $linuxlibrarybaselevel = "1"; + $linuxlibrarypatchlevel = "1.1"; + @linuxlinks = (); + @linkrpms = (); + $archiveformat = ""; + $minorupgradekey = ""; + $updatelastsequence = 0; + $updatesequencecounter = 0; + $updatedatabase = 0; + $updatedatabasepath = ""; + $pfffileexists = 0; + $pffcabfilename = "ooobasis3.0_pff.cab"; + $mergemodulenumber = 0; + %allmergemodulefilesequences = (); + %newupdatefiles = (); + %allusedupdatesequences = (); + %mergemodulefiles = (); + $mergefiles_added_into_collector = 0; + $creating_windows_installer_patch = 0; + + $strip = 1; + $solarjava = 0; + $jdklib = ""; + $jrepath = ""; + + $globallogging = 0; + $globalloggingform21 = 1; + $logfilename = "logfile.log"; # the default logfile name for global errors + @logfileinfo = (); + @errorlogfileinfo = (); + @globallogfileinfo = (); + $exitlog = ""; + $globalinfo_copied = 0; + $quiet = 0; + + $debug = 0; + $debugfilename = "debug.txt"; + $checksumfilename = "checksum.txt"; + @functioncalls = (); + + $ismultilingual = 0; + @multilanguagemodules = (); + $languagemodulesbase = "gid_Module_Root_"; + %alluniquefilenames = (); + %alllcuniquefilenames = (); + %uniquefilenamesequence = (); + %dependfilenames = (); + $isopensourceproduct = 1; + $manufacturer = ""; + $longmanufacturer = ""; + $sundirname = "Sun"; + $codefilename = "codes.txt"; + $componentfilename = "components.txt"; + $productcode = ""; + $upgradecode = ""; + $msiproductversion = ""; + $msimajorproductversion = ""; + $created_new_component_guid = 0; + @allddffiles = (); + $infodirectory = ""; + @currentcontent = (); + @installsetcontent = (); + %xpdpackageinfo = (); + $signfiles_checked = 0; + $dosign = 0; + $pwfile = ""; + $pwfile = ""; + $pfxfile = ""; + + %mergemodules = (); + %merge_media_line = (); + %merge_allfeature_hash = (); + %merge_alldirectory_hash = (); + %copy_msm_files = (); + $mergefeaturecollected = 0; + $mergedirectoriescollected = 0; + $lastsequence_before_merge = 0; + $lastcabfilename = ""; + + $createdxpddefaultlang = 0; + $xpddir = ""; + $productxpdfile = "setup.xpd"; + $xpd_files_prepared = 0; + $defaultlanguage = ""; + # @emptyxpdparents = (); + @createdxpdfiles = (); + @allxpdfiles = (); + $isxpdplatform = 0; + $javalanguagepath = ""; + $javasettozero = 0; + $addlicensefile = 1; + $addsystemintegration = 0; + $addjavainstaller = 0; + $added_directories = 0; + $makedownload = 1; + $makejds = 1; + $jdsexcludefilename = ""; + $jds_language_controlled = 0; + $correct_jds_language = 0; + @installsetfiles = (); + @binarytableonlyfiles = (); + @allscpactions = (); + $languagepackaddon = "LanguagePack"; + $patchaddon = "Patch"; + $ooodownloadfilename = ""; + $downloadfilename = ""; + $downloadfileextension = ""; + $followmeinfofilename = ""; + $oooversionstring = ""; + $shellnewfilesadded = 0; + %multilingual_only_modules = (); + %application_modules = (); + $defaultinstallorder = 1000; + $defaultsystemintinstallorder = 1200; + + $is_copy_only_project = 0; + $is_simple_packager_project = 0; + $patch_user_dir = 0; + $addchildprojects = 0; + $languagepack = 0; + $tab = 0; + $patch = 0; + $patchincludepath = ""; + $refresh_includepathes = 0; + $patchfilelistname = "patchfilelist.txt"; + @patchfilecollector = (); + $nopatchfilecollector = ""; + @userregistrycollector = (); + $addeduserregitrykeys = 0; + $poolpathset = 0; + $poolpath = 0; + $poollockfilename = ""; + $poolcheckfilename = ""; + %poolshiftedpackages = (); + %poolpackages = (); + %createpackages = (); + $processhaspoolcheckfile = 0; + $processhaspoollockfile = 0; + $newpcfcontentcalculated = 0; + $sessionid = 0; + $sessionidset = 0; + $savelockfilecontent = ""; + $savelockfilename = ""; + $getuidpath = ""; + $getuidpathset = 0; + $newpcfcontent = ""; + %pcfdifflist = (); + @pcfdiffcomment = (); + @epmdifflist = (); + $desktoplinkexists = 0; + $sundirexists = 0; + $analyze_spellcheckerlanguage = 0; + %spellcheckerlanguagehash = (); + %spellcheckerfilehash = (); + $registryrootcomponent = ""; + + $officeinstalldirectory = ""; + $officeinstalldirectoryset = 0; + $basisinstalldirectory = ""; + $basisinstalldirectoryset = 0; + $ureinstalldirectory = ""; + $ureinstalldirectoryset = 0; + $rootbrandpackage = ""; + $rootbrandpackageset = 0; + $officedirhostname = ""; + $basisdirhostname = ""; + $uredirhostname = ""; + $sundirhostname = ""; + $officedirgid = ""; + $basisdirgid = ""; + $uredirgid = ""; + $sundirgid = ""; + + %treestyles = ("UREDIRECTORY" => "INSTALLURE", "BASISDIRECTORY" => "INSTALLBASIS", "OFFICEDIRECTORY" => "INSTALLOFFICE"); + %installlocations = ("INSTALLLOCATION" => "1", "BASISINSTALLLOCATION" => "1", "OFFICEINSTALLLOCATION" => "1", "UREINSTALLLOCATION" => "1"); + %treelayername = ("UREDIRECTORY" => "URE", "BASISDIRECTORY" => "BASIS", "OFFICEDIRECTORY" => "BRAND"); + %hostnametreestyles = (); + %treeconditions = (); + %usedtreeconditions = (); + %moduledestination = (); + + $unomaxservices = 25; + $javamaxservices = 15; + + $one_cab_file = 0; + $fix_number_of_cab_files = 1; + $cab_file_per_component = 0; + $cabfilecompressionlevel = 2; + $number_of_cabfiles = 1; # only for $fix_number_of_cab_files = 1 + $include_cab_in_msi = 0; + $use_packages_for_cabs = 0; + $msidatabasename = ""; + $prepare_winpatch = 0; + $previous_idt_dir = ""; + $updatepack = 0; + $msitranpath = ""; + $insert_file_at_end = 0; + $newfilesexist = 0; + $usesharepointpath = 0; + %newfilescollector = (); + + $saveinstalldir = ""; + $csp_installdir = ""; # global installdir of createsimplepackage() in simplepackage.pm + $csp_installlogdir = ""; # global installlogdir of createsimplepackage() in simplepackage.pm + $csp_languagestring = ""; # global languagestring of createsimplepackage() in simplepackage.pm + $localunpackdir = ""; + $localinstalldirset = 0; + $localinstalldir = ""; + + $javafilename = ""; + $javafilename2 = ""; + $javafilename3 = ""; + $javafile = ""; + $urefile = ""; + + $postprocess_specialepm = 0; + $postprocess_standardepm = 0; + $mergemodules_analyzed = 0; + + $starttime = ""; + + @solarispatchscripts = ("checkinstall", "copyright", "patch_checkinstall", "patch_postinstall", "postinstall", "preinstall", "i.none"); + @solarispatchscriptsforextensions = ("checkinstall", "copyright", "patch_checkinstall", "patch_postinstall_extensions", "postinstall_extensions", "preinstall", "i.none"); + @solarispatchfiles = (".diPatch", "patchinfo"); + @environmentvariables = ( "SOLARVERSION", "GUI", "WORK_STAMP", "OUTPATH", "LOCAL_OUT", "LOCAL_COMMON_OUT" ); + @packagelistitems = ("module", "solarispackagename", "packagename", "copyright", "vendor", "description" ); + @regcompjars = ( "unoil.jar", "java_uno.jar", "ridl.jar", "jurt.jar", "juh.jar", "xmerge.jar", "commonwizards.jar" ); + @regcompregisterlibs = ( "javavm.uno", "javaloader.uno", "stocservices.uno" ); + @languagepackfeature =(); + @featurecollector =(); + $msiassemblyfiles = ""; + $nsisfilename = "Nsis"; + $nsis204 = 0; + $nsis231 = 0; + $unicodensis = 0; + $linuxlinkrpms = ""; + $extensioninstalldir = "gid_Dir_Share_Extension_Install"; + @languagenames = (); + @requiredpackages = (); + %componentcondition = (); + %componentid = (); + %comparecomponentname = (); + %languageproperties = (); + %allcabinets = (); + %allcabinetassigns = (); + %cabfilecounter = (); + %lastsequence = (); + %dontdeletecomponents = (); + %allcalculated_guids = (); + %calculated_component_guids = (); + %base_independent_components = (); + %all_english_languagestrings = (); + %all_required_english_languagestrings = (); + + @forced_properties = ("SERVICETAG_PRODUCTNAME", "SERVICETAG_PRODUCTVERSION", "SERVICETAG_PARENTNAME", "SERVICETAG_SOURCE", "SERVICETAG_URN"); + + @removedirs = (); + @jdsremovedirs = (); + @emptypackages = (); + %fontpackageexists = (); + + $plat = $^O; + + if (( $plat =~ /MSWin/i ) || (( $plat =~ /cygwin/i ) && ( $ENV{'USE_SHELL'} eq "4nt" ))) + { + $unzippath = "unzip.exe"; # Has to be in the path: r:\btw\unzip.exe + $zippath= "zip.exe"; # Has to be in the path: r:\btw\zip.exe + $checksumfile = "so_checksum.exe"; + $unopkgfile = "unopkg.exe"; + if ( $plat =~ /cygwin/i ) + { + $separator = "/"; + $pathseparator = "\:"; + $quote = "\'"; + } + else + { + $separator = "\\"; + $pathseparator = "\;"; + $quote = "\""; + } + $libextension = "\.dll"; + $isunix = 0; + $iswin = 1; + $archiveformat = ".zip"; + %savedmapping = (); + %savedrevmapping = (); + %savedrev83mapping = (); + %saved83dirmapping = (); + } + elsif (( $plat =~ /cygwin/i ) && ( $ENV{'USE_SHELL'} ne "4nt" )) + { + $unzippath = "unzip"; # Has to be in the path: /usr/bin/unzip + $zippath = "zip"; # Has to be in the path: /usr/bin/zip + $checksumfile = "so_checksum"; + $unopkgfile = "unopkg.exe"; + $separator = "/"; + $pathseparator = "\:"; + $libextension = "\.dll"; + $quote = "\'"; + $isunix = 0; + $iswin = 1; + $archiveformat = ".zip"; + %savedmapping = (); + %savedrevmapping = (); + %savedrev83mapping = (); + %saved83dirmapping = (); + } + else + { + $unzippath = "unzip"; # Has to be in the path: /usr/bin/unzip + $zippath = "zip"; # Has to be in the path: /usr/bin/zip + $checksumfile = "so_checksum"; + $unopkgfile = "unopkg"; + $separator = "/"; + $pathseparator = "\:"; + if ( $plat =~ /darwin/i ) + { + $libextension = "\.dylib"; + $archiveformat = ".dmg"; + } + else + { + $libextension = "\.so"; + $archiveformat = ".tar.gz"; + } + $quote = "\'"; + $isunix = 1; + $iswin = 0; + } + # WRAPCMD is gone - remove this and all related + # $installer::globals::wrapcmd entries + $wrapcmd = ""; + + if ( $plat =~ /linux/i ) { $islinux = 1; } + if ( $plat =~ /solaris/i ) { $issolaris = 1; } + if ( $plat =~ /darwin/i ) { $ismacosx = 1; } + + # ToDo: Needs to be expanded for additional platforms + +} + +1; diff --git a/solenv/bin/modules/installer/javainstaller.pm b/solenv/bin/modules/installer/javainstaller.pm new file mode 100644 index 000000000000..980b48dcbc0a --- /dev/null +++ b/solenv/bin/modules/installer/javainstaller.pm @@ -0,0 +1,1890 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: javainstaller.pm,v $ +# +# $Revision: 1.30 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +package installer::javainstaller; + +use Cwd; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::languages; +use installer::pathanalyzer; +use installer::scriptitems; +use installer::systemactions; +use installer::worker; +use installer::logger; + +############################################################## +# Returning a specific language string from the block +# of all translations +############################################################## + +sub get_language_string_from_language_block +{ + my ($language_block, $language, $oldstring) = @_; + + my $newstring = ""; + + for ( my $i = 0; $i <= $#{$language_block}; $i++ ) + { + if ( ${$language_block}[$i] =~ /^\s*$language\s*\=\s*\"(.*)\"\s*$/ ) + { + $newstring = $1; + last; + } + } + + if ( $newstring eq "" ) + { + $language = "en-US"; # defaulting to english + + for ( my $i = 0; $i <= $#{$language_block}; $i++ ) + { + if ( ${$language_block}[$i] =~ /^\s*$language\s*\=\s*\"(.*)\"\s*$/ ) + { + $newstring = $1; + last; + } + } + } + + return $newstring; +} + +############################################################## +# Returning the complete block in all languages +# for a specified string +############################################################## + +sub get_language_block_from_language_file +{ + my ($searchstring, $languagefile) = @_; + + my @language_block = (); + + for ( my $i = 0; $i <= $#{$languagefile}; $i++ ) + { + if ( ${$languagefile}[$i] =~ /^\s*\[\s*$searchstring\s*\]\s*$/ ) + { + my $counter = $i; + + push(@language_block, ${$languagefile}[$counter]); + $counter++; + + while (( $counter <= $#{$languagefile} ) && (!( ${$languagefile}[$counter] =~ /^\s*\[/ ))) + { + push(@language_block, ${$languagefile}[$counter]); + $counter++; + } + + last; + } + } + + return \@language_block; +} + +####################################################### +# Searching for the module name and description in the +# modules collector +####################################################### + +sub get_module_name_description +{ + my ($modulesarrayref, $onelanguage, $gid, $type) = @_; + + my $found = 0; + + my $newstring = ""; + + for ( my $i = 0; $i <= $#{$modulesarrayref}; $i++ ) + { + my $onemodule = ${$modulesarrayref}[$i]; + + if ( $onemodule->{'gid'} eq $gid ) + { + my $typestring = $type . " " . "(" . $onelanguage . ")"; + if ( $onemodule->{$typestring} ) { $newstring = $onemodule->{$typestring}; } + $found = 1; + } + + if ( $found ) { last; } + } + + # defaulting to english + + if ( ! $found ) + { + my $defaultlanguage = "en-US"; + + for ( my $i = 0; $i <= $#{$modulesarrayref}; $i++ ) + { + my $onemodule = ${$modulesarrayref}[$i]; + + if ( $onemodule->{'gid'} eq $gid ) + { + my $typestring = $type . " " . "(" . $defaultlanguage . ")"; + if ( $onemodule->{$typestring} ) { $newstring = $onemodule->{$typestring}; } + $found = 1; + } + + if ( $found ) { last; } + } + } + + return $newstring; +} + +####################################################### +# Setting the productname and productversion +####################################################### + +sub set_productname_and_productversion +{ + my ($templatefile, $variableshashref) = @_; + + my $infoline = "\nSetting product name and product version in Java template file\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $productname = $variableshashref->{'PRODUCTNAME'}; + my $productversion = $variableshashref->{'PRODUCTVERSION'}; + + for ( my $i = 0; $i <= $#{$templatefile}; $i++ ) + { + ${$templatefile}[$i] =~ s/\{PRODUCTNAME\}/$productname/g; + ${$templatefile}[$i] =~ s/\{PRODUCTVERSION\}/$productversion/g; + } + + $infoline = "End of: Setting product name and product version in Java template file\n\n"; + push( @installer::globals::logfileinfo, $infoline); +} + +####################################################### +# Setting the localized Module name and description +####################################################### + +sub set_component_name_and_description +{ + my ($templatefile, $modulesarrayref, $onelanguage) = @_; + + my $infoline = "\nSetting component names and description in Java template file\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $i = 0; $i <= $#{$templatefile}; $i++ ) + { + # OOO_gid_Module_Prg_Wrt_Name + # OOO_gid_Module_Prg_Wrt_Description + + my $oneline = ${$templatefile}[$i]; + my $oldstring = ""; + my $gid = ""; + my $type = ""; + + if ( $oneline =~ /\b(OOO_gid_\w+)\b/ ) + { + $oldstring = $1; + + $infoline = "Found: $oldstring\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ( $oldstring =~ /^\s*OOO_(gid_\w+)_(\w+?)\s*$/ ) + { + $gid = $1; + $type = $2; + } + + my $newstring = get_module_name_description($modulesarrayref, $onelanguage, $gid, $type); + + $infoline = "\tReplacing (language $onelanguage): OLDSTRING: $oldstring NEWSTRING $newstring\n"; + push( @installer::globals::logfileinfo, $infoline); + + ${$templatefile}[$i] =~ s/$oldstring/$newstring/; # always substitute, even if $newstring eq "" + } + } + + $infoline = "End of: Setting component names and description in Java template file\n\n"; + push( @installer::globals::logfileinfo, $infoline); +} + +####################################################### +# Translating the Java file +####################################################### + +sub translate_javafile +{ + my ($templatefile, $languagefile, $onelanguage) = @_; + + for ( my $i = 0; $i <= $#{$templatefile}; $i++ ) + { + my @allstrings = (); + + my $oneline = ${$templatefile}[$i]; + + while ( $oneline =~ /\b(OOO_\w+)\b/ ) + { + my $replacestring = $1; + push(@allstrings, $replacestring); + $oneline =~ s/$replacestring//; + } + + my $oldstring; + + foreach $oldstring (@allstrings) + { + my $language_block = get_language_block_from_language_file($oldstring, $languagefile); + my $newstring = get_language_string_from_language_block($language_block, $onelanguage, $oldstring); + + $newstring =~ s/\"/\\\"/g; # masquerading the " + $newstring =~ s/\\\\\"/\\\"/g; # unmasquerading if \" was converted to \\" (because " was already masked) + + # if (!( $newstring eq "" )) { ${$idtfile}[$i] =~ s/$oldstring/$newstring/; } + ${$templatefile}[$i] =~ s/$oldstring/$newstring/; # always substitute, even if $newstring eq "" + } + } +} + +########################################################### +# Returning the license file name for a defined language +########################################################### + +sub get_licensefilesource +{ + my ($language, $includepatharrayref) = @_; + + my $licensefilename = "LICENSE_" . $language; + + my $licenseref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$licensefilename, $includepatharrayref, 0); + if ($$licenseref eq "") { installer::exiter::exit_program("ERROR: Could not find License file $licensefilename!", "get_licensefilesource"); } + + my $infoline = "Found licensefile $licensefilename: $$licenseref \n"; + push( @installer::globals::logfileinfo, $infoline); + + return $$licenseref; +} + +####################################################### +# Converting the license string into the +# Java specific encoding. +####################################################### + +sub convert_licenstring +{ + my ($licensefile, $includepatharrayref, $javadir, $onelanguage) = @_; + + my $licensedir = $javadir . $installer::globals::separator . "license"; + installer::systemactions::create_directory($licensedir); + + # saving the original license file + + my $licensefilename = $licensedir . $installer::globals::separator . "licensefile.txt"; + installer::files::save_file($licensefilename, $licensefile); + + # creating the ulf file from the license file + + $licensefilename = $licensedir . $installer::globals::separator . "licensefile.ulf"; + my @licensearray = (); + + my $section = "\[TRANSLATE\]\n"; + push(@licensearray, $section); + + for ( my $i = 0; $i <= $#{$licensefile}; $i++ ) + { + my $oneline = ${$licensefile}[$i]; + + if ($i == 0) { $oneline =~ s/^\s*\ï\»\¿//; } + + $oneline =~ s/\s*$//; + $oneline =~ s/\"/\\\"/g; # masquerading the " + $oneline =~ s/\'/\\\'/g; # masquerading the ' + + $oneline =~ s/\$\{/\{/g; # replacement of variables, only {PRODUCTNAME}, not ${PRODUCTNAME} + + my $ulfstring = $onelanguage . " = " . "\"" . $oneline . "\"\n"; + push(@licensearray, $ulfstring); + } + + installer::files::save_file($licensefilename, \@licensearray); + + # converting the ulf file to the jlf file with ulfconv + + @licensearray = (); + + my $converter = "ulfconv"; + + my $converterref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$converter, $includepatharrayref, 0); + if ($$converterref eq "") { installer::exiter::exit_program("ERROR: Could not find converter $converter!", "convert_licenstring"); } + + my $infoline = "Found converter file $converter: $$converterref \n"; + push( @installer::globals::logfileinfo, $infoline); + + my $systemcall = "$$converterref $licensefilename |"; + open (CONV, "$systemcall"); + @licensearray = <CONV>; + close (CONV); + + $licensefilename = $licensedir . $installer::globals::separator . "licensefile.jlf"; + installer::files::save_file($licensefilename, \@licensearray); + + # creating the license string from the jlf file + + $licensestring = ""; + + for ( my $i = 1; $i <= $#licensearray; $i++ ) # not the first line! + { + my $oneline = $licensearray[$i]; + $oneline =~ s/^\s*$onelanguage\s*\=\s*\"//; + $oneline =~ s/\"\s*$//; + $licensestring = $licensestring . $oneline . "\\n"; + } + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ( $licensestring eq "" ) + { + $infoline = "ERROR: Could not convert $licensefilename !\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + return $licensestring; +} + +####################################################### +# Adding the license file into the java file +# In the template java file there are two +# occurences of INSTALLSDK_GUI_LICENSE +# and INSTALLSDK_CONSOLE_LICENSE +####################################################### + +sub add_license_file_into_javafile +{ + my ( $templatefile, $licensefile, $includepatharrayref, $javadir, $onelanguage ) = @_; + + my $licensestring = convert_licenstring($licensefile, $includepatharrayref, $javadir, $onelanguage); + + # saving the licensestring in an ulf file + # converting the file using "ulfconv license.ulf" + # including the new string into the java file + + for ( my $i = 0; $i <= $#{$templatefile}; $i++ ) + { + ${$templatefile}[$i] =~ s/INSTALLSDK_GUI_LICENSE/$licensestring/; + ${$templatefile}[$i] =~ s/INSTALLSDK_CONSOLE_LICENSE/$licensestring/; + } +} + +####################################################### +# Executing one system call +####################################################### + +sub make_systemcall +{ + my ( $systemcall, $logreturn ) = @_; + + my @returns = (); + + installer::logger::print_message( "... $systemcall ...\n" ); + + open (REG, "$systemcall"); + while (<REG>) {push(@returns, $_); } + close (REG); + + my $returnvalue = $?; # $? contains the return value of the systemcall + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ( $logreturn ) + { + for ( my $j = 0; $j <= $#returns; $j++ ) { push( @installer::globals::logfileinfo, "$returns[$j]"); } + } + + if ($returnvalue) + { + $infoline = "ERROR: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + $error_occured = 1; + } + else + { + $infoline = "SUCCESS: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + return \@returns; +} + +####################################################### +# Setting the class path for the Installer SDK +####################################################### + +sub set_classpath_for_install_sdk +{ + my ( $directory ) = @_; + + my $installsdk = ""; + my $solarVersion = ""; + my $inPath = ""; + my $updMinorExt = ""; + + if ( defined( $ENV{ 'SOLARVERSION' } ) ) { $solarVersion = $ENV{'SOLARVERSION'}; } + else { installer::exiter::exit_program("ERROR: Environment variable \"SOLARVERSION\" not set!", "set_classpath_for_install_sdk"); } + + if ( defined( $ENV{ 'INPATH' } ) ) { $inPath = $ENV{'INPATH'}; } + else { installer::exiter::exit_program("ERROR: Environment variable \"INPATH\" not set!", "set_classpath_for_install_sdk"); } + + if ( defined( $ENV{ 'UPDMINOREXT' } ) ) { $updMinorExt = $ENV{'UPDMINOREXT'}; } + else { installer::exiter::exit_program("ERROR: Environment variable \"UPDMINOREXT\" not set!", "set_classpath_for_install_sdk") if ( ! $ENV{UPDATER} ); } + + $installsdk = $solarVersion . $installer::globals::separator . $inPath . $installer::globals::separator . "bin" . $updMinorExt; + $installsdk = $installsdk . $installer::globals::separator . "javainstaller"; + + if ( $ENV{'INSTALLSDK_SOURCE'} ) { $installsdk = $ENV{'INSTALLSDK_SOURCE'}; } # overriding the Install SDK with INSTALLSDK_SOURCE + + # The variable CLASSPATH has to contain: + # $installsdk/classes:$installsdk/classes/setupsdk.jar: + # $installsdk/classes/parser.jar:$installsdk/classes/jaxp.jar: + # $installsdk/classes/ldapjdk.jar:$directory + + my @additional_classpath = (); + push(@additional_classpath, "$installsdk\/classes"); + push(@additional_classpath, "$installsdk\/installsdk.jar"); + push(@additional_classpath, "$installsdk\/classes\/parser.jar"); + push(@additional_classpath, "$installsdk\/classes\/jaxp.jar"); + push(@additional_classpath, "$directory"); + + my $newclasspathstring = ""; + my $oldclasspathstring = ""; + if ( $ENV{'CLASSPATH'} ) { $oldclasspathstring = $ENV{'CLASSPATH'}; } + else { $oldclasspathstring = "\."; } + + for ( my $i = 0; $i <= $#additional_classpath; $i++ ) + { + $newclasspathstring = $newclasspathstring . $additional_classpath[$i] . ":"; + } + + $newclasspathstring = $newclasspathstring . $oldclasspathstring; + + $ENV{'CLASSPATH'} = $newclasspathstring; + + my $infoline = "Setting CLASSPATH to $ENV{'CLASSPATH'}\n"; + push( @installer::globals::logfileinfo, $infoline); +} + +####################################################### +# Setting the class file name in the Java locale file +####################################################### + +sub set_classfilename +{ + my ($templatefile, $classfilename, $searchstring) = @_; + + for ( my $j = 0; $j <= $#{$templatefile}; $j++ ) + { + if ( ${$templatefile}[$j] =~ /\Q$searchstring\E/ ) + { + ${$templatefile}[$j] =~ s/$searchstring/$classfilename/; + last; + } + } +} + +####################################################### +# Substituting one variable in the xml file +####################################################### + +sub replace_one_variable +{ + my ($xmlfile, $variable, $searchstring) = @_; + + for ( my $i = 0; $i <= $#{$xmlfile}; $i++ ) + { + ${$xmlfile}[$i] =~ s/\$\{$searchstring\}/$variable/g; + } +} + +####################################################### +# Substituting the variables in the xml file +####################################################### + +sub substitute_variables +{ + my ($xmlfile, $variableshashref) = @_; + + my $key; + + foreach $key (keys %{$variableshashref}) + { + my $value = $variableshashref->{$key}; + replace_one_variable($xmlfile, $value, $key); + } +} + +########################################################## +# Finding the line number in xml file of a special +# component +########################################################## + +sub find_component_line +{ + my ($xmlfile, $componentname) = @_; + + my $linenumber = 0; + + for ( my $i = 0; $i <= $#{$xmlfile}; $i++ ) + { + if ( ${$xmlfile}[$i] =~ /name\s*\=\'\s*$componentname/ ) + { + $linenumber = $i; + last; + } + } + + return $linenumber; +} + +########################################################## +# Removing one package from the xml file +########################################################## + +sub remove_package +{ + my ($xmlfile, $packagename) = @_; + + my $searchstring = $packagename; + if ( $searchstring =~ /\-(\S+?)\s*$/ ) { $searchstring = $1; } # "SUNW%PRODUCTNAME-mailcap" -> "mailcap" + + my $packagestring = ""; + my $namestring = ""; + my $infoline = ""; + + if ( $installer::globals::issolarispkgbuild ) + { + $packagestring = "\<pkgunit"; + $namestring = "pkgName"; + } + elsif ( $installer::globals::islinuxrpmbuild ) + { + $packagestring = "\<rpmunit"; + $namestring = "rpmUniqueName"; + } + + my $removed_packge = 0; + + for ( my $i = 0; $i <= $#{$xmlfile}; $i++ ) + { + if ( ${$xmlfile}[$i] =~ /^\s*\Q$packagestring\E/ ) + { + # this is a package, but is it the correct one? + + my $do_delete = 0; + my $linecounter = 1; + my $startline = $i+1; + my $line = ${$xmlfile}[$startline]; + if (($line =~ /^\s*\Q$namestring\E\s*\=/) && ($line =~ /\-\Q$searchstring\E/)) { $do_delete = 1; } + + # but not deleting fonts package in language packs + if ( $line =~ /-ONELANGUAGE-/ ) { $do_delete = 0; } + + my $endcounter = 0; + + while ((!( $line =~ /\/\>/ )) && ( $startline <= $#{$xmlfile} )) + { + $linecounter++; + $startline++; + $line = ${$xmlfile}[$startline]; + if (($line =~ /^\s*\Q$namestring\E\s*\=/) && ($line =~ /\-\Q$searchstring\E/)) { $do_delete = 1; } + } + + $linecounter = $linecounter + 1; + + if ( $do_delete ) + { + my $infoline = "\tReally removing package $packagename from xml file.\n"; + push( @installer::globals::logfileinfo, $infoline); + splice(@{$xmlfile},$i, $linecounter); # removing $linecounter lines, beginning in line $i + $removed_packge = 1; + last; + } + } + } + + if ( $removed_packge ) + { + $infoline = "Package $packagename successfully removed from xml file.\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Did not find package $packagename in xml file.\n"; + push( @installer::globals::logfileinfo, $infoline); + } + +} + +########################################################## +# Removing one component from the xml file +########################################################## + +sub remove_component +{ + my ($xmlfile, $componentname) = @_; + + my @removed_lines = (); + + push(@removed_lines, "\n"); + + for ( my $i = 0; $i <= $#{$xmlfile}; $i++ ) + { + if ( ${$xmlfile}[$i] =~ /name\s*\=\'\s*$componentname/ ) + { + # Counting the lines till the second "</component>" + + push(@removed_lines, ${$xmlfile}[$i]); + my $linecounter = 1; + my $startline = $i+1; + my $line = ${$xmlfile}[$startline]; + push(@removed_lines, $line); + my $endcounter = 0; + + while ((!( $line =~ /^\s*\<\/component\>\s*$/ )) && ( $startline <= $#{$xmlfile} )) + { + $linecounter++; + $startline++; + $line = ${$xmlfile}[$startline]; + push(@removed_lines, $line); + } + + $linecounter = $linecounter + 2; # last line and following empty line + + splice(@{$xmlfile},$i, $linecounter); # removing $linecounter lines, beginning in line $i + last; + } + } + + return \@removed_lines; +} + +########################################################## +# If this is an installation set without language packs +# the language pack module can be removed +########################################################## + +sub remove_languagepack_from_xmlfile +{ + my ($xmlfile) = @_; + + # Component begins with "<component selected="true" name='module_languagepacks' componentVersion="${PRODUCTVERSION}">" + # and ends with "</component>" (the second "</component>" !) + + remove_component($xmlfile, "languagepack_DEFAULT"); + remove_component($xmlfile, "languagepack_ONELANGUAGE"); + remove_component($xmlfile, "module_languagepacks"); +} + +########################################################## +# Duplicating a component +########################################################## + +sub duplicate_component +{ + my ( $arrayref ) = @_; + + @newarray = (); + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + push(@newarray, ${$arrayref}[$i]); + } + + return \@newarray; +} + +########################################################## +# Including a component into the xml file +# at a specified line +########################################################## + +sub include_component_at_specific_line +{ + my ($xmlfile, $unit, $line) = @_; + + splice(@{$xmlfile},$line, 0, @{$unit}); +} + +########################################################## +# Font packages do not exist for all languages. +########################################################## + +sub remove_font_package_from_unit +{ + my ( $unitcopy, $onelanguage ) = @_; + + my $searchstring = "-fonts"; + + my $packagestring = ""; + my $namestring = ""; + + if ( $installer::globals::issolarispkgbuild ) + { + $packagestring = "\<pkgunit"; + $namestring = "pkgName"; + } + elsif ( $installer::globals::islinuxrpmbuild ) + { + $packagestring = "\<rpmunit"; + $namestring = "rpmUniqueName"; + } + + for ( my $i = 0; $i <= $#{$unitcopy}; $i++ ) + { + if ( ${$unitcopy}[$i] =~ /^\s*\Q$packagestring\E/ ) + { + # this is a package, but is it the correct one? + + my $do_delete = 0; + my $linecounter = 1; + my $startline = $i+1; + my $line = ${$unitcopy}[$startline]; + if (($line =~ /^\s*\Q$namestring\E\s*\=/) && ($line =~ /\Q$searchstring\E/)) { $do_delete = 1; } + + my $endcounter = 0; + + while ((!( $line =~ /\/\>/ )) && ( $startline <= $#{$unitcopy} )) + { + $linecounter++; + $startline++; + $line = ${$unitcopy}[$startline]; + if (($line =~ /^\s*\Q$namestring\E\s*\=/) && ($line =~ /\Q$searchstring\E/)) { $do_delete = 1; } + } + + $linecounter = $linecounter + 1; + + if ( $do_delete ) + { + splice(@{$unitcopy},$i, $linecounter); # removing $linecounter lines, beginning in line $i + last; + } + } + } +} + +########################################################## +# If this is an installation set with language packs, +# modules for each language pack have to be created +# dynamically +########################################################## + +sub duplicate_languagepack_in_xmlfile +{ + my ($xmlfile, $languagesarrayref) = @_; + + my $unit = remove_component($xmlfile, "languagepack_ONELANGUAGE"); + my $startline = find_component_line($xmlfile, "module_languagepacks"); + my $infoline = ""; + $startline = $startline + 1; + + for ( my $i = 0; $i <= $#{$languagesarrayref}; $i++ ) + { + my $onelanguage = ${$languagesarrayref}[$i]; + my $unitcopy = duplicate_component($unit); + + # replacing string ONELANGUAGE in the unit copy + for ( my $j = 0; $j <= $#{$unitcopy}; $j++ ) { ${$unitcopy}[$j] =~ s/ONELANGUAGE/$onelanguage/g; } + + # including the unitcopy into the xml file + include_component_at_specific_line($xmlfile, $unitcopy, $startline); + $startline = $startline + $#{$unitcopy} + 1; + } + + # adding the default language as language pack, too + $unit = remove_component($xmlfile, "languagepack_DEFAULT"); + $startline = find_component_line($xmlfile, "module_languagepacks"); + $startline = $startline + 1; + + $onelanguage = ${$languagesarrayref}[0]; + $unitcopy = duplicate_component($unit); + + # replacing string DEFAULT in the unit copy + for ( my $j = 0; $j <= $#{$unitcopy}; $j++ ) { ${$unitcopy}[$j] =~ s/DEFAULT/$onelanguage/g; } + + # including the unitcopy into the xml file + include_component_at_specific_line($xmlfile, $unitcopy, $startline); + $startline = $startline + $#{$unitcopy} + 1; +} + +####################################################### +# Removing empty packages from xml file. The names +# are stored in @installer::globals::emptypackages +####################################################### + +sub remove_empty_packages_in_xmlfile +{ + my ($xmlfile) = @_; + + for ( my $i = 0; $i <= $#installer::globals::emptypackages; $i++ ) + { + my $packagename = $installer::globals::emptypackages[$i]; + my $infoline = "Try to remove package $packagename from xml file.\n"; + push( @installer::globals::logfileinfo, $infoline); + remove_package($xmlfile, $packagename); + } +} + +####################################################### +# Preparing the language packs in the xml file +####################################################### + +sub prepare_language_pack_in_xmlfile +{ + my ($xmlfile, $languagesarrayref) = @_; + + # if ( ! $installer::globals::is_unix_multi ) + # { + # remove_languagepack_from_xmlfile($xmlfile); + # } + # else + # { + duplicate_languagepack_in_xmlfile($xmlfile, $languagesarrayref); + # } + +} + +####################################################### +# Returning a rpm unit from a xml file +####################################################### + +sub get_rpm_unit_from_xmlfile +{ + my ($rpmname, $xmlfile) = @_; + + my $infoline = "Searching for $rpmname in xml file.\n"; + push( @installer::globals::logfileinfo, $infoline); + + my @rpmunit = (); + my $includeline = 0; + my $record = 0; + my $foundrpm = 0; + + for ( my $i = 0; $i <= $#{$xmlfile}; $i++ ) + { + my $oneline = ${$xmlfile}[$i]; + + if ( $oneline =~ /^\s*\<rpmunit/ ) { $record = 1; } + + if ( $record ) { push(@rpmunit, $oneline); } + + if ( $oneline =~ /^\s*rpmUniqueName\s*=\s*\"\Q$rpmname\E\"\s*$/ ) { $foundrpm = 1; } + + if (( $record ) && ( $oneline =~ /\/\>\s*$/ )) { $record = 0; } + + if (( ! $foundrpm ) && ( ! $record )) { @rpmunit = (); } + + if (( $foundrpm ) && ( ! $record )) { $includeline = $i + 1; } + + if (( $foundrpm ) && ( ! $record )) { last; } + } + + if ( ! $foundrpm ) { installer::exiter::exit_program("ERROR: Did not find rpmunit $rpmname in xml file!", "get_rpm_unit_from_xmlfile"); } + + $infoline = "Found $rpmname in xml file. Returning block lines: $#rpmunit + 1. Includeline: $includeline \n"; + push( @installer::globals::logfileinfo, $infoline); + + return (\@rpmunit, $includeline); +} + +####################################################### +# Exchanging package names in xml file +####################################################### + +sub exchange_name_in_rpmunit +{ + my ($rpmunit, $oldpackagename, $newpackagename) = @_; + + for ( my $i = 0; $i <= $#{$rpmunit}; $i++ ) + { + ${$rpmunit}[$i] =~ s/$oldpackagename/$newpackagename/; + } +} + +####################################################### +# Preparing link RPMs in the xml file +####################################################### + +sub prepare_linkrpm_in_xmlfile +{ + my ($xmlfile, $rpmlist) = @_; + + for ( my $i = 0; $i <= $#{$rpmlist}; $i++ ) + { + my $oldpackagename = ""; + my $newpackagename = ""; + + my $rpmline = ${$rpmlist}[$i]; + + my $infoline = "Preparing link/patch RPM: $rpmline\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ( $rpmline =~ /^\s*(\S.*?\S)\s+(\S.*?\S)\s*$/ ) + { + $oldpackagename = $1; + $newpackagename = $2; + } + + my ($rpmunit, $includeline) = get_rpm_unit_from_xmlfile($oldpackagename, $xmlfile); + exchange_name_in_rpmunit($rpmunit, $oldpackagename, $newpackagename); + include_component_at_specific_line($xmlfile, $rpmunit, $includeline); + } +} + +####################################################################### +# Removing w4w filter module from xml file for Solaris x86 and Linux +####################################################################### + +sub remove_w4w_from_xmlfile +{ + my ($xmlfile) = @_; + + # Component begins with "<component selected='true' name='gid_Module_Prg_Wrt_Flt_W4w' componentVersion="8">" + # and ends with "</component>" + + for ( my $i = 0; $i <= $#{$xmlfile}; $i++ ) + { + if ( ${$xmlfile}[$i] =~ /name\s*\=\'\s*gid_Module_Prg_Wrt_Flt_W4w/ ) + { + # Counting the lines till "</component>" + + my $linecounter = 1; + my $startline = $i+1; + my $line = ${$xmlfile}[$startline]; + + while ((!( $line =~ /^\s*\<\/component\>\s*$/ )) && ( $startline <= $#{$xmlfile} )) + { + $linecounter++; + $startline++; + $line = ${$xmlfile}[$startline]; + } + + $linecounter = $linecounter + 2; # last line and following empty line + + splice(@{$xmlfile},$i, $linecounter); # removing $linecounter lines, beginning in line $i + last; + } + } +} + +####################################################################### +# Removing module from xml file, if not defined in scp +####################################################################### + +sub remove_scpgid_from_xmlfile +{ + my ($xmlfile, $scpgid) = @_; + + # Component begins with "<component selected='true' name='$scpgid' componentVersion="8">" + # and ends with "</component>" + + my $successfully_removed = 0; + + for ( my $i = 0; $i <= $#{$xmlfile}; $i++ ) + { + if ( ${$xmlfile}[$i] =~ /name\s*\=\'\s*\Q$scpgid\E/ ) + { + # Counting the lines till "</component>" + + my $linecounter = 1; + my $startline = $i+1; + my $line = ${$xmlfile}[$startline]; + + while ((!( $line =~ /^\s*\<\/component\>\s*$/ )) && ( $startline <= $#{$xmlfile} )) + { + $linecounter++; + $startline++; + $line = ${$xmlfile}[$startline]; + } + + $linecounter = $linecounter + 2; # last line and following empty line + + splice(@{$xmlfile},$i, $linecounter); # removing $linecounter lines, beginning in line $i + $successfully_removed = 1; + last; + } + } + + my $infoline = ""; + if ($successfully_removed) + { + $infoline = "Module $scpgid successfully removed from xml file.\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Module $scpgid not found in xml file (no problem).\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +####################################################################### +# Special mechanism for removing modules for xml file, if they are +# not defined in scp (introduced for onlineupdate module). +####################################################################### + +sub remove_module_if_not_defined +{ + my ($xmlfile, $modulesarrayref, $scpgid) = @_; + + my $infoline = "Checking existence of $scpgid in scp definition\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $found = 0; + + for ( my $i = 0; $i <= $#{$modulesarrayref}; $i++ ) + { + my $onemodule = ${$modulesarrayref}[$i]; + if ( $onemodule->{'gid'} eq $scpgid ) { $found = 1; } + if ( $found ) { last; } + } + + if ( ! $found ) + { + $infoline = "Module $scpgid not found -> Removing from xml file.\n"; + push( @installer::globals::logfileinfo, $infoline); + remove_scpgid_from_xmlfile($xmlfile, $scpgid); + } +} + +########################################################### +# Preparing the package subdirectory +########################################################### + +sub create_empty_packages +{ + my ( $xmlfile ) = @_; + + if ( $installer::globals::issolarispkgbuild ) + { + my $path = ""; + + for ( my $i = 0; $i <= $#{$xmlfile}; $i++ ) + { + if ( ${$xmlfile}[$i] =~ /pkgRelativePath\s*\=\s*\'(.*?)\'\s*$/ ) + { + $path = $1; + installer::systemactions::create_directory_structure($path); + last; # only creating one path + } + } + + for ( my $i = 0; $i <= $#{$xmlfile}; $i++ ) + { + if ( ${$xmlfile}[$i] =~ /pkgName\s*\=\s*\'(.*?)\'\s*$/ ) + { + my $pkgname = $1; + if ( $path ne "" ) { $pkgname = $path . $installer::globals::separator . $pkgname; } + installer::systemactions::create_directory_structure($pkgname); + } + } + } + + # "-novalidate" does not work for Linux RPMs + + if ( $installer::globals::islinuxrpmbuild ) + { + for ( my $i = 0; $i <= $#{$xmlfile}; $i++ ) + { + if ( ${$xmlfile}[$i] =~ /rpmPath\s*\=\s*\"(.*?)\"\s*$/ ) + { + my $rpmpath = $1; + my $path = ""; + + if ( $rpmpath =~ /^\s*(.*)\/(.*?)\s*$/ ) + { + $path = $1; + } + + if ( $path ne "" ) { installer::systemactions::create_directory_structure($path); } + + my $systemcall = "touch $rpmpath"; # creating empty rpm + system($systemcall); + } + } + } +} + +########################################################### +# Reading the archive file name from the xml file +########################################################### + +sub get_archivefilename +{ + my ( $xmlfile ) = @_; + + my $archivefilename = ""; + + for ( my $j = 0; $j <= $#{$xmlfile}; $j++ ) + { + if ( ${$xmlfile}[$j] =~ /archiveFileName\s*=\s*\'(.*?)\'/ ) + { + $archivefilename = $1; + last; + } + } + + return $archivefilename; +} + +####################################################### +# Copying the loader locally +####################################################### + +sub copy_setup_locally +{ + my ($includepatharrayref, $loadername, $newname) = @_; + + my $loadernameref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$loadername, $includepatharrayref, 0); + + if ($$loadernameref eq "") { installer::exiter::exit_program("ERROR: Could not find Java loader $loadername!", "copy_setup_locally"); } + + installer::systemactions::copy_one_file($$loadernameref, $newname); + my $localcall = "chmod 775 $newname \>\/dev\/null 2\>\&1"; + system($localcall); +} + + +####################################################### +# Copying the loader into the installation set +####################################################### + +sub put_loader_into_installset +{ + my ($installdir, $filename) = @_; + + my $installname = $installdir . $installer::globals::separator . $filename; + + installer::systemactions::copy_one_file($filename, $installname); + + my $localcall = "chmod 775 $installname \>\/dev\/null 2\>\&1"; + system($localcall); +} + +################################################################# +# Setting for Solaris the package names in the Java translation +# file. The name is used for the +# This name is displayed tools like prodreg. +# Unfortunately this name in the component is also used +# in the translation template file for the module name +# and module description translations. +################################################################# + +sub replace_component_name_in_java_file +{ + my ($alljavafiles, $oldname, $newname) = @_; + + # The new name must not contain white spaces + + $newname =~ s/ /\_/g; + + for ( my $i = 0; $i <= $#{$alljavafiles}; $i++ ) + { + my $javafilename = ${$alljavafiles}[$i]; + my $javafile = installer::files::read_file($javafilename); + + my $oldstring = "ComponentDescription-" . $oldname; + my $newstring = "ComponentDescription-" . $newname; + + for ( my $j = 0; $j <= $#{$javafile}; $j++ ) { ${$javafile}[$j] =~ s/\b$oldstring\b/$newstring/; } + + $oldstring = $oldname . "-install-DisplayName"; + $newstring = $newname . "-install-DisplayName"; + + for ( my $j = 0; $j <= $#{$javafile}; $j++ ) { ${$javafile}[$j] =~ s/\b$oldstring\b/$newstring/; } + + $oldstring = $oldname . "-uninstall-DisplayName"; + $newstring = $newname . "-uninstall-DisplayName"; + + for ( my $j = 0; $j <= $#{$javafile}; $j++ ) { ${$javafile}[$j] =~ s/\b$oldstring\b/$newstring/; } + + installer::files::save_file($javafilename, $javafile); + $infoline = "Changes in Java file: $javafilename : $oldname \-\> $newname\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +################################################################# +# Some module names are not defined in the scp project. +# The names for this modules are searched in the base Java +# translation file. +################################################################# + +sub get_module_name_from_basejavafile +{ + my ($componentname, $javatemplateorigfile, $ulffile) = @_; + + my $searchname = $componentname . "-install-DisplayName"; + my $modulename = ""; + my $replacename = ""; + + # line content: { "coremodule-install-DisplayName", "OOO_INSTALLSDK_117" }, + + for ( my $i = 0; $i <= $#{$javatemplateorigfile}; $i++ ) + { + if ( ${$javatemplateorigfile}[$i] =~ /\"\s*\Q$searchname\E\s*\"\s*\,\s*\"\s*(.*?)\s*\"\s*\}\s*\,\s*$/ ) + { + $replacename = $1; + last; + } + } + + if ( $replacename ne "" ) + { + my $language_block = get_language_block_from_language_file($replacename, $ulffile); + $modulename = get_language_string_from_language_block($language_block, "en-US", $replacename); + } + + return $modulename; +} + +################################################################# +# Setting for Solaris the package names in the xml file. +# This name is displayed tools like prodreg. +# Unfortunately this name in the component is also used +# in the translation template file for the module name +# and module description translations. +################################################################# + +sub replace_component_names +{ + my ($xmlfile, $templatefilename, $modulesarrayref, $javatemplateorigfile, $ulffile) = @_; + + # path in which all java languages files are located + + my $javafilesdir = $templatefilename; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$javafilesdir); + my $alljavafiles = installer::systemactions::find_file_with_file_extension("java", $javafilesdir); + for ( my $i = 0; $i <= $#{$alljavafiles}; $i++ ) { ${$alljavafiles}[$i] = $javafilesdir . ${$alljavafiles}[$i]; } + + # analyzing the xml file + + for ( my $i = 0; $i <= $#{$xmlfile}; $i++ ) + { + my $newstring = ""; + my $componentname = ""; + + if ( ${$xmlfile}[$i] =~ /\bcomponent\b.*\bname\s*\=\'\s*(.*?)\s*\'/ ) + { + $componentname = $1; + + # Getting module name from the scp files in $modulesarrayref + + my $onelanguage = "en-US"; + my $gid = $componentname; + my $type = "Name"; + + my $modulename = ""; + $modulename = get_module_name_description($modulesarrayref, $onelanguage, $gid, $type); + + if ( $modulename eq "" ) + { + $infoline = "Info: Modulename for $gid not defined in modules collector. Looking in Java ulf file.\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + if ( $modulename eq "" ) # the modulename can also be set in the Java ulf file + { + $modulename = get_module_name_from_basejavafile($componentname, $javatemplateorigfile, $ulffile); + } + + if ( $modulename ne "" ) # only do something, if the modulename was found + { + ${$xmlfile}[$i] =~ s/$componentname/$modulename/; + + $infoline = "Replacement in xml file (Solaris): $componentname \-\> $modulename\n"; + push( @installer::globals::logfileinfo, $infoline); + + # Replacement has to be done in all Java language files + replace_component_name_in_java_file($alljavafiles, $componentname, $modulename); + } + + if ( $modulename eq "" ) # the modulename can also be set in the Java ulf file + { + $infoline = "WARNING: No replacement in xml file for component: $componentname\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + } +} + +############################################################################# +# Collecting all packages or rpms located in the installation directory +############################################################################# + +sub get_all_packages_in_installdir +{ + my ($installdir, $subdir) = @_; + + my $infoline = ""; + + my @allrpms = (); # not needed for Solaris at the moment + my $allrpms = \@allrpms; + + $installdir =~ s/\Q$installer::globals::separator\E\s*$//; + my $directory = $installdir . $installer::globals::separator . $subdir; + $directory =~ s/\Q$installer::globals::separator\E\s*$//; + + if ( $installer::globals::islinuxrpmbuild ) + { + $allrpms = installer::systemactions::find_file_with_file_extension("rpm", $directory); + + # collecting rpms with the complete path + + for ( my $i = 0; $i <= $#{$allrpms}; $i++ ) + { + ${$allrpms}[$i] = $directory . $installer::globals::separator . ${$allrpms}[$i]; + $infoline = "Found RPM: ${$allrpms}[$i]\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + + return $allrpms; +} + +####################################################### +# Adding the values of the array +####################################################### + +sub do_sum +{ + my ( $allnumbers ) = @_; + + my $sum = 0; + + for ( my $i = 0; $i <= $#{$allnumbers}; $i++ ) + { + $sum = $sum + ${$allnumbers}[$i]; + } + + return $sum; +} + +####################################################### +# Setting the filesize for the RPMs in the xml file +####################################################### + +sub set_filesize_in_xmlfile +{ + my ($filesize, $rpmname, $xmlfile) = @_; + + my $infoline = ""; + my $foundrpm = 0; + my $filesizeset = 0; + + for ( my $i = 0; $i <= $#{$xmlfile}; $i++ ) + { + my $line = ${$xmlfile}[$i]; + + # searching for "rpmPath="RPMS/${UNIXPRODUCTNAME}-core01-${PACKAGEVERSION}-${PACKAGEREVISION}.i586.rpm"" + + if (( $line =~ /rpmPath\s*=/ ) && ( $line =~ /\Q$rpmname\E\"\s*$/ )) + { + $foundrpm = 1; + + my $number = $i; + $number++; + + while ( ! ( ${$xmlfile}[$number] =~ /\/\>\s*$/ )) + { + if ( ${$xmlfile}[$number] =~ /FILESIZEPLACEHOLDER/ ) + { + ${$xmlfile}[$number] =~ s/FILESIZEPLACEHOLDER/$filesize/; + $filesizeset = 1; + $infoline = "Setting filesize for $rpmname : $filesize\n"; + push( @installer::globals::logfileinfo, $infoline); + last; + } + + $number++; + } + + last; + } + } + + if ( ! $foundrpm ) + { + $infoline = "ERROR: Did not find $rpmname in xml file !\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + if ( ! $filesizeset ) + { + $infoline = "ERROR: Did not set filesize for $rpmname in xml file !\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +############################################################ +# Collecting all rpmUniqueName in xml file. +############################################################ + +sub collect_uniquenames_in_xmlfile +{ + my ($xmlfile) = @_; + + my @rpmuniquenames = (); + + for ( my $i = 0; $i <= $#{$xmlfile}; $i++ ) + { + my $oneline = ${$xmlfile}[$i]; + + if ( $oneline =~ /^\s*rpmUniqueName\s*\=\s*\"(.*)\"\s*$/ ) + { + my $rpmuniquename = $1; + push(@rpmuniquenames, $rpmuniquename) + } + } + + return \@rpmuniquenames; +} + +############################################################ +# Searching for the corresponding rpm, that fits to +# the unique rpm name. +# Simple mechanism: The name of the rpm starts with the +# unique rpm name followed by a "-". +############################################################ + +sub find_rpmname_to_uniquename +{ + my ($uniquename, $listofpackages) = @_; + + my @all_correct_rpms = (); + my $infoline = ""; + + # special handling for java RPMs, which have a very strange naming schema + my $localuniquename = $uniquename; + if ( $uniquename =~ /^\s*jre\-/ ) { $localuniquename = "jre"; } + + for ( my $i = 0; $i <= $#{$listofpackages}; $i++ ) + { + my $completerpmname = ${$listofpackages}[$i]; + my $rpmname = $completerpmname; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$rpmname); + + if ( $rpmname =~ /^\s*\Q$localuniquename\E\-\d/ ) { push(@all_correct_rpms, $rpmname); } + } + + # @all_correct_rpms has to contain exactly one value + + if ( $#all_correct_rpms > 0 ) + { + my $number = $#all_correct_rpms + 1; + $infoline = "There are $number RPMs for the unique name \"$uniquename\" :\n"; + push( @installer::globals::logfileinfo, $infoline); + my $allrpmstring = ""; + for ( my $i = 0; $i <= $#all_correct_rpms; $i++ ) { $allrpmstring = $allrpmstring . $all_correct_rpms[$i] . "\n"; } + push( @installer::globals::logfileinfo, $allrpmstring); + installer::exiter::exit_program("ERROR: Found $number RPMs that start with unique name \"$uniquename\". Only one allowed!", "find_rpmname_to_uniquename"); + } + + if ( $#all_correct_rpms < 0 ) + { + $infoline = "There is no rpm for the unique name \"$uniquename\"\n"; + push( @installer::globals::logfileinfo, $infoline); + installer::exiter::exit_program("ERROR: There is no RPM that start with unique name \"$uniquename\"!", "find_rpmname_to_uniquename"); + } + + if ( $#all_correct_rpms == 0 ) + { + $infoline = "Found one rpm for the unique name \"$uniquename\" : $all_correct_rpms[0]\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + return $all_correct_rpms[0]; +} + +####################################################### +# Including the complete RPM name into the xml file +####################################################### + +sub set_rpmname_into_xmlfile +{ + my ($rpmname, $uniquename, $xmlfile) = @_; + + my $foundrpm = 0; + my $rpmnameset = 0; + + for ( my $i = 0; $i <= $#{$xmlfile}; $i++ ) + { + my $oneline = ${$xmlfile}[$i]; + + if ( $oneline =~ /^\s*rpmUniqueName\s*\=\s*\"\Q$uniquename\E\"\s*$/ ) + { + $foundrpm = 1; + + my $number = $i; + $number++; + + while ( ! ( ${$xmlfile}[$number] =~ /\/\>\s*$/ )) + { + if ( ${$xmlfile}[$number] =~ /RPMFILENAMEPLACEHOLDER/ ) + { + ${$xmlfile}[$number] =~ s/RPMFILENAMEPLACEHOLDER/$rpmname/; + $rpmnameset = 1; + $infoline = "Setting RPM name for $uniquename : $rpmname\n"; + push( @installer::globals::logfileinfo, $infoline); + last; + } + + $number++; + } + + last; + } + } + + if ( ! $foundrpm ) + { + $infoline = "ERROR: Did not find $rpmname in xml file !\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + if ( ! $rpmnameset ) + { + $infoline = "ERROR: Did not set rpm name for $uniquename in xml file !\n"; + push( @installer::globals::logfileinfo, $infoline); + } + +} + +############################################################ +# Including the rpm path dynamically into the xml file. +# This is introduced, because system integration has +# variable PackageVersion and PackageRevision in xml file. +############################################################ + +sub put_rpmpath_into_xmlfile +{ + my ($xmlfile, $listofpackages) = @_; + + my $infoline = ""; + + my $alluniquenames = collect_uniquenames_in_xmlfile($xmlfile); + + my $number = $#{$listofpackages} + 1; + $infoline = "Number of packages in installation set: $number\n"; + push( @installer::globals::logfileinfo, $infoline); + $number = $#{$alluniquenames} + 1; + $infoline = "Number of unique RPM names in xml file: $number\n"; + push( @installer::globals::logfileinfo, $infoline); + + $infoline = "\nPackages in installation set:\n"; + push( @installer::globals::logfileinfo, $infoline); + for ( my $i = 0; $i <= $#{$listofpackages}; $i++ ) + { + $infoline = "${$listofpackages}[$i]\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + $infoline = "\nUnique RPM names in xml file:\n"; + push( @installer::globals::logfileinfo, $infoline); + for ( my $i = 0; $i <= $#{$alluniquenames}; $i++ ) + { + $infoline = "${$alluniquenames}[$i]\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + if ( $#{$alluniquenames} != $#{$listofpackages} ) { installer::exiter::exit_program("ERROR: xml file contains $#{$alluniquenames} unique names, but there are $#{$listofpackages} packages in installation set!", "put_rpmpath_into_xmlfile"); } + + for ( my $i = 0; $i <= $#{$alluniquenames}; $i++ ) + { + my $uniquename = ${$alluniquenames}[$i]; + my $rpmname = find_rpmname_to_uniquename($uniquename, $listofpackages); + set_rpmname_into_xmlfile($rpmname, $uniquename, $xmlfile); + } +} + +####################################################### +# Including the file size of the rpms into the +# xml file +####################################################### + +sub put_filesize_into_xmlfile +{ + my ($xmlfile, $listofpackages) = @_; + + my $infoline = ""; + + for ( my $i = 0; $i <= $#{$listofpackages}; $i++ ) + { + my $completerpmname = ${$listofpackages}[$i]; + my $rpmname = $completerpmname; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$rpmname); + + if ( ! $installer::globals::rpmquerycommand ) { installer::exiter::exit_program("ERROR: rpm not found for querying packages!", "put_filesize_into_xmlfile"); } + my $systemcall = "$installer::globals::rpmquerycommand -qp --queryformat \"\[\%\{FILESIZES\}\\n\]\" $completerpmname 2\>\&1 |"; + my $rpmout = make_systemcall($systemcall, 0); + my $filesize = do_sum($rpmout); + + $infoline = "Filesize $rpmname : $filesize\n"; + push( @installer::globals::logfileinfo, $infoline); + + set_filesize_in_xmlfile($filesize, $rpmname, $xmlfile); + } +} + +####################################################### +# Creating the java installer class file dynamically +####################################################### + +sub create_java_installer +{ + my ( $installdir, $newdir, $languagestringref, $languagesarrayref, $allvariableshashref, $includepatharrayref, $modulesarrayref ) = @_; + + installer::logger::include_header_into_logfile("Creating Java installer:"); + + my $infoline = ""; + + # collecting all packages or rpms located in the installation directory + my $listofpackages = get_all_packages_in_installdir($installdir, $newdir); + + # creating the directory + my $javadir = installer::systemactions::create_directories("javainstaller", $languagestringref); + $javadir =~ s/\/\s*$//; +# push(@installer::globals::removedirs, $javadir); + + # copying the content from directory install_sdk into the java directory + + my $projectroot = ""; + if ( $ENV{'PRJ'} ) { $projectroot = $ENV{'PRJ'}; } + else { installer::exiter::exit_program("ERROR: Environment variable PRJ not set", "create_java_installer"); } + + $projectroot =~ s/\/\s*$//; + my $sourcedir = "$projectroot/inc_global/unix/install_sdk"; + installer::systemactions::copy_complete_directory_without_cvs($sourcedir, $javadir); + + # determining the java template file + + my $templatefilename = $javadir . $installer::globals::separator . "locale/resources/MyResources_template.java"; + + # Saving the content of the template file. It is used in the xml files + + my $javatemplateorigfile = installer::files::read_file($templatefilename); + + # determining the ulf language file + + # my $ulffilename = "installsdk.ulf"; + my $ulffilename = "installsdk.jlf"; + $ulffilename = $installer::globals::javalanguagepath . $installer::globals::separator . $ulffilename; + my $ulffile = installer::files::read_file($ulffilename); + + $infoline = "\nReading ulf file: $ulffilename\n"; + push( @installer::globals::logfileinfo, $infoline); + + $infoline = "Translating the Java template file\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $i = 0; $i <= $#{$languagesarrayref}; $i++ ) + { + my $onelanguage = ${$languagesarrayref}[$i]; + + # replacing all strings in the Java file with content of ulf files + + my $templatefile = installer::files::read_file($templatefilename); + + set_component_name_and_description($templatefile, $modulesarrayref, $onelanguage); + translate_javafile($templatefile, $ulffile, $onelanguage); + + # adding the license file into the Java file + + my $licensefilesource = get_licensefilesource($onelanguage, $includepatharrayref); + my $licensefile = installer::files::read_file($licensefilesource); + add_license_file_into_javafile($templatefile, $licensefile, $includepatharrayref, $javadir, $onelanguage); + + # setting productname and productversion + + set_productname_and_productversion($templatefile, $allvariableshashref); + + # setting the class name in the java file ( "MyResources_TEMPLATE" -> "MyResources_en" ) + + # if ( $onelanguage =~ /^\s*(\w+)\-(\w+)\s*$/ ) { $onelanguage = $1; } + $onelanguage =~ s/en-US/en/; # java file name and class name contain only "_en" + $onelanguage =~ s/\-/\_/; # "pt-BR" -> "pt_BR" + my $classfilename = "MyResources_" . $onelanguage; + set_classfilename($templatefile, $classfilename, "MyResources_TEMPLATE"); + + # saving the new file + + my $newfilename = $templatefilename; + $newfilename =~ s/_template\.java\s*$/_$onelanguage\.java/; + + installer::files::save_file($newfilename, $templatefile); + + $infoline = "Saving Java file: $newfilename\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + # renaming one language java file to "MyResources.java" + + my $baselanguage = installer::languages::get_default_language($languagesarrayref); + $baselanguage =~ s/\-/\_/; # "pt-BR" -> "pt_BR" + $baselanguage =~ s/en_US/en/; # java file name and class name contain only "_en" + # if ( $baselanguage =~ /^\s*(\w+)\-(\w+)\s*$/ ) { $baselanguage = $1; } # java file name and class name contain only "_en" + # $baselanguage =~ s/en-US/en/; # java file name and class name contain only "_en" + my $baselanguagefilename = $javadir . $installer::globals::separator . "locale/resources/MyResources_" . $baselanguage . "\.java"; + my $basedestfilename = $javadir . $installer::globals::separator . "locale/resources/MyResources.java"; + installer::systemactions::copy_one_file($baselanguagefilename, $basedestfilename); + + # setting the class file name also for the base class + + my $basetemplatefile = installer::files::read_file($basedestfilename); + my $oldclassfilename = $baselanguagefilename; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$oldclassfilename); + $oldclassfilename =~ s/\.java//; + my $newclassfilename = $basedestfilename; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$newclassfilename); + $newclassfilename =~ s/\.java//; + + set_classfilename($basetemplatefile, $newclassfilename, $oldclassfilename); + + installer::files::save_file($basedestfilename, $basetemplatefile); + + $infoline = "Created base Java file: $basedestfilename\n"; + push( @installer::globals::logfileinfo, $infoline); + + # deleting the template file + + unlink($templatefilename); + + $infoline = "Deleted template Java resource file: $templatefilename\n"; + push( @installer::globals::logfileinfo, $infoline); + + # changing into Java directory + + my $from = cwd(); + + chdir($javadir); + + $infoline = "Changing into directory: $javadir\n"; + push( @installer::globals::logfileinfo, $infoline); + + # preparing the xml file + + my $xmlfilename = ""; + my $subdir = ""; + + if ( $installer::globals::issolarispkgbuild ) + { + $xmlfilename = "pkgUnit.xml"; + } + elsif ( $installer::globals::islinuxrpmbuild ) + { + $xmlfilename = "rpmUnit.xml"; + } + else + { + installer::exiter::exit_program("ERROR: No platform for Install SDK", "create_java_installer"); + } + + # reading, editing and saving the xmlfile + + my $xmlfile = installer::files::read_file($xmlfilename); + prepare_language_pack_in_xmlfile($xmlfile, $languagesarrayref); + my $xmlfilename2 = $xmlfilename . ".test2"; + installer::files::save_file($xmlfilename2, $xmlfile); + remove_empty_packages_in_xmlfile($xmlfile); + my $xmlfilename3 = $xmlfilename . ".test3"; + installer::files::save_file($xmlfilename3, $xmlfile); + substitute_variables($xmlfile, $allvariableshashref); + if (( $installer::globals::islinuxrpmbuild ) && ( $#installer::globals::linkrpms > -1 )) { prepare_linkrpm_in_xmlfile($xmlfile,\@installer::globals::linkrpms); } + if ( $installer::globals::issolarisx86build || $installer::globals::islinuxbuild ) { remove_w4w_from_xmlfile($xmlfile); } + remove_module_if_not_defined($xmlfile, $modulesarrayref, "gid_Module_Optional_Onlineupdate"); + replace_component_names($xmlfile, $templatefilename, $modulesarrayref, $javatemplateorigfile, $ulffile); + my $xmlfilename4 = $xmlfilename . ".test4"; + installer::files::save_file($xmlfilename4, $xmlfile); + if ( $installer::globals::islinuxrpmbuild ) { put_rpmpath_into_xmlfile($xmlfile, $listofpackages); } + if ( $installer::globals::islinuxrpmbuild ) { put_filesize_into_xmlfile($xmlfile, $listofpackages); } + installer::files::save_file($xmlfilename, $xmlfile); + $infoline = "Saving xml file: $xmlfilename\n"; + push( @installer::globals::logfileinfo, $infoline); + + # Setting the classpath and starting compiler + + set_classpath_for_install_sdk($javadir); + + # creating class files: + # language class file, dialog class files, installer class file + + my $jdkpath = ""; + if ( $ENV{'JDKPATH'} ) { $jdkpath = $ENV{'JDKPATH'}; } + + my $javac = "javac"; + if ( $jdkpath ) { $javac = $jdkpath . $installer::globals::separator . $javac; } + + my $systemcall = "$javac locale\/resources\/\*\.java 2\>\&1 |"; + make_systemcall($systemcall, 1); + + $systemcall = "$javac com\/sun\/staroffice\/install\/\*\.java 2\>\&1 |"; + make_systemcall($systemcall, 1); + + # making subdirectory creating empty packages + create_empty_packages($xmlfile); + + # Copy "jresetup" from solver locally to include it into the classfile + # Copy "jresetup" from solver to installdir + + my $setupname = "jresetup"; + my $newname = "setup"; + copy_setup_locally($includepatharrayref, $setupname, $newname); + + my $java = "java"; + if ( $jdkpath ) { $java = $jdkpath . $installer::globals::separator . $java; } + + $systemcall = "$java com.sun.setup.builder.InstallBuilder $xmlfilename -novalidate 2\>\&1 |"; + make_systemcall($systemcall, 1); + + # copying the newly created classfile into the installation set + + my $archivefilename = get_archivefilename($xmlfile); + $archivefilename = $archivefilename . ".class"; + + if ( ! -f $archivefilename ) { installer::exiter::exit_program("ERROR: Could not find Java class file $archivefilename!", "create_java_installer"); } + + installer::systemactions::copy_one_file($archivefilename, $installdir); + + # Adding the loader into the installation set. The name of the loader is setup. + put_loader_into_installset($installdir, $newname); + + chdir($from); + + $infoline = "Changing into directory: $from\n"; + push( @installer::globals::logfileinfo, $infoline); +} + +1; diff --git a/solenv/bin/modules/installer/languagepack.pm b/solenv/bin/modules/installer/languagepack.pm new file mode 100644 index 000000000000..11b8ecbd2edb --- /dev/null +++ b/solenv/bin/modules/installer/languagepack.pm @@ -0,0 +1,569 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: languagepack.pm,v $ +# +# $Revision: 1.16.226.1 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::languagepack; + +use installer::converter; +use installer::existence; +use installer::files; +use installer::globals; +use installer::logger; +use installer::pathanalyzer; +use installer::scpzipfiles; +use installer::scriptitems; +use installer::systemactions; +use installer::worker; + +#################################################### +# Selecting all files with the correct language +#################################################### + +sub select_language_items +{ + my ( $itemsref, $languagesarrayref, $itemname ) = @_; + + installer::logger::include_header_into_logfile("Selecting languages for language pack. Item: $itemname"); + + my @itemsarray = (); + + for ( my $i = 0; $i <= $#{$itemsref}; $i++ ) + { + my $oneitem = ${$itemsref}[$i]; + + my $ismultilingual = $oneitem->{'ismultilingual'}; + + if (!($ismultilingual)) + { + # Files with style "LANGUAGEPACK" and "FORCELANGUAGEPACK" also have to be included into the language pack. + # Files with style "LANGUAGEPACK" are only included into language packs. + # Files with style "FORCELANGUAGEPACK" are included into language packs and non language packs. They are + # forced, because otherwise they not not be included into languagepacks. + + my $styles = ""; + if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; } + + if (( $styles =~ /\bLANGUAGEPACK\b/ ) || ( $styles =~ /\bFORCELANGUAGEPACK\b/ )) { push(@itemsarray, $oneitem); } + + next; # single language files are not included into language pack + } + + my $specificlanguage = ""; + if ( $oneitem->{'specificlanguage'} ) { $specificlanguage = $oneitem->{'specificlanguage'}; } + + for ( my $j = 0; $j <= $#{$languagesarrayref}; $j++ ) # iterating over all languages + { + my $onelanguage = ${$languagesarrayref}[$j]; + my $locallang = $onelanguage; + $locallang =~ s/-/_/; + + if ( $specificlanguage eq $onelanguage ) + { + # $oneitem->{'modules'} = $installer::globals::rootmodulegid; # all files in a language pack are root files + # Using $installer::globals::languagemodulesbase (?) + +# # no more automatic change of module assignments +# $oneitem->{'modules'} = $installer::globals::rootmodulegid . "_$locallang"; # all files in a language pack are root files +# +# if (( $installer::globals::islinuxbuild ) || ( $installer::globals::issolarispkgbuild )) +# { +# if ( $oneitem->{'Dir'} ) +# { +# if ( $oneitem->{'Dir'} eq "gid_Dir_Fonts_Truetype" ) { $oneitem->{'modules'} = "gid_Module_Langpack_Fonts_$locallang"; } +# if ( $oneitem->{'Dir'} eq "gid_Dir_Resource" ) { $oneitem->{'modules'} = "gid_Module_Langpack_Resource_$locallang"; } +# if ( $oneitem->{'Dir'} eq "gid_Dir_Help_Isolanguage" ) { $oneitem->{'modules'} = "gid_Module_Langpack_Help_$locallang"; } +# } +# } + + # preparing different modules for Windows Installer language packs + # my $underlinelanguage = $specificlanguage; + # $underlinelanguage =~ s/-/_/; + # if ( $installer::globals::iswindowsbuild ) { $oneitem->{'modules'} = $installer::globals::languagemodulesbase . $underlinelanguage; } + +# # no more collecting of language pack feature +# if (! installer::existence::exists_in_array($oneitem->{'modules'}, \@installer::globals::languagepackfeature)) +# { +# push(@installer::globals::languagepackfeature, $oneitem->{'modules'}); # Collecting all language pack feature +# } + + push(@itemsarray, $oneitem); + } + } + } + + return \@itemsarray; +} + +sub replace_languagestring_variable +{ + my ($onepackageref, $languagestringref) = @_; + + my $key; + + foreach $key (keys %{$onepackageref}) + { + my $value = $onepackageref->{$key}; + $value =~ s/\%LANGUAGESTRING/$$languagestringref/g; + $onepackageref->{$key} = $value; + } +} + +######################################################### +# Including the license text into the script template +######################################################### + +sub put_license_file_into_script +{ + my ($scriptfile, $licensefile) = @_; + + my $infoline = "Adding licensefile into language pack script\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $includestring = ""; + + for ( my $i = 0; $i <= $#{$licensefile}; $i++ ) + { + $includestring = $includestring . ${$licensefile}[$i]; + } + + for ( my $i = 0; $i <= $#{$scriptfile}; $i++ ) + { + ${$scriptfile}[$i] =~ s/LICENSEFILEPLACEHOLDER/$includestring/; + } +} + +######################################################### +# Creating a tar.gz file from a Solaris package +######################################################### + +sub create_tar_gz_file +{ + my ($installdir, $packagename, $packagestring) = @_; + + $packagename =~ s/\.rpm\s*$//; + my $targzname = $packagename . ".tar.gz"; + $systemcall = "cd $installdir; tar -cf - $packagestring | gzip > $targzname"; + installer::logger::print_message( "... $systemcall ...\n" ); + + my $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + return $targzname; +} + +######################################################### +# Determining the name of the package file +######################################################### + +sub get_packagename_from_packagelist +{ + my ( $alldirs, $allvariables, $languagestringref ) = @_; + + # my $packagename = ""; + + # for ( my $i = 0; $i <= $#{$alldirs}; $i++ ) + # { + # if ( ${$alldirs}[$i] =~ /-fonts/ ) { next; } + # if ( ${$alldirs}[$i] =~ /-help/ ) { next; } + # if ( ${$alldirs}[$i] =~ /-res/ ) { next; } + # + # $packagename = ${$alldirs}[$i]; + # last; + # } + + # if ( $packagename eq "" ) { installer::exiter::exit_program("ERROR: Could not find base package in directory $installdir!", "get_packagename_from_packagelist"); } + + my $localproductname = $allvariables->{'PRODUCTNAME'}; + $localproductname = lc($localproductname); + $localproductname =~ s/ //g; + $localproductname =~ s/-/_/g; + + my $packagename = $localproductname . "_" . $$languagestringref; + + return $packagename; +} + +######################################################### +# Determining the name of the package file or the rpm +# in the installation directory. For language packs +# there is only one file in this directory +######################################################### + +sub determine_packagename +{ + my ( $installdir, $allvariables, $languagestringref ) = @_; + + my $packagename = ""; + my $allnames = ""; + + if ( $installer::globals::islinuxrpmbuild ) + { + # determining the rpm file in directory $installdir + + my $fileextension = "rpm"; + my $rpmfiles = installer::systemactions::find_file_with_file_extension($fileextension, $installdir); + if ( ! ( $#{$rpmfiles} > -1 )) { installer::exiter::exit_program("ERROR: Could not find package in directory $installdir!", "determine_packagename"); } + my $rpmsav = installer::converter::copy_array_from_references($rpmfiles); + for ( my $i = 0; $i <= $#{$rpmfiles}; $i++ ) { installer::pathanalyzer::make_absolute_filename_to_relative_filename(\${$rpmfiles}[$i]); } + + $packagename = get_packagename_from_packagelist($rpmfiles, $allvariables, $languagestringref); + + my $packagestring = installer::converter::convert_array_to_space_separated_string($rpmfiles); + $packagename = create_tar_gz_file($installdir, $packagename, $packagestring); # only one file + for ( my $i = 0; $i <= $#{$rpmsav}; $i++ ) + { + my $onefile = $installdir . $installer::globals::separator . ${$rpmsav}[$i]; + unlink($onefile); + } + + $allnames = $rpmfiles; + } + + if ( $installer::globals::issolarisbuild ) + { + # determining the Solaris package file in directory $installdir + my $alldirs = installer::systemactions::get_all_directories($installdir); + + if ( ! ( $#{$alldirs} > -1 )) { installer::exiter::exit_program("ERROR: Could not find package in directory $installdir!", "determine_packagename"); } + my $alldirssav = installer::converter::copy_array_from_references($alldirs); + for ( my $i = 0; $i <= $#{$alldirs}; $i++ ) { installer::pathanalyzer::make_absolute_filename_to_relative_filename(\${$alldirs}[$i]); } + + $packagename = get_packagename_from_packagelist($alldirs, $allvariables, $languagestringref); + my $packagestring = installer::converter::convert_array_to_space_separated_string($alldirs); + $packagename = create_tar_gz_file($installdir, $packagename, $packagestring); # only a file (not a directory) can be included into the shell script + for ( my $i = 0; $i <= $#{$alldirssav}; $i++ ) { installer::systemactions::remove_complete_directory(${$alldirssav}[$i], 1); } + $allnames = $alldirs; + } + + my $infoline = "Found package in installation directory $installdir : $packagename\n"; + push( @installer::globals::logfileinfo, $infoline); + + return ( $packagename, $allnames); +} + +######################################################### +# Including the name of the package file or the rpm +# into the script template +######################################################### + +sub put_packagename_into_script +{ + my ($scriptfile, $packagename, $allnames) = @_; + + my $localpackagename = $packagename; + $localpackagename =~ s/\.tar\.gz//; # making "OOOopenoffice-it-ea.tar.gz" to "OOOopenoffice-it-ea" + my $infoline = "Adding packagename $localpackagename into language pack script\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $installline = ""; + + if ( $installer::globals::issolarisbuild ) { $installline = " /usr/sbin/pkgadd -d \$outdir -a \$adminfile"; } + + if ( $installer::globals::islinuxrpmbuild ) { $installline = " rpm --prefix \$PRODUCTINSTALLLOCATION --replacepkgs -i"; } + + for ( my $i = 0; $i <= $#{$allnames}; $i++ ) + { + if ( $installer::globals::issolarisbuild ) { $installline = $installline . " ${$allnames}[$i]"; } + + if ( $installer::globals::islinuxrpmbuild ) { $installline = $installline . " \$outdir/${$allnames}[$i]"; } + } + + for ( my $j = 0; $j <= $#{$scriptfile}; $j++ ) + { + ${$scriptfile}[$j] =~ s/INSTALLLINES/$installline/; + } +} + +################################################################## +# Including the lowercase product name into the script template +################################################################## + +sub put_productname_into_script +{ + my ($scriptfile, $variableshashref) = @_; + + my $productname = $variableshashref->{'PRODUCTNAME'}; + $productname = lc($productname); + $productname =~ s/\.//g; # openoffice.org -> openofficeorg + + my $infoline = "Adding productname $productname into language pack script\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $i = 0; $i <= $#{$scriptfile}; $i++ ) + { + ${$scriptfile}[$i] =~ s/PRODUCTNAMEPLACEHOLDER/$productname/; + } +} + +################################################################## +# Including the full product name into the script template +# (name and version) +################################################################## + +sub put_fullproductname_into_script +{ + my ($scriptfile, $variableshashref) = @_; + + my $productname = $variableshashref->{'PRODUCTNAME'}; + my $productversion = ""; + if ( $variableshashref->{'PRODUCTVERSION'} ) { $productversion = $variableshashref->{'PRODUCTVERSION'}; }; + my $fullproductname = $productname . " " . $productversion; + + my $infoline = "Adding full productname \"$fullproductname\" into language pack script\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $i = 0; $i <= $#{$scriptfile}; $i++ ) + { + ${$scriptfile}[$i] =~ s/FULLPRODUCTNAMELONGPLACEHOLDER/$fullproductname/; + } +} + +################################################################## +# Including the name of the search package (-core01) +# into the script template +################################################################## + +sub put_searchpackage_into_script +{ + my ($scriptfile, $variableshashref) = @_; + + my $basispackageprefix = $variableshashref->{'BASISPACKAGEPREFIX'}; + my $basispackageversion = $variableshashref->{'OOOBASEVERSION'}; + + if ( $installer::globals::issolarisbuild ) { $basispackageversion =~ s/\.//g; } # "3.0" -> "30" + + my $infoline = "Adding basis package prefix $basispackageprefix into language pack script\n"; + push( @installer::globals::logfileinfo, $infoline); + + $infoline = "Adding basis package version $basispackageversion into language pack script\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $i = 0; $i <= $#{$scriptfile}; $i++ ) + { + ${$scriptfile}[$i] =~ s/BASISPACKAGEPREFIXPLACEHOLDER/$basispackageprefix/; + ${$scriptfile}[$i] =~ s/OOOBASEVERSIONPLACEHOLDER/$basispackageversion/; + } + +} + +######################################################### +# Including the linenumber into the script template +######################################################### + +sub put_linenumber_into_script +{ + my ( $scriptfile, $licensefile, $allnames ) = @_; + + my $linenumber = $#{$scriptfile} + $#{$licensefile} + 3; # also adding the content of the license file! + + my $infoline = "Adding linenumber $linenumber into language pack script\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $i = 0; $i <= $#{$scriptfile}; $i++ ) + { + ${$scriptfile}[$i] =~ s/LINENUMBERPLACEHOLDER/$linenumber/; + } +} + +######################################################### +# Determining the name of the new scriptfile +######################################################### + +sub determine_scriptfile_name +{ + my ( $packagename ) = @_; + + my $scriptfilename = $packagename; + +# if ( $installer::globals::islinuxrpmbuild ) { $scriptfilename =~ s/\.rpm\s*$/\.sh/; } +# if ( $installer::globals::issolarisbuild ) { $scriptfilename =~ s/\.tar\.gz\s*$/\.sh/; } + + $scriptfilename =~ s/\.tar\.gz\s*$/\.sh/; + + my $infoline = "Setting language pack script file name to $scriptfilename\n"; + push( @installer::globals::logfileinfo, $infoline); + + return $scriptfilename; +} + +######################################################### +# Saving the script file in the installation directory +######################################################### + +sub save_script_file +{ + my ($installdir, $newscriptfilename, $scriptfile) = @_; + + $newscriptfilename = $installdir . $installer::globals::separator . $newscriptfilename; + installer::files::save_file($newscriptfilename, $scriptfile); + + my $infoline = "Saving script file $newscriptfilename\n"; + push( @installer::globals::logfileinfo, $infoline); + + return $newscriptfilename; +} + +######################################################### +# Including the binary package into the script +######################################################### + +sub include_package_into_script +{ + my ( $scriptfilename, $installdir, $packagename ) = @_; + + my $longpackagename = $installdir . $installer::globals::separator . $packagename; + my $systemcall = "cat $longpackagename >>$scriptfilename"; + + my $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + my $localcall = "chmod 775 $scriptfilename \>\/dev\/null 2\>\&1"; + system($localcall); + +} + +######################################################### +# Removing the binary package +######################################################### + +sub remove_package +{ + my ( $installdir, $packagename ) = @_; + + my $remove_package = 1; + + if ( $ENV{'DONT_REMOVE_PACKAGE'} ) { $remove_package = 0; } + + if ( $remove_package ) + { + my $longpackagename = $installdir . $installer::globals::separator . $packagename; + unlink $longpackagename; + + my $infoline = "Removing package: $longpackagename \n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +#################################################### +# Unix language packs, that are not part of +# multilingual installation sets, need a +# shell script installer +#################################################### + +sub build_installer_for_languagepack +{ + my ($installdir, $allvariableshashref, $includepatharrayref, $languagesarrayref, $languagestringref) = @_; + + installer::logger::print_message( "... creating shell script installer ...\n" ); + + installer::logger::include_header_into_logfile("Creating shell script installer:"); + + # find and read setup script template + + my $scriptfilename = "langpackscript.sh"; + my $scriptref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$scriptfilename, $includepatharrayref, 0); + if ($$scriptref eq "") { installer::exiter::exit_program("ERROR: Could not find script file $scriptfilename!", "build_installer_for_languagepack"); } + my $scriptfile = installer::files::read_file($$scriptref); + + my $infoline = "Found script file $scriptfilename: $$scriptref \n"; + push( @installer::globals::logfileinfo, $infoline); + + # find and read english license file + my $licenselanguage = "en-US"; # always english ! + my $licensefilename = "LICENSE_" . $licenselanguage; + my $licenseincludepatharrayref = installer::worker::get_language_specific_include_pathes($includepatharrayref, $licenselanguage); + + my $licenseref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$licensefilename, $licenseincludepatharrayref, 0); + if ($$licenseref eq "") { installer::exiter::exit_program("ERROR: Could not find License file $licensefilename!", "build_installer_for_languagepack"); } + my $licensefile = installer::files::read_file($$licenseref); + + $infoline = "Found licensefile $licensefilename: $$licenseref \n"; + push( @installer::globals::logfileinfo, $infoline); + + # including variables into license file + installer::scpzipfiles::replace_all_ziplistvariables_in_file($licensefile, $allvariableshashref); + + # add license text into script template + put_license_file_into_script($scriptfile, $licensefile); + + # add rpm or package file name into script template + my ( $packagename, $allnames) = determine_packagename($installdir, $allvariableshashref, $languagestringref); + put_packagename_into_script($scriptfile, $packagename, $allnames); + + # add product name into script template + put_productname_into_script($scriptfile, $allvariableshashref); + + # add product name into script template + put_fullproductname_into_script($scriptfile, $allvariableshashref); + + # add product name into script template + put_searchpackage_into_script($scriptfile, $allvariableshashref); + + # replace linenumber in script template + put_linenumber_into_script($scriptfile, $licensefile, $allnames); + + # saving the script file + my $newscriptfilename = determine_scriptfile_name($packagename); + $newscriptfilename = save_script_file($installdir, $newscriptfilename, $scriptfile); + + # include rpm or package into script + include_package_into_script($newscriptfilename, $installdir, $packagename); + + # remove rpm or package + remove_package($installdir, $packagename); +} + +1; diff --git a/solenv/bin/modules/installer/languages.pm b/solenv/bin/modules/installer/languages.pm new file mode 100644 index 000000000000..978a213bda35 --- /dev/null +++ b/solenv/bin/modules/installer/languages.pm @@ -0,0 +1,383 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: languages.pm,v $ +# +# $Revision: 1.14 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::languages; + +use installer::converter; +use installer::existence; +use installer::exiter; +use installer::globals; +use installer::remover; +use installer::ziplist; + +############################################################################# +# Analyzing the laguage list parameter and language list from zip list file +############################################################################# + +sub analyze_languagelist +{ + my $first = $installer::globals::languagelist; + + $first =~ s/\_/\,/g; # substituting "_" by ",", in case of dmake definition 01_49 + + # Products are separated by a "#", if defined in zip-list by a "|". But "get_info_about_languages" + # substitutes already "|" to "#". This procedure only knows "#" as product separator. + # Different languages for one product are separated by ",". But on the command line the "_" is used. + # Therefore "_" is replaced by "," at the beginning of this procedure. + + while ($first =~ /^(\S+)\#(\S+?)$/) # Minimal matching, to keep the order of languages + { + $first = $1; + my $last = $2; + unshift(@installer::globals::languageproducts, $last); + } + + unshift(@installer::globals::languageproducts, $first); +} + +#################################################### +# Reading languages from zip list file +#################################################### + +sub get_info_about_languages +{ + my ( $allsettingsarrayref ) = @_; + + my $languagelistref; + + $languagelistref = installer::ziplist::getinfofromziplist($allsettingsarrayref, "languages"); + $installer::globals::languagelist = $$languagelistref; + + if ( $installer::globals::languagelist eq "" ) # not defined on command line and not in product list + { + installer::exiter::exit_program("ERROR: Languages not defined on command line (-l) and not in product list!", "get_info_about_languages"); + } + + # Adapting the separator format from zip list. + # | means new product, , (comma) means more than one language in one product + # On the command line, | is difficult to use. Therefore this script uses hashes + + $installer::globals::languagelist =~ s/\|/\#/g; + + analyze_languagelist(); +} + +############################################################################# +# Checking whether all elements of an array A are also member of array B +############################################################################# + +sub all_elements_of_array1_in_array2 +{ + my ($array1, $array2) = @_; + + my $array2_contains_all_elements_of_array1 = 1; + + for ( my $i = 0; $i <= $#{$array1}; $i++ ) + { + if (! installer::existence::exists_in_array(${$array1}[$i], $array2)) + { + $array2_contains_all_elements_of_array1 = 0; + last; + } + } + + return $array2_contains_all_elements_of_array1; +} + +############################################# +# All languages defined for one product +############################################# + +sub get_all_languages_for_one_product +{ + my ( $languagestring, $allvariables ) = @_; + + my @languagearray = (); + + my $last = $languagestring; + + $installer::globals::ismultilingual = 0; # setting the global variable $ismultilingual ! + if ( $languagestring =~ /\,/ ) { $installer::globals::ismultilingual = 1; } + + while ( $last =~ /^\s*(.+?)\,(.+)\s*$/) # "$" for minimal matching, comma separated list + { + my $first = $1; + $last = $2; + installer::remover::remove_leading_and_ending_whitespaces(\$first); + push(@languagearray, "$first"); + } + + installer::remover::remove_leading_and_ending_whitespaces(\$last); + push(@languagearray, "$last"); + + if ( $installer::globals::iswindowsbuild ) + { + my $furthercheck = 1; + + # For some languages (that are not supported by Windows, english needs to be added to the installation set + # Languages saved in "@installer::globals::noMSLocaleLangs" + + if ( all_elements_of_array1_in_array2(\@languagearray, \@installer::globals::noMSLocaleLangs) ) + { + my $officestartlanguage = $languagearray[0]; + unshift(@languagearray, "en-US"); # am Anfang einfügen! + $installer::globals::ismultilingual = 1; + $installer::globals::added_english = 1; + $installer::globals::set_office_start_language = 1; + # setting the variable PRODUCTLANGUAGE, needed for Linguistic-ForceDefaultLanguage.xcu + $allvariables->{'PRODUCTLANGUAGE'} = $officestartlanguage; + $furthercheck = 0; + } + + # In bilingual installation sets, in which english is the first language, + # the Office start language shall be the second language. + + if ( $furthercheck ) + { + if (( $#languagearray == 1 ) && ( $languagearray[0] eq "en-US" )) + { + my $officestartlanguage = $languagearray[1]; + $installer::globals::set_office_start_language = 1; + # setting the variable PRODUCTLANGUAGE, needed for Linguistic-ForceDefaultLanguage.xcu + $allvariables->{'PRODUCTLANGUAGE'} = $officestartlanguage; + } + } + } + + return \@languagearray; +} + +#################################################################################### +# FAKE: The languages string may contain only "de", "en-US", instead of "01", ... +# But this has to be removed as soon as possible. +# In the future the languages are determined with "en-US" instead "01" +# already on the command line and in the zip list file. +#################################################################################### + +sub fake_languagesstring +{ + my ($stringref) = @_; + + # ATTENTION: This function has to be removed as soon as possible! + + $$stringref =~ s/01/en-US/; + $$stringref =~ s/03/pt/; + $$stringref =~ s/07/ru/; + $$stringref =~ s/30/el/; + $$stringref =~ s/31/nl/; + $$stringref =~ s/33/fr/; + $$stringref =~ s/34/es/; + $$stringref =~ s/35/fi/; + $$stringref =~ s/36/hu/; + $$stringref =~ s/37/ca/; + $$stringref =~ s/39/it/; + $$stringref =~ s/42/cs/; + $$stringref =~ s/43/sk/; + $$stringref =~ s/44/en-GB/; + $$stringref =~ s/45/da/; + $$stringref =~ s/46/sv/; + $$stringref =~ s/47/no/; + $$stringref =~ s/48/pl/; + $$stringref =~ s/49/de/; + $$stringref =~ s/55/pt-BR/; + $$stringref =~ s/66/th/; + $$stringref =~ s/77/et/; + $$stringref =~ s/81/ja/; + $$stringref =~ s/82/ko/; + $$stringref =~ s/86/zh-CN/; + $$stringref =~ s/88/zh-TW/; + $$stringref =~ s/90/tr/; + $$stringref =~ s/91/hi-IN/; + $$stringref =~ s/96/ar/; + $$stringref =~ s/97/he/; +} + +########################################################## +# Converting the language array into a string for output +########################################################## + +sub get_language_string +{ + my ($languagesref) = @_; + + my $newstring = ""; + + for ( my $i = 0; $i <= $#{$languagesref}; $i++ ) + { + $newstring = $newstring . ${$languagesref}[$i] . "_"; + } + + # remove ending underline + + $newstring =~ s/\_\s*$//; + + return \$newstring; +} + +########################################################## +# Analyzing the languages in the languages array and +# returning the most important language +########################################################## + +sub get_default_language +{ + my ($languagesref) = @_; + + return ${$languagesref}[0]; # ToDo, only returning the first language +} + +############################################################# +# Contains the installation set one of the asian languages? +############################################################# + +sub detect_asian_language +{ + my ($languagesref) = @_; + + my $containsasia = 0; + + for ( my $i = 0; $i <= $#{$languagesref}; $i++ ) + { + my $onelang = ${$languagesref}[$i]; + $onelang =~ s/\s*$//; + + for ( my $j = 0; $j <= $#installer::globals::asianlanguages; $j++ ) + { + my $asialang = $installer::globals::asianlanguages[$j]; + $asialang =~ s/\s*$//; + + if ( $onelang eq $asialang ) + { + $containsasia = 1; + last; + } + } + + if ( $containsasia ) { last; } + } + + return $containsasia; +} + +############################################################# +# Contains the installation set only asian languages? +############################################################# + +sub contains_only_asian_languages +{ + my ($languagesref) = @_; + + my $onlyasian = 1; + + for ( my $i = 0; $i <= $#{$languagesref}; $i++ ) + { + my $onelang = ${$languagesref}[$i]; + $onelang =~ s/\s*$//; + + if (! installer::existence::exists_in_array($onelang, \@installer::globals::asianlanguages)) + { + $onlyasian = 0; + last; + } + } + + return $onlyasian; +} + +################################################################ +# Contains the installation set one of the western languages +################################################################ + +sub detect_western_language +{ + my ($languagesref) = @_; + + my $containswestern = 1; + + if ( contains_only_asian_languages($languagesref) ) { $containswestern = 0; } + + return $containswestern; +} + +################################################################ +# Determining the language used by the Java installer +################################################################ + +sub get_java_language +{ + my ( $language ) = @_; + + # my $javalanguage = ""; + + # if ( $language eq "en-US" ) { $javalanguage = "en_US"; } + # elsif ( $language eq "ar" ) { $javalanguage = "ar_AR"; } + # elsif ( $language eq "bg" ) { $javalanguage = "bg_BG"; } + # elsif ( $language eq "ca" ) { $javalanguage = "ca_CA"; } + # elsif ( $language eq "cs" ) { $javalanguage = "cs_CS"; } + # elsif ( $language eq "da" ) { $javalanguage = "da_DA"; } + # elsif ( $language eq "de" ) { $javalanguage = "de"; } + # elsif ( $language eq "de" ) { $javalanguage = "de_DE"; } + # elsif ( $language eq "et" ) { $javalanguage = "et_ET"; } + # elsif ( $language eq "el" ) { $javalanguage = "el_EL"; } + # elsif ( $language eq "fi" ) { $javalanguage = "fi_FI"; } + # elsif ( $language eq "fr" ) { $javalanguage = "fr_FR"; } + # elsif ( $language eq "hu" ) { $javalanguage = "hu_HU"; } + # elsif ( $language eq "he" ) { $javalanguage = "he_HE"; } + # elsif ( $language eq "it" ) { $javalanguage = "it_IT"; } + # elsif ( $language eq "nl" ) { $javalanguage = "nl_NL"; } + # elsif ( $language eq "es" ) { $javalanguage = "es_ES"; } + # elsif ( $language eq "sv" ) { $javalanguage = "sv_SV"; } + # elsif ( $language eq "sk" ) { $javalanguage = "sk_SK"; } + # elsif ( $language eq "pl" ) { $javalanguage = "pl_PL"; } + # elsif ( $language eq "pt-BR" ) { $javalanguage = "pt_BR"; } + # elsif ( $language eq "ru" ) { $javalanguage = "ru_RU"; } + # elsif ( $language eq "tr" ) { $javalanguage = "tr_TR"; } + # elsif ( $language eq "ja" ) { $javalanguage = "ja"; } + # elsif ( $language eq "ja" ) { $javalanguage = "ja_JP"; } + # elsif ( $language eq "ko" ) { $javalanguage = "ko_KR"; } + # elsif ( $language eq "th" ) { $javalanguage = "th_TH"; } + # elsif ( $language eq "zh-CN" ) { $javalanguage = "zh_CN"; } + # elsif ( $language eq "zh-TW" ) { $javalanguage = "zh_TW"; } + + # languages not defined yet + # if ( $javalanguage eq "" ) + # { + # $javalanguage = $language; + # $javalanguage =~ s/\-/\_/; + # } + + $javalanguage = $language; + $javalanguage =~ s/\-/\_/; + + return $javalanguage; +} + +1; diff --git a/solenv/bin/modules/installer/logger.pm b/solenv/bin/modules/installer/logger.pm new file mode 100644 index 000000000000..26d0b6313743 --- /dev/null +++ b/solenv/bin/modules/installer/logger.pm @@ -0,0 +1,343 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: logger.pm,v $ +# +# $Revision: 1.10 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::logger; + +use installer::files; +use installer::globals; + +#################################################### +# Including header files into the logfile +#################################################### + +sub include_header_into_logfile +{ + my ($message) = @_; + + my $infoline; + + $infoline = "\n" . get_time_string(); + push( @installer::globals::logfileinfo, $infoline); + + $infoline = "######################################################\n"; + push( @installer::globals::logfileinfo, $infoline); + + $infoline = "$message\n"; + push( @installer::globals::logfileinfo, $infoline); + + + $infoline = "######################################################\n"; + push( @installer::globals::logfileinfo, $infoline); +} + +#################################################### +# Including header files into the logfile +#################################################### + +sub include_header_into_globallogfile +{ + my ($message) = @_; + + my $infoline; + + $infoline = "\n" . get_time_string(); + push( @installer::globals::globallogfileinfo, $infoline); + + $infoline = "######################################################\n"; + push( @installer::globals::globallogfileinfo, $infoline); + + $infoline = "$message\n"; + push( @installer::globals::globallogfileinfo, $infoline); + + + $infoline = "######################################################\n"; + push( @installer::globals::globallogfileinfo, $infoline); +} + +#################################################### +# Write timestamp into log file +#################################################### + +sub include_timestamp_into_logfile +{ + my ($message) = @_; + + my $infoline; + my $timestring = get_time_string(); + $infoline = "$message\t$timestring"; + push( @installer::globals::logfileinfo, $infoline); +} + +#################################################### +# Writing all variables content into the log file +#################################################### + +sub log_hashref +{ + my ($hashref) = @_; + + my $infoline = "\nLogging variable settings:\n"; + push(@installer::globals::globallogfileinfo, $infoline); + + my $itemkey; + + foreach $itemkey ( keys %{$hashref} ) + { + my $line = ""; + my $itemvalue = ""; + if ( $hashref->{$itemkey} ) { $itemvalue = $hashref->{$itemkey}; } + $line = $itemkey . "=" . $itemvalue . "\n"; + push(@installer::globals::globallogfileinfo, $line); + } + + $infoline = "\n"; + push(@installer::globals::globallogfileinfo, $infoline); +} + +######################################################### +# Including global logging info into global log array +######################################################### + +sub globallog +{ + my ($message) = @_; + + my $infoline; + + $infoline = "\n" . get_time_string(); + push( @installer::globals::globallogfileinfo, $infoline); + + $infoline = "################################################################\n"; + push( @installer::globals::globallogfileinfo, $infoline); + + $infoline = "$message\n"; + push( @installer::globals::globallogfileinfo, $infoline); + + $infoline = "################################################################\n"; + push( @installer::globals::globallogfileinfo, $infoline); + +} + +############################################################### +# For each product (new language) a new log file is created. +# Therefore the global logging has to be saved in this file. +############################################################### + +sub copy_globalinfo_into_logfile +{ + for ( my $i = 0; $i <= $#installer::globals::globallogfileinfo; $i++ ) + { + push(@installer::globals::logfileinfo, $installer::globals::globallogfileinfo[$i]); + } +} + +############################################################### +# For each product (new language) a new log file is created. +# Therefore the global logging has to be saved in this file. +############################################################### + +sub debuginfo +{ + my ( $message ) = @_; + + $message = $message . "\n"; + push(@installer::globals::functioncalls, $message); +} + +############################################################### +# Saving the debug information. +############################################################### + +sub savedebug +{ + my ( $outputdir ) = @_; + + installer::files::save_file($outputdir . $installer::globals::debugfilename, \@installer::globals::functioncalls); + print_message( "... writing debug file " . $outputdir . $installer::globals::debugfilename . "\n" ); +} + +############################################################### +# Starting the time +############################################################### + +sub starttime +{ + $installer::globals::starttime = time(); +} + +############################################################### +# Convert time string +############################################################### + +sub convert_timestring +{ + my ($secondstring) = @_; + + my $timestring = ""; + + if ( $secondstring < 60 ) # less than a minute + { + if ( $secondstring < 10 ) { $secondstring = "0" . $secondstring; } + $timestring = "00\:$secondstring min\."; + } + elsif ( $secondstring < 3600 ) + { + my $minutes = $secondstring / 60; + my $seconds = $secondstring % 60; + if ( $minutes =~ /(\d*)\.\d*/ ) { $minutes = $1; } + if ( $minutes < 10 ) { $minutes = "0" . $minutes; } + if ( $seconds < 10 ) { $seconds = "0" . $seconds; } + $timestring = "$minutes\:$seconds min\."; + } + else # more than one hour + { + my $hours = $secondstring / 3600; + my $secondstring = $secondstring % 3600; + my $minutes = $secondstring / 60; + my $seconds = $secondstring % 60; + if ( $hours =~ /(\d*)\.\d*/ ) { $hours = $1; } + if ( $minutes =~ /(\d*)\.\d*/ ) { $minutes = $1; } + if ( $hours < 10 ) { $hours = "0" . $hours; } + if ( $minutes < 10 ) { $minutes = "0" . $minutes; } + if ( $seconds < 10 ) { $seconds = "0" . $seconds; } + $timestring = "$hours\:$minutes\:$seconds hours"; + } + + return $timestring; +} + +############################################################### +# Returning time string for logging +############################################################### + +sub get_time_string +{ + my $currenttime = time(); + $currenttime = $currenttime - $installer::globals::starttime; + $currenttime = convert_timestring($currenttime); + $currenttime = localtime() . " \(" . $currenttime . "\)\n"; + return $currenttime; +} + +############################################################### +# Returning the age of a file (in seconds) +############################################################### + +sub get_file_age +{ + my ( $filename ) = @_; + + my $filetime = (stat($filename))[9]; + my $timediff = time() - $filetime; + return $timediff; +} + +############################################################### +# Stopping the time +############################################################### + +sub stoptime +{ + my $infoline = get_time_string(); + print_message( "$infoline" ); +} + +############################################################### +# Set date string, format: yymmdd +############################################################### + +sub set_installation_date +{ + my $datestring = ""; + + my @timearray = localtime(time); + + my $day = $timearray[3]; + my $month = $timearray[4] + 1; + my $year = $timearray[5] - 100; + + if ( $year < 10 ) { $year = "0" . $year; } + if ( $month < 10 ) { $month = "0" . $month; } + if ( $day < 10 ) { $day = "0" . $day; } + + $datestring = $year . $month . $day; + + return $datestring; +} + +############################################################### +# Console output: messages +############################################################### + +sub print_message +{ + my $message = shift; + chomp $message; + my $force = shift || 0; + print "$message\n" if ( $force || ! $installer::globals::quiet ); + return; +} + +sub print_message_without_newline +{ + my $message = shift; + chomp $message; + print "$message" if ( ! $installer::globals::quiet ); + return; +} + +############################################################### +# Console output: warnings +############################################################### + +sub print_warning +{ + my $message = shift; + chomp $message; + print STDERR "WARNING: $message"; + return; +} + +############################################################### +# Console output: errors +############################################################### + +sub print_error +{ + my $message = shift; + chomp $message; + print STDERR "\n**************************************************\n"; + print STDERR "ERROR: $message"; + print STDERR "\n**************************************************\n"; + return; +} + +1; diff --git a/solenv/bin/modules/installer/mail.pm b/solenv/bin/modules/installer/mail.pm new file mode 100644 index 000000000000..054eccf3f4db --- /dev/null +++ b/solenv/bin/modules/installer/mail.pm @@ -0,0 +1,140 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: mail.pm,v $ +# +# $Revision: 1.10 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::mail; + +use Net::SMTP; +use installer::converter; +use installer::exiter; +use installer::ziplist; + +######################################### +# Sending a mail +######################################### + +sub send_mail +{ + my ($message, $listenerstring, $mailinfostring, $languagesref, $destdir) = @_; + + my $listener = installer::converter::convert_stringlist_into_array($listenerstring, ","); + my $mailinfo = installer::converter::convert_stringlist_into_array($mailinfostring, ","); + + my @listener = (); + + for ( my $i = 0; $i <= $#{$listener}; $i++ ) { push(@listener, ${$listener}[$i]); } + for ( my $i = 0; $i <= $#{$mailinfo}; $i++ ) { ${$mailinfo}[$i] =~ s/\s*$//g; } + + my $smtphost = ${$mailinfo}[0]; + my $account = ${$mailinfo}[1]; + my $sender = ${$mailinfo}[2]; + + if ( ! $smtphost ) { installer::exiter::exit_program("ERROR: Could not read SMTP Host in list file!", "send_mail"); } + if ( ! $account ) { installer::exiter::exit_program("ERROR: Could not read Account in list file!", "send_mail"); } + if ( ! $sender ) { installer::exiter::exit_program("ERROR: Could not read Sender in list file!", "send_mail"); } + + my $subject = ""; + my $basestring = $installer::globals::product . " " . $installer::globals::compiler . $installer::globals::productextension . " " . $installer::globals::build. " " . $installer::globals::buildid . " " . $$languagesref . "\n"; + if ( $message eq "ERROR" ) { $subject = "ERROR: $basestring" } + if ( $message eq "SUCCESS" ) { $subject = "SUCCESS: $basestring" } + + my @message = (); + + my $recipient_string = join ',', @listener; + push(@message, "Subject: $subject"); + push(@message, "To: $recipient_string"); + push(@message, "\n"); + push(@message, "Located at $destdir"); + + if ( $message eq "ERROR" ) + { + for ( my $j = 0; $j <= $#installer::globals::errorlogfileinfo; $j++ ) + { + my $line = $installer::globals::errorlogfileinfo[$j]; + $line =~ s/\s*$//g; + push(@message, $line); + } + } + + for ( my $i = 0; $i <= $#message; $i++ ) { $message[$i] = $message[$i] . "\015\012"; } + + my $smtp = Net::SMTP->new( $smtphost, Hello => $account, Debug => 0 ); + + # set sender + $smtp->mail($sender); + + # listener + my @good_addresses = (); + $smtp->recipient( @listener, { SkipBad => 1 } ); + + # send message + $smtp->data(\@message); + + # quit server + $smtp->quit(); +} + +sub send_fail_mail +{ + my ($allsettingsarrayref, $languagestringref, $errordir) = @_; + + # sending a mail into the error board + my $listener = ""; + $listener = installer::ziplist::getinfofromziplist($allsettingsarrayref, "fail"); + + if ( $$listener ) + { + my $mailinfo = installer::ziplist::getinfofromziplist($allsettingsarrayref, "mailinfo"); + + if ( $$mailinfo ) { send_mail("ERROR", $listener, $mailinfo, $languagestringref, $errordir); } + else { installer::exiter::exit_program("ERROR: Could not read mailinfo in list file!", "send_fail_mail"); } + } +} + +sub send_success_mail +{ + my ($allsettingsarrayref, $languagestringref, $completeshipinstalldir) = @_; + + # sending success mail + my $listener = ""; + $listener = installer::ziplist::getinfofromziplist($allsettingsarrayref, "success"); + + if ( $$listener ) + { + my $mailinfo = installer::ziplist::getinfofromziplist($allsettingsarrayref, "mailinfo"); + + if ( $$mailinfo ) { send_mail("SUCCESS", $listener, $mailinfo, $languagestringref, $completeshipinstalldir); } + else { installer::exiter::exit_program("ERROR: Could not read mailinfo in list file!", "send_success_mail"); } + + } +} + + +1; diff --git a/solenv/bin/modules/installer/packagelist.pm b/solenv/bin/modules/installer/packagelist.pm new file mode 100644 index 000000000000..fce606f7bfdf --- /dev/null +++ b/solenv/bin/modules/installer/packagelist.pm @@ -0,0 +1,844 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: packagelist.pm,v $ +# +# $Revision: 1.19 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::packagelist; + +use installer::converter; +use installer::exiter; +use installer::globals; +use installer::remover; +use installer::scriptitems; + +######################################## +# Check existence of module +######################################## + +sub check_module_existence +{ + my ($onegid, $moduleslist) = @_; + + my $foundgid = 0; + + for ( my $i = 0; $i <= $#{$moduleslist}; $i++ ) + { + my $gid = ${$moduleslist}[$i]->{'gid'}; + + if ( $gid eq $onegid ) + { + $foundgid = 1; + last; + } + } + + return $foundgid; +} + +################################################### +# Analyzing the gids, defined in the packagelist +################################################### + +sub analyze_list +{ + my ($packagelist, $moduleslist) = @_; + + @allpackages = (); + + my $moduleshash = get_module_hash($moduleslist); + + for ( my $i = 0; $i <= $#{$packagelist}; $i++ ) + { + my $onepackage = ${$packagelist}[$i]; + + my $onegid = $onepackage->{'module'}; + + installer::remover::remove_leading_and_ending_whitespaces(\$onegid); + + my $moduleexists = check_module_existence($onegid, $moduleslist); + + if ( ! $moduleexists ) { next; } + + my @allmodules = (); + + push(@allmodules, $onegid); + + # get_children($moduleslist, $onegid, \@allmodules); + get_children_with_hash($moduleshash, $onegid, \@allmodules); + + $onepackage->{'allmodules'} = \@allmodules; + + push(@allpackages, $onepackage); + } + + return \@allpackages; +} + +################################################### +# Creating a hash, that contains the module gids +# as keys and the parentids as values +################################################### + +sub get_module_hash +{ + my ($moduleslist) = @_; + + my %modulehash = (); + + for ( my $i = 0; $i <= $#{$moduleslist}; $i++ ) + { + my $gid = ${$moduleslist}[$i]->{'gid'}; + # Containing only modules with parent. Root modules can be ignored. + if ( ${$moduleslist}[$i]->{'ParentID'} ) { $modulehash{$gid} = ${$moduleslist}[$i]->{'ParentID'}; } + } + + return \%modulehash; +} + +######################################################## +# Recursively defined procedure to order +# modules and directories +######################################################## + +sub get_children_with_hash +{ + my ($modulehash, $parentgid, $newitemorder) = @_; + + foreach my $gid ( keys %{$modulehash} ) + { + my $parent = $modulehash->{$gid}; + + if ( $parent eq $parentgid ) + { + push(@{$newitemorder}, $gid); + my $parent = $gid; + get_children_with_hash($modulehash, $parent, $newitemorder); # recursive! + } + } +} + +######################################################## +# Recursively defined procedure to order +# modules and directories +######################################################## + +sub get_children +{ + my ($allitems, $startparent, $newitemorder) = @_; + + for ( my $i = 0; $i <= $#{$allitems}; $i++ ) + { + my $gid = ${$allitems}[$i]->{'gid'}; + my $parent = ""; + if ( ${$allitems}[$i]->{'ParentID'} ) { $parent = ${$allitems}[$i]->{'ParentID'}; } + + if ( $parent eq $startparent ) + { + push(@{$newitemorder}, $gid); + my $parent = $gid; + get_children($allitems, $parent, $newitemorder); # recursive! + } + } +} + +##################################################################### +# All modules below a defined gid_Module_A are collected now for +# each modules defined in the packagelist. Now the modules have +# to be removed, that are part of more than one package. +##################################################################### + +sub remove_multiple_modules_packages +{ + my ($allpackagemodules) = @_; + + # iterating over all packages + + for ( my $i = 0; $i <= $#{$allpackagemodules}; $i++ ) + { + my $onepackage = ${$allpackagemodules}[$i]; + my $allmodules = $onepackage->{'allmodules'}; + + # print "Modules below $onepackage->{'module'}: $#{$allmodules}\n"; + + # Comparing each package, with all following packages. If a + # gid for the module is part of more than one package, it is + # removed if the number of modules in the package is greater + # in the current package than in the compare package. + + # Taking all modules from package $i + + my $packagecount = $#{$allmodules}; + + my @optimizedpackage = (); + + # iterating over all modules of this package + + for ( my $j = 0; $j <= $#{$allmodules}; $j++ ) + { + my $onemodule = ${$allmodules}[$j]; # this is the module, that shall be removed or not + + my $put_module_into_new_package = 1; + + # iterating over all other packages + + for ( my $k = 0; $k <= $#{$allpackagemodules}; $k++ ) + { + if ( $k == $i ) { next; } # not comparing equal module + + if (! $put_module_into_new_package) { next; } # do not compare, if already found + + my $comparepackage = ${$allpackagemodules}[$k]; + my $allcomparemodules = $comparepackage->{'allmodules'}; + + my $comparepackagecount = $#{$allcomparemodules}; + + # modules will only be removed from packages, that have more modules + # than the compare package + + if ( $packagecount <= $comparepackagecount ) { next; } # nothing to do, take next package + + # iterating over all modules of this package + + for ( my $m = 0; $m <= $#{$allcomparemodules}; $m++ ) + { + my $onecomparemodule = ${$allcomparemodules}[$m]; + + if ( $onemodule eq $onecomparemodule ) # this $onemodule has to be removed + { + $put_module_into_new_package = 0; + } + } + } + + if ( $put_module_into_new_package ) + { + push(@optimizedpackage, $onemodule) + } + } + + $onepackage->{'allmodules'} = \@optimizedpackage; + } + + # for ( my $i = 0; $i <= $#{$allpackagemodules}; $i++ ) + # { + # my $onepackage = ${$allpackagemodules}[$i]; + # my $allmodules = $onepackage->{'allmodules'}; + # print "New: Modules below $onepackage->{'module'}: $#{$allmodules}\n"; + # } + +} + +##################################################################### +# Analyzing all files if they belong to a special package. +# A package is described by a list of modules. +##################################################################### + +sub find_files_for_package +{ + my ($filelist, $onepackage) = @_; + + my @newfilelist = (); + + for ( my $i = 0; $i <= $#{$filelist}; $i++ ) + { + my $onefile = ${$filelist}[$i]; + my $modulesstring = $onefile->{'modules'}; # comma separated modules list + my $moduleslist = installer::converter::convert_stringlist_into_array(\$modulesstring, ","); + + my $includefile = 0; + + # iterating over all modules of this file + + for ( my $j = 0; $j <= $#{$moduleslist}; $j++ ) + { + if ( $includefile ) { next; } + my $filemodule = ${$moduleslist}[$j]; + installer::remover::remove_leading_and_ending_whitespaces(\$filemodule); + + # iterating over all modules of the package + + my $packagemodules = $onepackage->{'allmodules'}; + + for ( my $k = 0; $k <= $#{$packagemodules}; $k++ ) + { + if ( $includefile ) { next; } + my $packagemodule = ${$packagemodules}[$k]; + + if ( $filemodule eq $packagemodule ) + { + $includefile = 1; + last; + } + } + } + + if ( $includefile ) + { + push(@newfilelist, $onefile); + } + } + + return \@newfilelist; +} + +##################################################################### +# Analyzing all links if they belong to a special package. +# A package is described by a list of modules. +# A link is inserted into the package, if the corresponding +# file is also inserted. +##################################################################### + +sub find_links_for_package +{ + my ($linklist, $filelist) = @_; + + # First looking for all links with a FileID. + # Then looking for all links with a ShortcutID. + + my @newlinklist = (); + + for ( my $i = 0; $i <= $#{$linklist}; $i++ ) + { + my $includelink = 0; + + my $onelink = ${$linklist}[$i]; + + my $fileid = ""; + if ( $onelink->{'FileID'} ) { $fileid = $onelink->{'FileID'}; } + + if ( $fileid eq "" ) { next; } # A link with a ShortcutID + + for ( my $j = 0; $j <= $#{$filelist}; $j++ ) # iterating over file list + { + my $onefile = ${$filelist}[$j]; + my $gid = $onefile->{'gid'}; + + if ( $gid eq $fileid ) + { + $includelink = 1; + last; + } + } + + if ( $includelink ) + { + push(@newlinklist, $onelink); + } + } + + # iterating over the new list, because of all links with a ShortcutID + + for ( my $i = 0; $i <= $#{$linklist}; $i++ ) + { + my $includelink = 0; + + my $onelink = ${$linklist}[$i]; + + my $shortcutid = ""; + if ( $onelink->{'ShortcutID'} ) { $shortcutid = $onelink->{'ShortcutID'}; } + + if ( $shortcutid eq "" ) { next; } # A link with a ShortcutID + + for ( my $j = 0; $j <= $#newlinklist; $j++ ) # iterating over newly created link list + { + my $onefilelink = $newlinklist[$j]; + my $gid = $onefilelink->{'gid'}; + + if ( $gid eq $shortcutid ) + { + $includelink = 1; + last; + } + } + + if ( $includelink ) + { + push(@newlinklist, $onelink); + } + } + + return \@newlinklist; +} + +##################################################################### +# Analyzing all directories if they belong to a special package. +# A package is described by a list of modules. +# Directories are included into the package, if they are needed +# by a file or a link included into the package. +# Attention: A directory with the flag CREATE, is only included +# into the root module: +# ($packagename eq $installer::globals::rootmodulegid) +##################################################################### + +sub find_dirs_for_package +{ + my ($dirlist, $onepackage) = @_; + + my @newdirlist = (); + + for ( my $i = 0; $i <= $#{$dirlist}; $i++ ) + { + my $onedir = ${$dirlist}[$i]; + my $modulesstring = $onedir->{'modules'}; # comma separated modules list + my $moduleslist = installer::converter::convert_stringlist_into_array(\$modulesstring, ","); + + my $includedir = 0; + + # iterating over all modules of this dir + + for ( my $j = 0; $j <= $#{$moduleslist}; $j++ ) + { + if ( $includedir ) { last; } + my $dirmodule = ${$moduleslist}[$j]; + installer::remover::remove_leading_and_ending_whitespaces(\$dirmodule); + + # iterating over all modules of the package + + my $packagemodules = $onepackage->{'allmodules'}; + + for ( my $k = 0; $k <= $#{$packagemodules}; $k++ ) + { + my $packagemodule = ${$packagemodules}[$k]; + + if ( $dirmodule eq $packagemodule ) + { + $includedir = 1; + last; + } + } + } + + if ( $includedir ) + { + push(@newdirlist, $onedir); + } + } + + return \@newdirlist; +} + +##################################################################### +# Resolving all variables in the packagename. +##################################################################### + +sub resolve_packagevariables +{ + my ($packagenameref, $variableshashref, $make_lowercase) = @_; + + my $key; + + foreach $key (keys %{$variableshashref}) + { + my $value = $variableshashref->{$key}; + if ( $make_lowercase ) { $value = lc($value); } + $$packagenameref =~ s/\%$key/$value/g; + } +} + +##################################################################### +# New packages system. +##################################################################### + +################################################################## +# Controlling the content of the packagelist +# 1. Items in @installer::globals::packagelistitems must exist +# 2. If a shellscript file is defined, it must exist +################################################################## + +sub check_packagelist +{ + my ($packages) = @_; + + if ( ! ( $#{$packages} > -1 )) { installer::exiter::exit_program("ERROR: No packages defined!", "check_packagelist"); } + + for ( my $i = 0; $i <= $#{$packages}; $i++ ) + { + my $onepackage = ${$packages}[$i]; + + my $element; + + # checking all items that must be defined + + foreach $element (@installer::globals::packagelistitems) + { + if ( ! exists($onepackage->{$element}) ) + { + installer::exiter::exit_program("ERROR in package list: No value for $element !", "check_packagelist"); + } + } + + # checking the existence of the script file, if defined + + if ( $onepackage->{'script'} ) + { + my $scriptfile = $onepackage->{'script'}; + my $gid = $onepackage->{'module'}; + my $fileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$scriptfile, "" , 0); + + if ( $$fileref eq "" ) { installer::exiter::exit_program("ERROR: Could not find script file $scriptfile for module $gid!", "check_packagelist"); } + + my $infoline = "$gid: Using script file: \"$$fileref\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + + $onepackage->{'script'} = $$fileref; + } + } +} + +##################################################################### +# Reading pack info for one module from packinfo file. +##################################################################### + +sub get_packinfo +{ + my ($gid, $filename, $packages, $onelanguage, $islanguagemodule) = @_; + + my $packagelist = installer::files::read_file($filename); + + my @allpackages = (); + + for ( my $i = 0; $i <= $#{$packagelist}; $i++ ) + { + my $line = ${$packagelist}[$i]; + + if ( $line =~ /^\s*\#/ ) { next; } # this is a comment line + + if ( $line =~ /^\s*Start\s*$/i ) # a new package definition + { + my %onepackage = (); + + my $counter = $i + 1; + + while (!( ${$packagelist}[$counter] =~ /^\s*End\s*$/i )) + { + if ( ${$packagelist}[$counter] =~ /^\s*(\S+)\s*\=\s*\"(.*)\"/ ) + { + my $key = $1; + my $value = $2; + $onepackage{$key} = $value; + } + + $counter++; + } + + $onepackage{'islanguagemodule'} = $islanguagemodule; + if ( $islanguagemodule ) + { + $saveonelanguage = $onelanguage; + $saveonelanguage =~ s/_/-/g; + $onepackage{'language'} = $saveonelanguage; + } + + push(@allpackages, \%onepackage); + } + } + + # looking for the packinfo with the correct gid + + my $foundgid = 0; + my $onepackage; + foreach $onepackage (@allpackages) + { + # Adding the language to the module gid for LanguagePacks ! + # Making the module gid language specific: gid_Module_Root -> gir_Module_Root_pt_BR (as defined in scp2) + if ( $onelanguage ne "" ) { $onepackage->{'module'} = $onepackage->{'module'} . "_$onelanguage"; } + + if ( $onepackage->{'module'} eq $gid ) + { + # Resolving the language identifier + my $onekey; + foreach $onekey ( keys %{$onepackage} ) + { + # Some keys require "-" instead of "_" for example in "en-US". All package names do not use underlines. + my $locallang = $onelanguage; + if (( $onekey eq "solarispackagename" ) || + ( $onekey eq "solarisrequires" ) || + ( $onekey eq "packagename" ) || + ( $onekey eq "requires" )) { $locallang =~ s/_/-/g; } # avoiding illegal package abbreviation + $onepackage->{$onekey} =~ s/\%LANGUAGESTRING/$locallang/g; + } + + # Saving the language for the package + my $lang = $onelanguage; + $lang =~ s/_/-/g; + $onepackage->{'specificlanguage'} = $lang; + + push(@{$packages}, $onepackage); + $foundgid = 1; + last; + } + } + + if ( ! $foundgid ) + { + installer::exiter::exit_program("ERROR: Could not find package info for module $gid in file \"$filename\"!", "get_packinfo"); + } +} + +##################################################################### +# Collecting all packages from scp project. +##################################################################### + +sub collectpackages +{ + my ( $allmodules, $languagesarrayref ) = @_; + + installer::logger::include_header_into_logfile("Collecting packages:"); + + my @packages = (); + my %gid_analyzed = (); + + my $onemodule; + foreach $onemodule ( @{$allmodules} ) + { + my $packageinfo = "PackageInfo"; + if (( $installer::globals::tab ) && ( $onemodule->{"TabPackageInfo"} )) { $packageinfo = "TabPackageInfo" } + + if ( $onemodule->{$packageinfo} ) # this is a package module! + { + my $modulegid = $onemodule->{'gid'}; + + # Only collecting modules with correct language for language packs +# if ( $installer::globals::languagepack ) { if ( ! ( $modulegid =~ /_$onelanguage\s*$/ )) { next; } } + # Resetting language, if this is no language pack +# if ( ! $installer::globals::languagepack ) { $onelanguage = ""; } + + my $styles = ""; + if ( $onemodule->{'Styles'} ) { $styles = $onemodule->{'Styles'}; } + + # checking modules with style LANGUAGEMODULE + my $islanguagemodule = 0; + my $onelanguage = ""; + if ( $styles =~ /\bLANGUAGEMODULE\b/ ) + { + $islanguagemodule = 1; + $onelanguage = $onemodule->{'Language'}; # already checked, that it is set. + $onelanguage =~ s/-/_/g; # pt-BR -> pt_BR in scp + } + + # Modules in different languages are listed more than once in multilingual installation sets + if ( exists($gid_analyzed{$modulegid}) ) { next; } + $gid_analyzed{$modulegid} = 1; + + my $packinfofile = $onemodule->{$packageinfo}; + + # The file with package information has to be found in path list + my $fileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$packinfofile, "" , 0); + + if ( $$fileref eq "" ) { installer::exiter::exit_program("ERROR: Could not find file $packinfofile for module $modulegid!", "collectpackages"); } + + my $infoline = "$modulegid: Using packinfo: \"$$fileref\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + + get_packinfo($modulegid, $$fileref, \@packages, $onelanguage, $islanguagemodule); + } + } + + return \@packages; +} + +##################################################################### +# Printing packages content for debugging purposes +##################################################################### + +sub log_packages_content +{ + my ($packages) = @_; + + if ( ! ( $#{$packages} > -1 )) { installer::exiter::exit_program("ERROR: No packages defined!", "print_content"); } + + installer::logger::include_header_into_logfile("Logging packages content:"); + + my $infoline = ""; + + for ( my $i = 0; $i <= $#{$packages}; $i++ ) + { + my $onepackage = ${$packages}[$i]; + + # checking all items that must be defined + + $infoline = "Package $onepackage->{'module'}\n"; + push(@installer::globals::logfileinfo, $infoline); + + my $key; + foreach $key (sort keys %{$onepackage}) + { + if ( $key =~ /^\s*\;/ ) { next; } + + if ( $key eq "allmodules" ) + { + $infoline = "\t$key:\n"; + push(@installer::globals::logfileinfo, $infoline); + my $onemodule; + foreach $onemodule ( @{$onepackage->{$key}} ) + { + $infoline = "\t\t$onemodule\n"; + push(@installer::globals::logfileinfo, $infoline); + } + } + else + { + $infoline = "\t$key: $onepackage->{$key}\n"; + push(@installer::globals::logfileinfo, $infoline); + } + } + + $infoline = "\n"; + push(@installer::globals::logfileinfo, $infoline); + + } +} + +##################################################################### +# Creating assignments from modules to destination pathes. +# This is required for logging in fileinfo file. Otherwise +# the complete destination file would not be known in file list. +# Saved in %installer::globals::moduledestination +##################################################################### + +sub create_module_destination_hash +{ + my ($packages, $allvariables) = @_; + + for ( my $i = 0; $i <= $#{$packages}; $i++ ) + { + my $onepackage = ${$packages}[$i]; + + my $defaultdestination = $onepackage->{'destpath'}; + resolve_packagevariables(\$defaultdestination, $allvariables, 1); + if ( $^O =~ /darwin/i ) { $defaultdestination =~ s/\/opt\//\/Applications\//; } + + foreach my $onemodule ( @{$onepackage->{'allmodules'}} ) + { + $installer::globals::moduledestination{$onemodule} = $defaultdestination; + } + } +} + +##################################################################### +# Adding the default pathes into the files collector for Unixes. +# This is necessary to know the complete destination path in +# fileinfo log file. +##################################################################### + +sub add_defaultpathes_into_filescollector +{ + my ($allfiles) = @_; + + for ( my $i = 0; $i <= $#{$allfiles}; $i++ ) + { + my $onefile = ${$allfiles}[$i]; + + if ( ! $onefile->{'destination'} ) { installer::exiter::exit_program("ERROR: No destination found at file $onefile->{'gid'}!", "add_defaultpathes_into_filescollector"); } + my $destination = $onefile->{'destination'}; + + if ( ! $onefile->{'modules'} ) { installer::exiter::exit_program("ERROR: No modules found at file $onefile->{'gid'}!", "add_defaultpathes_into_filescollector"); } + my $module = $onefile->{'modules'}; + # If modules contains a list of modules, only taking the first one. + if ( $module =~ /^\s*(.*?)\,/ ) { $module = $1; } + + if ( ! exists($installer::globals::moduledestination{$module}) ) { installer::exiter::exit_program("ERROR: No default destination path found for module $module!", "add_defaultpathes_into_filescollector"); } + my $defaultpath = $installer::globals::moduledestination{$module}; + $defaultpath =~ s/\/\s*$//; # removing ending slashes + my $fulldestpath = $defaultpath . $installer::globals::separator . $destination; + + $onefile->{'fulldestpath'} = $fulldestpath; + } +} + +##################################################################### +# Creating list of cabinet files from packages +##################################################################### + +sub prepare_cabinet_files +{ + my ($packages, $allvariables) = @_; + + if ( ! ( $#{$packages} > -1 )) { installer::exiter::exit_program("ERROR: No packages defined!", "print_content"); } + + installer::logger::include_header_into_logfile("Preparing cabinet files:"); + + my $infoline = ""; + + for ( my $i = 0; $i <= $#{$packages}; $i++ ) + { + my $onepackage = ${$packages}[$i]; + + my $cabinetfile = "$onepackage->{'packagename'}\.cab"; + + resolve_packagevariables(\$cabinetfile, $allvariables, 0); + + $installer::globals::allcabinets{$cabinetfile} = 1; + + # checking all items that must be defined + + $infoline = "Package $onepackage->{'module'}\n"; + push(@installer::globals::logfileinfo, $infoline); + + # Assigning the cab file to the module and also to all corresponding sub modules + + my $onemodule; + foreach $onemodule ( @{$onepackage->{'allmodules'}} ) + { + if ( ! exists($installer::globals::allcabinetassigns{$onemodule}) ) + { + $installer::globals::allcabinetassigns{$onemodule} = $cabinetfile; + } + else + { + my $infoline = "Warning: Already existing assignment: $onemodule : $installer::globals::allcabinetassigns{$onemodule}\n"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = "Ignoring further assignment: $onemodule : $cabinetfile\n"; + push(@installer::globals::logfileinfo, $infoline); + } + } + } +} + +##################################################################### +# Logging assignments of cabinet files +##################################################################### + +sub log_cabinet_assignments +{ + installer::logger::include_header_into_logfile("Logging cabinet files:"); + + my $infoline = "List of cabinet files:\n"; + push(@installer::globals::logfileinfo, $infoline); + + my $key; + foreach $key ( sort keys %installer::globals::allcabinets ) { push(@installer::globals::logfileinfo, "\t$key\n"); } + + $infoline = "\nList of assignments from modules to cabinet files:\n"; + push(@installer::globals::logfileinfo, $infoline); + + foreach $key ( sort keys %installer::globals::allcabinetassigns ) { push(@installer::globals::logfileinfo, "\t$key : $installer::globals::allcabinetassigns{$key}\n"); } +} + +1; diff --git a/solenv/bin/modules/installer/packagepool.pm b/solenv/bin/modules/installer/packagepool.pm new file mode 100644 index 000000000000..4ca68bf30d38 --- /dev/null +++ b/solenv/bin/modules/installer/packagepool.pm @@ -0,0 +1,1056 @@ +#************************************************************************* +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: copyproject.pm,v $ +# +# $Revision: 1.8 $ +# +# last change: $Author: obo $ $Date: 2007/07/19 07:16:23 $ +# +# The Contents of this file are made available subject to +# the terms of GNU Lesser General Public License Version 2.1. +# +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2005 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +#************************************************************************* + +package installer::packagepool; + +use Digest::MD5; +use installer::exiter; +use installer::globals; +use installer::logger; +use installer::pathanalyzer; +use installer::worker; + +###################################################### +# Checking the md5sum of a file +###################################################### + +sub get_md5sum +{ + my ($filename) = @_; + + open(FILE, "<$filename") or die "ERROR: Can't open $filename for creating file hash"; + binmode(FILE); + my $digest = Digest::MD5->new->addfile(*FILE)->hexdigest; + close(FILE); + + return $digest; +} + +#################################################### +# Setting a unique sessionid to identify this +# packaging process. +#################################################### + +sub set_sessionid +{ + my $pid = $$; # process id + my $timer = time(); # time + $installer::globals::sessionid = $pid . $timer; + $installer::globals::sessionidset = 1; + my $infoline = "\nPool: Setting session id: $installer::globals::sessionid.\n"; + push( @installer::globals::logfileinfo, $infoline); +} + +#################################################### +# Setting and creating pool path. +#################################################### + +sub set_pool_path +{ + $installer::globals::unpackpath =~ s/\Q$installer::globals::separator\E\s*$//; # removing ending slashes and backslashes + $installer::globals::poolpath = $installer::globals::unpackpath . $installer::globals::separator . "pool_" . $installer::globals::packageformat; + installer::systemactions::create_directory($installer::globals::poolpath); + $installer::globals::poolpathset = 1; +} + +#################################################### +# Comparing the content of two epm files. +#################################################### + +sub compare_epm_content +{ + my ($oldcontent, $newcontent) = @_; + + my $identical = 1; + my $diffinfo = ""; + + # Removing empty lines and files from $newcontent + + my @newlocalcontent = (); + for ( my $i = 0; $i <= $#{$newcontent}; $i++ ) + { + if ( ${$newcontent}[$i] =~ /^\s*$/ ) { next; } # Removing empty lines from $newcontent. Empty lines are also not included into pcf file, from where $oldcontent was read. + if ( ${$newcontent}[$i] =~ /^\s*f\s+/ ) { next; } # Ignoring files, they can contain temporary pathes + if (( ${$newcontent}[$i] =~ /^\s*%readme\s+/ ) || ( ${$newcontent}[$i] =~ /^\s*%license\s+/ )) { next; } # ignoring license and readme (language specific!) + my $oneline = ${$newcontent}[$i]; + $oneline =~ s/\s*$//; # Removing line ends. Also not included in old epm file, that is read from pcf file. + push(@newlocalcontent, $oneline); + } + + my $oldmember = $#{$oldcontent} + 1; + my $newmember = $#newlocalcontent + 1; + + # comparing the count + if ( $oldmember != $newmember ) + { + $identical = 0; + installer::logger::print_message("\n...... changed length of EPM file\n"); + $diffinfo = "Pool: EPM, different line count: old epm file: $oldmember, new epm file: $newmember\n"; + push(@installer::globals::epmdifflist, $diffinfo); + } + + # comparing the content line for line, so the order must not change + + if ( $identical ) + { + for ( my $i = 0; $i <= $#{$oldcontent}; $i++ ) + { + if ( ${$oldcontent}[$i] ne $newlocalcontent[$i] ) + { + $identical = 0; + my $line = $i + 1; + installer::logger::print_message("\n...... different content in EPM file\n"); + $diffinfo = "Pool: EPM, line $line changed from \"${$oldcontent}[$i]\" to \"$newlocalcontent[$i]\".\n"; + push(@installer::globals::epmdifflist, $diffinfo); + last; + } + } + } + + return $identical; +} + +#################################################### +# Comparing the content of two pcf files. +#################################################### + +sub compare_package_content +{ + my ($oldcontent, $newcontent) = @_; + + my $identical = 1; + my $infoline = ""; + + my $oldmember = scalar keys %{$oldcontent}; + my $newmember = scalar keys %{$newcontent}; + + # comparing the count + + if ( $oldmember != $newmember ) + { + # Logging the difference + $identical = 0; + installer::logger::print_message("\n...... different number of files in packages. New number: $newmember, old number: $oldmember\n"); + $infoline = "Different number of files in packages. New number: $newmember, old number: $oldmember\n"; + push(@installer::globals::pcfdiffcomment, $infoline); + } + + # comparing the keys + + if ( $identical ) + { + my $first = 1; + my $start = "\n"; + foreach my $dest ( keys %{$newcontent} ) + { + if ( ! exists($oldcontent->{$dest}) ) + { + $identical = 0; + installer::logger::print_message("$start...... file only in one package (A): $dest\n"); + $infoline = "File only in existing pool package: $dest\n"; + push(@installer::globals::pcfdiffcomment, $infoline); + if ( $first ) { $start = ""; } + $first = 0; + } + } + + # collecting all differences + if ( ! $identical ) + { + foreach my $dest ( keys %{$oldcontent} ) + { + if ( ! exists($newcontent->{$dest}) ) + { + $identical = 0; + installer::logger::print_message("$start...... file only in one package (B): $dest\n"); + $infoline = "File only in new package: $dest\n"; + push(@installer::globals::pcfdiffcomment, $infoline); + if ( $first ) { $start = ""; } + $first = 0; + } + } + } + } + + # comparing the checksum + + if ( $identical ) + { + my $first = 1; + + foreach my $dest ( keys %{$newcontent} ) + { + if ( $newcontent->{$dest}->{'md5sum'} ne $oldcontent->{$dest}->{'md5sum'} ) + { + $identical = 0; + if ( $first == 1 ) + { + installer::logger::print_message("\n"); + $first = 0; + } + $installer::globals::pcfdifflist{$dest} = 1; + installer::logger::print_message("...... different file: $dest\n"); + # last; + } + + if ( $installer::globals::iswindowsbuild ) + { + if ( $newcontent->{$dest}->{'uniquename'} ne $oldcontent->{$dest}->{'uniquename'} ) + { + $identical = 0; + $installer::globals::pcfdifflist{$dest} = 1; + installer::logger::print_message("\n...... different file: $dest"); + # last; + } + } + } + } + + return $identical; +} + +#################################################### +# Calculating content of pcf file. +#################################################### + +sub calculate_current_content +{ + my ($filesarray, $packagename) = @_; + + installer::logger::include_timestamp_into_logfile("\nCalculating content for package content file ($packagename), start"); + + my %globalcontent = (); + + for ( my $i = 0; $i <= $#{$filesarray}; $i++ ) + { + my %onefilehash = (); + + my $onefile = ${$filesarray}[$i]; + if ( ! $onefile->{'sourcepath'} ) { installer::exiter::exit_program("ERROR: No sourcepath found for file $onefile->{'gid'}", "calculate_current_content"); } + my $source = $onefile->{'sourcepath'}; + if ( $onefile->{'zipfilesource'} ) { $source = $onefile->{'zipfilesource'}; } + if ( ! -f $source ) { installer::exiter::exit_program("ERROR: Sourcefile not found: $source ($onefile->{'gid'})", "calculate_current_content"); } + + # For Windows the unique name inside the cabinet file also has to be saved + my $uniquename = ""; + if ( $installer::globals::iswindowsbuild ) { $uniquename = $onefile->{'uniquename'};} + + my $destination = $onefile->{'destination'}; + my $checksum = get_md5sum($source); + + $onefilehash{'md5sum'} = $checksum; + $onefilehash{'uniquename'} = $uniquename; + + if ( exists($globalcontent{$destination}) ) { installer::exiter::exit_program("ERROR: Destination not unique: $destination ($onefile->{'gid'})", "calculate_current_content"); } + $globalcontent{$destination} = \%onefilehash; + } + + installer::logger::include_timestamp_into_logfile("\nCalculating content for package content file ($packagename), start"); + + return \%globalcontent; +} + +#################################################### +# Writing pcf file. +#################################################### + +sub create_pcfcontent_file +{ + my ($realpackagename, $md5sum, $filesize, $fullpackagename, $pkgversion, $epmfilecontent, $pcffilename) = @_; + + my @content = (); + my $oneline = "PackageName: $realpackagename\n"; + push(@content, $oneline); + + $oneline = "md5sum: $md5sum\n"; + push(@content, $oneline); + + $oneline = "FileSize: $filesize\n"; + push(@content, $oneline); + + $oneline = "FullPackageName: $fullpackagename\n"; + push(@content, $oneline); + + $oneline = "PkgVersion: $pkgversion\n"; + push(@content, $oneline); + + foreach my $dest (keys %{$installer::globals::newpcfcontent} ) + { + $oneline = "Files:\t$dest\t$installer::globals::newpcfcontent->{$dest}->{'md5sum'}\t$installer::globals::newpcfcontent->{$dest}->{'uniquename'}\n"; + push(@content, $oneline); + } + + for ( my $i = 0; $i <= $#{$epmfilecontent}; $i++ ) + { + if ( ${$epmfilecontent}[$i] =~ /^\s*$/ ) { next; } # avoiding empty lines + if ( ${$epmfilecontent}[$i] =~ /^\s*f\s+/ ) { next; } # ignoring files, because they can contain temporary pathes + if (( ${$epmfilecontent}[$i] =~ /^\s*%readme\s+/ ) || ( ${$epmfilecontent}[$i] =~ /^\s*%license\s+/ )) { next; } # ignoring license and readme (language specific!) + $oneline = "EPM:\t${$epmfilecontent}[$i]"; + push(@content, $oneline); + } + + installer::files::save_file($pcffilename, \@content); +} + +####################################################### +# Reading the content of the package content file. +####################################################### + +sub read_pcf_content +{ + my ($pcffilename) = @_; + + my %allcontent = (); + my @epmfile = (); + my $realpackagename = ""; + + my $content = installer::files::read_file($pcffilename); + + for ( my $i = 0; $i <= $#{$content}; $i++ ) + { + my $line = ${$content}[$i]; + + if ( $line =~ /^\s*PackageName\:\s*(.*?)\s*$/ ) + { + $realpackagename = $1; + $installer::globals::xpdpackageinfo{'RealPackageName'} = $realpackagename; + next; + } + + if ( $line =~ /^\s*FullPackageName\:\s*(.*?)\s*$/ ) + { + $installer::globals::xpdpackageinfo{'FullPackageName'} = $1; + next; + } + + if ( $line =~ /^\s*FileSize\:\s*(.*?)\s*$/ ) + { + $installer::globals::xpdpackageinfo{'FileSize'} = $1; + next; + } + + if ( $line =~ /^\s*PkgVersion\:\s*(.*?)\s*$/ ) + { + $installer::globals::xpdpackageinfo{'PkgVersion'} = $1; + next; + } + + if ( $line =~ /^\s*md5sum\:\s*(.*?)\s*$/ ) + { + $installer::globals::xpdpackageinfo{'md5sum'} = $1; + next; + } + + if ( $line =~ /^\s*Files:\t(.+?)\t(.+?)\t(.*?)\s*$/ ) + { + my $destination = $1; + my $checksum = $2; + my $uniquename = $3; + + my %onefilehash = (); + $onefilehash{'md5sum'} = $checksum; + $onefilehash{'uniquename'} = $uniquename; + + $allcontent{$destination} = \%onefilehash; + next; + } + + if ( $line =~ /^\s*EPM:\t(.*?)\s*$/ ) # A line can be empty in epm file + { + my $epmcontent = $1; + push(@epmfile, $epmcontent); + next; + } + } + + if ( $realpackagename eq "" ) { installer::exiter::exit_program("ERROR: Real package name not found in pcf file: \"$pcffilename\"", "read_pcf_content"); } + + return ($realpackagename, \%allcontent, \@epmfile); +} + +#################################################### +# Checking, if a specific package can be +# created at the moment. +#################################################### + +sub check_package_availability +{ + my ($packagename) = @_; + + my $package_is_available = 1; + + my $checkfilename = $installer::globals::poolpath . $installer::globals::separator . $packagename . ".pcf.check"; + my $lockfilename = $installer::globals::poolpath . $installer::globals::separator . $packagename . ".pcf.lock"; + + if (( -f $checkfilename ) || ( -f $lockfilename )) { $package_is_available = 0; } + + return $package_is_available; +} + +#################################################### +# Check, if the existence of the check or lock +# file requires an exit of packaging process. +#################################################### + +sub check_pool_exit +{ + my ( $lockfilename, $timecounter ) = @_; + + # How old is this lock file? + my $timeage = installer::logger::get_file_age($lockfilename); + + # if ( $timeage > 1800 ) # file is older than half an hour + if ( $timeage > 3600 ) # file is older than an hour + { + my $timestring = installer::logger::convert_timestring($timeage); + my $infoline = "\nPool: Attention: \"$lockfilename\" is too old ($timestring). Removing file!\n"; + installer::logger::print_message( "... $infoline" ); + push( @installer::globals::logfileinfo, $infoline); + unlink $lockfilename; + # installer::exiter::exit_program("ERROR: Waiting too long for removal of lock file \"$lockfilename\"", "check_pool_exit (packagepool)"); + } + else + { + my $filecontent = installer::files::read_file($lockfilename); + my $waittime = $timecounter * 10; + $waittime = installer::logger::convert_timestring($waittime); + my $infoline = "\nPool: Warning: \"$lockfilename\" blocks this process for $waittime. Lock content: \"${$filecontent}[0]\"\n"; + installer::logger::print_message( "... $infoline" ); + push( @installer::globals::logfileinfo, $infoline); + } +} + +############################################################################ +# This function logs some information, that can be used to find +# pool problems. +############################################################################ + +sub log_pool_info +{ + my ( $file_exists ) = @_; + + my $infoline = ""; + + # Content saved in + # $installer::globals::savelockfilecontent = installer::files::read_file($filename); + # $installer::globals::savelockfilename = $filename; + + if ( $file_exists ) + { + $infoline = "\nPool Problem: Lock file \"$installer::globals::savelockfilename\" belongs to another process. This process has session id: $installer::globals::sessionid .\n"; + push( @installer::globals::logfileinfo, $infoline); + $infoline = "Content of Lock file:\n"; + push( @installer::globals::logfileinfo, $infoline); + foreach my $line ( @{$installer::globals::savelockfilecontent} ) { push( @installer::globals::logfileinfo, $line); } + } + else + { + $infoline = "\nPool Problem: Lock file \"$installer::globals::savelockfilename\" does not exist anymore (this process has session id: $installer::globals::sessionid) .\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +############################################################################ +# Checking, if this process is the owner of the lock file in the pool. +# This can be determined by the Process ID, that is written at the +# beginning of the first line into the lock file. +############################################################################ + +sub process_is_owner +{ + my ( $filename ) = @_; + + my $process_is_owner = 0; + + $installer::globals::savelockfilecontent = installer::files::read_file($filename); + $installer::globals::savelockfilename = $filename; + + if ( ${$installer::globals::savelockfilecontent}[0] =~ /^\s*\Q$installer::globals::sessionid\E\s+/ ) { $process_is_owner = 1; } + + return $process_is_owner; +} + +#################################################### +# Removing a package from installation set, if +# there were pooling problems. +#################################################### + +sub remove_package_from_installset +{ + my ($newpackagepath) = @_; + + my $infoline = "Pool problem: Removing package \"$newpackagepath\" from installation set!\n"; + push(@installer::globals::logfileinfo, $infoline); + + if ( -f $newpackagepath ) { unlink $newpackagepath; } + if ( -d $newpackagepath ) { installer::systemactions::remove_complete_directory($newpackagepath, 1); } + + # Keeping the content of @installer::globals::installsetcontent up to date. Removing the last package. + pop(@installer::globals::installsetcontent); +} + +#################################################### +# Check, if the package is in the pool and if +# there are no changes in the package. +#################################################### + +sub package_is_up_to_date +{ + my ($allvariables, $onepackage, $packagename, $newepmcontent, $filesinpackage, $installdir, $subdir, $languagestringref) = @_; + + installer::logger::print_message_without_newline( "... checking pool package $packagename ..." ); + + installer::logger::include_header_into_logfile("Checking package in pool: $packagename"); + + if ( ! $installer::globals::poolpathset ) { installer::packagepool::set_pool_path(); } + if ( ! $installer::globals::sessionidset ) { installer::packagepool::set_sessionid(); } + + my $infoline = ""; + # Resetting some variables for this package + my $package_is_up_to_date = 0; + my $realpackagename = ""; + my $oldepmcontent = ""; + my $waited_for_check = 0; + my $waited_for_lock = 0; + $installer::globals::newpcfcontentcalculated = 0; + %installer::globals::pcfdifflist = (); + @installer::globals::pcfdiffcomment = (); + @installer::globals::epmdifflist = (); + + # Reading the package content file, if this file exists (extension *.pcf) + my $filename = $installer::globals::poolpath . $installer::globals::separator . $packagename . ".pcf"; + my $checkfilename = $installer::globals::poolpath . $installer::globals::separator . $packagename . ".pcf.check"; + my $lockfilename = $installer::globals::poolpath . $installer::globals::separator . $packagename . ".pcf.lock"; + # Saving name in global variable, so that this file can be removed somewhere else (at the end of "put_content_into_pool"). + $installer::globals::poolcheckfilename = $checkfilename; + $installer::globals::poollockfilename = $lockfilename; + + my @checkfilecontent = ("$installer::globals::sessionid $installer::globals::product $$languagestringref $checkfilename"); # $$ is the process id + my @lockfilecontent = ("$installer::globals::sessionid $installer::globals::product $$languagestringref $lockfilename"); # $$ is the process id + + # Waiting, step 1 + # Checking, if another process checks this package at the moment + my $timecounter = 0; + while ( -f $checkfilename ) + { + $timecounter++; + + # including an exit to enable creation of other packages + if (( $timecounter == 1 ) && ( ! exists($installer::globals::poolshiftedpackages{$packagename}) )) + { + $package_is_up_to_date = 3; # repeat this package later + return $package_is_up_to_date; + } + + $infoline = "Pool: $checkfilename exists. WAITING 10 seconds ($timecounter).\n"; + if ( $timecounter == 1 ) { installer::logger::print_message( "\n" ); } + installer::logger::print_message( "... $infoline" ); + push( @installer::globals::logfileinfo, $infoline); + # if ( $timecounter % 50 == 0 ) { check_pool_exit($checkfilename, $timecounter); } + if ( $timecounter % 100 == 0 ) { check_pool_exit($checkfilename, $timecounter); } + sleep 10; # process sleeps 10 seconds + $waited_for_check = 1; + } + + # Creating file, showing that this package is checked at the moment by this process. No other process can reach this. + installer::files::save_file($checkfilename, \@checkfilecontent); # Creating the Lock, to check this package. This blocks all other processes. + $installer::globals::processhaspoolcheckfile = 1; + + # Check, if the Lock file creation was really successful + if ( ! -f $checkfilename ) + { + $infoline = "Pool problem: Pool lock file \"$checkfilename\" could not be created successfully or was removed by another process (A)!\n"; + push( @installer::globals::logfileinfo, $infoline); + log_pool_info(0); + $package_is_up_to_date = 4; # repeat this package + return $package_is_up_to_date; + } + + if ( ! process_is_owner($checkfilename) ) + { + $infoline = "Pool problem: Pool lock file \"$checkfilename\" belongs to another process (A)!\n"; + push( @installer::globals::logfileinfo, $infoline); + log_pool_info(1); + $package_is_up_to_date = 4; # repeat this package + return $package_is_up_to_date; + } + + $infoline = "Pool: Created file: $checkfilename\n"; + push( @installer::globals::logfileinfo, $infoline); + if ( $waited_for_check ) { installer::logger::print_message( "... $infoline" ); } + + # Waiting, step 2 + # Checking, if another process creates this package at the moment + $timecounter = 0; + while ( -f $lockfilename ) + { + $timecounter++; + $infoline = "Pool: $lockfilename exists. WAITING 10 seconds ($timecounter).\n"; + if ( $timecounter == 1 ) { installer::logger::print_message( "\n" ); } + installer::logger::print_message( "... $infoline" ); + push( @installer::globals::logfileinfo, $infoline); + # if ( $timecounter % 50 == 0 ) { check_pool_exit($lockfilename, $timecounter); } + if ( $timecounter % 100 == 0 ) { check_pool_exit($lockfilename, $timecounter); } + sleep 10; # process sleeps 10 seconds + $waited_for_lock = 1; + } + + # No lock file exists, therefore no process creates this package at the moment. Check can be done now. + if ( $waited_for_lock ) { installer::logger::print_message( "... Pool: Proceeding, $lockfilename was removed.\n" ); } + + my $package_already_exists = 0; + + if ( -f $filename ) + { + # Calculating content for pcf file + $installer::globals::newpcfcontent = calculate_current_content($filesinpackage, $packagename); + $installer::globals::newpcfcontentcalculated = 1; + + # reading the existing pcf file + ($realpackagename, $oldpcfcontent, $oldepmcontent) = read_pcf_content($filename); + + # First check: Package has to exist in pool (directories on Solaris) + my $fullpackage = $installer::globals::poolpath . $installer::globals::separator . $realpackagename; + if ( $installer::globals::issolarisbuild ) { $fullpackage = $fullpackage . ".tar"; } + if ( -f $fullpackage ) + { + $package_already_exists = 1; + # Second check: Only files + my $content_is_identical = compare_package_content($oldpcfcontent, $installer::globals::newpcfcontent); + + # Third check for Unix: Changes in the epm file? + if (( $content_is_identical ) && ( ! $installer::globals::iswindowsbuild )) + { + $content_is_identical = compare_epm_content($oldepmcontent, $newepmcontent); + } + + if ( $content_is_identical ) { $package_is_up_to_date = 1; } + } + } + + if ( $package_is_up_to_date ) + { + $infoline = "Pool: $packagename: No new content, using existing package\n"; + push( @installer::globals::logfileinfo, $infoline); + installer::logger::print_message( "... using package from pool\n" ); + } + else + { + if ( $package_already_exists ) + { + $infoline = "Pool: $packagename: Contains new content, creating new package. Differences:\n"; + push( @installer::globals::logfileinfo, $infoline); + foreach my $dest ( sort keys %installer::globals::pcfdifflist ) { push( @installer::globals::logfileinfo, "$dest\n"); } + foreach my $dest ( @installer::globals::pcfdiffcomment ) { push( @installer::globals::logfileinfo, "$dest"); } + foreach my $dest ( @installer::globals::epmdifflist ) { push( @installer::globals::logfileinfo, "$dest"); } + } + else + { + $infoline = "Pool: $packagename: Does not exist in pool.\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + installer::logger::print_message( "... packaging required\n" ); + %installer::globals::xpdpackageinfo = (); # reset the filled hash, because the package cannot be used. + + # Creating lock mechanism, so that other processes do not create this package, too. + installer::files::save_file($lockfilename, \@lockfilecontent); # Creating the Lock, to create this package (Lock for check still exists). + $installer::globals::processhaspoollockfile = 1; + + # Check if creation of Lock file was really successful + + if ( ! -f $lockfilename ) + { + $infoline = "Pool problem: Pool lock file \"$lockfilename\" could not be created successfully or was removed by another process (D)!\n"; + push( @installer::globals::logfileinfo, $infoline); + log_pool_info(0); + $package_is_up_to_date = 4; # repeat this package + return $package_is_up_to_date; + } + + if ( ! process_is_owner($lockfilename) ) + { + $infoline = "Pool problem: Pool lock file \"$lockfilename\" belongs to another process (D)!\n"; + push( @installer::globals::logfileinfo, $infoline); + log_pool_info(1); + $package_is_up_to_date = 4; # repeat this package + return $package_is_up_to_date; + } + + $infoline = "Pool: Created file: $lockfilename\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + my $newpackagepath = ""; + + if ( $package_is_up_to_date ) + { + # Before the package is copied into the installation set, it has to be checked, if this process is really the owner of this lock file.. + # Check, if lock file still exists and if this process is the owner. + + if ( ! -f $checkfilename ) + { + $infoline = "Pool problem: Pool lock file \"$checkfilename\" was removed by another process (B)!\n"; + push( @installer::globals::logfileinfo, $infoline); + log_pool_info(0); + $package_is_up_to_date = 4; # repeat this package + return $package_is_up_to_date; + } + + if ( ! process_is_owner($checkfilename) ) + { + $infoline = "Pool problem: Pool lock file \"$checkfilename\" belongs to another process (B)!\n"; + push( @installer::globals::logfileinfo, $infoline); + log_pool_info(1); + $package_is_up_to_date = 4; # repeat this package + return $package_is_up_to_date; + } + + # Copying the package from the pool into the installation set + $newpackagepath = copy_package_from_pool($installdir, $subdir, $realpackagename); + } + + # Before the lock file in the pool can be removed, it has to be checked, if this process is still the owner of this lock file. + # Check, if lock file still exists and if this process is the owner. + if ( ! -f $checkfilename ) + { + $infoline = "Pool problem: Pool lock file \"$checkfilename\" was removed by another process (C)!\n"; + push( @installer::globals::logfileinfo, $infoline); + log_pool_info(0); + + # removing new package from installation set + if ( $newpackagepath ne "" ) { remove_package_from_installset($newpackagepath); } # A file was copied and a problem occured with pooling + + $package_is_up_to_date = 4; # repeat this package + return $package_is_up_to_date; + } + + if ( ! process_is_owner($checkfilename) ) + { + $infoline = "Pool problem: Pool lock file \"$checkfilename\" belongs to another process (C)!\n"; + push( @installer::globals::logfileinfo, $infoline); + log_pool_info(1); + + # removing new package from installation set + if ( $newpackagepath ne "" ) { remove_package_from_installset($newpackagepath); } # A file was copied and a problem occured with pooling + + $package_is_up_to_date = 4; # repeat this package + return $package_is_up_to_date; + } + + # Removing the check file, releasing this package for the next process. + # The Lock to create this package still exists, if required. + unlink $checkfilename; + $installer::globals::processhaspoolcheckfile = 0; + $infoline = "Pool: Removing file: $checkfilename\n"; + push( @installer::globals::logfileinfo, $infoline); + + # Last chance before packaging starts, to check, if this process is really still owner + # of the packaging lock file. If not, this packaging process can be repeated. + if ( $installer::globals::processhaspoollockfile ) + { + if ( ! -f $lockfilename ) + { + $infoline = "Pool problem: Pool lock file \"$lockfilename\" was removed by another process (E)!\n"; + push( @installer::globals::logfileinfo, $infoline); + log_pool_info(0); + $package_is_up_to_date = 4; # repeat this package + return $package_is_up_to_date; + } + + if ( ! process_is_owner($lockfilename) ) + { + $infoline = "Pool problem: Pool lock file \"$lockfilename\" belongs to another process (E)!\n"; + push( @installer::globals::logfileinfo, $infoline); + log_pool_info(1); + $package_is_up_to_date = 4; # repeat this package + return $package_is_up_to_date; + } + } + + # Collecting log information + if ( $package_is_up_to_date == 1 ) { $installer::globals::poolpackages{$packagename} = 1; } + if ( $package_is_up_to_date == 0 ) + { + my @packreasons = (); + if ( $package_already_exists ) + { + $infoline = "\t\tPool: $packagename: Contains new content, creating new package. Differences:\n"; + push( @packreasons, $infoline); + foreach my $dest ( sort keys %installer::globals::pcfdifflist ) { push( @packreasons, "\t\t$dest\n"); } + foreach my $dest ( @installer::globals::pcfdiffcomment ) { push( @packreasons, "\t\t$dest"); } + foreach my $dest ( @installer::globals::epmdifflist ) { push( @packreasons, "\t\t$dest"); } + } + else + { + $infoline = "\t\tPool: $packagename: Does not exist in pool.\n"; + push( @packreasons, $infoline); + } + + $installer::globals::createpackages{$packagename} = \@packreasons; + } + + return $package_is_up_to_date; +} + +################################################### +# Determine, which package was created newly +################################################### + +sub determine_new_packagename +{ + my ( $dir ) = @_; + + my ($newcontent, $allcontent) = installer::systemactions::find_new_content_in_directory($dir, \@installer::globals::installsetcontent); + @installer::globals::installsetcontent = (); + foreach my $element ( @{$allcontent} ) { push(@installer::globals::installsetcontent, $element); } + + my $newentriesnumber = $#{$newcontent} + 1; + if ( $newentriesnumber > 1 ) + { + my $newpackages = ""; + foreach my $onepackage ( @{$newcontent} ) { $newpackages = $newpackages . " " . $onepackage; } + installer::exiter::exit_program("ERROR: More than one new package in directory $dir ($newpackages)", "determine_new_packagename (packagepool)"); + } + elsif ( $newentriesnumber < 1 ) + { + installer::exiter::exit_program("ERROR: No new package in directory $dir", "determine_new_packagename (packagepool)"); + } + my $newpackage = ${$newcontent}[0]; + + return $newpackage; +} + +#################################################### +# Including content into the package pool +#################################################### + +sub put_content_into_pool +{ + my ($packagename, $installdir, $subdir, $filesinpackage, $epmfilecontent) = @_; + + my $infoline = ""; + + my $fullinstalldir = $installdir . $installer::globals::separator . $subdir; + my $fullrealpackagename = determine_new_packagename($fullinstalldir); + my $realpackagename = $fullrealpackagename; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$realpackagename); + + installer::logger::include_header_into_logfile("Adding content into the package pool: $realpackagename (PackageName: $packagename)"); + + # Calculating content for pcf file, if not already done in "package_is_up_to_date" + if ( ! $installer::globals::newpcfcontentcalculated ) + { + $installer::globals::newpcfcontent = calculate_current_content($filesinpackage, $packagename); + $installer::globals::newpcfcontentcalculated = 1; + } + + # Determining md5sum and FileSize for the new package and saving in pcf file + my $md5sum = installer::xpdinstaller::get_md5_value($fullrealpackagename); + my $filesize = installer::xpdinstaller::get_size_value($fullrealpackagename); + my $fullpackagename = installer::xpdinstaller::get_fullpkgname_value($fullrealpackagename); + my $pkgversion = installer::xpdinstaller::get_pkgversion_value($fullrealpackagename); + + # Put package content file (pcf) into pool + my $pcffilename = $installer::globals::poolpath . $installer::globals::separator . $packagename . ".pcf"; + create_pcfcontent_file($realpackagename, $md5sum, $filesize, $fullpackagename, $pkgversion, $epmfilecontent, $pcffilename); + + # Creating xpd info + $installer::globals::xpdpackageinfo{'FileSize'} = $filesize; + $installer::globals::xpdpackageinfo{'FullPackageName'} = $fullpackagename; + $installer::globals::xpdpackageinfo{'md5sum'} = $md5sum; + $installer::globals::xpdpackageinfo{'RealPackageName'} = $realpackagename; + $installer::globals::xpdpackageinfo{'PkgVersion'} = $pkgversion; + + # Put package into pool + $infoline = "Pool: Adding package \"$packagename\" into pool.\n"; + push( @installer::globals::logfileinfo, $infoline); + + # Copying with unique name, containing PID. Only renaming if everything was fine. + my $realdestination = ""; + my $uniquedestination = ""; + if ( -f $fullrealpackagename ) + { + $realdestination = $installer::globals::poolpath . $installer::globals::separator . $realpackagename; + $uniquedestination = $realdestination . "." . $installer::globals::sessionid; + installer::systemactions::copy_one_file($fullrealpackagename, $uniquedestination); + } + + # Copying Solaris packages (as tar files) + if ( -d $fullrealpackagename ) + { + my $tarfilename = $packagename . ".tar"; + my $fulltarfilename = $fullinstalldir . $installer::globals::separator . $tarfilename; + my $size = installer::worker::tar_package($fullinstalldir, $packagename, $tarfilename, $installer::globals::getuidpath); + if (( ! -f $fulltarfilename ) || ( ! ( $size > 0 ))) { installer::exiter::exit_program("ERROR: Missing file: $fulltarfilename", "put_content_into_pool"); } + $realdestination = $installer::globals::poolpath . $installer::globals::separator . $tarfilename; + $uniquedestination = $realdestination . "." . $installer::globals::sessionid; + installer::systemactions::copy_one_file($fulltarfilename, $uniquedestination); + unlink $fulltarfilename; + } + + # Before the new package is renamed in the pool, it has to be checked, if this process still has the lock for this package. + # Check, if lock file still exists and if this process is the owner. Otherwise a pool error occured. + if ( ! -f $installer::globals::poollockfilename ) + { + unlink $uniquedestination; # removing file from pool + log_pool_info(0); + installer::exiter::exit_program("ERROR: Pool lock file \"$installer::globals::poollockfilename\" was removed by another process (F)!", "put_content_into_pool"); + } + + if ( ! process_is_owner($installer::globals::poollockfilename) ) + { + unlink $uniquedestination; # removing file from pool + log_pool_info(1); + installer::exiter::exit_program("ERROR: Pool lock file \"$installer::globals::poollockfilename\" belongs to another process (F)!", "put_content_into_pool"); + } + + # Renaming the file in the pool (atomic step) + rename($uniquedestination, $realdestination); + + $infoline = "Pool: Renamed file: \"$uniquedestination\" to \"$realdestination\".\n"; + push( @installer::globals::logfileinfo, $infoline); + + # Before the lock file in the pool can be removed, it has to be checked, if this process is still the owner of this lock file. + # Check, if lock file still exists and if this process is the owner. Otherwise a pool error occured. + if ( ! -f $installer::globals::poollockfilename ) + { + log_pool_info(0); + installer::exiter::exit_program("ERROR: Pool lock file \"$installer::globals::poollockfilename\" was removed by another process (G)!", "put_content_into_pool"); + } + + if ( ! process_is_owner($installer::globals::poollockfilename) ) + { + log_pool_info(1); + installer::exiter::exit_program("ERROR: Pool lock file \"$installer::globals::poollockfilename\" belongs to another process (G)!", "put_content_into_pool"); + } + + # Removing lock file, so that other processes can use this package now + unlink $installer::globals::poollockfilename; + $installer::globals::processhaspoollockfile = 0; + $infoline = "Pool: Removing file: $installer::globals::poollockfilename\n"; + push( @installer::globals::logfileinfo, $infoline); +} + +################################################################### +# Copying a package from the pool into the installation set +################################################################### + +sub copy_package_from_pool +{ + my ($installdir, $subdir, $packagename) = @_; + + my $infoline = "Pool: Using package \"$packagename\" from pool.\n"; + push( @installer::globals::logfileinfo, $infoline); + my $sourcefile = $installer::globals::poolpath . $installer::globals::separator . $packagename; + if ( $installer::globals::issolarisbuild ) { $sourcefile = $sourcefile . ".tar"; } + if ( ! -f $sourcefile ) { installer::exiter::exit_program("ERROR: Missing package in package pool: \"$sourcefile\"", "copy_package_from_pool"); } + my $destination = $installdir . $installer::globals::separator . $subdir; + if ( ! -d $destination ) { installer::systemactions::create_directory($destination); } + my $destinationfile = $destination . $installer::globals::separator . $packagename; + if ( $installer::globals::issolarisbuild ) { $destinationfile = $destinationfile . ".tar"; } + if ( -f $sourcefile ) { installer::systemactions::copy_one_file($sourcefile, $destinationfile); } + # Unpacking for Solaris + if ( $installer::globals::issolarisbuild ) + { + my $tarfilename = $packagename . ".tar"; + installer::worker::untar_package($destination, $tarfilename, $installer::globals::getuidpath); + unlink $destinationfile; + $destinationfile =~ s/.tar\s*$//; + } + + # Keeping the content of @installer::globals::installsetcontent up to date (with full pathes): + push(@installer::globals::installsetcontent, $destinationfile); + + return $destinationfile; +} + +################################################################### +# Counting keys in hash +################################################################### + +sub get_count +{ + my ( $hashref ) = @_; + + my $counter = 0; + foreach my $onekey ( keys %{$hashref} ) { $counter++; } + return $counter; +} + +################################################################### +# Logging some pool information +################################################################### + +sub log_pool_statistics +{ + my $infoline = ""; + + installer::logger::include_header_into_logfile("Pool statistics:"); + + # Info collected in global hashes + # %installer::globals::createpackages + # %installer::globals::poolpackages + + my $pool_packages = get_count(\%installer::globals::poolpackages); + my $created_packages = get_count(\%installer::globals::createpackages); + + $infoline = "Number of packages from pool: $pool_packages\n"; + push( @installer::globals::logfileinfo, $infoline); + + foreach my $packagename ( sort keys(%installer::globals::poolpackages) ) + { + $infoline = "\t$packagename\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + $infoline = "\nNumber of packages that were created: $created_packages\n"; + push( @installer::globals::logfileinfo, $infoline); + + foreach my $packagename ( sort keys(%installer::globals::createpackages) ) + { + $infoline = "\t$packagename\n"; + push( @installer::globals::logfileinfo, $infoline); + my $reason = $installer::globals::createpackages{$packagename}; + + for ( my $i = 0; $i <= $#{$reason}; $i++ ) + { + $infoline = "${$reason}[$i]"; + push( @installer::globals::logfileinfo, $infoline); + } + } +} + +1; diff --git a/solenv/bin/modules/installer/parameter.pm b/solenv/bin/modules/installer/parameter.pm new file mode 100644 index 000000000000..9bece8a3d069 --- /dev/null +++ b/solenv/bin/modules/installer/parameter.pm @@ -0,0 +1,657 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: parameter.pm,v $ +# +# $Revision: 1.56 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::parameter; + +use Cwd; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::logger; +use installer::remover; +use installer::systemactions; + +############################################ +# Parameter Operations +############################################ + +sub usage +{ + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::parameter::usage"); } + + print <<Ende; +-------------------------------------------------------------------------------- +$installer::globals::prog V1.0 (c) Ingo Schmidt 2003 +The following parameter are needed: +-f: Path to the product list (required) +-s: Path to the setup script (optional, if defined in product list) +-i: Install path of the product (/opt/openofficeorg20) (optional) +-p: Product from product list to be created (required) +-l: Language of the product (comma and hash) (optional, defined in productlist) +-b: Build, e.g. srx645 (optional) +-m: Minor, e.g. m10 (optional) +-simple: Path to do a simple install to +-c: Compiler, e.g. wntmsci8, unxlngi5, unxsols4, ... (optional) +-u: Path, in which zipfiles are unpacked (optional) +-msitemplate: Source of the msi file templates (Windows compiler only) +-msilanguage: Source of the msi file templates (Windows compiler only) +-javalanguage: Source of the Java language files (opt., non-Windows only) +-buildid: Current BuildID (optional) +-pro: Product version +-format: Package format +-debian: Create Debian packages for Linux +-dontunzip: do not unzip all files with flag ARCHIVE +-dontcallepm : do not call epm to create install sets (opt., non-Windows only) +-ispatchedepm : Usage of a patched (non-standard) epm (opt., non-Windows only) +-copyproject : is set for projects that are only used for copying (optional) +-languagepack : do create a languagepack, no product pack (optional) +-patch : do create a patch (optional) +-patchinc: Source for the patch include files (Solaris only) +-dontstrip: No file stripping (Unix only) +-log : Logging all available information (optional) +-debug : Collecting debug information + +Examples for Windows: + +perl make_epmlist.pl -f zip.lst -p OfficeFAT -l en-US + -u /export/unpack -buildid 8712 + -msitemplate /export/msi_files + -msilanguage /export/msi_languages + +Examples for Non-Windows: + +perl make_epmlist.pl -f zip.lst -p OfficeFAT -l en-US -format rpm + -u /export/unpack -buildid 8712 -ispatchedepm +-------------------------------------------------------------------------------- +Ende + exit(-1); +} + +######################################### +# Writing all parameter into logfile +######################################### + +sub saveparameter +{ + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::parameter::saveparameter"); } + + my $include = ""; + + installer::logger::globallog("Command line arguments:"); + + for ( my $i = 0; $i <= $#ARGV; $i++ ) + { + $include = $ARGV[$i] . "\n"; + push(@installer::globals::globallogfileinfo, $include); + } + + # also saving global settings: + + $include = "Separator: $installer::globals::separator\n"; + push(@installer::globals::globallogfileinfo, $include); + +} + +##################################### +# Reading parameter +##################################### + +sub getparameter +{ + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::parameter::getparameter"); } + + while ( $#ARGV >= 0 ) + { + my $param = shift(@ARGV); + + if ($param eq "-f") { $installer::globals::ziplistname = shift(@ARGV); } + elsif ($param eq "-s") { $installer::globals::setupscriptname = shift(@ARGV); } + elsif ($param eq "-p") { $installer::globals::product = shift(@ARGV); } + elsif ($param eq "-l") { $installer::globals::languagelist = shift(@ARGV); } + elsif ($param eq "-b") { $installer::globals::build = shift(@ARGV); } + elsif ($param eq "-m") { $installer::globals::minor = shift(@ARGV); } + elsif ($param eq "-dontunzip") { $installer::globals::dounzip = 0; } + elsif ($param eq "-c") { $installer::globals::compiler = shift(@ARGV); } + elsif ($param eq "-pro") { $installer::globals::pro = 1; } + elsif ($param eq "-format") { $installer::globals::packageformat = shift(@ARGV); } + elsif ($param eq "-log") { $installer::globals::globallogging = 1; } + elsif ($param eq "-quiet") { $installer::globals::quiet = 1; } + elsif ($param eq "-verbose") { $installer::globals::quiet = 0; } + elsif ($param eq "-debug") { $installer::globals::debug = 1; } + elsif ($param eq "-tab") { $installer::globals::tab = 1; } + elsif ($param eq "-u") { $installer::globals::unpackpath = shift(@ARGV); } + elsif ($param eq "-i") { $installer::globals::rootpath = shift(@ARGV); } + elsif ($param eq "-dontcallepm") { $installer::globals::call_epm = 0; } + elsif ($param eq "-msitemplate") { $installer::globals::idttemplatepath = shift(@ARGV); } + elsif ($param eq "-msilanguage") { $installer::globals::idtlanguagepath = shift(@ARGV); } + elsif ($param eq "-patchinc") { $installer::globals::patchincludepath = shift(@ARGV); } + elsif ($param eq "-javalanguage") { $installer::globals::javalanguagepath = shift(@ARGV); } + elsif ($param eq "-buildid") { $installer::globals::buildid = shift(@ARGV); } + elsif ($param eq "-copyproject") { $installer::globals::is_copy_only_project = 1; } + elsif ($param eq "-languagepack") { $installer::globals::languagepack = 1; } + elsif ($param eq "-patch") { $installer::globals::patch = 1; } + elsif ($param eq "-debian") { $installer::globals::debian = 1; } + elsif ($param eq "-dontstrip") { $installer::globals::strip = 0; } + elsif ($param eq "-destdir") # new parameter for simple installer + { + $installer::globals::rootpath ne "" && die "must set destdir before -i or -simple"; + $installer::globals::destdir = shift @ARGV; + } + elsif ($param eq "-simple") # new parameter for simple installer + { + $installer::globals::simple = 1; + $installer::globals::call_epm = 0; + $installer::globals::makedownload = 0; + $installer::globals::makejds = 0; + $installer::globals::strip = 0; + my $path = shift(@ARGV); + $path =~ s/^\Q$installer::globals::destdir\E//; + $installer::globals::rootpath = $path; + } + else + { + installer::logger::print_error( "unknown parameter: $param" ); + usage(); + exit(-1); + } + } + + # Usage of simple installer (not for Windows): + # $PERL -w $SOLARENV/bin/make_installer.pl \ + # -f openoffice.lst -l en-US -p OpenOffice \ + # -buildid $BUILD -rpm \ + # -destdir /tmp/nurk -simple $INSTALL_PATH +} + +############################################ +# Controlling the fundamental parameter +# (required for every process) +############################################ + +sub control_fundamental_parameter +{ + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::parameter::control_fundamental_parameter"); } + + if ($installer::globals::product eq "") + { + installer::logger::print_error( "Product name not set!" ); + usage(); + exit(-1); + } +} + +########################################################## +# The path parameters can be relative or absolute. +# This function creates absolute pathes. +########################################################## + +sub make_path_absolute +{ + my ($pathref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::parameter::make_path_absolute : $$pathref"); } + + if ( $installer::globals::isunix ) + { + if (!($$pathref =~ /^\s*\//)) # this is a relative unix path + { + $$pathref = cwd() . $installer::globals::separator . $$pathref; + } + } + + if ( $installer::globals::iswin ) + { + if ( $^O =~ /cygwin/i ) + { + if ( $$pathref !~ /^\s*\// && $$pathref !~ /^\s*\w\:/ ) # not an absolute POSIX or DOS path + { + $$pathref = cwd() . $installer::globals::separator . $$pathref; + } + my $p = $$pathref; + chomp( $p ); + my $q = ''; + # Avoid the $(LANG) problem. + if ($p =~ /(\A.*)(\$\(.*\Z)/) { + $p = $1; + $q = $2; + } + $p =~ s/\\/\\\\/g; + chomp( $p = qx{cygpath -w "$p"} ); + $$pathref = $p.$q; + # Use windows paths, but with '/'s. + $$pathref =~ s/\\/\//g; + } + else + { + if (!($$pathref =~ /^\s*\w\:/)) # this is a relative windows path (no dos drive) + { + $$pathref = cwd() . $installer::globals::separator . $$pathref; + + $$pathref =~ s/\//\\/g; + } + } + } + $$pathref =~ s/[\/\\]\s*$//; # removing ending slashes +} + +################################################## +# Setting some global parameters +# This has to be expanded with furher platforms +################################################## + +sub setglobalvariables +{ + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::parameter::setglobalvariables"); } + + # Setting the installertype directory corresponding to the environment variable PKGFORMAT + # The global variable $installer::globals::packageformat can only contain one package format. + # If PKGFORMAT cotains more than one format (for example "rpm deb") this is splitted in the + # makefile calling the perl program. + $installer::globals::installertypedir = $installer::globals::packageformat; + + if ( $installer::globals::compiler =~ /wnt(msc|gcc)i/ ) + { + $installer::globals::iswindowsbuild = 1; + if ( $installer::globals::installertypedir eq "" ) { $installer::globals::installertypedir = "msi"; } + } + + if ( $installer::globals::compiler =~ /unxso[lg][siux]/ ) + { + $installer::globals::issolarisbuild = 1; + if ( $installer::globals::packageformat eq "pkg" ) + { + $installer::globals::issolarispkgbuild = 1; + $installer::globals::epmoutpath = "packages"; + $installer::globals::isxpdplatform = 1; + } + } + if ( $installer::globals::compiler =~ /unxfbsd/ ) + { + if ( $installer::globals::packageformat eq "bsd" ) + { + $installer::globals::isfreebsdpkgbuild = 1; + } + } + + if ( $installer::globals::compiler =~ /unxso[lg]s/ ) { $installer::globals::issolarissparcbuild = 1; } + + if ( $installer::globals::compiler =~ /unxso[lg]i/ ) { $installer::globals::issolarisx86build = 1; } + + if ($ENV{OS} eq 'LINUX') + { + $installer::globals::islinuxbuild = 1; + if ( $installer::globals::packageformat eq "rpm" ) + { + $installer::globals::islinuxrpmbuild = 1; + $installer::globals::isxpdplatform = 1; + $installer::globals::epmoutpath = "RPMS"; + if ( $installer::globals::compiler =~ /unxlngi/ ) + { + $installer::globals::islinuxintelrpmbuild = 1; + } + if ( $installer::globals::compiler =~ /unxlngppc/ ) + { + $installer::globals::islinuxppcrpmbuild = 1; + } + if ( $installer::globals::compiler =~ /unxlngx/ ) + { + $installer::globals::islinuxx86_64rpmbuild = 1; + } + + if ( $installer::globals::rpm eq "" ) { installer::exiter::exit_program("ERROR: Environment variable \"\$RPM\" has to be defined!", "setglobalvariables"); } + } + + # Creating Debian packages ? + if (( $installer::globals::packageformat eq "deb" ) || ( $installer::globals::debian )) + { + $installer::globals::debian = 1; + $installer::globals::packageformat = "deb"; + my $message = "Creating Debian packages"; + installer::logger::print_message( $message ); + push(@installer::globals::globallogfileinfo, $message); + $installer::globals::islinuxrpmbuild = 0; + $installer::globals::islinuxdebbuild = 1; + $installer::globals::epmoutpath = "DEBS"; + if ( $installer::globals::compiler =~ /unxlngi/ ) + { + $installer::globals::islinuxinteldebbuild = 1; + } + if ( $installer::globals::compiler =~ /unxlngppc/ ) + { + $installer::globals::islinuxppcdebbuild = 1; + } + if ( $installer::globals::compiler =~ /unxlngx/ ) + { + $installer::globals::islinuxx86_64debbuild = 1; + } + } + } + + # Defaulting to native package format for epm + + if ( ! $installer::globals::packageformat ) { $installer::globals::packageformat = "native"; } + + # $installer::globals::servicesrdb_can_be_created can only be set, if regcomp (regcomp.exe) can be executed. + + if ( $installer::globals::iswin && $installer::globals::iswindowsbuild ) { $installer::globals::servicesrdb_can_be_created = 1; } + if ( $installer::globals::islinux && $installer::globals::islinuxbuild ) { $installer::globals::servicesrdb_can_be_created = 1; } + if ( $installer::globals::issolaris && $installer::globals::issolarisbuild ) { $installer::globals::servicesrdb_can_be_created = 1; } + + # ToDo: Needs to be expanded for additional compiler (setting $installer::globals::servicesrdb_can_be_created = 1 for all external platforms) + + if ((!($installer::globals::iswindowsbuild)) && (!($installer::globals::islinuxbuild)) && (!($installer::globals::issolarisbuild))) + { + $installer::globals::servicesrdb_can_be_created = 1; + } + + # extension, if $installer::globals::pro is set + if ($installer::globals::pro) { $installer::globals::productextension = ".pro"; } + + # no languages defined as parameter + if ($installer::globals::languagelist eq "") { $installer::globals::languages_defined_in_productlist = 1; } + + # setting and creating the unpackpath + + if ($installer::globals::unpackpath eq "") # unpackpath not set + { + $installer::globals::unpackpath = cwd(); + if ( $installer::globals::iswin ) { $installer::globals::unpackpath =~ s/\//\\/g; } + } + + if ( $installer::globals::localunpackdir ne "" ) { $installer::globals::unpackpath = $installer::globals::localunpackdir; } + + if (!($installer::globals::unpackpath eq "")) + { + make_path_absolute(\$installer::globals::unpackpath); + } + + $installer::globals::unpackpath =~ s/\Q$installer::globals::separator\E\s*$//; + + if (! -d $installer::globals::unpackpath ) # create unpackpath + { + installer::systemactions::create_directory($installer::globals::unpackpath); + } + + # setting jds exclude file list + + if ( $installer::globals::islinuxrpmbuild ) + { + $installer::globals::jdsexcludefilename = "jds_excludefiles_linux.txt"; + } + if ( $installer::globals::issolarissparcbuild ) + { + $installer::globals::jdsexcludefilename = "jds_excludefiles_solaris_sparc.txt"; + } + if ( $installer::globals::issolarisx86build ) + { + $installer::globals::jdsexcludefilename = "jds_excludefiles_solaris_intel.txt"; + } + + # setting and creating the temppath + + if (( $ENV{'TMP'} ) || ( $ENV{'TEMP'} ) || ( $ENV{'TMPDIR'} )) + { + if ( $ENV{'TMP'} ) { $installer::globals::temppath = $ENV{'TMP'}; } + elsif ( $ENV{'TEMP'} ) { $installer::globals::temppath = $ENV{'TEMP'}; } + elsif ( $ENV{'TMPDIR'} ) { $installer::globals::temppath = $ENV{'TMPDIR'}; } + $installer::globals::temppath =~ s/\Q$installer::globals::separator\E\s*$//; # removing ending slashes and backslashes + $installer::globals::temppath = $installer::globals::temppath . $installer::globals::separator . $installer::globals::globaltempdirname; + installer::systemactions::create_directory_with_privileges($installer::globals::temppath, "777"); + my $dirsave = $installer::globals::temppath; + + if ( $installer::globals::compiler =~ /^unxmac/ ) + { + my $localcall = "chmod 777 $installer::globals::temppath \>\/dev\/null 2\>\&1"; + system($localcall); + } + + $installer::globals::temppath = $installer::globals::temppath . $installer::globals::separator . "i"; + $installer::globals::temppath = installer::systemactions::create_pid_directory($installer::globals::temppath); + push(@installer::globals::removedirs, $installer::globals::temppath); + + if ( ! -d $installer::globals::temppath ) { installer::exiter::exit_program("ERROR: Failed to create directory $installer::globals::temppath ! Possible reason: Wrong privileges in directory $dirsave .", "setglobalvariables"); } + + $installer::globals::jdstemppath = $installer::globals::temppath; + $installer::globals::jdstemppath =~ s/i_/j_/; + push(@installer::globals::jdsremovedirs, $installer::globals::jdstemppath); + $installer::globals::temppath = $installer::globals::temppath . $installer::globals::separator . $installer::globals::compiler . $installer::globals::productextension; + installer::systemactions::create_directory($installer::globals::temppath); + if ( $^O =~ /cygwin/i ) + { + $installer::globals::cyg_temppath = $installer::globals::temppath; + $installer::globals::cyg_temppath =~ s/\\/\\\\/g; + chomp( $installer::globals::cyg_temppath = qx{cygpath -w "$installer::globals::cyg_temppath"} ); + } + $installer::globals::temppathdefined = 1; + $installer::globals::jdstemppathdefined = 1; + } + else + { + $installer::globals::temppathdefined = 0; + $installer::globals::jdstemppathdefined = 0; + } + + # only one cab file, if Windows msp patches shall be prepared + if ( $installer::globals::prepare_winpatch ) { $installer::globals::number_of_cabfiles = 1; } + +} + +############################################ +# Controlling the parameter that are +# required for special processes +############################################ + +sub control_required_parameter +{ + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::parameter::control_required_parameter"); } + + if (!($installer::globals::is_copy_only_project)) + { + ############################################################################################## + # idt template path. Only required for Windows build ($installer::globals::compiler =~ /wntmsci/) + # for the creation of the msi database. + ############################################################################################## + + if (($installer::globals::idttemplatepath eq "") && ($installer::globals::iswindowsbuild)) + { + installer::logger::print_error( "idt template path not set (-msitemplate)!" ); + usage(); + exit(-1); + } + + ############################################################################################## + # idt language path. Only required for Windows build ($installer::globals::compiler =~ /wntmsci/) + # for the creation of the msi database. + ############################################################################################## + + if (($installer::globals::idtlanguagepath eq "") && ($installer::globals::iswindowsbuild)) + { + installer::logger::print_error( "idt language path not set (-msilanguage)!" ); + usage(); + exit(-1); + } + + # Analyzing the idt template path + + if (!($installer::globals::idttemplatepath eq "")) # idttemplatepath set, relative or absolute? + { + make_path_absolute(\$installer::globals::idttemplatepath); + } + + installer::remover::remove_ending_pathseparator(\$installer::globals::idttemplatepath); + + # Analyzing the idt language path + + if (!($installer::globals::idtlanguagepath eq "")) # idtlanguagepath set, relative or absolute? + { + make_path_absolute(\$installer::globals::idtlanguagepath); + } + + installer::remover::remove_ending_pathseparator(\$installer::globals::idtlanguagepath); + + # In the msi template directory a files "codes.txt" has to exist, in which the ProductCode + # and the UpgradeCode for the product are defined. + # The name "codes.txt" can be overwritten in Product definition with CODEFILENAME (msiglobal.pm) + + if ($installer::globals::iswindowsbuild) + { + $installer::globals::codefilename = $installer::globals::idttemplatepath . $installer::globals::separator . $installer::globals::codefilename; + installer::files::check_file($installer::globals::codefilename); + $installer::globals::componentfilename = $installer::globals::idttemplatepath . $installer::globals::separator . $installer::globals::componentfilename; + installer::files::check_file($installer::globals::componentfilename); + } + + } + + ####################################### + # Patch currently only available + # for Solaris packages and Linux + ####################################### + + if (( $installer::globals::patch ) && ( ! $installer::globals::issolarispkgbuild ) && ( ! $installer::globals::islinuxrpmbuild ) && ( ! $installer::globals::islinuxdebbuild ) && ( ! $installer::globals::iswindowsbuild )) + { + installer::logger::print_error( "Sorry, Patch flag currently only available for Solaris pkg, Linux RPM and Windows builds!" ); + usage(); + exit(-1); + } + + if (( $installer::globals::patch ) && ( $installer::globals::issolarispkgbuild ) && ( ! $installer::globals::patchincludepath )) + { + installer::logger::print_error( "Solaris patch requires parameter -patchinc !" ); + usage(); + exit(-1); + } + + if (( $installer::globals::patch ) && ( $installer::globals::issolarispkgbuild ) && ( $installer::globals::patchincludepath )) + { + make_path_absolute(\$installer::globals::patchincludepath); + $installer::globals::patchincludepath = installer::converter::make_path_conform($installer::globals::patchincludepath); + } + + ####################################### + # Testing existence of files + # also for copy-only projects + ####################################### + + if ($installer::globals::ziplistname eq "") + { + installer::logger::print_error( "ERROR: Zip list file has to be defined (Parameter -f) !" ); + usage(); + exit(-1); + } + else + { + installer::files::check_file($installer::globals::ziplistname); + } + + if ($installer::globals::setupscriptname eq "") { $installer::globals::setupscript_defined_in_productlist = 1; } + else { installer::files::check_file($installer::globals::setupscriptname); } # if the setupscript file is defined, it has to exist + +} + +################################################ +# Writing parameter to shell and into logfile +################################################ + +sub outputparameter +{ + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::parameter::outputparameter"); } + + my $element; + + my @output = (); + + push(@output, "\n########################################################\n"); + push(@output, "$installer::globals::prog, version 1.0\n"); + push(@output, "Product list file: $installer::globals::ziplistname\n"); + if (!($installer::globals::setupscript_defined_in_productlist)) + { + push(@output, "Setup script: $installer::globals::setupscriptname\n"); + } + else + { + push(@output, "Taking setup script from solver\n"); + } + push(@output, "Unpackpath: $installer::globals::unpackpath\n"); + push(@output, "Compiler: $installer::globals::compiler\n"); + push(@output, "Product: $installer::globals::product\n"); + push(@output, "BuildID: $installer::globals::buildid\n"); + push(@output, "Build: $installer::globals::build\n"); + if ( $installer::globals::minor ) { push(@output, "Minor: $installer::globals::minor\n"); } + else { push(@output, "No minor set\n"); } + if ( $installer::globals::pro ) { push(@output, "Product version\n"); } + else { push(@output, "Non-Product version\n"); } + if ( $installer::globals::rootpath eq "" ) { push(@output, "Using default installpath\n"); } + else { push(@output, "Installpath: $installer::globals::rootpath\n"); } + push(@output, "Package format: $installer::globals::packageformat\n"); + if (!($installer::globals::idttemplatepath eq "")) { push(@output, "msi templatepath: $installer::globals::idttemplatepath\n"); } + if ((!($installer::globals::idttemplatepath eq "")) && (!($installer::globals::iswindowsbuild))) { push(@output, "msi template path will be ignored for non Windows builds!\n"); } + if (!($installer::globals::idtlanguagepath eq "")) { push(@output, "msi languagepath: $installer::globals::idtlanguagepath\n"); } + if ((!($installer::globals::idtlanguagepath eq "")) && (!($installer::globals::iswindowsbuild))) { push(@output, "msi language path will be ignored for non Windows builds!\n"); } + if ((!($installer::globals::iswindowsbuild)) && ( $installer::globals::call_epm )) { push(@output, "Calling epm\n"); } + if ((!($installer::globals::iswindowsbuild)) && (!($installer::globals::call_epm))) { push(@output, "Not calling epm\n"); } + if (!($installer::globals::javalanguagepath eq "")) { push(@output, "Java language path: $installer::globals::javalanguagepath\n"); } + if ((!($installer::globals::javalanguagepath eq "")) && ($installer::globals::iswindowsbuild)) { push(@output, "Java language path will be ignored for Windows builds!\n"); } + if ( $installer::globals::patchincludepath ) { push(@output, "Patch include path: $installer::globals::patchincludepath\n"); } + if ( $installer::globals::globallogging ) { push(@output, "Complete logging activated\n"); } + if ( $installer::globals::debug ) { push(@output, "Debug is activated\n"); } + if ( $installer::globals::tab ) { push(@output, "TAB version\n"); } + if ( $installer::globals::strip ) { push(@output, "Stripping files\n"); } + else { push(@output, "No file stripping\n"); } + if ( $installer::globals::debian ) { push(@output, "Linux: Creating Debian packages\n"); } + if ( $installer::globals::dounzip ) { push(@output, "Unzip ARCHIVE files\n"); } + else { push(@output, "Not unzipping ARCHIVE files\n"); } + if ( $installer::globals::servicesrdb_can_be_created ) { push(@output, "services.rdb can be created\n"); } + else { push(@output, "services.rdb cannot be created !\n"); } + if (!($installer::globals::languages_defined_in_productlist)) + { + push(@output, "Languages:\n"); + foreach $element (@installer::globals::languageproducts) { push(@output, "\t$element\n"); } + } + else + { + push(@output, "Languages defined in $installer::globals::ziplistname\n"); + } + if ( $installer::globals::is_copy_only_project ) { push(@output, "This is a copy only project!\n"); } + if ( $installer::globals::languagepack ) { push(@output, "Creating language pack!\n"); } + if ( $installer::globals::patch ) { push(@output, "Creating patch!\n"); } + push(@output, "########################################################\n"); + + # output into shell and into logfile + + for ( my $i = 0; $i <= $#output; $i++ ) + { + installer::logger::print_message( $output[$i] ); + push(@installer::globals::globallogfileinfo, $output[$i]); + } +} + +1; diff --git a/solenv/bin/modules/installer/pathanalyzer.pm b/solenv/bin/modules/installer/pathanalyzer.pm new file mode 100644 index 000000000000..3aa6ece5f691 --- /dev/null +++ b/solenv/bin/modules/installer/pathanalyzer.pm @@ -0,0 +1,79 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: pathanalyzer.pm,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::pathanalyzer; + +use installer::globals; + +########################################### +# Path analyzer +########################################### + +sub get_path_from_fullqualifiedname +{ + my ($longfilenameref) = @_; + + if ( $$longfilenameref =~ /\Q$installer::globals::separator\E/ ) # Is there a separator in the path? Otherwise the path is empty. + { + if ( $$longfilenameref =~ /^\s*(\S.*\S\Q$installer::globals::separator\E)(\S.+\S?)/ ) + { + $$longfilenameref = $1; + } + } + else + { + $$longfilenameref = ""; # there is no path + } +} + +sub make_absolute_filename_to_relative_filename +{ + my ($longfilenameref) = @_; + + if ( $installer::globals::isunix ) + { + if ( $$longfilenameref =~ /^.*\/(\S.+\S?)/ ) + { + $$longfilenameref = $1; + } + } + + if ( $installer::globals::iswin ) + { + # Either '/' or '\'. It would be possible to use $installer::globals::separator. + if ( $$longfilenameref =~ /^.*[\/\\](\S.+\S?)/ ) + { + $$longfilenameref = $1; + } + } +} + +1; diff --git a/solenv/bin/modules/installer/profiles.pm b/solenv/bin/modules/installer/profiles.pm new file mode 100644 index 000000000000..5bea2b9f9b27 --- /dev/null +++ b/solenv/bin/modules/installer/profiles.pm @@ -0,0 +1,235 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: profiles.pm,v $ +# +# $Revision: 1.9 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::profiles; + +use installer::converter; +use installer::existence; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::logger; +use installer::remover; +use installer::systemactions; + +############################# +# Profiles +############################# + +####################################################### +# Sorting the content of a profile +####################################################### + +sub sorting_profile +{ + my ($profilesref) = @_; + + my @profile = (); + my @definedsections = (); + + for ( my $i = 0; $i <= $#{$profilesref}; $i++ ) + { + my $line = ${$profilesref}[$i]; + + if ( $line =~ /^\s*(\[.*\])\s*$/ ) # this is a section (every second line) + { + my $section = $1; + + if (!(installer::existence::exists_in_array($section, \@definedsections))) + { + my $sectionline = $section . "\n"; + push(@definedsections, $section); + push(@profile, $sectionline); + + for ( my $j = 0; $j <= $#{$profilesref}; $j++ ) + { + my $oneline = ${$profilesref}[$j]; + installer::remover::remove_leading_and_ending_whitespaces(\$oneline); + + if ( $oneline eq $section ) + { + my $nextline = ${$profilesref}[$j+1]; + push(@profile, $nextline); + } + } + } + } + } + + return \@profile; +} + +##################################################################### +# Adding the newly created profile into the file list +##################################################################### + +sub add_profile_into_filelist +{ + my ($filesarrayref, $oneprofile, $completeprofilename, $allvariables) = @_; + + my %profile = (); + + # Taking the base data from the "gid_File_Lib_Vcl" + + my $vclgid = "gid_File_Lib_Vcl"; + if ( $allvariables->{'GLOBALFILEGID'} ) { $vclgid = $allvariables->{'GLOBALFILEGID'}; } + my $vclfile = installer::existence::get_specified_file($filesarrayref, $vclgid); + + # copying all base data + installer::converter::copy_item_object($vclfile, \%profile); + + # and overriding all new values + + $profile{'ismultilingual'} = 0; + $profile{'sourcepath'} = $completeprofilename; + $profile{'Name'} = $oneprofile->{'Name'}; + $profile{'UnixRights'} = "444"; + $profile{'gid'} = $oneprofile->{'gid'}; + $profile{'Dir'} = $oneprofile->{'Dir'}; + $profile{'destination'} = $oneprofile->{'destination'}; + $profile{'Styles'} = ""; + if ( $oneprofile->{'Styles'} ) { $profile{'Styles'} = $oneprofile->{'Styles'}; } + $profile{'modules'} = $oneprofile->{'ModuleID'}; # Profiles can only be added completely to a module + + push(@{$filesarrayref}, \%profile); +} + +################################################### +# Including Windows line ends in ini files +# Profiles on Windows shall have \r\n line ends +################################################### + +sub include_windows_lineends +{ + my ($onefile) = @_; + + for ( my $i = 0; $i <= $#{$onefile}; $i++ ) + { + ${$onefile}[$i] =~ s/\r?\n$/\r\n/; + } +} + +#################################### +# Create profiles +#################################### + +sub create_profiles +{ + my ($profilesref, $profileitemsref, $filesarrayref, $languagestringref, $allvariables) = @_; + + my $infoline; + + my $profilesdir = installer::systemactions::create_directories("profiles", $languagestringref); + + installer::logger::include_header_into_logfile("Creating profiles:"); + + # Attention: The module dependencies from ProfileItems have to be ignored, because + # the Profile has to be installed completely with all of its content and the correct name. + # Only complete profiles can belong to a specified module, but not ProfileItems! + + # iterating over all files + + for ( my $i = 0; $i <= $#{$profilesref}; $i++ ) + { + my $oneprofile = ${$profilesref}[$i]; + my $dir = $oneprofile->{'Dir'}; + if ( $dir eq "PREDEFINED_CONFIGDIR" ) { next; } # ignoring the profile sversion file + + my $profilegid = $oneprofile->{'gid'}; + my $profilename = $oneprofile->{'Name'}; + + my $localprofilesdir = $profilesdir . $installer::globals::separator . $profilegid; # uniqueness guaranteed by gid + if ( ! -d $localprofilesdir ) { installer::systemactions::create_directory($localprofilesdir); } + + my @onefile = (); + my $profileempty = 1; + + for ( my $j = 0; $j <= $#{$profileitemsref}; $j++ ) + { + my $oneprofileitem = ${$profileitemsref}[$j]; + + my $styles = ""; + if ( $oneprofileitem->{'Styles'} ) { $styles = $oneprofileitem->{'Styles'}; } + if ( $styles =~ /\bINIFILETABLE\b/ ) { next; } # these values are written during installation, not during packing + + my $profileid = $oneprofileitem->{'ProfileID'}; + + if ( $profileid eq $profilegid ) + { + my $section = $oneprofileitem->{'Section'}; + my $key = $oneprofileitem->{'Key'}; + my $value = $oneprofileitem->{'Value'}; + for (my $pk = 1; $pk <= 50; $pk++) + { + my $key = "ValueList" . $pk; + if ( $oneprofileitem->{$key} ) + { $value = $value . " " . $oneprofileitem->{$key} } + } + my $order = $oneprofileitem->{'Order'}; # ignoring order at the moment + + my $line = "[" . $section . "]" . "\n"; + push(@onefile, $line); + $line = $key . "=" . $value . "\n"; + push(@onefile, $line); + + $profileempty = 0; + } + } + + if ( $profileempty ) { next; } # ignoring empty profiles + + # Sorting the array @onefile + my $onefileref = sorting_profile(\@onefile); + + if ( $installer::globals::iswin && $installer::globals::plat =~ /cygwin/i) # Windows line ends only for Cygwin + { + include_windows_lineends($onefileref); + } + + # Saving the profile as a file + $completeprofilename = $localprofilesdir . $installer::globals::separator . $profilename; + + installer::files::save_file($completeprofilename, $onefileref); + + # Adding the file to the filearray + # Some data are set now, others are taken from the file "soffice.exe" ("soffice.bin") + add_profile_into_filelist($filesarrayref, $oneprofile, $completeprofilename, $allvariables); + + $infoline = "Created Profile: $completeprofilename\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + $infoline = "\n"; + push( @installer::globals::logfileinfo, $infoline); +} + + +1; diff --git a/solenv/bin/modules/installer/regmerge.pm b/solenv/bin/modules/installer/regmerge.pm new file mode 100644 index 000000000000..bb6461b00d7d --- /dev/null +++ b/solenv/bin/modules/installer/regmerge.pm @@ -0,0 +1,344 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: regmerge.pm,v $ +# +# $Revision: 1.7 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::regmerge; + +use Cwd; +use installer::converter; +use installer::existence; +use installer::exiter; +use installer::globals; +use installer::logger; +use installer::pathanalyzer; +use installer::remover; +use installer::scriptitems; +use installer::systemactions; + +################################################################ +# Collecting all files with content: +# Regmergefile = "mydatabasepart.rdb"; +################################################################ + +sub collect_all_regmergefiles +{ + my ($filesarrayref) = @_; + + my @regmergefiles = (); + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + if ( $onefile->{'Regmergefile'} ) { push(@regmergefiles, $onefile); } + } + + return \@regmergefiles; +} + +################################################################ +# Collecting all gids of the databases, that are part of +# the file definition +################################################################ + +sub collect_all_database_gids +{ + my ($filesarrayref) = @_; + + my @databasegids = (); + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + + if ( $onefile->{'RegistryID'} ) + { + my $databasegid = $onefile->{'RegistryID'}; + if (! installer::existence::exists_in_array($databasegid, \@databasegids)) { push(@databasegids, $databasegid); } + } + else + { + installer::exiter::exit_program("ERROR: File defintion error. File :$onefile->{'gid'} without RegistryID!", "collect_all_database_gids"); + } + } + + return \@databasegids; +} + +################################################################ +# Returning the database file from the files collector. In the +# future this file does not need to exist, but currently it +# has to exist already in the files collector. +################################################################ + +sub get_database_file +{ + my ($databasegid, $filesarrayref) = @_; + + my $found = 0; + my $onefile; + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + $onefile = ${$filesarrayref}[$i]; + my $gid = $onefile->{'gid'}; + + if ( $databasegid eq $gid ) + { + $found = 1; + last; + } + } + + if ( ! $found ) { installer::exiter::exit_program("ERROR: Did not find StarRegistry file $databasegid!", "get_database_file"); } + + return $onefile; +} + +################################################################ +# The regmerge file has to be found the in include pathes +################################################################ + +sub get_regmerge_file +{ + my ($includepatharrayref) = @_; + + my $searchname; + + if ($installer::globals::isunix) { $searchname = "regcomplazy"; } + else { $searchname = "regcomplazy.exe"; } + + my $regmergefileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$searchname, $includepatharrayref, 1); + if ( $$regmergefileref eq "" ) { installer::exiter::exit_program("ERROR: Could not find file $searchname for merging the StarRegistry!", "get_regmerge_file"); } + + return $$regmergefileref; +} + +################################################################ +# Collecting all files that are merged to one defined +# StarRegistry database +################################################################ + +sub collect_all_files_for_one_registry +{ + my ($regmergefiles, $databasegid) = @_; + + my @regmergefiles = (); + + for ( my $i = 0; $i <= $#{$regmergefiles}; $i++ ) + { + my $onefile = ${$regmergefiles}[$i]; + if ( $onefile->{'RegistryID'} eq $databasegid ) { push(@regmergefiles, $onefile); } + } + + return \@regmergefiles; +} + +################################################################ +# Collecting all particles from the regmerge files +################################################################ + +sub collect_all_regmerge_particles +{ + my ($databaseregisterfiles) = @_; + + my @regmergeparticles = (); + + for ( my $i = 0; $i <= $#{$databaseregisterfiles}; $i++ ) + { + my $onefile = ${$databaseregisterfiles}[$i]; + if ( $onefile->{'Regmergefile'} ) { push(@regmergeparticles, $onefile->{'Regmergefile'}); } + else { installer::exiter::exit_program("ERROR: Could not find entry for \"Regmergefile\" in $onefile->{'gid'}!", "collect_all_regmerge_particles"); } + } + + return \@regmergeparticles; +} + +################################################################ +# Collecting all source pathes of the regmerge particles +################################################################ + +sub get_all_source_pathes +{ + my ($regmergeparticles, $includepatharrayref) = @_; + + my @regmergeparticles = (); + + for ( my $i = 0; $i <= $#{$regmergeparticles}; $i++ ) + { + my $filename = ${$regmergeparticles}[$i]; + + my $fileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$filename, $includepatharrayref, 1); + if ( $$fileref eq "" ) { installer::exiter::exit_program("ERROR: Could not find file $filename for merging the StarRegistry!", "get_all_source_pathes"); } + + push(@regmergeparticles, $$fileref); + } + + return \@regmergeparticles; +} + +################################################################ +# Merging the rdb files into the StarRegistry database +################################################################ + +sub merge_files +{ + my ($regmergefile, $databasefile, $registerfiles, $databasedir, $allvariableshashref) = @_; + + my $databasesource = $databasefile->{'sourcepath'}; + my $databasename = $databasefile->{'Name'}; + my $databasedest = $databasedir . $installer::globals::separator . $databasename; + + installer::systemactions::copy_one_file($databasesource, $databasedest); + $databasefile->{'sourcepath'} = $databasedest; # new sourcepath for the StarRegistry file + + # One call for every merge particle. This is only possible, if there are only a few merge particles. + + my $prefix = $databasefile->{'NativeServicesURLPrefix'}; + # TODO: "NativeServicesURLPrefix" or "JavaServicesURLPrefix" + + my $error_occured = 0; + + for ( my $i = 0; $i <= $#{$registerfiles}; $i++ ) + { + my $registerfile = $databasedir . $installer::globals::separator . $i . ".tmp"; + open (IN, '<', $registerfiles->[$i]) or $error_occured = 1; + open (OUT, '>', $registerfile) or $error_occured = 1; + while (<IN>) + { + s/^ComponentName=/ComponentName=$prefix/; + print OUT $_ or $error_occured = 1; + } + close IN or $error_occured = 1; + close OUT or $error_occured = 1; + + my $systemcall = $regmergefile . " -v " . $databasedest . " " . $registerfile . " 2\>\&1 |"; + + my @regmergeoutput = (); + + my $var_library_path; + my $old_library_path; + if ($installer::globals::isunix) { + $var_library_path = $installer::globals::ismacosx ? + 'DYLD_LIBRARY_PATH' : 'LD_LIBRARY_PATH'; + $old_library_path = $ENV{$var_library_path}; + installer::servicesfile::include_libdir_into_ld_library_path( + $var_library_path, $regmergefile); + } + + open (REG, "$systemcall"); + while (<REG>) {push(@regmergeoutput, $_); } + close (REG); + + my $returnvalue = $?; # $? contains the return value of the systemcall + + if (defined $var_library_path) { + if (defined $old_library_path) { + $ENV{$var_library_path} = $old_library_path; + } else { + delete $ENV{$var_library_path}; + } + } + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $j = 0; $j <= $#regmergeoutput; $j++ ) { push( @installer::globals::logfileinfo, "$regmergeoutput[$j]"); } + + if ($returnvalue) + { + $infoline = "ERROR: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + $error_occured = 1; + } + else + { + $infoline = "SUCCESS: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + + return $error_occured; +} + +################################################################ +# Expanding the registry database files by merging rdb files +# into this registry database files. +################################################################ + +sub merge_registration_files +{ + my ($filesarrayref, $includepatharrayref, $languagestringref, $allvariableshashref) = @_; + + installer::logger::include_header_into_logfile("Creating starregistry databases:"); + + # Test if there is something to do. At least one file has to have the content: + # Regmergefile = "mydatabasepart.rdb"; + + my $regmergefiles = collect_all_regmergefiles($filesarrayref); + + if ( $#{$regmergefiles} > -1 ) # not empty -> at least one regmerge file + { + # prepare registration + + my $regmergefile = get_regmerge_file($includepatharrayref); # searching for regmerge (regcomplazy.exe) + + my $databasegids = collect_all_database_gids($regmergefiles); + + # iterating over all database gids + + my $regmergeerror = 0; + + for ( my $i = 0; $i <= $#{$databasegids}; $i++ ) + { + $databasegid = ${$databasegids}[$i]; + + # my $databasedirname = "starregistryrdb"; <- not unique! + my $databasedirname = $databasegid . "_rdb"; # <- unique! + my $databasedir = installer::systemactions::create_directories($databasedirname, $languagestringref); + push(@installer::globals::removedirs, $databasedir); + + my $databasefile = get_database_file($databasegid, $filesarrayref); + my $databaseregisterfiles = collect_all_files_for_one_registry($regmergefiles, $databasegid); + + if ( $#{$databaseregisterfiles} > -1 ) # not empty -> at least one regmerge file + { + my $regmergeparticles = collect_all_regmerge_particles($databaseregisterfiles); + $regmergeparticles = get_all_source_pathes($regmergeparticles, $includepatharrayref); + my $oneregmergeerror = merge_files($regmergefile, $databasefile, $regmergeparticles, $databasedir, $allvariableshashref); + if ($oneregmergeerror) { $regmergeerror = 1; } + } + } + + if ( $regmergeerror ) { installer::exiter::exit_program("ERROR: regmerge !", "merge_registration_files"); } + + } +} + +1; diff --git a/solenv/bin/modules/installer/remover.pm b/solenv/bin/modules/installer/remover.pm new file mode 100644 index 000000000000..e142682be614 --- /dev/null +++ b/solenv/bin/modules/installer/remover.pm @@ -0,0 +1,86 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: remover.pm,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::remover; + +use installer::globals; + +############################################ +# Remover +############################################ + +sub remove_leading_and_ending_whitespaces +{ + my ( $stringref ) = @_; + + $$stringref =~ s/^\s*//; + $$stringref =~ s/\s*$//; +} + +sub remove_leading_and_ending_quotationmarks +{ + my ( $stringref ) = @_; + + $$stringref =~ s/^\s*\"//; + $$stringref =~ s/\"\s*$//; +} + +sub remove_leading_and_ending_slashes +{ + my ( $stringref ) = @_; + + $$stringref =~ s/^\s*\///g; + $$stringref =~ s/\/\s*$//g; +} + +sub remove_ending_slashes +{ + my ( $stringref ) = @_; + + $$stringref =~ s/\/\s*$//g; +} + +sub remove_leading_and_ending_pathseparators +{ + my ( $stringref ) = @_; + + $$stringref =~ s/^\s*\Q$installer::globals::separator\E//; + $$stringref =~ s/\Q$installer::globals::separator\E\s*$//; +} + +sub remove_ending_pathseparator +{ + my ( $stringref ) = @_; + + $$stringref =~ s/\Q$installer::globals::separator\E\s*$//; +} + +1; diff --git a/solenv/bin/modules/installer/scppatchsoname.pm b/solenv/bin/modules/installer/scppatchsoname.pm new file mode 100644 index 000000000000..7ade6dee9c80 --- /dev/null +++ b/solenv/bin/modules/installer/scppatchsoname.pm @@ -0,0 +1,183 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: scppatchsoname.pm,v $ +# +# $Revision: 1.8 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::scppatchsoname; + +use installer::files; +use installer::globals; +use installer::logger; +use installer::setupscript; +use installer::systemactions; + +######################################################################################## +# The length of the new string must be identical with the length of the old string +######################################################################################## + +sub change_length_of_string +{ + my ($newstringref, $oldstring) = @_; + + while ( length($$newstringref) < length($oldstring) ) + { + $$newstringref = $$newstringref . chr(0); + } +} + +######################################################################################## +# Converting a string to a unicode string +######################################################################################## + +sub convert_to_unicode +{ + my ($string) = @_; + + my $unicodestring = ""; + + my $stringlength = length($string); + + for ( my $i = 0; $i < $stringlength; $i++ ) + { + $unicodestring = $unicodestring . substr($string, $i, 1); + $unicodestring = $unicodestring . chr(0); + } + + return $unicodestring; +} + +######################################################################################## +# Replacing the so name in all files with flag PATCH_SO_NAME +######################################################################################## + +sub replace_productname_in_file +{ + my ($sourcepath, $destpath, $variableshashref) = @_; + + my $onefile = installer::files::read_binary_file($sourcepath); + + my $onestring = "x" . chr(0); + my $replacestring = ""; + for ( my $i = 1; $i <= 80; $i++ ) { $replacestring .= $onestring; } + + my $productname = $variableshashref->{'PRODUCTNAME'} . " " . $variableshashref->{'PRODUCTVERSION'}; + my $unicode_productname = convert_to_unicode($productname); + + change_length_of_string(\$unicode_productname, $replacestring); + + my $found = $onefile =~ s/$replacestring/$unicode_productname/s; + + installer::files::save_binary_file($onefile, $destpath); + + return $found; +} + +######################################################### +# Analyzing files with flag PATCH_SO_NAME +######################################################### + +sub resolving_patchsoname_flag +{ + my ($filesarrayref, $variableshashref, $item, $languagestringref) = @_; + + my $diritem = lc($item); + + my $replacedirbase = installer::systemactions::create_directories("patchsoname_$diritem", $languagestringref); + + installer::logger::include_header_into_logfile("$item with flag PATCH_SO_NAME:"); + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + my $styles = ""; + + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } + + if ( $styles =~ /\bPATCH_SO_NAME\b/ ) + { + # Language specific subdirectory + + my $onelanguage = $onefile->{'specificlanguage'}; + + if ($onelanguage eq "") + { + $onelanguage = "00"; # files without language into directory "00" + } + + my $replacedir = $replacedirbase . $installer::globals::separator . $onelanguage . $installer::globals::separator; + installer::systemactions::create_directory($replacedir); # creating language specific directories + + # copy files and edit them with the variables defined in the zip.lst + + my $onefilename = $onefile->{'Name'}; + my $sourcepath = $onefile->{'sourcepath'}; + my $destinationpath = $replacedir . $onefilename; + my $movepath = $destinationpath . ".orig"; + + # if (!(-f $destinationpath)) # do nothing if the file already exists + # { + + my $copysuccess = installer::systemactions::copy_one_file($sourcepath, $movepath); + + if ( $copysuccess ) + { + # Now the file can be patch (binary!) + my $found = replace_productname_in_file($movepath, $destinationpath, $variableshashref); + + if ($found == 0) + { + my $infoline = "Did not patch the file $destinationpath\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + my $infoline = "Successfully patched $destinationpath, Count: $found\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + + # } + + # Saving the original source, where the file was found + $onefile->{'originalsourcepath'} = $onefile->{'sourcepath'}; + + # Saving the original source, where the file was found + $onefile->{'originalsourcepath'} = $onefile->{'sourcepath'}; + + # Writing the new sourcepath into the hashref, even if it was no copied + + $onefile->{'sourcepath'} = $destinationpath; + } + } + + my $infoline = "\n"; + push( @installer::globals::logfileinfo, $infoline); +} + +1; diff --git a/solenv/bin/modules/installer/scpzipfiles.pm b/solenv/bin/modules/installer/scpzipfiles.pm new file mode 100644 index 000000000000..f5a242b5ff0a --- /dev/null +++ b/solenv/bin/modules/installer/scpzipfiles.pm @@ -0,0 +1,191 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: scpzipfiles.pm,v $ +# +# $Revision: 1.15 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::scpzipfiles; + +use installer::files; +use installer::globals; +use installer::logger; +use installer::pathanalyzer; +use installer::systemactions; + +######################################################################################## +# Replacing all zip list variables in setup script and files with flag scpzip_replace +######################################################################################## + +sub replace_all_ziplistvariables_in_file +{ + my ( $fileref, $variableshashref ) = @_; + + for ( my $i = 0; $i <= $#{$fileref}; $i++ ) + { + my $line = ${$fileref}[$i]; + + if ( $line =~ /^.*\$\{\w+\}.*$/ ) # only occurence of ${abc} + { + my $key; + + foreach $key (keys %{$variableshashref}) + { + my $value = $variableshashref->{$key}; + $key = '${' . $key . '}'; + $line =~ s/\Q$key\E/$value/g; + ${$fileref}[$i] = $line; + } + } + } +} + +######################################################################################## +# Replacing all zip list variables in rtf files. In rtf files +# the brackets are masked. +######################################################################################## + +sub replace_all_ziplistvariables_in_rtffile +{ + my ( $fileref, $variablesref, $onelanguage, $loggingdir ) = @_; + + # installer::files::save_file($loggingdir . "license_" . $onelanguage . "_before.rtf", $fileref); + + for ( my $i = 0; $i <= $#{$fileref}; $i++ ) + { + my $line = ${$fileref}[$i]; + + if ( $line =~ /^.*\$\\\{\w+\\\}.*$/ ) # only occurence of $\{abc\} + { + for ( my $j = 0; $j <= $#{$variablesref}; $j++ ) + { + my $variableline = ${$variablesref}[$j]; + + my ($key, $value); + + if ( $variableline =~ /^\s*([\w-]+?)\s+(.*?)\s*$/ ) + { + $key = $1; + $value = $2; + $key = '$\{' . $key . '\}'; + } + + $line =~ s/\Q$key\E/$value/g; + + ${$fileref}[$i] = $line; + } + } + } + + # installer::files::save_file($loggingdir . "license_" . $onelanguage . "_after.rtf", $fileref); +} + +######################################################### +# Analyzing files with flag SCPZIP_REPLACE +# $item can be "File" or "ScpAction" +######################################################### + +sub resolving_scpzip_replace_flag +{ + my ($filesarrayref, $variableshashref, $item, $languagestringref) = @_; + + my $diritem = lc($item); + + my $replacedirbase = installer::systemactions::create_directories("replace_$diritem", $languagestringref); + + installer::logger::include_header_into_logfile("$item with flag SCPZIP:"); + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + my $styles = ""; + + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } + + if ( $styles =~ /\bSCPZIP_REPLACE\b/ ) + { + # Language specific subdirectory + + my $onelanguage = $onefile->{'specificlanguage'}; + + if ($onelanguage eq "") + { + $onelanguage = "00"; # files without language into directory "00" + } + + my $replacedir = $replacedirbase . $installer::globals::separator . $onelanguage . $installer::globals::separator; + installer::systemactions::create_directory($replacedir); # creating language specific directories + + # copy files and edit them with the variables defined in the zip.lst + + my $longfilename = 0; + + my $onefilename = $onefile->{'Name'}; + my $sourcepath = $onefile->{'sourcepath'}; + + if ( $onefilename =~ /^\s*\Q$installer::globals::separator\E/ ) # filename begins with a slash, for instance /registry/schema/org/openoffice/VCL.xcs + { + $onefilename =~ s/^\s*\Q$installer::globals::separator\E//; + $longfilename = 1; + } + + my $destinationpath = $replacedir . $onefilename; + my $movepath = $destinationpath . ".orig"; + + if ( $longfilename ) # the destination directory has to be created before copying + { + my $destdir = $movepath; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$destdir); + installer::systemactions::create_directory_structure($destdir); + } + + my $copysuccess = installer::systemactions::copy_one_file($sourcepath, $movepath); + + if ( $copysuccess ) + { + # Now the file can be edited + # ToDo: How about binary patching? + + my $onefileref = installer::files::read_file($movepath); + replace_all_ziplistvariables_in_file($onefileref, $variableshashref); + installer::files::save_file($destinationpath ,$onefileref); + } + + # Saving the original source, where the file was found + $onefile->{'originalsourcepath'} = $onefile->{'sourcepath'}; + + # Writing the new sourcepath into the hashref, even if it was no copied + + $onefile->{'sourcepath'} = $destinationpath; + } + } + + my $infoline = "\n"; + push( @installer::globals::logfileinfo, $infoline); +} + +1; diff --git a/solenv/bin/modules/installer/scriptitems.pm b/solenv/bin/modules/installer/scriptitems.pm new file mode 100644 index 000000000000..d02f91a62dcc --- /dev/null +++ b/solenv/bin/modules/installer/scriptitems.pm @@ -0,0 +1,2834 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: scriptitems.pm,v $ +# +# $Revision: 1.53 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::scriptitems; + +use installer::converter; +use installer::existence; +use installer::exiter; +use installer::globals; +use installer::languages; +use installer::logger; +use installer::pathanalyzer; +use installer::remover; +use installer::systemactions; + +################################################################ +# Resolving the GID for the directories defined in setup script +################################################################ + +sub resolve_all_directory_names +{ + my ($directoryarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::resolve_all_directory_names : $#{$directoryarrayref}"); } + + # After this procedure the hash shall contain the complete language + # dependent path, not only the language dependent HostName. + + my ($key, $value, $parentvalue, $parentgid, $parentdirectoryhashref); + + for ( my $i = 0; $i <= $#{$directoryarrayref}; $i++ ) + { + my $directoryhashref = ${$directoryarrayref}[$i]; + my $gid = $directoryhashref-> {'gid'}; + my $parentid = $directoryhashref-> {'ParentID'}; + + if ( $parentid ne "PREDEFINED_PROGDIR" ) + { + # find the array of the parentid, which has to be defined before in setup script + # and is therefore listed before in this array + + for ( my $j = 0; $j <= $i; $j++ ) + { + $parentdirectoryhashref = ${$directoryarrayref}[$j]; + $parentgid = $parentdirectoryhashref->{'gid'}; + + if ( $parentid eq $parentgid) + { + last; + } + } + + # and now we can put the path together + # But take care of the languages! + + my $dirismultilingual = $directoryhashref->{'ismultilingual'}; + my $parentismultilingual = $parentdirectoryhashref->{'ismultilingual'}; + + # First: Both directories are language independent or both directories are language dependent + + if ((( ! $dirismultilingual ) && ( ! $parentismultilingual )) || + (( $dirismultilingual ) && ( $parentismultilingual ))) + { + foreach $key (keys %{$directoryhashref}) + { + # the key ("HostName (en-US)") must be usable for both hashes + + if ( $key =~ /\bHostName\b/ ) + { + $parentvalue = ""; + $value = $directoryhashref->{$key}; + if ( $parentdirectoryhashref->{$key} ) { $parentvalue = $parentdirectoryhashref->{$key}; } + + # It is possible, that in scp project, a directory is defined in more languages than + # the directory parent (happened after automatic generation of macros.inc). + # Therefore this is checked now and written with a warning into the logfile. + # This is no error, because (in most cases) the concerned language is not build. + + if ($parentvalue eq "") + { + $directoryhashref->{$key} = "FAILURE"; + my $infoline = "WARNING: No hostname for $parentid with \"$key\". Needed by child directory $gid !\n"; + push( @installer::globals::globallogfileinfo, $infoline); + } + else + { + $directoryhashref->{$key} = $parentvalue . $installer::globals::separator . $value; + } + } + } + } + + # Second: The directory is language dependent, the parent not + + if (( $dirismultilingual ) && ( ! $parentismultilingual )) + { + $parentvalue = $parentdirectoryhashref->{'HostName'}; # there is only one + + foreach $key (keys %{$directoryhashref}) # the current directory + { + if ( $key =~ /\bHostName\b/ ) + { + $value = $directoryhashref->{$key}; + $directoryhashref->{$key} = $parentvalue . $installer::globals::separator . $value; + } + } + } + + # Third: The directory is not language dependent, the parent is language dependent + + if (( ! $dirismultilingual ) && ( $parentismultilingual )) + { + $value = $directoryhashref->{'HostName'}; # there is only one + delete($directoryhashref->{'HostName'}); + + foreach $key (keys %{$parentdirectoryhashref}) # the parent directory + { + if ( $key =~ /\bHostName\b/ ) + { + $parentvalue = $parentdirectoryhashref->{$key}; # there is only one + $directoryhashref->{$key} = $parentvalue . $installer::globals::separator . $value; + } + } + + $directoryhashref->{'ismultilingual'} = 1; # now this directory is also language dependent + } + } + } +} + +############################################################################# +# Files with flag DELETE_ONLY do not need to be packed into installation set +############################################################################# + +sub remove_delete_only_files_from_productlists +{ + my ($productarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_delete_only_files_from_productlists : $#{$productarrayref}"); } + + my @newitems = (); + + for ( my $i = 0; $i <= $#{$productarrayref}; $i++ ) + { + my $oneitem = ${$productarrayref}[$i]; + my $styles = ""; + + if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; } + + if (!($styles =~ /\bDELETE_ONLY\b/)) + { + push(@newitems, $oneitem); + } + } + + return \@newitems; +} + +############################################################################# +# Files with flag NOT_IN_SUITE do not need to be packed into +# Suite installation sets +############################################################################# + +sub remove_notinsuite_files_from_productlists +{ + my ($productarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_notinsuite_files_from_productlists : $#{$productarrayref}"); } + + my @newitems = (); + + for ( my $i = 0; $i <= $#{$productarrayref}; $i++ ) + { + my $oneitem = ${$productarrayref}[$i]; + my $styles = ""; + + if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; } + + if (!($styles =~ /\bNOT_IN_SUITE\b/)) + { + push(@newitems, $oneitem); + } + else + { + my $infoline = "INFO: Flag NOT_IN_SUITE \-\> Removing $oneitem->{'gid'} from file list.\n"; + push( @installer::globals::globallogfileinfo, $infoline); + } + } + + return \@newitems; +} + +############################################################################# +# Files with flag NOT_IN_SUITE do not need to be packed into +# Suite installation sets +############################################################################# + +sub remove_office_start_language_files +{ + my ($productarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_notinsuite_files_from_productlists : $#{$productarrayref}"); } + + my @newitems = (); + + for ( my $i = 0; $i <= $#{$productarrayref}; $i++ ) + { + my $oneitem = ${$productarrayref}[$i]; + my $styles = ""; + + if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; } + + if (!($styles =~ /\bSET_OFFICE_LANGUAGE\b/)) + { + push(@newitems, $oneitem); + } + else + { + my $infoline = "INFO: Flag SET_OFFICE_LANGUAGE \-\> Removing $oneitem->{'gid'} from file list.\n"; + push( @installer::globals::globallogfileinfo, $infoline); + } + } + + return \@newitems; +} + +############################################################################# +# Registryitems for Uninstall have to be removed +############################################################################# + +sub remove_uninstall_regitems_from_script +{ + my ($registryarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_uninstall_regitems_from_script : $#{$registryarrayref}"); } + + my @newitems = (); + + for ( my $i = 0; $i <= $#{$registryarrayref}; $i++ ) + { + my $oneitem = ${$registryarrayref}[$i]; + my $subkey = ""; + + if ( $oneitem->{'Subkey'} ) { $subkey = $oneitem->{'Subkey'}; } + + if ( $subkey =~ /Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall/ ) { next; } + + push(@newitems, $oneitem); + } + + return \@newitems; +} + +############################################################################## +# Searching the language module for a specified language +############################################################################## + +sub get_languagespecific_module +{ + my ( $lang, $modulestring ) = @_; + + my $langmodulestring = ""; + + my $module; + foreach $module ( keys %installer::globals::alllangmodules ) + { + if (( $installer::globals::alllangmodules{$module} eq $lang ) && ( $modulestring =~ /\b$module\b/ )) + { + $langmodulestring = "$langmodulestring,$module"; + } + } + + $langmodulestring =~ s/^\s*,//; + + if ( $langmodulestring eq "" ) { installer::exiter::exit_program("ERROR: No language pack module found for language $lang in string \"$modulestring\"!", "get_languagespecific_module"); } + + return $langmodulestring; +} + +############################################################################## +# Removing all items in product lists which do not have the correct languages +############################################################################## + +sub resolving_all_languages_in_productlists +{ + my ($productarrayref, $languagesarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::resolving_all_languages_in_productlists : $#{$productarrayref} : $#{$languagesarrayref}"); } + + my @itemsinalllanguages = (); + + my ($key, $value); + + for ( my $i = 0; $i <= $#{$productarrayref}; $i++ ) + { + my $oneitem = ${$productarrayref}[$i]; + + my $ismultilingual = $oneitem->{'ismultilingual'}; + + if (!($ismultilingual)) # nothing to do with single language items + { + $oneitem->{'specificlanguage'} = ""; + push(@itemsinalllanguages, $oneitem); + } + else #all language dependent files + { + for ( my $j = 0; $j <= $#{$languagesarrayref}; $j++ ) # iterating over all languages + { + my $onelanguage = ${$languagesarrayref}[$j]; + + my %oneitemhash = (); + + foreach $key (keys %{$oneitem}) + { + if ( $key =~ /\(\S+\)/ ) # this are the language dependent keys + { + if ( $key =~ /\(\Q$onelanguage\E\)/ ) + { + $value = $oneitem->{$key}; + $oneitemhash{$key} = $value; + } + } + else + { + $value = $oneitem->{$key}; + $oneitemhash{$key} = $value; + } + } + + $oneitemhash{'specificlanguage'} = $onelanguage; + + if ( $oneitemhash{'haslanguagemodule'} ) + { + my $langmodulestring = get_languagespecific_module($onelanguage, $oneitemhash{'modules'}); + $oneitemhash{'modules'} = $langmodulestring; + } + + push(@itemsinalllanguages, \%oneitemhash); + } + } + } + + return \@itemsinalllanguages; +} + +################################################################################ +# Removing all modules, that have the flag LANGUAGEMODULE, but do not +# have the correct language +################################################################################ + +sub remove_not_required_language_modules +{ + my ($modulesarrayref, $languagesarrayref) = @_; + + my @allmodules = (); + + for ( my $i = 0; $i <= $#{$modulesarrayref}; $i++ ) + { + my $module = ${$modulesarrayref}[$i]; + my $styles = ""; + if ( $module->{'Styles'} ) { $styles = $module->{'Styles'}; } + + if ( $styles =~ /\bLANGUAGEMODULE\b/ ) + { + if ( ! exists($module->{'Language'}) ) { installer::exiter::exit_program("ERROR: \"$module->{'gid'}\" has flag LANGUAGEMODULE, but does not know its language!", "remove_not_required_language_modules"); } + my $modulelanguage = $module->{'Language'}; + # checking, if language is required + my $doinclude = 0; + for ( my $j = 0; $j <= $#{$languagesarrayref}; $j++ ) + { + my $onelanguage = ${$languagesarrayref}[$j]; + if ( $onelanguage eq $modulelanguage ) + { + $doinclude = 1; + last; + } + } + + if ( $doinclude ) { push(@allmodules, $module); } + } + else + { + push(@allmodules, $module); + } + } + + return \@allmodules; +} + +################################################################################ +# Removing all modules, that have a spellchecker language that is not +# required for this product (spellchecker selection). +# All required spellchecker languages are stored in +# %installer::globals::spellcheckerlanguagehash +################################################################################ + +sub remove_not_required_spellcheckerlanguage_modules +{ + my ($modulesarrayref) = @_; + + my $infoline = ""; + my @allmodules = (); + + for ( my $i = 0; $i <= $#{$modulesarrayref}; $i++ ) + { + my $module = ${$modulesarrayref}[$i]; + if ( $module->{'Spellcheckerlanguage'} ) # selecting modules with Spellcheckerlanguage + { + if ( exists($installer::globals::spellcheckerlanguagehash{$module->{'Spellcheckerlanguage'}}) ) + { + push(@allmodules, $module); + } + else + { + $infoline = "Spellchecker selection: Removing module $module->{'gid'}\n"; + push( @installer::globals::logfileinfo, $infoline); + + # Collecting all files at modules that are removed + + if ( $module->{'Files'} ) + { + if ( $module->{'Files'} =~ /^\s*\((.*?)\)\s*$/ ) + { + my $filelist = $1; + + my $filelisthash = installer::converter::convert_stringlist_into_hash(\$filelist, ","); + foreach my $onefile ( keys %{$filelisthash} ) { $installer::globals::spellcheckerfilehash{$onefile} = 1; } + } + } + } + } + else + { + push(@allmodules, $module); + } + } + + return \@allmodules; +} + +################################################################################ +# Removing all modules, that belong to a module that was removed +# in "remove_not_required_spellcheckerlanguage_modules" because of the +# spellchecker language. The files belonging to the modules are collected +# in %installer::globals::spellcheckerfilehash. +################################################################################ + +sub remove_not_required_spellcheckerlanguage_files +{ + my ($filesarrayref) = @_; + + my @filesarray = (); + my $infoline = ""; + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + if ( exists($installer::globals::spellcheckerfilehash{$onefile->{'gid'}}) ) + { + $infoline = "Spellchecker selection: Removing file $onefile->{'gid'}\n"; + push( @installer::globals::logfileinfo, $infoline); + next; + } + push(@filesarray, $onefile); + } + + return \@filesarray; +} + +################################################################################ +# Looking for directories without correct HostName +################################################################################ + +sub checking_directories_with_corrupt_hostname +{ + my ($dirsref, $languagesarrayref) = @_; + + for ( my $i = 0; $i <= $#{$dirsref}; $i++ ) + { + my $onedir = ${$dirsref}[$i]; + + my $hostname = ""; + + if ( $onedir->{'HostName'} ) { $hostname = $onedir->{'HostName'}; } + + if ( $hostname eq "" ) + { + my $langstring = ""; + for ( my $j = 0; $j <= $#{$languagesarrayref}; $j++ ) { $langstring .= ${$languagesarrayref}[$j] . " "; } + installer::exiter::exit_program("ERROR: HostName not defined for $onedir->{'gid'} for specified language. Probably you wanted to create an installation set, in a language not defined in scp2 project. You selected the following language(s): $langstring", "checking_directories_with_corrupt_hostname"); + } + + if ( $hostname eq "FAILURE" ) + { + installer::exiter::exit_program("ERROR: Could not create HostName for $onedir->{'gid'} (missing language at parent). See logfile warning for more info!", "checking_directories_with_corrupt_hostname"); + } + } +} + +################################################################################ +# Setting global properties +################################################################################ + +sub set_global_directory_hostnames +{ + my ($dirsref, $allvariables) = @_; + + for ( my $i = 0; $i <= $#{$dirsref}; $i++ ) + { + my $onedir = ${$dirsref}[$i]; + my $styles = ""; + if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; } + + if ( $styles =~ /\bOFFICEDIRECTORY\b/ ) + { + $installer::globals::officedirhostname = $onedir->{'HostName'}; + $installer::globals::officedirgid = $onedir->{'gid'}; + $allvariables->{'OFFICEDIRECTORYHOSTNAME'} = $installer::globals::officedirhostname; + } + if ( $styles =~ /\bBASISDIRECTORY\b/ ) + { + $installer::globals::basisdirhostname = $onedir->{'HostName'}; + $installer::globals::basisdirgid = $onedir->{'gid'}; + $allvariables->{'BASISDIRECTORYHOSTNAME'} = $installer::globals::basisdirhostname; + } + if ( $styles =~ /\bUREDIRECTORY\b/ ) + { + $installer::globals::uredirhostname = $onedir->{'HostName'}; + $installer::globals::uredirgid = $onedir->{'gid'}; + $allvariables->{'UREDIRECTORYHOSTNAME'} = $installer::globals::uredirhostname; + } + if ( $styles =~ /\bSUNDIRECTORY\b/ ) + { + $installer::globals::sundirhostname = $onedir->{'HostName'}; + $installer::globals::sundirgid = $onedir->{'gid'}; + $allvariables->{'SUNDIRECTORYHOSTNAME'} = $installer::globals::sundirhostname; + } + } +} + +######################################################## +# Recursively defined procedure to order +# modules and directories +######################################################## + +sub get_children +{ + my ($allitems, $startparent, $newitemorder) = @_; + + for ( my $i = 0; $i <= $#{$allitems}; $i++ ) + { + my $gid = ${$allitems}[$i]->{'gid'}; + my $parent = ""; + if ( ${$allitems}[$i]->{'ParentID'} ) { $parent = ${$allitems}[$i]->{'ParentID'}; } + + if ( $parent eq $startparent ) + { + push(@{$newitemorder}, ${$allitems}[$i]); + my $parent = $gid; + get_children($allitems, $parent, $newitemorder); # recursive! + } + } +} + +################################################################################ +# Shifting parent directories of URE and Basis layer, so that +# these directories are located below the Brand layer. +# Style: SHIFT_BASIS_INTO_BRAND_LAYER +################################################################################ + +sub shift_basis_directory_parents +{ + my ($dirsref) = @_; + + my @alldirs = (); + my @savedirs = (); + my @shifteddirs = (); + + my $officedirgid = ""; + + for ( my $i = 0; $i <= $#{$dirsref}; $i++ ) + { + my $onedir = ${$dirsref}[$i]; + my $styles = ""; + if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; } + + if ( $styles =~ /\bOFFICEDIRECTORY\b/ ) { $officedirgid = $onedir->{'gid'}; } + } + + if ( $officedirgid ne "" ) + { + for ( my $i = 0; $i <= $#{$dirsref}; $i++ ) + { + my $onedir = ${$dirsref}[$i]; + my $styles = ""; + if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; } + + if (( $styles =~ /\bBASISDIRECTORY\b/ ) || ( $styles =~ /\bUREDIRECTORY\b/ )) + { + $onedir->{'ParentID'} = $officedirgid; + } + } + + # Sorting directories + my $startgid = "PREDEFINED_PROGDIR"; + get_children($dirsref, $startgid, \@alldirs); + } + + return \@alldirs; +} + +################################################################################ +# Simplifying the name for language dependent items from "Name (xy)" to "Name" +################################################################################ + +sub changing_name_of_language_dependent_keys +{ + my ($itemsarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::changing_name_of_language_dependent_keys : $#{$itemsarrayref}"); } + + # Changing key for multilingual items from "Name ( )" to "Name" or "HostName ( )" to "HostName" + + for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ ) + { + my $oneitem = ${$itemsarrayref}[$i]; + my $onelanguage = $oneitem->{'specificlanguage'}; + + if (!($onelanguage eq "" )) # language dependent item + { + my $itemkey; + + foreach $itemkey (keys %{$oneitem}) + { + if ( $itemkey =~ /^\s*(\S+?)\s+\(\S+\)\s*$/ ) + { + my $newitemkey = $1; + my $itemvalue = $oneitem->{$itemkey}; + $oneitem->{$newitemkey} = $itemvalue; + delete($oneitem->{$itemkey}); + } + } + } + } +} + +################################################################################ +# Collecting language specific names for language packs +################################################################################ + +sub collect_language_specific_names +{ + my ($itemsarrayref) = @_; + + for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ ) + { + my $oneitem = ${$itemsarrayref}[$i]; + my $styles = ""; + if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; } + + if ( $styles =~ /\bUSELANGUAGENAME\b/ ) + { + my $language = ""; + if ( $oneitem->{'Language'} ) { $language = $oneitem->{'Language'}; } + my $specificlanguage = ""; + if ( $oneitem->{'specificlanguage'} ) { $specificlanguage = $oneitem->{'specificlanguage'}; } + + if (( $language ne "" ) && ( $language eq $specificlanguage )) + { + if (! installer::existence::exists_in_array($oneitem->{'Name'}, \@installer::globals::languagenames )) + { + push(@installer::globals::languagenames, $oneitem->{'Name'}); + } + } + } + } +} + +################################################################################ +# Replacement of setup variables in ConfigurationItems and ProfileItems +# <productkey>, <buildid>, <sequence_languages>, <productcode>, <upgradecode>, <productupdate> +################################################################################ + +sub replace_setup_variables +{ + my ($itemsarrayref, $languagestringref, $hashref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::replace_setup_variables : $#{$itemsarrayref} : $$languagestringref : $hashref->{'PRODUCTNAME'}"); } + + my $languagesstring = $$languagestringref; + $languagesstring =~ s/\_/ /g; # replacing underscore with whitespace + # $languagesstring is "01 49" instead of "en-US de" + installer::languages::fake_languagesstring(\$languagesstring); + + my $productname = $hashref->{'PRODUCTNAME'}; + my $productversion = $hashref->{'PRODUCTVERSION'}; + my $userdirproductversion = ""; + if ( $hashref->{'USERDIRPRODUCTVERSION'} ) { $userdirproductversion = $hashref->{'USERDIRPRODUCTVERSION'}; } + my $productkey = $productname . " " . $productversion; + + # string $buildid, which is used to replace the setup variable <buildid> + + my $localminor = "flat"; + if ( $installer::globals::minor ne "" ) { $localminor = $installer::globals::minor; } + else { $localminor = $installer::globals::lastminor; } + + my $localbuild = $installer::globals::build; + + if ( $localbuild =~ /^\s*(\w+?)(\d+)\s*$/ ) { $localbuild = $2; } # using "680" instead of "src680" + + my $buildidstring = $localbuild . $localminor . "(Build:" . $installer::globals::buildid . ")"; + + # the environment variable CWS_WORK_STAMP is set only in CWS + if ( $ENV{'CWS_WORK_STAMP'} ) { $buildidstring = $buildidstring . "\[CWS\:" . $ENV{'CWS_WORK_STAMP'} . "\]"; } + + if ( $localminor =~ /^\s*\w(\d+)\w*\s*$/ ) { $localminor = $1; } + + # $updateid + my $updateid = $productname . "_" . $userdirproductversion . "_" . $$languagestringref; + $updateid =~ s/ /_/g; + + for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ ) + { + my $oneitem = ${$itemsarrayref}[$i]; + my $value = $oneitem->{'Value'}; + + $value =~ s/\<buildid\>/$buildidstring/; + $value =~ s/\<sequence_languages\>/$languagesstring/; + $value =~ s/\<productkey\>/$productkey/; + $value =~ s/\<productcode\>/$installer::globals::productcode/; + $value =~ s/\<upgradecode\>/$installer::globals::upgradecode/; + $value =~ s/\<alllanguages\>/$languagesstring/; + $value =~ s/\<productmajor\>/$localbuild/; + $value =~ s/\<productminor\>/$localminor/; + $value =~ s/\<productbuildid\>/$installer::globals::buildid/; + $value =~ s/\<sourceid\>/$installer::globals::build/; + $value =~ s/\<updateid\>/$updateid/; + $value =~ s/\<pkgformat\>/$installer::globals::packageformat/; + + $oneitem->{'Value'} = $value; + } +} + +################################################################################ +# By defining variable LOCALUSERDIR in *.lst it is possible to change +# the standard destination of user directory defined in scp2 ($SYSUSERCONFIG). +################################################################################ + +sub replace_userdir_variable +{ + my ($itemsarrayref) = @_; + + my $userdir = ""; + if ( $allvariableshashref->{'LOCALUSERDIR'} ) { $userdir = $allvariableshashref->{'LOCALUSERDIR'}; } + else { $userdir = $installer::globals::simpledefaultuserdir; } + + if ( $userdir ne "" ) + { + for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ ) + { + my $oneitem = ${$itemsarrayref}[$i]; + $oneitem->{'Value'} =~ s/\$SYSUSERCONFIG/$userdir/; + } + } +} + +##################################################################################### +# Files and ConfigurationItems are not included for all languages. +# For instance asian fonts. These can be removed, if no "Name" is found. +# ConfigurationItems are not always defined in the linguistic configuration file. +# The "Key" cannot be found for them. +##################################################################################### + +sub remove_non_existent_languages_in_productlists +{ + my ($itemsarrayref, $languagestringref, $searchkey, $itemtype) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_non_existent_languages_in_productlists : $#{$itemsarrayref} : $$languagestringref : $searchkey : $itemtype"); } + + # Removing of all non existent files, for instance asian fonts + + installer::logger::include_header_into_logfile("Removing for this language $$languagestringref:"); + + my @allexistentitems = (); + + my $infoline; + + for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ ) + { + my $oneitem = ${$itemsarrayref}[$i]; + my $oneitemname = ""; # $searchkey is "Name" for files and "Key" for ConfigurationItems + + if ( $oneitem->{$searchkey} ) { $oneitemname = $oneitem->{$searchkey} } + + my $itemtoberemoved = 0; + + if ($oneitemname eq "") # for instance asian font in english installation set + { + $itemtoberemoved = 1; + } + + if ($itemtoberemoved) + { + $infoline = "WARNING: Language $$languagestringref: No $itemtype packed for $oneitem->{'gid'}!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + push(@allexistentitems, $oneitem); + } + } + + $infoline = "\n"; + push( @installer::globals::logfileinfo, $infoline); + + return \@allexistentitems; +} + +######################################################################## +# Input is the directory gid, output the "HostName" of the directory +######################################################################## + +sub get_Directoryname_From_Directorygid +{ + my ($dirsarrayref ,$searchgid, $onelanguage, $oneitemgid) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::get_Directoryname_From_Directorygid : $#{$dirsarrayref} : $searchgid : $onelanguage"); } + + my $directoryname = ""; + my $onedirectory; + my $foundgid = 0; + + for ( my $i = 0; $i <= $#{$dirsarrayref}; $i++ ) + { + $onedirectory = ${$dirsarrayref}[$i]; + my $directorygid = $onedirectory->{'gid'}; + + if ($directorygid eq $searchgid) + { + $foundgid = 1; + last; + } + } + + if (!($foundgid)) + { + installer::exiter::exit_program("ERROR: Gid $searchgid not defined in $installer::globals::setupscriptname", "get_Directoryname_From_Directorygid"); + } + + if ( ! ( $onedirectory->{'ismultilingual'} )) # the directory is not language dependent + { + $directoryname = $onedirectory->{'HostName'}; + } + else + { + $directoryname = $onedirectory->{"HostName ($onelanguage)"}; + } + + # gid_Dir_Template_Wizard_Letter is defined as language dependent directory, but the file gid_Dir_Template_Wizard_Letter + # is not language dependent. Therefore $onelanguage is not defined. But which language is the correct language for the + # directory? + # Perhaps better solution: In scp it must be forbidden to have a language independent file in a language dependent directory. + + if (( ! $directoryname ) && ( $onelanguage eq "" )) + { + installer::exiter::exit_program("ERROR (in scp): Directory $searchgid is language dependent, but not $oneitemgid inside this directory", "get_Directoryname_From_Directorygid"); + } + + return \$directoryname; +} + +################################################################## +# Getting destination direcotory for links, files and profiles +################################################################## + +sub get_Destination_Directory_For_Item_From_Directorylist # this is used for Files, Profiles and Links +{ + my ($itemarrayref, $dirsarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::get_Destination_Directory_For_Item_From_Directorylist : $#{$itemarrayref} : $#{$dirsarrayref}"); } + + for ( my $i = 0; $i <= $#{$itemarrayref}; $i++ ) + { + my $oneitem = ${$itemarrayref}[$i]; + my $oneitemgid = $oneitem->{'gid'}; + my $directorygid = $oneitem->{'Dir'}; # for instance gid_Dir_Program + my $netdirectorygid = ""; + my $onelanguage = $oneitem->{'specificlanguage'}; + my $ispredefinedprogdir = 0; + my $ispredefinedconfigdir = 0; + + my $oneitemname = $oneitem->{'Name'}; + + if ( $oneitem->{'NetDir'} ) { $netdirectorygid = $oneitem->{'NetDir'}; } + + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$oneitemname); # making /registry/schema/org/openoffice/VCL.xcs to VCL.xcs + + my $searchdirgid; + + if ( $netdirectorygid eq "" ) # if NetDir is defined, it is privileged + { + $searchdirgid = $directorygid + } + else + { + $searchdirgid = $netdirectorygid + } + + if ($searchdirgid =~ /PREDEFINED_PROGDIR/) # the root directory is not defined in setup script + { + $ispredefinedprogdir = 1; + } + + if ($searchdirgid =~ /PREDEFINED_CONFIGDIR/) # the root directory is not defined in setup script + { + $ispredefinedconfigdir = 1; + } + + my $destfilename; + + if ((!( $ispredefinedprogdir )) && (!( $ispredefinedconfigdir ))) + { + my $directorynameref = get_Directoryname_From_Directorygid($dirsarrayref, $searchdirgid, $onelanguage, $oneitemgid); + $destfilename = $$directorynameref . $installer::globals::separator . $oneitemname; + } + else + { + $destfilename = $oneitemname; + } + + $oneitem->{'destination'} = $destfilename; + } +} + +########################################################################## +# Searching a file in a list of pathes +########################################################################## + +sub get_sourcepath_from_filename_and_includepath_classic +{ + my ($searchfilenameref, $includepatharrayref, $write_logfile) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::get_sourcepath_from_filename_and_includepath_classic : $$searchfilenameref : $#{$includepatharrayref} : $write_logfile"); } + + my ($onefile, $includepath, $infoline); + + my $foundsourcefile = 0; + + for ( my $j = 0; $j <= $#{$includepatharrayref}; $j++ ) + { + $includepath = ${$includepatharrayref}[$j]; + installer::remover::remove_leading_and_ending_whitespaces(\$includepath); + + $onefile = $includepath . $installer::globals::separator . $$searchfilenameref; + + if ( -f $onefile ) + { + $foundsourcefile = 1; + last; + } + } + + if (!($foundsourcefile)) + { + $onefile = ""; # the sourcepath has to be empty + if ( $write_logfile) + { + if ( $ENV{'DEFAULT_TO_ENGLISH_FOR_PACKING'} ) + { + $infoline = "WARNING: Source for $$searchfilenameref not found!\n"; # Important message in log file + } + else + { + $infoline = "ERROR: Source for $$searchfilenameref not found!\n"; # Important message in log file + } + + push( @installer::globals::logfileinfo, $infoline); + } + } + else + { + if ( $write_logfile) + { + $infoline = "SUCCESS: Source for $$searchfilenameref: $onefile\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + + return \$onefile; +} + +########################################################################## +# Input is one file name, output the complete absolute path of this file +########################################################################## + +sub get_sourcepath_from_filename_and_includepath +{ + my ($searchfilenameref, $unused, $write_logfile) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::get_sourcepath_from_filename_and_includepath : $$searchfilenameref : $#{$includepatharrayref} : $write_logfile"); } + + my ($onefile, $includepath, $infoline); + + my $foundsourcefile = 0; + my $foundnewname = 0; + + for ( my $j = 0; $j <= $#installer::globals::allincludepathes; $j++ ) + { + my $allfiles = $installer::globals::allincludepathes[$j]; + + if ( exists( $allfiles->{$$searchfilenameref} )) + { + $onefile = $allfiles->{'includepath'} . $installer::globals::separator . $$searchfilenameref; + $foundsourcefile = 1; + last; + } + } + + if (!($foundsourcefile)) # testing with lowercase filename + { + # Attention: README01.html is copied for Windows to readme01.html, not case sensitive + + for ( my $j = 0; $j <= $#installer::globals::allincludepathes; $j++ ) + { + my $allfiles = $installer::globals::allincludepathes[$j]; + + my $newfilename = $$searchfilenameref; + $newfilename =~ s/readme/README/; # special handling for readme files + $newfilename =~ s/license/LICENSE/; # special handling for license files + + if ( exists( $allfiles->{$newfilename} )) + { + $onefile = $allfiles->{'includepath'} . $installer::globals::separator . $newfilename; + $foundsourcefile = 1; + $foundnewname = 1; + last; + } + } + } + + if (!($foundsourcefile)) + { + $onefile = ""; # the sourcepath has to be empty + if ( $write_logfile) + { + if ( $ENV{'DEFAULT_TO_ENGLISH_FOR_PACKING'} ) + { + $infoline = "WARNING: Source for $$searchfilenameref not found!\n"; # Important message in log file + } + else + { + $infoline = "ERROR: Source for $$searchfilenameref not found!\n"; # Important message in log file + } + + push( @installer::globals::logfileinfo, $infoline); + } + } + else + { + if ( $write_logfile) + { + if (!($foundnewname)) + { + $infoline = "SUCCESS: Source for $$searchfilenameref: $onefile\n"; + } + else + { + $infoline = "SUCCESS/WARNING: Special handling for $$searchfilenameref: $onefile\n"; + } + push( @installer::globals::logfileinfo, $infoline); + } + } + + return \$onefile; +} + +############################################################## +# Determining, whether a specified directory is language +# dependent +############################################################## + +sub determine_directory_language_dependency +{ + my($directorygid, $dirsref) = @_; + + my $is_multilingual = 0; + + for ( my $i = 0; $i <= $#{$dirsref}; $i++ ) + { + my $onedir = ${$dirsref}[$i]; + my $gid = $onedir->{'gid'}; + + if ( $gid eq $directorygid ) + { + $is_multilingual = $onedir->{'ismultilingual'}; + last; + } + } + + return $is_multilingual; +} + +############################################################## +# Getting all source pathes for all files to be packed +# $item can be "Files" or "ScpActions" +############################################################## + +sub get_Source_Directory_For_Files_From_Includepathlist +{ + my ($filesarrayref, $includepatharrayref, $dirsref, $item) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::get_Source_Directory_For_Files_From_Includepathlist : $#{$filesarrayref} : $#{$includepatharrayref} : $item"); } + + installer::logger::include_header_into_logfile("$item:"); + + my $infoline = ""; + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + my $onelanguage = $onefile->{'specificlanguage'}; + + if ( ! $onefile->{'Name'} ) { installer::exiter::exit_program("ERROR: $item without name ! GID: $onefile->{'gid'} ! Language: $onelanguage", "get_Source_Directory_For_Files_From_Includepathlist"); } + + my $onefilename = $onefile->{'Name'}; + if ( $item eq "ScpActions" ) { $onefilename =~ s/\//$installer::globals::separator/g; } + $onefilename =~ s/^\s*\Q$installer::globals::separator\E//; # filename begins with a slash, for instance /registry/schema/org/openoffice/VCL.xcs + + my $styles = ""; + my $file_can_miss = 0; + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } + if (( $styles =~ /\bSTARREGISTRY\b/ ) || ( $styles =~ /\bFILE_CAN_MISS\b/ )) { $file_can_miss = 1; } + + my $sourcepathref = ""; + + if ( $file_can_miss ) { $sourcepathref = get_sourcepath_from_filename_and_includepath(\$onefilename, $includepatharrayref, 0); } + else { $sourcepathref = get_sourcepath_from_filename_and_includepath(\$onefilename, $includepatharrayref, 1); } + + $onefile->{'sourcepath'} = $$sourcepathref; # This $$sourcepathref is empty, if no source was found + + # defaulting to english for multilingual files if DEFAULT_TO_ENGLISH_FOR_PACKING is set + + if ( $ENV{'DEFAULT_TO_ENGLISH_FOR_PACKING'} ) + { + if (( ! $onefile->{'sourcepath'} ) && ( $onefile->{'ismultilingual'} )) + { + my $oldname = $onefile->{'Name'}; + my $oldlanguage = $onefile->{'specificlanguage'}; + my $newlanguage = "en-US"; + # $onefile->{'Name'} =~ s/$oldlanguage\./$newlanguage\./; # Example: tplwizfax_it.zip -> tplwizfax_en-US.zip + $onefilename = $onefile->{'Name'}; + $onefilename =~ s/$oldlanguage\./$newlanguage\./; # Example: tplwizfax_it.zip -> tplwizfax_en-US.zip + $onefilename =~ s/^\s*\Q$installer::globals::separator\E//; # filename begins with a slash, for instance /registry/schema/org/openoffice/VCL.xcs + $sourcepathref = get_sourcepath_from_filename_and_includepath(\$onefilename, $includepatharrayref, 1); + $onefile->{'sourcepath'} = $$sourcepathref; # This $$sourcepathref is empty, if no source was found + + if ($onefile->{'sourcepath'}) # defaulting to english was successful + { + $infoline = "WARNING: Using $onefilename instead of $oldname\n"; + push( @installer::globals::logfileinfo, $infoline); + print " $infoline"; + # if ( $onefile->{'destination'} ) { $onefile->{'destination'} =~ s/\Q$oldname\E/$onefile->{'Name'}/; } + + # If the directory, in which the new file is installed, is not language dependent, + # the filename has to be changed to avoid installation conflicts + # No mechanism for resource files! + # -> implementing for the content of ARCHIVE files + + if ( $onefile->{'Styles'} =~ /\bARCHIVE\b/ ) + { + my $directorygid = $onefile->{'Dir'}; + my $islanguagedependent = determine_directory_language_dependency($directorygid, $dirsref); + + if ( ! $islanguagedependent ) + { + $onefile->{'Styles'} =~ s/\bARCHIVE\b/ARCHIVE, RENAME_TO_LANGUAGE/; # Setting new flag RENAME_TO_LANGUAGE + $infoline = "Setting flag RENAME_TO_LANGUAGE: File $onefile->{'Name'} in directory: $directorygid\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + } + else + { + $infoline = "WARNING: Using $onefile->{'Name'} instead of $oldname was not successful\n"; + push( @installer::globals::logfileinfo, $infoline); + $onefile->{'Name'} = $oldname; # Switching back to old file name + } + } + } + } + + $infoline = "\n"; # empty line after listing of all files + push( @installer::globals::logfileinfo, $infoline); +} + +################################################################################# +# Removing files, that shall not be included into languagepacks +# (because of rpm conflicts) +################################################################################# + +sub remove_Files_For_Languagepacks +{ + my ($itemsarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_Files_For_Languagepacks : $#{$filesarrayref}"); } + + my $infoline; + + my @newitemsarray = (); + + for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ ) + { + my $oneitem = ${$itemsarrayref}[$i]; + my $gid = $oneitem->{'gid'}; + + # scp Todo: Remove asap after removal of old setup + + if (( $gid eq "gid_File_Extra_Fontunxpsprint" ) || + ( $gid eq "gid_File_Extra_Migration_Lang" )) + { + $infoline = "ATTENTION: Removing item $oneitem->{'gid'} from the installation set.\n"; + push( @installer::globals::logfileinfo, $infoline); + + next; + } + + push(@newitemsarray, $oneitem); + } + + return \@newitemsarray; +} + +################################################################################# +# Files, whose source directory is not found, are removed now (this is an ERROR) +################################################################################# + +sub remove_Files_Without_Sourcedirectory +{ + my ($filesarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_Files_Without_Sourcedirectory : $#{$filesarrayref}"); } + + my $infoline; + + my $error_occured = 0; + my @missingfiles = (); + push(@missingfiles, "ERROR: The following files could not be found: \n"); + + my @newfilesarray = (); + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + my $sourcepath = $onefile->{'sourcepath'}; + + if ($sourcepath eq "") + { + my $styles = $onefile->{'Styles'}; + + if ( ! ( $styles =~ /\bSTARREGISTRY\b/ )) # StarRegistry files will be created later + { + my $filename = $onefile->{'Name'}; + $infoline = "ERROR: Removing file $filename from file list.\n"; + push( @installer::globals::logfileinfo, $infoline); + + push(@missingfiles, "ERROR: File not found: $filename\n"); + $error_occured = 1; + + next; # removing this file from list, if sourcepath is empty + } + } + + push(@newfilesarray, $onefile); + } + + $infoline = "\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ( $error_occured ) + { + for ( my $i = 0; $i <= $#missingfiles; $i++ ) { print "$missingfiles[$i]"; } + installer::exiter::exit_program("ERROR: Missing files", "remove_Files_Without_Sourcedirectory"); + } + + return \@newfilesarray; +} + +############################################################################ +# License and Readme files in the default language have to be installed +# in the directory with flag OFFICEDIRECTORY. If this is not defined +# they have to be installed in the installation root. +############################################################################ + +sub get_office_directory_gid_and_hostname +{ + my ($dirsarrayref) = @_; + + my $foundofficedir = 0; + my $gid = ""; + my $hostname = ""; + + for ( my $i = 0; $i <= $#{$dirsarrayref}; $i++ ) + { + my $onedir = ${$dirsarrayref}[$i]; + if ( $onedir->{'Styles'} ) + { + my $styles = $onedir->{'Styles'}; + + if ( $styles =~ /\bOFFICEDIRECTORY\b/ ) + { + $foundofficedir = 1; + $gid = $onedir->{'gid'}; + $hostname = $onedir->{'HostName'}; + last; + } + } + } + + return ($foundofficedir, $gid, $hostname); +} + +############################################################################ +# License and Readme files in the default language have to be installed +# in the installation root (next to the program dir). This is in scp +# project done by a post install basic script +############################################################################ + +sub add_License_Files_into_Installdir +{ + my ($filesarrayref, $dirsarrayref, $languagesarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::add_License_Files_into_Installdir : $#{$filesarrayref} : $#{$languagesarrayref}"); } + + my $infoline; + + my @newfilesarray = (); + + my $defaultlanguage = installer::languages::get_default_language($languagesarrayref); + + my ($foundofficedir, $officedirectorygid, $officedirectoryhostname) = get_office_directory_gid_and_hostname($dirsarrayref); + + # copy all files from directory share/readme, that contain the default language in their name + # without default language into the installation root. This makes the settings of the correct + # file names superfluous. On the other hand this requires a dependency to the directory + # share/readme + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + my $destination = $onefile->{'destination'}; + my $styles = ""; + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } + + if ( ( $destination =~ /share\Q$installer::globals::separator\Ereadme\Q$installer::globals::separator\E(\w+?)_?$defaultlanguage\.?(\w*)\s*/ ) + || (( $styles =~ /\bROOTLICENSEFILE\b/ ) && ( $destination =~ /\Q$installer::globals::separator\E?(\w+?)_?$defaultlanguage\.?(\w*?)\s*$/ )) ) + { + my $filename = $1; + my $extension = $2; + + my $newfilename; + + if ( $extension eq "" ) { $newfilename = $filename; } + else { $newfilename = $filename . "\." . $extension; } + + my %newfile = (); + my $newfile = \%newfile; + + installer::converter::copy_item_object($onefile, $newfile); + + $newfile->{'gid'} = $onefile->{'gid'} . "_Copy"; + $newfile->{'Name'} = $newfilename; + $newfile->{'ismultilingual'} = "0"; + $newfile->{'specificlanguage'} = ""; + $newfile->{'haslanguagemodule'} = "0"; + + if ( $foundofficedir ) + { + $newfile->{'Dir'} = $officedirectorygid; + $newfile->{'destination'} = $officedirectoryhostname . $installer::globals::separator . $newfilename; + } + else + { + $newfile->{'Dir'} = "PREDEFINED_PROGDIR"; + $newfile->{'destination'} = $newfilename; + } + + # Also setting "modules=gid_Module_Root_Brand" (module with style: ROOT_BRAND_PACKAGE) + if ( $installer::globals::rootbrandpackageset ) + { + $newfile->{'modules'} = $installer::globals::rootbrandpackage; + } + + push(@newfilesarray, $newfile); + + $infoline = "New files: Adding file $newfilename for the installation root to the file list. Language: $defaultlanguage\n"; + push( @installer::globals::logfileinfo, $infoline); + + # Collecting license and readme file for the installation set + + push(@installer::globals::installsetfiles, $newfile); + $infoline = "New files: Adding file $newfilename to the file collector for the installation set. Language: $defaultlanguage\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + push(@newfilesarray, $onefile); + } + + return \@newfilesarray; +} + +############################################################################ +# Removing files with flag ONLY_ASIA_LANGUAGE, only if no asian +# language is part of the product. +# This special files are connected to the root module and are not +# included into a language pack (would lead to conflicts!). +# But this files shall only be included into the product, if the +# product contains at least one asian language. +############################################################################ + +sub remove_onlyasialanguage_files_from_productlists +{ + my ($filesarrayref) = @_; + + my $infoline; + + my @newfilesarray = (); + my $returnfilesarrayref; + + my $containsasianlanguage = installer::languages::detect_asian_language($installer::globals::alllanguagesinproductarrayref); + + my $alllangstring = installer::converter::convert_array_to_comma_separated_string($installer::globals::alllanguagesinproductarrayref); + $infoline = "\nLanguages in complete product: $alllangstring\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ( ! $containsasianlanguage ) + { + $infoline = "Product does not contain asian language -> removing files\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + my $styles = ""; + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } + if ( $styles =~ /\bONLY_ASIA_LANGUAGE\b/ ) + { + $infoline = "Flag ONLY_ASIA_LANGUAGE: Removing file $onefile->{'Name'} from files collector!\n"; + push( @installer::globals::logfileinfo, $infoline); + next; + } + + push(@newfilesarray, $onefile); + } + + $returnfilesarrayref = \@newfilesarray; + } + else + { + $returnfilesarrayref = $filesarrayref; + + $infoline = "Product contains asian language -> Nothing to do\n"; + push( @installer::globals::logfileinfo, $infoline); + + } + + return $returnfilesarrayref; +} + +############################################################################ +# Removing files with flag ONLY_WESTERN_LANGUAGE, only if no western +# language is part of the product. +# This special files are connected to the root module and are not +# included into a language pack (would lead to conflicts!). +# But this files shall only be included into the product, if the +# product contains at least one western language. +############################################################################ + +sub remove_onlywesternlanguage_files_from_productlists +{ + my ($filesarrayref) = @_; + + my $infoline; + + my @newfilesarray = (); + my $returnfilesarrayref; + + my $containswesternlanguage = installer::languages::detect_western_language($installer::globals::alllanguagesinproductarrayref); + + my $alllangstring = installer::converter::convert_array_to_comma_separated_string($installer::globals::alllanguagesinproductarrayref); + $infoline = "\nLanguages in complete product: $alllangstring\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ( ! $containswesternlanguage ) + { + $infoline = "Product does not contain western language -> removing files\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + my $styles = ""; + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } + if ( $styles =~ /\bONLY_WESTERN_LANGUAGE\b/ ) + { + $infoline = "Flag ONLY_WESTERN_LANGUAGE: Removing file $onefile->{'Name'} from files collector!\n"; + push( @installer::globals::logfileinfo, $infoline); + next; + } + + push(@newfilesarray, $onefile); + } + + $returnfilesarrayref = \@newfilesarray; + } + else + { + $returnfilesarrayref = $filesarrayref; + + $infoline = "Product contains western language -> Nothing to do\n"; + push( @installer::globals::logfileinfo, $infoline); + + } + + return $returnfilesarrayref; +} + +############################################################################ +# Some files are included for more than one language and have the same +# name and the same destination directory for all languages. This would +# lead to conflicts, if the filenames are not changed. +# In scp project this files must have the flag MAKE_LANG_SPECIFIC +# For this files, the language is included into the filename. +############################################################################ + +sub make_filename_language_specific +{ + my ($filesarrayref) = @_; + + my $infoline = ""; + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + + if ( $onefile->{'ismultilingual'} ) + { + my $styles = ""; + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } + if ( $styles =~ /\bMAKE_LANG_SPECIFIC\b/ ) + { + my $language = $onefile->{'specificlanguage'}; + my $olddestination = $onefile->{'destination'}; + my $oldname = $onefile->{'Name'}; + + # Including the language into the file name. + # But be sure, to include the language before the file extension. + + my $fileextension = ""; + + if ( $onefile->{'Name'} =~ /(\.\w+?)\s*$/ ) { $fileextension = $1; } + if ( $fileextension ne "" ) + { + $onefile->{'Name'} =~ s/\Q$fileextension\E\s*$/_$language$fileextension/; + $onefile->{'destination'} =~ s/\Q$fileextension\E\s*$/_$language$fileextension/; + } + + $infoline = "Flag MAKE_LANG_SPECIFIC:\n"; + push( @installer::globals::logfileinfo, $infoline); + $infoline = "Changing name from $oldname to $onefile->{'Name'} !\n"; + push( @installer::globals::logfileinfo, $infoline); + $infoline = "Changing destination from $olddestination to $onefile->{'destination'} !\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + } +} + +############################################################################ +# Removing all scpactions, that have no name. +# See: FlatLoaderZip +############################################################################ + +sub remove_scpactions_without_name +{ + my ($itemsarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_scpactions_without_name : $#{$itemsarrayref}"); } + + my $infoline; + + my @newitemsarray = (); + + for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ ) + { + my $oneitem = ${$itemsarrayref}[$i]; + my $name = ""; + + if ( $oneitem->{'Name'} ) { $name = $oneitem->{'Name'}; } + + if ( $name eq "" ) + { + $infoline = "ATTENTION: Removing scpaction $oneitem->{'gid'} from the installation set.\n"; + push( @installer::globals::logfileinfo, $infoline); + next; + } + + push(@newitemsarray, $oneitem); + } + + return \@newitemsarray; +} + +############################################################################ +# Because of the item "File" the source name must be "Name". Therefore +# "Copy" is changed to "Name" and "Name" is changed to "DestinationName". +############################################################################ + +sub change_keys_of_scpactions +{ + my ($itemsarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::change_keys_of_scpactions : $#{$itemsarrayref}"); } + + for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ ) + { + my $oneitem = ${$itemsarrayref}[$i]; + + my $key; + + # First Name to DestinationName, then deleting Name + foreach $key (keys %{$oneitem}) + { + if ( $key =~ /\bName\b/ ) + { + my $value = $oneitem->{$key}; + my $oldkey = $key; + $key =~ s/Name/DestinationName/; + $oneitem->{$key} = $value; + delete($oneitem->{$oldkey}); + } + } + + # Second Copy to Name, then deleting Copy + foreach $key (keys %{$oneitem}) + { + if ( $key =~ /\bCopy\b/ ) + { + my $value = $oneitem->{$key}; + my $oldkey = $key; + $key =~ s/Copy/Name/; + $oneitem->{$key} = $value; + delete($oneitem->{$oldkey}); + } + } + } +} + +############################################################################ +# Removing all xpd only items from installation set (scpactions with +# the style XPD_ONLY), except an xpd installation set is created +############################################################################ + +sub remove_Xpdonly_Items +{ + my ($itemsarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_Xpdonly_Items : $#{$itemsarrayref}"); } + + my $infoline; + + my @newitemsarray = (); + + for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ ) + { + my $oneitem = ${$itemsarrayref}[$i]; + my $styles = ""; + if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; } + + if ( $styles =~ /\bXPD_ONLY\b/ ) + { + $infoline = "Removing \"xpd only\" item $oneitem->{'gid'} from the installation set.\n"; + push( @installer::globals::globallogfileinfo, $infoline); + + next; + } + + push(@newitemsarray, $oneitem); + } + + $infoline = "\n"; + push( @installer::globals::globallogfileinfo, $infoline); + + return \@newitemsarray; +} + +############################################################################ +# Removing all language pack files from installation set (files with +# the style LANGUAGEPACK), except this is a language pack. +############################################################################ + +sub remove_Languagepacklibraries_from_Installset +{ + my ($itemsarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_Languagepacklibraries_from_Installset : $#{$itemsarrayref}"); } + + my $infoline; + + my @newitemsarray = (); + + for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ ) + { + my $oneitem = ${$itemsarrayref}[$i]; + my $styles = ""; + if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; } + + if ( $styles =~ /\bLANGUAGEPACK\b/ ) + { + $infoline = "Removing language pack file $oneitem->{'gid'} from the installation set.\n"; + push( @installer::globals::globallogfileinfo, $infoline); + + next; + } + + push(@newitemsarray, $oneitem); + } + + $infoline = "\n"; + push( @installer::globals::globallogfileinfo, $infoline); + + return \@newitemsarray; +} + +############################################################################ +# Removing all files with flag PATCH_ONLY from installation set. +# This function is not called during patch creation. +############################################################################ + +sub remove_patchonlyfiles_from_Installset +{ + my ($itemsarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_patchonlyfiles_from_Installset : $#{$itemsarrayref}"); } + + my $infoline; + + my @newitemsarray = (); + + for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ ) + { + my $oneitem = ${$itemsarrayref}[$i]; + my $styles = ""; + if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; } + + if ( $styles =~ /\bPATCH_ONLY\b/ ) + { + $infoline = "Removing file with flag PATCH_ONLY $oneitem->{'gid'} from the installation set.\n"; + push( @installer::globals::globallogfileinfo, $infoline); + + next; + } + + push(@newitemsarray, $oneitem); + } + + $infoline = "\n"; + push( @installer::globals::globallogfileinfo, $infoline); + + return \@newitemsarray; +} + +############################################################################ +# Removing all files with flag TAB_ONLY from installation set. +# This function is not called during tab creation. +############################################################################ + +sub remove_tabonlyfiles_from_Installset +{ + my ($itemsarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_tabonlyfiles_from_Installset : $#{$itemsarrayref}"); } + + my $infoline; + + my @newitemsarray = (); + + for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ ) + { + my $oneitem = ${$itemsarrayref}[$i]; + my $styles = ""; + if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; } + + if ( $styles =~ /\bTAB_ONLY\b/ ) + { + $infoline = "Removing tab only file $oneitem->{'gid'} from the installation set.\n"; + push( @installer::globals::globallogfileinfo, $infoline); + + next; + } + + push(@newitemsarray, $oneitem); + } + + $infoline = "\n"; + push( @installer::globals::globallogfileinfo, $infoline); + + return \@newitemsarray; +} + +############################################################################### +# Removing all files with flag ONLY_INSTALLED_PRODUCT from installation set. +# This function is not called for PKGFORMAT installed and archive. +############################################################################### + +sub remove_installedproductonlyfiles_from_Installset +{ + my ($itemsarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_installedproductonlyfiles_from_Installset : $#{$itemsarrayref}"); } + + my $infoline; + + my @newitemsarray = (); + + for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ ) + { + my $oneitem = ${$itemsarrayref}[$i]; + my $styles = ""; + if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; } + + if ( $styles =~ /\bONLY_INSTALLED_PRODUCT\b/ ) + { + $infoline = "Removing file $oneitem->{'gid'} from the installation set. This file is only required for PKGFORMAT archive or installed).\n"; + push( @installer::globals::globallogfileinfo, $infoline); + next; + } + + push(@newitemsarray, $oneitem); + } + + $infoline = "\n"; + push( @installer::globals::globallogfileinfo, $infoline); + + return \@newitemsarray; +} + +############################################################################ +# Some files cotain a $ in their name. epm conflicts with such files. +# Solution: Renaming this files, converting "$" to "$$" +############################################################################ + +sub quoting_illegal_filenames +{ + my ($filesarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::rename_illegal_filenames : $#{$filesarrayref}"); } + + # This function has to be removed as soon as possible! + + installer::logger::include_header_into_logfile("Renaming illegal filenames:"); + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + my $filename = $onefile->{'Name'}; + + if ( $filename =~ /\$/ ) + { + my $sourcepath = $onefile->{'sourcepath'}; + my $destpath = $onefile->{'destination'}; + + # sourcepath and destination have to be quoted for epm list file + + # $filename =~ s/\$/\$\$/g; + $destpath =~ s/\$/\$\$/g; + $sourcepath =~ s/\$/\$\$/g; + + # my $infoline = "ATTENTION: Files: Renaming $onefile->{'Name'} to $filename\n"; + # push( @installer::globals::logfileinfo, $infoline); + my $infoline = "ATTENTION: Files: Quoting sourcepath $onefile->{'sourcepath'} to $sourcepath\n"; + push( @installer::globals::logfileinfo, $infoline); + $infoline = "ATTENTION: Files: Quoting destination path $onefile->{'destination'} to $destpath\n"; + push( @installer::globals::logfileinfo, $infoline); + + # $onefile->{'Name'} = $filename; + $onefile->{'sourcepath'} = $sourcepath; + $onefile->{'destination'} = $destpath; + } + } +} + +############################################################################ +# Removing multiple occurences of same module. +############################################################################ + +sub optimize_list +{ + my ( $longlist ) = @_; + + my $shortlist = ""; + my $hashref = installer::converter::convert_stringlist_into_hash(\$longlist, ","); + foreach my $key (sort keys %{$hashref} ) { $shortlist = "$shortlist,$key"; } + $shortlist =~ s/^\s*\,//; + + return $shortlist; +} + +####################################################################### +# Collecting all directories needed for the epm list +# 1. Looking for all destination paths in the files array +# 2. Looking for directories with CREATE flag in the directory array +####################################################################### + +################################## +# Collecting directories: Part 1 +################################## + +sub collect_directories_from_filesarray +{ + my ($filesarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::collect_directories_from_filesarray : $#{$filesarrayref}"); } + + my @alldirectories = (); + my %alldirectoryhash = (); + + my $predefinedprogdir_added = 0; + my $alreadyincluded = 0; + + # Preparing this already as hash, although the only needed value at the moment is the HostName + # But also adding: "specificlanguage" and "Dir" (for instance gid_Dir_Program) + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + my $destinationpath = $onefile->{'destination'}; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$destinationpath); + $destinationpath =~ s/\Q$installer::globals::separator\E\s*$//; # removing ending slashes or backslashes + + $alreadyincluded = 0; + if ( exists($alldirectoryhash{$destinationpath}) ) { $alreadyincluded = 1; } + + if (!($alreadyincluded)) + { + my %directoryhash = (); + $directoryhash{'HostName'} = $destinationpath; + $directoryhash{'specificlanguage'} = $onefile->{'specificlanguage'}; + $directoryhash{'Dir'} = $onefile->{'Dir'}; + $directoryhash{'modules'} = $onefile->{'modules'}; # NEW, saving modules + # NEVER!!! if ( ! $installer::globals::iswindowsbuild ) { $directoryhash{'Styles'} = "(CREATE)"; } # this directories must be created + + if ( $onefile->{'Dir'} eq "PREDEFINED_PROGDIR" ) { $predefinedprogdir_added = 1; } + + $alldirectoryhash{$destinationpath} = \%directoryhash; + + # Problem: The $destinationpath can be share/registry/schema/org/openoffice + # but not all directories contain files and will be added to this list. + # Therefore the path has to be analyzed. + + while ( $destinationpath =~ /(^.*\S)\Q$installer::globals::separator\E(\S.*?)\s*$/ ) # as long as the path contains slashes + { + $destinationpath = $1; + + $alreadyincluded = 0; + if ( exists($alldirectoryhash{$destinationpath}) ) { $alreadyincluded = 1; } + + if (!($alreadyincluded)) + { + my %directoryhash = (); + + $directoryhash{'HostName'} = $destinationpath; + $directoryhash{'specificlanguage'} = $onefile->{'specificlanguage'}; + $directoryhash{'Dir'} = $onefile->{'Dir'}; + $directoryhash{'modules'} = $onefile->{'modules'}; # NEW, saving modules + # NEVER!!! if ( ! $installer::globals::iswindowsbuild ) { $directoryhash{'Styles'} = "(CREATE)"; } # this directories must be created + + $alldirectoryhash{$destinationpath} = \%directoryhash; + } + else + { + # Adding the modules to the module list! + $alldirectoryhash{$destinationpath}->{'modules'} = $alldirectoryhash{$destinationpath}->{'modules'} . "," . $onefile->{'modules'}; + } + } + } + else + { + # Adding the modules to the module list! + $alldirectoryhash{$destinationpath}->{'modules'} = $alldirectoryhash{$destinationpath}->{'modules'} . "," . $onefile->{'modules'}; + + # Also adding the module to all parents + while ( $destinationpath =~ /(^.*\S)\Q$installer::globals::separator\E(\S.*?)\s*$/ ) # as long as the path contains slashes + { + $destinationpath = $1; + $alldirectoryhash{$destinationpath}->{'modules'} = $alldirectoryhash{$destinationpath}->{'modules'} . "," . $onefile->{'modules'}; + } + } + } + + # if there is no file in the root directory PREDEFINED_PROGDIR, it has to be included into the directory array now + # HostName= specificlanguage= Dir=PREDEFINED_PROGDIR + + if (! $predefinedprogdir_added ) + { + my %directoryhash = (); + $directoryhash{'HostName'} = ""; + $directoryhash{'specificlanguage'} = ""; + $directoryhash{'modules'} = ""; # ToDo? + $directoryhash{'Dir'} = "PREDEFINED_PROGDIR"; + + push(@alldirectories, \%directoryhash); + } + + # Creating directory array + foreach my $destdir ( sort keys %alldirectoryhash ) + { + $alldirectoryhash{$destdir}->{'modules'} = optimize_list($alldirectoryhash{$destdir}->{'modules'}); + push(@alldirectories, $alldirectoryhash{$destdir}); + } + + return (\@alldirectories, \%alldirectoryhash); +} + +################################## +# Collecting directories: Part 2 +################################## + +sub collect_directories_with_create_flag_from_directoryarray +{ + my ($directoryarrayref, $alldirectoryhash) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::collect_directories_with_create_flag_from_directoryarray : $#{$directoryarrayref}"); } + + my $alreadyincluded = 0; + my @alldirectories = (); + + for ( my $i = 0; $i <= $#{$directoryarrayref}; $i++ ) + { + my $onedir = ${$directoryarrayref}[$i]; + my $styles = ""; + $newdirincluded = 0; + + if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; } + + if ( $styles =~ /\bCREATE\b/ ) + { + my $directoryname = ""; + + if ( $onedir->{'HostName'} ) { $directoryname = $onedir->{'HostName'}; } + else { installer::exiter::exit_program("ERROR: No directory name (HostName) set for specified language in gid $onedir->{'gid'}", "collect_directories_with_create_flag_from_directoryarray"); } + + $alreadyincluded = 0; + if ( exists($alldirectoryhash->{$directoryname}) ) { $alreadyincluded = 1; } + + if (!($alreadyincluded)) + { + my %directoryhash = (); + $directoryhash{'HostName'} = $directoryname; + $directoryhash{'specificlanguage'} = $onedir->{'specificlanguage'}; + # $directoryhash{'gid'} = $onedir->{'gid'}; + $directoryhash{'Dir'} = $onedir->{'gid'}; + $directoryhash{'Styles'} = $onedir->{'Styles'}; + + # saving also the modules + if ( ! $onedir->{'modules'} ) { installer::exiter::exit_program("ERROR: No assigned modules found for directory $onedir->{'gid'}", "collect_directories_with_create_flag_from_directoryarray"); } + $directoryhash{'modules'} = $onedir->{'modules'}; + + $alldirectoryhash->{$directoryname} = \%directoryhash; + $newdirincluded = 1; + + # Problem: The $destinationpath can be share/registry/schema/org/openoffice + # but not all directories contain files and will be added to this list. + # Therefore the path has to be analyzed. + + while ( $directoryname =~ /(^.*\S)\Q$installer::globals::separator\E(\S.*?)\s*$/ ) # as long as the path contains slashes + { + $directoryname = $1; + + $alreadyincluded = 0; + if ( exists($alldirectoryhash->{$directoryname}) ) { $alreadyincluded = 1; } + + if (!($alreadyincluded)) + { + my %directoryhash = (); + + $directoryhash{'HostName'} = $directoryname; + $directoryhash{'specificlanguage'} = $onedir->{'specificlanguage'}; + $directoryhash{'Dir'} = $onedir->{'gid'}; + if ( ! $installer::globals::iswindowsbuild ) { $directoryhash{'Styles'} = "(CREATE)"; } # Exeception for Windows? + + # saving also the modules + $directoryhash{'modules'} = $onedir->{'modules'}; + + $alldirectoryhash->{$directoryname} = \%directoryhash; + $newdirincluded = 1; + } + else + { + # Adding the modules to the module list! + $alldirectoryhash->{$directoryname}->{'modules'} = $alldirectoryhash->{$directoryname}->{'modules'} . "," . $onedir->{'modules'}; + } + } + } + else + { + # Adding the modules to the module list! + $alldirectoryhash->{$directoryname}->{'modules'} = $alldirectoryhash->{$directoryname}->{'modules'} . "," . $onedir->{'modules'}; + + while ( $directoryname =~ /(^.*\S)\Q$installer::globals::separator\E(\S.*?)\s*$/ ) # as long as the path contains slashes + { + $directoryname = $1; + # Adding the modules to the module list! + $alldirectoryhash->{$directoryname}->{'modules'} = $alldirectoryhash->{$directoryname}->{'modules'} . "," . $onedir->{'modules'}; + } + } + } + + # Saving the styles for already added directories in function collect_directories_from_filesarray + + if (( ! $newdirincluded ) && ( $styles ne "" )) + { + $styles =~ s/\bWORKSTATION\b//; + $styles =~ s/\bCREATE\b//; + + if (( ! ( $styles =~ /^\s*\(\s*\)\s*$/ )) && ( ! ( $styles =~ /^\s*\(\s*\,\s*\)\s*$/ )) && ( ! ( $styles =~ /^\s*$/ ))) # checking, if there are styles left + { + my $directoryname = ""; + if ( $onedir->{'HostName'} ) { $directoryname = $onedir->{'HostName'}; } + else { installer::exiter::exit_program("ERROR: No directory name (HostName) set for specified language in gid $onedir->{'gid'}", "collect_directories_with_create_flag_from_directoryarray"); } + + if ( exists($alldirectoryhash->{$directoryname}) ) + { + $alldirectoryhash->{$directoryname}->{'Styles'} = $styles; + } + } + } + } + + # Creating directory array + foreach my $destdir ( sort keys %{$alldirectoryhash} ) + { + $alldirectoryhash->{$destdir}->{'modules'} = optimize_list($alldirectoryhash->{$destdir}->{'modules'}); + push(@alldirectories, $alldirectoryhash->{$destdir}); + } + + return (\@alldirectories, \%alldirectoryhash); +} + +################################################# +# Determining the destination file of a link +################################################# + +sub get_destination_file_path_for_links +{ + my ($linksarrayref, $filesarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::get_destination_file_path_for_links : $#{$linksarrayref} : $#{$filesarrayref}"); } + + my $infoline; + + for ( my $i = 0; $i <= $#{$linksarrayref}; $i++ ) + { + my $fileid = ""; + my $onelink = ${$linksarrayref}[$i]; + if ( $onelink->{'FileID'} ) { $fileid = $onelink->{'FileID'}; } + + if (!( $fileid eq "" )) + { + my $foundfile = 0; + + for ( my $j = 0; $j <= $#{$filesarrayref}; $j++ ) + { + my $onefile = ${$filesarrayref}[$j]; + my $filegid = $onefile->{'gid'}; + + if ( $filegid eq $fileid ) + { + $foundfile = 1; + $onelink->{'destinationfile'} = $onefile->{'destination'}; + last; + } + } + + if (!($foundfile)) + { + $infoline = "Warning: FileID $fileid for Link $onelink->{'gid'} not found!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + } + + $infoline = "\n"; + push( @installer::globals::logfileinfo, $infoline); +} + +################################################# +# Determining the destination link of a link +################################################# + +sub get_destination_link_path_for_links +{ + my ($linksarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::get_destination_link_path_for_links : $#{$linksarrayref}"); } + + my $infoline; + + for ( my $i = 0; $i <= $#{$linksarrayref}; $i++ ) + { + my $shortcutid = ""; + my $onelink = ${$linksarrayref}[$i]; + if ( $onelink->{'ShortcutID'} ) { $shortcutid = $onelink->{'ShortcutID'}; } + + if (!( $shortcutid eq "" )) + { + my $foundlink = 0; + + for ( my $j = 0; $j <= $#{$linksarrayref}; $j++ ) + { + my $destlink = ${$linksarrayref}[$j]; + $shortcutgid = $destlink->{'gid'}; + + if ( $shortcutgid eq $shortcutid ) + { + $foundlink = 1; + $onelink->{'destinationfile'} = $destlink->{'destination'}; # making key 'destinationfile' + last; + } + } + + if (!($foundlink)) + { + $infoline = "Warning: ShortcutID $shortcutid for Link $onelink->{'gid'} not found!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + } + + $infoline = "\n"; + push( @installer::globals::logfileinfo, $infoline); +} + +################################################################################### +# Items with flag WORKSTATION are not needed (here: links and configurationitems) +################################################################################### + +sub remove_workstation_only_items +{ + my ($itemarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_workstation_only_items : $#{$itemarrayref}"); } + + my @newitemarray = (); + + for ( my $i = 0; $i <= $#{$itemarrayref}; $i++ ) + { + my $oneitem = ${$itemarrayref}[$i]; + my $styles = $oneitem->{'Styles'}; + + if (( $styles =~ /\bWORKSTATION\b/ ) && + (!( $styles =~ /\bNETWORK\b/ )) && + (!( $styles =~ /\bSTANDALONE\b/ ))) + { + next; # removing this link, it is only needed for a workstation installation + } + + push(@newitemarray, $oneitem); + } + + return \@newitemarray; +} + +################################################ +# Resolving relative path in links +################################################ + +sub resolve_links_with_flag_relative +{ + my ($linksarrayref) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::resolve_links_with_flag_relative : $#{$linksarrayref}"); } + + # Before this step is: + # destination=program/libsalhelperC52.so.3, this will be the name of the link + # destinationfile=program/libsalhelperC52.so.3, this will be the linked file or name + # If the flag RELATIVE is set, the pathes have to be analyzed. If the flag is not set + # (this will not occur in the future?) destinationfile has to be an absolute path name + + for ( my $i = 0; $i <= $#{$linksarrayref}; $i++ ) + { + my $onelink = ${$linksarrayref}[$i]; + my $styles = $onelink->{'Styles'}; + + if ( $styles =~ /\bRELATIVE\b/ ) + { + # ToDo: This is only a simple not sufficient mechanism + + my $destination = $onelink->{'destination'}; + my $destinationfile = $onelink->{'destinationfile'}; + + my $destinationpath = $destination; + + installer::pathanalyzer::get_path_from_fullqualifiedname(\$destinationpath); + + my $destinationfilepath = $destinationfile; + + # it is possible, that the destinationfile is no longer part of the files collector + if ($destinationfilepath) { installer::pathanalyzer::get_path_from_fullqualifiedname(\$destinationfilepath); } + else { $destinationfilepath = ""; } + + if ( $destinationpath eq $destinationfilepath ) + { + # link and file are in the same directory + # Therefore the path of the file can be removed + + my $newdestinationfile = $destinationfile; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$newdestinationfile); + + $onelink->{'destinationfile'} = $newdestinationfile; + } + } + } +} + +######################################################################## +# This function is a helper of function "assigning_modules_to_items" +######################################################################## + +sub insert_for_item ($$$) +{ + my ($hash, $item, $id) = @_; + + # print STDERR "insert '$id' for '$item'\n"; + if (!defined $hash->{$item}) + { + my @gids = (); + $hash->{$item} = \@gids; + } + my $gid_list = $hash->{$item}; + push @{$gid_list}, $id; + $hash->{$item} = $gid_list; +} + +sub build_modulegids_table +{ + my ($modulesref, $itemname) = @_; + + my %module_lookup_table = (); + + # build map of item names to list of respective module gids + # containing these items + for my $onemodule (@{$modulesref}) + { + next if ( ! defined $onemodule->{$itemname} ); + # these are the items contained in this module + # eg. Files = (gid_a_b_c,gid_d_e_f) + my $module_gids = $onemodule->{$itemname}; + + # prune outer brackets + $module_gids =~ s|^\s*\(||g; + $module_gids =~ s|\)\s*$||g; + for my $id (split (/,/, $module_gids)) + { + chomp $id; + insert_for_item(\%module_lookup_table, lc ($id), $onemodule->{'gid'}); + } + } + + return \%module_lookup_table; +} + +######################################################################## +# Items like files do not know their modules +# This function is a helper of function "assigning_modules_to_items" +######################################################################## + +sub get_string_of_modulegids_for_itemgid +{ + my ($module_lookup_table, $modulesref, $itemgid, $itemname) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::get_string_of_modulegids_for_itemgid : $#{$modulesref} : $itemgid : $itemname"); } + + my $allmodules = ""; + my $haslanguagemodule = 0; + my %foundmodules = (); + + # print STDERR "lookup '" . lc($itemgid) . "'\n"; + my $gid_list = $module_lookup_table->{lc($itemgid)}; + + for my $gid (@{$gid_list}) + { + $foundmodules{$gid} = 1; + $allmodules = $allmodules . "," . $gid; + # Is this module a language module? This info should be stored at the file. + if ( exists($installer::globals::alllangmodules{$gid}) ) { $haslanguagemodule = 1; } + } + + $allmodules =~ s/^\s*\,//; # removing leading comma + + # Check: All modules or no module must have flag LANGUAGEMODULE + if ( $haslanguagemodule ) + { + my $isreallylanguagemodule = installer::worker::key_in_a_is_also_key_in_b(\%foundmodules, \%installer::globals::alllangmodules); + if ( ! $isreallylanguagemodule ) { installer::exiter::exit_program("ERROR: \"$itemgid\" is assigned to modules with flag \"LANGUAGEMODULE\" and also to modules without this flag! Modules: $allmodules", "get_string_of_modulegids_for_itemgid"); } + } + + # print STDERR "get_string_for_itemgid ($itemgid, $itemname) => $allmodules, $haslanguagemodule\n"; + + return ($allmodules, $haslanguagemodule); +} + +######################################################## +# Items like files do not know their modules +# This function add the {'modules'} to these items +######################################################## + +sub assigning_modules_to_items +{ + my ($modulesref, $itemsref, $itemname) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::assigning_modules_to_items : $#{$modulesref} : $#{$itemsref} : $itemname"); } + + my $infoline = ""; + my $languageassignmenterror = 0; + my @languageassignmenterrors = (); + + my $module_lookup_table = build_modulegids_table($modulesref, $itemname); + + for my $oneitem (@{$itemsref}) + { + my $itemgid = $oneitem->{'gid'}; + + my $styles = ""; + if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; } + if (( $itemname eq "Dirs" ) && ( ! ( $styles =~ /\bCREATE\b/ ))) { next; } + + if ( $itemgid eq "" ) + { + installer::exiter::exit_program("ERROR in item collection: No gid for item $oneitem->{'Name'}", "assigning_modules_to_items"); + } + + # every item can belong to many modules + + my ($modulegids, $haslanguagemodule) = get_string_of_modulegids_for_itemgid($module_lookup_table, $modulesref, $itemgid, $itemname); + + if ($modulegids eq "") + { + installer::exiter::exit_program("ERROR in file collection: No module found for $itemname $itemgid", "assigning_modules_to_items"); + } + + $oneitem->{'modules'} = $modulegids; + $oneitem->{'haslanguagemodule'} = $haslanguagemodule; + + # Important check: "ismultilingual" and "haslanguagemodule" must have the same value ! + if (( $oneitem->{'ismultilingual'} ) && ( ! $oneitem->{'haslanguagemodule'} )) + { + $infoline = "Error: \"$oneitem->{'gid'}\" is multi lingual, but not in language pack (Assigned module: $modulegids)!\n"; + push( @installer::globals::globallogfileinfo, $infoline); + push( @languageassignmenterrors, $infoline ); + $languageassignmenterror = 1; + } + if (( $oneitem->{'haslanguagemodule'} ) && ( ! $oneitem->{'ismultilingual'} )) + { + $infoline = "Error: \"$oneitem->{'gid'}\" is in language pack, but not multi lingual (Assigned module: $modulegids)!\n"; + push( @installer::globals::globallogfileinfo, $infoline); + push( @languageassignmenterrors, $infoline ); + $languageassignmenterror = 1; + } + } + + if ($languageassignmenterror) + { + for ( my $i = 0; $i <= $#languageassignmenterrors; $i++ ) { print "$languageassignmenterrors[$i]"; } + installer::exiter::exit_program("ERROR: Incorrect assignments for language packs.", "assigning_modules_to_items"); + } + +} + +################################################################################################# +# Root path (for instance /opt/openofficeorg20) needs to be added to directories, files and links +################################################################################################# + +sub add_rootpath_to_directories +{ + my ($dirsref, $rootpath) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::add_rootpath_to_directories : $#{$dirsref} : $rootpath"); } + + for ( my $i = 0; $i <= $#{$dirsref}; $i++ ) + { + my $onedir = ${$dirsref}[$i]; + my $dir = ""; + + if ( $onedir->{'Dir'} ) { $dir = $onedir->{'Dir'}; } + + if (!($dir =~ /\bPREDEFINED_/ )) + { + my $hostname = $onedir->{'HostName'}; + $hostname = $rootpath . $installer::globals::separator . $hostname; + $onedir->{'HostName'} = $hostname; + } + + # added + + if ( $dir =~ /\bPREDEFINED_PROGDIR\b/ ) + { + my $hostname = $onedir->{'HostName'}; + if ( $hostname eq "" ) { $onedir->{'HostName'} = $rootpath; } + else { $onedir->{'HostName'} = $rootpath . $installer::globals::separator . $hostname; } + } + } +} + +sub add_rootpath_to_files +{ + my ($filesref, $rootpath) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::add_rootpath_to_files : $#{$filesref} : $rootpath"); } + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + my $destination = $onefile->{'destination'}; + $destination = $rootpath . $installer::globals::separator . $destination; + $onefile->{'destination'} = $destination; + } +} + +sub add_rootpath_to_links +{ + my ($linksref, $rootpath) = @_; + + if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::add_rootpath_to_links : $#{$linksref} : $rootpath"); } + + for ( my $i = 0; $i <= $#{$linksref}; $i++ ) + { + my $onelink = ${$linksref}[$i]; + my $styles = $onelink->{'Styles'}; + + my $destination = $onelink->{'destination'}; + $destination = $rootpath . $installer::globals::separator . $destination; + $onelink->{'destination'} = $destination; + + if (!($styles =~ /\bRELATIVE\b/ )) # for absolute links + { + my $destinationfile = $onelink->{'destinationfile'}; + $destinationfile = $rootpath . $installer::globals::separator . $destinationfile; + $onelink->{'destinationfile'} = $destinationfile; + } + } +} + +################################################################################# +# Collecting all parent gids +################################################################################# + +sub collect_all_parent_feature +{ + my ($modulesref) = @_; + + my @allparents = (); + + my $found_root_module = 0; + + for ( my $i = 0; $i <= $#{$modulesref}; $i++ ) + { + my $onefeature = ${$modulesref}[$i]; + + my $parentgid = ""; + if ( $onefeature->{'ParentID'} ) + { + $parentgid = $onefeature->{'ParentID'}; + } + + if ( $parentgid ne "" ) + { + if (! installer::existence::exists_in_array($parentgid, \@allparents)) + { + push(@allparents, $parentgid); + } + } + + # Setting the global root module + + if ( $parentgid eq "" ) + { + if ( $found_root_module ) { installer::exiter::exit_program("ERROR: Only one module without ParentID or with empty ParentID allowed ($installer::globals::rootmodulegid, $onefeature->{'gid'}).", "collect_all_parent_feature"); } + $installer::globals::rootmodulegid = $onefeature->{'gid'}; + $found_root_module = 1; + $infoline = "Setting Root Module: $installer::globals::rootmodulegid\n"; + push( @installer::globals::globallogfileinfo, $infoline); + } + + if ( ! $found_root_module ) { installer::exiter::exit_program("ERROR: Could not define root module. No module without ParentID or with empty ParentID exists.", "collect_all_parent_feature"); } + + } + + return \@allparents; +} + +################################################################################# +# Checking for every feature, whether it has children +################################################################################# + +sub set_children_flag +{ + my ($modulesref) = @_; + + my $allparents = collect_all_parent_feature($modulesref); + + for ( my $i = 0; $i <= $#{$modulesref}; $i++ ) + { + my $onefeature = ${$modulesref}[$i]; + my $gid = $onefeature->{'gid'}; + + # is this gid a parent? + + if ( installer::existence::exists_in_array($gid, $allparents) ) + { + $onefeature->{'has_children'} = 1; + } + else + { + $onefeature->{'has_children'} = 0; + } + } +} + +################################################################################# +# All modules, that use a template module, do now get the assignments of +# the template module. +################################################################################# + +sub resolve_assigned_modules +{ + my ($modulesref) = @_; + + # collecting all template modules + + my %directaccess = (); + + for ( my $i = 0; $i <= $#{$modulesref}; $i++ ) + { + my $onefeature = ${$modulesref}[$i]; + my $styles = ""; + if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; } + if ( $styles =~ /\bTEMPLATEMODULE\b/ ) { $directaccess{$onefeature->{'gid'}} = $onefeature; } + + # also looking for module with flag ROOT_BRAND_PACKAGE, to save is for further usage + if ( $styles =~ /\bROOT_BRAND_PACKAGE\b/ ) + { + $installer::globals::rootbrandpackage = $onefeature->{'gid'}; + $installer::globals::rootbrandpackageset = 1; + } + } + + # looking, where template modules are assigned + + for ( my $i = 0; $i <= $#{$modulesref}; $i++ ) + { + my $onefeature = ${$modulesref}[$i]; + if ( $onefeature->{'Assigns'} ) + { + my $templategid = $onefeature->{'Assigns'}; + + if ( ! exists($directaccess{$templategid}) ) + { + installer::exiter::exit_program("ERROR: Did not find definition of assigned template module \"$templategid\"", "resolve_assigned_modules"); + } + + # Currently no merging of Files, Dirs, ... + # This has to be included here, if it is required + my $item; + foreach $item (@installer::globals::items_at_modules) + { + if ( exists($directaccess{$templategid}->{$item}) ) { $onefeature->{$item} = $directaccess{$templategid}->{$item}; } + } + } + } +} + +################################################################################# +# Removing the template modules from the list, after all +# assignments are transferred to the "real" modules. +################################################################################# + +sub remove_template_modules +{ + my ($modulesref) = @_; + + my @modules = (); + + for ( my $i = 0; $i <= $#{$modulesref}; $i++ ) + { + my $onefeature = ${$modulesref}[$i]; + my $styles = ""; + if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; } + if ( $styles =~ /\bTEMPLATEMODULE\b/ ) { next; } + + push(@modules, $onefeature); + } + + return \@modules; +} + +################################################################################# +# Collecting all modules with flag LANGUAGEMODULE in a global +# collector. +################################################################################# + +sub collect_all_languagemodules +{ + my ($modulesref) = @_; + + for ( my $i = 0; $i <= $#{$modulesref}; $i++ ) + { + my $onefeature = ${$modulesref}[$i]; + my $styles = ""; + if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; } + if ( $styles =~ /\bLANGUAGEMODULE\b/ ) + { + if ( ! exists($onefeature->{'Language'}) ) { installer::exiter::exit_program("ERROR: \"$onefeature->{'gid'}\" has flag LANGUAGEMODULE, but does not know its language!", "collect_all_languagemodules"); } + $installer::globals::alllangmodules{$onefeature->{'gid'}} = $onefeature->{'Language'}; + # Collecting also the english names, that are used for nsis unpack directory for language packs + my $lang = $onefeature->{'Language'}; + my $name = ""; + foreach my $localkey ( keys %{$onefeature} ) + { + if ( $localkey =~ /^\s*Name\s*\(\s*en-US\s*\)\s*$/ ) + { + $installer::globals::all_english_languagestrings{$lang} = $onefeature->{$localkey}; + } + } + } + } +} + +################################################################################# +# Selecting from all collected english language strings those, that are really +# required in this installation set. +################################################################################# + +sub select_required_language_strings +{ + my ($modulesref) = @_; + + for ( my $i = 0; $i <= $#{$modulesref}; $i++ ) + { + my $onefeature = ${$modulesref}[$i]; + my $styles = ""; + if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; } + if ( $styles =~ /\bLANGUAGEMODULE\b/ ) + { + if ( ! exists($onefeature->{'Language'}) ) { installer::exiter::exit_program("ERROR: \"$onefeature->{'gid'}\" has flag LANGUAGEMODULE, but does not know its language!", "select_required_language_strings"); } + my $lang = $onefeature->{'Language'}; + + if (( exists($installer::globals::all_english_languagestrings{$lang}) ) && ( ! exists($installer::globals::all_required_english_languagestrings{$lang}) )) + { + $installer::globals::all_required_english_languagestrings{$lang} = $installer::globals::all_english_languagestrings{$lang}; + } + } + } +} + +##################################################################################### +# Unixlinks are not always required. For Linux RPMs and Solaris Packages they are +# created dynamically. Exception: For package formats "installed" or "archive". +# In scp2 this unixlinks have the flag LAYERLINK. +##################################################################################### + +sub filter_layerlinks_from_unixlinks +{ + my ( $unixlinksref ) = @_; + + my @alllinks = (); + + for ( my $i = 0; $i <= $#{$unixlinksref}; $i++ ) + { + my $isrequired = 1; + + my $onelink = ${$unixlinksref}[$i]; + my $styles = ""; + if ( $onelink->{'Styles'} ) { $styles = $onelink->{'Styles'}; } + + if ( $styles =~ /\bLAYERLINK\b/ ) + { + # Platforms, that do not need the layer links + if (( $installer::globals::islinuxrpmbuild ) || ( $installer::globals::issolarispkgbuild )) + { + $isrequired = 0; + } + + # Package formats, that need the layer link (platform independent) + if (( $installer::globals::packageformat eq "installed" ) || ( $installer::globals::packageformat eq "archive" )) + { + $isrequired = 1; + } + } + + if ( $isrequired ) { push(@alllinks, $onelink); } + } + + return \@alllinks; +} + +1; diff --git a/solenv/bin/modules/installer/servicesfile.pm b/solenv/bin/modules/installer/servicesfile.pm new file mode 100644 index 000000000000..1e21c39cdef3 --- /dev/null +++ b/solenv/bin/modules/installer/servicesfile.pm @@ -0,0 +1,1060 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: servicesfile.pm,v $ +# +# $Revision: 1.33 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::servicesfile; + +use Cwd; +use installer::converter; +use installer::existence; +use installer::exiter; +use installer::globals; +use installer::logger; +use installer::pathanalyzer; +use installer::remover; +use installer::scriptitems; +use installer::systemactions; + +################################################################ +# Adding the newly created file into the files collector +################################################################ + +sub add_services_sourcepath_into_filearray +{ + my ( $filesarrayref, $servicesfile, $servicesname ) = @_; + + my $found = 0; + my $onefile; + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + $onefile = ${$filesarrayref}[$i]; + my $name = $onefile->{'Name'}; + + if ( $servicesname eq $name ) + { + $found = 1; + $onefile->{'sourcepath'} = $servicesfile; # setting the sourcepath! + last; + } + } + + if ( ! $found ) { installer::exiter::exit_program("ERROR: Did not find $servicesname in files collector!", "add_services_sourcepath_into_filearray"); } + +} + +################################################################ +# Generating a file url from a path +################################################################ + +sub make_file_url +{ + my ( $path ) = @_; + + my $fileurl = ""; + + # removing ending slash/backslash + + installer::remover::remove_ending_pathseparator(\$path); + + if ($installer::globals::iswin) + { + $path =~ s/\\/\//g; + $fileurl = "file\:\/\/\/" . $path; + } + else + { + $fileurl = "file\:\/\/" . $path; + } + + return $fileurl; +} + +################################################################ +# Determining all sourcepath from the uno components +################################################################ + +sub get_all_sourcepathes +{ + my ( $filesref ) = @_; + + my @pathes = (); + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + my $path = $onefile->{'sourcepath'}; + + installer::pathanalyzer::get_path_from_fullqualifiedname(\$path); + + if (! installer::existence::exists_in_array($path, \@pathes)) + { + push(@pathes, $path); + } + } + + return \@pathes; +} + +################################################################ +# Registering all uno component files in the services.rdb +################################################################ + +sub register_unocomponents +{ + my ($allvariableshashref, $unocomponents, $regcompfileref, $servicesfile, $nativeservicesurlprefix) = @_; + + installer::logger::include_header_into_logfile("Registering UNO components:"); + + my $error_occured = 0; + my $filestring = ""; + for ( my $i = 0; $i <= $#{$unocomponents}; ) + { + my $sourcepath = ${$unocomponents}[$i++]->{'sourcepath'}; + + $filestring = $filestring . make_file_url($sourcepath); + + if ( $i % $installer::globals::unomaxservices == 0 || $i > $#{$unocomponents} ) # limiting to $installer::globals::maxservices files + { + my @regcompoutput = (); + + my $systemcall = "$installer::globals::wrapcmd $$regcompfileref -register -r ".fix_cygwin_path($servicesfile)." -c " . $installer::globals::quote . $filestring . $installer::globals::quote . " -wop=" . $installer::globals::quote . $nativeservicesurlprefix . $installer::globals::quote . " 2\>\&1 |"; + + open (REG, "$systemcall"); + while (<REG>) {push(@regcompoutput, $_); } + close (REG); + + my $returnvalue = $?; # $? contains the return value of the systemcall + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $j = 0; $j <= $#regcompoutput; $j++ ) { push( @installer::globals::logfileinfo, "$regcompoutput[$j]"); } + + if ($returnvalue) + { + $infoline = "ERROR: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + $error_occured = 1; + } + else + { + $infoline = "SUCCESS: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + $filestring = ""; + } + else + { + $filestring = $filestring . ";"; + } + } + + return $error_occured; +} + +################################################################ +# Registering all java component files in the services.rdb +################################################################ + +sub register_javacomponents +{ + my ($allvariableshashref, $javacomponents, $regcompfileref, $servicesfile, $regcomprdb, $javaservicesurlprefix) = @_; + + installer::logger::include_header_into_logfile("Registering Java components:"); + + my $ridljar_ref = "ridl.jar"; + my $ure_internal_java_dir_ref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$ridljar_ref, "", 1); + installer::pathanalyzer::get_path_from_fullqualifiedname($ure_internal_java_dir_ref); + if ( $$ure_internal_java_dir_ref eq "" ) { installer::exiter::exit_program("Could not determine URE_INTERNAL_JAVA_DIR when registering Java components!", "register_javacomponents"); } + + my $error_occured = 0; + + my $do_register = 1; + if (!( $installer::globals::solarjava )) { $do_register = 0; } + + if ( $do_register ) + { + my $filestring = ""; + + for ( my $i = 0; $i <= $#{$javacomponents}; ) + { + my $sourcepath = ${$javacomponents}[$i++]->{'sourcepath'}; + + $filestring = $filestring . make_file_url($sourcepath); + + if ( $i % $installer::globals::javamaxservices == 0 || $i > $#{$javacomponents} ) # limiting to $installer::globals::maxservices files + { + my @regcompoutput = (); + + my $systemcall = "$installer::globals::wrapcmd $$regcompfileref -register -br ".fix_cygwin_path($regcomprdb)." -r ".fix_cygwin_path($servicesfile)." -c " . $installer::globals::quote . $filestring . $installer::globals::quote . " -l com.sun.star.loader.Java2 -wop=" . $installer::globals::quote . $javaservicesurlprefix . $installer::globals::quote ." -env:URE_INTERNAL_JAVA_DIR=" . $installer::globals::quote . make_file_url($$ure_internal_java_dir_ref) . $installer::globals::quote . " 2\>\&1 |"; + + open (REG, "$systemcall"); + while (<REG>) {push(@regcompoutput, $_); } + close (REG); + + my $returnvalue = $?; # $? contains the return value of the systemcall + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $k = 0; $k <= $#regcompoutput; $k++ ) { push( @installer::globals::logfileinfo, "$regcompoutput[$k]"); } + + if ($returnvalue) + { + $infoline = "ERROR: $systemcall\n"; + $error_occured = 1; + } + else + { + $infoline = "SUCCESS: $systemcall\n"; + } + + push( @installer::globals::logfileinfo, $infoline); + + $filestring = ""; + } + else + { + $filestring = $filestring . ";"; + } + } + } + + return $error_occured; +} + + + +################################################################ +# Helper routine to change cygwin (POSIX) path to DOS notation +# if needed +################################################################ +sub fix_cygwin_path +{ + my ( $path ) = @_; + + if ( $installer::globals::iswin eq 1 && $ENV{'USE_SHELL'} ne "4nt" && $installer::globals::wrapcmd eq "" ) + { + $path = qx{cygpath -m "$path"}; + chomp($path); + } + + return $path; +} + + + +################################################################ +# Registering all uno component files in the services.rdb +################################################################ +sub get_source_path_cygwin_safe +{ + my ( $name, $array, $int ) = @_; + + my $ret = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$name, $array, $int); + if ( $installer::globals::iswin eq 1 && $ENV{'USE_SHELL'} ne "4nt" ) + { + if( substr( $$ret, 1,1 ) eq ":" ) + { + chomp($$ret = qx{cygpath -u "$$ret"}); + } + } + return $ret; +} + +sub register_pythoncomponents +{ + my ($pythoncomponents, $regcompfileref, $servicesfile,$includepatharrayref) = @_; + + installer::logger::include_header_into_logfile("Registering python UNO components:"); + + my $error_occured = 0; + my $counter = 0; + + my $systemcall = ""; + + my $allsourcepathes = get_all_sourcepathes($pythoncomponents); + + for ( my $j = 0; $j <= $#{$allsourcepathes}; $j++ ) + { + my $filestring = ""; + my $onesourcepath = ${$allsourcepathes}[$j]; + my $to = ""; + my $from = cwd(); + if ( $installer::globals::iswin ) { $from =~ s/\//\\/g; } + + my $typesrdbname = "types.rdb"; + + # FIXME: Remove the unneeded + # get_source_path_cygwin_safe() -> fix_cygwin_path() + # when WRAPCMD is gone + my $typesrdbref = get_source_path_cygwin_safe($typesrdbname, $includepatharrayref, 1); + + if ( $$typesrdbref eq "" ) { installer::exiter::exit_program("ERROR: Could not find file $typesrdbname !", "register_pythoncomponents"); } + + my $pyunoservicesrdbname = "pyuno_services.rdb"; + my $pyunoservicesrdbref = get_source_path_cygwin_safe($pyunoservicesrdbname, $includepatharrayref, 1); + + if ( $$pyunoservicesrdbref eq "" ) { installer::exiter::exit_program("ERROR: Could not find file $pyunoservicesrname !", "register_pythoncomponents"); } + + for ( my $i = 0; $i <= $#{$pythoncomponents}; $i++ ) + { + my $doinclude = 1; + my $sourcepath = ${$pythoncomponents}[$i]->{'sourcepath'}; + + $to = $sourcepath; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$to); + + if (!($to eq $onesourcepath)) { $doinclude = 0; } + + if ( $doinclude ) + { + my $filename = ${$pythoncomponents}[$i]->{'Name'}; + $filestring = $filestring . $filename . "\;"; + $counter++; + } + +# if ((( $counter > 0 ) && ( $counter%$installer::globals::unomaxservices == 0 )) || (( $counter > 0 ) && ( $i == $#{$pythoncomponents} ))) # limiting to $installer::globals::maxservices files + if ( $counter > 0 ) + { + $filestring =~ s/\;\s*$//; + $filestring = substr( $filestring, 0, length($filestring)-3); + chdir($onesourcepath); + + my @regcompoutput = (); + + $systemcall = "$installer::globals::wrapcmd $$regcompfileref -register" + . " -br " . fix_cygwin_path($$typesrdbref) + . " -br " . fix_cygwin_path($$pyunoservicesrdbref) + . " -r " . fix_cygwin_path($servicesfile) + . " -c vnd.openoffice.pymodule:" . $filestring . " -l com.sun.star.loader.Python 2\>\&1 |"; + + open (REG, "$systemcall"); + while (<REG>) {push(@regcompoutput, $_); } + close (REG); + + my $returnvalue = $?; # $? contains the return value of the systemcall + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $j = 0; $j <= $#regcompoutput; $j++ ) { push( @installer::globals::logfileinfo, "$regcompoutput[$j]"); } + + if ($returnvalue) + { + $infoline = "ERROR: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + $error_occured = 1; + } + else + { + $infoline = "SUCCESS: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + chdir($from); + + $counter = 0; + $filestring = ""; + } + } + } + + return $error_occured; +} + +################################################################ +# Iterating over all files, to find all files with the +# style UNO_COMPONENT. This can be libraries and jar files. +################################################################ + +sub register_all_components +{ + my ( $allvariableshashref, $servicesgid, $filesarrayref, $regcompfileref, $servicesfile, $regcomprdb, $includepatharrayref, $nativeservicesurlprefix, $javaservicesurlprefix ) = @_; + + my $registererrorflag = 0; + + my @unocomponents = (); + my @javacomponents = (); + my @pythoncomponents = (); + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + my $styles = ""; + my $regmergefile = ""; + my $registryid = ""; + + if ( $onefile->{'RegistryID'} ) { $registryid = $onefile->{'RegistryID'}; } + + if ( $servicesgid ne $registryid ) { next; } # only registration for the current $servicesgid + + if ( $onefile->{'Regmergefile'} ) { $regmergefile = $onefile->{'Regmergefile'}; } + + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } + + if (( $styles =~ /\bUNO_COMPONENT\b/ ) && ( $regmergefile eq "" )) # regmergefiles will not be registered with regcomp + { + my $filename = $onefile->{'Name'}; + + if ( $filename =~ /\.jar\s*$/ ) # java component + { + push(@javacomponents, $onefile); + } + elsif( $filename =~ /\.py\s*$/ ) # python_component + { + push(@pythoncomponents, $onefile); + } + else # uno component + { + push(@unocomponents, $onefile); + } + } + } + + $uno_error_occured = 0; + $java_error_occured = 0; + $python_error_occured = 0; + + if ( $#unocomponents > -1 ) { $uno_error_occured = register_unocomponents($allvariableshashref, \@unocomponents, $regcompfileref, $servicesfile, $nativeservicesurlprefix); } + if ( $#javacomponents > -1 ) { $java_error_occured = register_javacomponents($allvariableshashref, \@javacomponents, $regcompfileref, $servicesfile, $regcomprdb, $javaservicesurlprefix); } + if ( $#pythoncomponents > -1 ) { $python_error_occured = register_pythoncomponents(\@pythoncomponents, $regcompfileref, $servicesfile, $includepatharrayref); } + + if ( $uno_error_occured || $java_error_occured || $python_error_occured ) { $registererrorflag = 1; } + + return $registererrorflag; +} + +################################################### +# Include the solver lib directory into +# the LD_LIBRARY_PATH for Unix platforms +################################################### + +sub include_libdir_into_ld_library_path +{ + my ( $var, $binfile ) = @_; + + my $ld_library_path = $binfile; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$ld_library_path); + $ld_library_path =~ s/\/\s*$//; # removing ending slashes + $ld_library_path =~ s/\/bin\./\/lib\./; + $ld_library_path =~ s/\/bin\s*$/\/lib/; # when packing from flat + + my $oldldlibrarypathstring = $ENV{$var}; + my $new_ld_library_path = $ld_library_path; + if ( defined $oldldlibrarypathstring ) { + $new_ld_library_path = $new_ld_library_path . $installer::globals::pathseparator . $oldldlibrarypathstring; + } + if ( $ENV{'SYSTEM_MOZILLA'} && $ENV{'SYSTEM_MOZILLA'} eq "YES" && + (!$ENV{'WITH_OPENLDAP'} || $ENV{'WITH_OPENLDAP'} ne "YES")) { + $new_ld_library_path = $new_ld_library_path . $installer::globals::pathseparator . $ENV{'MOZ_LIB'}; + } + $ENV{$var} = $new_ld_library_path; + + my $infoline = "Setting $var to $ENV{$var}\n"; + push( @installer::globals::logfileinfo, $infoline); +} + +################################################################## +# Setting the needed jar files into the CLASSPATH +# They are needed from regcomp. +# The jar files are defined in @installer::globals::regcompjars +################################################################## + +sub prepare_classpath_for_java_registration +{ + my ( $includepatharrayref ) = @_; + my $local_pathseparator = $installer::globals::pathseparator; + + if( $^O =~ /cygwin/i ) + { # $CLASSPATH must use DOS separator even when using cygwin's perl + $local_pathseparator = ';'; + } + + for ( my $i = 0; $i <= $#installer::globals::regcompjars; $i++ ) + { + my $filename = $installer::globals::regcompjars[$i]; + + my $jarfileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$filename, $includepatharrayref, 1); + + if ( $$jarfileref eq "" ) { installer::exiter::exit_program("ERROR: Could not find file $filename for registering java components!", "prepare_classpath_for_java_registration"); } + + my $oldclasspathstring = ""; + if ( $ENV{'CLASSPATH'} ) { $oldclasspathstring = $ENV{'CLASSPATH'}; } + else { $oldclasspathstring = "\."; } + my $classpathstring = $$jarfileref . $local_pathseparator . $oldclasspathstring; + if (( $^O =~ /cygwin/i ) && ( $ENV{'USE_SHELL'} ne "4nt" )) { + $classpathstring =~ s/\//\\/g; # guw.pl likes '\' in $PATH. + } + $ENV{'CLASSPATH'} = $classpathstring; + + my $infoline = "Setting CLASSPATH to $ENV{'CLASSPATH'}\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +################################################################## +# Setting the jdk lib into the LD_LIBRARY_PATH (Unix) +# This is used by regcomp to register Java components. +# The jdk lib is defined in $installer::globals::jdklib +################################################################## + +sub add_jdklib_into_ld_library_path +{ + my ($var) = @_; + if (defined $installer::globals::jdklib) { + my $oldldlibrarypathstring = $ENV{$var}; + my $new_ld_library_path = $installer::globals::jdklib; + if (defined $oldldlibrarypathstring) { + $new_ld_library_path .= + $installer::globals::pathseparator . $oldldlibrarypathstring; + } + $ENV{$var} = $new_ld_library_path; + my $infoline = "Setting $var to $ENV{$var}\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +################################################################## +# Adding the libraries included in zip files into path variable +# (for example mozruntime.zip). This is needed to register all +# libraries successfully. +################################################################## + +sub add_path_to_pathvariable_directory +{ + my ( $filesarrayref, $searchstring ) = @_; + + # determining the path + + my $path = ""; + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + my $sourcepath = $onefile->{'sourcepath'}; + + installer::pathanalyzer::get_path_from_fullqualifiedname(\$sourcepath); + installer::remover::remove_ending_pathseparator(\$sourcepath); + + if ( $sourcepath =~ /\Q$searchstring\E\s*$/ ) + { + $path = $sourcepath; + last; + } + } + + # adding the path to the PATH variable + + if ( $path ne "" ) + { + my $oldpath = ""; + if ( $ENV{'PATH'} ) { $oldpath = $ENV{'PATH'}; } + else { $oldpath = "\."; } + if ( $^O =~ /cygwin/i ) { + $path = qx(cygpath -u "$path"); + chomp $path; + } + my $newpath = $path . $installer::globals::pathseparator . $oldpath; + $ENV{'PATH'} = $newpath; + + my $infoline = "Setting PATH to $ENV{'PATH'}\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +################################################################## +# Adding the path of a specified library to the path variable +# (for example msvcr70.dll). This is needed to register all +# libraries successfully. +################################################################## + +sub add_path_to_pathvariable +{ + my ( $filesarrayref, $searchstring ) = @_; + + # determining the path + + my $path = ""; + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + my $sourcepath = $onefile->{'sourcepath'}; + + if ( $sourcepath =~ /\Q$searchstring\E\s*$/ ) + { + installer::pathanalyzer::get_path_from_fullqualifiedname(\$sourcepath); + installer::remover::remove_ending_pathseparator(\$sourcepath); + $path = $sourcepath; + last; + } + } + + # adding the path to the PATH variable + + if ( $path ne "" ) + { + my $oldpath = ""; + if ( $ENV{'PATH'} ) { $oldpath = $ENV{'PATH'}; } + else { $oldpath = "\."; } + if ( $^O =~ /cygwin/i ) { + $path = qx(cygpath -u "$path"); + chomp $path; + } + my $newpath = $path . $installer::globals::pathseparator . $oldpath; + $ENV{'PATH'} = $newpath; + + my $infoline = "Setting PATH to $ENV{'PATH'}\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +################################################################## +# Setting the jre path into the PATH (Windows only) +# This is used by regcomp.exe to register Java components. +# The jre path is saved in $installer::globals::jrepath +################################################################## + +sub add_jrepath_into_path +{ + my $oldpath = ""; + if ( $ENV{'PATH'} ) { $oldpath = $ENV{'PATH'}; } + else { $oldpath = "\."; } + + if ( $installer::globals::jrepath ne "" ) + { + my $newpath = $installer::globals::jrepath . $installer::globals::pathseparator . $oldpath; + $ENV{'PATH'} = $newpath; + + my $infoline = "Setting PATH to $ENV{'PATH'}\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +####################################################################################### +# Preparing a registry "regcomp.rdb" which regcomp can work on (types+java services). +# Copying the "udkapi.rdb", renaming it to "regcomp.rdb" and registering the +# libraries @installer::globals::regcompregisterlibs, which are javavm.uno.so +# and javaloader.uno.so or javavm.uno.dll and javaloader.uno.dll +####################################################################################### + +sub prepare_regcomp_rdb +{ + my ( $regcompfile, $servicesdir, $includepatharrayref) = @_; + + # udkapi.rdb has to be found in the sourcepath + + my $filename = "udkapi.rdb"; + my $udkapirdbref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$filename, $includepatharrayref, 1); + if ( $$udkapirdbref eq "" ) { installer::exiter::exit_program("ERROR: Could not find file $filename for creating regcomp.rdb!", "prepare_regcomp_rdb"); } + + my $regcompfilename = "regcomp.rdb"; + my $regcomprdb = $servicesdir . $installer::globals::separator . $regcompfilename; + + # If there is an older version of this file, it has to be removed + if ( -f $regcomprdb ) { unlink($regcomprdb); } + + installer::systemactions::copy_one_file($$udkapirdbref, $regcomprdb); + + # now the libraries in @installer::globals::regcompregisterlibs can be registered in the "regcomp.rdb" + + for ( my $i = 0; $i <= $#installer::globals::regcompregisterlibs; $i++ ) + { + my $libfilename = $installer::globals::regcompregisterlibs[$i] . $installer::globals::libextension; + my $libfileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$libfilename, $includepatharrayref, 1); + if ( $$libfileref eq "" ) { installer::exiter::exit_program("ERROR: Could not find file $libfilename for creating regcomp.rdb!", "prepare_regcomp_rdb"); } + + my $from = cwd(); + if ( $installer::globals::iswin ) { $from =~ s/\//\\/g; } + + my $to = $$libfileref; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$to); + + chdir($to); + + my $systemcall = "$installer::globals::wrapcmd $regcompfile -register -s -r " . fix_cygwin_path($regcomprdb) . " -c $libfilename"; + + my $returnvalue = system($systemcall); + + chdir($from); + + my $infoline; + if ($returnvalue) { $infoline = "ERROR: $systemcall\n"; } + else { $infoline = "SUCCESS: $systemcall\n"; } + + push( @installer::globals::logfileinfo, $infoline); + } + + return $regcomprdb; +} + +################################################################ +# Collecting all gids of the databases, that are part of +# the file definition +################################################################ + +sub collect_all_services_gids +{ + my ($filesarrayref) = @_; + + my @databasegids = (); + my $error_occured = 0; + my @error_files = (); + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + + if ( $onefile->{'RegistryID'} ) + { + my $databasegid = $onefile->{'RegistryID'}; + if (! installer::existence::exists_in_array($databasegid, \@databasegids)) { push(@databasegids, $databasegid); } + } + else + { + push(@error_files, $onefile->{'gid'}); + $error_occured = 1; + } + } + + if ( $error_occured ) + { + my $infoline = "ERROR: Style UNO_COMPONENT is set, but no RegistryID is assigned!\n"; + push( @installer::globals::logfileinfo, $infoline); + print $infoline; + + for ( my $j = 0; $j <= $#error_files; $j++ ) + { + $infoline = "$error_files[$j]\n"; + push( @installer::globals::logfileinfo, $infoline); + print $infoline; + } + + installer::exiter::exit_program("ERROR: File defintion error.", "collect_all_services_gids"); + } + + return \@databasegids; +} + +###################################################################### +# All gids in $databasegids are as RegistryID assigned to files. +# For all this Registry Files a definition has to exist. +###################################################################### + +sub check_defintion_of_databasegids +{ + my ($databasegids, $registryfiles) = @_; + + my @registryfiles = (); + + # First check: For all assigned Registry files, a definition of + # a file with flag STARREGISTRY has to exist. + + for ( my $i = 0; $i <= $#{$databasegids}; $i++ ) + { + my $onegid = ${$databasegids}[$i]; + my $gid_defined = 0; + + for ( my $j = 0; $j <= $#{$registryfiles}; $j++ ) + { + my $registrygid = ${$registryfiles}[$j]->{'gid'}; + + if ( $onegid eq $registrygid ) + { + $gid_defined = 1; + last; + } + } + + if ( ! $gid_defined ) + { + installer::exiter::exit_program("ERROR: Gid $onegid is assigned to file(s), but not defined!", "check_defintion_of_databasegids"); + } + } + + # Second check: If there is a file defined as StarRegistry, is a file with flag UNO_COMPONENT assigned? + + for ( my $j = 0; $j <= $#{$registryfiles}; $j++ ) + { + my $onefile = ${$registryfiles}[$j]; + my $registrygid = $onefile->{'gid'}; + + my $gid_assigned = 0; + + for ( my $i = 0; $i <= $#{$databasegids}; $i++ ) + { + my $onegid = ${$databasegids}[$i]; + + if ( $onegid eq $registrygid ) + { + $gid_assigned = 1; + last; + } + } + + if ( ! $gid_assigned ) + { + my $infoline = "Warning: $registrygid is defined with flag STARREGISTRY, but no file is assigned to the registry.\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + push(@registryfiles, $onefile); + } + } + + return \@registryfiles; +} + +################################################################ +# Some files have flag UNO_COMPONENT, but are not registered +# with regcomp. This files use the regmerge mechanism, that +# is not used in this perl-file. Therefore this files +# have to be filtered out here. +################################################################ + +sub filter_regmergefiles +{ + my ($unocomponentfiles) = @_; + + my @regcompfiles = (); + + for ( my $i = 0; $i <= $#{$unocomponentfiles}; $i++ ) + { + my $onefile = ${$unocomponentfiles}[$i]; + my $regmergefile = ""; + + if ( $onefile->{'Regmergefile'} ) { $regmergefile = $onefile->{'Regmergefile'}; } + if ( $regmergefile ne "" ) { next; } + + push(@regcompfiles, $onefile); + } + + return \@regcompfiles; +} + +################################################################ +# Setting defaults for Creating services.rdb file by registering all uno components +################################################################ + +sub set_url_prefixes +{ + my ( $registryfile ) = @_; + + my $nativeservicesurlprefix = ""; + my $javaservicesurlprefix = ""; + + if ( $registryfile->{'NativeServicesURLPrefix'} ) { $nativeservicesurlprefix = $registryfile->{'NativeServicesURLPrefix'}; } + else { $nativeservicesurlprefix = "vnd.sun.star.expand:\$ORIGIN/"; } + + if ( $registryfile->{'JavaServicesURLPrefix'} ) { $javaservicesurlprefix = $registryfile->{'JavaServicesURLPrefix'}; } + else { $javaservicesurlprefix = "vnd.sun.star.expand:\$UNO_JAVA_COMPONENT_PATH/"; } + + return ($nativeservicesurlprefix, $javaservicesurlprefix); +} + +################################################################ +# Creating services.rdb file by registering all uno components +################################################################ + +sub create_services_rdb +{ + my ($allvariableshashref, $filesarrayref, $includepatharrayref, $languagestringref) = @_; + + # collecting all services files + my $unocomponentfiles = installer::worker::collect_all_items_with_special_flag($filesarrayref, "UNO_COMPONENT"); + $unocomponentfiles = filter_regmergefiles($unocomponentfiles); + + if ( $#{$unocomponentfiles} > -1 ) # not empty -> at least one file with flag UNO_COMPONENT + { + my $databasegids = collect_all_services_gids($unocomponentfiles); + + my $registryfiles = installer::worker::collect_all_items_with_special_flag($filesarrayref, "STARREGISTRY"); + + $registryfiles = check_defintion_of_databasegids($databasegids, $registryfiles); + + # Now the creation of all files with flag STARREGISTRY can begin + + for ( my $i = 0; $i <= $#{$registryfiles}; $i++ ) + { + my $registryfile = ${$registryfiles}[$i]; + + # my $servicesname = "services.rdb"; + my $servicesname = $registryfile->{'Name'}; # not unique! + my $servicesgid = $registryfile->{'gid'}; # unique + my $uniquedirname = $servicesgid . "_servicesrdb"; + # my $uniquedirname = $servicesgid; + + my ($nativeservicesurlprefix, $javaservicesurlprefix) = set_url_prefixes($registryfile); + + installer::logger::include_header_into_logfile("Creating $servicesname ($servicesgid):"); + + # my $servicesdir = installer::systemactions::create_directories($servicesname, $languagestringref); + my $servicesdir = installer::systemactions::create_directories($uniquedirname, $languagestringref); + + if ( $^O =~ /cygwin/i && $ENV{'USE_SHELL'} eq "4nt" ) + { # $servicesdir is used as a parameter for regcomp and has to be DOS style + $servicesdir = qx{cygpath -d "$servicesdir"}; + chomp($servicesdir); + $servicesdir =~ s/\\/\//g; + } + + push(@installer::globals::removedirs, $servicesdir); + + my $servicesfile = $servicesdir . $installer::globals::separator . $servicesname; + + # If there is an older version of this file, it has to be removed + if ( -f $servicesfile ) { unlink($servicesfile); } + + # if ((-f $servicesfile) && (!($installer::globals::services_rdb_created))) { $installer::globals::services_rdb_created = 1; } + # if ((!($installer::globals::services_rdb_created)) && $installer::globals::servicesrdb_can_be_created ) # This has to be done once + if ( $installer::globals::servicesrdb_can_be_created ) # This has to be done always + { + # Creating the services.rdb in directory "inprogress" + my $origservicesdir = $servicesdir; + $servicesdir = installer::systemactions::make_numbered_dir("inprogress", $servicesdir); + $servicesfile = $servicesdir . $installer::globals::separator . $servicesname; + + # determining the location of the file regcomp + # Because the program regcomp.exe (regcomp) is used now, it has to be taken the version + # from the platform, this script is running. It is not important, for which platform the + # product is built. + + my $searchname; + + if ($installer::globals::isunix) { $searchname = "regcomp"; } + else { $searchname = "regcomp.exe"; } + + $regcompfileref = get_source_path_cygwin_safe($searchname, $includepatharrayref, 1); + if ( $$regcompfileref eq "" ) { installer::exiter::exit_program("ERROR: Could not find file $searchname for registering uno components!", "create_services_rdb"); } + + # For Windows the libraries included into the mozruntime.zip have to be added to the path + if ($installer::globals::iswin) { add_path_to_pathvariable_directory($filesarrayref, "mozruntime_zip"); } + if ($installer::globals::iswin) { add_path_to_pathvariable($filesarrayref, "msvcr70.dll"); } + + # setting the LD_LIBRARY_PATH, needed by regcomp + # Linux: Take care of the lock daemon. He has to be started! + # For windows it is necessary that "msvcp7x.dll" and "msvcr7x.dll" are included into the path ! + + my $var_library_path; + my $old_library_path; + if ( $installer::globals::isunix ) { + $var_library_path = $installer::globals::ismacosx ? + 'DYLD_LIBRARY_PATH' : 'LD_LIBRARY_PATH'; + $old_library_path = $ENV{$var_library_path}; + include_libdir_into_ld_library_path( + $var_library_path, $$regcompfileref); + } + + my $regcomprdb = ""; + + if ( $installer::globals::solarjava ) # this is needed to register Java components + { + prepare_classpath_for_java_registration($includepatharrayref); + + if ( $installer::globals::isunix ) + { add_jdklib_into_ld_library_path($var_library_path); } + else { add_jrepath_into_path(); } + + # Preparing a registry which regcomp can work on (types+java services). + # Copying the "udkapi.rdb", renaming it to "regcomp.rdb" and registering the + # libraries $(REGISTERLIBS_JAVA), which are javavm.uno.so and javaloader.uno.so + # or javavm.uno.dll and javaloader.uno.dll + + $regcomprdb = prepare_regcomp_rdb($$regcompfileref, $servicesdir, $includepatharrayref); + } + + # and now iteration over all files + + # my $error_during_registration = register_all_components($filesarrayref, $regcompfileref, $servicesfile, $regcomprdb, $includepatharrayref); + my $error_during_registration = register_all_components($allvariableshashref, $servicesgid, $unocomponentfiles, $regcompfileref, $servicesfile, $regcomprdb, $includepatharrayref, $nativeservicesurlprefix, $javaservicesurlprefix); + + if (defined $var_library_path) { + if (defined $old_library_path) { + $ENV{$var_library_path} = $old_library_path; + } else { + delete $ENV{$var_library_path}; + } + } + + # Dependent from the success, the registration directory can be renamed. + + if ( $error_during_registration ) + { + $servicesdir = installer::systemactions::rename_string_in_directory($servicesdir, "inprogress", "witherror"); + push(@installer::globals::removedirs, $servicesdir); + # and exiting the packaging process + installer::exiter::exit_program("ERROR: Could not register all components for file $servicesname ($servicesgid)!", "create_services_rdb"); + } + else + { + $servicesdir = installer::systemactions::rename_directory($servicesdir, $origservicesdir); + } + + $servicesfile = $servicesdir . $installer::globals::separator . $servicesname; + } + else + { + my $infoline; + + if (!($installer::globals::servicesrdb_can_be_created)) + { + $infoline = "Warning: $servicesname was not created. Build platform and compiler do not match. Build platform: $installer::globals::plat, compiler : $installer::globals::compiler\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + if ( $installer::globals::services_rdb_created ) + { + $infoline = "Info: $servicesname was not created. $servicesfile already exists.\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + if ((!($installer::globals::servicesrdb_can_be_created)) && (!($installer::globals::services_rdb_created))) + { + $infoline = "ERROR: $servicesname was not created and does not exist!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + + # Adding the new services file source path to the filearray + $registryfile->{'sourcepath'} = $servicesfile; # setting the sourcepath! + # add_services_sourcepath_into_filearray( $filesarrayref, $servicesfile, $servicesname ); + } + } + + # Setting the global variable $installer::globals::services_rdb_created + + $installer::globals::services_rdb_created = 1; +} + +1; diff --git a/solenv/bin/modules/installer/setupscript.pm b/solenv/bin/modules/installer/setupscript.pm new file mode 100644 index 000000000000..a131d32b21c0 --- /dev/null +++ b/solenv/bin/modules/installer/setupscript.pm @@ -0,0 +1,489 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: setupscript.pm,v $ +# +# $Revision: 1.19 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::setupscript; + +use installer::existence; +use installer::exiter; +use installer::globals; +use installer::logger; +use installer::remover; +use installer::scriptitems; +use installer::ziplist; + +####################################################### +# Set setup script name, if not defined as parameter +####################################################### + +sub set_setupscript_name +{ + my ( $allsettingsarrayref, $includepatharrayref ) = @_; + + my $scriptnameref = installer::ziplist::getinfofromziplist($allsettingsarrayref, "script"); + + my $scriptname = $$scriptnameref; + + if ( $scriptname eq "" ) # not defined on command line and not in product list + { + installer::exiter::exit_program("ERROR: Setup script not defined on command line (-l) and not in product list!", "set_setupscript_name"); + } + + if ( $installer::globals::compiler =~ /wnt/ ) + { + $scriptname .= ".inf"; + } + else + { + $scriptname .= ".ins"; + } + + # and now the complete path for the setup script is needed + # The log file cannot be used, because this is the language independent section + + $scriptnameref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$scriptname, $includepatharrayref, 1); + + $installer::globals::setupscriptname = $$scriptnameref; + + if ( $installer::globals::setupscriptname eq "" ) + { + installer::exiter::exit_program("ERROR: Script $scriptname not found!", "set_setupscript_name"); + } +} + +##################################################################### +# Reading script variables from installation object of script file +##################################################################### + +sub get_all_scriptvariables_from_installation_object +{ + my ($scriptref) = @_; + + my @installobjectvariables; + + for ( my $i = 0; $i <= $#{$scriptref}; $i++ ) + { + my $line = ${$scriptref}[$i]; + + if ( $line =~ /^\s*Installation\s+\w+\s*$/ ) # should be the first line + { + my $counter = $i+1; + my $installline = ${$scriptref}[$counter]; + + while (!($installline =~ /^\s*End\s*$/ )) + { + if ( $installline =~ /^\s*(\w+)\s+\=\s*(.*?)\s*\;\s*$/ ) + { + my $key = $1; + my $value = $2; + + # removing leading and ending " in $value + + if ( $value =~ /^\s*\"(.*)\"\s*$/ ) + { + $value = $1; + } + + $key = "\%" . uc($key); # $key is %PRODUCTNAME + + my $input = $key . " " . $value . "\n"; # $key can only be the first word + + push(@installobjectvariables ,$input); + } + + $counter++; + $installline = ${$scriptref}[$counter]; + } + } + + last; # not interesting after installation object + } + + return \@installobjectvariables; +} + +###################################################################### +# Including LCPRODUCTNAME into the array +###################################################################### + +sub add_lowercase_productname_setupscriptvariable +{ + my ( $variablesref ) = @_; + + for ( my $j = 0; $j <= $#{$variablesref}; $j++ ) + { + my $variableline = ${$variablesref}[$j]; + + my ($key, $value); + + if ( $variableline =~ /^\s*\%(\w+?)\s+(.*?)\s*$/ ) + { + $key = $1; + $value = $2; + + if ( $key eq "PRODUCTNAME" ) + { + my $newline = "\%LCPRODUCTNAME " . lc($value) . "\n"; + push(@{$variablesref} ,$newline); + my $original = $value; + $value =~ s/\s*//g; + $newline = "\%ONEWORDPRODUCTNAME " . $value . "\n"; + push(@{$variablesref} ,$newline); + $newline = "\%LCONEWORDPRODUCTNAME " . lc($value) . "\n"; + push(@{$variablesref} ,$newline); + $value = $original; + $value =~ s/\s/\_/g; + $newline = "\%UNIXPRODUCTNAME " . lc($value) . "\n"; + push(@{$variablesref} ,$newline); + $value = $original; + $value =~ s/\s/\_/g; + $value =~ s/\.//g; + $newline = "\%WITHOUTDOTUNIXPRODUCTNAME " . lc($value) . "\n"; + push(@{$variablesref} ,$newline); + } + elsif ( $key eq "PRODUCTEXTENSION" ) + { + my $newline = "\%LCPRODUCTEXTENSION " . lc($value) . "\n"; + push(@{$variablesref} ,$newline); + } + elsif ( $key eq "PRODUCTVERSION" ) + { + $value =~ s/\.//g; + my $newline = "\%WITHOUTDOTPRODUCTVERSION " . $value . "\n"; + push(@{$variablesref} ,$newline); + } + elsif ( $key eq "OOOBASEVERSION" ) + { + $value =~ s/\.//g; + my $newline = "\%WITHOUTDOTOOOBASEVERSION " . $value . "\n"; + push(@{$variablesref} ,$newline); + } + + } + } +} + +###################################################################### +# Resolving the new introduced lowercase script variables +###################################################################### + +sub resolve_lowercase_productname_setupscriptvariable +{ + my ( $variablesref ) = @_; + + my %variables = (); + + # First step: Collecting variables + + for ( my $j = 0; $j <= $#{$variablesref}; $j++ ) + { + my $variableline = ${$variablesref}[$j]; + + my ($key, $value); + + if ( $variableline =~ /^\s*\%(\w+?)\s+(.*?)\s*$/ ) + { + $key = $1; + $value = $2; + $variables{$key} = $value; + } + } + + # Second step: Resolving variables + + for ( my $j = 0; $j <= $#{$variablesref}; $j++ ) + { + if ( ${$variablesref}[$j] =~ /\$\{(.*?)\}/ ) + { + my $key = $1; + ${$variablesref}[$j] =~ s/\$\{\Q$key\E\}/$variables{$key}/g; + } + } + +} + +###################################################################### +# Replacing all setup script variables inside the setup script file +###################################################################### + +sub replace_all_setupscriptvariables_in_script +{ + my ( $scriptref, $variablesref ) = @_; + + installer::logger::include_header_into_globallogfile("Replacing variables in setup script (start)"); + + # make hash of variables to be substituted if they appear in the script + my %subs; + for ( my $j = 0; $j <= $#{$variablesref}; $j++ ) + { + my $variableline = ${$variablesref}[$j]; + + if ( $variableline =~ /^\s*(\%\w+?)\s+(.*?)\s*$/ ) + { + $subs{$1}= $2; + } + } + + # This is far faster than running a regexp for each line + my $bigstring = ''; + for my $line (@{$scriptref}) { $bigstring = $bigstring . $line; } + + foreach my $key ( keys %subs ) + { + # Attention: It must be possible to substitute "%PRODUCTNAMEn", "%PRODUCTNAME%PRODUCTVERSIONabc" + my $value = $subs{$key}; + $bigstring =~ s/$key/$value/g; + } + + my @newlines = split /\n/, $bigstring; + $scriptref = \@newlines; + + # now check for any mis-named '%' variables that we have left + my $num = 0; + for my $check (@newlines) + { + $num++; + if ( $check =~ /^.*\%\w+.*$/ ) + { + if (( $check =~ /%1/ ) || ( $check =~ /%2/ ) || ( $check =~ /%verify/ )) { next; } + my $infoline = "WARNING: mis-named or un-known '%' variable in setup script at line $num:\n$check\n"; + push( @installer::globals::globallogfileinfo, $infoline); + # print STDERR "Warning: mis-named or un-known '%' variable at line $num:\n$check\n"; + } + } + + installer::logger::include_header_into_globallogfile("Replacing variables in setup script (end)"); + + return $scriptref; +} + +####################################################################### +# Collecting all items of the type "searchitem" from the setup script +####################################################################### + +sub get_all_items_from_script +{ + my ($scriptref, $searchitem) = @_; + + my @allitemarray = (); + + my ($itemkey, $itemvalue, $valuecounter); + + for ( my $i = 0; $i <= $#{$scriptref}; $i++ ) + { + my $line = ${$scriptref}[$i]; + + if ( $line =~ /^\s*\Q$searchitem\E\s+(\S+)\s*$/ ) + { + my $gid = $1; + my $counter = $i + 1; + + my %oneitemhash = (); + my $ismultilang = 0; + + $oneitemhash{'gid'} = $gid; + + while (!( $line =~ /^\s*End\s*$/ )) + { + if ( $counter > $#{$scriptref} ) { + installer::exiter::exit_program("Invalid setup script file. End of file reached before 'End' line of '$searchitem' section.", "get_all_items_from_script"); + } + $line = ${$scriptref}[$counter]; + $counter++; + + if ( $line =~ /^\s*(.+?)\s*\=\s*(.+?)\s*\;\s*$/ ) # only oneliner! + { + $itemkey = $1; + $itemvalue = $2; + + installer::remover::remove_leading_and_ending_quotationmarks(\$itemvalue); + $itemvalue =~ s/\s*$//; # removing ending whitespaces. Could be introduced by empty variables. + + $oneitemhash{$itemkey} = $itemvalue; + + if ( $itemkey =~ /^\s*\S+\s+\(\S+\)\s*$/ ) + { + $ismultilang = 1; + } + } + else + { + if ( $searchitem eq "Module" ) # more than one line, for instance files at modules! + { + if (( $line =~ /^\s*(.+?)\s*\=\s*\(/ ) && (!($line =~ /\)\;\s*$ / ))) + { + if ( $line =~ /^\s*(.+?)\s*\=\s*(.+)/ ) # the first line + { + $itemkey = $1; + $itemvalue = $2; + $itemvalue =~ s/\s*$//; + } + + # collecting the complete itemvalue + + $valuecounter = $counter; + $line = ${$scriptref}[$valuecounter]; + installer::remover::remove_leading_and_ending_whitespaces(\$line); + $itemvalue = $itemvalue . $line; + + while (!( $line =~ /\)\;\s*$/ )) + { + $valuecounter++; + $line = ${$scriptref}[$valuecounter]; + installer::remover::remove_leading_and_ending_whitespaces(\$line); + $itemvalue = $itemvalue . $line; + } + + # removing ending ";" + $itemvalue =~ s/\;\s*$//; + + $oneitemhash{$itemkey} = $itemvalue; + + if ( $itemkey =~ /^\s*\S+\s+\(\S+\)\s*$/ ) + { + $ismultilang = 1; + } + } + } + } + } + + $oneitemhash{'ismultilingual'} = $ismultilang; + + push(@allitemarray, \%oneitemhash); + } + } + + return \@allitemarray; +} + +###################################################################### +# Collecting all folder at folderitems, that are predefined values +# For example: PREDEFINED_AUTOSTART +###################################################################### + +sub add_predefined_folder +{ + my ( $folderitemref, $folderref ) = @_; + + for ( my $i = 0; $i <= $#{$folderitemref}; $i++ ) + { + my $folderitem = ${$folderitemref}[$i]; + my $folderid = $folderitem->{'FolderID'}; + + if ( $folderid =~ /PREDEFINED_/ ) + { + if (! installer::existence::exists_in_array_of_hashes("gid", $folderid, $folderref)) + { + my %folder = (); + $folder{'ismultilingual'} = "0"; + $folder{'Name'} = ""; + $folder{'gid'} = $folderid; + + push(@{$folderref}, \%folder); + } + } + } +} + +##################################################################################### +# If folderitems are non-advertised, the component needs to have a registry key +# below HKCU as key path. Therefore it is required, to mark the file belonging +# to a non-advertised shortcut, that a special userreg_xxx registry key can be +# created during packing process. +##################################################################################### + +sub prepare_non_advertised_files +{ + my ( $folderitemref, $filesref ) = @_; + + for ( my $i = 0; $i <= $#{$folderitemref}; $i++ ) + { + my $folderitem = ${$folderitemref}[$i]; + my $styles = ""; + if ( $folderitem->{'Styles'} ) { $styles = $folderitem->{'Styles'}; } + + if ( $styles =~ /\bNON_ADVERTISED\b/ ) + { + my $fileid = $folderitem->{'FileID'}; + if ( $folderitem->{'ComponentIDFile'} ) { $fileid = $folderitem->{'ComponentIDFile'}; } + my $onefile = installer::worker::find_file_by_id($filesref, $fileid); + + # Attention: If $onefile with "FileID" is not found, this is not always an error. + # FileID can also contain an executable file, for example msiexec.exe. + if ( $onefile ne "" ) { $onefile->{'needs_user_registry_key'} = 1; } + } + } +} + +##################################################################################### +# Adding all variables defined in the installation object into the hash +# of all variables from the zip list file. +# This is needed if variables are defined in the installation object, +# but not in the zip list file. +# If there is a definition in the zip list file and in the installation +# object, the installation object is more important +##################################################################################### + +sub add_installationobject_to_variables +{ + my ($allvariables, $allscriptvariablesref) = @_; + + for ( my $i = 0; $i <= $#{$allscriptvariablesref}; $i++ ) + { + my $line = ${$allscriptvariablesref}[$i]; + + if ( $line =~ /^\s*\%(\w+)\s+(.*?)\s*$/ ) + { + my $key = $1; + my $value = $2; + + $allvariables->{$key} = $value; # overwrite existing values from zip.lst + } + } +} + +##################################################################################### +# Adding all variables, that must be defined, but are not defined until now. +# List of this varibles: @installer::globals::forced_properties +##################################################################################### + +sub add_forced_properties +{ + my ($allvariables) = @_; + + my $property; + foreach $property ( @installer::globals::forced_properties ) + { + if ( ! exists($allvariables->{$property}) ) { $allvariables->{$property} = ""; } + } +} + +1; diff --git a/solenv/bin/modules/installer/simplepackage.pm b/solenv/bin/modules/installer/simplepackage.pm new file mode 100644 index 000000000000..0e5a588d3299 --- /dev/null +++ b/solenv/bin/modules/installer/simplepackage.pm @@ -0,0 +1,430 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: simplepackage.pm,v $ +# +# $Revision: 1.19.48.1 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::simplepackage; + +use Cwd; +use installer::download; +use installer::exiter; +use installer::globals; +use installer::logger; +use installer::strip; +use installer::systemactions; +use installer::worker; + +#################################################### +# Checking if the simple packager is required. +# This can be achieved by setting the global +# variable SIMPLE_PACKAGE in *.lst file or by +# setting the environment variable SIMPLE_PACKAGE. +#################################################### + +sub check_simple_packager_project +{ + my ( $allvariables ) = @_; + + if (( $installer::globals::packageformat eq "installed" ) || + ( $installer::globals::packageformat eq "archive" )) + { + $installer::globals::is_simple_packager_project = 1; + $installer::globals::patch_user_dir = 1; + } + elsif( $installer::globals::packageformat eq "dmg" ) + { + $installer::globals::is_simple_packager_project = 1; + } +} + +#################################################### +# Registering extensions +#################################################### + +sub register_extensions +{ + my ($officedir, $languagestringref) = @_; + + my $programdir = $officedir . $installer::globals::separator; + # if ( $installer::globals::sundirhostname ne "" ) { $programdir = $programdir . $installer::globals::sundirhostname . $installer::globals::separator; } + if ( $installer::globals::officedirhostname ne "" ) { $programdir = $programdir . $installer::globals::officedirhostname . $installer::globals::separator; } + $programdir = $programdir . "program"; + + my $from = cwd(); + chdir($programdir); + + my $infoline = ""; + + # my $unopkgfile = $officedir . $installer::globals::separator . "program" . + # $installer::globals::separator . $installer::globals::unopkgfile; + + my $unopkgfile = $installer::globals::unopkgfile; + + # my $extensiondir = $officedir . $installer::globals::separator . "share" . + # $installer::globals::separator . "extension" . + # $installer::globals::separator . "install"; + + my $extensiondir = ".." . $installer::globals::separator . "share" . $installer::globals::separator . "extension" . $installer::globals::separator . "install"; + + my $allextensions = installer::systemactions::find_file_with_file_extension("oxt", $extensiondir); + + if ( $#{$allextensions} > -1) + { + my $currentdir = cwd(); + print "... current dir: $currentdir ...\n"; + $infoline = "Current dir: $currentdir\n"; + push( @installer::globals::logfileinfo, $infoline); + + for ( my $i = 0; $i <= $#{$allextensions}; $i++ ) + { + my $oneextension = $extensiondir . $installer::globals::separator . ${$allextensions}[$i]; + + # my $systemcall = $unopkgfile . " add --shared " . "\"" . $oneextension . "\""; + + if ( ! -f $unopkgfile ) { installer::exiter::exit_program("ERROR: $unopkgfile not found!", "register_extensions"); } + if ( ! -f $oneextension ) { installer::exiter::exit_program("ERROR: $oneextension not found!", "register_extensions"); } + + my $localtemppath = installer::systemactions::create_directories("uno", $languagestringref); + + if ( $installer::globals::iswindowsbuild ) + { + if (( $^O =~ /cygwin/i ) && ( $ENV{'USE_SHELL'} ne "4nt" )) + { + $localtemppath = $installer::globals::cyg_temppath; + } + else + { + $windowsslash = "\/"; + } + $localtemppath =~ s/\\/\//g; + $localtemppath = "/".$localtemppath; + } + my $systemcall = $unopkgfile . " add --shared --verbose " . $oneextension . " -env:UserInstallation=file://" . $localtemppath . " 2\>\&1 |"; + + print "... $systemcall ...\n"; + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + my @unopkgoutput = (); + + open (UNOPKG, $systemcall); + while (<UNOPKG>) {push(@unopkgoutput, $_); } + close (UNOPKG); + + for ( my $j = 0; $j <= $#unopkgoutput; $j++ ) { push( @installer::globals::logfileinfo, "$unopkgoutput[$j]"); } + + my $returnvalue = $?; # $? contains the return value of the systemcall + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\nExitcode: '$returnvalue'\n"; + push( @installer::globals::logfileinfo, $infoline); + installer::exiter::exit_program("ERROR: $systemcall failed!", "register_extensions"); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + } + else + { + $infoline = "No extensions located in directory $extensiondir.\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + chdir($from); +} + +############################################# +# Creating the "simple" package. +# "zip" for Windows +# "dmg" on Mac OS X +# "tar.gz" for all other platforms +############################################# + +sub create_package +{ + my ( $installdir, $packagename, $allvariables, $includepatharrayref ) = @_; + + # moving dir into temporary directory + my $pid = $$; # process id + my $tempdir = $installdir . "_temp" . "." . $pid; + my $systemcall = ""; + my $from = ""; + my $return_to_start = 0; + installer::systemactions::rename_directory($installdir, $tempdir); + + # creating new directory with original name + installer::systemactions::create_directory($installdir); + + my $archive = $installdir . $installer::globals::separator . $packagename . $installer::globals::archiveformat; + + if ( $archive =~ /zip$/ ) + { + $from = cwd(); + $return_to_start = 1; + chdir($tempdir); + $systemcall = "$installer::globals::zippath -qr $archive ."; + # $systemcall = "$installer::globals::zippath -r $archive ."; + } + elsif ( $archive =~ /dmg$/ ) + { + installer::worker::put_scpactions_into_installset("$tempdir/$packagename"); + my $folder = (( -l "$tempdir/$packagename/Applications" ) or ( -l "$tempdir/$packagename/opt" )) ? $packagename : "\."; + + if ( $allvariables->{'PACK_INSTALLED'} ) { + $folder = $packagename; + } + + my $volume_name = $allvariables->{'PRODUCTNAME'} . ' ' . $allvariables->{'PRODUCTVERSION'}; + $volume_name = $volume_name . ' ' . $allvariables->{'PRODUCTEXTENSION'} if $allvariables->{'PRODUCTEXTENSION'}; + if ( $allvariables->{'DMG_VOLUMEEXTENSION'} ) { + $volume_name = $volume_name . ' ' . $allvariables->{'DMG_VOLUMEEXTENSION'}; + } + + my $sla = 'sla.r'; + my $ref = installer::scriptitems::get_sourcepath_from_filename_and_includepath( \$sla, $includepatharrayref, 0); + + $systemcall = "cd $tempdir && hdiutil makehybrid -hfs -hfs-openfolder $folder $folder -hfs-volume-name \"$volume_name\" -ov -o $installdir/tmp && hdiutil convert -ov -format UDZO $installdir/tmp.dmg -o $archive && "; + if ($$ref ne "") { + $systemcall .= "hdiutil unflatten $archive && Rez -a $$ref -o $archive && hdiutil flatten $archive &&"; + } + $systemcall .= "rm -f $installdir/tmp.dmg"; + } + else + { + # getting the path of the getuid.so (only required for Solaris and Linux) + my $getuidlibrary = ""; + my $ldpreloadstring = ""; + if (( $installer::globals::issolarisbuild ) || ( $installer::globals::islinuxbuild )) + { + $getuidlibrary = installer::download::get_path_for_library($includepatharrayref); + if ( $getuidlibrary ne "" ) { $ldpreloadstring = "LD_PRELOAD=" . $getuidlibrary; } + } + + $systemcall = "cd $tempdir; $ldpreloadstring tar -cf - . | gzip > $archive"; + } + + print "... $systemcall ...\n"; + my $returnvalue = system($systemcall); + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + if ( $return_to_start ) { chdir($from); } + + print "... removing $tempdir ...\n"; + installer::systemactions::remove_complete_directory($tempdir); +} + +#################################################### +# Main method for creating the simple package +# installation sets +#################################################### + +sub create_simple_package +{ + my ( $filesref, $dirsref, $scpactionsref, $linksref, $unixlinksref, $loggingdir, $languagestringref, $shipinstalldir, $allsettingsarrayref, $allvariables, $includepatharrayref ) = @_; + + # Creating directories + + my $current_install_number = ""; + my $infoline = ""; + + installer::logger::print_message( "... creating installation directory ...\n" ); + installer::logger::include_header_into_logfile("Creating installation directory"); + + $installer::globals::csp_installdir = installer::worker::create_installation_directory($shipinstalldir, $languagestringref, \$current_install_number); + $installer::globals::csp_installlogdir = installer::systemactions::create_directory_next_to_directory($installer::globals::csp_installdir, "log"); + + my $installdir = $installer::globals::csp_installdir; + my $installlogdir = $installer::globals::csp_installlogdir; + + # Setting package name (similar to the download name) + my $packagename = ""; + + if ( $installer::globals::packageformat eq "archive" || + $installer::globals::packageformat eq "dmg" ) + { + $installer::globals::csp_languagestring = $$languagestringref; + + my $locallanguage = $installer::globals::csp_languagestring; + + if ( $allvariables->{'OOODOWNLOADNAME'} ) + { + $packagename = installer::download::set_download_filename(\$locallanguage, $allvariables); + } + else + { + $downloadname = installer::ziplist::getinfofromziplist($allsettingsarrayref, "downloadname"); + $packagename = installer::download::resolve_variables_in_downloadname($allvariables, $$downloadname, \$locallanguage); + } + } + + # Creating subfolder in installdir, which shall become the root of package or zip file + my $subfolderdir = ""; + if ( $packagename ne "" ) { $subfolderdir = $installdir . $installer::globals::separator . $packagename; } + else { $subfolderdir = $installdir; } + + if ( ! -d $subfolderdir ) { installer::systemactions::create_directory($subfolderdir); } + + # Create directories, copy files and ScpActions + + installer::logger::print_message( "... creating directories ...\n" ); + installer::logger::include_header_into_logfile("Creating directories:"); + + for ( my $i = 0; $i <= $#{$dirsref}; $i++ ) + { + my $onedir = ${$dirsref}[$i]; + + if ( $onedir->{'HostName'} ) + { + my $destdir = $subfolderdir . $installer::globals::separator . $onedir->{'HostName'}; + if ( ! -d $destdir ) { installer::systemactions::create_directory_structure($destdir); } + } + } + + # stripping files ?! + if (( $installer::globals::strip ) && ( ! $installer::globals::iswindowsbuild )) { installer::strip::strip_libraries($filesref, $languagestringref); } + + # copy Files + installer::logger::print_message( "... copying files ...\n" ); + installer::logger::include_header_into_logfile("Copying files:"); + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + + if (( $onefile->{'Styles'} ) && ( $onefile->{'Styles'} =~ /\bBINARYTABLE_ONLY\b/ )) { next; } + + my $source = $onefile->{'sourcepath'}; + my $destination = $onefile->{'destination'}; + $destination = $subfolderdir . $installer::globals::separator . $destination; + + # Replacing $$ by $ is necessary to install files with $ in its name (back-masquerading) + # Otherwise, the following shell command does not work and the file list is not correct + $source =~ s/\$\$/\$/; + $destination =~ s/\$\$/\$/; + + installer::systemactions::copy_one_file($source, $destination); + + if (( ! $installer::globals::iswindowsbuild ) || + (( $^O =~ /cygwin/i ) && ( $ENV{'USE_SHELL'} ne "4nt" ))) + { + my $unixrights = ""; + if ( $onefile->{'UnixRights'} ) + { + $unixrights = $onefile->{'UnixRights'}; + + # special unix rights "555" on cygwin + if (( $^O =~ /cygwin/i ) && ( $ENV{'USE_SHELL'} ne "4nt" ) && ( $unixrights =~ /444/ )) { $unixrights = "555"; } + + my $localcall = "$installer::globals::wrapcmd chmod $unixrights \'$destination\' \>\/dev\/null 2\>\&1"; + system($localcall); + } + } + } + + # creating Links + + installer::logger::print_message( "... creating links ...\n" ); + installer::logger::include_header_into_logfile("Creating links:"); + + for ( my $i = 0; $i <= $#{$linksref}; $i++ ) + { + my $onelink = ${$linksref}[$i]; + my $destination = $onelink->{'destination'}; + $destination = $subfolderdir . $installer::globals::separator . $destination; + my $destinationfile = $onelink->{'destinationfile'}; + + my $localcall = "ln -sf \'$destinationfile\' \'$destination\' \>\/dev\/null 2\>\&1"; + system($localcall); + + $infoline = "Creating link: \"ln -sf $destinationfile $destination\"\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + for ( my $i = 0; $i <= $#{$unixlinksref}; $i++ ) + { + my $onelink = ${$unixlinksref}[$i]; + my $target = $onelink->{'Target'}; + my $destination = $subfolderdir . $installer::globals::separator . $onelink->{'destination'}; + + my $localcall = "ln -sf \'$target\' \'$destination\' \>\/dev\/null 2\>\&1"; + system($localcall); + + $infoline = "Creating Unix link: \"ln -sf $target $destination\"\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + # Registering the extensions + + installer::logger::print_message( "... registering extensions ...\n" ); + installer::logger::include_header_into_logfile("Registering extensions:"); + register_extensions($subfolderdir, $languagestringref); + + # Adding scpactions for mac installations sets, that use not dmg format. Without scpactions the + # office does not start. + + if (( $installer::globals::packageformat eq "installed" ) && ( $installer::globals::compiler =~ /^unxmacx/ )) + { + installer::worker::put_scpactions_into_installset("$installdir/$packagename"); + } + + # Creating archive file + if (( $installer::globals::packageformat eq "archive" ) || ( $installer::globals::packageformat eq "dmg" )) + { + # creating a package + # -> zip for Windows + # -> tar.gz for all other platforms + installer::logger::print_message( "... creating $installer::globals::packageformat file ...\n" ); + installer::logger::include_header_into_logfile("Creating $installer::globals::packageformat file:"); + create_package($installdir, $packagename, $allvariables, $includepatharrayref); + } + + # Analyzing the log file + + installer::worker::clean_output_tree(); # removing directories created in the output tree + installer::worker::analyze_and_save_logfile($loggingdir, $installdir, $installlogdir, $allsettingsarrayref, $languagestringref, $current_install_number); +} + +1; diff --git a/solenv/bin/modules/installer/sorter.pm b/solenv/bin/modules/installer/sorter.pm new file mode 100644 index 000000000000..080a20223e70 --- /dev/null +++ b/solenv/bin/modules/installer/sorter.pm @@ -0,0 +1,120 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: sorter.pm,v $ +# +# $Revision: 1.6 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::sorter; + +######################################### +# Sorting an array of hashes +######################################### + +sub sorting_array_of_hashes +{ + my ($arrayref, $sortkey) = @_; + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + my $onehashunder = ${$arrayref}[$i]; + my $sortvalueunder = $onehashunder->{$sortkey}; + + for ( my $j = $i + 1; $j <= $#{$arrayref}; $j++ ) + { + my $onehashover = ${$arrayref}[$j]; + my $sortvalueover = $onehashover->{$sortkey}; + + if ( $sortvalueunder gt $sortvalueover) + { + ${$arrayref}[$i] = $onehashover; + ${$arrayref}[$j] = $onehashunder; + + $onehashunder = $onehashover; + $sortvalueunder = $sortvalueover; + } + } + } +} + +###################################################### +# Sorting an array of hashes with a numerical value +###################################################### + +sub sort_array_of_hashes_numerically +{ + my ($arrayref, $sortkey) = @_; + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + my $onehashunder = ${$arrayref}[$i]; + my $sortvalueunder = $onehashunder->{$sortkey}; + + for ( my $j = $i + 1; $j <= $#{$arrayref}; $j++ ) + { + my $onehashover = ${$arrayref}[$j]; + my $sortvalueover = $onehashover->{$sortkey}; + + if ( $sortvalueunder > $sortvalueover) + { + ${$arrayref}[$i] = $onehashover; + ${$arrayref}[$j] = $onehashunder; + + $onehashunder = $onehashover; + $sortvalueunder = $sortvalueover; + } + } + } +} + +######################################### +# Sorting an array of of strings +######################################### + +sub sorting_array_of_strings +{ + my ($arrayref) = @_; + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + my $onestringunder = ${$arrayref}[$i]; + + for ( my $j = $i + 1; $j <= $#{$arrayref}; $j++ ) + { + my $onestringover = ${$arrayref}[$j]; + + if ( $onestringunder gt $onestringover) + { + ${$arrayref}[$i] = $onestringover; + ${$arrayref}[$j] = $onestringunder; + $onestringunder = $onestringover; + } + } + } +} + +1; diff --git a/solenv/bin/modules/installer/strip.pm b/solenv/bin/modules/installer/strip.pm new file mode 100644 index 000000000000..5a2f3b23947c --- /dev/null +++ b/solenv/bin/modules/installer/strip.pm @@ -0,0 +1,143 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: strip.pm,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::strip; + +use installer::converter; +use installer::existence; +use installer::globals; +use installer::logger; +use installer::pathanalyzer; +use installer::systemactions; + +##################################################################### +# Checking whether a file has to be stripped +##################################################################### + +sub need_to_strip +{ + my ( $filename ) = @_; + + my $strip = 0; + + # Check using the "file" command + + open (FILE, "file $filename |"); + my $fileoutput = <FILE>; + close (FILE); + + if (( $fileoutput =~ /not stripped/i ) && ( $fileoutput =~ /\bELF\b/ )) { $strip = 1; } + + return $strip +} + +##################################################################### +# Checking whether a file has to be stripped +##################################################################### + +sub do_strip +{ + my ( $filename ) = @_; + + my $systemcall = "strip" . " " . $filename; + + my $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not strip $filename!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "SUCCESS: Stripped library $filename!\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +##################################################################### +# Resolving all variables in the packagename. +##################################################################### + +sub strip_libraries +{ + my ( $filelist, $languagestringref ) = @_; + + installer::logger::include_header_into_logfile("Stripping files:"); + + my $strippeddirbase = installer::systemactions::create_directories("stripped", $languagestringref); + + if (! installer::existence::exists_in_array($strippeddirbase, \@installer::globals::removedirs)) + { + push(@installer::globals::removedirs, $strippeddirbase); + } + + for ( my $i = 0; $i <= $#{$filelist}; $i++ ) + { + my $sourcefilename = ${$filelist}[$i]->{'sourcepath'}; + + if ( need_to_strip($sourcefilename) ) + { + my $shortfilename = $sourcefilename; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$shortfilename); + + $infoline = "Strip: $shortfilename\n"; + push( @installer::globals::logfileinfo, $infoline); + + # copy file into directory for stripped libraries + + my $onelanguage = ${$filelist}[$i]->{'specificlanguage'}; + + # files without language into directory "00" + + if ($onelanguage eq "") { $onelanguage = "00"; } + + my $strippeddir = $strippeddirbase . $installer::globals::separator . $onelanguage; + installer::systemactions::create_directory($strippeddir); # creating language specific subdirectories + + my $destfilename = $strippeddir . $installer::globals::separator . $shortfilename; + installer::systemactions::copy_one_file($sourcefilename, $destfilename); + + # change sourcepath in files collector + + ${$filelist}[$i]->{'sourcepath'} = $destfilename; + + # strip file + + do_strip($destfilename); + } + } +} + +1; diff --git a/solenv/bin/modules/installer/substfilenamefiles.pm b/solenv/bin/modules/installer/substfilenamefiles.pm new file mode 100644 index 000000000000..c97b2ec6ec57 --- /dev/null +++ b/solenv/bin/modules/installer/substfilenamefiles.pm @@ -0,0 +1,173 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: substfilenamefiles.pm,v $ +# +# $Revision: 1.2 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::substfilenamefiles; + +use installer::exiter; +use installer::globals; +use installer::logger; +use installer::pathanalyzer; +use installer::systemactions; + +######################################################### +# Analyzing files with flag SCPZIP_REPLACE +# $item can be "File" or "ScpAction" +######################################################### + +sub resolving_subst_filename_flag +{ + my ($filesarrayref, $variableshashref, $languagestringref) = @_; + + my $diritem = lc($item); + + my $replacedirbase = installer::systemactions::create_directories("change_filename", $languagestringref); + + installer::logger::include_header_into_logfile("Files with flag SUBST_FILENAME:"); + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + my $styles = ""; + + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } + + if ( $styles =~ /\bSUBST_FILENAME\b/ ) + { + # Files with flag SUBST_FILENAME must have a "Substitute" key + if (( ! $onefile->{'Substitute'} ) && ( ! $onefile->{'InstallName'} )) + { + installer::exiter::exit_program("ERROR: SUBST_FILENAME is set, but no Substitute and no InstallName defined at file $onefile->{'gid'}!", "resolving_subst_filename_flag"); + } + + # Language specific subdirectory + my $onelanguage = $onefile->{'specificlanguage'}; + + if ($onelanguage eq "") + { + $onelanguage = "00"; # files without language into directory "00" + } + + my $replacedir = $replacedirbase . $installer::globals::separator . $onelanguage . $installer::globals::separator; + installer::systemactions::create_directory($replacedir); # creating language specific directories + + # copy files and edit them with the variables defined in the zip.lst + + my $longfilename = 0; + + my $onefilename = $onefile->{'Name'}; + + my $sourcepath = $onefile->{'sourcepath'}; + + # if ( $onefilename =~ /^\s*\Q$installer::globals::separator\E/ ) # filename begins with a slash, for instance /registry/schema/org/openoffice/VCL.xcs + if ( $onefilename =~ /\Q$installer::globals::separator\E/ ) # filename begins with a slash, for instance /registry/schema/org/openoffice/VCL.xcs + { + $onefilename =~ s/^\s*\Q$installer::globals::separator\E//; + $longfilename = 1; + } + + my $destinationpath = $replacedir . $onefilename; + my $movepath = $destinationpath . ".orig"; + my $destdir = $replacedir; + + if ( $longfilename ) # the destination directory has to be created before copying + { + $destdir = $movepath; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$destdir); + installer::systemactions::create_directory_structure($destdir); + } + + my $copysuccess = installer::systemactions::copy_one_file($sourcepath, $movepath); + + if ( $copysuccess ) + { + if ( $onefile->{'Substitute'} ) + { + my $substitute = $onefile->{'Substitute'}; + + my $newfilename = $destinationpath; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$newfilename); + eval '$newfilename =~ ' . "$substitute"; + + my $longnewfilename = $destdir . $newfilename; + + $copysuccess = installer::systemactions::copy_one_file($movepath, $longnewfilename); + + # Saving the new file name + $onefile->{'Name'} = $newfilename; + + # Saving the new destination + my $newdest = $onefile->{'destination'}; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$newdest); + $onefile->{'destination'} = $newdest . $newfilename; + + # Saving the original source, where the file was found + $onefile->{'originalsourcepath'} = $onefile->{'sourcepath'}; + + # Writing the new sourcepath into the hashref, even if it was not copied + $onefile->{'sourcepath'} = $longnewfilename; + } + else + { + if ( $onefile->{'InstallName'} ) + { + my $installname = $onefile->{'InstallName'}; + + my $newfilename = $destinationpath; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$newfilename); + + my $longnewfilename = $destdir . $installname; + + $copysuccess = installer::systemactions::copy_one_file($movepath, $longnewfilename); + + # Saving the new file name + $onefile->{'Name'} = $installname; + + # Saving the new destination + my $newdest = $onefile->{'destination'}; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$newdest); + $onefile->{'destination'} = $newdest . $installname; + + # Saving the original source, where the file was found + $onefile->{'originalsourcepath'} = $onefile->{'sourcepath'}; + + # Writing the new sourcepath into the hashref, even if it was not copied + $onefile->{'sourcepath'} = $longnewfilename; + } + } + } + } + } + + my $infoline = "\n"; + push( @installer::globals::logfileinfo, $infoline); +} + +1; diff --git a/solenv/bin/modules/installer/systemactions.pm b/solenv/bin/modules/installer/systemactions.pm new file mode 100644 index 000000000000..16cd938c6280 --- /dev/null +++ b/solenv/bin/modules/installer/systemactions.pm @@ -0,0 +1,1643 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: systemactions.pm,v $ +# +# $Revision: 1.38 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::systemactions; + +use Cwd; +use File::Copy; +use installer::converter; +use installer::exiter; +use installer::globals; +use installer::pathanalyzer; +use installer::remover; + +###################################################### +# Creating a new direcotory +###################################################### + +sub create_directory +{ + my ($directory) = @_; + + my $returnvalue = 1; + my $infoline = ""; + + if (!(-d $directory)) + { + $returnvalue = mkdir($directory, 0775); + + if ($returnvalue) + { + $infoline = "\nCreated directory: $directory\n"; + push(@installer::globals::logfileinfo, $infoline); + + if ( defined $ENV{'USE_SHELL'} && $ENV{'USE_SHELL'} ne "4nt" ) + { + my $localcall = "chmod 775 $directory \>\/dev\/null 2\>\&1"; + system($localcall); + } + } + else + { + # New solution in parallel packing: It is possible, that the directory now exists, although it + # was not created in this process. There is only an important error, if the directory does not + # exist now. + + $infoline = "\nDid not succeed in creating directory: \"$directory\". Further attempts will follow.\n"; + push(@installer::globals::logfileinfo, $infoline); + + if (!(-d $directory)) + { + # Problem with parallel packaging? -> Try a little harder, before exiting. + # Did someone else remove the parent directory in the meantime? + my $parentdir = $directory; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$parentdir); + if (!(-d $parentdir)) + { + $returnvalue = mkdir($parentdir, 0775); + + if ($returnvalue) + { + $infoline = "\nAttention: Successfully created parent directory (should already be created before): $parentdir\n"; + push(@installer::globals::logfileinfo, $infoline); + + if ( defined $ENV{'USE_SHELL'} && $ENV{'USE_SHELL'} ne "4nt" ) + { + my $localcall = "chmod 775 $parentdir \>\/dev\/null 2\>\&1"; + system($localcall); + } + } + else + { + $infoline = "\Error: \"$directory\" could not be created. Even the parent directory \"$parentdir\" does not exist and could not be created.\n"; + push(@installer::globals::logfileinfo, $infoline); + if ( -d $parentdir ) + { + $infoline = "\nAttention: Finally the parent directory \"$parentdir\" exists, but I could not create it.\n"; + push(@installer::globals::logfileinfo, $infoline); + } + else + { + # Now it is time to exit, even the parent could not be created. + installer::exiter::exit_program("ERROR: Could not create parent directory \"$parentdir\"", "create_directory"); + } + } + } + + # At this point we have to assume, that the parent directory exist. + # Trying once more to create the desired directory + + $returnvalue = mkdir($directory, 0775); + + if ($returnvalue) + { + $infoline = "\nAttention: Created directory \"$directory\" in the second try.\n"; + push(@installer::globals::logfileinfo, $infoline); + + if ( defined $ENV{'USE_SHELL'} && $ENV{'USE_SHELL'} ne "4nt" ) + { + my $localcall = "chmod 775 $directory \>\/dev\/null 2\>\&1"; + system($localcall); + } + } + else + { + if ( -d $directory ) + { + $infoline = "\nAttention: Finally the directory \"$directory\" exists, but I could not create it.\n"; + push(@installer::globals::logfileinfo, $infoline); + } + else + { + # It is time to exit, even the second try failed. + installer::exiter::exit_program("ERROR: Failed to create the directory: $directory", "create_directory"); + } + } + } + else + { + $infoline = "\nAnother process created this directory in exactly this moment :-) : $directory\n"; + push(@installer::globals::logfileinfo, $infoline); + } + } + } + else + { + $infoline = "\nAlready existing directory, did not create: $directory\n"; + push(@installer::globals::logfileinfo, $infoline); + } +} + +###################################################### +# Creating a new direcotory with defined privileges +###################################################### + +sub create_directory_with_privileges +{ + my ($directory, $privileges) = @_; + + my $returnvalue = 1; + my $infoline = ""; + + if (!(-d $directory)) + { + my $localprivileges = oct("0".$privileges); # changes "777" to 0777 + $returnvalue = mkdir($directory, $localprivileges); + + if ($returnvalue) + { + $infoline = "\nCreated directory: $directory\n"; + push(@installer::globals::logfileinfo, $infoline); + + if ( defined $ENV{'USE_SHELL'} && $ENV{'USE_SHELL'} ne "4nt" ) + { + my $localcall = "chmod $privileges $directory \>\/dev\/null 2\>\&1"; + system($localcall); + } + } + else + { + # New solution in parallel packing: It is possible, that the directory now exists, although it + # was not created in this process. There is only an important error, if the directory does not + # exist now. + + $infoline = "\nDid not succeed in creating directory: \"$directory\". Further attempts will follow.\n"; + push(@installer::globals::logfileinfo, $infoline); + + if (!(-d $directory)) + { + # Problem with parallel packaging? -> Try a little harder, before exiting. + # Did someone else remove the parent directory in the meantime? + my $parentdir = $directory; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$parentdir); + if (!(-d $parentdir)) + { + $returnvalue = mkdir($directory, $localprivileges); + + if ($returnvalue) + { + $infoline = "\nAttention: Successfully created parent directory (should already be created before): $parentdir\n"; + push(@installer::globals::logfileinfo, $infoline); + + if ( defined $ENV{'USE_SHELL'} && $ENV{'USE_SHELL'} ne "4nt" ) + { + my $localcall = "chmod $privileges $parentdir \>\/dev\/null 2\>\&1"; + system($localcall); + } + } + else + { + $infoline = "\Error: \"$directory\" could not be created. Even the parent directory \"$parentdir\" does not exist and could not be created.\n"; + push(@installer::globals::logfileinfo, $infoline); + if ( -d $parentdir ) + { + $infoline = "\nAttention: Finally the parent directory \"$parentdir\" exists, but I could not create it.\n"; + push(@installer::globals::logfileinfo, $infoline); + } + else + { + # Now it is time to exit, even the parent could not be created. + installer::exiter::exit_program("ERROR: Could not create parent directory \"$parentdir\"", "create_directory_with_privileges"); + } + } + } + + # At this point we have to assume, that the parent directory exist. + # Trying once more to create the desired directory + + $returnvalue = mkdir($directory, $localprivileges); + + if ($returnvalue) + { + $infoline = "\nAttention: Created directory \"$directory\" in the second try.\n"; + push(@installer::globals::logfileinfo, $infoline); + + if ( defined $ENV{'USE_SHELL'} && $ENV{'USE_SHELL'} ne "4nt" ) + { + my $localcall = "chmod $privileges $directory \>\/dev\/null 2\>\&1"; + system($localcall); + } + } + else + { + if ( -d $directory ) + { + $infoline = "\nAttention: Finally the directory \"$directory\" exists, but I could not create it.\n"; + push(@installer::globals::logfileinfo, $infoline); + } + else + { + # It is time to exit, even the second try failed. + installer::exiter::exit_program("ERROR: Failed to create the directory: $directory", "create_directory_with_privileges"); + } + } + } + else + { + $infoline = "\nAnother process created this directory in exactly this moment :-) : $directory\n"; + push(@installer::globals::logfileinfo, $infoline); + } + } + } + else + { + $infoline = "\nAlready existing directory, did not create: $directory\n"; + push(@installer::globals::logfileinfo, $infoline); + + if ( defined $ENV{'USE_SHELL'} && $ENV{'USE_SHELL'} ne "4nt" ) + { + my $localcall = "chmod $privileges $directory \>\/dev\/null 2\>\&1"; + system($localcall); + } + } +} + +###################################################### +# Removing a new direcotory +###################################################### + +sub remove_empty_directory +{ + my ($directory) = @_; + + my $returnvalue = 1; + + if (-d $directory) + { + my $systemcall = "rmdir $directory"; + + $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not remove \"$directory\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Removed \"$directory\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } +} + +####################################################################### +# Creating the directories, in which files are generated or unzipped +####################################################################### + +sub create_directories +{ + my ($newdirectory, $languagesref) =@_; + + $installer::globals::unpackpath =~ s/\Q$installer::globals::separator\E\s*$//; # removing ending slashes and backslashes + + my $path = ""; + + if (( $newdirectory eq "uno" ) || ( $newdirectory eq "zip" ) || ( $newdirectory eq "cab" ) || ( $newdirectory =~ /rdb\s*$/i )) # special handling for zip files, cab files and services file because of performance reasons + { + if ( $installer::globals::temppathdefined ) { $path = $installer::globals::temppath; } + else { $path = $installer::globals::unpackpath; } + $path =~ s/\Q$installer::globals::separator\E\s*$//; # removing ending slashes and backslashes + $path = $path . $installer::globals::separator; + } + elsif ( ( $newdirectory eq "jds" ) ) + { + if ( $installer::globals::jdstemppathdefined ) { $path = $installer::globals::jdstemppath; } + else { $path = $installer::globals::unpackpath; } + $path =~ s/\Q$installer::globals::separator\E\s*$//; # removing ending slashes and backslashes + $path = $path . $installer::globals::separator; + installer::systemactions::create_directory($path); + } + else + { + $path = $installer::globals::unpackpath . $installer::globals::separator; + } + + $infoline = "create_directories: Using $path for $newdirectory !\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($newdirectory eq "unzip" ) # special handling for common directory + { + $path = $path . ".." . $installer::globals::separator . "common" . $installer::globals::productextension . $installer::globals::separator; + create_directory($path); + + $path = $path . $newdirectory . $installer::globals::separator; + create_directory($path); + } + else + { + my $localproductname = $installer::globals::product; + my $localproductsubdir = ""; + + if ( $installer::globals::product =~ /^\s*(.+?)\_\_(.+?)\s*$/ ) + { + $localproductname = $1; + $localproductsubdir = $2; + } + + if ( $installer::globals::languagepack ) { $path = $path . $localproductname . "_languagepack" . $installer::globals::separator; } + elsif ( $installer::globals::patch ) { $path = $path . $localproductname . "_patch" . $installer::globals::separator; } + else { $path = $path . $localproductname . $installer::globals::separator; } + + create_directory($path); + + if ( $localproductsubdir ) + { + $path = $path . $localproductsubdir . $installer::globals::separator; + create_directory($path); + } + + $path = $path . $installer::globals::installertypedir . $installer::globals::separator; + create_directory($path); + + $path = $path . $newdirectory . $installer::globals::separator; + create_directory($path); + + my $locallanguagesref = ""; + + if ( $$languagesref ) { $locallanguagesref = $$languagesref; } + + if (!($locallanguagesref eq "" )) # this will be a path like "01_49", for Profiles and ConfigurationFiles, idt-Files + { + my $languagestring = $$languagesref; + + if (length($languagestring) > $installer::globals::max_lang_length ) + { + chomp(my $shorter = `echo $languagestring | md5sum | sed -e "s/ .*//g"`); + $languagestring = $shorter; + } + + $path = $path . $languagestring . $installer::globals::separator; + create_directory($path); + } + } + + installer::remover::remove_ending_pathseparator(\$path); + + $path = installer::converter::make_path_conform($path); + + return $path; +} + +######################## +# Copying one file +######################## + +sub copy_one_file +{ + my ($source, $dest) = @_; + + my ($returnvalue, $infoline); + + my $copyreturn = copy($source, $dest); + + if ($copyreturn) + { + $infoline = "Copy: $source to $dest\n"; + $returnvalue = 1; + } + else + { + $infoline = "ERROR: Could not copy $source to $dest\n"; + $returnvalue = 0; + } + + push(@installer::globals::logfileinfo, $infoline); + + if ( !$returnvalue ) { + return $returnvalue; + } + + # taking care of file attributes + if ($installer::globals::iswin && -f $dest) { + my $mode = -x $source ? 0775 : 0664; + my $mode_str = sprintf("%o", $mode); + my $chmodreturn = chmod($mode, $dest); + if ($chmodreturn) + { + $infoline = "chmod $mode_str, $dest\n"; + $returnvalue = 1; + } + else + { + $infoline = "WARNING: Could not chmod $dest: $!\n"; + $returnvalue = 0; + } + + push(@installer::globals::logfileinfo, $infoline); + } + + return $returnvalue; +} + +########################## +# Hard linking one file +########################## + +sub hardlink_one_file +{ + my ($source, $dest) = @_; + + my ($returnvalue, $infoline); + + my $copyreturn = link($source, $dest); + + if ($copyreturn) + { + $infoline = "Link: $source to $dest\n"; + $returnvalue = 1; + } + else + { + $infoline = "ERROR: Could not link $source to $dest\n"; + $returnvalue = 0; + } + + push(@installer::globals::logfileinfo, $infoline); + + return $returnvalue; +} + +########################## +# Soft linking one file +########################## + +sub softlink_one_file +{ + my ($source, $dest) = @_; + + my ($returnvalue, $infoline); + + my $linkreturn = symlink($source, $dest); + + if ($linkreturn) + { + $infoline = "Symlink: $source to $dest\n"; + $returnvalue = 1; + } + else + { + $infoline = "ERROR: Could not symlink $source to $dest\n"; + $returnvalue = 0; + } + + push(@installer::globals::logfileinfo, $infoline); + + return $returnvalue; +} + +######################## +# Renaming one file +######################## + +sub rename_one_file +{ + my ($source, $dest) = @_; + + my ($returnvalue, $infoline); + + my $renamereturn = rename($source, $dest); + + if ($renamereturn) + { + $infoline = "Rename: $source to $dest\n"; + $returnvalue = 1; + } + else + { + $infoline = "ERROR: Could not rename $source to $dest\n"; + $returnvalue = 0; + } + + push(@installer::globals::logfileinfo, $infoline); + + return $returnvalue; +} + +########################################## +# Copying all files from one directory +# to another directory +########################################## + +sub copy_directory +{ + my ($sourcedir, $destdir) = @_; + + my @sourcefiles = (); + + $sourcedir =~ s/\Q$installer::globals::separator\E\s*$//; + $destdir =~ s/\Q$installer::globals::separator\E\s*$//; + + my $infoline = "\n"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = "Copying files from directory $sourcedir to directory $destdir\n"; + push(@installer::globals::logfileinfo, $infoline); + + opendir(DIR, $sourcedir); + @sourcefiles = readdir(DIR); + closedir(DIR); + + my $onefile; + + foreach $onefile (@sourcefiles) + { + if ((!($onefile eq ".")) && (!($onefile eq ".."))) + { + my $sourcefile = $sourcedir . $installer::globals::separator . $onefile; + my $destfile = $destdir . $installer::globals::separator . $onefile; + if ( -f $sourcefile ) # only files, no directories + { + copy_one_file($sourcefile, $destfile); + } + } + } +} + +########################################## +# Copying all files from one directory +# to another directory +########################################## + +sub is_empty_dir +{ + my ($dir) = @_; + + my $directory_is_empty = 1; + my @sourcefiles = (); + + opendir(DIR, $dir); + @sourcefiles = readdir(DIR); + closedir(DIR); + + my $onefile; + my @realcontent = (); + + foreach $onefile (@sourcefiles) + { + if ((!($onefile eq ".")) && (!($onefile eq ".."))) + { + push(@realcontent, $onefile); + } + } + + if ( $#realcontent > -1 ) { $directory_is_empty = 0; } + + return $directory_is_empty; +} + +##################################################################### +# Creating hard links to a complete directory with sub directories. +##################################################################### + +sub hardlink_complete_directory +{ + my ($sourcedir, $destdir) = @_; + + my @sourcefiles = (); + + $sourcedir =~ s/\Q$installer::globals::separator\E\s*$//; + $destdir =~ s/\Q$installer::globals::separator\E\s*$//; + + if ( ! -d $destdir ) { create_directory($destdir); } + + my $infoline = "\n"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = "Creating hard links for all files from directory $sourcedir to directory $destdir\n"; + push(@installer::globals::logfileinfo, $infoline); + + opendir(DIR, $sourcedir); + @sourcefiles = readdir(DIR); + closedir(DIR); + + my $onefile; + + foreach $onefile (@sourcefiles) + { + if ((!($onefile eq ".")) && (!($onefile eq ".."))) + { + my $source = $sourcedir . $installer::globals::separator . $onefile; + my $dest = $destdir . $installer::globals::separator . $onefile; + if ( -f $source ) # only files, no directories + { + hardlink_one_file($source, $dest); + } + if ( -d $source ) # recursive + { + hardlink_complete_directory($source, $dest); + } + } + } +} + +##################################################################### +# Creating hard links to a complete directory with sub directories. +##################################################################### + +sub softlink_complete_directory +{ + my ($sourcedir, $destdir, $depth) = @_; + + my @sourcefiles = (); + + $sourcedir =~ s/\Q$installer::globals::separator\E\s*$//; + $destdir =~ s/\Q$installer::globals::separator\E\s*$//; + + if ( ! -d $destdir ) { create_directory($destdir); } + + my $infoline = "\n"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = "Creating soft links for all files from directory $sourcedir to directory $destdir\n"; + push(@installer::globals::logfileinfo, $infoline); + + opendir(DIR, $sourcedir); + @sourcefiles = readdir(DIR); + closedir(DIR); + + my $onefile; + + foreach $onefile (@sourcefiles) + { + if ((!($onefile eq ".")) && (!($onefile eq ".."))) + { + my $source = $sourcedir . $installer::globals::separator . $onefile; + my $dest = $destdir . $installer::globals::separator . $onefile; + if ( -f $source ) # only files, no directories + { + my $localsource = $source; + if ( $depth > 0 ) { for ( my $i = 1; $i <= $depth; $i++ ) { $localsource = "../" . $localsource; } } + softlink_one_file($localsource, $dest); + } + if ( -d $source ) # recursive + { + my $newdepth = $depth + 1; + softlink_complete_directory($source, $dest, $newdepth); + } + } + } +} + +##################################################### +# Copying a complete directory with sub directories. +##################################################### + +sub copy_complete_directory +{ + my ($sourcedir, $destdir) = @_; + + my @sourcefiles = (); + + $sourcedir =~ s/\Q$installer::globals::separator\E\s*$//; + $destdir =~ s/\Q$installer::globals::separator\E\s*$//; + + if ( ! -d $destdir ) { create_directory($destdir); } + + my $infoline = "\n"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = "Copying files from directory $sourcedir to directory $destdir\n"; + push(@installer::globals::logfileinfo, $infoline); + + opendir(DIR, $sourcedir); + @sourcefiles = readdir(DIR); + closedir(DIR); + + my $onefile; + + foreach $onefile (@sourcefiles) + { + if ((!($onefile eq ".")) && (!($onefile eq ".."))) + { + my $source = $sourcedir . $installer::globals::separator . $onefile; + my $dest = $destdir . $installer::globals::separator . $onefile; + if ( -f $source ) # only files, no directories + { + copy_one_file($source, $dest); + } + if ( -d $source ) # recursive + { + if ((!( $source =~ /packages\/SUNW/ )) && (!( $source =~ /packages\/OOO/ ))) # do not copy complete Solaris packages! + { + copy_complete_directory($source, $dest); + } + } + } + } +} + +##################################################################################### +# Copying a complete directory with sub directories, but not the CVS directories. +##################################################################################### + +sub copy_complete_directory_without_cvs +{ + my ($sourcedir, $destdir) = @_; + + my @sourcefiles = (); + + $sourcedir =~ s/\Q$installer::globals::separator\E\s*$//; + $destdir =~ s/\Q$installer::globals::separator\E\s*$//; + + if ( ! -d $destdir ) { create_directory($destdir); } + + my $infoline = "\n"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = "Copying files from directory $sourcedir to directory $destdir (without CVS)\n"; + push(@installer::globals::logfileinfo, $infoline); + + opendir(DIR, $sourcedir); + @sourcefiles = readdir(DIR); + closedir(DIR); + + my $onefile; + + foreach $onefile (@sourcefiles) + { + if ((!($onefile eq ".")) && (!($onefile eq "..")) && (!($onefile eq "CVS"))) + { + my $source = $sourcedir . $installer::globals::separator . $onefile; + my $dest = $destdir . $installer::globals::separator . $onefile; + if ( -f $source ) # only files, no directories + { + copy_one_file($source, $dest); + } + if ( -d $source ) # recursive + { + copy_complete_directory_without_cvs($source, $dest); + } + } + } +} + +##################################################### +# Copying all files with a specified file extension +# from one directory to another directory. +##################################################### + +sub copy_directory_with_fileextension +{ + my ($sourcedir, $destdir, $extension) = @_; + + my @sourcefiles = (); + + $sourcedir =~ s/\Q$installer::globals::separator\E\s*$//; + $destdir =~ s/\Q$installer::globals::separator\E\s*$//; + + $infoline = "\n"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = "Copying files with extension $extension from directory $sourcedir to directory $destdir\n"; + push(@installer::globals::logfileinfo, $infoline); + + opendir(DIR, $sourcedir); + @sourcefiles = readdir(DIR); + closedir(DIR); + + my $onefile; + + foreach $onefile (@sourcefiles) + { + if ((!($onefile eq ".")) && (!($onefile eq ".."))) + { + if ( $onefile =~ /\.$extension\s*$/ ) # only copying specified files + { + my $sourcefile = $sourcedir . $installer::globals::separator . $onefile; + my $destfile = $destdir . $installer::globals::separator . $onefile; + if ( -f $sourcefile ) # only files, no directories + { + copy_one_file($sourcefile, $destfile); + } + } + } + } +} + +######################################################### +# Copying all files without a specified file extension +# from one directory to another directory. +######################################################### + +sub copy_directory_except_fileextension +{ + my ($sourcedir, $destdir, $extension) = @_; + + my @sourcefiles = (); + + $sourcedir =~ s/\Q$installer::globals::separator\E\s*$//; + $destdir =~ s/\Q$installer::globals::separator\E\s*$//; + + $infoline = "\n"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = "Copying files without extension $extension from directory $sourcedir to directory $destdir\n"; + push(@installer::globals::logfileinfo, $infoline); + + opendir(DIR, $sourcedir); + @sourcefiles = readdir(DIR); + closedir(DIR); + + my $onefile; + + foreach $onefile (@sourcefiles) + { + if ((!($onefile eq ".")) && (!($onefile eq ".."))) + { + if ( ! ( $onefile =~ /\.$extension\s*$/ )) # only copying not having the specified extension + { + my $sourcefile = $sourcedir . $installer::globals::separator . $onefile; + my $destfile = $destdir . $installer::globals::separator . $onefile; + if ( -f $sourcefile ) # only files, no directories + { + copy_one_file($sourcefile, $destfile); + } + } + } + } +} + +######################################################## +# Renaming all files with a specified file extension +# in a specified directory. +# Example: "Feature.idt.01" -> "Feature.idt" +######################################################## + +sub rename_files_with_fileextension +{ + my ($dir, $extension) = @_; + + my @sourcefiles = (); + + $dir =~ s/\Q$installer::globals::separator\E\s*$//; + + my $infoline = "\n"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = "Renaming files with extension \"$extension\" in the directory $dir\n"; + push(@installer::globals::logfileinfo, $infoline); + + opendir(DIR, $dir); + @sourcefiles = readdir(DIR); + closedir(DIR); + + my $onefile; + + foreach $onefile (@sourcefiles) + { + if ((!($onefile eq ".")) && (!($onefile eq ".."))) + { + if ( $onefile =~ /^\s*(\S.*?)\.$extension\s*$/ ) # only renaming specified files + { + my $destfile = $1; + my $sourcefile = $dir . $installer::globals::separator . $onefile; + $destfile = $dir . $installer::globals::separator . $destfile; + if ( -f $sourcefile ) # only files, no directories + { + rename_one_file($sourcefile, $destfile); + } + } + } + } +} + +######################################################## +# Finding all files with a specified file extension +# in a specified directory. +######################################################## + +sub find_file_with_file_extension +{ + my ($extension, $dir) = @_; + + my @allfiles = (); + + $dir =~ s/\Q$installer::globals::separator\E\s*$//; + + my $infoline = "\n"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = "Searching files with extension \"$extension\" in the directory $dir\n"; + push(@installer::globals::logfileinfo, $infoline); + + opendir(DIR, $dir); + @sourcefiles = readdir(DIR); + closedir(DIR); + + my $onefile; + + foreach $onefile (@sourcefiles) + { + if ((!($onefile eq ".")) && (!($onefile eq ".."))) + { + if ( $onefile =~ /^\s*(\S.*?)\.$extension\s*$/ ) + { + push(@allfiles, $onefile) + } + } + } + + return \@allfiles; +} + +############################################################## +# Creating a unique directory, for example "01_inprogress_7" +# in the install directory. +############################################################## + +sub make_numbered_dir +{ + my ($newstring, $olddir) = @_; + + my $basedir = $olddir; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$basedir); + + my $alldirs = get_all_directories($basedir); + + # searching for the highest number extension + + my $maxnumber = 0; + + for ( my $i = 0; $i <= $#{$alldirs}; $i++ ) + { + if ( ${$alldirs}[$i] =~ /\_(\d+)\s*$/ ) + { + my $number = $1; + if ( $number > $maxnumber ) { $maxnumber = $number; } + } + } + + my $newnumber = $maxnumber + 1; + + my $newdir = $olddir . "_" . $newstring . "_" . $newnumber; + + my $returndir = ""; + + if ( move($olddir, $newdir) ) + { + $infoline = "\nMoved directory from $olddir to $newdir\n"; + push(@installer::globals::logfileinfo, $infoline); + $returndir = $newdir; + } + else + { + $infoline = "\nATTENTION: Could not move directory from $olddir to $newdir, \"make_numbered_dir\"\n"; + push(@installer::globals::logfileinfo, $infoline); + $returndir = $olddir; + } + + return $returndir; +} + +############################################################## +# Determining the highest number in the install directory. +############################################################## + +sub determine_maximum_number +{ + my ($dir, $languagestringref) = @_; + + my $basedir = $dir; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$basedir); + + my $alldirs = get_all_directories($basedir); + + my $maxnumber = 1; + + # In control.pm the installation directory is determined as: + # $installer::globals::build . "_" . $installer::globals::lastminor . "_" . + # "native_inprogress-number_" . $$languagesref . "\." . $installer::globals::buildid; + + # searching for the highest number extension after the first "-", which belongs to + # $installer::globals::build, $installer::globals::lastminor and $installer::globals::buildid + # In this step not looking for the language! + + my @correctbuildiddirs = (); + + for ( my $i = 0; $i <= $#{$alldirs}; $i++ ) + { + my $onedir = ${$alldirs}[$i]; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$onedir); + + if ( $onedir =~ /^\s*\Q$installer::globals::build\E\_\Q$installer::globals::lastminor\E\_(.*?)\-(\d+)\_(.*?)\.\Q$installer::globals::buildid\E\s*$/ ) + { + my $number = $2; + if ( $number > $maxnumber ) { $maxnumber = $number; } + push(@correctbuildiddirs, $onedir); + } + } + + # From all directories with correct $installer::globals::build, $installer::globals::lastminor + # and $installer::globals::buildid, those directories, which already have the maximum number + # have to be selected + + my @maximumnumberdirs = (); + + for ( my $i = 0; $i <= $#correctbuildiddirs; $i++ ) + { + my $onedir = $correctbuildiddirs[$i]; + + if ( $onedir =~ /^\s*(.*?)\-(\d+)\_(.*?)\.(.*?)\s*$/ ) + { + my $number = $2; + + if ( $number == $maxnumber ) + { + push(@maximumnumberdirs, $onedir); + } + } + } + + # @maximumnumberdirs contains only those directories with correct $installer::globals::build, + # $installer::globals::lastminor and $installer::globals::buildid, which already have the maximum number. + # If the current language is part of this directory, the number has to be increased. + + my $increase_counter = 0; + + for ( my $i = 0; $i <= $#maximumnumberdirs; $i++ ) + { + my $onedir = $maximumnumberdirs[$i]; + + if ( $onedir =~ /^\s*(.*?)\-(\d+)\_(.*?)\.(.*?)\s*$/ ) + { + my $number = $2; + my $languagestring = $3; + + if ( $languagestring eq $$languagestringref ) + { + $increase_counter = 1; + } + } + } + + if ( $increase_counter ) + { + $maxnumber = $maxnumber + 1; + } + + return $maxnumber; +} + +##################################################################################### +# Renaming a directory by exchanging a string, for example from "01_inprogress_7" +# to "01_witherror_7". +##################################################################################### + +sub rename_string_in_directory +{ + my ($olddir, $oldstring, $newstring) = @_; + + my $newdir = $olddir; + my $infoline = ""; + + $newdir =~ s/$oldstring/$newstring/g; + + if (( -d $newdir ) && ( $olddir ne $newdir )) { remove_complete_directory($newdir, 1); } + + if ( move($olddir, $newdir) ) + { + $infoline = "\nMoved directory from $olddir to $newdir\n"; + push(@installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "\nATTENTION: Could not move directory from $olddir to $newdir, \"rename_string_in_directory\"\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + return $newdir; +} + +###################################################### +# Returning the complete directory name, +# input is the first part of the directory name. +###################################################### + +sub get_directoryname +{ + my ($searchdir, $startstring) = @_; + + my $dirname = ""; + my $founddir = 0; + my $direntry; + + opendir(DIR, $searchdir); + + foreach $direntry (readdir (DIR)) + { + next if $direntry eq "."; + next if $direntry eq ".."; + + if (( -d $direntry ) && ( $direntry =~ /^\s*\Q$startstring\E/ )) + { + $dirname = $direntry; + $founddir = 1; + last; + } + } + + closedir(DIR); + + if ( ! $founddir ) { installer::exiter::exit_program("ERROR: Did not find directory beginning with $startstring in directory $searchdir", "get_directoryname"); } + + return $dirname; +} + + +################################### +# Renaming a directory +################################### + +sub rename_directory +{ + my ($olddir, $newdir) = @_; + + my $infoline = ""; + + if ( move($olddir, $newdir) ) + { + $infoline = "\nMoved directory from $olddir to $newdir\n"; + push(@installer::globals::logfileinfo, $infoline); + } + else + { + installer::exiter::exit_program("ERROR: Could not move directory from $olddir to $newdir", "rename_directory"); + # $infoline = "\nATTENTION: Could not move directory from $olddir to $newdir, \"rename_directory\"\n"; + # push(@installer::globals::logfileinfo, $infoline); + } + + return $newdir; +} + +############################################################## +# Creating a directory next to an existing directory +############################################################## + +sub create_directory_next_to_directory +{ + my ($topdir, $dirname) = @_; + + my $basedir = $topdir; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$basedir); + + $basedir =~ s/\Q$installer::globals::separator\E\s*$//; + + my $newdir = $basedir . $installer::globals::separator . $dirname; + + create_directory($newdir); + + return $newdir; +} + +############################################################## +# Collecting all directories inside a directory +############################################################## + +sub get_all_directories +{ + my ($basedir) = @_; + + my @alldirs = (); + my $direntry; + + $basedir =~ s/\Q$installer::globals::separator\E\s*$//; + + opendir(DIR, $basedir); + + foreach $direntry (readdir (DIR)) + { + next if $direntry eq "."; + next if $direntry eq ".."; + + my $completeentry = $basedir . $installer::globals::separator . $direntry; + + if ( -d $completeentry ) { push(@alldirs, $completeentry); } + } + + closedir(DIR); + + return \@alldirs; +} + +############################################################## +# Collecting all directories inside a directory +# Returning without path +############################################################## + +sub get_all_directories_without_path +{ + my ($basedir) = @_; + + my @alldirs = (); + my $direntry; + + $basedir =~ s/\Q$installer::globals::separator\E\s*$//; + + opendir(DIR, $basedir); + + foreach $direntry (readdir (DIR)) + { + next if $direntry eq "."; + next if $direntry eq ".."; + + my $completeentry = $basedir . $installer::globals::separator . $direntry; + + if ( -d $completeentry ) { push(@alldirs, $direntry); } + } + + closedir(DIR); + + return \@alldirs; +} + +############################################################## +# Collecting all files inside one directory +############################################################## + +sub get_all_files_from_one_directory +{ + my ($basedir) = @_; + + my @allfiles = (); + my $direntry; + + $basedir =~ s/\Q$installer::globals::separator\E\s*$//; + + opendir(DIR, $basedir); + + foreach $direntry (readdir (DIR)) + { + next if $direntry eq "."; + next if $direntry eq ".."; + + my $completeentry = $basedir . $installer::globals::separator . $direntry; + + if ( -f $completeentry ) { push(@allfiles, $completeentry); } + } + + closedir(DIR); + + return \@allfiles; +} + +############################################################## +# Collecting all files inside one directory +############################################################## + +sub get_all_files_from_one_directory_without_path +{ + my ($basedir) = @_; + + my @allfiles = (); + my $direntry; + + $basedir =~ s/\Q$installer::globals::separator\E\s*$//; + + opendir(DIR, $basedir); + + foreach $direntry (readdir (DIR)) + { + next if $direntry eq "."; + next if $direntry eq ".."; + + my $completeentry = $basedir . $installer::globals::separator . $direntry; + + if ( -f $completeentry ) { push(@allfiles, $direntry); } + } + + closedir(DIR); + + return \@allfiles; +} + +############################################################## +# Collecting all files and directories inside one directory +############################################################## + +sub read_directory +{ + my ($basedir) = @_; + + my @allcontent = (); + my $direntry; + + $basedir =~ s/\Q$installer::globals::separator\E\s*$//; + + opendir(DIR, $basedir); + + foreach $direntry (readdir (DIR)) + { + next if $direntry eq "."; + next if $direntry eq ".."; + + my $completeentry = $basedir . $installer::globals::separator . $direntry; + + if (( -f $completeentry ) || ( -d $completeentry )) { push(@allcontent, $completeentry); } + } + + closedir(DIR); + + return \@allcontent; +} + +############################################################## +# Finding the new content in a directory +############################################################## + +sub find_new_content_in_directory +{ + my ( $basedir, $oldcontent ) = @_; + + my @newcontent = (); + my @allcontent = (); + + my $direntry; + + $basedir =~ s/\Q$installer::globals::separator\E\s*$//; + + opendir(DIR, $basedir); + + foreach $direntry (readdir (DIR)) + { + next if $direntry eq "."; + next if $direntry eq ".."; + + my $completeentry = $basedir . $installer::globals::separator . $direntry; + + if (( -f $completeentry ) || ( -d $completeentry )) + { + push(@allcontent, $completeentry); + if (! installer::existence::exists_in_array($completeentry, $oldcontent)) + { + push(@newcontent, $completeentry); + } + } + } + + closedir(DIR); + + return (\@newcontent, \@allcontent); +} + +############################################################## +# Trying to create a directory, no error if this fails +############################################################## + +sub try_to_create_directory +{ + my ($directory) = @_; + + my $returnvalue = 1; + my $created_directory = 0; + + if (!(-d $directory)) + { + $returnvalue = mkdir($directory, 0775); + + if ($returnvalue) + { + $created_directory = 1; + $infoline = "\nCreated directory: $directory\n"; + push(@installer::globals::logfileinfo, $infoline); + + if ( defined $ENV{'USE_SHELL'} && $ENV{'USE_SHELL'} ne "4nt" ) + { + my $localcall = "chmod 775 $directory \>\/dev\/null 2\>\&1"; + system($localcall); + } + } + else + { + $created_directory = 0; + } + } + else + { + $created_directory = 1; + } + + return $created_directory; +} + +############################################################## +# Creating a complete directory structure +############################################################## + +sub create_directory_structure +{ + my ($directory) = @_; + + if ( ! try_to_create_directory($directory) ) + { + my $parentdir = $directory; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$parentdir); + + my $infoline = "INFO: Did not create directory $directory\n"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = "Now trying to create parent directory $parentdir\n"; + push(@installer::globals::logfileinfo, $infoline); + + create_directory_structure($parentdir); # recursive + } + + create_directory($directory); # now it has to succeed +} + +###################################################### +# Removing a complete directory with subdirectories +###################################################### + +sub remove_complete_directory +{ + my ($directory, $start) = @_; + + my @content = (); + my $infoline = ""; + + $directory =~ s/\Q$installer::globals::separator\E\s*$//; + + if ( -d $directory ) + { + if ( $start ) + { + $infoline = "\n"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = "Removing directory $directory\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + opendir(DIR, $directory); + @content = readdir(DIR); + closedir(DIR); + + my $oneitem; + + foreach $oneitem (@content) + { + if ((!($oneitem eq ".")) && (!($oneitem eq ".."))) + { + my $item = $directory . $installer::globals::separator . $oneitem; + + if ( -f $item || -l $item ) # deleting files or links + { + unlink($item); + } + + if ( -d $item ) # recursive + { + remove_complete_directory($item, 0); + } + } + } + + # try to remove empty directory + + my $returnvalue = rmdir $directory; + + if ( ! $returnvalue ) + { + $infoline = "Warning: Problem with removing empty dir $directory\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + # try a little bit harder (sometimes there is a performance problem) + if ( -d $directory ) + { + for ( my $j = 1; $j <= 3; $j++ ) + { + if ( -d $directory ) + { + $infoline = "\n"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = "Warning (Try $j): Problems with removing directory $directory\n"; + push(@installer::globals::logfileinfo, $infoline); + + $returnvalue = rmdir $directory; + + if ( $returnvalue ) + { + $infoline = "Successfully removed empty dir $directory\n"; + push(@installer::globals::logfileinfo, $infoline); + } else { + $infoline = "Warning: rmdir $directory failed.\n"; + push(@installer::globals::logfileinfo, $infoline); + } + } + } + } + } +} + +###################################################### +# Creating a unique directory with number extension +###################################################### + +sub create_unique_directory +{ + my ($directory) = @_; + + $directory =~ s/\Q$installer::globals::separator\E\s*$//; + $directory = $directory . "_INCREASINGNUMBER"; + + my $counter = 1; + my $created = 0; + my $localdirectory = ""; + + do + { + $localdirectory = $directory; + $localdirectory =~ s/INCREASINGNUMBER/$counter/; + $counter++; + + if ( ! -d $localdirectory ) + { + create_directory($localdirectory); + $created = 1; + } + } + while ( ! $created ); + + return $localdirectory; +} + +###################################################### +# Creating a unique directory with pid extension +###################################################### + +sub create_pid_directory +{ + my ($directory) = @_; + + $directory =~ s/\Q$installer::globals::separator\E\s*$//; + my $pid = $$; # process id + my $time = time(); # time + + $directory = $directory . "_" . $pid . $time; + + if ( ! -d $directory ) { create_directory($directory); } + else { installer::exiter::exit_program("ERROR: Directory $directory already exists!", "create_pid_directory"); } + + return $directory; +} + +############################################################## +# Reading all files from a directory and its subdirectories +############################################################## + +sub read_complete_directory +{ + my ($directory, $pathstring, $filecollector) = @_; + + my @content = (); + opendir(DIR, $directory); + @content = readdir(DIR); + closedir(DIR); + + my $onefile; + + foreach $onefile (@content) + { + if ((!($onefile eq ".")) && (!($onefile eq ".."))) + { + my $completefilename = $directory . $installer::globals::separator . $onefile; + my $sep = ""; + if ( $pathstring ne "" ) { $sep = $installer::globals::separator; } + + if ( ! -d $completefilename ) # only files, no directories + { + my $content = $pathstring . $sep . $onefile; + push(@{$filecollector}, $content); + } + else # recursive for directories + { + my $newpathstring = $pathstring . $sep . $onefile; + read_complete_directory($completefilename, $newpathstring, $filecollector); + } + } + } +} + +1; diff --git a/solenv/bin/modules/installer/upx.pm b/solenv/bin/modules/installer/upx.pm new file mode 100644 index 000000000000..ebdd859a87d2 --- /dev/null +++ b/solenv/bin/modules/installer/upx.pm @@ -0,0 +1,160 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: upx.pm,v $ +# +# $Revision: 1.3 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::upx; + +use installer::converter; +use installer::existence; +use installer::globals; +use installer::logger; +use installer::pathanalyzer; +use installer::scriptitems; +use installer::systemactions; + +##################################################################### +# Checking whether a file has to be stripped +##################################################################### + +sub is_upx_candidate +{ + my ( $filename, $onefile ) = @_; + + my $useupx = 0; + + if (( $filename =~ /\.so\s*$/ ) || + ( $filename =~ /\.dll\s*$/ ) || + ( $filename =~ /\.exe\s*$/ ) || + ( $filename =~ /\.bin\s*$/ )) + { + my $styles = ""; + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } + if ( ! ( $styles =~ /\bDONT_UPX\b/ )) { $useupx = 1; } + } + + return $useupx; +} + +##################################################################### +# Checking whether a file has to be stripped +##################################################################### + +sub do_upx +{ + my ( $filename ) = @_; + + my $compression = "9"; + my $systemcall = $installer::globals::upxfile . " -" . $compression . " " . $filename; + + my $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "WARNING: Could not successfully upx $filename! Using original file.\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "SUCCESS: upx $filename!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + return $returnvalue; +} + +##################################################################### +# Using upx to decrease file size +##################################################################### + +sub upx_on_libraries +{ + my ( $filelist, $languagestringref) = @_; + + installer::logger::include_header_into_logfile("UPX'ing files:"); + my $infoline = ""; + + if ( ! $installer::globals::upx_in_path ) + { + $infoline = "\n\nWarning: This is an UPX product, but upx was not found in PATH!\n\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Using upx: $installer::globals::upxfile\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $upxdirbase = installer::systemactions::create_directories("upx", $languagestringref); + + if (! installer::existence::exists_in_array($upxdirbase, \@installer::globals::removedirs)) + { + push(@installer::globals::removedirs, $upxdirbase); + } + + for ( my $i = 0; $i <= $#{$filelist}; $i++ ) + { + my $sourcefilename = ${$filelist}[$i]->{'sourcepath'}; + + if ( is_upx_candidate($sourcefilename, ${$filelist}[$i]) ) + { + my $shortfilename = $sourcefilename; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$shortfilename); + + $infoline = "\nUpx: $shortfilename"; + push( @installer::globals::logfileinfo, $infoline); + + # copy file into directory for stripped libraries + my $onelanguage = ${$filelist}[$i]->{'specificlanguage'}; + + # files without language into directory "00" + if ($onelanguage eq "") { $onelanguage = "00"; } + + my $upxdir = $upxdirbase . $installer::globals::separator . $onelanguage; + installer::systemactions::create_directory($upxdir); # creating language specific subdirectories + + my $destfilename = $upxdir . $installer::globals::separator . $shortfilename; + installer::systemactions::copy_one_file($sourcefilename, $destfilename); + + # change sourcepath in files collector + ${$filelist}[$i]->{'sourcepath'} = $destfilename; + + # do upx on file + my $return = do_upx($destfilename); + + # Using original file, if upx was not successful (no reason for error) + if ( $return ) { ${$filelist}[$i]->{'sourcepath'} = $sourcefilename; } + } + } + } +} + +1; diff --git a/solenv/bin/modules/installer/windows/admin.pm b/solenv/bin/modules/installer/windows/admin.pm new file mode 100644 index 000000000000..0c8a7ff9912c --- /dev/null +++ b/solenv/bin/modules/installer/windows/admin.pm @@ -0,0 +1,769 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: admin.pm,v $ +# +# $Revision: 1.1.2.2 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::admin; + +use File::Copy; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::pathanalyzer; +use installer::systemactions; +use installer::windows::idtglobal; + +################################################################################# +# Unpacking cabinet files with expand +################################################################################# + +sub unpack_cabinet_file +{ + my ($cabfilename, $unpackdir) = @_; + + my $infoline = "Unpacking cabinet file: $cabfilename\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $expandfile = "expand.exe"; # Has to be in the path + my $expandlogfile = $unpackdir . $installer::globals::separator . "expand.log"; + + # exclude cabinet file + # my $systemcall = $cabarc . " -o X " . $mergemodulehash->{'cabinetfile'}; + + my $systemcall = ""; + if ( $^O =~ /cygwin/i ) { + my $localunpackdir = qx{cygpath -w "$unpackdir"}; + $localunpackdir =~ s/\\/\\\\/g; + $systemcall = $expandfile . " " . $cabfilename . " -F:\\\* " . $localunpackdir; + } + else + { + $systemcall = $expandfile . " " . $cabfilename . " -F:\* " . $unpackdir . " \> " . $expandlogfile; + } + + my $returnvalue = system($systemcall); + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute $systemcall !\n"; + push( @installer::globals::logfileinfo, $infoline); + installer::exiter::exit_program("ERROR: Could not extract cabinet file: $mergemodulehash->{'cabinetfile'} !", "change_file_table"); + } + else + { + $infoline = "Success: Executed $systemcall successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +################################################################################# +# Include tables into a msi database +################################################################################# + +sub include_tables_into_pcpfile +{ + my ($fullmsidatabasepath, $workdir, $tables) = @_; + + my $msidb = "msidb.exe"; # Has to be in the path + my $infoline = ""; + my $systemcall = ""; + my $returnvalue = ""; + + # Make all table 8+3 conform + my $alltables = installer::converter::convert_stringlist_into_array(\$tables, " "); + + for ( my $i = 0; $i <= $#{$alltables}; $i++ ) + { + my $tablename = ${$alltables}[$i]; + $tablename =~ s/\s*$//; + my $namelength = length($tablename); + if ( $namelength > 8 ) + { + my $newtablename = substr($tablename, 0, 8); # name, offset, length + my $oldfile = $workdir . $installer::globals::separator . $tablename . ".idt"; + my $newfile = $workdir . $installer::globals::separator . $newtablename . ".idt"; + if ( -f $newfile ) { unlink $newfile; } + installer::systemactions::copy_one_file($oldfile, $newfile); + my $savfile = $oldfile . ".orig"; + installer::systemactions::copy_one_file($oldfile, $savfile); + } + } + + # Import of tables + + $systemcall = $msidb . " -d " . $fullmsidatabasepath . " -f " . $workdir . " -i " . $tables; + + $returnvalue = system($systemcall); + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute $systemcall !\n"; + push( @installer::globals::logfileinfo, $infoline); + installer::exiter::exit_program("ERROR: Could not include tables into msi database: $fullmsidatabasepath !", "include_tables_into_pcpfile"); + } + else + { + $infoline = "Success: Executed $systemcall successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +################################################################################# +# Extracting tables from msi database +################################################################################# + +sub extract_tables_from_pcpfile +{ + my ($fullmsidatabasepath, $workdir, $tablelist) = @_; + + my $msidb = "msidb.exe"; # Has to be in the path + my $infoline = ""; + my $systemcall = ""; + my $returnvalue = ""; + + # Export of all tables by using "*" + + $systemcall = $msidb . " -d " . $fullmsidatabasepath . " -f " . $workdir . " -e $tablelist"; + $returnvalue = system($systemcall); + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute $systemcall !\n"; + push( @installer::globals::logfileinfo, $infoline); + installer::exiter::exit_program("ERROR: Could not exclude tables from pcp file: $fullmsidatabasepath !", "extract_tables_from_pcpfile"); + } + else + { + $infoline = "Success: Executed $systemcall successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +################################################################################ +# Analyzing the content of Directory.idt +################################################################################# + +sub analyze_directory_file +{ + my ($filecontent) = @_; + + my %table = (); + + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; } + + if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\s*$/ ) + { + my $dir = $1; + my $parent = $2; + my $name = $3; + + if ( $name =~ /^\s*(.*?)\s*\:\s*(.*?)\s*$/ ) { $name = $2; } + if ( $name =~ /^\s*(.*?)\s*\|\s*(.*?)\s*$/ ) { $name = $2; } + + my %helphash = (); + $helphash{'Directory_Parent'} = $parent; + $helphash{'DefaultDir'} = $name; + $table{$dir} = \%helphash; + } + } + + return \%table; +} + +################################################################################# +# Analyzing the content of Component.idt +################################################################################# + +sub analyze_component_file +{ + my ($filecontent) = @_; + + my %table = (); + + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; } + + if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) + { + my $component = $1; + my $dir = $3; + + $table{$component} = $dir; + } + } + + return \%table; +} + +################################################################################# +# Analyzing the full content of Component.idt +################################################################################# + +sub analyze_keypath_component_file +{ + my ($filecontent) = @_; + + my %keypathtable = (); + + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; } + + if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) + { + my $component = $1; + my $keypath = $6; + + $keypathtable{$keypath} = $component; + } + } + + return (\%keypathtable); + +} + +################################################################################# +# Analyzing the content of Registry.idt +################################################################################# + +sub analyze_registry_file +{ + my ($filecontent) = @_; + + my %table = (); + + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; } + + if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) + { + my $registry = $1; + my $root = $2; + my $key = $3; + my $name = $4; + my $value = $5; + my $component = $6; + + my %helphash = (); + # $helphash{'Registry'} = $registry; + $helphash{'Root'} = $root; + $helphash{'Key'} = $key; + $helphash{'Name'} = $name; + $helphash{'Value'} = $value; + $helphash{'Component'} = $component; + + $table{$registry} = \%helphash; + } + } + + return \%table; +} + +################################################################################# +# Analyzing the content of File.idt +################################################################################# + +sub analyze_file_file +{ + my ($filecontent) = @_; + + my %table = (); + my %fileorder = (); + my $maxsequence = 0; + + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; } + + if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) + { + my $file = $1; + my $comp = $2; + my $filename = $3; + my $sequence = $8; + + if ( $filename =~ /^\s*(.*?)\s*\|\s*(.*?)\s*$/ ) { $filename = $2; } + + my %helphash = (); + $helphash{'Component'} = $comp; + $helphash{'FileName'} = $filename; + $helphash{'Sequence'} = $sequence; + + $table{$file} = \%helphash; + + $fileorder{$sequence} = $file; + + if ( $sequence > $maxsequence ) { $maxsequence = $sequence; } + } + } + + return (\%table, \%fileorder, $maxsequence); +} + +#################################################################################### +# Recursively creating the directory tree +#################################################################################### + +sub create_directory_tree +{ + my ($parent, $pathcollector, $fulldir, $dirhash) = @_; + + foreach my $dir ( keys %{$dirhash} ) + { + if (( $dirhash->{$dir}->{'Directory_Parent'} eq $parent ) && ( $dirhash->{$dir}->{'DefaultDir'} ne "." )) + { + my $dirname = $dirhash->{$dir}->{'DefaultDir'}; + # Create the directory + my $newdir = $fulldir . $installer::globals::separator . $dirname; + if ( ! -f $newdir ) { mkdir $newdir; } + # Saving in collector + $pathcollector->{$dir} = $newdir; + # Iteration + create_directory_tree($dir, $pathcollector, $newdir, $dirhash); + } + } +} + +#################################################################################### +# Creating the directory tree +#################################################################################### + +sub create_directory_structure +{ + my ($dirhash, $targetdir) = @_; + + my %fullpathhash = (); + + my @startparents = ("TARGETDIR", "INSTALLLOCATION"); + + foreach $dir (@startparents) { create_directory_tree($dir, \%fullpathhash, $targetdir, $dirhash); } + + return \%fullpathhash; +} + +#################################################################################### +# Copying files into installation set +#################################################################################### + +sub copy_files_into_directory_structure +{ + my ($fileorder, $filehash, $componenthash, $fullpathhash, $maxsequence, $unpackdir, $installdir, $dirhash) = @_; + + for ( my $i = 1; $i <= $maxsequence; $i++ ) + { + if ( exists($fileorder->{$i}) ) + { + my $file = $fileorder->{$i}; + if ( ! exists($filehash->{$file}->{'Component'}) ) { installer::exiter::exit_program("ERROR: Did not find component for file: \"$file\".", "copy_files_into_directory_structure"); } + my $component = $filehash->{$file}->{'Component'}; + if ( ! exists($componenthash->{$component}) ) { installer::exiter::exit_program("ERROR: Did not find directory for component: \"$component\".", "copy_files_into_directory_structure"); } + my $dirname = $componenthash->{$component}; + if ( ! exists($fullpathhash->{$dirname}) ) { installer::exiter::exit_program("ERROR: Did not find full directory path for dir: \"$dirname\".", "copy_files_into_directory_structure"); } + my $destdir = $fullpathhash->{$dirname}; + if ( ! exists($filehash->{$file}->{'FileName'}) ) { installer::exiter::exit_program("ERROR: Did not find \"FileName\" for file: \"$file\".", "copy_files_into_directory_structure"); } + my $destfile = $filehash->{$file}->{'FileName'}; + + $destfile = $destdir . $installer::globals::separator . $destfile; + my $sourcefile = $unpackdir . $installer::globals::separator . $file; + + if ( ! -f $sourcefile ) + { + # It is possible, that this was an unpacked file + # Looking in the dirhash, to find the subdirectory in the installation set (the id is $dirname) + # subdir is not recursively analyzed, only one directory. + + my $oldsourcefile = $sourcefile; + my $subdir = ""; + if ( exists($dirhash->{$dirname}->{'DefaultDir'}) ) { $subdir = $dirhash->{$dirname}->{'DefaultDir'} . $installer::globals::separator; } + my $realfilename = $filehash->{$file}->{'FileName'}; + my $localinstalldir = $installdir; + + $localinstalldir =~ s/\\\s*$//; + $localinstalldir =~ s/\/\s*$//; + + $sourcefile = $localinstalldir . $installer::globals::separator . $subdir . $realfilename; + + if ( ! -f $sourcefile ) + { + installer::exiter::exit_program("ERROR: File not found: \"$oldsourcefile\" (or \"$sourcefile\").", "copy_files_into_directory_structure"); + } + } + + my $copyreturn = copy($sourcefile, $destfile); + + if ( ! $copyreturn) # only logging problems + { + my $infoline = "ERROR: Could not copy $sourcefile to $destfile (insufficient disc space for $destfile ?)\n"; + $returnvalue = 0; + push(@installer::globals::logfileinfo, $infoline); + installer::exiter::exit_program($infoline, "copy_files_into_directory_structure"); + } + + # installer::systemactions::copy_one_file($sourcefile, $destfile); + } + # else # allowing missing sequence numbers ? + # { + # installer::exiter::exit_program("ERROR: No file assigned to sequence $i", "copy_files_into_directory_structure"); + # } + } +} + + +############################################################### +# Setting the time string for the +# Summary Information stream in the +# msi database of the admin installations. +############################################################### + +sub get_sis_time_string +{ + # Syntax: <yyyy/mm/dd hh:mm:ss> + my $second = (localtime())[0]; + my $minute = (localtime())[1]; + my $hour = (localtime())[2]; + my $day = (localtime())[3]; + my $month = (localtime())[4]; + my $year = 1900 + (localtime())[5]; + + $month++; # zero based month + + if ( $second < 10 ) { $second = "0" . $second; } + if ( $minute < 10 ) { $minute = "0" . $minute; } + if ( $hour < 10 ) { $hour = "0" . $hour; } + if ( $day < 10 ) { $day = "0" . $day; } + if ( $month < 10 ) { $month = "0" . $month; } + + my $timestring = $year . "/" . $month . "/" . $day . " " . $hour . ":" . $minute . ":" . $second; + + return $timestring; +} + +############################################################### +# Windows registry entries containing properties are not set +# correctly during msp patch process. The properties are +# empty or do get their default values. This destroys the +# values of many entries in Windows registry. +# This can be fixed by removing all entries in Registry table, +# containing a property before starting msimsp.exe. +############################################################### + +sub remove_properties_from_registry_table +{ + my ($registryhash, $componentkeypathhash, $registryfilecontent) = @_; + + installer::logger::include_timestamp_into_logfile("\nPerformance Info: Start remove_properties_from_registry_table"); + + my @registrytable = (); + + # Registry hash + # Collecting all RegistryItems with values containing a property: [...] + # To which component do they belong + # Is this after removal an empty component? Create a replacement, so that + # no Component has to be removed. + # Is this RegistryItem a KeyPath of a component. Then it cannot be removed. + + my %problemitems = (); + my %problemcomponents = (); + my %securecomponents = (); + my $changevalue = ""; + my $changeroot = ""; + my $infoline = ""; + + my $newitemcounter = 0; + my $olditemcounter = 0; + + foreach my $regitem ( keys %{$registryhash} ) + { + my $value = ""; + if ( exists($registryhash->{$regitem}->{'Value'}) ) { $value = $registryhash->{$regitem}->{'Value'}; } + + if ( $value =~ /^.*(\[.*?\]).*$/ ) + { + my $property = $1; + + # Collecting registry item + $problemitems{$regitem} = 1; # "1" -> can be removed + if ( exists($componentkeypathhash->{$regitem}) ) { $problemitems{$regitem} = 2; } # "2" -> cannot be removed, KeyPath + + # Collecting component (and number of problematic registry items + # my $component = $registryhash->{$regitem}->{'Component'}; + # if ( exists($problemcomponents{$regitem}) ) { $problemcomponents{$regitem} = $problemcomponents{$regitem} + 1; } + # else { $problemcomponents{$regitem} = 1; } + } + else + { + # Collecting all components with secure regisry items + my $component = ""; + if ( exists($registryhash->{$regitem}->{'Component'}) ) { $component = $registryhash->{$regitem}->{'Component'}; } + if ( $component eq "" ) { installer::exiter::exit_program("ERROR: Did not find component for registry item \"$regitem\".", "remove_properties_from_registry_table"); } + $securecomponents{$component} = 1; + } + + # Searching for change value + my $localkey = ""; + if ( exists($registryhash->{$regitem}->{'Key'}) ) { $localkey = $registryhash->{$regitem}->{'Key'}; } + if (( $localkey =~ /^\s*(Software\\.*\\)StartMenu\s*$/ ) && ( $changevalue eq "" )) + { + $changevalue = $1; + $changeroot = $registryhash->{$regitem}->{'Root'}; + } + + $olditemcounter++; + } + + my $removecounter = 0; + my $renamecounter = 0; + + foreach my $regitem ( keys %{$registryhash} ) + { + my $value = ""; + if ( exists($registryhash->{$regitem}->{'Value'}) ) { $value = $registryhash->{$regitem}->{'Value'}; } + + if ( $value =~ /^.*(\[.*?\]).*$/ ) + { + # Removing registry items, that are no KeyPath and that belong to components, + # that have other secure registry items. + + my $component = ""; + if ( exists($registryhash->{$regitem}->{'Component'}) ) { $component = $registryhash->{$regitem}->{'Component'}; } + if ( $component eq "" ) { installer::exiter::exit_program("ERROR: Did not find component for registry item (2) \"$regitem\".", "remove_properties_from_registry_table"); } + + if (( $problemitems{$regitem} == 1 ) && ( exists($securecomponents{$component}) )) + { + # remove complete registry item + delete($registryhash->{$regitem}); + $removecounter++; + $infoline = "Removing registry item: $regitem : $value\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + # Changing values of registry items, that are KeyPath or that contain to + # components with only unsecure registry items. + + if (( $problemitems{$regitem} == 2 ) || ( ! exists($securecomponents{$component}) )) + { + # change value of registry item + if ( $changevalue eq "" ) { installer::exiter::exit_program("ERROR: Did not find good change value for registry items", "remove_properties_from_registry_table"); } + + my $oldkey = ""; + if ( exists($registryhash->{$regitem}->{'Key'}) ) { $oldkey = $registryhash->{$regitem}->{'Key'}; }; + my $oldname = ""; + if ( exists($registryhash->{$regitem}->{'Name'}) ) { $oldname = $registryhash->{$regitem}->{'Name'}; } + my $oldvalue = ""; + if ( exists($registryhash->{$regitem}->{'Value'}) ) { $oldvalue = $registryhash->{$regitem}->{'Value'}; } + + $registryhash->{$regitem}->{'Key'} = $changevalue . "RegistryItem"; + $registryhash->{$regitem}->{'Root'} = $changeroot; + $registryhash->{$regitem}->{'Name'} = $regitem; + $registryhash->{$regitem}->{'Value'} = 1; + $renamecounter++; + + $infoline = "Changing registry item: $regitem\n"; + $infoline = "Old: $oldkey : $oldname : $oldvalue\n"; + $infoline = "New: $registryhash->{$regitem}->{'Key'} : $registryhash->{$regitem}->{'Name'} : $registryhash->{$regitem}->{'Value'}\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + } + } + + $infoline = "Number of removed registry items: $removecounter\n"; + push( @installer::globals::logfileinfo, $infoline); + $infoline = "Number of changed registry items: $renamecounter\n"; + push( @installer::globals::logfileinfo, $infoline); + + # Creating the new content of Registry table + # First three lines from $registryfilecontent + # All further files from changed $registryhash + + for ( my $i = 0; $i <= 2; $i++ ) { push(@registrytable, ${$registryfilecontent}[$i]); } + + foreach my $regitem ( keys %{$registryhash} ) + { + my $root = ""; + if ( exists($registryhash->{$regitem}->{'Root'}) ) { $root = $registryhash->{$regitem}->{'Root'}; } + else { installer::exiter::exit_program("ERROR: Did not find root in registry table for item: \"$regitem\".", "remove_properties_from_registry_table"); } + my $localkey = ""; + if ( exists($registryhash->{$regitem}->{'Key'}) ) { $localkey = $registryhash->{$regitem}->{'Key'}; } + my $name = ""; + if ( exists($registryhash->{$regitem}->{'Name'}) ) { $name = $registryhash->{$regitem}->{'Name'}; } + my $value = ""; + if ( exists($registryhash->{$regitem}->{'Value'}) ) { $value = $registryhash->{$regitem}->{'Value'}; } + my $comp = ""; + if ( exists($registryhash->{$regitem}->{'Component'}) ) { $comp = $registryhash->{$regitem}->{'Component'}; } + + my $oneline = $regitem . "\t" . $root . "\t" . $localkey . "\t" . $name . "\t" . $value . "\t" . $comp . "\n"; + push(@registrytable, $oneline); + + $newitemcounter++; + } + + $infoline = "Number of registry items: $newitemcounter. Old value: $olditemcounter.\n"; + push( @installer::globals::logfileinfo, $infoline); + + installer::logger::include_timestamp_into_logfile("\nPerformance Info: End remove_properties_from_registry_table"); + + return (\@registrytable); +} + +############################################################### +# Writing content of administrative installations into +# Summary Information Stream of msi database. +# This is required for example for following +# patch processes using Windows Installer service. +############################################################### + +sub write_sis_info +{ + my ($msidatabase) = @_ ; + + if ( ! -f $msidatabase ) { installer::exiter::exit_program("ERROR: Cannot find file $msidatabase", "write_sis_info"); } + + my $msiinfo = "msiinfo.exe"; # Has to be in the path + my $infoline = ""; + my $systemcall = ""; + my $returnvalue = ""; + + # Required setting for administrative installations: + # -w 4 (source files are unpacked), wordcount + # -s <date of admin installation>, LastPrinted, Syntax: <yyyy/mm/dd hh:mm:ss> + # -l <person_making_admin_installation>, LastSavedBy + + my $wordcount = 4; # Unpacked files + my $lastprinted = get_sis_time_string(); + my $lastsavedby = "Installer"; + + $systemcall = $msiinfo . " " . "\"" . $msidatabase . "\"" . " -w " . $wordcount . " -s " . "\"" . $lastprinted . "\"" . " -l $lastsavedby"; + push(@installer::globals::logfileinfo, $systemcall); + $returnvalue = system($systemcall); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute $systemcall !\n"; + push(@installer::globals::logfileinfo, $infoline); + installer::exiter::exit_program($infoline, "write_sis_info"); + } +} + +#################################################################################### +# Simulating an administrative installation +#################################################################################### + +sub make_admin_install +{ + my ($databasepath, $targetdir) = @_; + + # Create helper directory + + installer::logger::print_message( "... installing $databasepath in directory $targetdir ...\n" ); + + my $helperdir = $targetdir . $installer::globals::separator . "installhelper"; + installer::systemactions::create_directory($helperdir); + + # Get File.idt, Component.idt and Directory.idt from database + + my $tablelist = "File Directory Component Registry"; + extract_tables_from_pcpfile($databasepath, $helperdir, $tablelist); + + # Unpack all cab files into $helperdir, cab files must be located next to msi database + my $installdir = $databasepath; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$installdir); + my $databasefilename = $databasepath; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$databasefilename); + + my $cabfiles = installer::systemactions::find_file_with_file_extension("cab", $installdir); + + if ( $#{$cabfiles} < 0 ) { installer::exiter::exit_program("ERROR: Did not find any cab file in directory $installdir", "make_admin_install"); } + + # Set unpackdir + my $unpackdir = $helperdir . $installer::globals::separator . "unpack"; + installer::systemactions::create_directory($unpackdir); + + for ( my $i = 0; $i <= $#{$cabfiles}; $i++ ) + { + my $cabfile = $installdir . $installer::globals::separator . ${$cabfiles}[$i]; + unpack_cabinet_file($cabfile, $unpackdir); + } + + # Reading tables + my $filename = $helperdir . $installer::globals::separator . "Directory.idt"; + my $filecontent = installer::files::read_file($filename); + my $dirhash = analyze_directory_file($filecontent); + + $filename = $helperdir . $installer::globals::separator . "Component.idt"; + my $componentfilecontent = installer::files::read_file($filename); + my $componenthash = analyze_component_file($componentfilecontent); + + $filename = $helperdir . $installer::globals::separator . "File.idt"; + $filecontent = installer::files::read_file($filename); + my ( $filehash, $fileorder, $maxsequence ) = analyze_file_file($filecontent); + + # Creating the directory structure + my $fullpathhash = create_directory_structure($dirhash, $targetdir); + + # Copying files + copy_files_into_directory_structure($fileorder, $filehash, $componenthash, $fullpathhash, $maxsequence, $unpackdir, $installdir, $dirhash); + + my $msidatabase = $targetdir . $installer::globals::separator . $databasefilename; + installer::systemactions::copy_one_file($databasepath, $msidatabase); + + # Editing registry table because of wrong Property value + # my $registryfilename = $helperdir . $installer::globals::separator . "Registry.idt"; + # my $componentfilename = $helperdir . $installer::globals::separator . "Component.idt"; + # my $componentkeypathhash = analyze_keypath_component_file($componentfilecontent); + + # my $registryfilecontent = installer::files::read_file($registryfilename); + # my $registryhash = analyze_registry_file($registryfilecontent); + + # $registryfilecontent = remove_properties_from_registry_table($registryhash, $componentkeypathhash, $registryfilecontent); + + # installer::files::save_file($registryfilename, $registryfilecontent); + # $tablelist = "Registry"; + # include_tables_into_pcpfile($msidatabase, $helperdir, $tablelist); + + # Saving info in Summary Information Stream of msi database (required for following patches) + write_sis_info($msidatabase); + + return $msidatabase; +} + +1; diff --git a/solenv/bin/modules/installer/windows/assembly.pm b/solenv/bin/modules/installer/windows/assembly.pm new file mode 100644 index 000000000000..7b2372603b70 --- /dev/null +++ b/solenv/bin/modules/installer/windows/assembly.pm @@ -0,0 +1,375 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: assembly.pm,v $ +# +# $Revision: 1.11 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::assembly; + +use installer::files; +use installer::globals; +use installer::worker; +use installer::windows::idtglobal; + +############################################################## +# Returning the first module of a file from the +# comma separated list of modules. +############################################################## + +sub get_msiassembly_feature +{ + my ( $onefile ) = @_; + + my $module = ""; + + if ( $onefile->{'modules'} ) { $module = $onefile->{'modules'}; } + + # If modules contains a list of modules, only taking the first one. + + if ( $module =~ /^\s*(.*?)\,/ ) { $module = $1; } + + # Attention: Maximum feature length is 38! + installer::windows::idtglobal::shorten_feature_gid(\$module); + + return $module; +} + +############################################################## +# Returning the component of a file. +############################################################## + +sub get_msiassembly_component +{ + my ( $onefile ) = @_; + + my $component = ""; + + $component = $onefile->{'componentname'}; + + return $component; +} + +############################################################## +# Returning the file name as manifest file +############################################################## + +sub get_msiassembly_filemanifest +{ + my ( $onefile ) = @_; + + my $filemanifest = ""; + + $filemanifest = $onefile->{'uniquename'}; + # $filemanifest = $onefile->{'Name'}; + + return $filemanifest; +} + + +############################################################## +# Returning the file application +############################################################## + +sub get_msiassembly_fileapplication +{ + my ( $onefile ) = @_; + + my $fileapplication = ""; + + return $fileapplication; +} + +############################################################## +# Returning the file attributes +############################################################## + +sub get_msiassembly_attributes +{ + my ( $onefile ) = @_; + + my $fileattributes = ""; + + if ( $onefile->{'Attributes'} ne "" ) { $fileattributes = $onefile->{'Attributes'}; } + + return $fileattributes; +} + +############################################################## +# Returning the file object for the msiassembly table. +############################################################## + +sub get_msiassembly_file +{ + my ( $filesref, $filename ) = @_; + + my $foundfile = 0; + my $onefile; + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + $onefile = ${$filesref}[$i]; + my $name = $onefile->{'Name'}; + + if ( $name eq $filename ) + { + $foundfile = 1; + last; + } + } + + # It does not need to exist. For example products that do not contain the libraries. + # if (! $foundfile ) { installer::exiter::exit_program("ERROR: No unique file name found for $filename !", "get_selfreg_file"); } + + if (! $foundfile ) { $onefile = ""; } + + return $onefile; +} + +############################################################## +# Returning the file object for the msiassembly table. +############################################################## + +sub get_msiassembly_file_by_gid +{ + my ( $filesref, $gid ) = @_; + + my $foundfile = 0; + my $onefile; + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + $onefile = ${$filesref}[$i]; + my $filegid = $onefile->{'gid'}; + + if ( $filegid eq $gid ) + { + $foundfile = 1; + last; + } + } + + # It does not need to exist. For example products that do not contain the libraries. + # if (! $foundfile ) { installer::exiter::exit_program("ERROR: No unique file name found for $filename !", "get_selfreg_file"); } + + if (! $foundfile ) { $onefile = ""; } + + return $onefile; +} + +#################################################################################### +# Creating the file MsiAssembly.idt dynamically +# Content: +# Component_ Feature_ File_Manifest File_Application Attributes +# s72 s38 S72 S72 I2 +# MsiAssembly Component_ +#################################################################################### + +sub create_msiassembly_table +{ + my ($filesref, $basedir) = @_; + + $installer::globals::msiassemblyfiles = installer::worker::collect_all_items_with_special_flag($filesref, "ASSEMBLY"); + + my @msiassemblytable = (); + + installer::windows::idtglobal::write_idt_header(\@msiassemblytable, "msiassembly"); + + # Registering all libraries listed in $installer::globals::msiassemblyfiles + + for ( my $i = 0; $i <= $#{$installer::globals::msiassemblyfiles}; $i++ ) + { + my $onefile = ${$installer::globals::msiassemblyfiles}[$i]; + + my %msiassembly = (); + + $msiassembly{'Component_'} = get_msiassembly_component($onefile); + $msiassembly{'Feature_'} = get_msiassembly_feature($onefile); + $msiassembly{'File_Manifest'} = get_msiassembly_filemanifest($onefile); + $msiassembly{'File_Application'} = get_msiassembly_fileapplication($onefile); + $msiassembly{'Attributes'} = get_msiassembly_attributes($onefile); + + my $oneline = $msiassembly{'Component_'} . "\t" . $msiassembly{'Feature_'} . "\t" . + $msiassembly{'File_Manifest'} . "\t" . $msiassembly{'File_Application'} . "\t" . + $msiassembly{'Attributes'} . "\n"; + + push(@msiassemblytable, $oneline); + } + + # Saving the file + + my $msiassemblytablename = $basedir . $installer::globals::separator . "MsiAssem.idt"; + installer::files::save_file($msiassemblytablename ,\@msiassemblytable); + my $infoline = "Created idt file: $msiassemblytablename\n"; + push(@installer::globals::logfileinfo, $infoline); +} + +#################################################################################### +# Returning the name for the table MsiAssemblyName +#################################################################################### + +sub get_msiassemblyname_name +{ + ( $number ) = @_; + + my $name = ""; + + if ( $number == 1 ) { $name = "name"; } + elsif ( $number == 2 ) { $name = "publicKeyToken"; } + elsif ( $number == 3 ) { $name = "version"; } + elsif ( $number == 4 ) { $name = "culture"; } + + return $name; +} + +#################################################################################### +# Creating the file MsiAssemblyName.idt dynamically +# Content: +# Component_ Name Value +# s72 s255 s255 +# MsiAssemblyName Component_ Name +#################################################################################### + +sub create_msiassemblyname_table +{ + my ($filesref, $basedir) = @_; + + my @msiassemblynametable = (); + + installer::windows::idtglobal::write_idt_header(\@msiassemblynametable, "msiassemblyname"); + + for ( my $i = 0; $i <= $#{$installer::globals::msiassemblyfiles}; $i++ ) + { + my $onefile = ${$installer::globals::msiassemblyfiles}[$i]; + + my $component = get_msiassembly_component($onefile); + my $oneline = ""; + + # Order: (Assembly)name, publicKeyToken, version, culture. + + if ( $onefile->{'Assemblyname'} ) + { + $oneline = $component . "\t" . "name" . "\t" . $onefile->{'Assemblyname'} . "\n"; + push(@msiassemblynametable, $oneline); + } + + if ( $onefile->{'PublicKeyToken'} ) + { + $oneline = $component . "\t" . "publicKeyToken" . "\t" . $onefile->{'PublicKeyToken'} . "\n"; + push(@msiassemblynametable, $oneline); + } + + if ( $onefile->{'Version'} ) + { + $oneline = $component . "\t" . "version" . "\t" . $onefile->{'Version'} . "\n"; + push(@msiassemblynametable, $oneline); + } + + if ( $onefile->{'Culture'} ) + { + $oneline = $component . "\t" . "culture" . "\t" . $onefile->{'Culture'} . "\n"; + push(@msiassemblynametable, $oneline); + } + + if ( $onefile->{'ProcessorArchitecture'} ) + { + $oneline = $component . "\t" . "processorArchitecture" . "\t" . $onefile->{'ProcessorArchitecture'} . "\n"; + push(@msiassemblynametable, $oneline); + } + } + + # Saving the file + + my $msiassemblynametablename = $basedir . $installer::globals::separator . "MsiAsseN.idt"; + installer::files::save_file($msiassemblynametablename ,\@msiassemblynametable); + my $infoline = "Created idt file: $msiassemblynametablename\n"; + push(@installer::globals::logfileinfo, $infoline); + +} + +#################################################################################### +# setting an installation condition for the assembly libraries saved in +# @installer::globals::msiassemblynamecontent +#################################################################################### + +sub add_assembly_condition_into_component_table +{ + my ($filesref, $basedir) = @_; + + my $componenttablename = $basedir . $installer::globals::separator . "Componen.idt"; + my $componenttable = installer::files::read_file($componenttablename); + my $changed = 0; + my $infoline = ""; + + for ( my $i = 0; $i <= $#{$installer::globals::msiassemblyfiles}; $i++ ) + { + my $onefile = ${$installer::globals::msiassemblyfiles}[$i]; + + my $filecomponent = get_msiassembly_component($onefile); + + for ( my $j = 0; $j <= $#{$componenttable}; $j++ ) + { + my $oneline = ${$componenttable}[$j]; + + if ( $oneline =~ /(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)/ ) + { + my $component = $1; + my $componentid = $2; + my $directory = $3; + my $attributes = $4; + my $condition = $5; + my $keypath = $6; + + if ( $component eq $filecomponent ) + { + # setting the condition + + # $condition = "MsiNetAssemblySupport"; + $condition = "DOTNET_SUFFICIENT=1"; + $oneline = $component . "\t" . $componentid . "\t" . $directory . "\t" . $attributes . "\t" . $condition . "\t" . $keypath . "\n"; + ${$componenttable}[$j] = $oneline; + $changed = 1; + $infoline = "Changing $componenttablename :\n"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = $oneline; + push(@installer::globals::logfileinfo, $infoline); + last; + } + } + } + } + + if ( $changed ) + { + # Saving the file + installer::files::save_file($componenttablename ,$componenttable); + $infoline = "Saved idt file: $componenttablename\n"; + push(@installer::globals::logfileinfo, $infoline); + } +} + +1;
\ No newline at end of file diff --git a/solenv/bin/modules/installer/windows/binary.pm b/solenv/bin/modules/installer/windows/binary.pm new file mode 100644 index 000000000000..4f327b6d93c0 --- /dev/null +++ b/solenv/bin/modules/installer/windows/binary.pm @@ -0,0 +1,81 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: binary.pm,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::binary; + +use installer::existence; +use installer::files; +use installer::globals; + +########################################################################################################### +# Updating the table Binary dynamically with all files from $binarytablefiles +# Content: +# Name Data +# s72 v0 +# Binary Name +########################################################################################################### + +sub update_binary_table +{ + my ($languageidtdir, $filesref, $binarytablefiles) = @_; + + my $binaryidttablename = $languageidtdir . $installer::globals::separator . "Binary.idt"; + my $binaryidttable = installer::files::read_file($binaryidttablename); + + # Only the iconfiles, that are used in the shortcut table for the + # FolderItems (entries in Windows startmenu) are added into the icon table. + + for ( my $i = 0; $i <= $#{$binarytablefiles}; $i++ ) + { + my $binaryfile = ${$binarytablefiles}[$i]; + my $binaryfilename = $binaryfile->{'Name'}; + my $binaryfiledata = $binaryfilename; + + $binaryfilename =~ s/\.//g; # removing "." in filename: "abc.dll" to "abcdll" in name column + + my %binary = (); + + $binary{'Name'} = $binaryfilename; + $binary{'Data'} = $binaryfiledata; + + my $oneline = $binary{'Name'} . "\t" . $binary{'Data'} . "\n"; + + push(@{$binaryidttable}, $oneline); + } + + # Saving the file + + installer::files::save_file($binaryidttablename ,$binaryidttable); + my $infoline = "Updated idt file: $binaryidttablename\n"; + push(@installer::globals::logfileinfo, $infoline); +} + +1; diff --git a/solenv/bin/modules/installer/windows/component.pm b/solenv/bin/modules/installer/windows/component.pm new file mode 100644 index 000000000000..1cddc98cf6af --- /dev/null +++ b/solenv/bin/modules/installer/windows/component.pm @@ -0,0 +1,532 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: component.pm,v $ +# +# $Revision: 1.14 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::component; + +use installer::converter; +use installer::existence; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::windows::idtglobal; +use installer::windows::language; + +############################################################## +# Returning a globally unique ID (GUID) for a component +# If the component is new, a unique guid has to be created. +# If the component already exists, the guid has to be +# taken from a list component <-> guid +# Sample for a guid: {B68FD953-3CEF-4489-8269-8726848056E8} +############################################################## + +sub get_component_guid +{ + my ( $componentname, $componentidhashref ) = @_; + + # At this time only a template + my $returnvalue = "\{COMPONENTGUID\}"; + + if (( $installer::globals::updatedatabase ) && ( exists($componentidhashref->{$componentname}) )) + { + $returnvalue = $componentidhashref->{$componentname}; + } + + # Returning a ComponentID, that is assigned in scp project + if ( exists($installer::globals::componentid{$componentname}) ) + { + $returnvalue = "\{" . $installer::globals::componentid{$componentname} . "\}"; + } + + return $returnvalue; +} + +############################################################## +# Returning the directory for a file component. +############################################################## + +sub get_file_component_directory +{ + my ($componentname, $filesref, $dirref) = @_; + + my ($onefile, $component, $onedir, $hostname, $uniquedir); + my $found = 0; + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + $onefile = ${$filesref}[$i]; + $component = $onefile->{'componentname'}; + + if ( $component eq $componentname ) + { + $found = 1; + last; + } + } + + if (!($found)) + { + # This component can be ignored, if it exists in a version with extension "_pff" (this was renamed in file::get_sequence_for_file() ) + my $ignore_this_component = 0; + my $origcomponentname = $componentname; + my $componentname = $componentname . "_pff"; + + for ( my $j = 0; $j <= $#{$filesref}; $j++ ) + { + $onefile = ${$filesref}[$j]; + $component = $onefile->{'componentname'}; + + if ( $component eq $componentname ) + { + $ignore_this_component = 1; + last; + } + } + + if ( $ignore_this_component ) { return "IGNORE_COMP"; } + else { installer::exiter::exit_program("ERROR: Did not find component \"$origcomponentname\" in file collection", "get_file_component_directory"); } + } + + my $localstyles = ""; + + if ( $onefile->{'Styles'} ) { $localstyles = $onefile->{'Styles'}; } + + if ( $localstyles =~ /\bFONT\b/ ) # special handling for font files + { + return $installer::globals::fontsfolder; + } + + my $destdir = ""; + + if ( $onefile->{'Dir'} ) { $destdir = $onefile->{'Dir'}; } + + if ( $destdir =~ /\bPREDEFINED_OSSHELLNEWDIR\b/ ) # special handling for shellnew files + { + return $installer::globals::templatefolder; + } + + my $destination = $onefile->{'destination'}; + + installer::pathanalyzer::get_path_from_fullqualifiedname(\$destination); + + $destination =~ s/\Q$installer::globals::separator\E\s*$//; + + # This path has to be defined in the directory collection at "HostName" + + if ($destination eq "") # files in the installation root + { + $uniquedir = "INSTALLLOCATION"; + } + else + { + $found = 0; + + for ( my $i = 0; $i <= $#{$dirref}; $i++ ) + { + $onedir = ${$dirref}[$i]; + $hostname = $onedir->{'HostName'}; + + if ( $hostname eq $destination ) + { + $found = 1; + last; + } + } + + if (!($found)) + { + installer::exiter::exit_program("ERROR: Did not find destination $destination in directory collection", "get_file_component_directory"); + } + + $uniquedir = $onedir->{'uniquename'}; + } + + $onefile->{'uniquedirname'} = $uniquedir; # saving it in the file collection + + return $uniquedir +} + +############################################################## +# Returning the directory for a registry component. +# This cannot be a useful value +############################################################## + +sub get_registry_component_directory +{ + my $componentdir = ""; + + if ( $installer::globals::officeinstalldirectoryset ) + { + $componentdir = $installer::globals::officeinstalldirectory; + } + else + { + $componentdir = "INSTALLLOCATION"; + } + + return $componentdir; +} + +############################################################## +# Returning the attributes for a file component. +# Always 8 in this first try? +############################################################## + +sub get_file_component_attributes +{ + my ($componentname, $filesref) = @_; + + my $attributes; + + $attributes = 2; + + # special handling for font files + + my $onefile; + my $found = 0; + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + $onefile = ${$filesref}[$i]; + my $component = $onefile->{'componentname'}; + + if ( $component eq $componentname ) + { + $found = 1; + last; + } + } + + if (!($found)) + { + installer::exiter::exit_program("ERROR: Did not find component in file collection", "get_file_component_attributes"); + } + + my $localstyles = ""; + + if ( $onefile->{'Styles'} ) { $localstyles = $onefile->{'Styles'}; } + + if ( $localstyles =~ /\bFONT\b/ ) + { + $attributes = 16; # font files will not be deinstalled + } + + if ( $localstyles =~ /\bASSEMBLY\b/ ) + { + $attributes = 0; # Assembly files cannot run from source + } + + if (( $onefile->{'Dir'} =~ /\bPREDEFINED_OSSHELLNEWDIR\b/ ) || ( $onefile->{'needs_user_registry_key'} )) + { + $attributes = 4; # Files in shellnew dir and in non advertised startmenu entries must have user registry key as KeyPath + } + + return $attributes +} + +############################################################## +# Returning the attributes for a registry component. +# Always 4, indicating, the keypath is a defined in +# table registry +############################################################## + +sub get_registry_component_attributes +{ + my ($componentname) = @_; + + my $attributes; + + $attributes = 4; + + if ( exists($installer::globals::dontdeletecomponents{$componentname}) ) { $attributes = $attributes + 16; } + + return $attributes +} + +############################################################## +# Returning the conditions for a component. +# This is important for language dependent components +# in multilingual installation sets. +############################################################## + +sub get_file_component_condition +{ + my ($componentname, $filesref) = @_; + + my $condition = ""; + + if (exists($installer::globals::componentcondition{$componentname})) + { + $condition = $installer::globals::componentcondition{$componentname}; + } + + # there can be also tree conditions for multilayer products + if (exists($installer::globals::treeconditions{$componentname})) + { + if ( $condition eq "" ) + { + $condition = $installer::globals::treeconditions{$componentname}; + } + else + { + $condition = "($condition) And ($installer::globals::treeconditions{$componentname})"; + } + } + + return $condition +} + +############################################################## +# Returning the conditions for a registry component. +############################################################## + +sub get_component_condition +{ + my ($componentname) = @_; + + my $condition; + + $condition = ""; # Always ? + + if (exists($installer::globals::componentcondition{$componentname})) + { + $condition = $installer::globals::componentcondition{$componentname}; + } + + return $condition +} + +#################################################################### +# Returning the keypath for a component. +# This will be the name of the first file/registry, found in the +# collection $itemsref +# Attention: This has to be the unique (file)name, not the +# real filename! +#################################################################### + +sub get_component_keypath +{ + my ($componentname, $itemsref, $componentidkeypathhashref) = @_; + + my $oneitem; + my $found = 0; + my $infoline = ""; + + for ( my $i = 0; $i <= $#{$itemsref}; $i++ ) + { + $oneitem = ${$itemsref}[$i]; + my $component = $oneitem->{'componentname'}; + + if ( $component eq $componentname ) + { + $found = 1; + last; + } + } + + if (!($found)) + { + installer::exiter::exit_program("ERROR: Did not find component in file/registry collection, function get_component_keypath", "get_component_keypath"); + } + + my $keypath = $oneitem->{'uniquename'}; # "uniquename", not "Name" + + # Special handling for updates from existing databases, because KeyPath must not change + if (( $installer::globals::updatedatabase ) && ( exists($componentidkeypathhashref->{$componentname}) )) + { + $keypath = $componentidkeypathhashref->{$componentname}; + # -> check, if this is a valid key path?! + if ( $keypath ne $oneitem->{'uniquename'} ) + { + # Warning: This keypath was changed because of info from old database + $infoline = "WARNING: The KeyPath for component \"$componentname\" was changed from \"$oneitem->{'uniquename'}\" to \"$keypath\" because of information from update database"; + push(@installer::globals::logfileinfo, $infoline); + } + } + + # Special handling for components in PREDEFINED_OSSHELLNEWDIR. These components + # need as KeyPath a RegistryItem in HKCU + if ( $oneitem->{'userregkeypath'} ) { $keypath = $oneitem->{'userregkeypath'}; } + + # saving it in the file and registry collection + $oneitem->{'keypath'} = $keypath; + + return $keypath +} + +################################################################### +# Creating the file Componen.idt dynamically +# Content: +# Component ComponentId Directory_ Attributes Condition KeyPath +################################################################### + +sub create_component_table +{ + my ($filesref, $registryref, $dirref, $allfilecomponentsref, $allregistrycomponents, $basedir, $componentidhashref, $componentidkeypathhashref) = @_; + + my @componenttable = (); + + my ($oneline, $infoline); + + installer::windows::idtglobal::write_idt_header(\@componenttable, "component"); + + # collect_layer_conditions(); + + + # File components + + for ( my $i = 0; $i <= $#{$allfilecomponentsref}; $i++ ) + { + my %onecomponent = (); + + $onecomponent{'name'} = ${$allfilecomponentsref}[$i]; + $onecomponent{'guid'} = get_component_guid($onecomponent{'name'}, $componentidhashref); + $onecomponent{'directory'} = get_file_component_directory($onecomponent{'name'}, $filesref, $dirref); + if ( $onecomponent{'directory'} eq "IGNORE_COMP" ) { next; } + $onecomponent{'attributes'} = get_file_component_attributes($onecomponent{'name'}, $filesref); + $onecomponent{'condition'} = get_file_component_condition($onecomponent{'name'}, $filesref); + $onecomponent{'keypath'} = get_component_keypath($onecomponent{'name'}, $filesref, $componentidkeypathhashref); + + $oneline = $onecomponent{'name'} . "\t" . $onecomponent{'guid'} . "\t" . $onecomponent{'directory'} . "\t" + . $onecomponent{'attributes'} . "\t" . $onecomponent{'condition'} . "\t" . $onecomponent{'keypath'} . "\n"; + + push(@componenttable, $oneline); + } + + # Registry components + + for ( my $i = 0; $i <= $#{$allregistrycomponents}; $i++ ) + { + my %onecomponent = (); + + $onecomponent{'name'} = ${$allregistrycomponents}[$i]; + $onecomponent{'guid'} = get_component_guid($onecomponent{'name'}, $componentidhashref); + $onecomponent{'directory'} = get_registry_component_directory(); + $onecomponent{'attributes'} = get_registry_component_attributes($onecomponent{'name'}); + $onecomponent{'condition'} = get_component_condition($onecomponent{'name'}); + $onecomponent{'keypath'} = get_component_keypath($onecomponent{'name'}, $registryref, $componentidkeypathhashref); + + $oneline = $onecomponent{'name'} . "\t" . $onecomponent{'guid'} . "\t" . $onecomponent{'directory'} . "\t" + . $onecomponent{'attributes'} . "\t" . $onecomponent{'condition'} . "\t" . $onecomponent{'keypath'} . "\n"; + + push(@componenttable, $oneline); + } + + # Saving the file + + my $componenttablename = $basedir . $installer::globals::separator . "Componen.idt"; + installer::files::save_file($componenttablename ,\@componenttable); + $infoline = "Created idt file: $componenttablename\n"; + push(@installer::globals::logfileinfo, $infoline); +} + +#################################################################################### +# Returning a component for a scp module gid. +# Pairs are saved in the files collector. +#################################################################################### + +sub get_component_name_from_modulegid +{ + my ($modulegid, $filesref) = @_; + + my $componentname = ""; + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + + if ( $onefile->{'modules'} ) + { + my $filemodules = $onefile->{'modules'}; + my $filemodulesarrayref = installer::converter::convert_stringlist_into_array_without_newline(\$filemodules, ","); + + if (installer::existence::exists_in_array($modulegid, $filemodulesarrayref)) + { + $componentname = $onefile->{'componentname'}; + last; + } + } + } + + return $componentname; +} + +#################################################################################### +# Updating the file Environm.idt dynamically +# Content: +# Environment Name Value Component_ +#################################################################################### + +sub set_component_in_environment_table +{ + my ($basedir, $filesref) = @_; + + my $infoline = ""; + + my $environmentfilename = $basedir . $installer::globals::separator . "Environm.idt"; + + if ( -f $environmentfilename ) # only do something, if file exists + { + my $environmentfile = installer::files::read_file($environmentfilename); + + for ( my $i = 3; $i <= $#{$environmentfile}; $i++ ) # starting in line 4 of Environm.idt + { + if ( ${$environmentfile}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) + { + my $modulegid = $4; # in Environment table a scp module gid can be used as component replacement + + my $componentname = get_component_name_from_modulegid($modulegid, $filesref); + + if ( $componentname ) # only do something if a component could be found + { + $infoline = "Updated Environment table:\n"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = "Old line: ${$environmentfile}[$i]\n"; + push(@installer::globals::logfileinfo, $infoline); + + ${$environmentfile}[$i] =~ s/$modulegid/$componentname/; + + $infoline = "New line: ${$environmentfile}[$i]\n"; + push(@installer::globals::logfileinfo, $infoline); + + } + } + } + + # Saving the file + + installer::files::save_file($environmentfilename ,$environmentfile); + $infoline = "Updated idt file: $environmentfilename\n"; + push(@installer::globals::logfileinfo, $infoline); + + } +} + +1;
\ No newline at end of file diff --git a/solenv/bin/modules/installer/windows/createfolder.pm b/solenv/bin/modules/installer/windows/createfolder.pm new file mode 100644 index 000000000000..3abb3acad3d3 --- /dev/null +++ b/solenv/bin/modules/installer/windows/createfolder.pm @@ -0,0 +1,157 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: createfolder.pm,v $ +# +# $Revision: 1.7 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::createfolder; + +use installer::existence; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::windows::idtglobal; + +############################################################## +# Returning directory for createfolder table. +############################################################## + +sub get_createfolder_directory +{ + my ($onedir) = @_; + + my $uniquename = $onedir->{'uniquename'}; + + return $uniquename; +} + +############################################################## +# Searching the correct file for language pack directories. +############################################################## + +sub get_languagepack_file +{ + my ($filesref, $onedir) = @_; + + my $language = $onedir->{'specificlanguage'}; + my $foundfile = 0; + my $onefile = ""; + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + $onefile = ${$filesref}[$i]; + + if ( $onefile->{'specificlanguage'} eq $onedir->{'specificlanguage'} ) + { + $foundfile = 1; + last; + } + } + + if ( ! $foundfile ) { installer::exiter::exit_program("ERROR: No file with correct language found (language pack build)!", "get_languagepack_file"); } + + return $onefile; +} + +############################################################## +# Returning component for createfolder table. +############################################################## + +sub get_createfolder_component +{ + my ($onedir, $filesref, $allvariableshashref) = @_; + + # Directories do not belong to a module. + # Therefore they can only belong to the root module and + # will be added to a component at the root module. + # All directories will be added to the component + # containing the file $allvariableshashref->{'GLOBALFILEGID'} + + if ( ! $allvariableshashref->{'GLOBALFILEGID'} ) { installer::exiter::exit_program("ERROR: GLOBALFILEGID must be defined in list file!", "get_createfolder_component"); } + if (( $installer::globals::patch ) && ( ! $allvariableshashref->{'GLOBALFILEGID'} )) { installer::exiter::exit_program("ERROR: GLOBALPATCHFILEGID must be defined in list file!", "get_createfolder_component"); } + + my $globalfilegid = $allvariableshashref->{'GLOBALFILEGID'}; + if ( $installer::globals::patch ) { $globalfilegid = $allvariableshashref->{'GLOBALPATCHFILEGID'}; } + + my $onefile = ""; + if ( $installer::globals::languagepack ) { $onefile = get_languagepack_file($filesref, $onedir); } + else { $onefile = installer::existence::get_specified_file($filesref, $globalfilegid); } + + return $onefile->{'componentname'}; +} + +#################################################################################### +# Creating the file CreateFo.idt dynamically for creation of empty directories +# Content: +# Directory_ Component_ +#################################################################################### + +sub create_createfolder_table +{ + my ($dirref, $filesref, $basedir, $allvariableshashref) = @_; + + my @createfoldertable = (); + + my $infoline; + + installer::windows::idtglobal::write_idt_header(\@createfoldertable, "createfolder"); + + for ( my $i = 0; $i <= $#{$dirref}; $i++ ) + { + my $onedir = ${$dirref}[$i]; + + # language packs get only language dependent directories + if (( $installer::globals::languagepack ) && ( $onedir->{'specificlanguage'} eq "" )) { next }; + + my $styles = ""; + + if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; } + + if ( $styles =~ /\bCREATE\b/ ) + { + my %directory = (); + + $directory{'Directory_'} = get_createfolder_directory($onedir); + $directory{'Component_'} = get_createfolder_component($onedir, $filesref, $allvariableshashref); + + my $oneline = $directory{'Directory_'} . "\t" . $directory{'Component_'} . "\n"; + + push(@createfoldertable, $oneline); + } + } + + # Saving the file + + my $createfoldertablename = $basedir . $installer::globals::separator . "CreateFo.idt"; + installer::files::save_file($createfoldertablename ,\@createfoldertable); + $infoline = "Created idt file: $createfoldertablename\n"; + push(@installer::globals::logfileinfo, $infoline); + +} + +1;
\ No newline at end of file diff --git a/solenv/bin/modules/installer/windows/directory.pm b/solenv/bin/modules/installer/windows/directory.pm new file mode 100644 index 000000000000..94ac41d8cb92 --- /dev/null +++ b/solenv/bin/modules/installer/windows/directory.pm @@ -0,0 +1,439 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: directory.pm,v $ +# +# $Revision: 1.30.126.1 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::directory; + +use installer::exiter; +use installer::files; +use installer::globals; +use installer::pathanalyzer; +use installer::windows::idtglobal; + +############################################################## +# 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'}; + } +} + +############################################################## +# Adding unique directory names to the directory collection +############################################################## + +sub create_unique_directorynames +{ + my ($directoryref) = @_; + + $installer::globals::officeinstalldirectoryset = 0; + + for ( my $i = 0; $i <= $#{$directoryref}; $i++ ) + { + my $onedir = ${$directoryref}[$i]; + my $uniquename = $onedir->{'HostName'}; + my $styles = ""; + if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; } + # get_path_from_fullqualifiedname(\$uniqueparentname); + # making /registry/schema/org/openoffice/VCL.xcs to VCL.xcs + + $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/\Q$installer::globals::separator\E/\_/g; # replacing slash and backslash with underline + + my $uniqueparentname = $uniquename; + + if ( $uniqueparentname =~ /^\s*(.*)\_(.*?)\s*$/ ) # the underline is now the separator + { + $uniqueparentname = $1; + } + else + { + $uniqueparentname = "INSTALLLOCATION"; + } + + if ( $styles =~ /\bPROGRAMFILESFOLDER\b/ ) { $uniqueparentname = $installer::globals::programfilesfolder; } + if ( $styles =~ /\bCOMMONFILESFOLDER\b/ ) { $uniqueparentname = $installer::globals::commonfilesfolder; } + if ( $styles =~ /\bCOMMONAPPDATAFOLDER\b/ ) { $uniqueparentname = $installer::globals::commonappdatafolder; } + if ( $styles =~ /\bLOCALAPPDATAFOLDER\b/ ) { $uniqueparentname = $installer::globals::localappdatafolder; } + + if ( $styles =~ /\bSHAREPOINTPATH\b/ ) + { + $uniqueparentname = "SHAREPOINTPATH"; + $installer::globals::usesharepointpath = 1; + } + + $uniquename =~ s/\-/\_/g; # making "-" to "_" + $uniqueparentname =~ s/\-/\_/g; # making "-" to "_" + + $onedir->{'uniquename'} = $uniquename; + $onedir->{'uniqueparentname'} = $uniqueparentname; + + # setting the office installation directory + if ( $styles =~ /\bOFFICEDIRECTORY\b/ ) + { + if ( $installer::globals::officeinstalldirectoryset ) { installer::exiter::exit_program("ERROR: Directory with flag OFFICEDIRECTORY alread set: \"$installer::globals::officeinstalldirectory\".", "create_unique_directorynames"); } + $installer::globals::officeinstalldirectory = $uniquename; + $installer::globals::officeinstalldirectoryset = 1; + if ( $installer::globals::officeinstalldirectory =~ /sun_/i ) { $installer::globals::sundirexists = 1; } + } + + # setting the bais installation directory + if ( $styles =~ /\bBASISDIRECTORY\b/ ) + { + if ( $installer::globals::basisinstalldirectoryset ) { installer::exiter::exit_program("ERROR: Directory with flag BASISDIRECTORY alread set: \"$installer::globals::basisinstalldirectory\".", "create_unique_directorynames"); } + $installer::globals::basisinstalldirectory = $uniquename; + $installer::globals::basisinstalldirectoryset = 1; + } + + # setting the ure installation directory + if ( $styles =~ /\bUREDIRECTORY\b/ ) + { + if ( $installer::globals::ureinstalldirectoryset ) { installer::exiter::exit_program("ERROR: Directory with flag UREDIRECTORY alread set: \"$installer::globals::ureinstalldirectory\".", "create_unique_directorynames"); } + $installer::globals::ureinstalldirectory = $uniquename; + $installer::globals::ureinstalldirectoryset = 1; + } + } +} + +##################################################### +# 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 $oneline = "TARGETDIR\t\tSourceDir\n"; + push(@{$directorytableref}, $oneline); + + my $sourcediraddon = ""; + if (($installer::globals::addchildprojects) || + ($installer::globals::patch) || + ($installer::globals::languagepack) || + ($allvariableshashref->{'CHANGETARGETDIR'})) + { + $sourcediraddon = "\:\."; + } + + if (!($installer::globals::product =~ /ada/i )) # the following directories not for ada products + { + $oneline = "$installer::globals::programfilesfolder\tTARGETDIR\t.\n"; + push(@{$directorytableref}, $oneline); + + # my $manufacturer = $installer::globals::manufacturer; + # my $shortmanufacturer = installer::windows::idtglobal::make_eight_three_conform($manufacturer, "dir"); # third parameter not used + # $shortmanufacturer =~ s/\s/\_/g; # changing empty space to underline + + 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 + + if ( $allvariableshashref->{'SUNDIR'} ) + { + $oneline = "sundirectory\t$installer::globals::programfilesfolder\t$installer::globals::sundirname$sourcediraddon\n"; + push(@{$directorytableref}, $oneline); + + $oneline = "INSTALLLOCATION\tsundirectory\t$shortproductkey|$productkey$sourcediraddon\n"; + push(@{$directorytableref}, $oneline); + } + else + { + if ( $allvariableshashref->{'PROGRAMFILESROOT'} ) + { + $oneline = "INSTALLLOCATION\t$installer::globals::programfilesfolder\t.\n"; + } + else + { + $oneline = "INSTALLLOCATION\t$installer::globals::programfilesfolder\t$shortproductkey|$productkey$sourcediraddon\n"; + } + + push(@{$directorytableref}, $oneline); + } + + $oneline = "$installer::globals::programmenufolder\tTARGETDIR\t.\n"; + push(@{$directorytableref}, $oneline); + + if (( ! $installer::globals::patch ) && ( ! $installer::globals::languagepack ) && ( ! $allvariableshashref->{'DONTUSESTARTMENUFOLDER'} )) + { + $oneline = "$installer::globals::officemenufolder\t$installer::globals::programmenufolder\t$shortproductkey|$realproductkey\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) = @_; + + # 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 + + my @directorytable = (); + my $infoline; + + overwrite_programfilesfolder($allvariableshashref); + create_unique_directorynames($directoryref); + create_defaultdir_directorynames($directoryref, $shortdirnamehashref); # only destdir! + 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); + $infoline = "Created idt file: $directorytablename\n"; + push(@installer::globals::logfileinfo, $infoline); + +} + +1; diff --git a/solenv/bin/modules/installer/windows/feature.pm b/solenv/bin/modules/installer/windows/feature.pm new file mode 100644 index 000000000000..b422dc45eb65 --- /dev/null +++ b/solenv/bin/modules/installer/windows/feature.pm @@ -0,0 +1,449 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: feature.pm,v $ +# +# $Revision: 1.24 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::feature; + +use installer::existence; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::sorter; +use installer::worker; +use installer::windows::idtglobal; +use installer::windows::language; + +############################################################## +# Returning the gid for a feature. +# Attention: Maximum length +############################################################## + +sub get_feature_gid +{ + my ($onefeature) = @_; + + my $gid = ""; + + if ( $onefeature->{'gid'} ) { $gid = $onefeature->{'gid'}; } + + # Attention: Maximum feature length is 38! + installer::windows::idtglobal::shorten_feature_gid(\$gid); + + return $gid +} + +############################################################## +# Returning the gid of the parent. +# Attention: Maximum length +############################################################## + +sub get_feature_parent +{ + my ($onefeature) = @_; + + my $parentgid = ""; + + if ( $onefeature->{'ParentID'} ) { $parentgid = $onefeature->{'ParentID'}; } + + # The modules, hanging directly below the root, have to be root modules. + # Only then it is possible to make the "real" root module invisible by + # setting the display to "0". + + if ( $parentgid eq $installer::globals::rootmodulegid ) { $parentgid = ""; } + + # Attention: Maximum feature length is 38! + installer::windows::idtglobal::shorten_feature_gid(\$parentgid); + + return $parentgid +} + +############################################################## +# Returning the display for a feature. +# 0: Feature is not shown +# odd: subfeatures are shown +# even: subfeatures are not shown +############################################################## + +sub get_feature_display +{ + my ($onefeature) = @_; + + my $display; + my $parentid = ""; + + if ( $onefeature->{'ParentID'} ) { $parentid = $onefeature->{'ParentID'}; } + + if ( $parentid eq "" ) + { + $display = "0"; # root module is not visible + } + elsif ( $onefeature->{'gid'} eq "gid_Module_Prg") # program module shows subfeatures + { + $display = "1"; # root module shows subfeatures + } + else + { + $display = "2"; # all other modules do not show subfeatures + } + + # special case: Feature has flag "HIDDEN_ROOT" -> $display is 0 + my $styles = ""; + if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; } + if ( $styles =~ /\bHIDDEN_ROOT\b/ ) { $display = "0"; } + + # Special handling for language modules. Only visible in multilingual installation set + if (( $styles =~ /\bSHOW_MULTILINGUAL_ONLY\b/ ) && ( ! $installer::globals::ismultilingual )) { $display = "0"; } + + # Special handling for c05office. No program module visible. + if (( $onefeature->{'gid'} eq "gid_Module_Prg" ) && ( $installer::globals::product =~ /c05office/i )) { $display = "0"; } + + # making all feature invisible in Language packs! + if ( $installer::globals::languagepack ) { $display = "0"; } + + return $display +} + +############################################################## +# Returning the level for a feature. +############################################################## + +sub get_feature_level +{ + my ($onefeature) = @_; + + my $level = "20"; # the default + + my $localdefault = ""; + + if ( $onefeature->{'Default'} ) { $localdefault = $onefeature->{'Default'}; } + + if ( $localdefault eq "NO" ) # explicitely set Default = "NO" + { + $level = "200"; # deselected in default installation, base is 100 + if ( $installer::globals::patch ) { $level = "20"; } + } + + # special handling for Java and Ada + if ( $onefeature->{'Name'} ) + { + if ( $onefeature->{'Name'} =~ /java/i ) { $level = $level + 40; } + } + + # if FeatureLevel is defined in scp, this will be used + + if ( $onefeature->{'FeatureLevel'} ) { $level = $onefeature->{'FeatureLevel'}; } + + return $level +} + +############################################################## +# Returning the directory for a feature. +############################################################## + +sub get_feature_directory +{ + my ($onefeature) = @_; + + my $directory; + + $directory = "INSTALLLOCATION"; + + return $directory +} + +############################################################## +# Returning the directory for a feature. +############################################################## + +sub get_feature_attributes +{ + my ($onefeature) = @_; + + my $attributes; + + # No advertising of features and no leaving on network. + # Feature without parent must not have the "2" + + my $parentgid = ""; + if ( $onefeature->{'ParentID'} ) { $parentgid = $onefeature->{'ParentID'}; } + + if (( $parentgid eq "" ) || ( $parentgid eq $installer::globals::rootmodulegid )) { $attributes = "8"; } + else { $attributes = "10"; } + + return $attributes +} + +################################################################################# +# Replacing one variable in one files +################################################################################# + +sub replace_one_variable +{ + my ($translationfile, $variable, $searchstring) = @_; + + for ( my $i = 0; $i <= $#{$translationfile}; $i++ ) + { + ${$translationfile}[$i] =~ s/\%$searchstring/$variable/g; + } +} + +################################################################################# +# Replacing the variables in the feature names and descriptions +################################################################################# + +sub replace_variables +{ + my ($translationfile, $variableshashref) = @_; + + foreach $key (keys %{$variableshashref}) + { + my $value = $variableshashref->{$key}; + replace_one_variable($translationfile, $value, $key); + } +} + +################################################################################# +# Collecting the feature recursively. +################################################################################# + +sub collect_modules_recursive +{ + my ($modulesref, $parentid, $feature, $directaccess, $directgid, $directparent, $directsortkey, $sorted) = @_; + + my @allchildren = (); + my $childrenexist = 0; + + # Collecting children from Module $parentid + + my $modulegid; + foreach $modulegid ( keys %{$directparent}) + { + if ( $directparent->{$modulegid} eq $parentid ) + { + my %childhash = ( "gid" => "$modulegid", "Sortkey" => "$directsortkey->{$modulegid}"); + push(@allchildren, \%childhash); + $childrenexist = 1; + } + } + + # Sorting children + + if ( $childrenexist ) + { + # Sort children + installer::sorter::sort_array_of_hashes_numerically(\@allchildren, "Sortkey"); + + # Adding children to new array + my $childhashref; + foreach $childhashref ( @allchildren ) + { + my $gid = $childhashref->{'gid'}; + + # Saving all lines, that have this 'gid' + + my $unique; + foreach $unique ( keys %{$directgid} ) + { + if ( $directgid->{$unique} eq $gid ) + { + push(@{$feature}, ${$modulesref}[$directaccess->{$unique}]); + if ( $sorted->{$unique} == 1 ) { installer::exiter::exit_program("ERROR: Sorting feature failed! \"$unique\" already sorted.", "sort_feature"); } + $sorted->{$unique} = 1; + } + } + + collect_modules_recursive($modulesref, $gid, $feature, $directaccess, $directgid, $directparent, $directsortkey, $sorted); + } + } +} + +################################################################################# +# Sorting the feature in specified order. Evaluated is the key "Sortkey", that +# is set in scp2 projects. +# The display order of modules in Windows Installer is dependent from the order +# in the idt file. Therefore the order of the modules array has to be adapted +# to the Sortkey order, before the idt file is created. +################################################################################# + +sub sort_feature +{ + my ($modulesref) = @_; + + my @feature = (); + + my %directaccess = (); + my %directparent = (); + my %directgid = (); + my %directsortkey = (); + my %sorted = (); + + for ( my $i = 0; $i <= $#{$modulesref}; $i++ ) + { + my $onefeature = ${$modulesref}[$i]; + + my $uniquekey = $onefeature->{'uniquekey'}; + my $modulegid = $onefeature->{'gid'}; + + $directaccess{$uniquekey} = $i; + + $directgid{$uniquekey} = $onefeature->{'gid'}; + + # ParentID and Sortkey are not saved for the 'uniquekey', but only for the 'gid' + + if ( $onefeature->{'ParentID'} ) { $directparent{$modulegid} = $onefeature->{'ParentID'}; } + else { $directparent{$modulegid} = ""; } + + if ( $onefeature->{'Sortkey'} ) { $directsortkey{$modulegid} = $onefeature->{'Sortkey'}; } + else { $directsortkey{$modulegid} = "9999"; } + + # Bookkeeping: + $sorted{$uniquekey} = 0; + } + + # Searching all feature recursively, beginning with ParentID = "" + my $parentid = ""; + collect_modules_recursive($modulesref, $parentid, \@feature, \%directaccess, \%directgid, \%directparent, \%directsortkey, \%sorted); + + # Bookkeeping + my $modulekey; + foreach $modulekey ( keys %sorted ) + { + if ( $sorted{$modulekey} == 0 ) + { + my $infoline = "Warning: Module \"$modulekey\" could not be sorted. Added to the end of the module array.\n"; + push(@installer::globals::logfileinfo, $infoline); + push(@feature, ${$modulesref}[$directaccess{$modulekey}]); + } + } + + return \@feature; +} + +################################################################################# +# Adding a unique key to the modules array. The gid is not unique for +# multilingual modules. Only the combination from gid and specific language +# is unique. Uniqueness is required for sorting mechanism. +################################################################################# + +sub add_uniquekey +{ + my ( $modulesref ) = @_; + + for ( my $i = 0; $i <= $#{$modulesref}; $i++ ) + { + my $uniquekey = ${$modulesref}[$i]->{'gid'}; + if ( ${$modulesref}[$i]->{'specificlanguage'} ) { $uniquekey = $uniquekey . "_" . ${$modulesref}[$i]->{'specificlanguage'}; } + ${$modulesref}[$i]->{'uniquekey'} = $uniquekey; + } +} + +################################################################################# +# Creating the file Feature.idt dynamically +# Content: +# Feature Feature_Parent Title Description Display Level Directory_ Attributes +################################################################################# + +sub create_feature_table +{ + my ($modulesref, $basedir, $languagesarrayref, $allvariableshashref) = @_; + + for ( my $m = 0; $m <= $#{$languagesarrayref}; $m++ ) + { + my $onelanguage = ${$languagesarrayref}[$m]; + + my $infoline; + + my @featuretable = (); + + installer::windows::idtglobal::write_idt_header(\@featuretable, "feature"); + + for ( my $i = 0; $i <= $#{$modulesref}; $i++ ) + { + my $onefeature = ${$modulesref}[$i]; + + # Java and Ada only, if the correct settings are set + my $styles = ""; + if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; } + if (( $styles =~ /\bJAVAMODULE\b/ ) && ( ! ($allvariableshashref->{'JAVAPRODUCT'} ))) { next; } + if (( $styles =~ /\bADAMODULE\b/ ) && ( ! ($allvariableshashref->{'ADAPRODUCT'} ))) { next; } + + # Controlling the language! + # Only language independent feature or feature with the correct language will be included into the table + + if (! (!(( $onefeature->{'ismultilingual'} )) || ( $onefeature->{'specificlanguage'} eq $onelanguage )) ) { next; } + + my %feature = (); + + $feature{'feature'} = get_feature_gid($onefeature); + $feature{'feature_parent'} = get_feature_parent($onefeature); + # if ( $onefeature->{'ParentID'} eq "" ) { $feature{'feature_parent'} = ""; } # Root has no parent + $feature{'Title'} = $onefeature->{'Name'}; + $feature{'Description'} = $onefeature->{'Description'}; + $feature{'Display'} = get_feature_display($onefeature); + $feature{'Level'} = get_feature_level($onefeature); + $feature{'Directory_'} = get_feature_directory($onefeature); + $feature{'Attributes'} = get_feature_attributes($onefeature); + + my $oneline = $feature{'feature'} . "\t" . $feature{'feature_parent'} . "\t" . $feature{'Title'} . "\t" + . $feature{'Description'} . "\t" . $feature{'Display'} . "\t" . $feature{'Level'} . "\t" + . $feature{'Directory_'} . "\t" . $feature{'Attributes'} . "\n"; + + push(@featuretable, $oneline); + + # collecting all feature in global feature collector (so that properties can be set in property table) + if ( ! installer::existence::exists_in_array($feature{'feature'}, \@installer::globals::featurecollector) ) + { + push(@installer::globals::featurecollector, $feature{'feature'}); + } + + # collecting all language feature in feature collector for check of language selection + if (( $styles =~ /\bSHOW_MULTILINGUAL_ONLY\b/ ) && ( $onefeature->{'ParentID'} ne $installer::globals::rootmodulegid )) + { + $installer::globals::multilingual_only_modules{$feature{'feature'}} = 1; + } + + # collecting all application feature in global feature collector for check of application selection + if ( $styles =~ /\bAPPLICATIONMODULE\b/ ) + { + $installer::globals::application_modules{$feature{'feature'}} = 1; + } + } + + # Saving the file + + my $featuretablename = $basedir . $installer::globals::separator . "Feature.idt" . "." . $onelanguage; + installer::files::save_file($featuretablename ,\@featuretable); + $infoline = "Created idt file: $featuretablename\n"; + push(@installer::globals::logfileinfo, $infoline); + } + +} + +1; diff --git a/solenv/bin/modules/installer/windows/featurecomponent.pm b/solenv/bin/modules/installer/windows/featurecomponent.pm new file mode 100644 index 000000000000..0c3d5763325e --- /dev/null +++ b/solenv/bin/modules/installer/windows/featurecomponent.pm @@ -0,0 +1,248 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: featurecomponent.pm,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::featurecomponent; + +use installer::converter; +use installer::existence; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::windows::idtglobal; + +################################################################################# +# Collecting all pairs of features and components from the files collector +################################################################################# + +sub create_featurecomponent_table_from_files_collector +{ + my ($featurecomponenttableref, $filesref) = @_; + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + + my $filecomponent = $onefile->{'componentname'}; + my $filemodules = $onefile->{'modules'}; + + if ( $filecomponent eq "" ) + { + installer::exiter::exit_program("ERROR: No component defined for file $onefile->{'Name'}", "create_featurecomponent_table_from_files_collector"); + } + if ( $filemodules eq "" ) + { + installer::exiter::exit_program("ERROR: No modules found for file $onefile->{'Name'}", "create_featurecomponent_table_from_files_collector"); + } + + my $filemodulesarrayref = installer::converter::convert_stringlist_into_array(\$filemodules, ","); + + for ( my $j = 0; $j <= $#{$filemodulesarrayref}; $j++ ) + { + my %featurecomponent = (); + + my $onemodule = ${$filemodulesarrayref}[$j]; + $onemodule =~ s/\s*$//; + $featurecomponent{'Feature'} = $onemodule; + $featurecomponent{'Component'} = $filecomponent; + + # Attention: Features are renamed, because the maximum length is 38. + # But in the files collector ($filesref), the original names are saved. + + installer::windows::idtglobal::shorten_feature_gid(\$featurecomponent{'Feature'}); + + $oneline = "$featurecomponent{'Feature'}\t$featurecomponent{'Component'}\n"; + + # control of uniqueness + + if (! installer::existence::exists_in_array($oneline, $featurecomponenttableref)) + { + push(@{$featurecomponenttableref}, $oneline); + } + } + } +} + +################################################################################# +# Collecting all pairs of features and components from the registry collector +################################################################################# + +sub create_featurecomponent_table_from_registry_collector +{ + my ($featurecomponenttableref, $registryref) = @_; + + for ( my $i = 0; $i <= $#{$registryref}; $i++ ) + { + my $oneregistry = ${$registryref}[$i]; + + my $registrycomponent = $oneregistry->{'componentname'}; + my $registrymodule = $oneregistry->{'ModuleID'}; + + if ( $registrycomponent eq "" ) + { + installer::exiter::exit_program("ERROR: No component defined for registry $oneregistry->{'gid'}", "create_featurecomponent_table_from_registry_collector"); + } + if ( $registrymodule eq "" ) + { + installer::exiter::exit_program("ERROR: No modules found for registry $oneregistry->{'gid'}", "create_featurecomponent_table_from_registry_collector"); + } + + my %featurecomponent = (); + + $featurecomponent{'Feature'} = $registrymodule; + $featurecomponent{'Component'} = $registrycomponent; + + # Attention: Features are renamed, because the maximum length is 38. + # But in the files collector ($filesref), the original names are saved. + + installer::windows::idtglobal::shorten_feature_gid(\$featurecomponent{'Feature'}); + + $oneline = "$featurecomponent{'Feature'}\t$featurecomponent{'Component'}\n"; + + # control of uniqueness + + if (! installer::existence::exists_in_array($oneline, $featurecomponenttableref)) + { + push(@{$featurecomponenttableref}, $oneline); + } + } +} + +################################################################################# +# Collecting all feature that are listed in the featurecomponent table. +################################################################################# + +sub collect_all_feature +{ + my ($featurecomponenttable) = @_; + + my @allfeature = (); + + for ( my $i = 3; $i <= $#{$featurecomponenttable}; $i++ ) # beginning in line 4 + { + my $oneline = ${$featurecomponenttable}[$i]; + + if ( $oneline =~ /^\s*(\S+)\s+(\S+)\s*$/ ) + { + my $feature = $1; + + if (! installer::existence::exists_in_array($feature, \@allfeature)) { push(@allfeature, $feature); } + } + } + + return \@allfeature; +} + +################################################################################# +# On Win98 and Win Me there seems to be the problem, that maximum 817 +# components can be added to a feature. Even if Windows Installer 2.0 +# is used. +################################################################################# + +sub check_number_of_components_at_feature +{ + my ($featurecomponenttable) = @_; + + my $infoline = "\nChecking number of components at features. Maximum is 817 (for Win 98 and Win Me)\n"; + push(@installer::globals::logfileinfo, $infoline); + + my $allfeature = collect_all_feature($featurecomponenttable); + + for ( my $i = 0; $i <= $#{$allfeature}; $i++ ) + { + my $onefeature = ${$allfeature}[$i]; + my $featurecomponents = 0; + + for ( my $j = 0; $j <= $#{$featurecomponenttable}; $j++ ) + { + if ( ${$featurecomponenttable}[$j] =~ /^\s*\Q$onefeature\E\s+(\S+)\s*$/ ) { $featurecomponents++; } + } + + if ( $featurecomponents > 816 ) + { + installer::exiter::exit_program("ERROR: More than 816 components ($featurecomponents) at feature $onefeature. This causes problems on Win 98 and Win Me!", "check_number_of_components_at_feature"); + } + + # Logging the result + + $infoline = "Number of components at feature $onefeature : $featurecomponents\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + $infoline = "\n"; + push(@installer::globals::logfileinfo, $infoline); +} + +################################################################################# +# Creating the file FeatureC.idt dynamically +# Content: +# Feature Component +################################################################################# + +sub create_featurecomponent_table +{ + my ($filesref, $registryref, $basedir) = @_; + + my @featurecomponenttable = (); + my $infoline; + + installer::windows::idtglobal::write_idt_header(\@featurecomponenttable, "featurecomponent"); + + # This is the first time, that features and componentes are related + # Problem: How about created profiles, configurationfiles, services.rdb + # -> simple solution: putting them all to the root module + # Otherwise profiles and configurationfiles cannot be created the way, they are now created + # -> especially a problem for the configurationfiles! # ToDo + # Very good: All ProfileItems belong to the root + # services.rdb belongs to the root anyway. + + # At the moment only the files are related to components (and the files know their modules). + # The component for each file is written into the files collector $filesinproductlanguageresolvedarrayref + + create_featurecomponent_table_from_files_collector(\@featurecomponenttable, $filesref); + + create_featurecomponent_table_from_registry_collector(\@featurecomponenttable, $registryref); + + # Additional components have to be added here + + # Checking, whether there are more than 817 components at a feature + + check_number_of_components_at_feature(\@featurecomponenttable); + + # Saving the file + + my $featurecomponenttablename = $basedir . $installer::globals::separator . "FeatureC.idt"; + installer::files::save_file($featurecomponenttablename ,\@featurecomponenttable); + $infoline = "Created idt file: $featurecomponenttablename\n"; + push(@installer::globals::logfileinfo, $infoline); + +} + +1;
\ No newline at end of file diff --git a/solenv/bin/modules/installer/windows/file.pm b/solenv/bin/modules/installer/windows/file.pm new file mode 100644 index 000000000000..e8d46c124317 --- /dev/null +++ b/solenv/bin/modules/installer/windows/file.pm @@ -0,0 +1,975 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: file.pm,v $ +# +# $Revision: 1.24 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::file; + +use Digest::MD5; +use installer::existence; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::logger; +use installer::pathanalyzer; +use installer::worker; +use installer::windows::font; +use installer::windows::idtglobal; +use installer::windows::language; + +########################################################################## +# Assigning one cabinet file to each file. This is requrired, +# if cabinet files shall be equivalent to packages. +########################################################################## + +sub assign_cab_to_files +{ + my ( $filesref ) = @_; + + my $infoline = ""; + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + if ( ! exists(${$filesref}[$i]->{'modules'}) ) { installer::exiter::exit_program("ERROR: No module assignment found for ${$filesref}[$i]->{'gid'} !", "assign_cab_to_files"); } + my $module = ${$filesref}[$i]->{'modules'}; + # If modules contains a list of modules, only taking the first one. + if ( $module =~ /^\s*(.*?)\,/ ) { $module = $1; } + + if ( ! exists($installer::globals::allcabinetassigns{$module}) ) { installer::exiter::exit_program("ERROR: No cabinet file assigned to module \"$module\" (${$filesref}[$i]->{'gid'}) !", "assign_cab_to_files"); } + ${$filesref}[$i]->{'assignedcabinetfile'} = $installer::globals::allcabinetassigns{$module}; + + # Counting the files in each cabinet file + if ( ! exists($installer::globals::cabfilecounter{${$filesref}[$i]->{'assignedcabinetfile'}}) ) + { + $installer::globals::cabfilecounter{${$filesref}[$i]->{'assignedcabinetfile'}} = 1; + } + else + { + $installer::globals::cabfilecounter{${$filesref}[$i]->{'assignedcabinetfile'}}++; + } + } + + # logging the number of files in each cabinet file + + $infoline = "\nCabinet file content:\n"; + push(@installer::globals::logfileinfo, $infoline); + my $cabfile; + foreach $cabfile ( sort keys %installer::globals::cabfilecounter ) + { + $infoline = "$cabfile : $installer::globals::cabfilecounter{$cabfile} files\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + # assigning startsequencenumbers for each cab file + + my $offset = 1; + foreach $cabfile ( sort keys %installer::globals::cabfilecounter ) + { + my $filecount = $installer::globals::cabfilecounter{$cabfile}; + $installer::globals::cabfilecounter{$cabfile} = $offset; + $offset = $offset + $filecount; + + $installer::globals::lastsequence{$cabfile} = $offset - 1; + } + + # logging the start sequence numbers + + $infoline = "\nCabinet file start sequences:\n"; + push(@installer::globals::logfileinfo, $infoline); + foreach $cabfile ( sort keys %installer::globals::cabfilecounter ) + { + $infoline = "$cabfile : $installer::globals::cabfilecounter{$cabfile}\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + # logging the last sequence numbers + + $infoline = "\nCabinet file last sequences:\n"; + push(@installer::globals::logfileinfo, $infoline); + foreach $cabfile ( sort keys %installer::globals::lastsequence ) + { + $infoline = "$cabfile : $installer::globals::lastsequence{$cabfile}\n"; + push(@installer::globals::logfileinfo, $infoline); + } +} + +########################################################################## +# Assigning sequencenumbers to files. This is requrired, +# if cabinet files shall be equivalent to packages. +########################################################################## + +sub assign_sequencenumbers_to_files +{ + my ( $filesref ) = @_; + + my %directaccess = (); + my %allassigns = (); + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + + # Keeping order in cabinet files + # -> collecting all files in one cabinet file + # -> sorting files and assigning numbers + + # Saving counter $i for direct access into files array + # "destination" of the file is a unique identifier ('Name' is not unique!) + if ( exists($directaccess{$onefile->{'destination'}}) ) { installer::exiter::exit_program("ERROR: 'destination' at file not unique: $onefile->{'destination'}", "assign_sequencenumbers_to_files"); } + $directaccess{$onefile->{'destination'}} = $i; + + my $cabfilename = $onefile->{'assignedcabinetfile'}; + # collecting files in cabinet files + if ( ! exists($allassigns{$cabfilename}) ) + { + my %onecabfile = (); + $onecabfile{$onefile->{'destination'}} = 1; + $allassigns{$cabfilename} = \%onecabfile; + } + else + { + $allassigns{$cabfilename}->{$onefile->{'destination'}} = 1; + } + } + + # Sorting each hash and assigning numbers + # The destination of the file determines the sort order, not the filename! + my $cabfile; + foreach $cabfile ( sort keys %allassigns ) + { + my $counter = $installer::globals::cabfilecounter{$cabfile}; + my $dest; + foreach $dest ( sort keys %{$allassigns{$cabfile}} ) # <- sorting the destination! + { + my $directaccessnumber = $directaccess{$dest}; + ${$filesref}[$directaccessnumber]->{'assignedsequencenumber'} = $counter; + $counter++; + } + } +} + +############################################### +# Generating the component name from a file +############################################### + +sub get_file_component_name +{ + my ($fileref, $filesref) = @_; + + # In this function exists the rule to create components from files + # Rule: + # Two files get the same componentid, if: + # both have the same destination directory. + # both have the same "gid" -> both were packed in the same zip file + # All other files are included into different components! + + # my $componentname = $fileref->{'gid'} . "_" . $fileref->{'Dir'}; + + # $fileref->{'Dir'} is not sufficient! All files in a zip file have the same $fileref->{'Dir'}, + # but can be in different subdirectories. + # Solution: destination=share\Scripts\beanshell\Capitalise\capitalise.bsh + # in which the filename (capitalise.bsh) has to be removed and all backslashes (slashes) are + # converted into underline. + + my $destination = $fileref->{'destination'}; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$destination); + $destination =~ s/\s//g; + $destination =~ s/\\/\_/g; + $destination =~ s/\//\_/g; + $destination =~ s/\_\s*$//g; # removing ending underline + + my $componentname = $fileref->{'gid'} . "__" . $destination; + + # Files with different languages, need to be packed into different components. + # Then the installation of the language specific component is determined by a language condition. + + if ( $fileref->{'ismultilingual'} ) + { + my $officelanguage = $fileref->{'specificlanguage'}; + $componentname = $componentname . "_" . $officelanguage; + } + + $componentname = lc($componentname); # componentnames always lowercase + + $componentname =~ s/\-/\_/g; # converting "-" to "_" + $componentname =~ s/\./\_/g; # converting "-" to "_" + + # Attention: Maximum length for the componentname is 72 + + $componentname =~ s/gid_file_/g_f_/g; + $componentname =~ s/_extra_/_e_/g; + $componentname =~ s/_config_/_c_/g; + $componentname =~ s/_org_openoffice_/_o_o_/g; + $componentname =~ s/_program_/_p_/g; + $componentname =~ s/_typedetection_/_td_/g; + $componentname =~ s/_linguistic_/_l_/g; + $componentname =~ s/_module_/_m_/g; + $componentname =~ s/_optional_/_opt_/g; + $componentname =~ s/_packages/_pack/g; + $componentname =~ s/_menubar/_mb/g; + $componentname =~ s/_common_/_cm_/g; + $componentname =~ s/_export_/_exp_/g; + $componentname =~ s/_table_/_tb_/g; + $componentname =~ s/_sofficecfg_/_sc_/g; + $componentname =~ s/_startmodulecommands_/_smc_/g; + $componentname =~ s/_drawimpresscommands_/_dic_/g; + $componentname =~ s/_basiccommands_/_bac_/g; + $componentname =~ s/_basicidecommands_/_baic_/g; + $componentname =~ s/_genericcommands_/_genc_/g; + $componentname =~ s/_bibliographycommands_/_bibc_/g; + $componentname =~ s/_share_/_s_/g; + $componentname =~ s/_modules_/_ms_/g; + $componentname =~ s/_uiconfig_zip_/_ucz_/g; + $componentname =~ s/_soffice_cfg_/_sc_/g; + + # All this is not necessary for files, which have the flag ASSIGNCOMPOMENT + + my $styles = ""; + if ( $fileref->{'Styles'} ) { $styles = $fileref->{'Styles'}; } + if ( $styles =~ /\bASSIGNCOMPOMENT\b/ ) { $componentname = get_component_from_assigned_file($fileref->{'AssignComponent'}, $filesref); } + + return $componentname; +} + +#################################################################### +# Returning the component name for a defined file gid. +# This is necessary for files with flag ASSIGNCOMPOMENT +#################################################################### + +sub get_component_from_assigned_file +{ + my ($gid, $filesref) = @_; + + my $onefile = installer::existence::get_specified_file($filesref, $gid); + my $componentname = ""; + if ( $onefile->{'componentname'} ) { $componentname = $onefile->{'componentname'}; } + else { installer::exiter::exit_program("ERROR: No component defined for file: $gid", "get_component_from_assigned_file"); } + + return $componentname; +} + +#################################################################### +# Generating the special filename for the database file File.idt +# Sample: CONTEXTS, CONTEXTS1 +# This name has to be unique. +# In most cases this is simply the filename. +#################################################################### + +sub generate_unique_filename_for_filetable +{ + my ($fileref, $component, $uniquefilenamehashref) = @_; + + # This new filename has to be saved into $fileref, because this is needed to find the source. + # The filename sbasic.idx/OFFSETS is changed to OFFSETS, but OFFSETS is not unique. + # In this procedure names like OFFSETS5 are produced. And exactly this string has to be added to + # the array of all files. + + my $uniquefilename = ""; + my $counter = 0; + + if ( $fileref->{'Name'} ) { $uniquefilename = $fileref->{'Name'}; } + + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$uniquefilename); # making /registry/schema/org/openoffice/VCL.xcs to VCL.xcs + + # Reading unique filename with help of "Component_" in File table from old database + if (( $installer::globals::updatedatabase ) && ( exists($uniquefilenamehashref->{"$component/$uniquefilename"}) )) + { + $uniquefilename = $uniquefilenamehashref->{"$component/$uniquefilename"}; # syntax of $value: ($uniquename;$shortname) + if ( $uniquefilename =~ /^\s*(.*?)\;\s*(.*?)\s*$/ ) { $uniquefilename = $1; } + $lcuniquefilename = lc($uniquefilename); + $installer::globals::alluniquefilenames{$uniquefilename} = 1; + $installer::globals::alllcuniquefilenames{$lcuniquefilename} = 1; + return $uniquefilename; + } + elsif (( $installer::globals::prepare_winpatch ) && ( exists($installer::globals::savedmapping{"$component/$uniquefilename"}) )) + { + # If we have a FTK mapping for this component/file, use it. + $installer::globals::savedmapping{"$component/$uniquefilename"} =~ m/^(.*);/; + $uniquefilename = $1; + $lcuniquefilename = lc($uniquefilename); + $installer::globals::alluniquefilenames{$uniquefilename} = 1; + $installer::globals::alllcuniquefilenames{$lcuniquefilename} = 1; + return $uniquefilename; + } + + $uniquefilename =~ s/\-/\_/g; # no "-" allowed + $uniquefilename =~ s/\@/\_/g; # no "@" allowed + $uniquefilename =~ s/\$/\_/g; # no "$" allowed + $uniquefilename =~ s/^\s*\./\_/g; # no "." at the beginning allowed allowed + $uniquefilename =~ s/^\s*\d/\_d/g; # no number at the beginning allowed allowed (even file "0.gif", replacing to "_d.gif") + $uniquefilename =~ s/org_openoffice_/ooo_/g; # shorten the unique file name + + my $lcuniquefilename = lc($uniquefilename); # only lowercase names + + my $newname = 0; + + if ( ! exists($installer::globals::alllcuniquefilenames{$lcuniquefilename}) && + ! exists($installer::globals::savedrevmapping{$lcuniquefilename}) ) + { + $installer::globals::alluniquefilenames{$uniquefilename} = 1; + $installer::globals::alllcuniquefilenames{$lcuniquefilename} = 1; + $newname = 1; + } + + if ( ! $newname ) + { + # adding a number until the name is really unique: OFFSETS, OFFSETS1, OFFSETS2, ... + # But attention: Making "abc.xcu" to "abc1.xcu" + + my $uniquefilenamebase = $uniquefilename; + + do + { + $counter++; + + if ( $uniquefilenamebase =~ /\./ ) + { + $uniquefilename = $uniquefilenamebase; + $uniquefilename =~ s/\./$counter\./; + } + else + { + $uniquefilename = $uniquefilenamebase . $counter; + } + + $newname = 0; + $lcuniquefilename = lc($uniquefilename); # only lowercase names + + if ( ! exists($installer::globals::alllcuniquefilenames{$lcuniquefilename}) && + ! exists($installer::globals::savedrevmapping{$lcuniquefilename}) ) + { + $installer::globals::alluniquefilenames{$uniquefilename} = 1; + $installer::globals::alllcuniquefilenames{$lcuniquefilename} = 1; + $newname = 1; + } + } + until ( $newname ) + } + + return $uniquefilename; +} + +#################################################################### +# Generating the special file column for the database file File.idt +# Sample: NAMETR~1.TAB|.nametranslation.table +# The first part has to be 8.3 conform. +#################################################################### + +sub generate_filename_for_filetable +{ + my ($fileref, $shortnamesref, $uniquefilenamehashref) = @_; + + my $returnstring = ""; + + my $filename = $fileref->{'Name'}; + + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$filename); # making /registry/schema/org/openoffice/VCL.xcs to VCL.xcs + + my $shortstring; + + # Reading short string with help of "FileName" in File table from old database + if (( $installer::globals::updatedatabase ) && ( exists($uniquefilenamehashref->{"$fileref->{'componentname'}/$filename"}) )) + { + my $value = $uniquefilenamehashref->{"$fileref->{'componentname'}/$filename"}; # syntax of $value: ($uniquename;$shortname) + if ( $value =~ /^\s*(.*?)\;\s*(.*?)\s*$/ ) { $shortstring = $2; } # already collected in function "collect_shortnames_from_old_database" + else { $shortstring = $filename; } + } + elsif (( $installer::globals::prepare_winpatch ) && ( exists($installer::globals::savedmapping{"$fileref->{'componentname'}/$filename"}) )) + { + $installer::globals::savedmapping{"$fileref->{'componentname'}/$filename"} =~ m/.*;(.*)/; + if ($1 ne '') + { + $shortstring = $1; + } + else + { + $shortstring = installer::windows::idtglobal::make_eight_three_conform_with_hash($filename, "file", $shortnamesref); + } + } + else + { + $shortstring = installer::windows::idtglobal::make_eight_three_conform_with_hash($filename, "file", $shortnamesref); + } + + if ( $shortstring eq $filename ) { $returnstring = $filename; } # nothing changed + else {$returnstring = $shortstring . "\|" . $filename; } + + return $returnstring; +} + +######################################### +# Returning the filesize of a file +######################################### + +sub get_filesize +{ + my ($fileref) = @_; + + my $file = $fileref->{'sourcepath'}; + + my $filesize; + + if ( -f $file ) # test of existence. For instance services.rdb does not always exist + { + $filesize = ( -s $file ); # file size can be "0" + } + else + { + $filesize = -1; + } + + return $filesize; +} + +############################################# +# Returning the file version, if required +# Sample: "8.0.1.8976"; +############################################# + +sub get_fileversion +{ + my ($onefile, $allvariables, $styles) = @_; + + my $fileversion = ""; + + if ( $allvariables->{'USE_FILEVERSION'} ) + { + if ( ! $allvariables->{'LIBRARYVERSION'} ) { installer::exiter::exit_program("ERROR: USE_FILEVERSION is set, but not LIBRARYVERSION", "get_fileversion"); } + my $libraryversion = $allvariables->{'LIBRARYVERSION'}; + if ( $libraryversion =~ /^\s*(\d+)\.(\d+)\.(\d+)\s*$/ ) + { + my $major = $1; + my $minor = $2; + my $micro = $3; + my $concat = 100 * $minor + $micro; + $libraryversion = $major . "\." . $concat; + } + my $vendornumber = 0; + if ( $allvariables->{'VENDORPATCHVERSION'} ) { $vendornumber = $allvariables->{'VENDORPATCHVERSION'}; } + $fileversion = $libraryversion . "\." . $installer::globals::buildid . "\." . $vendornumber; + if ( $onefile->{'FileVersion'} ) { $fileversion = $onefile->{'FileVersion'}; } # overriding FileVersion in scp + + # if ( $styles =~ /\bFONT\b/ ) + # { + # my $newfileversion = installer::windows::font::get_font_version($onefile->{'sourcepath'}); + # if ( $newfileversion != 0 ) { $fileversion = $newfileversion; } + # } + } + + if ( $installer::globals::prepare_winpatch ) { $fileversion = ""; } # Windows patches do not allow this version # -> who says so? + + return $fileversion; +} + +############################################# +# Returning the sequence for a file +############################################# + +sub get_sequence_for_file +{ + my ($number, $onefile, $fileentry, $allupdatesequenceshashref, $allupdatecomponentshashref, $allupdatefileorderhashref, $allfilecomponents) = @_; + + my $sequence = ""; + my $infoline = ""; + my $pffcomponentname = $onefile->{'componentname'} . "_pff"; + + if ( $installer::globals::updatedatabase ) + { + if (( exists($allupdatesequenceshashref->{$onefile->{'uniquename'}}) ) && + (( $onefile->{'componentname'} eq $allupdatecomponentshashref->{$onefile->{'uniquename'}} ) || + ( $pffcomponentname eq $allupdatecomponentshashref->{$onefile->{'uniquename'}} ))) + { + # The second condition is necessary to find shifted files, that have same "uniquename", but are now + # located in another directory. This can be seen at the component name. + $sequence = $allupdatesequenceshashref->{$onefile->{'uniquename'}}; + $onefile->{'assignedsequencenumber'} = $sequence; + # Collecting all used sequences, to guarantee, that no number is unused + $installer::globals::allusedupdatesequences{$sequence} = 1; + # Special help for files, that already have a "pff" component name (for example after ServicePack 1) + if ( $pffcomponentname eq $allupdatecomponentshashref->{$onefile->{'uniquename'}} ) + { + $infoline = "Warning: Special handling for component \"$pffcomponentname\". This file was added after the final, but before this ServicePack.\n"; + push(@installer::globals::logfileinfo, $infoline); + $onefile->{'componentname'} = $pffcomponentname; # pff for "post final file" + $fileentry->{'Component_'} = $onefile->{'componentname'}; + if ( ! exists($allfilecomponents->{$fileentry->{'Component_'}}) ) { $allfilecomponents->{$fileentry->{'Component_'}} = 1; } + } + } + else + { + $installer::globals::updatesequencecounter++; + $sequence = $installer::globals::updatesequencecounter; + $onefile->{'assignedsequencenumber'} = $sequence; + # $onefile->{'assignedcabinetfile'} = $installer::globals::pffcabfilename; # assigning to cabinet file for "post final files" + # Collecting all new files + $installer::globals::newupdatefiles{$sequence} = $onefile; + # Saving in sequence hash + $allupdatefileorderhashref->{$sequence} = $onefile->{'uniquename'}; + + # If the new file is part of an existing component, this must be changed now. All files + # of one component have to be included in one cabinet file. But because the order must + # not change, all new files have to be added to new components. + # $onefile->{'componentname'} = $file{'Component_'}; + + $onefile->{'componentname'} = $onefile->{'componentname'} . "_pff"; # pff for "post final file" + $fileentry->{'Component_'} = $onefile->{'componentname'}; + if ( ! exists($allfilecomponents->{$fileentry->{'Component_'}}) ) { $allfilecomponents->{$fileentry->{'Component_'}} = 1; } + $onefile->{'PostFinalFile'} = 1; + # $installer::globals::pfffileexists = 1; + # The sequence for this file has changed. It has to be inserted at the end of the files collector. + $installer::globals::insert_file_at_end = 1; + $installer::globals::newfilescollector{$sequence} = $onefile; # Adding new files to the end of the filescollector + $installer::globals::newfilesexist = 1; + } + } + elsif (( $onefile->{'assignedsequencenumber'} ) && ( $installer::globals::use_packages_for_cabs )) + { + $sequence = $onefile->{'assignedsequencenumber'}; + } + else + { + $sequence = $number; + # my $sequence = $number + 1; + + # Idea: Each component is packed into a cab file. + # This requires that all files in one cab file have sequences directly follwing each other, + # for instance from 1456 to 1466. Then in the media table the LastSequence for this cab file + # is 1466. + # Because all files belonging to one component are directly behind each other in the file + # collector, it is possible to use simply an increasing number as sequence value. + # If files belonging to one component are not directly behind each other in the files collector + # this mechanism will no longer work. + } + + return $sequence; +} + +############################################# +# Returning the Windows language of a file +############################################# + +sub get_language_for_file +{ + my ($fileref) = @_; + + my $language = ""; + + if ( $fileref->{'specificlanguage'} ) { $language = $fileref->{'specificlanguage'}; } + + if (!($language eq "")) + { + $language = installer::windows::language::get_windows_language($language); + } + + return $language; +} + +#################################################################### +# Creating a new KeyPath for components in TemplatesFolder. +#################################################################### + +sub generate_registry_keypath +{ + my ($onefile) = @_; + + my $keypath = $onefile->{'Name'}; + $keypath =~ s/\.//g; + $keypath = lc($keypath); + $keypath = "userreg_" . $keypath; + + return $keypath; +} + +#################################################################### +# Check, if in an update process files are missing. No removal +# of files allowed for Windows Patch creation. +# Also logging all new files, that have to be included in extra +# components and cab files. +#################################################################### + +sub check_file_sequences +{ + my ($allupdatefileorderhashref, $allupdatecomponentorderhashref) = @_; + + # All used sequences stored in %installer::globals::allusedupdatesequences + # Maximum sequence number of old database stored in $installer::globals::updatelastsequence + # All new files stored in %installer::globals::newupdatefiles + + my $infoline = ""; + + my @missing_sequences = (); + my @really_missing_sequences = (); + + for ( my $i = 1; $i <= $installer::globals::updatelastsequence; $i++ ) + { + if ( ! exists($installer::globals::allusedupdatesequences{$i}) ) { push(@missing_sequences, $i); } + } + + if ( $#missing_sequences > -1 ) + { + # Missing sequences can also be caused by files included in merge modules. This files are added later into the file table. + # Therefore now it is time to check the content of the merge modules. + + for ( my $j = 0; $j <= $#missing_sequences; $j++ ) + { + my $filename = $allupdatefileorderhashref->{$missing_sequences[$j]}; + + # Is this a file from a merge module? Then this is no error. + if ( ! exists($installer::globals::mergemodulefiles{$filename}) ) + { + push(@really_missing_sequences, $missing_sequences[$j]); + } + } + } + + if ( $#really_missing_sequences > -1 ) + { + my $errorstring = ""; + for ( my $j = 0; $j <= $#really_missing_sequences; $j++ ) + { + my $filename = $allupdatefileorderhashref->{$really_missing_sequences[$j]}; + my $comp = $allupdatecomponentorderhashref->{$really_missing_sequences[$j]}; + $errorstring = "$errorstring$filename (Sequence: $really_missing_sequences[$j], Component: \"$comp\")\n"; + } + + $infoline = "ERROR: Files are removed compared with update database.\nThe following files are missing:\n$errorstring"; + push(@installer::globals::logfileinfo, $infoline); + installer::exiter::exit_program($infoline, "check_file_sequences"); + } + + # Searching for new files + + my $counter = 0; + + foreach my $key ( keys %installer::globals::newupdatefiles ) + { + my $onefile = $installer::globals::newupdatefiles{$key}; + $counter++; + if ( $counter == 1 ) + { + $infoline = "\nNew files compared to the update database:\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + $infoline = "$onefile->{'Name'} ($onefile->{'gid'}) Sequence: $onefile->{'assignedsequencenumber'}\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + if ( $counter == 0 ) + { + $infoline = "Info: No new file compared with update database!\n"; + push(@installer::globals::logfileinfo, $infoline); + } + +} + +################################################################### +# Collecting further conditions for the component table. +# This is used by multilayer products, to enable installation +# of separate layers. +################################################################### + +sub get_tree_condition_for_component +{ + my ($onefile, $componentname) = @_; + + if ( $onefile->{'destination'} ) + { + my $dest = $onefile->{'destination'}; + + # Comparing the destination path with + # $installer::globals::hostnametreestyles{$hostname} = $treestyle; + # (-> hostname is the key, the style the value!) + + foreach my $hostname ( keys %installer::globals::hostnametreestyles ) + { + if (( $dest eq $hostname ) || ( $dest =~ /^\s*\Q$hostname\E\\/ )) + { + # the value is the style + my $style = $installer::globals::hostnametreestyles{$hostname}; + # the condition is saved in %installer::globals::treestyles + my $condition = $installer::globals::treestyles{$style}; + # Saving condition to be added in table Property + $installer::globals::usedtreeconditions{$condition} = 1; + $condition = $condition . "=1"; + # saving this condition + $installer::globals::treeconditions{$componentname} = $condition; + + # saving also at the file, for usage in fileinfo + $onefile->{'layer'} = $installer::globals::treelayername{$style}; + } + } + } +} + +############################################ +# Collecting all short names, that are +# already used by the old database +############################################ + +sub collect_shortnames_from_old_database +{ + my ($uniquefilenamehashref, $shortnameshashref) = @_; + + foreach my $key ( keys %{$uniquefilenamehashref} ) + { + my $value = $uniquefilenamehashref->{$key}; # syntax of $value: ($uniquename;$shortname) + + if ( $value =~ /^\s*(.*?)\;\s*(.*?)\s*$/ ) + { + my $shortstring = $2; + $shortnameshashref->{$shortstring} = 1; # adding the shortname to the array of all shortnames + } + } +} + +############################################ +# Creating the file File.idt dynamically +############################################ + +sub create_files_table +{ + my ($filesref, $allfilecomponentsref, $basedir, $allvariables, $uniquefilenamehashref, $allupdatesequenceshashref, $allupdatecomponentshashref, $allupdatefileorderhashref) = @_; + + installer::logger::include_timestamp_into_logfile("Performance Info: File Table start"); + + # Structure of the files table: + # File Component_ FileName FileSize Version Language Attributes Sequence + # In this function, all components are created. + # + # $allfilecomponentsref is empty at the beginning + + my $infoline; + + my @allfiles = (); + my @filetable = (); + my @filehashtable = (); + my %allfilecomponents = (); + my $counter = 0; + + if ( $^O =~ /cygwin/i ) { installer::worker::generate_cygwin_pathes($filesref); } + + # The filenames must be collected because of uniqueness + # 01-44-~1.DAT, 01-44-~2.DAT, ... + # my @shortnames = (); + my %shortnames = (); + + if ( $installer::globals::updatedatabase ) { collect_shortnames_from_old_database($uniquefilenamehashref, \%shortnames); } + + installer::windows::idtglobal::write_idt_header(\@filetable, "file"); + installer::windows::idtglobal::write_idt_header(\@filehashtable, "filehash"); + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my %file = (); + + my $onefile = ${$filesref}[$i]; + + my $styles = ""; + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } + if (( $styles =~ /\bJAVAFILE\b/ ) && ( ! ($allvariables->{'JAVAPRODUCT'} ))) { next; } + + $file{'Component_'} = get_file_component_name($onefile, $filesref); + $file{'File'} = generate_unique_filename_for_filetable($onefile, $file{'Component_'}, $uniquefilenamehashref); + + $onefile->{'uniquename'} = $file{'File'}; + $onefile->{'componentname'} = $file{'Component_'}; + + # Collecting all components + # if (!(installer::existence::exists_in_array($file{'Component_'}, $allfilecomponentsref))) { push(@{$allfilecomponentsref}, $file{'Component_'}); } + + if ( ! exists($allfilecomponents{$file{'Component_'}}) ) { $allfilecomponents{$file{'Component_'}} = 1; } + + $file{'FileName'} = generate_filename_for_filetable($onefile, \%shortnames, $uniquefilenamehashref); + + $file{'FileSize'} = get_filesize($onefile); + + $file{'Version'} = get_fileversion($onefile, $allvariables, $styles); + + $file{'Language'} = get_language_for_file($onefile); + + if ( $styles =~ /\bDONT_PACK\b/ ) { $file{'Attributes'} = "8192"; } + else { $file{'Attributes'} = "16384"; } + + # $file{'Attributes'} = "16384"; # Sourcefile is packed + # $file{'Attributes'} = "8192"; # Sourcefile is unpacked + + $installer::globals::insert_file_at_end = 0; + $counter++; + $file{'Sequence'} = get_sequence_for_file($counter, $onefile, \%file, $allupdatesequenceshashref, $allupdatecomponentshashref, $allupdatefileorderhashref, \%allfilecomponents); + + $onefile->{'sequencenumber'} = $file{'Sequence'}; + + my $oneline = $file{'File'} . "\t" . $file{'Component_'} . "\t" . $file{'FileName'} . "\t" + . $file{'FileSize'} . "\t" . $file{'Version'} . "\t" . $file{'Language'} . "\t" + . $file{'Attributes'} . "\t" . $file{'Sequence'} . "\n"; + + push(@filetable, $oneline); + + if ( ! $installer::globals::insert_file_at_end ) { push(@allfiles, $onefile); } + + # Collecting all component conditions + if ( $onefile->{'ComponentCondition'} ) + { + if ( ! exists($installer::globals::componentcondition{$file{'Component_'}})) + { + $installer::globals::componentcondition{$file{'Component_'}} = $onefile->{'ComponentCondition'}; + } + } + + # Collecting also all tree conditions for multilayer products + get_tree_condition_for_component($onefile, $file{'Component_'}); + + # Collecting all component names, that have flag VERSION_INDEPENDENT_COMP_ID + # This should be all components with constant API, for example URE + if ( $styles =~ /\bVERSION_INDEPENDENT_COMP_ID\b/ ) + { + $installer::globals::base_independent_components{$onefile->{'componentname'}} = 1; + } + + # Collecting all component ids, that are defined at files in scp project (should not be used anymore) + if ( $onefile->{'CompID'} ) + { + if ( ! exists($installer::globals::componentid{$onefile->{'componentname'}})) + { + $installer::globals::componentid{$onefile->{'componentname'}} = $onefile->{'CompID'}; + } + else + { + if ( $installer::globals::componentid{$onefile->{'componentname'}} ne $onefile->{'CompID'} ) + { + installer::exiter::exit_program("ERROR: There is already a ComponentID for component \"$onefile->{'componentname'}\" : \"$installer::globals::componentid{$onefile->{'componentname'}}\" . File \"$onefile->{'gid'}\" uses \"$onefile->{'CompID'}\" !", "create_files_table"); + } + } + + # Also checking vice versa. Is this ComponentID already used? If yes, is the componentname the same? + + if ( ! exists($installer::globals::comparecomponentname{$onefile->{'CompID'}})) + { + $installer::globals::comparecomponentname{$onefile->{'CompID'}} = $onefile->{'componentname'}; + } + else + { + if ( $installer::globals::comparecomponentname{$onefile->{'CompID'}} ne $onefile->{'componentname'} ) + { + installer::exiter::exit_program("ERROR: There is already a component for ComponentID \"$onefile->{'CompID'}\" : \"$installer::globals::comparecomponentname{$onefile->{'CompID'}}\" . File \"$onefile->{'gid'}\" has same component id but is included in component \"$onefile->{'componentname'}\" !", "create_files_table"); + } + } + } + + # Collecting all language specific conditions + # if ( $onefile->{'haslanguagemodule'} ) + if ( $onefile->{'ismultilingual'} ) + { + if ( $onefile->{'ComponentCondition'} ) { installer::exiter::exit_program("ERROR: Cannot set language condition. There is already another component condition for file $onefile->{'gid'}: \"$onefile->{'ComponentCondition'}\" !", "create_files_table"); } + + if ( $onefile->{'specificlanguage'} eq "" ) { installer::exiter::exit_program("ERROR: There is no specific language for file at language module: $onefile->{'gid'} !", "create_files_table"); } + my $locallanguage = $onefile->{'specificlanguage'}; + my $property = "IS" . $file{'Language'}; + my $value = 1; + my $condition = $property . "=" . $value; + + $onefile->{'ComponentCondition'} = $condition; + + if ( exists($installer::globals::componentcondition{$file{'Component_'}})) + { + if ( $installer::globals::componentcondition{$file{'Component_'}} ne $condition ) { installer::exiter::exit_program("ERROR: There is already another component condition for file $onefile->{'gid'}: \"$installer::globals::componentcondition{$file{'Component_'}}\" and \"$condition\" !", "create_files_table"); } + } + else + { + $installer::globals::componentcondition{$file{'Component_'}} = $condition; + } + + # collecting all properties for table Property + if ( ! exists($installer::globals::languageproperties{$property}) ) { $installer::globals::languageproperties{$property} = $value; } + } + + if ( $installer::globals::prepare_winpatch ) + { + my $path = $onefile->{'sourcepath'}; + if ( $^O =~ /cygwin/i ) { $path = $onefile->{'cyg_sourcepath'}; } + + open(FILE, $path) or die "ERROR: Can't open $path for creating file hash"; + binmode(FILE); + my $hashinfo = pack("l", 20); + $hashinfo .= Digest::MD5->new->addfile(*FILE)->digest; + + my @i = unpack ('x[l]l4', $hashinfo); + $oneline = $file{'File'} . "\t" . + "0" . "\t" . + $i[0] . "\t" . + $i[1] . "\t" . + $i[2] . "\t" . + $i[3] . "\n"; + push (@filehashtable, $oneline); + } + + # Saving the sequence number in a hash with uniquefilename as key. + # This is used for better performance in "save_packorder" + $installer::globals::uniquefilenamesequence{$onefile->{'uniquename'}} = $onefile->{'sequencenumber'}; + + # Special handling for files in PREDEFINED_OSSHELLNEWDIR. These components + # need as KeyPath a RegistryItem in HKCU + my $destdir = ""; + if ( $onefile->{'Dir'} ) { $destdir = $onefile->{'Dir'}; } + + if (( $destdir =~ /\bPREDEFINED_OSSHELLNEWDIR\b/ ) || ( $onefile->{'needs_user_registry_key'} )) + { + my $keypath = generate_registry_keypath($onefile); + $onefile->{'userregkeypath'} = $keypath; + push(@installer::globals::userregistrycollector, $onefile); + $installer::globals::addeduserregitrykeys = 1; + } + } + + # putting content from %allfilecomponents to $allfilecomponentsref for later usage + foreach $localkey (keys %allfilecomponents ) { push( @{$allfilecomponentsref}, $localkey); } + + my $filetablename = $basedir . $installer::globals::separator . "File.idt"; + installer::files::save_file($filetablename ,\@filetable); + $infoline = "\nCreated idt file: $filetablename\n"; + push(@installer::globals::logfileinfo, $infoline); + + installer::logger::include_timestamp_into_logfile("Performance Info: File Table end"); + + my $filehashtablename = $basedir . $installer::globals::separator . "MsiFileHash.idt"; + installer::files::save_file($filehashtablename ,\@filehashtable); + $infoline = "\nCreated idt file: $filehashtablename\n"; + push(@installer::globals::logfileinfo, $infoline); + + # Now the new files can be added to the files collector (only in update packaging processes) + if ( $installer::globals::newfilesexist ) + { + foreach my $seq (sort keys %installer::globals::newfilescollector) { push(@allfiles, $installer::globals::newfilescollector{$seq}) } + } + + return \@allfiles; +} + +1; diff --git a/solenv/bin/modules/installer/windows/font.pm b/solenv/bin/modules/installer/windows/font.pm new file mode 100644 index 000000000000..fec60e719150 --- /dev/null +++ b/solenv/bin/modules/installer/windows/font.pm @@ -0,0 +1,114 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: font.pm,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::font; + +use installer::files; +use installer::globals; +use installer::windows::idtglobal; + + +################################################################################# +# Creating the file Font.idt dynamically +# Content: +# File_ FontTitle +################################################################################# + +sub create_font_table +{ + my ($filesref, $basedir) = @_; + + my @fonttable = (); + + installer::windows::idtglobal::write_idt_header(\@fonttable, "font"); + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + my $styles = ""; + + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } + + if ( $styles =~ /\bFONT\b/ ) + { + my %font = (); + + $font{'File_'} = $onefile->{'uniquename'}; + # $font{'FontTitle'} = $onefile->{'FontName'}; # results in a warning during validation + $font{'FontTitle'} = ""; + + my $oneline = $font{'File_'} . "\t" . $font{'FontTitle'} . "\n"; + + push(@fonttable, $oneline); + } + } + + # Saving the file + + my $fonttablename = $basedir . $installer::globals::separator . "Font.idt"; + installer::files::save_file($fonttablename ,\@fonttable); + my $infoline = "Created idt file: $fonttablename\n"; + push(@installer::globals::logfileinfo, $infoline); + +} + +################################################################################# +# Reading the Font version from the ttf file, to avoid installation +# of older files over newer files. +################################################################################# + +sub get_font_version +{ + my ( $fontfile ) = @_; + + if ( ! -f $fontfile ) { installer::exiter::exit_program("ERROR: Font file does not exist: \"$fontfile\"", "get_font_version"); } + + my $fontversion = 0; + my $infoline = ""; + + my $onefile = installer::files::read_binary_file($fontfile); + + if ( $onefile =~ /Version\s+(\d+\.\d+\.*\d*)/ ) + { + $fontversion = $1; + $infoline = "FONT: Font \"$fontfile\" version: $fontversion\n"; + push(@installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "FONT: Could not determine font version: \"$fontfile\"\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + return $fontversion; +} + +1; diff --git a/solenv/bin/modules/installer/windows/icon.pm b/solenv/bin/modules/installer/windows/icon.pm new file mode 100644 index 000000000000..5f101131ff4f --- /dev/null +++ b/solenv/bin/modules/installer/windows/icon.pm @@ -0,0 +1,81 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: icon.pm,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::icon; + +use installer::files; +use installer::globals; +use installer::pathanalyzer; +use installer::windows::idtglobal; + +########################################################################################################### +# Creating the file Icon.idt dynamically +# Content: +# Name Data +########################################################################################################### + +sub create_icon_table +{ + my ($iconfilecollector, $basedir) = @_; + + my @icontable = (); + + installer::windows::idtglobal::write_idt_header(\@icontable, "icon"); + + # Only the iconfiles, that are used in the shortcut table for the + # FolderItems (entries in Windows startmenu) are added into the icon table. + + for ( my $i = 0; $i <= $#{$iconfilecollector}; $i++ ) + { + my $iconfile = ${$iconfilecollector}[$i]; + + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$iconfile); + + my %icon = (); + + $icon{'Name'} = $iconfile; # simply soffice.exe + $icon{'Data'} = $iconfile; # simply soffice.exe + + my $oneline = $icon{'Name'} . "\t" . $icon{'Data'} . "\n"; + + push(@icontable, $oneline); + } + + # Saving the file + + my $icontablename = $basedir . $installer::globals::separator . "Icon.idt"; + installer::files::save_file($icontablename ,\@icontable); + my $infoline = "Created idt file: $icontablename\n"; + push(@installer::globals::logfileinfo, $infoline); + +} + +1; diff --git a/solenv/bin/modules/installer/windows/idtglobal.pm b/solenv/bin/modules/installer/windows/idtglobal.pm new file mode 100644 index 000000000000..c61a6789fdcb --- /dev/null +++ b/solenv/bin/modules/installer/windows/idtglobal.pm @@ -0,0 +1,2450 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: idtglobal.pm,v $ +# +# $Revision: 1.45 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::idtglobal; + +use Cwd; +use installer::converter; +use installer::existence; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::pathanalyzer; +use installer::remover; +use installer::scriptitems; +use installer::systemactions; +use installer::windows::language; + +############################################################## +# Shorten the gid for a feature. +# Attention: Maximum length is 38 +############################################################## + +sub shorten_feature_gid +{ + my ($stringref) = @_; + + $$stringref =~ s/gid_Module_/gm_/; + $$stringref =~ s/_Root_/_r_/; + $$stringref =~ s/_Prg_/_p_/; + $$stringref =~ s/_Optional_/_o_/; + $$stringref =~ s/_Wrt_Flt_/_w_f_/; + $$stringref =~ s/_Javafilter_/_jf_/; +} + +############################################ +# Getting the next free number, that +# can be added. +# Sample: 01-44-~1.DAT, 01-44-~2.DAT, ... +############################################ + +sub get_next_free_number +{ + my ($name, $shortnamesref) = @_; + + my $counter = 0; + my $dontsave = 0; + my $alreadyexists; + my ($newname, $shortname); + + do + { + $alreadyexists = 0; + $counter++; + $newname = $name . $counter; + + for ( my $i = 0; $i <= $#{$shortnamesref}; $i++ ) + { + $shortname = ${$shortnamesref}[$i]; + + if ( uc($shortname) eq uc($newname) ) # case insensitive + { + $alreadyexists = 1; + last; + } + } + } + until (!($alreadyexists)); + + if (( $counter > 9 ) && ( length($name) > 6 )) + { + $dontsave = 1; + } + + if (!($dontsave)) + { + push(@{$shortnamesref}, $newname); # adding the new shortname to the array of shortnames + } + + return $counter +} + +############################################ +# Getting the next free number, that +# can be added. +# Sample: 01-44-~1.DAT, 01-44-~2.DAT, ... +############################################ + +sub get_next_free_number_with_hash +{ + my ($name, $shortnamesref, $ext) = @_; + + my $counter = 0; + my $dontsave = 0; + my $saved = 0; + my $alreadyexists; + my ($newname, $shortname); + + do + { + $alreadyexists = 0; + $counter++; + $newname = $name . $counter; + $newname = uc($newname); # case insensitive, always upper case + if ( exists($shortnamesref->{$newname}) || + exists($installer::globals::savedrev83mapping{$newname.$ext}) ) + { + $alreadyexists = 1; + } + } + until (!($alreadyexists)); + + if (( $counter > 9 ) && ( length($name) > 6 )) { $dontsave = 1; } + if (( $counter > 99 ) && ( length($name) > 5 )) { $dontsave = 1; } + + if (!($dontsave)) + { + # push(@{$shortnamesref}, $newname); # adding the new shortname to the array of shortnames + $shortnamesref->{$newname} = 1; # adding the new shortname to the array of shortnames, always uppercase + $saved = 1; + } + + return ( $counter, $saved ) +} + +######################################### +# 8.3 for filenames and directories +######################################### + +sub make_eight_three_conform +{ + my ($inputstring, $pattern, $shortnamesref) = @_; + + # all shortnames are collected in $shortnamesref, because of uniqueness + + my ($name, $namelength, $number); + my $conformstring = ""; + my $changed = 0; + + if (( $inputstring =~ /^\s*(.*?)\.(.*?)\s*$/ ) && ( $pattern eq "file" )) # files with a dot + { + $name = $1; + my $extension = $2; + + $namelength = length($name); + my $extensionlength = length($extension); + + if ( $extensionlength > 3 ) + { + # simply taking the first three letters + $extension = substr($extension, 0, 3); # name, offset, length + } + + # Attention: readme.html -> README~1.HTM + + if (( $namelength > 8 ) || ( $extensionlength > 3 )) + { + # taking the first six letters + $name = substr($name, 0, 6); # name, offset, length + $name =~ s/\s*$//; # removing ending whitespaces + $name = $name . "\~"; + $number = get_next_free_number($name, $shortnamesref); + + # if $number>9 the new name would be "abcdef~10.xyz", which is 9+3, and therefore not allowed + + if ( $number > 9 ) + { + $name = substr($name, 0, 5); # name, offset, length + $name =~ s/\s*$//; # removing ending whitespaces + $name = $name . "\~"; + $number = get_next_free_number($name, $shortnamesref); + } + + $name = $name . "$number"; + + $changed = 1; + } + + $conformstring = $name . "\." . $extension; + + if ( $changed ) { $conformstring= uc($conformstring); } + } + else # no dot in filename or directory (also used for shortcuts) + { + $name = $inputstring; + $namelength = length($name); + + if ( $namelength > 8 ) + { + # taking the first six letters + $name = substr($name, 0, 6); # name, offset, length + $name =~ s/\s*$//; # removing ending whitespaces + $name = $name . "\~"; + $number = get_next_free_number($name, $shortnamesref); + + # if $number>9 the new name would be "abcdef~10.xyz", which is 9+3, and therefore not allowed + + if ( $number > 9 ) + { + $name = substr($name, 0, 5); # name, offset, length + $name =~ s/\s*$//; # removing ending whitespaces + $name = $name . "\~"; + $number = get_next_free_number($name, $shortnamesref); + } + + $name = $name . "$number"; + $changed = 1; + if ( $pattern eq "dir" ) { $name =~ s/\./\_/g; } # in directories replacing "." with "_" + } + + $conformstring = $name; + + if ( $changed ) { $conformstring = uc($name); } + } + + return $conformstring; +} + +######################################### +# 8.3 for filenames and directories +# $shortnamesref is a hash in this case +# -> performance reasons +######################################### + +sub make_eight_three_conform_with_hash +{ + my ($inputstring, $pattern, $shortnamesref) = @_; + + # all shortnames are collected in $shortnamesref, because of uniqueness (a hash!) + + my ($name, $namelength, $number); + my $conformstring = ""; + my $changed = 0; + my $saved; + + # if (( $inputstring =~ /^\s*(.*?)\.(.*?)\s*$/ ) && ( $pattern eq "file" )) # files with a dot + if (( $inputstring =~ /^\s*(.*)\.(.*?)\s*$/ ) && ( $pattern eq "file" )) # files with a dot + { + # extension has to be non-greedy, but name is. This is important to find the last dot in the filename + $name = $1; + my $extension = $2; + + if ( $name =~ /^\s*(.*?)\s*$/ ) { $name = $1; } # now the name is also non-greedy + $name =~ s/\.//g; # no dots in 8+3 conform filename + + $namelength = length($name); + my $extensionlength = length($extension); + + if ( $extensionlength > 3 ) + { + # simply taking the first three letters + $extension = substr($extension, 0, 3); # name, offset, length + $changed = 1; + } + + # Attention: readme.html -> README~1.HTM + + if (( $namelength > 8 ) || ( $extensionlength > 3 )) + { + # taking the first six letters, if filename is longer than 6 characters + if ( $namelength > 6 ) + { + $name = substr($name, 0, 6); # name, offset, length + $name =~ s/\s*$//; # removing ending whitespaces + $name = $name . "\~"; + ($number, $saved) = get_next_free_number_with_hash($name, $shortnamesref, '.'.uc($extension)); + + # if $number>9 the new name would be "abcdef~10.xyz", which is 9+3, and therefore not allowed + + if ( ! $saved ) + { + $name = substr($name, 0, 5); # name, offset, length + $name =~ s/\s*$//; # removing ending whitespaces + $name = $name . "\~"; + ($number, $saved) = get_next_free_number_with_hash($name, $shortnamesref, '.'.uc($extension)); + + # if $number>99 the new name would be "abcde~100.xyz", which is 9+3, and therefore not allowed + + if ( ! $saved ) + { + $name = substr($name, 0, 4); # name, offset, length + $name =~ s/\s*$//; # removing ending whitespaces + $name = $name . "\~"; + ($number, $saved) = get_next_free_number_with_hash($name, $shortnamesref, '.'.uc($extension)); + + if ( ! $saved ) + { + installer::exiter::exit_program("ERROR: Could not set 8+3 conform name for $inputstring !", "make_eight_three_conform_with_hash"); + } + } + } + + $name = $name . "$number"; + $changed = 1; + } + } + + $conformstring = $name . "\." . $extension; + + if ( $changed ) { $conformstring= uc($conformstring); } + } + else # no dot in filename or directory (also used for shortcuts) + { + $name = $inputstring; + $namelength = length($name); + + if ( $namelength > 8 ) + { + # taking the first six letters + $name = substr($name, 0, 6); # name, offset, length + $name =~ s/\s*$//; # removing ending whitespaces + $name = $name . "\~"; + ( $number, $saved ) = get_next_free_number_with_hash($name, $shortnamesref, ''); + + # if $number>9 the new name would be "abcdef~10", which is 9+0, and therefore not allowed + + if ( ! $saved ) + { + $name = substr($name, 0, 5); # name, offset, length + $name =~ s/\s*$//; # removing ending whitespaces + $name = $name . "\~"; + ( $number, $saved ) = get_next_free_number_with_hash($name, $shortnamesref, ''); + + # if $number>99 the new name would be "abcde~100", which is 9+0, and therefore not allowed + + if ( ! $saved ) + { + $name = substr($name, 0, 4); # name, offset, length + $name =~ s/\s*$//; # removing ending whitespaces + $name = $name . "\~"; + ( $number, $saved ) = get_next_free_number_with_hash($name, $shortnamesref, ''); + + if ( ! $saved ) { installer::exiter::exit_program("ERROR: Could not set 8+3 conform name for $inputstring !", "make_eight_three_conform_with_hash"); } + } + } + + $name = $name . "$number"; + $changed = 1; + if ( $pattern eq "dir" ) { $name =~ s/\./\_/g; } # in directories replacing "." with "_" + } + + $conformstring = $name; + + if ( $changed ) { $conformstring = uc($name); } + } + + return $conformstring; +} + +######################################### +# Writing the header for idt files +######################################### + +sub write_idt_header +{ + my ($idtref, $definestring) = @_; + + my $oneline; + + if ( $definestring eq "file" ) + { + $oneline = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"; + push(@{$idtref}, $oneline); + $oneline = "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"; + push(@{$idtref}, $oneline); + $oneline = "File\tFile\n"; + push(@{$idtref}, $oneline); + } + + if ( $definestring eq "filehash" ) + { + $oneline = "File_\tOptions\tHashPart1\tHashPart2\tHashPart3\tHashPart4\n"; + push(@{$idtref}, $oneline); + $oneline = "s72\ti2\ti4\ti4\ti4\ti4\n"; + push(@{$idtref}, $oneline); + $oneline = "MsiFileHash\tFile_\n"; + push(@{$idtref}, $oneline); + } + + if ( $definestring eq "directory" ) + { + $oneline = "Directory\tDirectory_Parent\tDefaultDir\n"; + push(@{$idtref}, $oneline); + $oneline = "s72\tS72\tl255\n"; + push(@{$idtref}, $oneline); + $oneline = "Directory\tDirectory\n"; + push(@{$idtref}, $oneline); + } + + if ( $definestring eq "component" ) + { + $oneline = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"; + push(@{$idtref}, $oneline); + $oneline = "s72\tS38\ts72\ti2\tS255\tS72\n"; + push(@{$idtref}, $oneline); + $oneline = "Component\tComponent\n"; + push(@{$idtref}, $oneline); + } + + if ( $definestring eq "feature" ) + { + $oneline = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"; + push(@{$idtref}, $oneline); + $oneline = "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"; + push(@{$idtref}, $oneline); + $oneline = "WINDOWSENCODINGTEMPLATE\tFeature\tFeature\n"; + push(@{$idtref}, $oneline); + } + + if ( $definestring eq "featurecomponent" ) + { + $oneline = "Feature_\tComponent_\n"; + push(@{$idtref}, $oneline); + $oneline = "s38\ts72\n"; + push(@{$idtref}, $oneline); + $oneline = "FeatureComponents\tFeature_\tComponent_\n"; + push(@{$idtref}, $oneline); + } + + if ( $definestring eq "media" ) + { + $oneline = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"; + push(@{$idtref}, $oneline); + $oneline = "i2\ti2\tL64\tS255\tS32\tS72\n"; + push(@{$idtref}, $oneline); + $oneline = "Media\tDiskId\n"; + push(@{$idtref}, $oneline); + } + + if ( $definestring eq "font" ) + { + $oneline = "File_\tFontTitle\n"; + push(@{$idtref}, $oneline); + $oneline = "s72\tS128\n"; + push(@{$idtref}, $oneline); + $oneline = "Font\tFile_\n"; + push(@{$idtref}, $oneline); + } + + if ( $definestring eq "shortcut" ) + { + $oneline = "Shortcut\tDirectory_\tName\tComponent_\tTarget\tArguments\tDescription\tHotkey\tIcon_\tIconIndex\tShowCmd\tWkDir\n"; + push(@{$idtref}, $oneline); + $oneline = "s72\ts72\tl128\ts72\ts72\tS255\tL255\tI2\tS72\tI2\tI2\tS72\n"; + push(@{$idtref}, $oneline); + $oneline = "WINDOWSENCODINGTEMPLATE\tShortcut\tShortcut\n"; + push(@{$idtref}, $oneline); + } + + if ( $definestring eq "registry" ) + { + $oneline = "Registry\tRoot\tKey\tName\tValue\tComponent_\n"; + push(@{$idtref}, $oneline); + $oneline = "s72\ti2\tl255\tL255\tL0\ts72\n"; + push(@{$idtref}, $oneline); + $oneline = "Registry\tRegistry\n"; + push(@{$idtref}, $oneline); + } + + if ( $definestring eq "createfolder" ) + { + $oneline = "Directory_\tComponent_\n"; + push(@{$idtref}, $oneline); + $oneline = "s72\ts72\n"; + push(@{$idtref}, $oneline); + $oneline = "CreateFolder\tDirectory_\tComponent_\n"; + push(@{$idtref}, $oneline); + } + + if ( $definestring eq "removefile" ) + { + $oneline = "FileKey\tComponent_\tFileName\tDirProperty\tInstallMode\n"; + push(@{$idtref}, $oneline); + $oneline = "s72\ts72\tL255\ts72\ti2\n"; + push(@{$idtref}, $oneline); + $oneline = "RemoveFile\tFileKey\n"; + push(@{$idtref}, $oneline); + } + + if ( $definestring eq "upgrade" ) + { + $oneline = "UpgradeCode\tVersionMin\tVersionMax\tLanguage\tAttributes\tRemove\tActionProperty\n"; + push(@{$idtref}, $oneline); + $oneline = "s38\tS20\tS20\tS255\ti4\tS255\ts72\n"; + push(@{$idtref}, $oneline); + $oneline = "Upgrade\tUpgradeCode\tVersionMin\tVersionMax\tLanguage\tAttributes\n"; + push(@{$idtref}, $oneline); + } + + if ( $definestring eq "icon" ) + { + $oneline = "Name\tData\n"; + push(@{$idtref}, $oneline); + $oneline = "s72\tv0\n"; + push(@{$idtref}, $oneline); + $oneline = "Icon\tName\n"; + push(@{$idtref}, $oneline); + } + + if ( $definestring eq "inifile" ) + { + $oneline = "IniFile\tFileName\tDirProperty\tSection\tKey\tValue\tAction\tComponent_\n"; + push(@{$idtref}, $oneline); + $oneline = "s72\tl255\tS72\tl96\tl128\tl255\ti2\ts72\n"; + push(@{$idtref}, $oneline); + $oneline = "IniFile\tIniFile\n"; + push(@{$idtref}, $oneline); + } + + if ( $definestring eq "selfreg" ) + { + $oneline = "File_\tCost\n"; + push(@{$idtref}, $oneline); + $oneline = "s72\tI2\n"; + push(@{$idtref}, $oneline); + $oneline = "SelfReg\tFile_\n"; + push(@{$idtref}, $oneline); + } + + if ( $definestring eq "msiassembly" ) + { + $oneline = "Component_\tFeature_\tFile_Manifest\tFile_Application\tAttributes\n"; + push(@{$idtref}, $oneline); + $oneline = "s72\ts38\tS72\tS72\tI2\n"; + push(@{$idtref}, $oneline); + $oneline = "MsiAssembly\tComponent_\n"; + push(@{$idtref}, $oneline); + } + + if ( $definestring eq "msiassemblyname" ) + { + $oneline = "Component_\tName\tValue\n"; + push(@{$idtref}, $oneline); + $oneline = "s72\ts255\ts255\n"; + push(@{$idtref}, $oneline); + $oneline = "MsiAssemblyName\tComponent_\tName\n"; + push(@{$idtref}, $oneline); + } + + if ( $definestring eq "appsearch" ) + { + $oneline = "Property\tSignature_\n"; + push(@{$idtref}, $oneline); + $oneline = "s72\ts72\n"; + push(@{$idtref}, $oneline); + $oneline = "AppSearch\tProperty\tSignature_\n"; + push(@{$idtref}, $oneline); + } + + if ( $definestring eq "reglocat" ) + { + $oneline = "Signature_\tRoot\tKey\tName\tType\n"; + push(@{$idtref}, $oneline); + $oneline = "s72\ti2\ts255\tS255\tI2\n"; + push(@{$idtref}, $oneline); + $oneline = "RegLocator\tSignature_\n"; + push(@{$idtref}, $oneline); + } + + if ( $definestring eq "signatur" ) + { + $oneline = "Signature\tFileName\tMinVersion\tMaxVersion\tMinSize\tMaxSize\tMinDate\tMaxDate\tLanguages\n"; + push(@{$idtref}, $oneline); + $oneline = "s72\ts255\tS20\tS20\tI4\tI4\tI4\tI4\tS255\n"; + push(@{$idtref}, $oneline); + $oneline = "Signature\tSignature\n"; + push(@{$idtref}, $oneline); + } + +} + +############################################################## +# Returning the name of the rranslation file for a +# given language. +# Sample: "01" oder "en-US" -> "1033.txt" +############################################################## + +sub get_languagefilename +{ + my ($idtfilename, $basedir) = @_; + + # $idtfilename =~ s/\.idt/\.ulf/; + $idtfilename =~ s/\.idt/\.mlf/; + + my $languagefilename = $basedir . $installer::globals::separator . $idtfilename; + + return $languagefilename; +} + +############################################################## +# Returning the complete block in all languages +# for a specified string +############################################################## + +sub get_language_block_from_language_file +{ + my ($searchstring, $languagefile) = @_; + + my @language_block = (); + + for ( my $i = 0; $i <= $#{$languagefile}; $i++ ) + { + if ( ${$languagefile}[$i] =~ /^\s*\[\s*$searchstring\s*\]\s*$/ ) + { + my $counter = $i; + + push(@language_block, ${$languagefile}[$counter]); + $counter++; + + while (( $counter <= $#{$languagefile} ) && (!( ${$languagefile}[$counter] =~ /^\s*\[/ ))) + { + push(@language_block, ${$languagefile}[$counter]); + $counter++; + } + + last; + } + } + + return \@language_block; +} + +############################################################## +# Returning a specific language string from the block +# of all translations +############################################################## + +sub get_language_string_from_language_block +{ + my ($language_block, $language, $oldstring) = @_; + + my $newstring = ""; + + for ( my $i = 0; $i <= $#{$language_block}; $i++ ) + { + if ( ${$language_block}[$i] =~ /^\s*$language\s*\=\s*\"(.*)\"\s*$/ ) + { + $newstring = $1; + last; + } + } + + if ( $newstring eq "" ) + { + $language = "en-US"; # defaulting to english + + for ( my $i = 0; $i <= $#{$language_block}; $i++ ) + { + if ( ${$language_block}[$i] =~ /^\s*$language\s*\=\s*\"(.*)\"\s*$/ ) + { + $newstring = $1; + last; + } + } + } + + return $newstring; +} + +############################################################## +# Returning a specific code from the block +# of all codes. No defaulting to english! +############################################################## + +sub get_code_from_code_block +{ + my ($codeblock, $language) = @_; + + my $newstring = ""; + + for ( my $i = 0; $i <= $#{$codeblock}; $i++ ) + { + if ( ${$codeblock}[$i] =~ /^\s*$language\s*\=\s*\"(.*)\"\s*$/ ) + { + $newstring = $1; + last; + } + } + + return $newstring; +} + +############################################################## +# Translating an idt file +############################################################## + +sub translate_idtfile +{ + my ($idtfile, $languagefile, $onelanguage) = @_; + + for ( my $i = 0; $i <= $#{$idtfile}; $i++ ) + { + my @allstrings = (); + + my $oneline = ${$idtfile}[$i]; + + while ( $oneline =~ /\b(OOO_\w+)\b/ ) + { + my $replacestring = $1; + push(@allstrings, $replacestring); + $oneline =~ s/$replacestring//; + } + + my $oldstring; + + foreach $oldstring (@allstrings) + { + my $language_block = get_language_block_from_language_file($oldstring, $languagefile); + my $newstring = get_language_string_from_language_block($language_block, $onelanguage, $oldstring); + + # if (!( $newstring eq "" )) { ${$idtfile}[$i] =~ s/$oldstring/$newstring/; } + ${$idtfile}[$i] =~ s/$oldstring/$newstring/; # always substitute, even if $newstring eq "" (there are empty strings for control.idt) + } + } +} + +############################################################## +# Copying all needed files to create a msi database +# into one language specific directory +############################################################## + +sub prepare_language_idt_directory +{ + my ($destinationdir, $newidtdir, $onelanguage, $filesref, $iconfilecollector, $binarytablefiles, $allvariables) = @_; + + # Copying all idt-files from the source $installer::globals::idttemplatepath to the destination $destinationdir + # Copying all files in the subdirectory "Binary" + # Copying all files in the subdirectory "Icon" + + my $infoline = ""; + + installer::systemactions::copy_directory($installer::globals::idttemplatepath, $destinationdir); + + if ( -d $installer::globals::idttemplatepath . $installer::globals::separator . "Binary") + { + installer::systemactions::create_directory($destinationdir . $installer::globals::separator . "Binary"); + installer::systemactions::copy_directory($installer::globals::idttemplatepath . $installer::globals::separator . "Binary", $destinationdir . $installer::globals::separator . "Binary"); + + if (( $installer::globals::patch ) && ( $allvariables->{'WINDOWSPATCHBITMAPDIRECTORY'} )) + { + my $newsourcedir = $installer::globals::unpackpath . $installer::globals::separator . $allvariables->{'WINDOWSPATCHBITMAPDIRECTORY'}; # path setting in list file dependent from unpackpath !? + $infoline = "\nOverwriting files in directory \"" . $destinationdir . $installer::globals::separator . "Binary" . "\" with files from directory \"" . $newsourcedir . "\".\n"; + push( @installer::globals::logfileinfo, $infoline); + if ( ! -d $newsourcedir ) + { + my $currentdir = cwd(); + installer::exiter::exit_program("ERROR: Directory $newsourcedir does not exist! Current directory is: $currentdir", "prepare_language_idt_directory"); + } + installer::systemactions::copy_directory($newsourcedir, $destinationdir . $installer::globals::separator . "Binary"); + } + } + + installer::systemactions::create_directory($destinationdir . $installer::globals::separator . "Icon"); + + if ( -d $installer::globals::idttemplatepath . $installer::globals::separator . "Icon") + { + installer::systemactions::copy_directory($installer::globals::idttemplatepath . $installer::globals::separator . "Icon", $destinationdir . $installer::globals::separator . "Icon"); + } + + # Copying all files in $iconfilecollector, that describe icons of folderitems + + for ( my $i = 0; $i <= $#{$iconfilecollector}; $i++ ) + { + my $iconfilename = ${$iconfilecollector}[$i]; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$iconfilename); + installer::systemactions::copy_one_file(${$iconfilecollector}[$i], $destinationdir . $installer::globals::separator . "Icon" . $installer::globals::separator . $iconfilename); + } + + # Copying all files in $binarytablefiles in the binary directory + + for ( my $i = 0; $i <= $#{$binarytablefiles}; $i++ ) + { + my $binaryfile = ${$binarytablefiles}[$i]; + my $binaryfilepath = $binaryfile->{'sourcepath'}; + my $binaryfilename = $binaryfilepath; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$binaryfilename); + installer::systemactions::copy_one_file($binaryfilepath, $destinationdir . $installer::globals::separator . "Binary" . $installer::globals::separator . $binaryfilename); + } + + # Copying all new created and language independent idt-files to the destination $destinationdir. + # Example: "File.idt" + + installer::systemactions::copy_directory_with_fileextension($newidtdir, $destinationdir, "idt"); + + # Copying all new created and language dependent idt-files to the destination $destinationdir. + # Example: "Feature.idt.01" + + installer::systemactions::copy_directory_with_fileextension($newidtdir, $destinationdir, $onelanguage); + installer::systemactions::rename_files_with_fileextension($destinationdir, $onelanguage); + +} + +############################################################## +# Returning the source path of the rtf licensefile for +# a specified language +############################################################## + +sub get_rtflicensefilesource +{ + my ($language, $includepatharrayref) = @_; + + my $licensefilename = "license_" . $language . ".rtf"; + + my $sourcefileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$licensefilename, $includepatharrayref, 1); + + if ($$sourcefileref eq "") { installer::exiter::exit_program("ERROR: Could not find $licensefilename!", "get_rtflicensefilesource"); } + + my $infoline = "Using licensefile: $$sourcefileref\n"; + push( @installer::globals::logfileinfo, $infoline); + + return $$sourcefileref; +} + +############################################################## +# Returning the source path of the licensefile for +# a specified language +############################################################## + +sub get_licensefilesource +{ + my ($language, $filesref) = @_; + + my $licensefilename = "license_" . $language . ".txt"; + my $sourcepath = ""; + my $foundlicensefile = 0; + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + my $filename = $onefile->{'Name'}; + + if ($filename eq $licensefilename) + { + $sourcepath = $onefile->{'sourcepath'}; + $foundlicensefile = 1; + last; + } + } + + if ( ! $foundlicensefile ) { installer::exiter::exit_program("ERROR: Did not find file $licensefilename in file collector!", "get_licensefilesource"); } + + return $sourcepath; +} + +############################################################## +# A simple converter to create the license text +# in rtf format +############################################################## + +sub get_rtf_licensetext +{ + my ($licensefile) = @_; + + # A very simple rtf converter + + # The static header + + my $rtf_licensetext = '{\rtf1\ansi\deff0'; + $rtf_licensetext = $rtf_licensetext . '{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}}'; + $rtf_licensetext = $rtf_licensetext . '{\colortbl\red0\green0\blue0;\red255\green255\blue255;\red128\green128\blue128;}'; + $rtf_licensetext = $rtf_licensetext . '{\stylesheet{\s1\snext1 Standard;}}'; + $rtf_licensetext = $rtf_licensetext . '{\info{\comment StarWriter}{\vern5690}}\deftab709'; + $rtf_licensetext = $rtf_licensetext . '{\*\pgdsctbl'; + $rtf_licensetext = $rtf_licensetext . '{\pgdsc0\pgdscuse195\pgwsxn11905\pghsxn16837\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\pgdscnxt0 Standard;}}'; + $rtf_licensetext = $rtf_licensetext . '\paperh16837\paperw11905\margl1134\margr1134\margt1134\margb1134\sectd\sbknone\pgwsxn11905\pghsxn16837\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc'; + $rtf_licensetext = $rtf_licensetext . '\pard\plain \s1'; + + for ( my $i = 0; $i <= $#{$licensefile}; $i++ ) + { + my $oneline = ${$licensefile}[$i]; + # if ( $oneline =~ /^\s*$/ ) { $oneline = '\par'; } # empty lines + + if ( $i == 0 ) { $oneline =~ s/^\W*//; } + + $oneline =~ s/\t/ /g; # no tabs allowed, converting to four spaces + $oneline =~ s/\n$//g; # no newline at line end + +# $oneline =~ s/ä/\\\'e4/g; # converting "ä" +# $oneline =~ s/ö/\\\'f6/g; # converting "ö" +# $oneline =~ s/ü/\\\'fc/g; # converting "ü" +# $oneline =~ s/ß/\\\'df/g; # converting "ß" + + # german replacements + + $oneline =~ s/\Ã\„/\\\'c4/g; # converting "Ä" + $oneline =~ s/\Ã\–/\\\'d6/g; # converting "Ö" + $oneline =~ s/\Ã\œ/\\\'dc/g; # converting "Ü" + $oneline =~ s/\Ã\¤/\\\'e4/g; # converting "ä" + $oneline =~ s/\Ã\¶/\\\'f6/g; # converting "ö" + $oneline =~ s/\Ã\¼/\\\'fc/g; # converting "ü" + $oneline =~ s/\Ã\Ÿ/\\\'df/g; # converting "ß" + + # french replacements + + $oneline =~ s/\Ã\‰/\\\'c9/g; + $oneline =~ s/\Ã\€/\\\'c0/g; + $oneline =~ s/\Â\«/\\\'ab/g; + $oneline =~ s/\Â\»/\\\'bb/g; + $oneline =~ s/\Ã\©/\\\'e9/g; + $oneline =~ s/\Ã\¨/\\\'e8/g; + $oneline =~ s/\Ã\ /\\\'e0/g; + $oneline =~ s/\Ã\´/\\\'f4/g; + $oneline =~ s/\Ã\§/\\\'e7/g; + $oneline =~ s/\Ã\ª/\\\'ea/g; + $oneline =~ s/\Ã\Š/\\\'ca/g; + $oneline =~ s/\Ã\»/\\\'fb/g; + $oneline =~ s/\Ã\¹/\\\'f9/g; + $oneline =~ s/\Ã\®/\\\'ee/g; + + # quotation marks + + $oneline =~ s/\â\€\ž/\\\'84/g; + $oneline =~ s/\â\€\œ/\\ldblquote/g; + $oneline =~ s/\â\€\™/\\rquote/g; + + + $oneline =~ s/\Â\ /\\\~/g; + + $oneline = '\par ' . $oneline; + + $rtf_licensetext = $rtf_licensetext . $oneline; + } + + # and the end + + $rtf_licensetext = $rtf_licensetext . '\par \par }'; + + return $rtf_licensetext; +} + +############################################################## +# A simple converter to create a license txt string from +# the rtf format +############################################################## + +sub make_string_licensetext +{ + my ($licensefile) = @_; + + my $rtf_licensetext = ""; + + for ( my $i = 0; $i <= $#{$licensefile}; $i++ ) + { + my $oneline = ${$licensefile}[$i]; + $oneline =~ s/\s*$//g; # no whitespace at line end + + $rtf_licensetext = $rtf_licensetext . $oneline . " "; + } + + return $rtf_licensetext; +} + +############################################################## +# Setting the path, where the soffice.exe is installed, into +# the CustomAction table +############################################################## + +sub add_officedir_to_database +{ + my ($basedir, $allvariables) = @_; + + my $customactionfilename = $basedir . $installer::globals::separator . "CustomAc.idt"; + + my $customacfile = installer::files::read_file($customactionfilename); + + my $found = 0; + + # Updating the values + + if ( $installer::globals::officeinstalldirectoryset ) + { + $found = 0; + + for ( my $i = 0; $i <= $#{$customacfile}; $i++ ) + { + if ( ${$customacfile}[$i] =~ /\bOFFICEDIRECTORYGID\b/ ) + { + ${$customacfile}[$i] =~ s/\bOFFICEDIRECTORYGID\b/$installer::globals::officeinstalldirectory/; + $found = 1; + } + } + + if (( ! $found ) && ( ! $allvariables->{'IGNOREDIRECTORYLAYER'} )) + { + installer::exiter::exit_program("ERROR: \"OFFICEDIRECTORYGID\" not found in \"$customactionfilename\" !", "add_officedir_to_database"); + } + } + + if ( $installer::globals::basisinstalldirectoryset ) + { + $found = 0; + + for ( my $i = 0; $i <= $#{$customacfile}; $i++ ) + { + if ( ${$customacfile}[$i] =~ /\bBASISDIRECTORYGID\b/ ) + { + ${$customacfile}[$i] =~ s/\bBASISDIRECTORYGID\b/$installer::globals::basisinstalldirectory/; + $found = 1; + } + } + + if (( ! $found ) && ( ! $allvariables->{'IGNOREDIRECTORYLAYER'} )) + { + installer::exiter::exit_program("ERROR: \"BASISDIRECTORYGID\" not found in \"$customactionfilename\" !", "add_officedir_to_database"); + } + } + + if ( $installer::globals::ureinstalldirectoryset ) + { + $found = 0; + + for ( my $i = 0; $i <= $#{$customacfile}; $i++ ) + { + if ( ${$customacfile}[$i] =~ /\bUREDIRECTORYGID\b/ ) + { + ${$customacfile}[$i] =~ s/\bUREDIRECTORYGID\b/$installer::globals::ureinstalldirectory/; + $found = 1; + } + } + + if (( ! $found ) && ( ! $allvariables->{'IGNOREDIRECTORYLAYER'} )) + { + installer::exiter::exit_program("ERROR: \"UREDIRECTORYGID\" not found in \"$customactionfilename\" !", "add_officedir_to_database"); + } + } + + # Saving the file + + installer::files::save_file($customactionfilename ,$customacfile); + my $infoline = "Updated idt file: $customactionfilename\n"; + push(@installer::globals::logfileinfo, $infoline); + +} + +############################################################## +# Including the license text into the table control.idt +############################################################## + +sub add_licensefile_to_database +{ + my ($licensefile, $controltable) = @_; + + # Nine tabs before the license text and two tabs after it + # The license text has to be included into the dialog + # LicenseAgreement into the control Memo. + + my $foundlicenseline = 0; + my ($number, $line); + + for ( my $i = 0; $i <= $#{$controltable}; $i++ ) + { + $line = ${$controltable}[$i]; + + if ( $line =~ /^\s*\bLicenseAgreement\b\t\bMemo\t/ ) + { + $foundlicenseline = 1; + $number = $i; + last; + } + } + + if (!($foundlicenseline)) + { + installer::exiter::exit_program("ERROR: Line for license file in Control.idt not found!", "add_licensefile_to_database"); + } + else + { + my %control = (); + + if ( $line =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) + { + $control{'Dialog_'} = $1; + $control{'Control'} = $2; + $control{'Type'} = $3; + $control{'X'} = $4; + $control{'Y'} = $5; + $control{'Width'} = $6; + $control{'Height'} = $7; + $control{'Attributes'} = $8; + $control{'Property'} = $9; + $control{'Text'} = $10; + $control{'Control_Next'} = $11; + $control{'Help'} = $12; + } + else + { + installer::exiter::exit_program("ERROR: Could not split line correctly!", "add_licensefile_to_database"); + } + + # my $licensetext = get_rtf_licensetext($licensefile); + my $licensetext = make_string_licensetext($licensefile); + + $control{'Text'} = $licensetext; + + my $newline = $control{'Dialog_'} . "\t" . $control{'Control'} . "\t" . $control{'Type'} . "\t" . + $control{'X'} . "\t" . $control{'Y'} . "\t" . $control{'Width'} . "\t" . + $control{'Height'} . "\t" . $control{'Attributes'} . "\t" . $control{'Property'} . "\t" . + $control{'Text'} . "\t" . $control{'Control_Next'} . "\t" . $control{'Help'} . "\n"; + + ${$controltable}[$number] = $newline + } +} + +################################################################################################ +# Including the checkboxes for the language selection dialog +# into the table control.idt . This is only relevant for +# multilingual installation sets. +# +# old: +# LanguageSelection CheckBox1 CheckBox 22 60 15 24 3 IS1033 CheckBox2 +# LanguageSelection Text1 Text 40 60 70 15 65539 OOO_CONTROL_LANG_1033 +# LanguageSelection CheckBox2 CheckBox 22 90 15 24 3 IS1031 Next +# LanguageSelection Text2 Text 40 90 70 15 65539 OOO_CONTROL_LANG_1031 +# new: +# LanguageSelection CheckBox1 CheckBox 22 60 15 24 3 IS1033 Text CheckBox2 +# LanguageSelection CheckBox2 CheckBox 22 90 15 24 3 IS1031 Text Next +################################################################################################ + +sub add_language_checkboxes_to_database +{ + my ($controltable, $languagesarrayref) = @_; + + # for each language, two lines have to be inserted + + for ( my $i = 0; $i <= $#{$languagesarrayref}; $i++ ) + { + my $last = 0; + if ( $i == $#{$languagesarrayref} ) { $last = 1; } # special handling for the last + + my $onelanguage = ${$languagesarrayref}[$i]; + my $windowslanguage = installer::windows::language::get_windows_language($onelanguage); + + # my $is_english = 0; + # if ( $windowslanguage eq "1033" ) { $is_english = 1; } + + my $checkboxattribute = "3"; + # if ( $is_english ) { $checkboxattribute = "1"; } # english is not deselectable + + my $count = $i + 1; + my $nextcount = $i + 2; + my $checkboxcount = "CheckBox" . $count; + + my $multiplier = 20; + my $offset = 60; + if ( $#{$languagesarrayref} > 7 ) + { + $multiplier = 15; # smaller differences for more than 7 languages + $offset = 50; # smaller offset for more than 7 languages + } + + my $yvalue = $offset + $i * $multiplier; + + my $property = "IS" . $windowslanguage; + # if ( ! exists($installer::globals::languageproperties{$property}) ) { installer::exiter::exit_program("ERROR: Could not find property \"$property\" in the list of language properties!", "add_language_checkboxes_to_database"); } + + my $controlnext = ""; + if ( $last ) { $controlnext = "Next"; } + else { $controlnext = "CheckBox" . $nextcount; } + + my $stringname = "OOO_CONTROL_LANG_" . $windowslanguage; + + my $line1 = "LanguageSelection" . "\t" . $checkboxcount . "\t" . "CheckBox" . "\t" . + "22" . "\t" . $yvalue . "\t" . "200" . "\t" . "15" . "\t" . $checkboxattribute . "\t" . + $property . "\t" . $stringname . "\t" . $controlnext . "\t" . "\n"; + + push(@{$controltable}, $line1); + + # my $textcount = "Text" . $count; + # my $stringname = "OOO_CONTROL_LANG_" . $windowslanguage; + # + # $yvalue = $yvalue + 2; # text 2 pixel lower than checkbox + # + # my $line2 = "LanguageSelection" . "\t" . $textcount . "\t" . "Text" . "\t" . + # "40" . "\t" . $yvalue . "\t" . "70" . "\t" . "15" . "\t" . "65539" . "\t" . + # "\t" . $stringname . "\t" . "\t" . "\n"; + # + # push(@{$controltable}, $line2); + } +} + +################################################################### +# Determining the last position in a sequencetable +# into the tables CustomAc.idt and InstallE.idt. +################################################################### + +sub get_last_position_in_sequencetable +{ + my ($sequencetable) = @_; + + my $position = 0; + + for ( my $i = 0; $i <= $#{$sequencetable}; $i++ ) + { + my $line = ${$sequencetable}[$i]; + + if ( $line =~ /^\s*\w+\t.*\t\s*(\d+)\s$/ ) + { + my $newposition = $1; + if ( $newposition > $position ) { $position = $newposition; } + } + } + + return $position; +} + +######################################################################### +# Determining the position of a specified Action in the sequencetable +######################################################################### + +sub get_position_in_sequencetable +{ + my ($action, $sequencetable) = @_; + + my $position = 0; + + $action =~ s/^\s*behind_//; + + for ( my $i = 0; $i <= $#{$sequencetable}; $i++ ) + { + my $line = ${$sequencetable}[$i]; + + if ( $line =~ /^\s*(\w+)\t.*\t\s*(\d+)\s$/ ) + { + my $compareaction = $1; + $position = $2; + if ( $compareaction eq $action ) { last; } + } + } + + return $position; +} + +################################################################################################ +# Including the CustomAction for the configuration +# into the tables CustomAc.idt and InstallE.idt. +# +# CustomAc.idt: ExecutePkgchk 82 pkgchk.exe -s +# InstallE.idt: ExecutePkgchk Not REMOVE="ALL" 3175 +# +# CustomAc.idt: ExecuteQuickstart 82 install_quickstart.exe +# InstallE.idt: ExecuteQuickstart &gm_o_Quickstart=3 3200 +# +# CustomAc.idt: ExecuteInstallRegsvrex 82 regsvrex.exe shlxthdl.dll +# InstallE.idt: ExecuteInstallRegsvrex Not REMOVE="ALL" 3225 +# +# CustomAc.idt: ExecuteUninstallRegsvrex 82 regsvrex.exe /u shlxthdl.dll +# InstallE.idt: ExecuteUninstallRegsvrex REMOVE="ALL" 690 +# +# CustomAc.idt: Regmsdocmsidll1 1 reg4msdocmsidll Reg4MsDocEntry +# InstallU.idt: Regmsdocmsidll1 Not REMOVE="ALL" 610 +# +# CustomAc.idt: Regmsdocmsidll2 1 reg4msdocmsidll Reg4MsDocEntry +# InstallE.idt: Regmsdocmsidll2 Not REMOVE="ALL" 3160 +################################################################################################ + +sub set_custom_action +{ + my ($customactionidttable, $actionname, $actionflags, $exefilename, $actionparameter, $inbinarytable, $filesref, $customactionidttablename, $styles) = @_; + + my $included_customaction = 0; + my $infoline = ""; + my $customaction_exefilename = $exefilename; + my $uniquename = ""; + + # when the style NO_FILE is set, no searching for the file is needed, no filtering is done, we can add that custom action + if ( $styles =~ /\bNO_FILE\b/ ) + { + my $line = $actionname . "\t" . $actionflags . "\t" . $customaction_exefilename . "\t" . $actionparameter . "\n"; + push(@{$customactionidttable}, $line); + + $infoline = "Added $actionname CustomAction into table $customactionidttablename (NO_FILE has been set)\n"; + push(@installer::globals::logfileinfo, $infoline); + + $included_customaction = 1; + return $included_customaction; + } + + # is the $exefilename a library that is included into the binary table + + if ( $inbinarytable ) { $customaction_exefilename =~ s/\.//; } # this is the entry in the binary table ("abc.dll" -> "abcdll") + + # is the $exefilename included into the product? + + my $contains_file = 0; + + # All files are located in $filesref and in @installer::globals::binarytableonlyfiles. + # Both must be added together + my $localfilesref = installer::converter::combine_arrays_from_references(\@installer::globals::binarytableonlyfiles, $filesref); + + for ( my $i = 0; $i <= $#{$localfilesref}; $i++ ) + { + my $onefile = ${$localfilesref}[$i]; + my $filename = ""; + if ( exists($onefile->{'Name'}) ) + { + $filename = $onefile->{'Name'}; + + if ( $filename eq $exefilename ) + { + $contains_file = 1; + $uniquename = ${$localfilesref}[$i]->{'uniquename'}; + last; + } + } + else + { + installer::exiter::exit_program("ERROR: Did not find \"Name\" for file \"$onefile->{'uniquename'}\" ($onefile->{'gid'})!", "set_custom_action"); + } + } + + if ( $contains_file ) + { + # Now the CustomAction can be included into the CustomAc.idt + + if ( ! $inbinarytable ) { $customaction_exefilename = $uniquename; } # the unique file name has to be added to the custom action table + + my $line = $actionname . "\t" . $actionflags . "\t" . $customaction_exefilename . "\t" . $actionparameter . "\n"; + push(@{$customactionidttable}, $line); + + $included_customaction = 1; + } + + if ( $included_customaction ) { $infoline = "Added $actionname CustomAction into table $customactionidttablename\n"; } + else { $infoline = "Did not add $actionname CustomAction into table $customactionidttablename\n"; } + push(@installer::globals::logfileinfo, $infoline); + + return $included_customaction; +} + +#################################################################### +# Adding a Custom Action to InstallExecuteTable or InstallUITable +#################################################################### + +sub add_custom_action_to_install_table +{ + my ($installtable, $exefilename, $actionname, $actioncondition, $position, $filesref, $installtablename, $styles) = @_; + + my $included_customaction = 0; + my $feature = ""; + my $infoline = ""; + + # when the style NO_FILE is set, no searching for the file is needed, no filtering is done, we can add that custom action + if ( $styles =~ /\bNO_FILE\b/ ) + { + # then the InstallE.idt.idt or InstallU.idt.idt + $actioncondition =~ s/FEATURETEMPLATE/$feature/g; # only execute Custom Action, if feature of the file is installed + + my $actionposition = 0; + + if ( $position eq "end" ) { $actionposition = get_last_position_in_sequencetable($installtable) + 25; } + elsif ( $position =~ /^\s*behind_/ ) { $actionposition = get_position_in_sequencetable($position, $installtable) + 2; } + else { $actionposition = get_position_in_sequencetable($position, $installtable) - 2; } + + my $line = $actionname . "\t" . $actioncondition . "\t" . $actionposition . "\n"; + push(@{$installtable}, $line); + + $infoline = "Added $actionname CustomAction into table $customactionidttablename (NO_FILE has been set)\n"; + push(@installer::globals::logfileinfo, $infoline); + return; + } + + my $contains_file = 0; + + # All files are located in $filesref and in @installer::globals::binarytableonlyfiles. + # Both must be added together + my $localfilesref = installer::converter::combine_arrays_from_references(\@installer::globals::binarytableonlyfiles, $filesref); + + for ( my $i = 0; $i <= $#{$localfilesref}; $i++ ) + { + my $filename = ${$localfilesref}[$i]->{'Name'}; + + if ( $filename eq $exefilename ) + { + $contains_file = 1; + + # Determining the feature of the file + + if ( ${$localfilesref}[$i] ) { $feature = ${$localfilesref}[$i]->{'modules'}; } + + # If modules contains a list of modules, only taking the first one. + if ( $feature =~ /^\s*(.*?)\,/ ) { $feature = $1; } + # Attention: Maximum feature length is 38! + shorten_feature_gid(\$feature); + + last; + } + } + + if ( $contains_file ) + { + # then the InstallE.idt.idt or InstallU.idt.idt + + $actioncondition =~ s/FEATURETEMPLATE/$feature/g; # only execute Custom Action, if feature of the file is installed + +# my $actionposition = 0; +# if ( $position eq "end" ) { $actionposition = get_last_position_in_sequencetable($installtable) + 25; } +# elsif ( $position =~ /^\s*behind_/ ) { $actionposition = get_position_in_sequencetable($position, $installtable) + 2; } +# else { $actionposition = get_position_in_sequencetable($position, $installtable) - 2; } +# my $line = $actionname . "\t" . $actioncondition . "\t" . $actionposition . "\n"; + + my $positiontemplate = ""; + if ( $position =~ /^\s*\d+\s*$/ ) { $positiontemplate = $position; } # setting the position directly, number defined in scp2 + else { $positiontemplate = "POSITIONTEMPLATE_" . $position; } + + my $line = $actionname . "\t" . $actioncondition . "\t" . $positiontemplate . "\n"; + push(@{$installtable}, $line); + + $included_customaction = 1; + } + + if ( $included_customaction ) { $infoline = "Added $actionname CustomAction into table $installtablename\n"; } + else { $infoline = "Did not add $actionname CustomAction into table $installtablename\n"; } + push(@installer::globals::logfileinfo, $infoline); + +} + +################################################################## +# A line in the table ControlEvent connects a Control +# with a Custom Action +################################################################# + +sub connect_custom_action_to_control +{ + my ( $table, $tablename, $dialog, $control, $event, $argument, $condition, $ordering) = @_; + + my $line = $dialog . "\t" . $control. "\t" . $event. "\t" . $argument. "\t" . $condition. "\t" . $ordering . "\n"; + + push(@{$table}, $line); + + $line =~ s/\s*$//g; + + $infoline = "Added line \"$line\" into table $tablename\n"; + push(@installer::globals::logfileinfo, $infoline); +} + +################################################################## +# A line in the table ControlCondition connects a Control state +# with a condition +################################################################## + +sub connect_condition_to_control +{ + my ( $table, $tablename, $dialog, $control, $event, $condition) = @_; + + my $line = $dialog . "\t" . $control. "\t" . $event. "\t" . $condition. "\n"; + + push(@{$table}, $line); + + $line =~ s/\s*$//g; + + $infoline = "Added line \"$line\" into table $tablename\n"; + push(@installer::globals::logfileinfo, $infoline); +} + +################################################################## +# Searching for a sequencenumber in InstallUISequence table +# "ExecuteAction" must be the last action +################################################################## + +sub get_free_number_in_uisequence_table +{ + my ( $installuitable ) = @_; + + # determining the sequence of "ExecuteAction" + + my $executeactionnumber = 0; + + for ( my $i = 0; $i <= $#{$installuitable}; $i++ ) + { + if ( ${$installuitable}[$i] =~ /^\s*(\w+)\t\w*\t(\d+)\s*$/ ) + { + my $actionname = $1; + my $actionnumber = $2; + + if ( $actionname eq "ExecuteAction" ) + { + $executeactionnumber = $actionnumber; + last; + } + } + } + + if ( $executeactionnumber == 0 ) { installer::exiter::exit_program("ERROR: Did not find \"ExecuteAction\" in InstallUISequence table!", "get_free_number_in_uisequence_table"); } + + # determining the sequence of the action before "ExecuteAction" + + my $lastactionnumber = 0; + + for ( my $i = 0; $i <= $#{$installuitable}; $i++ ) + { + if ( ${$installuitable}[$i] =~ /^\s*\w+\t\w*\t(\d+)\s*$/ ) + { + my $actionnumber = $1; + + if (( $actionnumber > $lastactionnumber ) && ( $actionnumber != $executeactionnumber )) + { + $lastactionnumber = $actionnumber; + } + } + } + + # the new number can now be calculated + + my $newnumber = 0; + + if ((( $lastactionnumber + $executeactionnumber ) % 2 ) == 0 ) { $newnumber = ( $lastactionnumber + $executeactionnumber ) / 2; } + else { $newnumber = ( $lastactionnumber + $executeactionnumber -1 ) / 2; } + + return $newnumber; +} + +################################################################## +# Searching for a specified string in the feature table +################################################################## + +sub get_feature_name +{ + my ( $string, $featuretable ) = @_; + + my $featurename = ""; + + for ( my $i = 0; $i <= $#{$featuretable}; $i++ ) + { + if ( ${$featuretable}[$i] =~ /^\s*(\w+$string)\t/ ) + { + $featurename = $1; + last; + } + } + + return $featurename; +} + +###################################################################### +# Returning the toplevel directory name of one specific file +###################################################################### + +sub get_directory_name_from_file +{ + my ($onefile) = @_; + + my $destination = $onefile->{'destination'}; + my $name = $onefile->{'Name'}; + + $destination =~ s/\Q$name\E\s*$//; + $destination =~ s/\Q$installer::globals::separator\E\s*$//; + + my $path = ""; + + if ( $destination =~ /\Q$installer::globals::separator\E/ ) + { + if ( $destination =~ /^\s*(\S.*\S\Q$installer::globals::separator\E)(\S.+\S?)/ ) + { + $path = $2; + } + } + else + { + $path = $destination; + } + + return $path; +} + +############################################################# +# Including the new subdir into the directory table +############################################################# + +sub include_subdirname_into_directory_table +{ + my ($dirname, $directorytable, $directorytablename, $onefile) = @_; + + my $subdir = ""; + if ( $onefile->{'Subdir'} ) { $subdir = $onefile->{'Subdir'}; } + if ( $subdir eq "" ) { installer::exiter::exit_program("ERROR: No \"Subdir\" defined for $onefile->{'Name'}", "include_subdirname_into_directory_table"); } + + # program INSTALLLOCATION program -> subjava INSTALLLOCATION program:java + + my $uniquename = ""; + my $parent = ""; + my $name = ""; + + my $includedline = 0; + + my $newdir = ""; + + for ( my $i = 0; $i <= $#{$directorytable}; $i++ ) + { + + if ( ${$directorytable}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\s*$/ ) + { + $uniquename = $1; + $parent = $2; + $name = $3; + + if ( $dirname eq $name ) + { + my $newuniquename = "sub" . $subdir; + $newdir = $newuniquename; + my $newparent = $parent; + my $newname = $name . "\:" . $subdir; + my $newline = + $line = "$newuniquename\t$newparent\t$newname\n"; + push(@{$directorytable}, $line); + installer::remover::remove_leading_and_ending_whitespaces(\$line); + $infoline = "Added $line into directory table $directorytablename\n"; + push(@installer::globals::logfileinfo, $infoline); + + $includedline = 1; + last; + } + } + } + + if ( ! $includedline ) { installer::exiter::exit_program("ERROR: Could not include new subdirectory into directory table for file $onefile->{'Name'}!", "include_subdirname_into_directory_table"); } + + return $newdir; +} + +################################################################## +# Including the new sub directory into the component table +################################################################## + +sub include_subdir_into_componenttable +{ + my ($subdir, $onefile, $componenttable) = @_; + + my $componentname = $onefile->{'componentname'}; + + my $changeddirectory = 0; + + for ( my $i = 0; $i <= $#{$componenttable}; $i++ ) + { + if ( ${$componenttable}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) + { + my $localcomponentname = $1; + my $directory = $3; + + if ( $componentname eq $localcomponentname ) + { + my $oldvalue = ${$componenttable}[$i]; + ${$componenttable}[$i] =~ s/\b\Q$directory\E\b/$subdir/; + my $newvalue = ${$componenttable}[$i]; + + installer::remover::remove_leading_and_ending_whitespaces(\$oldvalue); + installer::remover::remove_leading_and_ending_whitespaces(\$newvalue); + $infoline = "Change in Component table: From \"$oldvalue\" to \"$newvalue\"\n"; + push(@installer::globals::logfileinfo, $infoline); + + $changeddirectory = 1; + last; + } + } + } + + if ( ! $changeddirectory ) { installer::exiter::exit_program("ERROR: Could not change directory for component: $onefile->{'Name'}!", "include_subdir_into_componenttable"); } + +} + +################################################################################################ +# Including the content for the child installations +# into the tables: +# CustomAc.idt, InstallU.idt, Feature.idt +################################################################################################ + +sub add_childprojects +{ + my ($languageidtdir, $filesref, $allvariables) = @_; + + my $customactiontablename = $languageidtdir . $installer::globals::separator . "CustomAc.idt"; + my $customactiontable = installer::files::read_file($customactiontablename); + my $installuitablename = $languageidtdir . $installer::globals::separator . "InstallU.idt"; + my $installuitable = installer::files::read_file($installuitablename); + my $featuretablename = $languageidtdir . $installer::globals::separator . "Feature.idt"; + my $featuretable = installer::files::read_file($featuretablename); + my $directorytablename = $languageidtdir . $installer::globals::separator . "Director.idt"; + my $directorytable = installer::files::read_file($directorytablename); + my $componenttablename = $languageidtdir . $installer::globals::separator . "Componen.idt"; + my $componenttable = installer::files::read_file($componenttablename); + + my $infoline = ""; + my $line = ""; + + $installer::globals::javafile = installer::worker::return_first_item_with_special_flag($filesref ,"JAVAFILE"); + $installer::globals::urefile = installer::worker::return_first_item_with_special_flag($filesref ,"UREFILE"); + + if (( $installer::globals::javafile eq "" ) && ( $allvariables->{'JAVAPRODUCT'} )) { installer::exiter::exit_program("ERROR: No JAVAFILE found in files collector!", "add_childprojects"); } + if (( $installer::globals::urefile eq "" ) && ( $allvariables->{'UREPRODUCT'} )) { installer::exiter::exit_program("ERROR: No UREFILE found in files collector!", "add_childprojects"); } + + # Content for Directory table + # SystemFolder TARGETDIR . + + my $contains_systemfolder = 0; + + for ( my $i = 0; $i <= $#{$directorytable}; $i++ ) + { + if ( ${$directorytable}[$i] =~ /^\s*SystemFolder\t/ ) + { + $contains_systemfolder = 1; + last; + } + } + + if ( ! $contains_systemfolder ) + { + $line = "SystemFolder\tTARGETDIR\t\.\n"; + push(@{$directorytable}, $line); + installer::remover::remove_leading_and_ending_whitespaces(\$line); + $infoline = "Added $line into table $directorytablename\n"; + } + else + { + $infoline = "SystemFolder already exists in table $directorytablename\n"; + } + + push(@installer::globals::logfileinfo, $infoline); + + # Additional content for the directory table + # subjava INSTALLLOCATION program:java + # subure INSTALLLOCATION program:ure + + my $dirname = ""; + my $subjavadir = ""; + my $suburedir = ""; + + if ( $allvariables->{'JAVAPRODUCT'} ) + { + $dirname = get_directory_name_from_file($installer::globals::javafile); + $subjavadir = include_subdirname_into_directory_table($dirname, $directorytable, $directorytablename, $installer::globals::javafile); + } + + if ( $allvariables->{'UREPRODUCT'} ) + { + $dirname = get_directory_name_from_file($installer::globals::urefile); + $suburedir = include_subdirname_into_directory_table($dirname, $directorytable, $directorytablename, $installer::globals::urefile); + } + + # Content for the Component table + # The Java and Ada components have new directories + + if ( $allvariables->{'JAVAPRODUCT'} ) { include_subdir_into_componenttable($subjavadir, $installer::globals::javafile, $componenttable); } + if ( $allvariables->{'UREPRODUCT'} ) { include_subdir_into_componenttable($suburedir, $installer::globals::urefile, $componenttable); } + + # Content for CustomAction table + + if ( $allvariables->{'JAVAPRODUCT'} ) + { + $line = "InstallJava\t98\tSystemFolder\t[SourceDir]$installer::globals::javafile->{'Subdir'}\\$installer::globals::javafile->{'Name'} \/qb REBOOT=Suppress SPONSORS=0 DISABLEAD=1\n"; + push(@{$customactiontable} ,$line); + installer::remover::remove_leading_and_ending_whitespaces(\$line); + $infoline = "Added $line into table $customactiontablename\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + if ( $allvariables->{'UREPRODUCT'} ) + { + $line = "InstallUre\t98\tSystemFolder\t$installer::globals::urefile->{'Subdir'}\\$installer::globals::urefile->{'Name'} /S\n"; + push(@{$customactiontable} ,$line); + installer::remover::remove_leading_and_ending_whitespaces(\$line); + $infoline = "Added $line into table $customactiontablename\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + if ( $allvariables->{'JAVAPRODUCT'} ) + { + $line = "MaintenanceJava\t82\t$installer::globals::javafile->{'uniquename'}\t\/qb REBOOT=Suppress SPONSORS=0 DISABLEAD=1\n"; + push(@{$customactiontable} ,$line); + installer::remover::remove_leading_and_ending_whitespaces(\$line); + $infoline = "Added $line into table $customactiontablename\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + if ( $allvariables->{'UREPRODUCT'} ) + { + $line = "MaintenanceUre\t82\t$installer::globals::urefile->{'uniquename'}\t\/S\n"; + push(@{$customactiontable} ,$line); + installer::remover::remove_leading_and_ending_whitespaces(\$line); + $infoline = "Added $line into table $customactiontablename\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + # Content for InstallUISequence table + # InstallAdabas &gm_o_Adabas=3 825 + # InstallJava &gm_o_Java=3 827 + + my $number = ""; + my $featurename = ""; + + if ( $allvariables->{'ADAPRODUCT'} ) + { + $number = get_free_number_in_uisequence_table($installuitable); + $featurename = get_feature_name("_Adabas", $featuretable); + $line = "InstallAdabas\t\&$featurename\=3 And Not Installed And Not PATCH\t$number\n"; + push(@{$installuitable} ,$line); + installer::remover::remove_leading_and_ending_whitespaces(\$line); + $infoline = "Added $line into table $installuitablename\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + if ( $allvariables->{'JAVAPRODUCT'} ) + { + $number = get_free_number_in_uisequence_table($installuitable) + 2; + $featurename = get_feature_name("_Java", $featuretable); + if ( $featurename ) { $line = "InstallJava\t\&$featurename\=3 And Not Installed And JAVAPATH\=\"\" And Not PATCH\t$number\n"; } + else { $line = "InstallJava\tNot Installed And JAVAPATH\=\"\" And Not PATCH\t$number\n"; } # feature belongs to root + push(@{$installuitable} ,$line); + installer::remover::remove_leading_and_ending_whitespaces(\$line); + $infoline = "Added $line into table $installuitablename\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + if ( $allvariables->{'ADAPRODUCT'} ) + { + $number = get_free_number_in_uisequence_table($installuitable) + 4; + $featurename = get_feature_name("_Adabas", $featuretable); + $line = "MaintenanceAdabas\t\&$featurename\=3 And Installed And Not PATCH\t$number\n"; + push(@{$installuitable} ,$line); + installer::remover::remove_leading_and_ending_whitespaces(\$line); + $infoline = "Added $line into table $installuitablename\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + if ( $allvariables->{'JAVAPRODUCT'} ) + { + $number = get_free_number_in_uisequence_table($installuitable) + 6; + $featurename = get_feature_name("_Java", $featuretable); + if ( $featurename ) { $line = "MaintenanceJava\t\&$featurename\=3 And Installed And JAVAPATH\=\"\" And Not PATCH\t$number\n"; } + else { $line = "MaintenanceJava\tInstalled And JAVAPATH\=\"\" And Not PATCH\t$number\n"; } # feature belongs to root + push(@{$installuitable} ,$line); + installer::remover::remove_leading_and_ending_whitespaces(\$line); + $infoline = "Added $line into table $installuitablename\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + if ( $allvariables->{'UREPRODUCT'} ) + { + $number = get_free_number_in_uisequence_table($installuitable) + 8; + $featurename = get_feature_name("_Ure", $featuretable); + if ( $featurename ) { $line = "InstallUre\t\&$featurename\=3 And Not Installed\t$number\n"; } + else { $line = "InstallUre\tNot Installed\t$number\n"; } # feature belongs to root + push(@{$installuitable} ,$line); + installer::remover::remove_leading_and_ending_whitespaces(\$line); + $infoline = "Added $line into table $installuitablename\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + if ( $allvariables->{'UREPRODUCT'} ) + { + $number = get_free_number_in_uisequence_table($installuitable) + 10; + $featurename = get_feature_name("_Ure", $featuretable); + if ( $featurename ) { $line = "MaintenanceUre\t\&$featurename\=3 And Installed\t$number\n"; } + else { $line = "MaintenanceUre\tInstalled\t$number\n"; } # feature belongs to root + push(@{$installuitable} ,$line); + installer::remover::remove_leading_and_ending_whitespaces(\$line); + $infoline = "Added $line into table $installuitablename\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + # Content for Feature table, better from scp (translation) + # gm_o_java gm_optional Java 1.4.2 Description 2 200 + + installer::files::save_file($customactiontablename, $customactiontable); + installer::files::save_file($installuitablename, $installuitable); + installer::files::save_file($featuretablename, $featuretable); + installer::files::save_file($directorytablename, $directorytable); + installer::files::save_file($componenttablename, $componenttable); +} + +################################################################## +# Setting the encoding in all idt files. Replacing the +# variable WINDOWSENCODINGTEMPLATE +################################################################## + +sub setencoding +{ + my ( $languageidtdir, $onelanguage ) = @_; + + my $encoding = installer::windows::language::get_windows_encoding($onelanguage); + + # collecting all idt files in the directory $languageidtdir and substituting the string + + my $idtfiles = installer::systemactions::find_file_with_file_extension("idt", $languageidtdir); + + for ( my $i = 0; $i <= $#{$idtfiles}; $i++ ) + { + my $onefilename = $languageidtdir . $installer::globals::separator . ${$idtfiles}[$i]; + my $onefile = installer::files::read_file($onefilename); + + for ( my $j = 0; $j <= $#{$onefile}; $j++ ) + { + ${$onefile}[$j] =~ s/WINDOWSENCODINGTEMPLATE/$encoding/g; + } + + installer::files::save_file($onefilename, $onefile); + } +} + +################################################################## +# Setting the condition, that at least one module is selected. +# All modules with flag SHOW_MULTILINGUAL_ONLY were already +# collected. In table ControlE.idt, the string +# LANGUAGECONDITIONINSTALL needs to be replaced. +# Also for APPLICATIONCONDITIONINSTALL for the applications +# with flag APPLICATIONMODULE. +################################################################## + +sub set_multilanguageonly_condition +{ + my ( $languageidtdir ) = @_; + + my $onefilename = $languageidtdir . $installer::globals::separator . "ControlE.idt"; + my $onefile = installer::files::read_file($onefilename); + + # Language modules + + my $condition = ""; + + foreach my $module ( sort keys %installer::globals::multilingual_only_modules ) + { + $condition = $condition . " &$module=3 Or"; + } + + $condition =~ s/^\s*//; + $condition =~ s/\s*Or\s*$//; # removing the ending "Or" + + if ( $condition eq "" ) { $condition = "1"; } + + for ( my $j = 0; $j <= $#{$onefile}; $j++ ) + { + ${$onefile}[$j] =~ s/LANGUAGECONDITIONINSTALL/$condition/; + } + + # Application modules + + $condition = ""; + + foreach my $module ( sort keys %installer::globals::application_modules ) + { + $condition = $condition . " &$module=3 Or"; + } + + $condition =~ s/^\s*//; + $condition =~ s/\s*Or\s*$//; # removing the ending "Or" + + if ( $condition eq "" ) { $condition = "1"; } + + for ( my $j = 0; $j <= $#{$onefile}; $j++ ) + { + ${$onefile}[$j] =~ s/APPLICATIONCONDITIONINSTALL/$condition/; + } + + installer::files::save_file($onefilename, $onefile); +} + +############################################# +# Putting array values into hash +############################################# + +sub fill_assignment_hash +{ + my ($gid, $name, $key, $assignmenthashref, $parameter, $tablename, $assignmentarray) = @_; + + my $max = $parameter - 1; + + if ( $max != $#{$assignmentarray} ) + { + my $definedparameter = $#{$assignmentarray} + 1; + installer::exiter::exit_program("ERROR: gid: $gid, key: $key ! Wrong parameter in scp. For table $tablename $parameter parameter are required ! You defined: $definedparameter", "fill_assignment_hash"); + } + + for ( my $i = 0; $i <= $#{$assignmentarray}; $i++ ) + { + my $counter = $i + 1; + my $key = "parameter". $counter; + + my $localvalue = ${$assignmentarray}[$i]; + installer::remover::remove_leading_and_ending_quotationmarks(\$localvalue); + $localvalue =~ s/\\\"/\"/g; + $localvalue =~ s/\\\!/\!/g; + $localvalue =~ s/\\\&/\&/g; + $localvalue =~ s/\\\</\</g; + $localvalue =~ s/\\\>/\>/g; + $assignmenthashref->{$key} = $localvalue; + } +} + +########################################################################## +# Checking the assignment of a Windows CustomAction and putting it +# into a hash +########################################################################## + +sub create_customaction_assignment_hash +{ + my ($gid, $name, $key, $assignmentarray) = @_; + + my %assignment = (); + my $assignmenthashref = \%assignment; + + my $tablename = ${$assignmentarray}[0]; + installer::remover::remove_leading_and_ending_quotationmarks(\$tablename); + + my $tablename_defined = 0; + my $parameter = 0; + + if ( $tablename eq "InstallUISequence" ) + { + $tablename_defined = 1; + $parameter = 3; + fill_assignment_hash($gid, $name, $key, $assignmenthashref, $parameter, $tablename, $assignmentarray); + } + + if ( $tablename eq "InstallExecuteSequence" ) + { + $tablename_defined = 1; + $parameter = 3; + fill_assignment_hash($gid, $name, $key, $assignmenthashref, $parameter, $tablename, $assignmentarray); + } + + if ( $tablename eq "AdminExecuteSequence" ) + { + $tablename_defined = 1; + $parameter = 3; + fill_assignment_hash($gid, $name, $key, $assignmenthashref, $parameter, $tablename, $assignmentarray); + } + + if ( $tablename eq "ControlEvent" ) + { + $tablename_defined = 1; + $parameter = 7; + fill_assignment_hash($gid, $name, $key, $assignmenthashref, $parameter, $tablename, $assignmentarray); + } + + if ( $tablename eq "ControlCondition" ) + { + $tablename_defined = 1; + $parameter = 5; + fill_assignment_hash($gid, $name, $key, $assignmenthashref, $parameter, $tablename, $assignmentarray); + } + + if ( ! $tablename_defined ) + { + installer::exiter::exit_program("ERROR: gid: $gid, key: $key ! Unknown Windows CustomAction table: $tablename ! Currently supported: InstallUISequence, InstallExecuteSequence, ControlEvent, ControlCondition", "create_customaction_assignment_hash"); + } + + return $assignmenthashref; +} + +########################################################################## +# Finding the position of a specified CustomAction. +# If the CustomAction is not found, the return value is "-1". +# If the CustomAction position is not defined yet, +# the return value is also "-1". +########################################################################## + +sub get_customaction_position +{ + my ($action, $sequencetable) = @_; + + my $position = -1; + + for ( my $i = 0; $i <= $#{$sequencetable}; $i++ ) + { + my $line = ${$sequencetable}[$i]; + + if ( $line =~ /^\s*(\w+)\t.*\t\s*(\d+)\s$/ ) # matching only, if position is a number! + { + my $compareaction = $1; + my $localposition = $2; + + if ( $compareaction eq $action ) + { + $position = $localposition; + last; + } + } + } + + return $position; +} + +########################################################################## +# Setting the position of CustomActions in sequence tables. +# Replacing all occurences of "POSITIONTEMPLATE_" +########################################################################## + +sub set_positions_in_table +{ + my ( $sequencetable, $tablename ) = @_; + + my $infoline = "\nSetting positions in table \"$tablename\".\n"; + push(@installer::globals::logfileinfo, $infoline); + + # Step 1: Resolving all occurences of "POSITIONTEMPLATE_end" + + my $lastposition = get_last_position_in_sequencetable($sequencetable); + + for ( my $i = 0; $i <= $#{$sequencetable}; $i++ ) + { + if ( ${$sequencetable}[$i] =~ /^\s*(\w+)\t.*\t\s*POSITIONTEMPLATE_end\s*$/ ) + { + my $customaction = $1; + $lastposition = $lastposition + 25; + ${$sequencetable}[$i] =~ s/POSITIONTEMPLATE_end/$lastposition/; + $infoline = "Setting position \"$lastposition\" for custom action \"$customaction\".\n"; + push(@installer::globals::logfileinfo, $infoline); + } + } + + # Step 2: Resolving all occurences of "POSITIONTEMPLATE_abc" or "POSITIONTEMPLATE_behind_abc" + # where abc is the name of the reference Custom Action. + # This has to be done, until there is no more occurence of POSITIONTEMPLATE (success) + # or there is no replacement in one circle (failure). + + my $template_exists = 0; + my $template_replaced = 0; + my $counter = 0; + + do + { + $template_exists = 0; + $template_replaced = 0; + $counter++; + + for ( my $i = 0; $i <= $#{$sequencetable}; $i++ ) + { + if ( ${$sequencetable}[$i] =~ /^\s*(\w+)\t.*\t\s*(POSITIONTEMPLATE_.*?)\s*$/ ) + { + my $onename = $1; + my $templatename = $2; + my $positionname = $templatename; + my $customaction = $templatename; + $customaction =~ s/POSITIONTEMPLATE_//; + $template_exists = 1; + + # Trying to find the correct number. + # This can fail, if the custom action has no number + + my $setbehind = 0; + if ( $customaction =~ /^\s*behind_(.*?)\s*$/ ) + { + $customaction = $1; + $setbehind = 1; + } + + my $position = get_customaction_position($customaction, $sequencetable); + + if ( $position >= 0 ) # Found CustomAction and is has a position. Otherwise return value is "-1". + { + my $newposition = 0; + if ( $setbehind ) { $newposition = $position + 2; } + else { $newposition = $position - 2; } + ${$sequencetable}[$i] =~ s/$templatename/$newposition/; + $template_replaced = 1; + $infoline = "Setting position \"$newposition\" for custom action \"$onename\" (scp: \"$positionname\" at position $position).\n"; + push(@installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Could not assign position for custom action \"$onename\" yet (scp: \"$positionname\").\n"; + push(@installer::globals::logfileinfo, $infoline); + } + } + } + } while (( $template_exists ) && ( $template_replaced )); + + # An error occured, because templates still exist, but could not be replaced. + # Reason: + # 1. Wrong name of CustomAction in scp2 (typo?) + # 2. Circular dependencies of CustomActions (A after B and B after A) + + # Problem: It is allowed, that a CustomAction is defined in scp2 in a library that is + # part of product ABC, but this CustomAction is not used in this product + # and the reference CustomAction is not part of this product. + # Therefore this cannot be an error, but only produce a warning. The assigned number + # must be the last sequence number. + + if (( $template_exists ) && ( ! $template_replaced )) + { + # Giving a precise error message, collecting all unresolved templates + # my $templatestring = ""; + + for ( my $i = 0; $i <= $#{$sequencetable}; $i++ ) + { + if ( ${$sequencetable}[$i] =~ /^\s*(\w+)\t.*\t\s*(POSITIONTEMPLATE_.*?)\s*$/ ) + { + my $customactionname = $1; + my $fulltemplate = $2; + my $template = $fulltemplate; + $template =~ s/POSITIONTEMPLATE_//; + # my $newstring = $customactionname . " (" . $template . ")"; + # $templatestring = $templatestring . $newstring . ", "; + # Setting at the end! + $lastposition = $lastposition + 25; + ${$sequencetable}[$i] =~ s/$fulltemplate/$lastposition/; + $infoline = "WARNING: Setting position \"$lastposition\" for custom action \"$customactionname\". Could not find CustomAction \"$template\".\n"; + push(@installer::globals::logfileinfo, $infoline); + } + } + # $templatestring =~ s/,\s*$//; + + # $infoline = "Error: Saving table \"$tablename\"\n"; + # push(@installer::globals::logfileinfo, $infoline); + # print $infoline; + # installer::files::save_file($tablename, $sequencetable); + # installer::exiter::exit_program("ERROR: Unresolved positions in CustomActions in scp2: $templatestring", "set_positions_in_table"); + } +} + +########################################################################## +# Setting the Windows custom actions into different tables +# CustomAc.idt, InstallE.idt, InstallU.idt, ControlE.idt, ControlC.idt +########################################################################## + +sub addcustomactions +{ + my ($languageidtdir, $customactions, $filesarray) = @_; + + installer::logger::include_timestamp_into_logfile("\nPerformance Info: addcustomactions start\n"); + + my $customactionidttablename = $languageidtdir . $installer::globals::separator . "CustomAc.idt"; + my $customactionidttable = installer::files::read_file($customactionidttablename); + my $installexecutetablename = $languageidtdir . $installer::globals::separator . "InstallE.idt"; + my $installexecutetable = installer::files::read_file($installexecutetablename); + my $adminexecutetablename = $languageidtdir . $installer::globals::separator . "AdminExe.idt"; + my $adminexecutetable = installer::files::read_file($adminexecutetablename); + my $installuitablename = $languageidtdir . $installer::globals::separator . "InstallU.idt"; + my $installuitable = installer::files::read_file($installuitablename); + my $controleventtablename = $languageidtdir . $installer::globals::separator . "ControlE.idt"; + my $controleventtable = installer::files::read_file($controleventtablename); + my $controlconditiontablename = $languageidtdir . $installer::globals::separator . "ControlC.idt"; + my $controlconditiontable = installer::files::read_file($controlconditiontablename); + + # Iterating over all Windows custom actions + + for ( my $i = 0; $i <= $#{$customactions}; $i++ ) + { + my $customaction = ${$customactions}[$i]; + my $name = $customaction->{'Name'}; + my $typ = $customaction->{'Typ'}; + my $source = $customaction->{'Source'}; + my $target = $customaction->{'Target'}; + my $inbinarytable = $customaction->{'Inbinarytable'}; + my $gid = $customaction->{'gid'}; + + my $styles = ""; + if ( $customaction->{'Styles'} ) { $styles = $customaction->{'Styles'}; } + + my $added_customaction = set_custom_action($customactionidttable, $name, $typ, $source, $target, $inbinarytable, $filesarray, $customactionidttablename, $styles); + + if ( $added_customaction ) + { + # If the CustomAction was added into the CustomAc.idt, it can be connected to the installation. + # There are currently two different ways for doing this: + # 1. Using "add_custom_action_to_install_table", which adds the CustomAction to the install sequences, + # which are saved in InstallE.idt and InstallU.idt + # 2. Using "connect_custom_action_to_control" and "connect_custom_action_to_control". The first method + # connects a CustomAction to a control in ControlE.idt. The second method sets a condition for a control, + # which might be influenced by the CustomAction. This happens in ControlC.idt. + + # Any Windows CustomAction can have a lot of different assignments. + + for ( my $j = 1; $j <= 50; $j++ ) + { + my $key = "Assignment" . $j; + my $value = ""; + if ( $customaction->{$key} ) + { + $value = $customaction->{$key}; + + # in a patch the Assignment can be overwritten by a PatchAssignment + if ( $installer::globals::patch ) + { + $patchkey = "PatchAssignment" . $j; + if ( $customaction->{$patchkey} ) + { + $value = $customaction->{$patchkey}; + $key = $patchkey; + } + } + + } + else { last; } + + # $value is now a comma separated list + if ( $value =~ /^\s*\(\s*(.*)\s*\);?\s*$/ ) { $value = $1; } + my $assignmentarray = installer::converter::convert_stringlist_into_array(\$value, ","); + my $assignment = create_customaction_assignment_hash($gid, $name, $key, $assignmentarray); + + if ( $assignment->{'parameter1'} eq "InstallExecuteSequence" ) + { + add_custom_action_to_install_table($installexecutetable, $source, $name, $assignment->{'parameter2'}, $assignment->{'parameter3'}, $filesarray, $installexecutetablename, $styles); + } + elsif ( $assignment->{'parameter1'} eq "AdminExecuteSequence" ) + { + add_custom_action_to_install_table($adminexecutetable, $source, $name, $assignment->{'parameter2'}, $assignment->{'parameter3'}, $filesarray, $adminexecutetablename, $styles); + } + elsif ( $assignment->{'parameter1'} eq "InstallUISequence" ) + { + add_custom_action_to_install_table($installuitable, $source, $name, $assignment->{'parameter2'}, $assignment->{'parameter3'}, $filesarray, $installuitablename, $styles); + } + elsif ( $assignment->{'parameter1'} eq "ControlEvent" ) + { + connect_custom_action_to_control($controleventtable, $controleventtablename, $assignment->{'parameter2'}, $assignment->{'parameter3'}, $assignment->{'parameter4'}, $assignment->{'parameter5'}, $assignment->{'parameter6'}, $assignment->{'parameter7'}); + } + elsif ( $assignment->{'parameter1'} eq "ControlCondition" ) + { + connect_condition_to_control($controlconditiontable, $controlconditiontablename, $assignment->{'parameter2'}, $assignment->{'parameter3'}, $assignment->{'parameter4'}, $assignment->{'parameter5'}); + } + else + { + installer::exiter::exit_program("ERROR: gid: $gid, key: $key ! Unknown Windows CustomAction table: $assignmenthashref->{'parameter1'} ! Currently supported: InstallUISequence, InstallESequence, ControlEvent, ControlCondition", "addcustomactions"); + } + } + } + } + + # Setting the positions in the tables + + set_positions_in_table($installexecutetable, $installexecutetablename); + set_positions_in_table($installuitable, $installuitablename); + set_positions_in_table($adminexecutetable, $adminexecutetablename); + + # Saving the files + + installer::files::save_file($customactionidttablename, $customactionidttable); + installer::files::save_file($installexecutetablename, $installexecutetable); + installer::files::save_file($adminexecutetablename, $adminexecutetable); + installer::files::save_file($installuitablename, $installuitable); + installer::files::save_file($controleventtablename, $controleventtable); + installer::files::save_file($controlconditiontablename, $controlconditiontable); + + my $infoline = "Updated idt file: $customactionidttablename\n"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = "Updated idt file: $installexecutetablename\n"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = "Updated idt file: $adminexecutetablename\n"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = "Updated idt file: $installuitablename\n"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = "Updated idt file: $controleventtablename\n"; + push(@installer::globals::logfileinfo, $infoline); + $infoline = "Updated idt file: $controlconditiontablename\n"; + push(@installer::globals::logfileinfo, $infoline); + + installer::logger::include_timestamp_into_logfile("\nPerformance Info: addcustomactions end\n"); +} + +########################################################################## +# Setting bidi attributes in idt tables +########################################################################## + +sub setbidiattributes +{ + my ($languageidtdir, $onelanguage) = @_; + + # Editing the files Dialog.idt and Control.idt + + my $dialogfilename = $languageidtdir . $installer::globals::separator . "Dialog.idt"; + my $controlfilename = $languageidtdir . $installer::globals::separator . "Control.idt"; + + my $dialogfile = installer::files::read_file($dialogfilename); + my $controlfile = installer::files::read_file($controlfilename); + + # Searching attributes in Dialog.idt and adding "896". + # Attributes are in column 6 (from 10). + + my $bidiattribute = 896; + for ( my $i = 0; $i <= $#{$dialogfile}; $i++ ) + { + if ( $i < 3 ) { next; } + if ( ${$dialogfile}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) + { + my $one = $1; + my $two = $2; + my $three = $3; + my $four = $4; + my $five = $5; + my $attribute = $6; + my $seven = $7; + my $eight = $8; + $attribute = $attribute + $bidiattribute; + ${$dialogfile}[$i] = "$one\t$two\t$three\t$four\t$five\t$attribute\t$seven\t$eight\n"; + } + } + + # Searching attributes in Control.idt and adding "224". + # Attributes are in column 8 (from 12). + + $bidiattribute = 224; + for ( my $i = 0; $i <= $#{$controlfile}; $i++ ) + { + if ( $i < 3 ) { next; } + if ( ${$controlfile}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) + { + my $one = $1; + my $two = $2; + my $three = $3; + my $four = $4; + my $five = $5; + my $six = $6; + my $seven = $7; + my $attribute = $8; + my $nine = $9; + my $ten = $10; + my $eleven = $11; + my $twelve = $12; + $attribute = $attribute + $bidiattribute; + ${$controlfile}[$i] = "$one\t$two\t$three\t$four\t$five\t$six\t$seven\t$attribute\t$nine\t$ten\t$eleven\t$twelve\n"; + } + } + + # Saving the file + + installer::files::save_file($dialogfilename, $dialogfile); + $infoline = "Set bidi support in idt file \"$dialogfilename\" for language $onelanguage\n"; + push(@installer::globals::logfileinfo, $infoline); + + installer::files::save_file($controlfilename, $controlfile); + $infoline = "Set bidi support in idt file \"$controlfilename\" for language $onelanguage\n"; + push(@installer::globals::logfileinfo, $infoline); +} + +1; diff --git a/solenv/bin/modules/installer/windows/inifile.pm b/solenv/bin/modules/installer/windows/inifile.pm new file mode 100644 index 000000000000..b6737495279a --- /dev/null +++ b/solenv/bin/modules/installer/windows/inifile.pm @@ -0,0 +1,150 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: inifile.pm,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::inifile; + +use installer::existence; +use installer::files; +use installer::globals; +use installer::windows::idtglobal; + +#################################################### +# Setting the profile for a special profileitem +#################################################### + +sub get_profile_for_profileitem +{ + my ($profileid, $filesref) = @_; + + my $profile = installer::existence::get_specified_file($filesref, $profileid); + + return $profile; +} + +#################################################### +# Checking whether profile is included in patch +#################################################### + +sub profile_has_patch_flag +{ + my ($profile) = @_; + + my $in_patch = 0; + + my $styles = ""; + if ( $profile->{'Styles'} ) { $styles = $profile->{'Styles'}; } + if ( $styles =~ /\bPATCH\b/ ) { $in_patch = 1; } + + return $in_patch; +} + +#################################################### +# Checking whether profile is part of product +#################################################### + +sub file_is_part_of_product +{ + my ($profilegid, $filesref) = @_; + + my $part_of_product = 0; + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + $onefile = ${$filesref}[$i]; + my $filegid = $onefile->{'gid'}; + + if ( $filegid eq $profilegid ) + { + $part_of_product = 1; + last; + } + } + + return $part_of_product; +} + +########################################################################################################### +# Creating the file IniFile.idt dynamically +# Content: +# IniFile\tFileName\tDirProperty\tSection\tKey\tValue\tAction\tComponent_ +########################################################################################################### + +sub create_inifile_table +{ + my ($inifiletableentries, $filesref, $basedir) = @_; + + my @inifiletable = (); + + installer::windows::idtglobal::write_idt_header(\@inifiletable, "inifile"); + + for ( my $i = 0; $i <= $#{$inifiletableentries}; $i++ ) + { + my $profileitem = ${$inifiletableentries}[$i]; + + my $profileid = $profileitem->{'ProfileID'}; + + # Is this profile part of the product? This is not sure, for example in patch process. + # If the profile is not part of the product, this ProfileItem must be ignored. + + if ( ! file_is_part_of_product($profileid, $filesref) ) { next; } + + my $profile = get_profile_for_profileitem($profileid, $filesref); + + if (( $installer::globals::patch ) && ( ! profile_has_patch_flag($profile) )) { next; } + + my %inifile = (); + + $inifile{'IniFile'} = $profileitem->{'Inifiletablekey'}; + $inifile{'FileName'} = $profile->{'Name'}; + $inifile{'DirProperty'} = $profile->{'uniquedirname'}; + $inifile{'Section'} = $profileitem->{'Section'}; + $inifile{'Key'} = $profileitem->{'Key'}; + $inifile{'Value'} = $profileitem->{'Value'}; + $inifile{'Action'} = $profileitem->{'Inifiletableaction'}; + $inifile{'Component_'} = $profile->{'componentname'}; + + my $oneline = $inifile{'IniFile'} . "\t" . $inifile{'FileName'} . "\t" . $inifile{'DirProperty'} . "\t" + . $inifile{'Section'} . "\t" . $inifile{'Key'} . "\t" . $inifile{'Value'} . "\t" + . $inifile{'Action'} . "\t" . $inifile{'Component_'} . "\n"; + + push(@inifiletable, $oneline); + } + + # Saving the file + + my $inifiletablename = $basedir . $installer::globals::separator . "IniFile.idt"; + installer::files::save_file($inifiletablename ,\@inifiletable); + my $infoline = "Created idt file: $inifiletablename\n"; + push(@installer::globals::logfileinfo, $infoline); + +} + +1; diff --git a/solenv/bin/modules/installer/windows/java.pm b/solenv/bin/modules/installer/windows/java.pm new file mode 100644 index 000000000000..6b9cb7d725aa --- /dev/null +++ b/solenv/bin/modules/installer/windows/java.pm @@ -0,0 +1,124 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: java.pm,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::java; + +use installer::exiter; +use installer::files; +use installer::globals; +use installer::windows::idtglobal; + +#################################################################################### +# Writing content into RegLocat.idt and AppSearc.idt to find Java on system +#################################################################################### + +sub update_java_tables +{ + my ($basedir, $allvariables) = @_; + + my $reglocatfile = ""; + my $appsearchfile = ""; + + my $reglocatfilename = $basedir . $installer::globals::separator . "RegLocat.idt"; + my $appsearchfilename = $basedir . $installer::globals::separator . "AppSearc.idt"; + my $signaturefilename = $basedir . $installer::globals::separator . "Signatur.idt"; + + if ( -f $reglocatfilename ) + { + $reglocatfile = installer::files::read_file($reglocatfilename); + } + else + { + my @reglocattable = (); + $reglocatfile = \@reglocattable; + installer::windows::idtglobal::write_idt_header($reglocatfile, "reglocat"); + } + + if ( -f $appsearchfilename ) + { + $appsearchfile = installer::files::read_file($appsearchfilename); + } + else + { + my @appsearchtable = (); + $appsearchfile = \@appsearchtable; + installer::windows::idtglobal::write_idt_header($appsearchfile, "appsearch"); + } + + if ( -f $signaturefilename ) + { + $signaturefile = installer::files::read_file($signaturefilename); + } + else + { + my @signaturetable = (); + $signaturefile = \@signaturetable; + installer::windows::idtglobal::write_idt_header($signaturefile, "signatur"); + } + + # Writing content into this tables + # Java version is saved in scp project + # $installer::globals::javafile was defined in installer::windows::idtglobal::add_childprojects + + if ( ! $installer::globals::javafile->{'Javaversion'} ) { installer::exiter::exit_program("ERROR: \"Javaversion\" has to be defined in $installer::globals::javafile->{'gid'} in scp project!", "update_java_tables"); } + + my $javastring = $installer::globals::javafile->{'Javaversion'}; + + my $signature = "JavaReg"; + my $rootvalue = "2"; + my $key = "Software\\JavaSoft\\Java Runtime Environment\\" . $javastring; + my $name = "JavaHome"; + my $type = 2; + my $property = "JAVAPATH"; + + my $oneline = $signature . "\t" . $rootvalue . "\t" . $key . "\t" . $name . "\t" . $type . "\n"; + push(@{$reglocatfile}, $oneline); + + $oneline = $property . "\t" . $signature . "\n"; + push(@{$appsearchfile}, $oneline); + + # Saving the files + + installer::files::save_file($reglocatfilename ,$reglocatfile); + my $infoline = "Updated idt file for Java: $reglocatfilename\n"; + push(@installer::globals::logfileinfo, $infoline); + + installer::files::save_file($appsearchfilename ,$appsearchfile); + $infoline = "Updated idt file for Java: $appsearchfilename\n"; + push(@installer::globals::logfileinfo, $infoline); + + installer::files::save_file($signaturefilename ,$signaturefile); + $infoline = "Updated idt file: $signaturefilename\n"; + push(@installer::globals::logfileinfo, $infoline); + +} + +1; diff --git a/solenv/bin/modules/installer/windows/language.pm b/solenv/bin/modules/installer/windows/language.pm new file mode 100644 index 000000000000..11a31c6c5f60 --- /dev/null +++ b/solenv/bin/modules/installer/windows/language.pm @@ -0,0 +1,78 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: language.pm,v $ +# +# $Revision: 1.10 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::language; + +use installer::exiter; + +#################################################### +# Determining the Windows language (LCID) +# English: 1033 +#################################################### + +sub get_windows_language +{ + my ($language) = @_; + + my $windowslanguage = ""; + + if ( $installer::globals::msilanguage->{$language} ) { $windowslanguage = $installer::globals::msilanguage->{$language}; } + + if ( $windowslanguage eq "" ) { installer::exiter::exit_program("ERROR: Unknown language $language in function get_windows_language", "get_windows_language"); } + + return $windowslanguage; +} + +#################################################### +# Determining the Windows language ANSI-Codepage +# English: 1252 +#################################################### + +sub get_windows_encoding +{ + my ($language) = @_; + + my $windowsencoding = ""; + + if ( $installer::globals::msiencoding->{$language} ) { $windowsencoding = $installer::globals::msiencoding->{$language}; } + + # if ( $windowsencoding eq "" ) { installer::exiter::exit_program("ERROR: Unknown language $language in function get_windows_encoding", "get_windows_encoding"); } + if ( $windowsencoding eq "" ) { $windowsencoding = "0"; } # setting value, if the language is not listed in the encodinglist + + if ( $windowsencoding eq "0" ) { $windowsencoding = "65001"; } # languages with "0" have to be available in UTF-8 (65001) + + # Asian multilingual installation sets need a code neutral Windows Installer database -> $windowsencoding = 0 + if (( $language eq "en-US" ) && (( $installer::globals::product =~ /suitemulti/i ) || ( $installer::globals::product =~ /officemulti/i ) || ( $installer::globals::product =~ /c05office/i ) || ( $installer::globals::added_english ))) { $windowsencoding = "0"; } + + return $windowsencoding; +} + +1;
\ No newline at end of file diff --git a/solenv/bin/modules/installer/windows/media.pm b/solenv/bin/modules/installer/windows/media.pm new file mode 100644 index 000000000000..c8b1e03ab5e3 --- /dev/null +++ b/solenv/bin/modules/installer/windows/media.pm @@ -0,0 +1,462 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: media.pm,v $ +# +# $Revision: 1.12 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::media; + +use installer::exiter; +use installer::files; +use installer::globals; +use installer::windows::idtglobal; + +############################################################## +# Returning the diskid for the media table. +############################################################## + +sub get_media_diskid +{ + my ($id) = @_; + + return $id; +} + +############################################################## +# Returning the lastsequence for the media table. +############################################################## + +sub get_media_lastsequence +{ + my ($fileref) = @_; + + return $fileref->{'sequencenumber'}; +} + +############################################################## +# Returning the diskprompt for the media table. +############################################################## + +sub get_media_diskprompt +{ + return 1; +} + +############################################################## +# Returning the cabinet file name for the media table. +############################################################## + +sub get_media_cabinet +{ + my ($id) = @_; + + my $number = 1000 + $id; + my $filename = "f_" . $number . ".cab"; + + if ( $installer::globals::include_cab_in_msi ) { $filename = "\#" . $filename; } + + return $filename; +} + +############################################################## +# Returning the volumelabel for the media table. +############################################################## + +sub get_media_volumelabel +{ + return "DISK1"; +} + +############################################################## +# Returning the source for the media table. +############################################################## + +sub get_media_source +{ + return ""; +} + +############################################################## +# Saving the cabinet file name in the files collector. +# This is useful for making a list to connect the +# source of each file with the destination cabinet file. +############################################################## + +sub set_cabinetfilename_for_component_in_file_collector +{ + my ($cabinetfilename, $filesref, $componentname, $max) = @_; + + for ( my $i = 0; $i <= $max; $i++ ) + { + my $onefile = ${$filesref}[$i]; + my $component = $onefile->{'componentname'}; + + if ( $component eq $componentname ) + { + my $cabinet = ""; + + if ( $onefile->{'cabinet'} ) { $cabinet = $onefile->{'cabinet'}; } + + if ( $cabinet eq "" ) + { + $onefile->{'cabinet'} = $cabinetfilename; + } + } + } +} + +################################################# +# Creating the cab file name dynamically +################################################# + +sub generate_cab_filename_for_some_cabs +{ + my ( $allvariables, $id ) = @_; + + my $name = $allvariables->{'PRODUCTNAME'}; + + $name = lc($name); + $name =~ s/\.//g; + $name =~ s/\s//g; + + # possibility to overwrite the name with variable CABFILENAME + if ( $allvariables->{'CABFILENAME'} ) { $name = $allvariables->{'CABFILENAME'}; } + + $name = $name . $id . ".cab"; + + if ( $installer::globals::include_cab_in_msi ) { $name = "\#" . $name; } + + return $name; +} + +################################################# +# Creating the cab file name for cab files +# defined in packages. +################################################# + +sub get_cabfilename +{ + my ($name) = @_; + + if ( $installer::globals::include_cab_in_msi ) { $name = "\#" . $name; } + + return $name; +} + +################################################# +# Creating the cab file name dynamically +################################################# + +sub generate_cab_filename +{ + my ( $allvariables ) = @_; + + my $name = $allvariables->{'PRODUCTNAME'}; + + $name = lc($name); + $name =~ s/\.//g; + $name =~ s/\s//g; + + # possibility to overwrite the name with variable CABFILENAME + if ( $allvariables->{'CABFILENAME'} ) { $name = $allvariables->{'CABFILENAME'}; } + + $name = $name . ".cab"; + + if ( $installer::globals::include_cab_in_msi ) { $name = "\#" . $name; } + + return $name; +} + +sub get_maximum_filenumber +{ + my ($allfiles, $maxcabfilenumber) = @_; + + my $maxfile = 0; + + while ( ! ( $allfiles%$maxcabfilenumber == 0 )) + { + $allfiles++; + } + + $maxfile = $allfiles / $maxcabfilenumber; + + $maxfile++; # for securitry + + return $maxfile; +} + +################################################################################# +# Setting the last sequence for the cabinet files +################################################################################# + +sub get_last_sequence +{ + my ( $cabfilename, $alludpatelastsequences ) = @_; + + my $sequence = 0; + + if (( $installer::globals::updatedatabase ) && ( exists($alludpatelastsequences->{$cabfilename}) )) + { + $sequence = $alludpatelastsequences->{$cabfilename}; + } + else + { + $sequence = $installer::globals::lastsequence{$cabfilename}; + } + + return $sequence; +} + +################################################################################# +# Creating the file Media.idt dynamically +# Content: +# DiskId LastSequence DiskPrompt Cabinet VolumeLabel Source +# Idea: Every component is packed into each own cab file +################################################################################# + +sub create_media_table +{ + my ($filesref, $basedir, $allvariables, $alludpatelastsequences, $allupdatediskids) = @_; + + my @mediatable = (); + + my $diskid = 0; + + installer::windows::idtglobal::write_idt_header(\@mediatable, "media"); + + if ( $allvariables->{'INCLUDE_CAB_IN_MSI'} ) { $installer::globals::include_cab_in_msi = 1; } + + if ( $installer::globals::use_packages_for_cabs ) + { + my $cabfile; + foreach $cabfile ( sort keys %installer::globals::lastsequence ) + { + my %media = (); + $diskid++; + + $media{'DiskId'} = get_media_diskid($diskid); + $media{'LastSequence'} = get_last_sequence($cabfile, $alludpatelastsequences); + $media{'DiskPrompt'} = get_media_diskprompt(); + $media{'Cabinet'} = get_cabfilename($cabfile); + $media{'VolumeLabel'} = get_media_volumelabel(); + $media{'Source'} = get_media_source(); + + my $oneline = $media{'DiskId'} . "\t" . $media{'LastSequence'} . "\t" . $media{'DiskPrompt'} . "\t" + . $media{'Cabinet'} . "\t" . $media{'VolumeLabel'} . "\t" . $media{'Source'} . "\n"; + + push(@mediatable, $oneline); + + # Comparing the disk id with the disk id from update database. Both have to be identical. New files have to be added + # to the new pff cabinet file. And existing cab files must not be removed. + if ( $installer::globals::updatedatabase ) + { + # Comparing lines in new media table with line from media table in udpate database. + if ( exists($allupdatediskids->{$media{'Cabinet'}}) ) + { + if ( $media{'DiskId'} != $allupdatediskids->{$media{'Cabinet'}} ) + { + installer::exiter::exit_program("ERROR: Different DiskIDs for cab file \"$media{'Cabinet'}\".\nCurrent installation set: \"$media{'DiskId'}\", but update database used \"$allupdatediskids->{$media{'Cabinet'}}\".\nWere cabinet files removed or added?", "create_media_table"); + } + } + else + { + my $localinfoline = "Warning: Could not find cabinet file \"$media{'Cabinet'}}\" in update database. This seems to be an new cabinet file!?\n"; + push(@installer::globals::logfileinfo, $localinfoline); + } + } + } + + # one new cabinet file for all files added after the final release + if (( $installer::globals::updatedatabase ) && ( $installer::globals::pfffileexists )) + { + my %media = (); + $diskid++; + + $media{'DiskId'} = get_media_diskid($diskid) + $installer::globals::mergemodulenumber; # Adding mergemodulenumber, because this files are included later + $media{'LastSequence'} = $installer::globals::updatesequencecounter; + $media{'DiskPrompt'} = get_media_diskprompt(); + $media{'Cabinet'} = get_cabfilename($installer::globals::pffcabfilename); + $media{'VolumeLabel'} = get_media_volumelabel(); + $media{'Source'} = get_media_source(); + + my $oneline = $media{'DiskId'} . "\t" . $media{'LastSequence'} . "\t" . $media{'DiskPrompt'} . "\t" + . $media{'Cabinet'} . "\t" . $media{'VolumeLabel'} . "\t" . $media{'Source'} . "\n"; + + push(@mediatable, $oneline); + } + + } + elsif ( $installer::globals::cab_file_per_component ) + { + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + my $nextfile = ${$filesref}[$i+1]; + + my $filecomponent = ""; + my $nextcomponent = ""; + + if ( $onefile->{'componentname'} ) { $filecomponent = $onefile->{'componentname'}; } + if ( $nextfile->{'componentname'} ) { $nextcomponent = $nextfile->{'componentname'}; } + + if ( $filecomponent eq $nextcomponent ) + { + next; # nothing to do, this is not the last file of a component + } + + my %media = (); + $diskid++; + + $media{'DiskId'} = get_media_diskid($diskid); + $media{'LastSequence'} = get_media_lastsequence($onefile); + $media{'DiskPrompt'} = get_media_diskprompt(); + $media{'Cabinet'} = get_media_cabinet($diskid); + $media{'VolumeLabel'} = get_media_volumelabel(); + $media{'Source'} = get_media_source(); + + my $oneline = $media{'DiskId'} . "\t" . $media{'LastSequence'} . "\t" . $media{'DiskPrompt'} . "\t" + . $media{'Cabinet'} . "\t" . $media{'VolumeLabel'} . "\t" . $media{'Source'} . "\n"; + + push(@mediatable, $oneline); + + $media{'Cabinet'} =~ s/^\s*\#//; # removing leading hash + set_cabinetfilename_for_component_in_file_collector($media{'Cabinet'}, $filesref, $filecomponent, $i); + } + } + elsif ( $installer::globals::fix_number_of_cab_files ) + { + # number of cabfiles + my $maxcabfilenumber = $installer::globals::number_of_cabfiles; + if ( $allvariables->{'CABFILENUMBER'} ) { $maxcabfilenumber = $allvariables->{'CABFILENUMBER'}; } + my $allfiles = $#{$filesref} + 1; + my $maxfilenumber = get_maximum_filenumber($allfiles, $maxcabfilenumber); + # my $maxfilenumber = 1000; # maximum 1000 files in each cabinet file + my $cabfilenumber = 0; + my $cabfull = 0; + my $counter = 0; + + # Sorting of files collector files required ! + # Attention: The order in the cab file is not guaranteed (especially in udpate process) + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + if (( $counter >= $maxfilenumber ) || ( $i == $#{$filesref} )) { $cabfull = 1; } + + $counter++; # counting the files in the cab file + + my $onefile = ${$filesref}[$i]; + my $nextfile = ${$filesref}[$i+1]; + + my $filecomponent = ""; + my $nextcomponent = ""; + + if ( $onefile->{'componentname'} ) { $filecomponent = $onefile->{'componentname'}; } + if ( $nextfile->{'componentname'} ) { $nextcomponent = $nextfile->{'componentname'}; } + + if ( $filecomponent eq $nextcomponent ) # all files of one component have to be in one cab file + { + next; # nothing to do, this is not the last file of a component + } + + if ( $cabfull ) + { + my %media = (); + $cabfilenumber++; + + $media{'DiskId'} = get_media_diskid($cabfilenumber); + # $media{'LastSequence'} = get_media_lastsequence($onefile); + $media{'LastSequence'} = $i + 1; # This should be correct, also for unsorted files collectors + $media{'DiskPrompt'} = get_media_diskprompt(); + $media{'Cabinet'} = generate_cab_filename_for_some_cabs($allvariables, $cabfilenumber); + $media{'VolumeLabel'} = get_media_volumelabel(); + $media{'Source'} = get_media_source(); + + my $oneline = $media{'DiskId'} . "\t" . $media{'LastSequence'} . "\t" . $media{'DiskPrompt'} . "\t" + . $media{'Cabinet'} . "\t" . $media{'VolumeLabel'} . "\t" . $media{'Source'} . "\n"; + + push(@mediatable, $oneline); + + # Saving the cabinet file name in the file collector + + $media{'Cabinet'} =~ s/^\s*\#//; # removing leading hash + + for ( my $j = 0; $j <= $i; $j++ ) + { + my $onefile = ${$filesref}[$j]; + if ( ! $onefile->{'cabinet'} ) { $onefile->{'cabinet'} = $media{'Cabinet'}; } + } + + $cabfull = 0; + $counter = 0; + } + } + } + elsif ( $installer::globals::one_cab_file ) + { + my %media = (); + $diskid++; + + my $maximumfile = $#{$filesref}; + + $media{'DiskId'} = get_media_diskid($diskid); + # $media{'LastSequence'} = ${$filesref}[$maximumfile]->{'sequencenumber'}; # sequence number of the last file + $media{'LastSequence'} = $maximumfile + 1; # This works also for unsorted file collector + $media{'DiskPrompt'} = get_media_diskprompt(); + $media{'Cabinet'} = generate_cab_filename($allvariables); + $media{'VolumeLabel'} = get_media_volumelabel(); + $media{'Source'} = get_media_source(); + + my $oneline = $media{'DiskId'} . "\t" . $media{'LastSequence'} . "\t" . $media{'DiskPrompt'} . "\t" + . $media{'Cabinet'} . "\t" . $media{'VolumeLabel'} . "\t" . $media{'Source'} . "\n"; + + push(@mediatable, $oneline); + + # Saving the cabinet file name in the file collector + + $media{'Cabinet'} =~ s/^\s*\#//; # removing leading hash + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + $onefile->{'cabinet'} = $media{'Cabinet'}; + } + } + else + { + installer::exiter::exit_program("ERROR: No cab file specification in globals.pm !", "create_media_table"); + } + + # Saving the file + + my $mediatablename = $basedir . $installer::globals::separator . "Media.idt"; + installer::files::save_file($mediatablename ,\@mediatable); + my $infoline = "Created idt file: $mediatablename\n"; + push(@installer::globals::logfileinfo, $infoline); +} + +1; diff --git a/solenv/bin/modules/installer/windows/mergemodule.pm b/solenv/bin/modules/installer/windows/mergemodule.pm new file mode 100755 index 000000000000..7dfd8ff49c76 --- /dev/null +++ b/solenv/bin/modules/installer/windows/mergemodule.pm @@ -0,0 +1,1656 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: mergemodule.pm,v $ +# +# $Revision: 1.8 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::mergemodule; + +use Cwd; +use Digest::MD5; +use installer::converter; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::logger; +use installer::pathanalyzer; +use installer::remover; +use installer::scriptitems; +use installer::systemactions; +use installer::worker; +use installer::windows::idtglobal; +use installer::windows::language; + +################################################################# +# Merging the Windows MergeModules into the msi database. +################################################################# + +sub merge_mergemodules_into_msi_database +{ + my ($mergemodules, $filesref, $msifilename, $languagestringref, $language, $languagefile, $allvariables, $includepatharrayref, $allupdatesequences, $allupdatelastsequences, $allupdatediskids) = @_; + + my $domerge = 0; + if (( $#{$mergemodules} > -1 ) && ( ! $installer::globals::patch ) && ( ! $installer::globals::languagepack )) { $domerge = 1; } + + if ( $domerge ) + { + installer::logger::include_header_into_logfile("Merging merge modules into msi database"); + installer::logger::print_message( "... merging msm files into msi database ... \n" ); + installer::logger::include_timestamp_into_logfile("\nPerformance Info: MergeModule into msi database, start"); + + my $msidb = "msidb.exe"; # Has to be in the path + my $cabinetfile = "MergeModule.CABinet"; # the name of each cabinet file in a merge file + my $infoline = ""; + my $systemcall = ""; + my $returnvalue = ""; + + # 1. Analyzing the MergeModule (has only to be done once) + # a. -> Extracting cabinet file: msidb.exe -d <msmfile> -x MergeModule.CABinet + # b. -> Number of files in cabinet file: msidb.exe -d <msmfile> -f <directory> -e File + # c. -> List of components: msidb.exe -d <msmfile> -f <directory> -e Component + + if ( ! $installer::globals::mergemodules_analyzed ) + { + installer::logger::include_timestamp_into_logfile("\nPerformance Info: Analyzing MergeModules, start"); + $infoline = "Analyzing all Merge Modules\n\n"; + push( @installer::globals::logfileinfo, $infoline); + + %installer::globals::mergemodules = (); + + my $mergemoduledir = installer::systemactions::create_directories("mergefiles", $languagestringref); + # push(@installer::globals::removedirs, $mergemoduledir); + + my $mergemodule; + foreach $mergemodule ( @{$mergemodules} ) + { + my $filename = $mergemodule->{'Name'}; + my $mergefile = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$filename, $includepatharrayref, 1); + + if ( ! -f $$mergefile ) { installer::exiter::exit_program("ERROR: msm file not found: $filename !", "merge_mergemodules_into_msi_database"); } + my $completesource = $$mergefile; + + my $mergegid = $mergemodule->{'gid'}; + my $workdir = $mergemoduledir . $installer::globals::separator . $mergegid; + if ( ! -d $workdir ) { installer::systemactions::create_directory($workdir); } + + $infoline = "Analyzing Merge Module: $filename\n"; + push( @installer::globals::logfileinfo, $infoline); + + # copy msm file into working directory + my $completedest = $workdir . $installer::globals::separator . $filename; + installer::systemactions::copy_one_file($completesource, $completedest); + if ( ! -f $completedest ) { installer::exiter::exit_program("ERROR: msm file not found: $completedest !", "merge_mergemodules_into_msi_database"); } + + # changing directory + my $from = cwd(); + my $to = $workdir; + chdir($to); + + # remove an existing cabinet file + if ( -f $cabinetfile ) { unlink($cabinetfile); } + + # exclude cabinet file + $systemcall = $msidb . " -d " . $filename . " -x " . $cabinetfile; + $returnvalue = system($systemcall); + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute $systemcall !\n"; + push( @installer::globals::logfileinfo, $infoline); + installer::exiter::exit_program("ERROR: Could not extract cabinet file from merge file: $completedest !", "merge_mergemodules_into_msi_database"); + } + else + { + $infoline = "Success: Executed $systemcall successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + # exclude tables from mergefile + # Attention: All listed tables have to exist in the database. If they not exist, an error window pops up + # and the return value of msidb.exe is not zero. The error window makes it impossible to check the existence + # of a table with the help of the return value. + # Solution: Export of all tables by using "*" . Some tables must exist (File Component Directory), other + # tables do not need to exist (MsiAssembly). + + if ( $^O =~ /cygwin/i ) { + # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) + my $localworkdir = $workdir; + $localworkdir =~ s/\//\\\\/g; + $systemcall = $msidb . " -d " . $filename . " -f " . $localworkdir . " -e \\\*"; + } + else + { + # $systemcall = $msidb . " -d " . $filename . " -f " . $workdir . " -e File Component MsiAssembly Directory"; + $systemcall = $msidb . " -d " . $filename . " -f " . $workdir . " -e \*"; + } + + $returnvalue = system($systemcall); + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute $systemcall !\n"; + push( @installer::globals::logfileinfo, $infoline); + installer::exiter::exit_program("ERROR: Could not exclude tables from merge file: $completedest !", "merge_mergemodules_into_msi_database"); + } + else + { + $infoline = "Success: Executed $systemcall successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + # Determining files + my $idtfilename = "File.idt"; # must exist + if ( ! -f $idtfilename ) { installer::exiter::exit_program("ERROR: File \"$idtfilename\" not found in directory \"$workdir\" !", "merge_mergemodules_into_msi_database"); } + my $filecontent = installer::files::read_file($idtfilename); + my @file_idt_content = (); + my $filecounter = 0; + my %mergefilesequence = (); + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if ( $i <= 2 ) { next; } # ignoring first three lines + if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines + $filecounter++; + push(@file_idt_content, ${$filecontent}[$i]); + if ( ${$filecontent}[$i] =~ /^\s*(.+?)\t(.+?)\t(.+?)\t(.+?)\t(.*?)\t(.*?)\t(.*?)\t(\d+?)\s*$/ ) + { + my $filename = $1; + my $filesequence = $8; + $mergefilesequence{$filename} = $filesequence; + } + else + { + my $linecount = $i + 1; + installer::exiter::exit_program("ERROR: Unknown line format in table \"$idtfilename\" (line $linecount) !", "merge_mergemodules_into_msi_database"); + } + } + + # Determining components + $idtfilename = "Component.idt"; # must exist + if ( ! -f $idtfilename ) { installer::exiter::exit_program("ERROR: File \"$idtfilename\" not found in directory \"$workdir\" !", "merge_mergemodules_into_msi_database"); } + $filecontent = installer::files::read_file($idtfilename); + my %componentnames = (); + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if ( $i <= 2 ) { next; } # ignoring first three lines + if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines + if ( ${$filecontent}[$i] =~ /^\s*(\S+)\s+/ ) { $componentnames{$1} = 1; } + } + + # Determining directories + $idtfilename = "Directory.idt"; # must exist + if ( ! -f $idtfilename ) { installer::exiter::exit_program("ERROR: File \"$idtfilename\" not found in directory \"$workdir\" !", "merge_mergemodules_into_msi_database"); } + $filecontent = installer::files::read_file($idtfilename); + my %mergedirectories = (); + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if ( $i <= 2 ) { next; } # ignoring first three lines + if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines + if ( ${$filecontent}[$i] =~ /^\s*(\S+)\s+/ ) { $mergedirectories{$1} = 1; } + } + + # Determining assemblies + $idtfilename = "MsiAssembly.idt"; # does not need to exist + my $hasmsiassemblies = 0; + my %mergeassemblies = (); + if ( -f $idtfilename ) + { + $filecontent = installer::files::read_file($idtfilename); + $hasmsiassemblies = 1; + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if ( $i <= 2 ) { next; } # ignoring first three lines + if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines + if ( ${$filecontent}[$i] =~ /^\s*(\S+)\s+/ ) { $mergeassemblies{$1} = 1; } + } + } + + # It is possible, that other tables have to be checked here. This happens, if tables in the + # merge module have to know the "Feature" or the "Directory", under which the content of the + # msm file is integrated into the msi database. + + # Determining name of cabinet file in installation set + my $cabfilename = $mergemodule->{'Cabfilename'}; + installer::packagelist::resolve_packagevariables(\$cabfilename, $allvariables, 0); + + # Analyzing styles + # Flag REMOVE_FILE_TABLE is required for msvc9 Merge-Module, because otherwise msidb.exe + # fails during integration of msm file into msi database. + + my $styles = ""; + my $removefiletable = 0; + if ( $mergemodule->{'Styles'} ) { $styles = $mergemodule->{'Styles'}; } + if ( $styles =~ /\bREMOVE_FILE_TABLE\b/ ) { $removefiletable = 1; } + + if ( $removefiletable ) + { + my $removeworkdir = $workdir . $installer::globals::separator . "remove_file_idt"; + if ( ! -d $removeworkdir ) { installer::systemactions::create_directory($removeworkdir); } + my $completeremovedest = $removeworkdir . $installer::globals::separator . $filename; + installer::systemactions::copy_one_file($completedest, $completeremovedest); + if ( ! -f $completeremovedest ) { installer::exiter::exit_program("ERROR: msm file not found: $completeremovedest !", "merge_mergemodules_into_msi_database"); } + + # Unpacking msm file + if ( $^O =~ /cygwin/i ) { + # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) + my $localcompleteremovedest = $completeremovedest; + my $localremoveworkdir = $removeworkdir; + $localcompleteremovedest =~ s/\//\\\\/g; + $localremoveworkdir =~ s/\//\\\\/g; + $systemcall = $msidb . " -d " . $localcompleteremovedest . " -f " . $localremoveworkdir . " -e \\\*"; + } + else + { + $systemcall = $msidb . " -d " . $completeremovedest . " -f " . $removeworkdir . " -e \*"; + } + + $returnvalue = system($systemcall); + + my $idtfilename = $removeworkdir . $installer::globals::separator . "File.idt"; + if ( -f $idtfilename ) { unlink $idtfilename; } + unlink $completeremovedest; + + # Packing msm file without "File.idt" + if ( $^O =~ /cygwin/i ) { + # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) + my $localcompleteremovedest = $completeremovedest; + my $localremoveworkdir = $removeworkdir; + $localcompleteremovedest =~ s/\//\\\\/g; + $localremoveworkdir =~ s/\//\\\\/g; + $systemcall = $msidb . " -c -d " . $localcompleteremovedest . " -f " . $localremoveworkdir . " -i \\\*"; + } + else + { + $systemcall = $msidb . " -c -d " . $completeremovedest . " -f " . $removeworkdir . " -i \*"; + } + $returnvalue = system($systemcall); + + # Using this msm file for merging + if ( -f $completeremovedest ) { $completedest = $completeremovedest; } + else { installer::exiter::exit_program("ERROR: Could not find msm file without File.idt: $completeremovedest !", "merge_mergemodules_into_msi_database"); } + } + + # Saving MergeModule info + + my %onemergemodulehash = (); + $onemergemodulehash{'mergefilepath'} = $completedest; + $onemergemodulehash{'workdir'} = $workdir; + $onemergemodulehash{'cabinetfile'} = $workdir . $installer::globals::separator . $cabinetfile; + $onemergemodulehash{'filenumber'} = $filecounter; + $onemergemodulehash{'componentnames'} = \%componentnames; + $onemergemodulehash{'cabfilename'} = $cabfilename; + $onemergemodulehash{'feature'} = $mergemodule->{'Feature'}; + $onemergemodulehash{'rootdir'} = $mergemodule->{'RootDir'}; + $onemergemodulehash{'name'} = $mergemodule->{'Name'}; + $onemergemodulehash{'mergefilesequence'} = \%mergefilesequence; + $onemergemodulehash{'mergeassemblies'} = \%mergeassemblies; + $onemergemodulehash{'mergedirectories'} = \%mergedirectories; + $onemergemodulehash{'hasmsiassemblies'} = $hasmsiassemblies; + $onemergemodulehash{'removefiletable'} = $removefiletable; + $onemergemodulehash{'fileidtcontent'} = \@file_idt_content; + + $installer::globals::mergemodules{$mergegid} = \%onemergemodulehash; + + # Collecting all cab files, to copy them into installation set + $installer::globals::copy_msm_files{$cabfilename} = $onemergemodulehash{'cabinetfile'}; + + chdir($from); + } + + $infoline = "All Merge Modules successfully analyzed\n"; + push( @installer::globals::logfileinfo, $infoline); + + $installer::globals::mergemodules_analyzed = 1; + installer::logger::include_timestamp_into_logfile("\nPerformance Info: Analyzing MergeModules, stop"); + + $infoline = "\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + # 2. Change msi database (has to be done for every msi database -> for every language) + # a. Merge msm file into msi database: msidb.exe -d <msifile> -m <mergefile> + # b. Extracting tables from msi database: msidb.exe -d <msifile> -f <directory> -e File Media, ... + # c. Changing content of msi database in tables: File, Media, Directory, FeatureComponent + # d. Including tables into msi database: msidb.exe -d <msifile> -f <directory> -i File Media, ... + # e. Copying cabinet file into installation set (later) + + my $counter = 0; + my $mergemodulegid; + foreach $mergemodulegid (keys %installer::globals::mergemodules) + { + my $mergemodulehash = $installer::globals::mergemodules{$mergemodulegid}; + $counter++; + + installer::logger::include_header_into_logfile("Merging Module: $mergemodulehash->{'name'}"); + installer::logger::print_message( "\t... $mergemodulehash->{'name'} ... \n" ); + + $msifilename = installer::converter::make_path_conform($msifilename); + my $workdir = $msifilename; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$workdir); + + # changing directory + my $from = cwd(); + my $to = $workdir; + chdir($to); + + # Saving original msi database + installer::systemactions::copy_one_file($msifilename, "$msifilename\.$counter"); + + # Merging msm file, this is the "real" merge command + + installer::logger::include_timestamp_into_logfile("\nPerformance Info: Before merging database"); + + if ( $^O =~ /cygwin/i ) { + # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) + my $localmergemodulepath = $mergemodulehash->{'mergefilepath'}; + my $localmsifilename = $msifilename; + $localmergemodulepath =~ s/\//\\\\/g; + $localmsifilename =~ s/\//\\\\/g; + $systemcall = $msidb . " -d " . $localmsifilename . " -m " . $localmergemodulepath; + } + else + { + $systemcall = $msidb . " -d " . $msifilename . " -m " . $mergemodulehash->{'mergefilepath'}; + } + $returnvalue = system($systemcall); + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute $systemcall . Returnvalue: $returnvalue!\n"; + push( @installer::globals::logfileinfo, $infoline); + installer::exiter::exit_program("ERROR: Could not merge msm file into database: $mergemodulehash->{'mergefilepath'} !", "merge_mergemodules_into_msi_database"); + } + else + { + $infoline = "Success: Executed $systemcall successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + installer::logger::include_timestamp_into_logfile("\nPerformance Info: After merging database"); + + # Saving original idt files + if ( -f "File.idt" ) { installer::systemactions::rename_one_file("File.idt", "File.idt.$counter"); } + if ( -f "Media.idt" ) { installer::systemactions::rename_one_file("Media.idt", "Media.idt.$counter"); } + if ( -f "Directory.idt" ) { installer::systemactions::rename_one_file("Directory.idt", "Directory.idt.$counter"); } + if ( -f "Director.idt" ) { installer::systemactions::rename_one_file("Director.idt", "Director.idt.$counter"); } + if ( -f "FeatureComponents.idt" ) { installer::systemactions::rename_one_file("FeatureComponents.idt", "FeatureComponents.idt.$counter"); } + if ( -f "FeatureC.idt" ) { installer::systemactions::rename_one_file("FeatureC.idt", "FeatureC.idt.$counter"); } + if ( -f "MsiAssembly.idt" ) { installer::systemactions::rename_one_file("MsiAssembly.idt", "MsiAssembly.idt.$counter"); } + if ( -f "MsiAssem.idt" ) { installer::systemactions::rename_one_file("MsiAssem.idt", "MsiAssem.idt.$counter"); } + + # Extracting tables + + installer::logger::include_timestamp_into_logfile("\nPerformance Info: Before extracting tables"); + + my $workingtables = "File Media Directory FeatureComponents"; # required tables + # Optional tables can be added now + if ( $mergemodulehash->{'hasmsiassemblies'} ) { $workingtables = $workingtables . " MsiAssembly"; } + + # Table "Feature" has to be exported, but it is not necessary to import it. + if ( $^O =~ /cygwin/i ) { + # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) + my $localmsifilename = $msifilename; + my $localworkdir = $workdir; + $localmsifilename =~ s/\//\\\\/g; + $localworkdir =~ s/\//\\\\/g; + $systemcall = $msidb . " -d " . $localmsifilename . " -f " . $localworkdir . " -e " . "Feature " . $workingtables; + } + else + { + $systemcall = $msidb . " -d " . $msifilename . " -f " . $workdir . " -e " . "Feature " . $workingtables; + } + $returnvalue = system($systemcall); + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute $systemcall !\n"; + push( @installer::globals::logfileinfo, $infoline); + installer::exiter::exit_program("ERROR: Could not exclude tables from msi database: $msifilename !", "merge_mergemodules_into_msi_database"); + } + else + { + $infoline = "Success: Executed $systemcall successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + installer::logger::include_timestamp_into_logfile("\nPerformance Info: After extracting tables"); + + # Using 8+3 table names, that are used, when tables are integrated into database. The export of tables + # creates idt-files, that have long names. + + if ( -f "Directory.idt" ) { installer::systemactions::rename_one_file("Directory.idt", "Director.idt"); } + if ( -f "FeatureComponents.idt" ) { installer::systemactions::rename_one_file("FeatureComponents.idt", "FeatureC.idt"); } + if ( -f "MsiAssembly.idt" ) { installer::systemactions::rename_one_file("MsiAssembly.idt", "MsiAssem.idt"); } + + # Changing content of tables: File, Media, Directory, FeatureComponent, MsiAssembly + installer::logger::include_timestamp_into_logfile("\nPerformance Info: Changing Media table"); + change_media_table($mergemodulehash, $workdir, $mergemodulegid, $allupdatelastsequences, $allupdatediskids); + installer::logger::include_timestamp_into_logfile("\nPerformance Info: Changing File table"); + $filesref = change_file_table($mergemodulehash, $workdir, $allupdatesequences, $includepatharrayref, $filesref, $mergemodulegid); + installer::logger::include_timestamp_into_logfile("\nPerformance Info: Changing FeatureComponent table"); + change_featurecomponent_table($mergemodulehash, $workdir); + installer::logger::include_timestamp_into_logfile("\nPerformance Info: Changing Directory table"); + change_directory_table($mergemodulehash, $workdir); + if ( $mergemodulehash->{'hasmsiassemblies'} ) + { + installer::logger::include_timestamp_into_logfile("\nPerformance Info: Changing MsiAssembly table"); + change_msiassembly_table($mergemodulehash, $workdir); + } + + # msidb.exe does not merge InstallExecuteSequence, AdminExecuteSequence and AdvtExecuteSequence. Instead it creates + # new tables ModuleInstallExecuteSequence, ModuleAdminExecuteSequence and ModuleAdvtExecuteSequence that need to be + # merged into the three ExecuteSequences with the following process (also into InstallUISequence.idt). + + # Saving original idt files + if ( -f "InstallE.idt" ) { installer::systemactions::rename_one_file("InstallE.idt", "InstallE.idt.$counter"); } + if ( -f "InstallU.idt" ) { installer::systemactions::rename_one_file("InstallU.idt", "InstallU.idt.$counter"); } + if ( -f "AdminExe.idt" ) { installer::systemactions::rename_one_file("AdminExe.idt", "AdminExe.idt.$counter"); } + if ( -f "AdvtExec.idt" ) { installer::systemactions::rename_one_file("AdvtExec.idt", "AdvtExec.idt.$counter"); } + if ( -f "ModuleInstallExecuteSequence.idt" ) { installer::systemactions::rename_one_file("ModuleInstallExecuteSequence.idt", "ModuleInstallExecuteSequence.idt.$counter"); } + if ( -f "ModuleAdminExecuteSequence.idt" ) { installer::systemactions::rename_one_file("ModuleAdminExecuteSequence.idt", "ModuleAdminExecuteSequence.idt.$counter"); } + if ( -f "ModuleAdvtExecuteSequence.idt" ) { installer::systemactions::rename_one_file("ModuleAdvtExecuteSequence.idt", "ModuleAdvtExecuteSequence.idt.$counter"); } + + # Extracting tables + my $moduleexecutetables = "ModuleInstallExecuteSequence ModuleAdminExecuteSequence ModuleAdvtExecuteSequence"; # new tables + my $executetables = "InstallExecuteSequence InstallUISequence AdminExecuteSequence AdvtExecuteSequence"; # tables to be merged + + + if ( $^O =~ /cygwin/i ) { + # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) + my $localmsifilename = $msifilename; + my $localworkdir = $workdir; + $localmsifilename =~ s/\//\\\\/g; + $localworkdir =~ s/\//\\\\/g; + $systemcall = $msidb . " -d " . $localmsifilename . " -f " . $localworkdir . " -e " . "Feature " . $moduleexecutetables; + } + else + { + $systemcall = $msidb . " -d " . $msifilename . " -f " . $workdir . " -e " . "Feature " . $moduleexecutetables; + } + $returnvalue = system($systemcall); + + if ( $^O =~ /cygwin/i ) { + # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) + my $localmsifilename = $msifilename; + my $localworkdir = $workdir; + $localmsifilename =~ s/\//\\\\/g; + $localworkdir =~ s/\//\\\\/g; + $systemcall = $msidb . " -d " . $localmsifilename . " -f " . $localworkdir . " -e " . "Feature " . $executetables; + } + else + { + $systemcall = $msidb . " -d " . $msifilename . " -f " . $workdir . " -e " . "Feature " . $executetables; + } + $returnvalue = system($systemcall); + + # Using 8+3 table names, that are used, when tables are integrated into database. The export of tables + # creates idt-files, that have long names. + + if ( -f "InstallExecuteSequence.idt" ) { installer::systemactions::rename_one_file("InstallExecuteSequence.idt", "InstallE.idt"); } + if ( -f "InstallUISequence.idt" ) { installer::systemactions::rename_one_file("InstallUISequence.idt", "InstallU.idt"); } + if ( -f "AdminExecuteSequence.idt" ) { installer::systemactions::rename_one_file("AdminExecuteSequence.idt", "AdminExe.idt"); } + if ( -f "AdvtExecuteSequence.idt" ) { installer::systemactions::rename_one_file("AdvtExecuteSequence.idt", "AdvtExec.idt"); } + + # Merging content of tables ModuleInstallExecuteSequence, ModuleAdminExecuteSequence and ModuleAdvtExecuteSequence + # into tables InstallExecuteSequence, AdminExecuteSequence and AdvtExecuteSequence + if ( -f "ModuleInstallExecuteSequence.idt" ) + { + installer::logger::include_timestamp_into_logfile("\nPerformance Info: Changing InstallExecuteSequence table"); + change_executesequence_table($mergemodulehash, $workdir, "InstallE.idt", "ModuleInstallExecuteSequence.idt"); + installer::logger::include_timestamp_into_logfile("\nPerformance Info: Changing InstallUISequence table"); + change_executesequence_table($mergemodulehash, $workdir, "InstallU.idt", "ModuleInstallExecuteSequence.idt"); + } + + if ( -f "ModuleAdminExecuteSequence.idt" ) + { + installer::logger::include_timestamp_into_logfile("\nPerformance Info: Changing AdminExecuteSequence table"); + change_executesequence_table($mergemodulehash, $workdir, "AdminExe.idt", "ModuleAdminExecuteSequence.idt"); + } + + if ( -f "ModuleAdvtExecuteSequence.idt" ) + { + installer::logger::include_timestamp_into_logfile("\nPerformance Info: Changing AdvtExecuteSequence table"); + change_executesequence_table($mergemodulehash, $workdir, "AdvtExec.idt", "ModuleAdvtExecuteSequence.idt"); + } + + installer::logger::include_timestamp_into_logfile("\nPerformance Info: All tables edited"); + + # Including tables into msi database + + installer::logger::include_timestamp_into_logfile("\nPerformance Info: Before including tables"); + + if ( $^O =~ /cygwin/i ) { + # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) + my $localmsifilename = $msifilename; + my $localworkdir = $workdir; + $localmsifilename =~ s/\//\\\\/g; + $localworkdir =~ s/\//\\\\/g; + $systemcall = $msidb . " -d " . $localmsifilename . " -f " . $localworkdir . " -i " . $workingtables. " " . $executetables; + } + else + { + $systemcall = $msidb . " -d " . $msifilename . " -f " . $workdir . " -i " . $workingtables. " " . $executetables; + } + $returnvalue = system($systemcall); + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute $systemcall !\n"; + push( @installer::globals::logfileinfo, $infoline); + installer::exiter::exit_program("ERROR: Could not include tables into msi database: $msifilename !", "merge_mergemodules_into_msi_database"); + } + else + { + $infoline = "Success: Executed $systemcall successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + installer::logger::include_timestamp_into_logfile("\nPerformance Info: After including tables"); + + chdir($from); + } + + if ( ! $installer::globals::mergefiles_added_into_collector ) { $installer::globals::mergefiles_added_into_collector = 1; } # Now all mergemodules are merged for one language. + + installer::logger::include_timestamp_into_logfile("\nPerformance Info: MergeModule into msi database, stop"); + } + + return $filesref; +} + +######################################################################### +# Analyzing the content of the media table. +######################################################################### + +sub analyze_media_file +{ + my ($filecontent, $workdir) = @_; + + my %filehash = (); + my $linecount = 0; + my $counter = 0; + my $filename = "Media.idt"; + + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if ( $i <= 2 ) { next; } # ignoring first three lines + if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines + if ( ${$filecontent}[$i] =~ /^\s*(.+?)\t(.+?)\t(.+?)\t(.+?)\t(.+?)\t(.*?)\s*$/ ) + { + my %line = (); + # Format: DiskId LastSequence DiskPrompt Cabinet VolumeLabel Source + $line{'DiskId'} = $1; + $line{'LastSequence'} = $2; + $line{'DiskPrompt'} = $3; + $line{'Cabinet'} = $4; + $line{'VolumeLabel'} = $5; + $line{'Source'} = $6; + + $counter++; + $filehash{$counter} = \%line; + } + else + { + $linecount = $i + 1; + installer::exiter::exit_program("ERROR: Unknown line format in table \"$filename\" in \"$workdir\" (line $linecount) !", "analyze_media_file"); + } + } + + return \%filehash; +} + +######################################################################### +# Setting the DiskID for the new cabinet file +######################################################################### + +sub get_diskid +{ + my ($mediafile, $allupdatediskids, $cabfilename) = @_; + + my $diskid = 0; + my $line; + + if (( $installer::globals::updatedatabase ) && ( exists($allupdatediskids->{$cabfilename}) )) + { + $diskid = $allupdatediskids->{$cabfilename}; + } + else + { + foreach $line ( keys %{$mediafile} ) + { + if ( $mediafile->{$line}->{'DiskId'} > $diskid ) { $diskid = $mediafile->{$line}->{'DiskId'}; } + } + + $diskid++; + } + + return $diskid; +} + +######################################################################### +# Setting the global LastSequence variable +######################################################################### + +sub set_current_last_sequence +{ + my ($mediafile) = @_; + + my $lastsequence = 0; + my $line; + foreach $line ( keys %{$mediafile} ) + { + if ( $mediafile->{$line}->{'LastSequence'} > $lastsequence ) { $lastsequence = $mediafile->{$line}->{'LastSequence'}; } + } + + $installer::globals::lastsequence_before_merge = $lastsequence; +} + +######################################################################### +# Setting the LastSequence for the new cabinet file +######################################################################### + +sub get_lastsequence +{ + my ($mergemodulehash, $allupdatelastsequences) = @_; + + my $lastsequence = 0; + + if (( $installer::globals::updatedatabase ) && ( exists($allupdatelastsequences->{$mergemodulehash->{'cabfilename'}}) )) + { + $lastsequence = $allupdatelastsequences->{$mergemodulehash->{'cabfilename'}}; + } + else + { + $lastsequence = $installer::globals::lastsequence_before_merge + $mergemodulehash->{'filenumber'}; + } + + return $lastsequence; +} + +######################################################################### +# Setting the DiskPrompt for the new cabinet file +######################################################################### + +sub get_diskprompt +{ + my ($mediafile) = @_; + + my $diskprompt = ""; + my $line; + foreach $line ( keys %{$mediafile} ) + { + if ( exists($mediafile->{$line}->{'DiskPrompt'}) ) + { + $diskprompt = $mediafile->{$line}->{'DiskPrompt'}; + last; + } + } + + return $diskprompt; +} + +######################################################################### +# Setting the VolumeLabel for the new cabinet file +######################################################################### + +sub get_volumelabel +{ + my ($mediafile) = @_; + + my $volumelabel = ""; + my $line; + foreach $line ( keys %{$mediafile} ) + { + if ( exists($mediafile->{$line}->{'VolumeLabel'}) ) + { + $volumelabel = $mediafile->{$line}->{'VolumeLabel'}; + last; + } + } + + return $volumelabel; +} + +######################################################################### +# Setting the Source for the new cabinet file +######################################################################### + +sub get_source +{ + my ($mediafile) = @_; + + my $source = ""; + my $line; + foreach $line ( keys %{$mediafile} ) + { + if ( exists($mediafile->{$line}->{'Source'}) ) + { + $diskprompt = $mediafile->{$line}->{'Source'}; + last; + } + } + + return $source; +} + +######################################################################### +# For each Merge Module one new line has to be included into the +# media table. +######################################################################### + +sub create_new_media_line +{ + my ($mergemodulehash, $mediafile, $allupdatelastsequences, $allupdatediskids) = @_; + + my $diskid = get_diskid($mediafile, $allupdatediskids, $mergemodulehash->{'cabfilename'}); + my $lastsequence = get_lastsequence($mergemodulehash, $allupdatelastsequences); + my $diskprompt = get_diskprompt($mediafile); + my $cabinet = $mergemodulehash->{'cabfilename'}; + my $volumelabel = get_volumelabel($mediafile); + my $source = get_source($mediafile); + + if ( $installer::globals::include_cab_in_msi ) { $cabinet = "\#" . $cabinet; } + + my $newline = "$diskid\t$lastsequence\t$diskprompt\t$cabinet\t$volumelabel\t$source\n"; + + return $newline; +} + +######################################################################### +# Setting the last diskid in media table. +######################################################################### + +sub get_last_diskid +{ + my ($mediafile) = @_; + + my $lastdiskid = 0; + my $line; + foreach $line ( keys %{$mediafile} ) + { + if ( $mediafile->{$line}->{'DiskId'} > $lastdiskid ) { $lastdiskid = $mediafile->{$line}->{'DiskId'}; } + } + + return $lastdiskid; +} + +######################################################################### +# Setting global variable for last cab file name. +######################################################################### + +sub set_last_cabfile_name +{ + my ($mediafile, $lastdiskid) = @_; + + my $line; + foreach $line ( keys %{$mediafile} ) + { + if ( $mediafile->{$line}->{'DiskId'} == $lastdiskid ) { $installer::globals::lastcabfilename = $mediafile->{$line}->{'Cabinet'}; } + } + my $infoline = "Setting last cabinet file: $installer::globals::lastcabfilename\n"; + push( @installer::globals::logfileinfo, $infoline); +} + +######################################################################### +# In the media table the new cabinet file has to be added or the +# number of the last cabinet file has to be increased. +######################################################################### + +sub change_media_table +{ + my ( $mergemodulehash, $workdir, $mergemodulegid, $allupdatelastsequences, $allupdatediskids ) = @_; + + my $infoline = "Changing content of table \"Media\"\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $filename = "Media.idt"; + if ( ! -f $filename ) { installer::exiter::exit_program("ERROR: Could not find file \"$filename\" in \"$workdir\" !", "change_media_table"); } + + my $filecontent = installer::files::read_file($filename); + my $mediafile = analyze_media_file($filecontent, $workdir); + set_current_last_sequence($mediafile); + + if ( $installer::globals::fix_number_of_cab_files ) + { + # Determining the line with the highest sequencenumber. That file needs to be updated. + my $lastdiskid = get_last_diskid($mediafile); + if ( $installer::globals::lastcabfilename eq "" ) { set_last_cabfile_name($mediafile, $lastdiskid); } + my $newmaxsequencenumber = $installer::globals::lastsequence_before_merge + $mergemodulehash->{'filenumber'}; + + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if ( $i <= 2 ) { next; } # ignoring first three lines + if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines + if ( ${$filecontent}[$i] =~ /^\s*(\Q$lastdiskid\E\t)\Q$installer::globals::lastsequence_before_merge\E(\t.*)$/ ) + { + my $start = $1; + my $final = $2; + $infoline = "Merge: Old line in media table: ${$filecontent}[$i]\n"; + push( @installer::globals::logfileinfo, $infoline); + my $newline = $start . $newmaxsequencenumber . $final . "\n"; + ${$filecontent}[$i] = $newline; + $infoline = "Merge: Changed line in media table: ${$filecontent}[$i]\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + } + else + { + # the new line is identical for all localized databases, but has to be created for each MergeModule ($mergemodulegid) + if ( ! exists($installer::globals::merge_media_line{$mergemodulegid}) ) + { + $installer::globals::merge_media_line{$mergemodulegid} = create_new_media_line($mergemodulehash, $mediafile, $allupdatelastsequences, $allupdatediskids); + } + + $infoline = "Adding line: $installer::globals::merge_media_line{$mergemodulegid}\n"; + push( @installer::globals::logfileinfo, $infoline); + + # adding new line + push(@{$filecontent}, $installer::globals::merge_media_line{$mergemodulegid}); + } + + # saving file + installer::files::save_file($filename, $filecontent); +} + +######################################################################### +# Putting the directory table content into a hash. +######################################################################### + +sub analyze_directorytable_file +{ + my ($filecontent, $idtfilename) = @_; + + my %dirhash = (); + # Iterating over the file content + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if ( $i <= 2 ) { next; } # ignoring first three lines + if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines + if ( ${$filecontent}[$i] =~ /^\s*(.+?)\t(.*?)\t(.*?)\s*$/ ) + { + my %line = (); + # Format: Directory Directory_Parent DefaultDir + $line{'Directory'} = $1; + $line{'Directory_Parent'} = $2; + $line{'DefaultDir'} = $3; + $line{'linenumber'} = $i; # saving also the line number for direct access + + my $uniquekey = $line{'Directory'}; + $dirhash{$uniquekey} = \%line; + } + else + { + my $linecount = $i + 1; + installer::exiter::exit_program("ERROR: Unknown line format in table \"$idtfilename\" (line $linecount) !", "analyze_directorytable_file"); + } + } + + return \%dirhash; +} + +######################################################################### +# Putting the msi assembly table content into a hash. +######################################################################### + +sub analyze_msiassemblytable_file +{ + my ($filecontent, $idtfilename) = @_; + + my %assemblyhash = (); + # Iterating over the file content + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if ( $i <= 2 ) { next; } # ignoring first three lines + if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines + if ( ${$filecontent}[$i] =~ /^\s*(.+?)\t(.+?)\t(.+?)\t(.*?)\t(.*?)\s*$/ ) + { + my %line = (); + # Format: Component_ Feature_ File_Manifest File_Application Attributes + $line{'Component'} = $1; + $line{'Feature'} = $2; + $line{'File_Manifest'} = $3; + $line{'File_Application'} = $4; + $line{'Attributes'} = $5; + $line{'linenumber'} = $i; # saving also the line number for direct access + + my $uniquekey = $line{'Component'}; + $assemblyhash{$uniquekey} = \%line; + } + else + { + my $linecount = $i + 1; + installer::exiter::exit_program("ERROR: Unknown line format in table \"$idtfilename\" (line $linecount) !", "analyze_msiassemblytable_file"); + } + } + + return \%assemblyhash; +} + +######################################################################### +# Putting the file table content into a hash. +######################################################################### + +sub analyze_filetable_file +{ + my ( $filecontent, $idtfilename ) = @_; + + my %filehash = (); + # Iterating over the file content + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if ( $i <= 2 ) { next; } # ignoring first three lines + if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines + if ( ${$filecontent}[$i] =~ /^\s*(.+?)\t(.+?)\t(.+?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.+?)\s*$/ ) + { + my %line = (); + # Format: File Component_ FileName FileSize Version Language Attributes Sequence + $line{'File'} = $1; + $line{'Component'} = $2; + $line{'FileName'} = $3; + $line{'FileSize'} = $4; + $line{'Version'} = $5; + $line{'Language'} = $6; + $line{'Attributes'} = $7; + $line{'Sequence'} = $8; + $line{'linenumber'} = $i; # saving also the line number for direct access + + my $uniquekey = $line{'File'}; + $filehash{$uniquekey} = \%line; + } + else + { + my $linecount = $i + 1; + installer::exiter::exit_program("ERROR: Unknown line format in table \"$idtfilename\" (line $linecount) !", "analyze_filetable_file"); + } + } + + return \%filehash; +} + +######################################################################### +# Creating a new line for the directory table. +######################################################################### + +sub get_new_line_for_directory_table +{ + my ($dir) = @_; + + my $newline = "$dir->{'Directory'}\t$dir->{'Directory_Parent'}\t$dir->{'DefaultDir'}\n"; + + return $newline; +} + +######################################################################### +# Creating a new line for the file table. +######################################################################### + +sub get_new_line_for_file_table +{ + my ($file) = @_; + + my $newline = "$file->{'File'}\t$file->{'Component'}\t$file->{'FileName'}\t$file->{'FileSize'}\t$file->{'Version'}\t$file->{'Language'}\t$file->{'Attributes'}\t$file->{'Sequence'}\n"; + + return $newline; +} + +######################################################################### +# Creating a new line for the msiassembly table. +######################################################################### + +sub get_new_line_for_msiassembly_table +{ + my ($assembly) = @_; + + my $newline = "$assembly->{'Component'}\t$assembly->{'Feature'}\t$assembly->{'File_Manifest'}\t$assembly->{'File_Application'}\t$assembly->{'Attributes'}\n"; + + return $newline; +} + +######################################################################### +# Sorting the files collector, if there are files, following +# the merge module files. +######################################################################### + +sub sort_files_collector_for_sequence +{ + my ($filesref) = @_; + + my @sortarray = (); + my %helphash = (); + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + if ( ! exists($onefile->{'sequencenumber'}) ) { installer::exiter::exit_program("ERROR: Could not find sequencenumber for file: $onefile->{'uniquename'} !", "sort_files_collector_for_sequence"); } + my $sequence = $onefile->{'sequencenumber'}; + $helphash{$sequence} = $onefile; + } + + foreach my $seq ( sort { $a <=> $b } keys %helphash ) { push(@sortarray, $helphash{$seq}); } + + return \@sortarray; +} + +######################################################################### +# In the file table "Sequence" and "Attributes" have to be changed. +######################################################################### + +sub change_file_table +{ + my ($mergemodulehash, $workdir, $allupdatesequenceshashref, $includepatharrayref, $filesref, $mergemodulegid) = @_; + + my $infoline = "Changing content of table \"File\"\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $idtfilename = "File.idt"; + if ( ! -f $idtfilename ) { installer::exiter::exit_program("ERROR: Could not find file \"$idtfilename\" in \"$workdir\" !", "change_file_table"); } + + my $filecontent = installer::files::read_file($idtfilename); + + # If File.idt needed to be removed before the msm database was merged into the msi database, + # now it is time to add the content into File.idt + if ( $mergemodulehash->{'removefiletable'} ) + { + for ( my $i = 0; $i <= $#{$mergemodulehash->{'fileidtcontent'}}; $i++ ) + { + push(@{$filecontent}, ${$mergemodulehash->{'fileidtcontent'}}[$i]); + } + } + + # Unpacking the MergeModule.CABinet (only once) + # Unpacking into temp directory. Warning: expand.exe has problems with very long unpack directories. + + my $unpackdir = installer::systemactions::create_directories("cab", ""); + push(@installer::globals::removedirs, $unpackdir); + $unpackdir = $unpackdir . $installer::globals::separator . $mergemodulegid; + + my %newfileshash = (); + if (( $installer::globals::fix_number_of_cab_files ) && ( ! $installer::globals::mergefiles_added_into_collector )) + { + if ( ! -d $unpackdir ) { installer::systemactions::create_directory($unpackdir); } + + # Unpack the cab file, so that in can be included into the last office cabinet file. Attention: cararc.exe from cabsdk required. + # cabarc.exe -o X <fullcabfilepath> + + # my $cabarcfilename = "cabarc.exe"; + # my $cabarcfile = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$cabarcfilename, $includepatharrayref, 1); + + # if ( ! -f $$cabarcfile ) + # { + # $cabarcfilename = "CABARC.EXE"; + # $cabarcfile = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$cabarcfilename, $includepatharrayref, 1); + # if ( ! -f $$cabarcfile ) + # { + # installer::exiter::exit_program("ERROR: cabarc.exe not found !", "change_file_table"); + # } + # } + # my $cabarc = $$cabarcfile; + + # changing directory + my $from = cwd(); + my $to = $mergemodulehash->{'workdir'}; + if ( $^O =~ /cygwin/i ) { + $to = qx(cygpath -u "$to"); + chomp $to; + } + + chdir($to) || die "Could not chdir to \"$to\"\n"; + + # Unpack the cab file, so that in can be included into the last office cabinet file. + # Not using cabarc.exe from cabsdk for unpacking cabinet files, but "expand.exe" that + # should be available on every Windows system. + + $infoline = "Unpacking cabinet file: $mergemodulehash->{'cabinetfile'}\n"; + push( @installer::globals::logfileinfo, $infoline); + + # Avoid the Cygwin expand command + my $expandfile = "expand.exe"; # Has to be in the path + if ( $^O =~ /cygwin/i ) { + $expandfile = qx(cygpath -u "$ENV{WINDIR}"/System32/expand.exe); + chomp $expandfile; + } + + my $cabfilename = "MergeModule.CABinet"; + + # exclude cabinet file + # my $systemcall = $cabarc . " -o X " . $mergemodulehash->{'cabinetfile'}; + + my $systemcall = ""; + if ( $^O =~ /cygwin/i ) { + my $localunpackdir = qx(cygpath -m "$unpackdir"); + chomp $localunpackdir; + $systemcall = $expandfile . " " . $cabfilename . " -F:\\\* " . $localunpackdir; + } + else + { + $systemcall = $expandfile . " " . $cabfilename . " -F:\* " . $unpackdir . " 2\>\&1"; + } + + my $returnvalue = system($systemcall); + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute $systemcall !\n"; + push( @installer::globals::logfileinfo, $infoline); + installer::exiter::exit_program("ERROR: Could not extract cabinet file: $mergemodulehash->{'cabinetfile'} !", "change_file_table"); + } + else + { + $infoline = "Success: Executed $systemcall successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + chdir($from); + } + + # For performance reasons creating a hash with file names and rows + # The content of File.idt is changed after every merge -> content cannot be saved in global hash + $merge_filetablehashref = analyze_filetable_file($filecontent, $idtfilename); + + my $attributes = "16384"; # Always + + my $filename; + foreach $filename (keys %{$mergemodulehash->{'mergefilesequence'}} ) + { + my $mergefilesequence = $mergemodulehash->{'mergefilesequence'}->{$filename}; + + if ( ! exists($merge_filetablehashref->{$filename}) ) { installer::exiter::exit_program("ERROR: Could not find file \"$filename\" in \"$idtfilename\" !", "change_file_table"); } + my $filehash = $merge_filetablehashref->{$filename}; + my $linenumber = $filehash->{'linenumber'}; + + # <- this line has to be changed concerning "Sequence" and "Attributes" + $filehash->{'Attributes'} = $attributes; + + # If this is an update process, the sequence numbers have to be reused. + if ( $installer::globals::updatedatabase ) + { + if ( ! exists($allupdatesequenceshashref->{$filehash->{'File'}}) ) { installer::exiter::exit_program("ERROR: Sequence not defined for file \"$filehash->{'File'}\" !", "change_file_table"); } + $filehash->{'Sequence'} = $allupdatesequenceshashref->{$filehash->{'File'}}; + # Saving all mergemodule sequence numbers. This is important for creating ddf files + $installer::globals::allmergemodulefilesequences{$filehash->{'Sequence'}} = 1; + } + else + { + # Important saved data: $installer::globals::lastsequence_before_merge. + # This mechanism keeps the correct order inside the new cabinet file. + $filehash->{'Sequence'} = $filehash->{'Sequence'} + $installer::globals::lastsequence_before_merge; + } + + my $oldline = ${$filecontent}[$linenumber]; + my $newline = get_new_line_for_file_table($filehash); + ${$filecontent}[$linenumber] = $newline; + + $infoline = "Merge, replacing line:\n"; + push( @installer::globals::logfileinfo, $infoline); + $infoline = "Old: $oldline\n"; + push( @installer::globals::logfileinfo, $infoline); + $infoline = "New: $newline\n"; + push( @installer::globals::logfileinfo, $infoline); + + # Adding files to the files collector (but only once) + if (( $installer::globals::fix_number_of_cab_files ) && ( ! $installer::globals::mergefiles_added_into_collector )) + { + # If the number of cabinet files is kept constant, + # all files from the mergemodule cabinet files will + # be integrated into the last office cabinet file + # (installer::globals::lastcabfilename). + # Therefore the files must now be added to the filescollector, + # so that they will be integrated into the ddf files. + + # Problem with very long filenames -> copying to shorter filenames + my $newfilename = "f" . $filehash->{'Sequence'}; + my $completesource = $unpackdir . $installer::globals::separator . $filehash->{'File'}; + my $completedest = $unpackdir . $installer::globals::separator . $newfilename; + installer::systemactions::copy_one_file($completesource, $completedest); + + my $locallastcabfilename = $installer::globals::lastcabfilename; + if ( $locallastcabfilename =~ /^\s*\#/ ) { $locallastcabfilename =~ s/^\s*\#//; } # removing beginning hashes + + # Create new file hash for file collector + my %newfile = (); + $newfile{'sequencenumber'} = $filehash->{'Sequence'}; + $newfile{'assignedsequencenumber'} = $filehash->{'Sequence'}; + $newfile{'cabinet'} = $locallastcabfilename; + $newfile{'sourcepath'} = $completedest; + $newfile{'componentname'} = $filehash->{'Component'}; + $newfile{'uniquename'} = $filehash->{'File'}; + $newfile{'Name'} = $filehash->{'File'}; + + # Saving in globals sequence hash + $installer::globals::uniquefilenamesequence{$filehash->{'File'}} = $filehash->{'Sequence'}; + + if ( ! -f $newfile{'sourcepath'} ) { installer::exiter::exit_program("ERROR: File \"$newfile{'sourcepath'}\" must exist!", "change_file_table"); } + + # Collecting all new files. Attention: This files must be included into files collector in correct order! + $newfileshash{$filehash->{'Sequence'}} = \%newfile; + # push(@{$filesref}, \%newfile); -> this is not the correct order + } + } + + # Now the files can be added to the files collector + # In the case of an update process, there can be new files, that have to be added after the merge module files. + # Warning: In multilingual installation sets, the files only have to be added once to the files collector! + + if ( ! $installer::globals::mergefiles_added_into_collector ) + { + foreach my $localsequence ( sort { $a <=> $b } keys %newfileshash ) { push(@{$filesref}, $newfileshash{$localsequence}); } + if ( $installer::globals::newfilesexist ) { $filesref = sort_files_collector_for_sequence($filesref); } + # $installer::globals::mergefiles_added_into_collector = 1; -> Not yet. Only if all mergemodules are merged for one language. + } + + # Saving the idt file (for every language) + installer::files::save_file($idtfilename, $filecontent); + + return $filesref; +} + +######################################################################### +# Reading the file "Director.idt". The Directory, that is defined in scp +# has to be defined in this table. +######################################################################### + +sub collect_directories +{ + my $idtfilename = "Director.idt"; + my $filecontent = installer::files::read_file($idtfilename); + + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if ( $i <= 2 ) { next; } # ignoring first three lines + if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines + # Format: Directory Directory_Parent DefaultDir + if ( ${$filecontent}[$i] =~ /^\s*(.+?)\t(.*?)\t(.*?)\s*$/ ) + { + $installer::globals::merge_alldirectory_hash{$1} = 1; + } + else + { + my $linecount = $i + 1; + installer::exiter::exit_program("ERROR: Unknown line format in table \"$idtfilename\" (line $linecount) !", "collect_directories"); + } + } +} + +######################################################################### +# Reading the file "Feature.idt". The Feature, that is defined in scp +# has to be defined in this table. +######################################################################### + +sub collect_feature +{ + my $idtfilename = "Feature.idt"; + if ( ! -f $idtfilename ) { installer::exiter::exit_program("ERROR: Could not find file \"$idtfilename\" in \"$workdir\" !", "collect_feature"); } + my $filecontent = installer::files::read_file($idtfilename); + + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if ( $i <= 2 ) { next; } # ignoring first three lines + if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines + # Format: Feature Feature_Parent Title Description Display Level Directory_ Attributes + if ( ${$filecontent}[$i] =~ /^\s*(.+?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) + { + $installer::globals::merge_allfeature_hash{$1} = 1; + } + else + { + my $linecount = $i + 1; + installer::exiter::exit_program("ERROR: Unknown line format in table \"$idtfilename\" (line $linecount) !", "collect_feature"); + } + } +} + +######################################################################### +# In the featurecomponent table, the new connections have to be added. +######################################################################### + +sub change_featurecomponent_table +{ + my ($mergemodulehash, $workdir) = @_; + + my $infoline = "Changing content of table \"FeatureComponents\"\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $idtfilename = "FeatureC.idt"; + if ( ! -f $idtfilename ) { installer::exiter::exit_program("ERROR: Could not find file \"$idtfilename\" in \"$workdir\" !", "change_featurecomponent_table"); } + + my $filecontent = installer::files::read_file($idtfilename); + + # Simply adding for each new component one line. The Feature has to be defined in scp project. + my $feature = $mergemodulehash->{'feature'}; + + if ( ! $installer::globals::mergefeaturecollected ) + { + collect_feature(); # putting content into hash %installer::globals::merge_allfeature_hash + $installer::globals::mergefeaturecollected = 1; + } + + if ( ! exists($installer::globals::merge_allfeature_hash{$feature}) ) + { + installer::exiter::exit_program("ERROR: Unknown feature defined in scp: \"$feature\" . Not defined in table \"Feature\" !", "change_featurecomponent_table"); + } + + my $component; + foreach $component ( keys %{$mergemodulehash->{'componentnames'}} ) + { + my $line = "$feature\t$component\n"; + push(@{$filecontent}, $line); + $infoline = "Adding line: $line\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + # saving file + installer::files::save_file($idtfilename, $filecontent); +} + +######################################################################### +# In the directory table, the directory parent has to be changed, +# if it is not TARGETDIR. +######################################################################### + +sub change_directory_table +{ + my ($mergemodulehash, $workdir) = @_; + + # directory for MergeModule has to be defined in scp project + my $scpdirectory = $mergemodulehash->{'rootdir'}; + + if ( $scpdirectory ne "TARGETDIR" ) # TARGETDIR works fine, when using msidb.exe + { + my $infoline = "Changing content of table \"Directory\"\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $idtfilename = "Director.idt"; + if ( ! -f $idtfilename ) { installer::exiter::exit_program("ERROR: Could not find file \"$idtfilename\" in \"$workdir\" !", "change_directory_table"); } + + my $filecontent = installer::files::read_file($idtfilename); + + if ( ! $installer::globals::mergedirectoriescollected ) + { + collect_directories(); # putting content into %installer::globals::merge_alldirectory_hash, only first column! + $installer::globals::mergedirectoriescollected = 1; + } + + if ( ! exists($installer::globals::merge_alldirectory_hash{$scpdirectory}) ) + { + installer::exiter::exit_program("ERROR: Unknown directory defined in scp: \"$scpdirectory\" . Not defined in table \"Directory\" !", "change_directory_table"); + } + + # If the definition in scp is okay, now the complete content of "Director.idt" can be analyzed + my $merge_directorytablehashref = analyze_directorytable_file($filecontent, $idtfilename); + + my $directory; + foreach $directory (keys %{$mergemodulehash->{'mergedirectories'}} ) + { + if ( ! exists($merge_directorytablehashref->{$directory}) ) { installer::exiter::exit_program("ERROR: Could not find directory \"$directory\" in \"$idtfilename\" !", "change_directory_table"); } + my $dirhash = $merge_directorytablehashref->{$directory}; + my $linenumber = $dirhash->{'linenumber'}; + + # <- this line has to be changed concerning "Directory_Parent", + # if the current value is "TARGETDIR", which is the default value from msidb.exe + + if ( $dirhash->{'Directory_Parent'} eq "TARGETDIR" ) + { + $dirhash->{'Directory_Parent'} = $scpdirectory; + + my $oldline = ${$filecontent}[$linenumber]; + my $newline = get_new_line_for_directory_table($dirhash); + ${$filecontent}[$linenumber] = $newline; + + $infoline = "Merge, replacing line:\n"; + push( @installer::globals::logfileinfo, $infoline); + $infoline = "Old: $oldline\n"; + push( @installer::globals::logfileinfo, $infoline); + $infoline = "New: $newline\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + + # saving file + installer::files::save_file($idtfilename, $filecontent); + } +} + +######################################################################### +# In the msiassembly table, the feature has to be changed. +######################################################################### + +sub change_msiassembly_table +{ + my ($mergemodulehash, $workdir) = @_; + + my $infoline = "Changing content of table \"MsiAssembly\"\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $idtfilename = "MsiAssem.idt"; + if ( ! -f $idtfilename ) { installer::exiter::exit_program("ERROR: Could not find file \"$idtfilename\" in \"$workdir\" !", "change_msiassembly_table"); } + + my $filecontent = installer::files::read_file($idtfilename); + + # feature has to be defined in scp project + my $feature = $mergemodulehash->{'feature'}; + + if ( ! $installer::globals::mergefeaturecollected ) + { + collect_feature(); # putting content into hash %installer::globals::merge_allfeature_hash + $installer::globals::mergefeaturecollected = 1; + } + + if ( ! exists($installer::globals::merge_allfeature_hash{$feature}) ) + { + installer::exiter::exit_program("ERROR: Unknown feature defined in scp: \"$feature\" . Not defined in table \"Feature\" !", "change_msiassembly_table"); + } + + my $merge_msiassemblytablehashref = analyze_msiassemblytable_file($filecontent, $idtfilename); + + my $component; + foreach $component (keys %{$mergemodulehash->{'mergeassemblies'}} ) + { + if ( ! exists($merge_msiassemblytablehashref->{$component}) ) { installer::exiter::exit_program("ERROR: Could not find component \"$component\" in \"$idtfilename\" !", "change_msiassembly_table"); } + my $assemblyhash = $merge_msiassemblytablehashref->{$component}; + my $linenumber = $assemblyhash->{'linenumber'}; + + # <- this line has to be changed concerning "Feature" + $assemblyhash->{'Feature'} = $feature; + + my $oldline = ${$filecontent}[$linenumber]; + my $newline = get_new_line_for_msiassembly_table($assemblyhash); + ${$filecontent}[$linenumber] = $newline; + + $infoline = "Merge, replacing line:\n"; + push( @installer::globals::logfileinfo, $infoline); + $infoline = "Old: $oldline\n"; + push( @installer::globals::logfileinfo, $infoline); + $infoline = "New: $newline\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + # saving file + installer::files::save_file($idtfilename, $filecontent); +} + +######################################################################### +# Creating file content hash +######################################################################### + +sub make_executeidtcontent_hash +{ + my ($filecontent, $idtfilename) = @_; + + my %newhash = (); + + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if ( $i <= 2 ) { next; } # ignoring first three lines + if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines + # Format for all sequence tables: Action Condition Sequence + if ( ${$filecontent}[$i] =~ /^\s*(.+?)\t(.*?)\t(.*?)\s*$/ ) + { + my %onehash = (); + $onehash{'Action'} = $1; + $onehash{'Condition'} = $2; + $onehash{'Sequence'} = $3; + $newhash{$onehash{'Action'}} = \%onehash; + } + else + { + my $linecount = $i + 1; + installer::exiter::exit_program("ERROR: Unknown line format in table \"$idtfilename\" (line $linecount) !", "make_executeidtcontent_hash"); + } + } + + return \%newhash; +} + +######################################################################### +# Creating file content hash +######################################################################### + +sub make_moduleexecuteidtcontent_hash +{ + my ($filecontent, $idtfilename) = @_; + + my %newhash = (); + + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if ( $i <= 2 ) { next; } # ignoring first three lines + if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines + # Format for all module sequence tables: Action Sequence BaseAction After Condition + if ( ${$filecontent}[$i] =~ /^\s*(.+?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) + { + my %onehash = (); + $onehash{'Action'} = $1; + $onehash{'Sequence'} = $2; + $onehash{'BaseAction'} = $3; + $onehash{'After'} = $4; + $onehash{'Condition'} = $5; + $newhash{$onehash{'Action'}} = \%onehash; + } + else + { + my $linecount = $i + 1; + installer::exiter::exit_program("ERROR: Unknown line format in table \"$idtfilename\" (line $linecount) !", "make_executeidtcontent_hash"); + } + } + + return \%newhash; +} + +######################################################################### +# ExecuteSequence tables need to be merged with +# ModuleExecuteSequence tables created by msidb.exe. +######################################################################### + +sub change_executesequence_table +{ + my ($mergemodulehash, $workdir, $idtfilename, $moduleidtfilename) = @_; + + my $infoline = "Changing content of table \"$idtfilename\"\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ( ! -f $idtfilename ) { installer::exiter::exit_program("ERROR: Could not find file \"$idtfilename\" in \"$workdir\" !", "change_executesequence_table"); } + if ( ! -f $moduleidtfilename ) { installer::exiter::exit_program("ERROR: Could not find file \"$moduleidtfilename\" in \"$workdir\" !", "change_executesequence_table"); } + + # Reading file content + my $idtfilecontent = installer::files::read_file($idtfilename); + my $moduleidtfilecontent = installer::files::read_file($moduleidtfilename); + + # Converting to hash + my $idtcontenthash = make_executeidtcontent_hash($idtfilecontent, $idtfilename); + my $moduleidtcontenthash = make_moduleexecuteidtcontent_hash($moduleidtfilecontent, $moduleidtfilename); + + # Merging + foreach my $action ( keys %{$moduleidtcontenthash} ) + { + if ( exists($idtcontenthash->{$action}) ) { next; } # Action already exists, can be ignored + + if (( $idtfilename eq "InstallU.idt" ) && ( ! ( $action =~ /^\s*WindowsFolder\./ ))) { next; } # Only "WindowsFolder.*" CustomActions for UI Sequence table + + my $actionhashref = $moduleidtcontenthash->{$action}; + if ( $actionhashref->{'Sequence'} ne "" ) + { + # Format for all sequence tables: Action Condition Sequence + my $newline = $actionhashref->{'Action'} . "\t" . $actionhashref->{'Condition'} . "\t" . $actionhashref->{'Sequence'} . "\n"; + # Adding to table + push(@{$idtfilecontent}, $newline); + # Also adding to hash + my %idttablehash = (); + $idttablehash{'Action'} = $actionhashref->{'Action'}; + $idttablehash{'Condition'} = $actionhashref->{'Condition'}; + $idttablehash{'Sequence'} = $actionhashref->{'Sequence'}; + $idtcontenthash->{$action} = \%idttablehash; + + } + else # no sequence defined, using syntax "BaseAction" and "After" + { + my $baseactionname = $actionhashref->{'BaseAction'}; + # If this baseactionname is not defined in execute idt file, it is not possible to merge + if ( ! exists($idtcontenthash->{$baseactionname}) ) { installer::exiter::exit_program("ERROR: Merge problem: Could not find action \"$baseactionname\" in file \"$idtfilename\" !", "change_executesequence_table"); } + + my $baseaction = $idtcontenthash->{$baseactionname}; + my $sequencenumber = $baseaction->{'Sequence'}; + if ( $actionhashref->{'After'} == 1 ) { $sequencenumber = $sequencenumber + 1; } + else { $sequencenumber = $sequencenumber - 1; } + + # Format for all sequence tables: Action Condition Sequence + my $newline = $actionhashref->{'Action'} . "\t" . $actionhashref->{'Condition'} . "\t" . $sequencenumber . "\n"; + # Adding to table + push(@{$idtfilecontent}, $newline); + # Also adding to hash + my %idttablehash = (); + $idttablehash{'Action'} = $actionhashref->{'Action'}; + $idttablehash{'Condition'} = $actionhashref->{'Condition'}; + $idttablehash{'Sequence'} = $sequencenumber; + $idtcontenthash->{$action} = \%idttablehash; + } + } + + # saving file + installer::files::save_file($idtfilename, $idtfilecontent); +} + + +1; diff --git a/solenv/bin/modules/installer/windows/msiglobal.pm b/solenv/bin/modules/installer/windows/msiglobal.pm new file mode 100644 index 000000000000..030bb2d6ac50 --- /dev/null +++ b/solenv/bin/modules/installer/windows/msiglobal.pm @@ -0,0 +1,2295 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: msiglobal.pm,v $ +# +# $Revision: 1.51 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::msiglobal; + +use Cwd; +use Digest::MD5; +use installer::converter; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::logger; +use installer::pathanalyzer; +use installer::remover; +use installer::scriptitems; +use installer::systemactions; +use installer::worker; +use installer::windows::idtglobal; +use installer::windows::language; + +########################################################################### +# Generating the header of the ddf file. +# The usage of ddf files is needed, because makecab.exe can only include +# one sourcefile into a cab file +########################################################################### + +sub write_ddf_file_header +{ + my ($ddffileref, $cabinetfile, $installdir) = @_; + + my $oneline; + + $oneline = ".Set CabinetName1=" . $cabinetfile . "\n"; + push(@{$ddffileref} ,$oneline); + $oneline = ".Set ReservePerCabinetSize=128\n"; # This reserves space for a digital signature. + push(@{$ddffileref} ,$oneline); + $oneline = ".Set MaxDiskSize=CDROM\n"; # This allows the .cab file to be as large as needed. + push(@{$ddffileref} ,$oneline); + $oneline = ".Set CompressionType=LZX\n"; + push(@{$ddffileref} ,$oneline); + $oneline = ".Set Compress=ON\n"; + push(@{$ddffileref} ,$oneline); + $oneline = ".Set CompressionLevel=$installer::globals::cabfilecompressionlevel\n"; + push(@{$ddffileref} ,$oneline); + $oneline = ".Set Cabinet=ON\n"; + push(@{$ddffileref} ,$oneline); + $oneline = ".Set DiskDirectoryTemplate=" . $installdir . "\n"; + push(@{$ddffileref} ,$oneline); +} + +########################################################################## +# Lines in ddf files must not contain more than 256 characters +########################################################################## + +sub check_ddf_file +{ + my ( $ddffile, $ddffilename ) = @_; + + my $maxlength = 0; + my $maxline = 0; + my $linelength = 0; + my $linenumber = 0; + + for ( my $i = 0; $i <= $#{$ddffile}; $i++ ) + { + my $oneline = ${$ddffile}[$i]; + + $linelength = length($oneline); + $linenumber = $i + 1; + + if ( $linelength > 256 ) + { + installer::exiter::exit_program("ERROR \"$ddffilename\" line $linenumber: Lines in ddf files must not contain more than 256 characters!", "check_ddf_file"); + } + + if ( $linelength > $maxlength ) + { + $maxlength = $linelength; + $maxline = $linenumber; + } + } + + my $infoline = "Check of ddf file \"$ddffilename\": Maximum length \"$maxlength\" in line \"$maxline\" (allowed line length: 256 characters)\n"; + push(@installer::globals::logfileinfo, $infoline); +} + +########################################################################## +# Lines in ddf files must not be longer than 256 characters. +# Therefore it can be useful to use relative pathes. Then it is +# necessary to change into temp directory before calling +# makecab.exe. +########################################################################## + +sub make_relative_ddf_path +{ + my ( $sourcepath ) = @_; + + my $windowstemppath = $installer::globals::temppath; + + if ( $^O =~ /cygwin/i ) + { + $windowstemppath = $installer::globals::cyg_temppath; + } + + $sourcepath =~ s/\Q$windowstemppath\E//; + $sourcepath =~ s/^\\//; + + return $sourcepath; +} + +########################################################################## +# Returning the order of the sequences in the files array. +########################################################################## + +sub get_sequenceorder +{ + my ($filesref) = @_; + + my %order = (); + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + if ( ! $onefile->{'assignedsequencenumber'} ) { installer::exiter::exit_program("ERROR: No sequence number assigned to $onefile->{'gid'} ($onefile->{'uniquename'})!", "get_sequenceorder"); } + $order{$onefile->{'assignedsequencenumber'}} = $i; + } + + return \%order; +} + +########################################################################## +# Generation the list, in which the source of the files is connected +# with the cabinet destination file. Because more than one file needs +# to be included into a cab file, this has to be done via ddf files. +########################################################################## + +sub generate_cab_file_list +{ + my ($filesref, $installdir, $ddfdir, $allvariables) = @_; + + my @cabfilelist = (); + + installer::logger::include_header_into_logfile("Generating ddf files"); + + installer::logger::include_timestamp_into_logfile("Performance Info: ddf file generation start"); + + if ( $^O =~ /cygwin/i ) { installer::worker::generate_cygwin_pathes($filesref); } + + if ( $installer::globals::use_packages_for_cabs ) + { + my $sequenceorder = get_sequenceorder($filesref); + + my $counter = 1; + my $currentcabfile = ""; + + while ( ( exists($sequenceorder->{$counter}) ) || ( exists($installer::globals::allmergemodulefilesequences{$counter}) ) ) # Taking care of files from merge modules + { + if ( exists($installer::globals::allmergemodulefilesequences{$counter}) ) + { + # Skipping this sequence, it is not included in $filesref, because it is assigned to a file from a merge module.\n"; + $counter++; + next; + } + + # Files with increasing sequencerorder are included in one cab file + my $onefile = ${$filesref}[$sequenceorder->{$counter}]; + my $cabinetfile = $onefile->{'assignedcabinetfile'}; + my $sourcepath = $onefile->{'sourcepath'}; + if ( $^O =~ /cygwin/i ) { $sourcepath = $onefile->{'cyg_sourcepath'}; } + my $uniquename = $onefile->{'uniquename'}; + + my $styles = ""; + my $doinclude = 1; + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; }; + if ( $styles =~ /\bDONT_PACK\b/ ) { $doinclude = 0; } + + # to avoid lines with more than 256 characters, it can be useful to use relative pathes + if ( $allvariables->{'RELATIVE_PATHES_IN_DDF'} ) { $sourcepath = make_relative_ddf_path($sourcepath); } + + # all files with the same cabinetfile have increasing sequencenumbers + + my @ddffile = (); + + write_ddf_file_header(\@ddffile, $cabinetfile, $installdir); + + my $ddfline = "\"" . $sourcepath . "\"" . " " . $uniquename . "\n"; + if ( $doinclude ) { push(@ddffile, $ddfline); } + + $counter++; # increasing the counter + my $nextfile = ""; + my $nextcabinetfile = ""; + if ( exists($sequenceorder->{$counter}) ) { $nextfile = ${$filesref}[$sequenceorder->{$counter}]; } + if ( $nextfile->{'assignedcabinetfile'} ) { $nextcabinetfile = $nextfile->{'assignedcabinetfile'}; } + + while ( $nextcabinetfile eq $cabinetfile ) + { + $sourcepath = $nextfile->{'sourcepath'}; + if ( $^O =~ /cygwin/i ) { $sourcepath = $nextfile->{'cyg_sourcepath'}; } + # to avoid lines with more than 256 characters, it can be useful to use relative pathes + if ( $allvariables->{'RELATIVE_PATHES_IN_DDF'} ) { $sourcepath = make_relative_ddf_path($sourcepath); } + $uniquename = $nextfile->{'uniquename'}; + my $localdoinclude = 1; + my $nextfilestyles = ""; + if ( $nextfile->{'Styles'} ) { $nextfilestyles = $nextfile->{'Styles'}; } + if ( $nextfilestyles =~ /\bDONT_PACK\b/ ) { $localdoinclude = 0; } + $ddfline = "\"" . $sourcepath . "\"" . " " . $uniquename . "\n"; + if ( $localdoinclude ) { push(@ddffile, $ddfline); } + + $counter++; # increasing the counter! + $nextcabinetfile = "_lastfile_"; + if ( exists($sequenceorder->{$counter}) ) + { + $nextfile = ${$filesref}[$sequenceorder->{$counter}]; + $nextcabinetfile = $nextfile->{'assignedcabinetfile'}; + } + } + + # creating the DDF file + + my $ddffilename = $cabinetfile; + $ddffilename =~ s/.cab/.ddf/; + $ddfdir =~ s/\Q$installer::globals::separator\E\s*$//; + $ddffilename = $ddfdir . $installer::globals::separator . $ddffilename; + + installer::files::save_file($ddffilename ,\@ddffile); + my $infoline = "Created ddf file: $ddffilename\n"; + push(@installer::globals::logfileinfo, $infoline); + + # lines in ddf files must not be longer than 256 characters + check_ddf_file(\@ddffile, $ddffilename); + + # Writing the makecab system call + + my $oneline = "makecab.exe /V3 /F " . $ddffilename . " 2\>\&1 |" . "\n"; + + push(@cabfilelist, $oneline); + + # collecting all ddf files + push(@installer::globals::allddffiles, $ddffilename); + } + } + elsif ((( $installer::globals::cab_file_per_component ) || ( $installer::globals::fix_number_of_cab_files )) && ( $installer::globals::updatedatabase )) + { + my $sequenceorder = get_sequenceorder($filesref); + + my $counter = 1; + my $currentcabfile = ""; + + while ( ( exists($sequenceorder->{$counter}) ) || ( exists($installer::globals::allmergemodulefilesequences{$counter}) ) ) # Taking care of files from merge modules + { +# if ( exists($installer::globals::allmergemodulefilesequences{$counter}) ) +# { +# # Skipping this sequence, it is not included in $filesref, because it is assigned to a file from a merge module.\n"; +# $counter++; +# next; +# } + + my $onefile = ${$filesref}[$sequenceorder->{$counter}]; + $counter++; + + my $cabinetfile = $onefile->{'cabinet'}; + my $sourcepath = $onefile->{'sourcepath'}; + if ( $^O =~ /cygwin/i ) { $sourcepath = $onefile->{'cyg_sourcepath'}; } + my $uniquename = $onefile->{'uniquename'}; + + my $styles = ""; + my $doinclude = 1; + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; }; + if ( $styles =~ /\bDONT_PACK\b/ ) { $doinclude = 0; } + + # to avoid lines with more than 256 characters, it can be useful to use relative pathes + if ( $allvariables->{'RELATIVE_PATHES_IN_DDF'} ) { $sourcepath = make_relative_ddf_path($sourcepath); } + + my @ddffile = (); + + write_ddf_file_header(\@ddffile, $cabinetfile, $installdir); + + my $ddfline = "\"" . $sourcepath . "\"" . " " . $uniquename . "\n"; + if ( $doinclude ) { push(@ddffile, $ddfline); } + + my $nextfile = ""; + if ( ${$filesref}[$sequenceorder->{$counter}] ) { $nextfile = ${$filesref}[$sequenceorder->{$counter}]; } + + my $nextcabinetfile = ""; + + if ( $nextfile->{'cabinet'} ) { $nextcabinetfile = $nextfile->{'cabinet'}; } + + while ( $nextcabinetfile eq $cabinetfile ) + { + $sourcepath = $nextfile->{'sourcepath'}; + if ( $^O =~ /cygwin/i ) { $sourcepath = $nextfile->{'cyg_sourcepath'}; } + # to avoid lines with more than 256 characters, it can be useful to use relative pathes + if ( $allvariables->{'RELATIVE_PATHES_IN_DDF'} ) { $sourcepath = make_relative_ddf_path($sourcepath); } + $uniquename = $nextfile->{'uniquename'}; + my $localdoinclude = 1; + my $nextfilestyles = ""; + if ( $nextfile->{'Styles'} ) { $nextfilestyles = $nextfile->{'Styles'}; } + if ( $nextfilestyles =~ /\bDONT_PACK\b/ ) { $localdoinclude = 0; } + $ddfline = "\"" . $sourcepath . "\"" . " " . $uniquename . "\n"; + if ( $localdoinclude ) { push(@ddffile, $ddfline); } + $counter++; # increasing the counter! + $nextfile = ""; + $nextcabinetfile = "_lastfile_"; + if (( exists($sequenceorder->{$counter}) ) && ( ${$filesref}[$sequenceorder->{$counter}] )) + { + $nextfile = ${$filesref}[$sequenceorder->{$counter}]; + $nextcabinetfile = $nextfile->{'cabinet'}; + } + } + + # creating the DDF file + + my $ddffilename = $cabinetfile; + $ddffilename =~ s/.cab/.ddf/; + $ddfdir =~ s/\Q$installer::globals::separator\E\s*$//; + $ddffilename = $ddfdir . $installer::globals::separator . $ddffilename; + + installer::files::save_file($ddffilename ,\@ddffile); + my $infoline = "Created ddf file: $ddffilename\n"; + push(@installer::globals::logfileinfo, $infoline); + + # lines in ddf files must not be longer than 256 characters + check_ddf_file(\@ddffile, $ddffilename); + + # Writing the makecab system call + + my $oneline = "makecab.exe /V3 /F " . $ddffilename . " 2\>\&1 |" . "\n"; + + push(@cabfilelist, $oneline); + + # collecting all ddf files + push(@installer::globals::allddffiles, $ddffilename); + } + } + elsif (( $installer::globals::cab_file_per_component ) || ( $installer::globals::fix_number_of_cab_files )) + { + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + my $cabinetfile = $onefile->{'cabinet'}; + my $sourcepath = $onefile->{'sourcepath'}; + if ( $^O =~ /cygwin/i ) { $sourcepath = $onefile->{'cyg_sourcepath'}; } + my $uniquename = $onefile->{'uniquename'}; + + my $styles = ""; + my $doinclude = 1; + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; }; + if ( $styles =~ /\bDONT_PACK\b/ ) { $doinclude = 0; } + + + # to avoid lines with more than 256 characters, it can be useful to use relative pathes + if ( $allvariables->{'RELATIVE_PATHES_IN_DDF'} ) { $sourcepath = make_relative_ddf_path($sourcepath); } + + # all files with the same cabinetfile are directly behind each other in the files collector + + my @ddffile = (); + + write_ddf_file_header(\@ddffile, $cabinetfile, $installdir); + + my $ddfline = "\"" . $sourcepath . "\"" . " " . $uniquename . "\n"; + if ( $doinclude ) { push(@ddffile, $ddfline); } + + my $nextfile = ${$filesref}[$i+1]; + my $nextcabinetfile = ""; + + if ( $nextfile->{'cabinet'} ) { $nextcabinetfile = $nextfile->{'cabinet'}; } + + while ( $nextcabinetfile eq $cabinetfile ) + { + $sourcepath = $nextfile->{'sourcepath'}; + if ( $^O =~ /cygwin/i ) { $sourcepath = $nextfile->{'cyg_sourcepath'}; } + # to avoid lines with more than 256 characters, it can be useful to use relative pathes + if ( $allvariables->{'RELATIVE_PATHES_IN_DDF'} ) { $sourcepath = make_relative_ddf_path($sourcepath); } + $uniquename = $nextfile->{'uniquename'}; + my $localdoinclude = 1; + my $nextfilestyles = ""; + if ( $nextfile->{'Styles'} ) { $nextfilestyles = $nextfile->{'Styles'}; } + if ( $nextfilestyles =~ /\bDONT_PACK\b/ ) { $localdoinclude = 0; } + $ddfline = "\"" . $sourcepath . "\"" . " " . $uniquename . "\n"; + if ( $localdoinclude ) { push(@ddffile, $ddfline); } + $i++; # increasing the counter! + $nextfile = ${$filesref}[$i+1]; + if ( $nextfile ) { $nextcabinetfile = $nextfile->{'cabinet'}; } + else { $nextcabinetfile = "_lastfile_"; } + } + + # creating the DDF file + + my $ddffilename = $cabinetfile; + $ddffilename =~ s/.cab/.ddf/; + $ddfdir =~ s/\Q$installer::globals::separator\E\s*$//; + $ddffilename = $ddfdir . $installer::globals::separator . $ddffilename; + + installer::files::save_file($ddffilename ,\@ddffile); + my $infoline = "Created ddf file: $ddffilename\n"; + push(@installer::globals::logfileinfo, $infoline); + + # lines in ddf files must not be longer than 256 characters + check_ddf_file(\@ddffile, $ddffilename); + + # Writing the makecab system call + + my $oneline = "makecab.exe /V3 /F " . $ddffilename . " 2\>\&1 |" . "\n"; + + push(@cabfilelist, $oneline); + + # collecting all ddf files + push(@installer::globals::allddffiles, $ddffilename); + } + } + elsif (( $installer::globals::one_cab_file ) && ( $installer::globals::updatedatabase )) + { + my $sequenceorder = get_sequenceorder($filesref); + + my $counter = 1; + my $currentcabfile = ""; + + while ( ( exists($sequenceorder->{$counter}) ) || ( exists($installer::globals::allmergemodulefilesequences{$counter}) ) ) # Taking care of files from merge modules + { + if ( exists($installer::globals::allmergemodulefilesequences{$counter}) ) + { + # Skipping this sequence, it is not included in $filesref, because it is assigned to a file from a merge module.\n"; + $counter++; + next; + } + + my $onefile = ${$filesref}[$sequenceorder->{$counter}]; + + $cabinetfile = $onefile->{'cabinet'}; + my $sourcepath = $onefile->{'sourcepath'}; + if ( $^O =~ /cygwin/i ) { $sourcepath = $onefile->{'cyg_sourcepath'}; } + my $uniquename = $onefile->{'uniquename'}; + + # to avoid lines with more than 256 characters, it can be useful to use relative pathes + if ( $allvariables->{'RELATIVE_PATHES_IN_DDF'} ) { $sourcepath = make_relative_ddf_path($sourcepath); } + + if ( $counter == 1 ) { write_ddf_file_header(\@ddffile, $cabinetfile, $installdir); } + + my $styles = ""; + my $doinclude = 1; + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; }; + if ( $styles =~ /\bDONT_PACK\b/ ) { $doinclude = 0; } + + my $ddfline = "\"" . $sourcepath . "\"" . " " . $uniquename . "\n"; + if ( $doinclude ) { push(@ddffile, $ddfline); } + + $counter++; # increasing the counter + } + + # creating the DDF file + + my $ddffilename = $cabinetfile; + $ddffilename =~ s/.cab/.ddf/; + $ddfdir =~ s/[\/\\]\s*$//; + $ddffilename = $ddfdir . $installer::globals::separator . $ddffilename; + + installer::files::save_file($ddffilename ,\@ddffile); + my $infoline = "Created ddf file: $ddffilename\n"; + push(@installer::globals::logfileinfo, $infoline); + + # lines in ddf files must not be longer than 256 characters + check_ddf_file(\@ddffile, $ddffilename); + + # Writing the makecab system call + + # my $oneline = "makecab.exe /F " . $ddffilename . "\n"; + my $oneline = "makecab.exe /V3 /F " . $ddffilename . " 2\>\&1 |" . "\n"; + + push(@cabfilelist, $oneline); + + # collecting all ddf files + push(@installer::globals::allddffiles, $ddffilename); + } + elsif ( $installer::globals::one_cab_file ) + { + my @ddffile = (); + + my $cabinetfile = ""; + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + $cabinetfile = $onefile->{'cabinet'}; + my $sourcepath = $onefile->{'sourcepath'}; + if ( $^O =~ /cygwin/i ) { $sourcepath = $onefile->{'cyg_sourcepath'}; } + my $uniquename = $onefile->{'uniquename'}; + + # to avoid lines with more than 256 characters, it can be useful to use relative pathes + if ( $allvariables->{'RELATIVE_PATHES_IN_DDF'} ) { $sourcepath = make_relative_ddf_path($sourcepath); } + + if ( $i == 0 ) { write_ddf_file_header(\@ddffile, $cabinetfile, $installdir); } + + my $styles = ""; + my $doinclude = 1; + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; }; + if ( $styles =~ /\bDONT_PACK\b/ ) { $doinclude = 0; } + + my $ddfline = "\"" . $sourcepath . "\"" . " " . $uniquename . "\n"; + if ( $doinclude ) { push(@ddffile, $ddfline); } + } + + # creating the DDF file + + my $ddffilename = $cabinetfile; + $ddffilename =~ s/.cab/.ddf/; + $ddfdir =~ s/[\/\\]\s*$//; + $ddffilename = $ddfdir . $installer::globals::separator . $ddffilename; + + installer::files::save_file($ddffilename ,\@ddffile); + my $infoline = "Created ddf file: $ddffilename\n"; + push(@installer::globals::logfileinfo, $infoline); + + # lines in ddf files must not be longer than 256 characters + check_ddf_file(\@ddffile, $ddffilename); + + # Writing the makecab system call + + my $oneline = "makecab.exe /F " . $ddffilename . "\n"; + + push(@cabfilelist, $oneline); + + # collecting all ddf files + push(@installer::globals::allddffiles, $ddffilename); + } + else + { + installer::exiter::exit_program("ERROR: No cab file specification in globals.pm !", "create_media_table"); + } + + installer::logger::include_timestamp_into_logfile("Performance Info: ddf file generation end"); + + return \@cabfilelist; # contains all system calls for packaging process +} + +######################################################################## +# Returning the file sequence of a specified file. +######################################################################## + +sub get_file_sequence +{ + my ($filesref, $uniquefilename) = @_; + + my $sequence = ""; + my $found_sequence = 0; + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + my $uniquename = $onefile->{'uniquename'}; + + if ( $uniquename eq $uniquefilename ) + { + $sequence = $onefile->{'sequencenumber'}; + $found_sequence = 1; + last; + } + } + + if ( ! $found_sequence ) { installer::exiter::exit_program("ERROR: No sequence found for $uniquefilename !", "get_file_sequence"); } + + return $sequence; +} + +######################################################################## +# For update and patch reasons the pack order needs to be saved. +# The pack order is saved in the ddf files; the names and locations +# of the ddf files are saved in @installer::globals::allddffiles. +# The outputfile "packorder.txt" can be saved in +# $installer::globals::infodirectory . +######################################################################## + +sub save_packorder +{ + installer::logger::include_header_into_logfile("Saving pack order"); + + installer::logger::include_timestamp_into_logfile("Performance Info: saving pack order start"); + + my $packorderfilename = "packorder.txt"; + $packorderfilename = $installer::globals::infodirectory . $installer::globals::separator . $packorderfilename; + + my @packorder = (); + + my $headerline = "\# Syntax\: Filetable_Sequence Cabinetfilename Physical_FileName Unique_FileName\n\n"; + push(@packorder, $headerline); + + for ( my $i = 0; $i <= $#installer::globals::allddffiles; $i++ ) + { + my $ddffilename = $installer::globals::allddffiles[$i]; + my $ddffile = installer::files::read_file($ddffilename); + my $cabinetfile = ""; + + for ( my $j = 0; $j <= $#{$ddffile}; $j++ ) + { + my $oneline = ${$ddffile}[$j]; + + # Getting the Cabinet file name + + if ( $oneline =~ /^\s*\.Set\s+CabinetName.*\=(.*?)\s*$/ ) { $cabinetfile = $1; } + if ( $oneline =~ /^\s*\.Set\s+/ ) { next; } + + if ( $oneline =~ /^\s*\"(.*?)\"\s+(.*?)\s*$/ ) + { + my $sourcefile = $1; + my $uniquefilename = $2; + + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$sourcefile); + + # Using the hash created in create_files_table for performance reasons to get the sequence number + my $filesequence = ""; + if ( exists($installer::globals::uniquefilenamesequence{$uniquefilename}) ) { $filesequence = $installer::globals::uniquefilenamesequence{$uniquefilename}; } + else { installer::exiter::exit_program("ERROR: No sequence number value for $uniquefilename !", "save_packorder"); } + + my $line = $filesequence . "\t" . $cabinetfile . "\t" . $sourcefile . "\t" . $uniquefilename . "\n"; + push(@packorder, $line); + } + } + } + + installer::files::save_file($packorderfilename ,\@packorder); + + installer::logger::include_timestamp_into_logfile("Performance Info: saving pack order end"); +} + +################################################################# +# Returning the name of the msi database +################################################################# + +sub get_msidatabasename +{ + my ($allvariableshashref, $language) = @_; + + my $databasename = $allvariableshashref->{'PRODUCTNAME'} . $allvariableshashref->{'PRODUCTVERSION'}; + $databasename = lc($databasename); + $databasename =~ s/\.//g; + $databasename =~ s/\-//g; + $databasename =~ s/\s//g; + + # possibility to overwrite the name with variable DATABASENAME + if ( $allvariableshashref->{'DATABASENAME'} ) + { + $databasename = $allvariableshashref->{'DATABASENAME'}; + } + + if ( $language ) + { + if (!($language eq "")) + { + $databasename .= "_$language"; + } + } + + $databasename .= ".msi"; + + return $databasename; +} + +################################################################# +# Creating the msi database +# This works only on Windows +################################################################# + +sub create_msi_database +{ + my ($idtdirbase ,$msifilename) = @_; + + # -f : path containing the idt files + # -d : msi database, including path + # -c : create database + # -i : include the following tables ("*" includes all available tables) + + my $msidb = "msidb.exe"; # Has to be in the path + my $extraslash = ""; # Has to be set for non-ActiveState perl + + installer::logger::include_header_into_logfile("Creating msi database"); + + $idtdirbase = installer::converter::make_path_conform($idtdirbase); + + $msifilename = installer::converter::make_path_conform($msifilename); + + if ( $^O =~ /cygwin/i ) { + # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) + $idtdirbase =~ s/\//\\\\/g; + $msifilename =~ s/\//\\\\/g; + $extraslash = "\\"; + } + my $systemcall = $msidb . " -f " . $idtdirbase . " -d " . $msifilename . " -c " . "-i " . $extraslash . "*"; + + my $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute $msidb!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed $msidb successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +##################################################################### +# Returning the value from sis.mlf for Summary Information Stream +##################################################################### + +sub get_value_from_sis_lng +{ + my ($language, $languagefile, $searchstring) = @_; + + my $language_block = installer::windows::idtglobal::get_language_block_from_language_file($searchstring, $languagefile); + my $newstring = installer::windows::idtglobal::get_language_string_from_language_block($language_block, $language, $searchstring); + $newstring = "\"" . $newstring . "\""; + + return $newstring; +} + +################################################################# +# Returning the msi version for the Summary Information Stream +################################################################# + +sub get_msiversion_for_sis +{ + my $msiversion = "200"; + return $msiversion; +} + +################################################################# +# Returning the word count for the Summary Information Stream +################################################################# + +sub get_wordcount_for_sis +{ + my $wordcount = "0"; + return $wordcount; +} + +################################################################# +# Returning the codepage for the Summary Information Stream +################################################################# + +sub get_codepage_for_sis +{ + my ( $language ) = @_; + + my $codepage = installer::windows::language::get_windows_encoding($language); + + # Codepage 65001 does not work in Summary Information Stream + if ( $codepage == 65001 ) { $codepage = 0; } + + # my $codepage = "1252"; # determine dynamically in a function + # my $codepage = "65001"; # UTF-8 + return $codepage; +} + +################################################################# +# Returning the template for the Summary Information Stream +################################################################# + +sub get_template_for_sis +{ + my ( $language ) = @_; + + my $windowslanguage = installer::windows::language::get_windows_language($language); + + my $value = "\"Intel;" . $windowslanguage; # adding the Windows language + + $value = $value . "\""; # adding ending '"' + + return $value ; +} + +################################################################# +# Returning the PackageCode for the Summary Information Stream +################################################################# + +sub get_packagecode_for_sis +{ + # always generating a new package code for each package + + my $guidref = get_guid_list(1, 1); # only one GUID shall be generated + + ${$guidref}[0] =~ s/\s*$//; # removing ending spaces + + my $guid = "\{" . ${$guidref}[0] . "\}"; + + my $infoline = "PackageCode: $guid\n"; + push( @installer::globals::logfileinfo, $infoline); + + return $guid; +} + +################################################################# +# Returning the title for the Summary Information Stream +################################################################# + +sub get_title_for_sis +{ + my ( $language, $languagefile, $searchstring ) = @_; + + my $title = get_value_from_sis_lng($language, $languagefile, $searchstring ); + + return $title; +} + +################################################################# +# Returning the author for the Summary Information Stream +################################################################# + +sub get_author_for_sis +{ + my $author = $installer::globals::longmanufacturer; + + $author = "\"" . $author . "\""; + + return $author; +} + +################################################################# +# Returning the subject for the Summary Information Stream +################################################################# + +sub get_subject_for_sis +{ + my ( $allvariableshashref ) = @_; + + my $subject = $allvariableshashref->{'PRODUCTNAME'} . " " . $allvariableshashref->{'PRODUCTVERSION'}; + + $subject = "\"" . $subject . "\""; + + return $subject; +} + +################################################################# +# Returning the comment for the Summary Information Stream +################################################################# + +sub get_comment_for_sis +{ + my ( $language, $languagefile, $searchstring ) = @_; + + my $comment = get_value_from_sis_lng($language, $languagefile, $searchstring ); + + return $comment; +} + +################################################################# +# Returning the keywords for the Summary Information Stream +################################################################# + +sub get_keywords_for_sis +{ + my ( $language, $languagefile, $searchstring ) = @_; + + my $keywords = get_value_from_sis_lng($language, $languagefile, $searchstring ); + + return $keywords; +} + +###################################################################### +# Returning the application name for the Summary Information Stream +###################################################################### + +sub get_appname_for_sis +{ + my ( $language, $languagefile, $searchstring ) = @_; + + my $appname = get_value_from_sis_lng($language, $languagefile, $searchstring ); + + return $appname; +} + +###################################################################### +# Returning the security for the Summary Information Stream +###################################################################### + +sub get_security_for_sis +{ + my $security = "0"; + return $security; +} + +################################################################# +# Writing the Summary information stream into the msi database +# This works only on Windows +################################################################# + +sub write_summary_into_msi_database +{ + my ($msifilename, $language, $languagefile, $allvariableshashref) = @_; + + # -g : requrired msi version + # -c : codepage + # -p : template + + installer::logger::include_header_into_logfile("Writing summary information stream"); + + my $msiinfo = "msiinfo.exe"; # Has to be in the path + + my $sislanguage = "en-US"; # title, comment, keyword and appname alway in english + + my $msiversion = get_msiversion_for_sis(); + my $codepage = get_codepage_for_sis($language); + my $template = get_template_for_sis($language); + my $guid = get_packagecode_for_sis(); + my $title = get_title_for_sis($sislanguage,$languagefile, "OOO_SIS_TITLE"); + my $author = get_author_for_sis(); + my $subject = get_subject_for_sis($allvariableshashref); + my $comment = get_comment_for_sis($sislanguage,$languagefile, "OOO_SIS_COMMENT"); + my $keywords = get_keywords_for_sis($sislanguage,$languagefile, "OOO_SIS_KEYWORDS"); + my $appname = get_appname_for_sis($sislanguage,$languagefile, "OOO_SIS_APPNAME"); + my $security = get_security_for_sis(); + my $wordcount = get_wordcount_for_sis(); + + $msifilename = installer::converter::make_path_conform($msifilename); + + my $systemcall = $msiinfo . " " . $msifilename . " -g " . $msiversion . " -c " . $codepage + . " -p " . $template . " -v " . $guid . " -t " . $title . " -a " . $author + . " -j " . $subject . " -o " . $comment . " -k " . $keywords . " -n " . $appname + . " -u " . $security . " -w " . $wordcount; + + my $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute $msiinfo!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed $msiinfo successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +######################################################################### +# For more than one language in the installation set: +# Use one database and create Transformations for all other languages +######################################################################### + +sub create_transforms +{ + my ($languagesarray, $defaultlanguage, $installdir, $allvariableshashref) = @_; + + installer::logger::include_header_into_logfile("Creating Transforms"); + + my $msitran = "msitran.exe"; # Has to be in the path + + $installdir = installer::converter::make_path_conform($installdir); + + # Syntax for creating a transformation + # msitran.exe -g <baseDB> <referenceDB> <transformfile> [<errorhandling>} + + my $basedbname = get_msidatabasename($allvariableshashref, $defaultlanguage); + $basedbname = $installdir . $installer::globals::separator . $basedbname; + + my $errorhandling = "f"; # Suppress "change codepage" error + + # Iterating over all files + + foreach ( @{$languagesarray} ) + { + my $onelanguage = $_; + + if ( $onelanguage eq $defaultlanguage ) { next; } + + my $referencedbname = get_msidatabasename($allvariableshashref, $onelanguage); + $referencedbname = $installdir . $installer::globals::separator . $referencedbname; + + my $transformfile = $installdir . $installer::globals::separator . "trans_" . $onelanguage . ".mst"; + + my $systemcall = $msitran . " " . " -g " . $basedbname . " " . $referencedbname . " " . $transformfile . " " . $errorhandling; + + my $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + # Problem: msitran.exe in version 4.0 always returns "1", even if no failure occured. + # Therefore it has to be checked, if this is version 4.0. If yes, if the mst file + # exists and if it is larger than 0 bytes. If this is true, then no error occured. + # File Version of msitran.exe: 4.0.6000.16384 has checksum: "b66190a70145a57773ec769e16777b29". + # Same for msitran.exe from wntmsci12: "aa25d3445b94ffde8ef0c1efb77a56b8" + + if ($returnvalue) + { + $infoline = "WARNING: Returnvalue of $msitran is not 0. Checking version of $msitran!\n"; + push( @installer::globals::logfileinfo, $infoline); + + open(FILE, "<$installer::globals::msitranpath") or die "ERROR: Can't open $installer::globals::msitranpath for creating file hash"; + binmode(FILE); + my $digest = Digest::MD5->new->addfile(*FILE)->hexdigest; + close(FILE); + + my @problemchecksums = ("b66190a70145a57773ec769e16777b29", "aa25d3445b94ffde8ef0c1efb77a56b8"); + my $isproblemchecksum = 0; + + foreach my $problemchecksum ( @problemchecksums ) + { + $infoline = "Checksum of problematic MsiTran.exe: $problemchecksum\n"; + push( @installer::globals::logfileinfo, $infoline); + $infoline = "Checksum of used MsiTran.exe: $digest\n"; + push( @installer::globals::logfileinfo, $infoline); + if ( $digest eq $problemchecksum ) { $isproblemchecksum = 1; } + } + + if ( $isproblemchecksum ) + { + # Check existence of mst + if ( -f $transformfile ) + { + $infoline = "File $transformfile exists.\n"; + push( @installer::globals::logfileinfo, $infoline); + my $filesize = ( -s $transformfile ); + $infoline = "Size of $transformfile: $filesize\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ( $filesize > 0 ) + { + $infoline = "Info: Returnvalue $returnvalue of $msitran is no problem :-) .\n"; + push( @installer::globals::logfileinfo, $infoline); + $returnvalue = 0; # reset the error + } + else + { + $infoline = "Filesize indicates that an error occured.\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + else + { + $infoline = "File $transformfile does not exist -> An error occured.\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + else + { + $infoline = "This is not a problematic version of msitran.exe. Therefore the error is not caused by problematic msitran.exe.\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute $msitran!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed $msitran successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + # The reference database can be deleted + + my $result = unlink($referencedbname); + # $result contains the number of deleted files + + if ( $result == 0 ) + { + $infoline = "ERROR: Could not remove file $$referencedbname !\n"; + push( @installer::globals::logfileinfo, $infoline); + installer::exiter::exit_program($infoline, "create_transforms"); + } + } +} + +######################################################################### +# The default language msi database does not need to contain +# the language in the database name. Therefore the file +# is renamed. Example: "openofficeorg20_01.msi" to "openofficeorg20.msi" +######################################################################### + +sub rename_msi_database_in_installset +{ + my ($defaultlanguage, $installdir, $allvariableshashref) = @_; + + installer::logger::include_header_into_logfile("Renaming msi database"); + + my $olddatabasename = get_msidatabasename($allvariableshashref, $defaultlanguage); + $olddatabasename = $installdir . $installer::globals::separator . $olddatabasename; + + my $newdatabasename = get_msidatabasename($allvariableshashref); + + $installer::globals::shortmsidatabasename = $newdatabasename; + + $newdatabasename = $installdir . $installer::globals::separator . $newdatabasename; + + installer::systemactions::rename_one_file($olddatabasename, $newdatabasename); + + $installer::globals::msidatabasename = $newdatabasename; +} + +######################################################################### +# Adding the language to the name of the msi databasename, +# if this is required (ADDLANGUAGEINDATABASENAME) +######################################################################### + +sub add_language_to_msi_database +{ + my ($defaultlanguage, $installdir, $allvariables) = @_; + + my $languagestring = $defaultlanguage; + if ( $allvariables->{'USELANGUAGECODE'} ) { $languagestring = installer::windows::language::get_windows_language($defaultlanguage); } + my $newdatabasename = $installer::globals::shortmsidatabasename; + $newdatabasename =~ s/\.msi\s*$/_$languagestring\.msi/; + $installer::globals::shortmsidatabasename = $newdatabasename; + $newdatabasename = $installdir . $installer::globals::separator . $newdatabasename; + + my $olddatabasename = $installer::globals::msidatabasename; + + installer::systemactions::rename_one_file($olddatabasename, $newdatabasename); + + $installer::globals::msidatabasename = $newdatabasename; +} + +########################################################################## +# Writing the databasename into the setup.ini. +########################################################################## + +sub put_databasename_into_setupini +{ + my ($setupinifile, $allvariableshashref) = @_; + + my $databasename = get_msidatabasename($allvariableshashref); + my $line = "database=" . $databasename . "\n"; + + push(@{$setupinifile}, $line); +} + +########################################################################## +# Writing the path to the instmsiw.exe into setup.ini +########################################################################## + +sub put_instmsiwpath_into_setupini +{ + my ($setupinifile) = @_; + + my $instmsiwexepath = "instmsiw.exe"; + my $line = "instmsiw=" . $instmsiwexepath . "\n"; + + push(@{$setupinifile}, $line); +} + +########################################################################## +# Writing the path to the instmsia.exe into setup.ini +########################################################################## + +sub put_instmsiapath_into_setupini +{ + my ($setupinifile) = @_; + + my $instmsiaexepath = "instmsia.exe"; + my $line = "instmsia=" . $instmsiaexepath . "\n"; + + push(@{$setupinifile}, $line); +} + +########################################################################## +# Writing the required msi version into setup.ini +########################################################################## + +sub put_msiversion_into_setupini +{ + my ($setupinifile) = @_; + + my $msiversion = "2.0"; + my $line = "msiversion=" . $msiversion . "\n"; + + push(@{$setupinifile}, $line); +} + +########################################################################## +# Writing the productname into setup.ini +########################################################################## + +sub put_productname_into_setupini +{ + my ($setupinifile, $allvariableshashref) = @_; + + my $productname = $allvariableshashref->{'PRODUCTNAME'}; + my $line = "productname=" . $productname . "\n"; + + push(@{$setupinifile}, $line); +} + +########################################################################## +# Writing the productcode into setup.ini +########################################################################## + +sub put_productcode_into_setupini +{ + my ($setupinifile) = @_; + + my $productcode = $installer::globals::productcode; + my $line = "productcode=" . $productcode . "\n"; + + push(@{$setupinifile}, $line); +} + +########################################################################## +# Writing the ProductVersion from Property table into setup.ini +########################################################################## + +sub put_productversion_into_setupini +{ + my ($setupinifile) = @_; + + my $line = "productversion=" . $installer::globals::msiproductversion . "\n"; + push(@{$setupinifile}, $line); +} + +########################################################################## +# Writing the key for Minor Upgrades into setup.ini +########################################################################## + +sub put_upgradekey_into_setupini +{ + my ($setupinifile) = @_; + + if ( $installer::globals::minorupgradekey ne "" ) + { + my $line = "upgradekey=" . $installer::globals::minorupgradekey . "\n"; + push(@{$setupinifile}, $line); + } +} + +########################################################################## +# Writing the number of languages into setup.ini +########################################################################## + +sub put_languagecount_into_setupini +{ + my ($setupinifile, $languagesarray) = @_; + + my $languagecount = $#{$languagesarray} + 1; + my $line = "count=" . $languagecount . "\n"; + + push(@{$setupinifile}, $line); +} + +########################################################################## +# Writing the defaultlanguage into setup.ini +########################################################################## + +sub put_defaultlanguage_into_setupini +{ + my ($setupinifile, $defaultlanguage) = @_; + + my $windowslanguage = installer::windows::language::get_windows_language($defaultlanguage); + my $line = "default=" . $windowslanguage . "\n"; + push(@{$setupinifile}, $line); +} + +########################################################################## +# Writing the information about transformations into setup.ini +########################################################################## + +sub put_transforms_into_setupini +{ + my ($setupinifile, $onelanguage, $counter) = @_; + + my $windowslanguage = installer::windows::language::get_windows_language($onelanguage); + my $transformfilename = "trans_" . $onelanguage . ".mst"; + + my $line = "lang" . $counter . "=" . $windowslanguage . "," . $transformfilename . "\n"; + + push(@{$setupinifile}, $line); +} + +################################################### +# Including Windows line ends in ini files +# Profiles on Windows shall have \r\n line ends +################################################### + +sub include_windows_lineends +{ + my ($onefile) = @_; + + for ( my $i = 0; $i <= $#{$onefile}; $i++ ) + { + ${$onefile}[$i] =~ s/\r?\n$/\r\n/; + } +} + +########################################################################## +# Generation the file setup.ini, that is used by the loader setup.exe. +########################################################################## + +sub create_setup_ini +{ + my ($languagesarray, $defaultlanguage, $installdir, $allvariableshashref) = @_; + + installer::logger::include_header_into_logfile("Creating setup.ini"); + + my $setupinifilename = $installdir . $installer::globals::separator . "setup.ini"; + + my @setupinifile = (); + my $setupinifile = \@setupinifile; + + my $line = "\[setup\]\n"; + push(@setupinifile, $line); + + put_databasename_into_setupini($setupinifile, $allvariableshashref); + put_instmsiwpath_into_setupini($setupinifile); + put_instmsiapath_into_setupini($setupinifile); + put_msiversion_into_setupini($setupinifile); + put_productname_into_setupini($setupinifile, $allvariableshashref); + put_productcode_into_setupini($setupinifile); + put_productversion_into_setupini($setupinifile); + put_upgradekey_into_setupini($setupinifile); + + $line = "\[languages\]\n"; + push(@setupinifile, $line); + + put_languagecount_into_setupini($setupinifile, $languagesarray); + put_defaultlanguage_into_setupini($setupinifile, $defaultlanguage); + + if ( $#{$languagesarray} > 0 ) # writing the transforms information + { + my $counter = 1; + + for ( my $i = 0; $i <= $#{$languagesarray}; $i++ ) + { + if ( ${$languagesarray}[$i] eq $defaultlanguage ) { next; } + + put_transforms_into_setupini($setupinifile, ${$languagesarray}[$i], $counter); + $counter++; + } + } + + if ( $installer::globals::iswin && $installer::globals::plat =~ /cygwin/i) # Windows line ends only for Cygwin + { + include_windows_lineends($setupinifile); + } + + installer::files::save_file($setupinifilename, $setupinifile); + + $infoline = "Generated file $setupinifilename !\n"; + push( @installer::globals::logfileinfo, $infoline); +} + +################################################################# +# Copying the files defined as ScpActions into the +# installation set. +################################################################# + +sub copy_scpactions_into_installset +{ + my ($defaultlanguage, $installdir, $allscpactions) = @_; + + installer::logger::include_header_into_logfile("Copying ScpAction files into installation set"); + + for ( my $i = 0; $i <= $#{$allscpactions}; $i++ ) + { + my $onescpaction = ${$allscpactions}[$i]; + + if ( $onescpaction->{'Name'} eq "loader.exe" ) { next; } # do not copy this ScpAction loader + + # only copying language independent files or files with the correct language (the defaultlanguage) + + my $filelanguage = $onescpaction->{'specificlanguage'}; + + if ( ($filelanguage eq $defaultlanguage) || ($filelanguage eq "") ) + { + my $sourcefile = $onescpaction->{'sourcepath'}; + my $destfile = $installdir . $installer::globals::separator . $onescpaction->{'DestinationName'}; + + installer::systemactions::copy_one_file($sourcefile, $destfile); + } + } +} + +################################################################# +# Copying the files for the Windows installer into the +# installation set (setup.exe, instmsia.exe, instmsiw.exe). +################################################################# + +sub copy_windows_installer_files_into_installset +{ + my ($installdir, $includepatharrayref, $allvariables) = @_; + + installer::logger::include_header_into_logfile("Copying Windows installer files into installation set"); + + @copyfile = (); + push(@copyfile, "instmsia.exe"); + push(@copyfile, "instmsiw.exe"); + push(@copyfile, "loader2.exe"); + + if ( $allvariables->{'NOLOADERREQUIRED'} ) { @copyfile = (); } + + for ( my $i = 0; $i <= $#copyfile; $i++ ) + { + my $filename = $copyfile[$i]; + my $sourcefileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$filename, $includepatharrayref, 1); + + if ( ! -f $$sourcefileref ) { installer::exiter::exit_program("ERROR: msi file not found: $$sourcefileref !", "copy_windows_installer_files_into_installset"); } + + my $destfile; + if ( $copyfile[$i] eq "loader2.exe" ) { $destfile = "setup.exe"; } # renaming the loader + else { $destfile = $copyfile[$i]; } + + $destfile = $installdir . $installer::globals::separator . $destfile; + + installer::systemactions::copy_one_file($$sourcefileref, $destfile); + } +} + +################################################################# +# Copying MergeModules for the Windows installer into the +# installation set. The list of MergeModules is located +# in %installer::globals::copy_msm_files +################################################################# + +sub copy_merge_modules_into_installset +{ + my ($installdir) = @_; + + installer::logger::include_header_into_logfile("Copying Merge files into installation set"); + + my $cabfile; + foreach $cabfile ( keys %installer::globals::copy_msm_files ) + { + my $sourcefile = $installer::globals::copy_msm_files{$cabfile}; + my $destfile = $installdir . $installer::globals::separator . $cabfile; + + installer::systemactions::copy_one_file($sourcefile, $destfile); + } +} + +################################################################# +# Copying the child projects into the +# installation set +################################################################# + +sub copy_child_projects_into_installset +{ + my ($installdir, $allvariables) = @_; + + my $sourcefile = ""; + my $destdir = ""; + + # adding Java + + if ( $allvariables->{'JAVAPRODUCT'} ) + { + $sourcefile = $installer::globals::javafile->{'sourcepath'}; + $destdir = $installdir . $installer::globals::separator . $installer::globals::javafile->{'Subdir'}; + if ( ! -d $destdir) { installer::systemactions::create_directory($destdir); } + installer::systemactions::copy_one_file($sourcefile, $destdir); + } + + if ( $allvariables->{'UREPRODUCT'} ) + { + $sourcefile = $installer::globals::urefile->{'sourcepath'}; + $destdir = $installdir . $installer::globals::separator . $installer::globals::urefile->{'Subdir'}; + if ( ! -d $destdir) { installer::systemactions::create_directory($destdir); } + installer::systemactions::copy_one_file($sourcefile, $destdir); + } +} + +################################################################# +# Getting a list of GUID using uuidgen.exe. +# This works only on Windows +################################################################# + +sub get_guid_list +{ + my ($number, $log) = @_; + + if ( $log ) { installer::logger::include_header_into_logfile("Generating $number GUID"); } + + my $uuidgen = "uuidgen.exe"; # Has to be in the path + + # "-c" for uppercase output + + # my $systemcall = "$uuidgen -n$number -c |"; + my $systemcall = "$uuidgen -n$number |"; + open (UUIDGEN, "$systemcall" ) or die("uuidgen is missing."); + my @uuidlist = <UUIDGEN>; + close (UUIDGEN); + + my $infoline = "Systemcall: $systemcall\n"; + if ( $log ) { push( @installer::globals::logfileinfo, $infoline); } + + my $comparenumber = $#uuidlist + 1; + + if ( $comparenumber == $number ) + { + $infoline = "Success: Executed $uuidgen successfully!\n"; + if ( $log ) { push( @installer::globals::logfileinfo, $infoline); } + } + else + { + $infoline = "ERROR: Could not execute $uuidgen successfully!\n"; + if ( $log ) { push( @installer::globals::logfileinfo, $infoline); } + } + + # uppercase, no longer "-c", because this is only supported in uuidgen.exe v.1.01 + for ( my $i = 0; $i <= $#uuidlist; $i++ ) { $uuidlist[$i] = uc($uuidlist[$i]); } + + return \@uuidlist; +} + +################################################################# +# Calculating a GUID with a string using md5. +################################################################# + +sub calculate_guid +{ + my ( $string ) = @_; + + my $guid = ""; + + my $md5 = Digest::MD5->new; + $md5->add($string); + my $digest = $md5->hexdigest; + $digest = uc($digest); + + # my $id = pack("A32", $digest); + my ($first, $second, $third, $fourth, $fifth) = unpack ('A8 A4 A4 A4 A12', $digest); + $guid = "$first-$second-$third-$fourth-$fifth"; + + return $guid; +} + +################################################################# +# Filling the component hash with the values of the +# component file. +################################################################# + +sub fill_component_hash +{ + my ($componentfile) = @_; + + my %components = (); + + for ( my $i = 0; $i <= $#{$componentfile}; $i++ ) + { + my $line = ${$componentfile}[$i]; + + if ( $line =~ /^\s*(.*?)\t(.*?)\s*$/ ) + { + my $key = $1; + my $value = $2; + + $components{$key} = $value; + } + } + + return \%components; +} + +################################################################# +# Creating a new component file, if new guids were generated. +################################################################# + +sub create_new_component_file +{ + my ($componenthash) = @_; + + my @componentfile = (); + + my $key; + + foreach $key (keys %{$componenthash}) + { + my $value = $componenthash->{$key}; + my $input = "$key\t$value\n"; + push(@componentfile ,$input); + } + + return \@componentfile; +} + +################################################################# +# Filling real component GUID into the component table. +# This works only on Windows +################################################################# + +sub set_uuid_into_component_table +{ + my ($idtdirbase, $allvariables) = @_; + + my $componenttablename = $idtdirbase . $installer::globals::separator . "Componen.idt"; + + my $componenttable = installer::files::read_file($componenttablename); + + # For update and patch reasons (small update) the GUID of an existing component must not change! + # The collection of component GUIDs is saved in the directory $installer::globals::idttemplatepath in the file "components.txt" + + my $infoline = ""; + my $counter = 0; + # my $componentfile = installer::files::read_file($installer::globals::componentfilename); + # my $componenthash = fill_component_hash($componentfile); + + for ( my $i = 3; $i <= $#{$componenttable}; $i++ ) # ignoring the first three lines + { + my $oneline = ${$componenttable}[$i]; + my $componentname = ""; + if ( $oneline =~ /^\s*(\S+?)\t/ ) { $componentname = $1; } + + my $uuid = ""; + + # if ( $componenthash->{$componentname} ) + # { + # $uuid = $componenthash->{$componentname}; + # } + # else + # { + + if ( exists($installer::globals::calculated_component_guids{$componentname})) + { + $uuid = $installer::globals::calculated_component_guids{$componentname}; + } + else + { + # Calculating new GUID with the help of the component name. + my $useooobaseversion = 1; + if ( exists($installer::globals::base_independent_components{$componentname})) { $useooobaseversion = 0; } + my $sourcestring = $componentname; + + if ( $useooobaseversion ) + { + if ( ! exists($allvariables->{'OOOBASEVERSION'}) ) { installer::exiter::exit_program("ERROR: Could not find variable \"OOOBASEVERSION\" (required value for GUID creation)!", "set_uuid_into_component_table"); } + $sourcestring = $sourcestring . "_" . $allvariables->{'OOOBASEVERSION'}; + } + $uuid = calculate_guid($sourcestring); + $counter++; + + # checking, if there is a conflict with an already created guid + if ( exists($installer::globals::allcalculated_guids{$uuid}) ) { installer::exiter::exit_program("ERROR: \"$uuid\" was already created before!", "set_uuid_into_component_table"); } + $installer::globals::allcalculated_guids{$uuid} = 1; + $installer::globals::calculated_component_guids{$componentname} = $uuid; + + # Setting new uuid + # $componenthash->{$componentname} = $uuid; + + # Setting flag + # $installer::globals::created_new_component_guid = 1; # this is very important! + } + # } + + ${$componenttable}[$i] =~ s/COMPONENTGUID/$uuid/; + } + + installer::files::save_file($componenttablename, $componenttable); + +# if ( $installer::globals::created_new_component_guid ) +# { +# # create new component file! +# $componentfile = create_new_component_file($componenthash); +# installer::worker::sort_array($componentfile); +# +# # To avoid conflict the components file cannot be saved at the same place +# # All important data have to be saved in the directory: $installer::globals::infodirectory +# my $localcomponentfilename = $installer::globals::componentfilename; +# installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$localcomponentfilename); +# $localcomponentfilename = $installer::globals::infodirectory . $installer::globals::separator . $localcomponentfilename; +# installer::files::save_file($localcomponentfilename, $componentfile); +# +# # installer::files::save_file($installer::globals::componentfilename, $componentfile); # version using new file in solver +# +# $infoline = "COMPONENTCODES: Created $counter new GUIDs for components ! \n"; +# push( @installer::globals::logfileinfo, $infoline); +# } +# else +# { +# $infoline = "SUCCESS COMPONENTCODES: All component codes exist! \n"; +# push( @installer::globals::logfileinfo, $infoline); +# } + +} + +################################################################# +# Include all cab files into the msi database. +# This works only on Windows +################################################################# + +sub include_cabs_into_msi +{ + my ($installdir) = @_; + + installer::logger::include_header_into_logfile("Including cabs into msi database"); + + my $from = cwd(); + my $to = $installdir; + + chdir($to); + + my $infoline = "Changing into directory: $to"; + push( @installer::globals::logfileinfo, $infoline); + + my $msidb = "msidb.exe"; # Has to be in the path + my $extraslash = ""; # Has to be set for non-ActiveState perl + + my $msifilename = $installer::globals::msidatabasename; + + $msifilename = installer::converter::make_path_conform($msifilename); + + if ( $ENV{'USE_SHELL'} ne "4nt" ) { + # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) + $idtdirbase =~ s/\//\\\\/g; + $msifilename =~ s/\//\\\\/g; + $extraslash = "\\"; + } + + my $allcabfiles = installer::systemactions::find_file_with_file_extension("cab", $installdir); + + for ( my $i = 0; $i <= $#{$allcabfiles}; $i++ ) + { + my $systemcall = $msidb . " -d " . $msifilename . " -a " . ${$allcabfiles}[$i]; + + my $returnvalue = system($systemcall); + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute $systemcall !\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed $systemcall successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + # deleting the cab file + + unlink(${$allcabfiles}[$i]); + + $infoline = "Deleted cab file: ${$allcabfiles}[$i]\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + $infoline = "Changing back into directory: $from"; + push( @installer::globals::logfileinfo, $infoline); + + chdir($from); +} + +################################################################# +# Executing the created batch file to pack all files. +# This works only on Windows +################################################################# + +sub execute_packaging +{ + my ($localpackjobref, $loggingdir, $allvariables) = @_; + + installer::logger::include_header_into_logfile("Packaging process"); + + installer::logger::include_timestamp_into_logfile("Performance Info: Execute packaging start"); + + my $infoline = ""; + my $from = cwd(); + my $to = $loggingdir; + + chdir($to); + $infoline = "chdir: $to \n"; + push( @installer::globals::logfileinfo, $infoline); + + # if the ddf file contains relative pathes, it is necessary to change into the temp directory + if ( $allvariables->{'RELATIVE_PATHES_IN_DDF'} ) + { + $to = $installer::globals::temppath; + chdir($to); + $infoline = "chdir: $to \n"; + push( @installer::globals::logfileinfo, $infoline); + } + + # changing the tmp directory, because makecab.exe generates temporary cab files + my $origtemppath = ""; + if ( $ENV{'TMP'} ) { $origtemppath = $ENV{'TMP'}; } + $ENV{'TMP'} = $installer::globals::temppath; # setting TMP to the new unique directory! + + my $maxmakecabcalls = 3; + my $allmakecabcalls = $#{$localpackjobref} + 1; + + for ( my $i = 0; $i <= $#{$localpackjobref}; $i++ ) + { + my $systemcall = ${$localpackjobref}[$i]; + + my $callscounter = $i + 1; + + installer::logger::print_message( "... makecab.exe ($callscounter/$allmakecabcalls) ... \n" ); + + # my $returnvalue = system($systemcall); + + for ( my $n = 1; $n <= $maxmakecabcalls; $n++ ) + { + my @ddfoutput = (); + + $infoline = "Systemcall: $systemcall"; + push( @installer::globals::logfileinfo, $infoline); + + open (DDF, "$systemcall"); + while (<DDF>) {push(@ddfoutput, $_); } + close (DDF); + + my $returnvalue = $?; # $? contains the return value of the systemcall + + if ($returnvalue) + { + if ( $n < $maxmakecabcalls ) + { + installer::logger::print_message( "makecab_error (Try $n): Trying again \n" ); + $infoline = "makecab_error (Try $n): $systemcall !"; + } + else + { + installer::logger::print_message( "ERROR (Try $n): Abort packing \n" ); + $infoline = "ERROR (Try $n): $systemcall !"; + } + + push( @installer::globals::logfileinfo, $infoline); + # for ( my $j = 0; $j <= $#ddfoutput; $j++ ) { push( @installer::globals::logfileinfo, "$ddfoutput[$j]"); } + + for ( my $m = 0; $m <= $#ddfoutput; $m++ ) + { + if ( $ddfoutput[$m] =~ /(ERROR\:.*?)\s*$/ ) + { + $infoline = $1 . "\n"; + if ( $n < $maxmakecabcalls ) { $infoline =~ s/ERROR\:/makecab_error\:/i; } + installer::logger::print_message( $infoline ); + push( @installer::globals::logfileinfo, $infoline); + } + } + + if ( $n == $maxmakecabcalls ) { installer::exiter::exit_program("ERROR: \"$systemcall\"!", "execute_packaging"); } + } + else + { + # installer::logger::print_message( "Success (Try $n): \"$systemcall\"\n" ); + $infoline = "Success (Try $n): $systemcall"; + push( @installer::globals::logfileinfo, $infoline); + last; + } + } + } + + installer::logger::include_timestamp_into_logfile("Performance Info: Execute packaging end"); + + # setting back to the original tmp directory + $ENV{'TMP'} = $origtemppath; + + chdir($from); + $infoline = "chdir: $from \n"; + push( @installer::globals::logfileinfo, $infoline); +} + +############################################################### +# Setting the global variables ProductCode and the UpgradeCode +############################################################### + +sub set_global_code_variables +{ + my ( $languagesref, $languagestringref, $allvariableshashref, $alloldproperties ) = @_; + + # In the msi template directory a files "codes.txt" has to exist, in which the ProductCode + # and the UpgradeCode for the product are defined. + # The name "codes.txt" can be overwritten in Product definition with CODEFILENAME . + # Default $installer::globals::codefilename is defined in parameter.pm. + + if ( $allvariableshashref->{'CODEFILENAME'} ) + { + $installer::globals::codefilename = $installer::globals::idttemplatepath . $installer::globals::separator . $allvariableshashref->{'CODEFILENAME'}; + installer::files::check_file($installer::globals::codefilename); + } + + my $infoline = "Using Codes file: $installer::globals::codefilename \n"; + push( @installer::globals::logfileinfo, $infoline); + + my $codefile = installer::files::read_file($installer::globals::codefilename); + + my $isopensource = 0; + if ( $allvariableshashref->{'OPENSOURCE'} ) { $isopensource = $allvariableshashref->{'OPENSOURCE'}; } + + my $onelanguage = ""; + + if ( $#{$languagesref} > 0 ) # more than one language + { + if (( ${$languagesref}[1] =~ /jp/ ) || + ( ${$languagesref}[1] =~ /ko/ ) || + ( ${$languagesref}[1] =~ /zh/ )) + { + $onelanguage = "multiasia"; + } + else + { + $onelanguage = "multiwestern"; + } + } + else # only one language + { + $onelanguage = ${$languagesref}[0]; + } + + # ProductCode must not change, if Windows patches shall be applied + if ( $installer::globals::updatedatabase ) + { + $installer::globals::productcode = $alloldproperties->{'ProductCode'}; + } + elsif ( $installer::globals::prepare_winpatch ) + { + # ProductCode has to be specified in each language + my $searchstring = "PRODUCTCODE"; + my $codeblock = installer::windows::idtglobal::get_language_block_from_language_file($searchstring, $codefile); + $installer::globals::productcode = installer::windows::idtglobal::get_code_from_code_block($codeblock, $onelanguage); + } else { + my $guidref = get_guid_list(1, 1); # only one GUID shall be generated + ${$guidref}[0] =~ s/\s*$//; # removing ending spaces + $installer::globals::productcode = "\{" . ${$guidref}[0] . "\}"; + } + + if ( $installer::globals::patch ) # patch upgrade codes are defined in soffice.lst + { + if ( $allvariableshashref->{'PATCHUPGRADECODE'} ) { $installer::globals::upgradecode = $allvariableshashref->{'PATCHUPGRADECODE'}; } + else { installer::exiter::exit_program("ERROR: PATCHUPGRADECODE not defined in list file!", "set_global_code_variables"); } + } + else + { + # UpgradeCode can take english as default, if not defined in specified language + + $searchstring = "UPGRADECODE"; # searching in the codes.txt file + $codeblock = installer::windows::idtglobal::get_language_block_from_language_file($searchstring, $codefile); + $installer::globals::upgradecode = installer::windows::idtglobal::get_language_string_from_language_block($codeblock, $onelanguage, ""); + } + + # if (( $installer::globals::productcode eq "" ) && ( ! $isopensource )) { installer::exiter::exit_program("ERROR: ProductCode for language $onelanguage not defined in $installer::globals::codefilename !", "set_global_code_variables"); } + if ( $installer::globals::upgradecode eq "" ) { installer::exiter::exit_program("ERROR: UpgradeCode not defined in $installer::globals::codefilename !", "set_global_code_variables"); } + + $infoline = "Setting ProductCode to: $installer::globals::productcode \n"; + push( @installer::globals::logfileinfo, $infoline); + $infoline = "Setting UpgradeCode to: $installer::globals::upgradecode \n"; + push( @installer::globals::logfileinfo, $infoline); + + # Adding both variables into the variables array + + $allvariableshashref->{'PRODUCTCODE'} = $installer::globals::productcode; + $allvariableshashref->{'UPGRADECODE'} = $installer::globals::upgradecode; + + $infoline = "Defined variable PRODUCTCODE: $installer::globals::productcode \n"; + push( @installer::globals::logfileinfo, $infoline); + + $infoline = "Defined variable UPGRADECODE: $installer::globals::upgradecode \n"; + push( @installer::globals::logfileinfo, $infoline); + +} + +############################################################### +# Setting the product version used in property table and +# upgrade table. Saving in global variable $msiproductversion +############################################################### + +sub set_msiproductversion +{ + my ( $allvariables ) = @_; + + my $productversion = $allvariables->{'PRODUCTVERSION'}; + + if (( $productversion =~ /^\s*\d+\s*$/ ) && ( $productversion > 255 )) { $productversion = $productversion%256; } + + if ( $productversion =~ /^\s*(\d+)\.(\d+)\.(\d+)\s*$/ ) + { + $productversion = $1 . "\." . $2 . $3 . "\." . $installer::globals::buildid; + } + elsif ( $productversion =~ /^\s*(\d+)\.(\d+)\s*$/ ) + { + $productversion = $1 . "\." . $2 . "\." . $installer::globals::buildid; + } + else + { + my $productminor = "00"; + if (( $allvariables->{'PACKAGEVERSION'} ) && ( $allvariables->{'PACKAGEVERSION'} ne "" )) + { + if ( $allvariables->{'PACKAGEVERSION'} =~ /^\s*(\d+)\.(\d+)\.(\d+)\s*$/ ) { $productminor = $2; } + } + $productversion = $productversion . "\." . $productminor . "\." . $installer::globals::buildid; + } + + $installer::globals::msiproductversion = $productversion; + + # Setting $installer::globals::msimajorproductversion, to differ between old version in upgrade table + + if ( $installer::globals::msiproductversion =~ /^\s*(\d+)\./ ) + { + my $major = $1; + $installer::globals::msimajorproductversion = $major . "\.0\.0"; + } +} + +################################################################################# +# Including the msi product version into the bootstrap.ini, Windows only +################################################################################# + +sub put_msiproductversion_into_bootstrapfile +{ + my ($filesref) = @_; + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + + if ( $onefile->{'gid'} eq "gid_Profile_Version_Ini" ) + { + my $file = installer::files::read_file($onefile->{'sourcepath'}); + + for ( my $j = 0; $j <= $#{$file}; $j++ ) + { + ${$file}[$j] =~ s/\<msiproductversion\>/$installer::globals::msiproductversion/; + } + + installer::files::save_file($onefile->{'sourcepath'}, $file); + + last; + } + } +} + +#################################################################################### +# Updating the file Property.idt dynamically +# Content: +# Property Value +#################################################################################### + +sub update_reglocat_table +{ + my ($basedir, $allvariables) = @_; + + my $reglocatfilename = $basedir . $installer::globals::separator . "RegLocat.idt"; + + # Only do something, if this file exists + + if ( -f $reglocatfilename ) + { + my $reglocatfile = installer::files::read_file($reglocatfilename); + + my $layername = ""; + if ( $allvariables->{'REGISTRYLAYERNAME'} ) + { + $layername = $allvariables->{'REGISTRYLAYERNAME'}; + } + else + { + for ( my $i = 0; $i <= $#{$reglocatfile}; $i++ ) + { + if ( ${$reglocatfile}[$i] =~ /\bLAYERNAMETEMPLATE\b/ ) + { + installer::exiter::exit_program("ERROR: Variable \"REGISTRYLAYERNAME\" has to be defined", "update_reglocat_table"); + } + } + } + + if ( $layername ne "" ) + { + # Updating the layername in + + for ( my $i = 0; $i <= $#{$reglocatfile}; $i++ ) + { + ${$reglocatfile}[$i] =~ s/\bLAYERNAMETEMPLATE\b/$layername/; + } + + # Saving the file + installer::files::save_file($reglocatfilename ,$reglocatfile); + my $infoline = "Updated idt file: $reglocatfilename\n"; + push(@installer::globals::logfileinfo, $infoline); + } + } +} + + + +#################################################################################### +# Updating the file RemoveRe.idt dynamically (RemoveRegistry.idt) +# The name of the component has to be replaced. +#################################################################################### + +sub update_removere_table +{ + my ($basedir) = @_; + + my $removeregistryfilename = $basedir . $installer::globals::separator . "RemoveRe.idt"; + + # Only do something, if this file exists + + if ( -f $removeregistryfilename ) + { + my $removeregistryfile = installer::files::read_file($removeregistryfilename); + + for ( my $i = 0; $i <= $#{$removeregistryfile}; $i++ ) + { + for ( my $i = 0; $i <= $#{$removeregistryfile}; $i++ ) + { + ${$removeregistryfile}[$i] =~ s/\bREGISTRYROOTCOMPONENT\b/$installer::globals::registryrootcomponent/; + } + } + + # Saving the file + installer::files::save_file($removeregistryfilename ,$removeregistryfile); + my $infoline = "Updated idt file: $removeregistryfilename \n"; + push(@installer::globals::logfileinfo, $infoline); + } +} + +########################################################################## +# Reading saved mappings in Files.idt and Director.idt. +# This is required, if installation sets shall be created, +# that can be used for creation of msp files. +########################################################################## + +sub read_saved_mappings +{ + installer::logger::include_header_into_logfile("Reading saved mappings from older installation sets:"); + + installer::logger::include_timestamp_into_logfile("Performance Info: Reading saved mappings start"); + + if ( $installer::globals::previous_idt_dir ) + { + my @errorlines = (); + my $errorstring = ""; + my $error_occured = 0; + my $file_error_occured = 0; + my $dir_error = 0; + + my $idtdir = $installer::globals::previous_idt_dir; + $idtdir =~ s/\Q$installer::globals::separator\E\s*$//; + + # Reading File.idt + + my $idtfile = $idtdir . $installer::globals::separator . "File.idt"; + push( @installer::globals::globallogfileinfo, "\nAnalyzing file: $idtfile\n" ); + if ( ! -f $idtfile ) { push( @installer::globals::globallogfileinfo, "Warning: File $idtfile does not exist!\n" ); } + + my $n = 0; + open (F, "<$idtfile") || installer::exiter::exit_program("ERROR: Cannot open file $idtfile for reading", "read_saved_mappings"); + <F>; <F>; <F>; + while (<F>) + { + m/^([^\t]+)\t([^\t]+)\t((.*)\|)?([^\t]*)/; + print "AAA1: \$1: $1, \$2: $2, \$3: $3, \$4: $4, \$5: $5\n"; + next if ("$1" eq "$5") && (!defined($3)); + my $lc1 = lc($1); + + if ( exists($installer::globals::savedmapping{"$2/$5"})) + { + if ( ! $file_error_occured ) + { + $errorstring = "\nErrors in $idtfile: \n"; + push(@errorlines, $errorstring); + } + $errorstring = "Duplicate savedmapping{" . "$2/$5}\n"; + push(@errorlines, $errorstring); + $error_occured = 1; + $file_error_occured = 1; + } + + if ( exists($installer::globals::savedrevmapping{$lc1})) + { + if ( ! $file_error_occured ) + { + $errorstring = "\nErrors in $idtfile: \n"; + push(@errorlines, $errorstring); + } + $errorstring = "Duplicate savedrevmapping{" . "$lc1}\n"; + push(@errorlines, $errorstring); + $error_occured = 1; + $file_error_occured = 1; + } + + my $shortname = $4 || ''; + + # Don't reuse illegal 8.3 mappings that we used to generate in 2.0.4 + if (index($shortname, '.') > 8 || + (index($shortname, '.') == -1 && length($shortname) > 8)) + { + $shortname = ''; + } + + if (( $shortname ne '' ) && ( index($shortname, '~') > 0 ) && ( exists($installer::globals::savedrev83mapping{$shortname}) )) + { + if ( ! $file_error_occured ) + { + $errorstring = "\nErrors in $idtfile: \n"; + push(@errorlines, $errorstring); + } + $errorstring = "Duplicate savedrev83mapping{" . "$shortname}\n"; + push(@errorlines, $errorstring); + $error_occured = 1; + $file_error_occured = 1; + } + + $installer::globals::savedmapping{"$2/$5"} = "$1;$shortname"; + $installer::globals::savedrevmapping{lc($1)} = "$2/$5"; + $installer::globals::savedrev83mapping{$shortname} = "$2/$5" if $shortname ne ''; + $n++; + } + + close (F); + + push( @installer::globals::globallogfileinfo, "Read $n old file table key or 8.3 name mappings from $idtfile\n" ); + + # Reading Director.idt + + $idtfile = $idtdir . $installer::globals::separator . "Director.idt"; + push( @installer::globals::globallogfileinfo, "\nAnalyzing file $idtfile\n" ); + if ( ! -f $idtfile ) { push( @installer::globals::globallogfileinfo, "Warning: File $idtfile does not exist!\n" ); } + + $n = 0; + open (F, "<$idtfile") || installer::exiter::exit_program("ERROR: Cannot open file $idtfile for reading", "read_saved_mappings"); + <F>; <F>; <F>; + while (<F>) + { + m/^([^\t]+)\t([^\t]+)\t(([^~]+~\d.*)\|)?([^\t]*)/; + next if (!defined($3)); + my $lc1 = lc($1); + + print "AAA2: \$1: $1, \$2: $2, \$3: $3\n"; + + if ( exists($installer::globals::saved83dirmapping{$1}) ) + { + if ( ! $dir_error_occured ) + { + $errorstring = "\nErrors in $idtfile: \n"; + push(@errorlines, $errorstring); + } + $errorstring = "Duplicate saved83dirmapping{" . "$1}\n"; + push(@errorlines, $errorstring); + $error_occured = 1; + $dir_error_occured = 1; + } + + $installer::globals::saved83dirmapping{$1} = $4; + $n++; + } + close (F); + + push( @installer::globals::globallogfileinfo, "Read $n old directory 8.3 name mappings from $idtfile\n" ); + + # Analyzing errors + + if ( $error_occured ) + { + for ( my $i = 0; $i <= $#errorlines; $i++ ) + { + print "$errorlines[$i]"; + push( @installer::globals::globallogfileinfo, "$errorlines[$i]"); + } + installer::exiter::exit_program("ERROR: Duplicate entries in saved mappings!", "read_saved_mappings"); + } + } else { + # push( @installer::globals::globallogfileinfo, "WARNING: Windows patch shall be prepared, but PREVIOUS_IDT_DIR is not set!\n" ); + installer::exiter::exit_program("ERROR: Windows patch shall be prepared, but environment variable PREVIOUS_IDT_DIR is not set!", "read_saved_mappings"); + } + + installer::logger::include_timestamp_into_logfile("Performance Info: Reading saved mappings end"); +} + +1; + diff --git a/solenv/bin/modules/installer/windows/msp.pm b/solenv/bin/modules/installer/windows/msp.pm new file mode 100644 index 000000000000..27f3342e4cc9 --- /dev/null +++ b/solenv/bin/modules/installer/windows/msp.pm @@ -0,0 +1,1229 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: msp.pm,v $ +# +# $Revision: 1.1.2.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::msp; + +use installer::control; +use installer::converter; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::logger; +use installer::pathanalyzer; +use installer::systemactions; +use installer::windows::admin; +use installer::windows::idtglobal; +use installer::windows::update; + +################################################################################# +# Making all required administrative installations +################################################################################# + +sub install_installation_sets +{ + my ($installationdir) = @_; + + # Finding the msi database in the new installation set, that is located in $installationdir + + my $msifiles = installer::systemactions::find_file_with_file_extension("msi", $installationdir); + + if ( $#{$msifiles} < 0 ) { installer::exiter::exit_program("ERROR: Did not find msi database in directory $installationdir", "create_msp_patch"); } + if ( $#{$msifiles} > 0 ) { installer::exiter::exit_program("ERROR: Did find more than one msi database in directory $installationdir", "create_msp_patch"); } + + my $newinstallsetdatabasepath = $installationdir . $installer::globals::separator . ${$msifiles}[0]; + my $oldinstallsetdatabasepath = $installer::globals::updatedatabasepath; + + # Creating temp directory again + installer::systemactions::create_directory_structure($installer::globals::temppath); + + # Creating old installation directory + my $dirname = "admin"; + my $installpath = $installer::globals::temppath . $installer::globals::separator . $dirname; + if ( ! -d $installpath) { installer::systemactions::create_directory($installpath); } + + my $oldinstallpath = $installpath . $installer::globals::separator . "old"; + my $newinstallpath = $installpath . $installer::globals::separator . "new"; + + if ( ! -d $oldinstallpath) { installer::systemactions::create_directory($oldinstallpath); } + if ( ! -d $newinstallpath) { installer::systemactions::create_directory($newinstallpath); } + + my $olddatabase = installer::windows::admin::make_admin_install($oldinstallsetdatabasepath, $oldinstallpath); + my $newdatabase = installer::windows::admin::make_admin_install($newinstallsetdatabasepath, $newinstallpath); + + return ($olddatabase, $newdatabase); +} + +################################################################################# +# Extracting all tables from a pcp file +################################################################################# + +sub extract_all_tables_from_pcpfile +{ + my ($fullpcpfilepath, $workdir) = @_; + + my $msidb = "msidb.exe"; # Has to be in the path + my $infoline = ""; + my $systemcall = ""; + my $returnvalue = ""; + + # Export of all tables by using "*" + + $systemcall = $msidb . " -d " . $fullpcpfilepath . " -f " . $workdir . " -e \*"; + $returnvalue = system($systemcall); + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute $systemcall !\n"; + push( @installer::globals::logfileinfo, $infoline); + installer::exiter::exit_program("ERROR: Could not exclude tables from pcp file: $fullpcpfilepath !", "extract_all_tables_from_msidatabase"); + } + else + { + $infoline = "Success: Executed $systemcall successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +################################################################################# +# Include tables into a pcp file +################################################################################# + +sub include_tables_into_pcpfile +{ + my ($fullpcpfilepath, $workdir, $tables) = @_; + + my $msidb = "msidb.exe"; # Has to be in the path + my $infoline = ""; + my $systemcall = ""; + my $returnvalue = ""; + + # Make all table 8+3 conform + my $alltables = installer::converter::convert_stringlist_into_array(\$tables, " "); + + for ( my $i = 0; $i <= $#{$alltables}; $i++ ) + { + my $tablename = ${$alltables}[$i]; + $tablename =~ s/\s*$//; + my $namelength = length($tablename); + if ( $namelength > 8 ) + { + my $newtablename = substr($tablename, 0, 8); # name, offset, length + my $oldfile = $workdir . $installer::globals::separator . $tablename . ".idt"; + my $newfile = $workdir . $installer::globals::separator . $newtablename . ".idt"; + if ( -f $newfile ) { unlink $newfile; } + installer::systemactions::copy_one_file($oldfile, $newfile); + } + } + + # Import of tables + + $systemcall = $msidb . " -d " . $fullpcpfilepath . " -f " . $workdir . " -i " . $tables; + + $returnvalue = system($systemcall); + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute $systemcall !\n"; + push( @installer::globals::logfileinfo, $infoline); + installer::exiter::exit_program("ERROR: Could not include tables into pcp file: $fullpcpfilepath !", "include_tables_into_pcpfile"); + } + else + { + $infoline = "Success: Executed $systemcall successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +################################################################################# +# Calling msimsp.exe +################################################################################# + +sub execute_msimsp +{ + my ($fullpcpfilename, $mspfilename, $localmspdir) = @_; + + my $msimsp = "msimsp.exe"; # Has to be in the path + my $infoline = ""; + my $systemcall = ""; + my $returnvalue = ""; + my $logfilename = $localmspdir . $installer::globals::separator . "msimsp.log"; + + # Using a specific temp for each msimsp.exe process + # Creating temp directory again (should already have happened) + installer::systemactions::create_directory_structure($installer::globals::temppath); + + # Creating old installation directory + my $dirname = "msimsptemp"; + my $msimsptemppath = $installer::globals::temppath . $installer::globals::separator . $dirname; + if ( ! -d $msimsptemppath) { installer::systemactions::create_directory($msimsptemppath); } + + # r:\msvc9p\PlatformSDK\v6.1\bin\msimsp.exe -s c:\patch\hotfix_qfe1.pcp -p c:\patch\patch_ooo3_m2_m3.msp -l c:\patch\patch_ooo3_m2_m3.log + + if ( -f $logfilename ) { unlink $logfilename; } + + $systemcall = $msimsp . " -s " . $fullpcpfilename . " -p " . $mspfilename . " -l " . $logfilename . " -f " . $msimsptemppath; + installer::logger::print_message( "... $systemcall ...\n" ); + + $returnvalue = system($systemcall); + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute $systemcall !\n"; + push( @installer::globals::logfileinfo, $infoline); + installer::exiter::exit_program("ERROR: Could not execute $systemcall !", "execute_msimsp"); + } + else + { + $infoline = "Success: Executed $systemcall successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + return $logfilename; +} + +#################################################################### +# Checking existence and saving all tables, that need to be edited +#################################################################### + +sub check_and_save_tables +{ + my ($tablelist, $workdir) = @_; + + my $tables = installer::converter::convert_stringlist_into_array(\$tablelist, " "); + + for ( my $i = 0; $i <= $#{$tables}; $i++ ) + { + my $filename = ${$tables}[$i]; + $filename =~ s/\s*$//; + my $fullfilename = $workdir . $installer::globals::separator . $filename . ".idt"; + + if ( ! -f $fullfilename ) { installer::exiter::exit_program("ERROR: Required idt file could not be found: \"$fullfilename\"!", "check_and_save_tables"); } + + my $savfilename = $fullfilename . ".sav"; + installer::systemactions::copy_one_file($fullfilename, $savfilename); + } +} + +#################################################################### +# Setting the name of the msp database +#################################################################### + +sub set_mspfilename +{ + my ($allvariables, $mspdir) = @_; + + my $databasename = $allvariables->{'PRODUCTNAME'} . $allvariables->{'PRODUCTVERSION'}; + $databasename = lc($databasename); + $databasename =~ s/\.//g; + $databasename =~ s/\-//g; + $databasename =~ s/\s//g; + + # possibility to overwrite the name with variable DATABASENAME + # if ( $allvariables->{'DATABASENAME'} ) { $databasename = $allvariables->{'DATABASENAME'}; } + + # Adding patch info to database name + # if ( $installer::globals::buildid ) { $databasename = $databasename . "_" . $installer::globals::buildid; } + + # if ( $allvariables->{'VENDORPATCHVERSION'} ) { $databasename = $databasename . "_" . $allvariables->{'VENDORPATCHVERSION'}; } + + + if (( $allvariables->{'SERVICEPACK'} ) && ( $allvariables->{'SERVICEPACK'} == 1 )) + { + my $windowspatchlevel = 0; + if ( $allvariables->{'WINDOWSPATCHLEVEL'} ) { $windowspatchlevel = $allvariables->{'WINDOWSPATCHLEVEL'}; } + $databasename = $databasename . "_servicepack_" . $windowspatchlevel; + } + else + { + my $hotfixaddon = "hotfix_"; + $hotfixaddon = $hotfixaddon . $installer::globals::buildid; + my $cwsname = ""; + if ( $ENV{'CWS_WORK_STAMP'} ) { $hotfixaddon = $ENV{'CWS_WORK_STAMP'}; } + if ( $allvariables->{'OVERWRITE_CWSNAME'} ) { $hotfixaddon = $allvariables->{'OVERWRITE_CWSNAME'}; } + $databasename = $databasename . "_" . $hotfixaddon; + } + + $databasename = $databasename . ".msp"; + + my $fullmspname = $mspdir . $installer::globals::separator . $databasename; + + return $fullmspname; +} + +#################################################################### +# Editing table Properties +#################################################################### + +sub change_properties_table +{ + my ($localmspdir, $mspfilename) = @_; + + my $infoline = "Changing content of table \"Properties\"\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $filename = $localmspdir . $installer::globals::separator . "Properties.idt"; + if ( ! -f $filename ) { installer::exiter::exit_program("ERROR: Could not find file \"$filename\" !", "change_properties_table"); } + + my $filecontent = installer::files::read_file($filename); + + + my $guidref = installer::windows::msiglobal::get_guid_list(1, 1); + ${$guidref}[0] =~ s/\s*$//; # removing ending spaces + my $patchcode = "\{" . ${$guidref}[0] . "\}"; + + # Setting "PatchOutputPath" + my $found_patchoutputpath = 0; + my $found_patchguid = 0; + + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if ( ${$filecontent}[$i] =~ /^\s*PatchOutputPath\t(.*?)\s*$/ ) + { + my $oldvalue = $1; + ${$filecontent}[$i] =~ s/\Q$oldvalue\E/$mspfilename/; + $found_patchoutputpath = 1; + } + + if ( ${$filecontent}[$i] =~ /^\s*PatchGUID\t(.*?)\s*$/ ) + { + my $oldvalue = $1; + ${$filecontent}[$i] =~ s/\Q$oldvalue\E/$patchcode/; + $found_patchguid = 1; + } + } + + if ( ! $found_patchoutputpath ) + { + my $newline = "PatchOutputPath\t$mspfilename\n"; + push(@{$filecontent}, $newline); + } + + if ( ! $found_patchguid ) + { + my $newline = "PatchGUID\t$patchcode\n"; + push(@{$filecontent}, $newline); + } + + # saving file + installer::files::save_file($filename, $filecontent); +} + +#################################################################### +# Editing table TargetImages +#################################################################### + +sub change_targetimages_table +{ + my ($localmspdir, $olddatabase) = @_; + + my $infoline = "Changing content of table \"TargetImages\"\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $filename = $localmspdir . $installer::globals::separator . "TargetImages.idt"; + if ( ! -f $filename ) { installer::exiter::exit_program("ERROR: Could not find file \"$filename\" !", "change_targetimages_table"); } + + my $filecontent = installer::files::read_file($filename); + my @newcontent = (); + + # Copying the header + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) { if ( $i < 3 ) { push(@newcontent, ${$filecontent}[$i]); } } + + #Adding all targets + my $newline = "T1\t$olddatabase\t\tU1\t1\t0x00000922\t1\n"; + push(@newcontent, $newline); + + # saving file + installer::files::save_file($filename, \@newcontent); +} + +#################################################################### +# Editing table UpgradedImages +#################################################################### + +sub change_upgradedimages_table +{ + my ($localmspdir, $newdatabase) = @_; + + my $infoline = "Changing content of table \"UpgradedImages\"\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $filename = $localmspdir . $installer::globals::separator . "UpgradedImages.idt"; + if ( ! -f $filename ) { installer::exiter::exit_program("ERROR: Could not find file \"$filename\" !", "change_upgradedimages_table"); } + + my $filecontent = installer::files::read_file($filename); + my @newcontent = (); + + # Copying the header + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) { if ( $i < 3 ) { push(@newcontent, ${$filecontent}[$i]); } } + + # Syntax: Upgraded MsiPath PatchMsiPath SymbolPaths Family + + # default values + my $upgraded = "U1"; + my $msipath = $newdatabase; + my $patchmsipath = ""; + my $symbolpaths = ""; + my $family = "22334455"; + + if ( $#{$filecontent} >= 3 ) + { + my $line = ${$filecontent}[3]; + if ( $line =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) + { + $upgraded = $1; + $patchmsipath = $3; + $symbolpaths = $4; + $family = $5; + } + } + + #Adding sequence line, saving PatchFamily + my $newline = "$upgraded\t$msipath\t$patchmsipath\t$symbolpaths\t$family\n"; + push(@newcontent, $newline); + + # saving file + installer::files::save_file($filename, \@newcontent); +} + +#################################################################### +# Editing table ImageFamilies +#################################################################### + +sub change_imagefamilies_table +{ + my ($localmspdir) = @_; + + my $infoline = "Changing content of table \"ImageFamilies\"\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $filename = $localmspdir . $installer::globals::separator . "ImageFamilies.idt"; + if ( ! -f $filename ) { installer::exiter::exit_program("ERROR: Could not find file \"$filename\" !", "change_imagefamilies_table"); } + + my $filecontent = installer::files::read_file($filename); + my @newcontent = (); + + # Copying the header + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) { if ( $i < 3 ) { push(@newcontent, ${$filecontent}[$i]); } } + + # Syntax: Family MediaSrcPropName MediaDiskId FileSequenceStart DiskPrompt VolumeLabel + # "FileSequenceStart has to be set + + # Default values: + + my $family = "22334455"; + my $mediasrcpropname = "MediaSrcPropName"; + my $mediadiskid = "2"; + my $filesequencestart = get_filesequencestart(); + my $diskprompt = ""; + my $volumelabel = ""; + + if ( $#{$filecontent} >= 3 ) + { + my $line = ${$filecontent}[3]; + if ( $line =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) + { + $family = $1; + $mediasrcpropname = $2; + $mediadiskid = $3; + $diskprompt = $5; + $volumelabel = $6; + } + } + + #Adding sequence line + my $newline = "$family\t$mediasrcpropname\t$mediadiskid\t$filesequencestart\t$diskprompt\t$volumelabel\n"; + push(@newcontent, $newline); + + # saving file + installer::files::save_file($filename, \@newcontent); +} + +#################################################################### +# Setting start sequence for patch +#################################################################### + +sub get_filesequencestart +{ + my $sequence = 1000; # default + + if ( $installer::globals::updatelastsequence ) { $sequence = $installer::globals::updatelastsequence + 500; } + + return $sequence; +} + +#################################################################### +# Setting time value into pcp file +# Format mm/dd/yyyy hh:mm +#################################################################### + +sub get_patchtime_value +{ + # Syntax: 8/8/2008 11:55 + my $minute = (localtime())[1]; + my $hour = (localtime())[2]; + my $day = (localtime())[3]; + my $month = (localtime())[4]; + my $year = 1900 + (localtime())[5]; + + $month++; # zero based month + if ( $minute < 10 ) { $minute = "0" . $minute; } + if ( $hour < 10 ) { $hour = "0" . $hour; } + + my $timestring = $month . "/" . $day . "/" . $year . " " . $hour . ":" . $minute; + + return $timestring; +} + +################################################################################# +# Checking, if this is the correct database. +################################################################################# + +sub correct_langs +{ + my ($langs, $languagestringref) = @_; + + my $correct_langs = 0; + + # Comparing $langs with $languagestringref + + my $langlisthash = installer::converter::convert_stringlist_into_hash(\$langs, ","); + my $langstringhash = installer::converter::convert_stringlist_into_hash($languagestringref, "_"); + + my $not_included = 0; + foreach my $onelang ( keys %{$langlisthash} ) + { + if ( ! exists($langstringhash->{$onelang}) ) + { + $not_included = 1; + last; + } + } + + if ( ! $not_included ) + { + foreach my $onelanguage ( keys %{$langstringhash} ) + { + if ( ! exists($langlisthash->{$onelanguage}) ) + { + $not_included = 1; + last; + } + } + + if ( ! $not_included ) { $correct_langs = 1; } + } + + return $correct_langs; +} + +################################################################################# +# Searching for the path to the reference database for this special product. +################################################################################# + +sub get_patchid_from_list +{ + my ($filecontent, $languagestringref, $filename) = @_; + + my $patchid = ""; + + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + my $line = ${$filecontent}[$i]; + if ( $line =~ /^\s*$/ ) { next; } # empty line + if ( $line =~ /^\s*\#/ ) { next; } # comment line + + if ( $line =~ /^\s*(.+?)\s*=\s*(.+?)\s*$/ ) + { + my $langs = $1; + my $localpatchid = $2; + + if ( correct_langs($langs, $languagestringref) ) + { + $patchid = $localpatchid; + last; + } + } + else + { + installer::exiter::exit_program("ERROR: Wrong syntax in file: $filename! Line: \"$line\"", "get_patchid_from_list"); + } + } + + return $patchid; +} + +#################################################################### +# Editing table PatchMetadata +#################################################################### + +sub change_patchmetadata_table +{ + my ($localmspdir, $allvariables, $languagestringref) = @_; + + my $infoline = "Changing content of table \"PatchMetadata\"\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $filename = $localmspdir . $installer::globals::separator . "PatchMetadata.idt"; + if ( ! -f $filename ) { installer::exiter::exit_program("ERROR: Could not find file \"$filename\" !", "change_patchmetadata_table"); } + + my $filecontent = installer::files::read_file($filename); + my @newcontent = (); + + # Syntax: Company Property Value + # Interesting properties: "Classification" and "CreationTimeUTC" + + my $classification_set = 0; + my $creationtime_set = 0; + my $targetproductname_set = 0; + my $manufacturer_set = 0; + my $displayname_set = 0; + my $description_set = 0; + my $allowremoval_set = 0; + + my $defaultcompany = ""; + + my $classificationstring = "Classification"; + my $classificationvalue = "Hotfix"; + if (( $allvariables->{'SERVICEPACK'} ) && ( $allvariables->{'SERVICEPACK'} == 1 )) { $classificationvalue = "ServicePack"; } + + my $allowremovalstring = "AllowRemoval"; + my $allowremovalvalue = "1"; + if (( exists($allvariables->{'MSPALLOWREMOVAL'}) ) && ( $allvariables->{'MSPALLOWREMOVAL'} == 0 )) { $allowremovalvalue = 0; } + + my $timestring = "CreationTimeUTC"; + # Syntax: 8/8/2008 11:55 + my $timevalue = get_patchtime_value(); + + my $targetproductnamestring = "TargetProductName"; + my $targetproductnamevalue = $allvariables->{'PRODUCTNAME'}; + if ( $allvariables->{'PROPERTYTABLEPRODUCTNAME'} ) { $targetproductnamevalue = $allvariables->{'PROPERTYTABLEPRODUCTNAME'}; } + + my $manufacturerstring = "ManufacturerName"; + my $manufacturervalue = "OpenOffice.org"; + if ( $installer::globals::longmanufacturer ) { $manufacturervalue = $installer::globals::longmanufacturer; } + + my $displaynamestring = "DisplayName"; + my $descriptionstring = "Description"; + my $displaynamevalue = ""; + my $descriptionvalue = ""; + + my $base = $allvariables->{'PRODUCTNAME'} . " " . $allvariables->{'PRODUCTVERSION'}; + if ( $installer::globals::languagepack ) { $base = $targetproductnamevalue; } + + my $windowspatchlevel = 0; + if ( $allvariables->{'WINDOWSPATCHLEVEL'} ) { $windowspatchlevel = $allvariables->{'WINDOWSPATCHLEVEL'}; } + + my $displayaddon = ""; + if ( $allvariables->{'PATCHDISPLAYADDON'} ) { $displayaddon = $allvariables->{'PATCHDISPLAYADDON'}; } + + my $cwsname = ""; + if ( $ENV{'CWS_WORK_STAMP'} ) { $cwsname = $ENV{'CWS_WORK_STAMP'}; } + if (( $cwsname ne "" ) && ( $allvariables->{'OVERWRITE_CWSNAME'} )) { $cwsname = $allvariables->{'OVERWRITE_CWSNAME'}; } + + my $patchsequence = get_patchsequence($allvariables); + + if (( $allvariables->{'SERVICEPACK'} ) && ( $allvariables->{'SERVICEPACK'} == 1 )) + { + $displaynamevalue = $base . " ServicePack " . $windowspatchlevel . " " . $patchsequence . " Build: " . $installer::globals::buildid; + $descriptionvalue = $base . " ServicePack " . $windowspatchlevel . " " . $patchsequence . " Build: " . $installer::globals::buildid; + } + else + { + $displaynamevalue = $base . " Hotfix " . $cwsname . " " . $displayaddon . " " . $patchsequence . " Build: " . $installer::globals::buildid; + $descriptionvalue = $base . " Hotfix " . $cwsname . " " . $displayaddon . " " . $patchsequence . " Build: " . $installer::globals::buildid; + $displaynamevalue =~ s/ / /g; + $descriptionvalue =~ s/ / /g; + $displaynamevalue =~ s/ / /g; + $descriptionvalue =~ s/ / /g; + $displaynamevalue =~ s/ / /g; + $descriptionvalue =~ s/ / /g; + } + + if ( $allvariables->{'MSPPATCHNAMELIST'} ) + { + my $patchnamelistfile = $allvariables->{'MSPPATCHNAMELIST'}; + $patchnamelistfile = $installer::globals::idttemplatepath . $installer::globals::separator . $patchnamelistfile; + if ( ! -f $patchnamelistfile ) { installer::exiter::exit_program("ERROR: Could not find file \"$patchnamelistfile\".", "change_patchmetadata_table"); } + my $filecontent = installer::files::read_file($patchnamelistfile); + + # Get name and path of reference database + my $patchid = get_patchid_from_list($filecontent, $languagestringref, $patchnamelistfile); + + if ( $patchid eq "" ) { installer::exiter::exit_program("ERROR: Could not find file patchid in file \"$patchnamelistfile\" for language(s) \"$$languagestringref\".", "change_patchmetadata_table"); } + + # Setting language specific patch id + } + + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\s*$/ ) + { + my $company = $1; + my $property = $2; + my $value = $3; + + if ( $property eq $classificationstring ) + { + ${$filecontent}[$i] = "$company\t$property\t$classificationvalue\n"; + $classification_set = 1; + } + + if ( $property eq $allowremovalstring ) + { + ${$filecontent}[$i] = "$company\t$property\t$allowremovalvalue\n"; + $allowremoval_set = 1; + } + + if ( $property eq $timestring ) + { + ${$filecontent}[$i] = "$company\t$property\t$timevalue\n"; + $creationtime_set = 1; + } + + if ( $property eq $targetproductnamestring ) + { + ${$filecontent}[$i] = "$company\t$property\t$targetproductnamevalue\n"; + $targetproductname_set = 1; + } + + if ( $property eq $manufacturerstring ) + { + ${$filecontent}[$i] = "$company\t$property\t$manufacturervalue\n"; + $manufacturer_set = 1; + } + + if ( $property eq $displaynamestring ) + { + ${$filecontent}[$i] = "$company\t$property\t$displaynamevalue\n"; + $displayname_set = 1; + } + + if ( $property eq $descriptionstring ) + { + ${$filecontent}[$i] = "$company\t$property\t$descriptionvalue\n"; + $description_set = 1; + } + } + + push(@newcontent, ${$filecontent}[$i]); + } + + if ( ! $classification_set ) + { + my $line = "$defaultcompany\t$classificationstring\t$classificationvalue\n"; + push(@newcontent, $line); + } + + if ( ! $allowremoval_set ) + { + my $line = "$defaultcompany\t$classificationstring\t$allowremovalvalue\n"; + push(@newcontent, $line); + } + + if ( ! $allowremoval_set ) + { + my $line = "$defaultcompany\t$classificationstring\t$allowremovalvalue\n"; + push(@newcontent, $line); + } + + if ( ! $creationtime_set ) + { + my $line = "$defaultcompany\t$timestring\t$timevalue\n"; + push(@newcontent, $line); + } + + if ( ! $targetproductname_set ) + { + my $line = "$defaultcompany\t$targetproductnamestring\t$targetproductnamevalue\n"; + push(@newcontent, $line); + } + + if ( ! $manufacturer_set ) + { + my $line = "$defaultcompany\t$manufacturerstring\t$manufacturervalue\n"; + push(@newcontent, $line); + } + + if ( ! $displayname_set ) + { + my $line = "$defaultcompany\t$displaynamestring\t$displaynamevalue\n"; + push(@newcontent, $line); + } + + if ( ! $description_set ) + { + my $line = "$defaultcompany\t$descriptionstring\t$descriptionvalue\n"; + push(@newcontent, $line); + } + + # saving file + installer::files::save_file($filename, \@newcontent); +} + +#################################################################### +# Editing table PatchSequence +#################################################################### + +sub change_patchsequence_table +{ + my ($localmspdir, $allvariables) = @_; + + my $infoline = "Changing content of table \"PatchSequence\"\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $filename = $localmspdir . $installer::globals::separator . "PatchSequence.idt"; + if ( ! -f $filename ) { installer::exiter::exit_program("ERROR: Could not find file \"$filename\" !", "change_patchsequence_table"); } + + my $filecontent = installer::files::read_file($filename); + my @newcontent = (); + + # Copying the header + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) { if ( $i < 3 ) { push(@newcontent, ${$filecontent}[$i]); } } + + # Syntax: PatchFamily Target Sequence Supersede + + my $patchfamily = "SO"; + my $target = ""; + my $patchsequence = get_patchsequence($allvariables); + my $supersede = get_supersede($allvariables); + + if ( $#{$filecontent} >= 3 ) + { + my $line = ${$filecontent}[3]; + if ( $line =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\s$/ ) + { + $patchfamily = $1; + $target = $2; + } + } + + #Adding sequence line, saving PatchFamily + my $newline = "$patchfamily\t$target\t$patchsequence\t$supersede\n"; + push(@newcontent, $newline); + + # saving file + installer::files::save_file($filename, \@newcontent); +} + +#################################################################### +# Setting supersede, "0" for Hotfixes, "1" for ServicePack +#################################################################### + +sub get_supersede +{ + my ( $allvariables ) = @_; + + my $supersede = 0; # if not defined, this is a Hotfix + + if (( $allvariables->{'SERVICEPACK'} ) && ( $allvariables->{'SERVICEPACK'} == 1 )) { $supersede = 1; } + + return $supersede; +} + +#################################################################### +# Setting the sequence of the patch +#################################################################### + +sub get_patchsequence +{ + my ( $allvariables ) = @_; + + my $patchsequence = "1.0"; + + if ( ! $allvariables->{'PACKAGEVERSION'} ) { installer::exiter::exit_program("ERROR: PACKAGEVERSION must be set for msp patch creation!", "get_patchsequence"); } + + my $packageversion = $allvariables->{'PACKAGEVERSION'}; + + if ( $packageversion =~ /^\s*(\d+)\.(\d+)\.(\d+)\s*$/ ) + { + my $major = $1; + my $minor = $2; + my $micro = $3; + my $concat = 100 * $minor + $micro; + $packageversion = $major . "\." . $concat; + } + my $vendornumber = 0; + if ( $allvariables->{'VENDORPATCHVERSION'} ) { $vendornumber = $allvariables->{'VENDORPATCHVERSION'}; } + $patchsequence = $packageversion . "\." . $installer::globals::buildid . "\." . $vendornumber; + + if ( $allvariables->{'PATCHSEQUENCE'} ) { $patchsequence = $allvariables->{'PATCHSEQUENCE'}; } + + return $patchsequence; +} + +#################################################################### +# Editing all tables from pcp file, that need to be edited +#################################################################### + +sub edit_tables +{ + my ($tablelist, $localmspdir, $olddatabase, $newdatabase, $mspfilename, $allvariables, $languagestringref) = @_; + + # table list contains: my $tablelist = "Properties TargetImages UpgradedImages ImageFamilies PatchMetadata PatchSequence"; + + change_properties_table($localmspdir, $mspfilename); + change_targetimages_table($localmspdir, $olddatabase); + change_upgradedimages_table($localmspdir, $newdatabase); + change_imagefamilies_table($localmspdir); + change_patchmetadata_table($localmspdir, $allvariables, $languagestringref); + change_patchsequence_table($localmspdir, $allvariables); +} + +################################################################################# +# Checking, if this is the correct database. +################################################################################# + +sub correct_patch +{ + my ($product, $pro, $langs, $languagestringref) = @_; + + my $correct_patch = 0; + + # Comparing $product with $installer::globals::product and + # $pro with $installer::globals::pro and + # $langs with $languagestringref + + my $product_is_good = 0; + + my $localproduct = $installer::globals::product; + if ( $installer::globals::languagepack ) { $localproduct = $localproduct . "LanguagePack"; } + + if ( $product eq $localproduct ) { $product_is_good = 1; } + + if ( $product_is_good ) + { + my $pro_is_good = 0; + + if ((( $pro eq "pro" ) && ( $installer::globals::pro )) || (( $pro eq "nonpro" ) && ( ! $installer::globals::pro ))) { $pro_is_good = 1; } + + if ( $pro_is_good ) + { + my $langlisthash = installer::converter::convert_stringlist_into_hash(\$langs, ","); + my $langstringhash = installer::converter::convert_stringlist_into_hash($languagestringref, "_"); + + my $not_included = 0; + foreach my $onelang ( keys %{$langlisthash} ) + { + if ( ! exists($langstringhash->{$onelang}) ) + { + $not_included = 1; + last; + } + } + + if ( ! $not_included ) + { + foreach my $onelanguage ( keys %{$langstringhash} ) + { + if ( ! exists($langlisthash->{$onelanguage}) ) + { + $not_included = 1; + last; + } + } + + if ( ! $not_included ) { $correct_patch = 1; } + } + } + } + + return $correct_patch; +} + +################################################################################# +# Searching for the path to the required patch for this special product. +################################################################################# + +sub get_requiredpatchfile_from_list +{ + my ($filecontent, $languagestringref, $filename) = @_; + + my $patchpath = ""; + + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + my $line = ${$filecontent}[$i]; + if ( $line =~ /^\s*$/ ) { next; } # empty line + if ( $line =~ /^\s*\#/ ) { next; } # comment line + + if ( $line =~ /^\s*(.+?)\s*\t+\s*(.+?)\s*\t+\s*(.+?)\s*\t+\s*(.+?)\s*$/ ) + { + my $product = $1; + my $pro = $2; + my $langs = $3; + my $path = $4; + + if (( $pro ne "pro" ) && ( $pro ne "nonpro" )) { installer::exiter::exit_program("ERROR: Wrong syntax in file: $filename. Only \"pro\" or \"nonpro\" allowed in column 1! Line: \"$line\"", "get_databasename_from_list"); } + + if ( correct_patch($product, $pro, $langs, $languagestringref) ) + { + $patchpath = $path; + last; + } + } + else + { + installer::exiter::exit_program("ERROR: Wrong syntax in file: $filename! Line: \"$line\"", "get_requiredpatchfile_from_list"); + } + } + + return $patchpath; +} + +################################################################## +# Converting unicode file to ascii +# to be more precise: uft-16 little endian to ascii +################################################################## + +sub convert_unicode_to_ascii +{ + my ( $filename ) = @_; + + my @localfile = (); + + my $savfilename = $filename . "_before.unicode"; + installer::systemactions::copy_one_file($filename, $savfilename); + +# open( IN, "<:utf16", $filename ) || installer::exiter::exit_program("ERROR: Cannot open file $filename for reading", "convert_unicode_to_ascii"); +# open( IN, "<:para:crlf:uni", $filename ) || installer::exiter::exit_program("ERROR: Cannot open file $filename for reading", "convert_unicode_to_ascii"); + open( IN, "<:encoding(UTF16-LE)", $filename ) || installer::exiter::exit_program("ERROR: Cannot open file $filename for reading", "convert_unicode_to_ascii"); +# open( IN, "<:encoding(UTF-8)", $filename ) || installer::exiter::exit_program("ERROR: Cannot open file $filename for reading", "convert_unicode_to_ascii"); + while ( $line = <IN> ) { + push @localfile, $line; + } + close( IN ); + + if ( open( OUT, ">", $filename ) ) + { + print OUT @localfile; + close(OUT); + } +} + +#################################################################### +# Analyzing the log file created by msimsp.exe to find all +# files included into the patch. +#################################################################### + +sub analyze_msimsp_logfile +{ + my ($logfile, $filesarray) = @_; + + # Reading log file after converting from utf-16 (LE) to ascii + convert_unicode_to_ascii($logfile); + my $logfilecontent = installer::files::read_file($logfile); + + # Creating hash from $filesarray: unique file name -> destination of file + my %filehash = (); + my %destinationcollector = (); + + for ( my $i = 0; $i <= $#{$filesarray}; $i++ ) + { + my $onefile = ${$filesarray}[$i]; + + # Only collecting files with "uniquename" and "destination" + if (( exists($onefile->{'uniquename'}) ) && ( exists($onefile->{'uniquename'}) )) + { + my $uniquefilename = $onefile->{'uniquename'}; + my $destpath = $onefile->{'destination'}; + $filehash{$uniquefilename} = $destpath; + } + } + + # Analyzing log file of msimsp.exe, finding all changed files + # and searching all destinations of unique file names. + # Content in log file: "INFO File Key: <file key> is modified" + # Collecting content in @installer::globals::patchfilecollector + + for ( my $i = 0; $i <= $#{$logfilecontent}; $i++ ) + { + if ( ${$logfilecontent}[$i] =~ /Key\:\s*(.*?) is modified\s*$/ ) + { + my $filekey = $1; + if ( exists($filehash{$filekey}) ) { $destinationcollector{$filehash{$filekey}} = 1; } + else { installer::exiter::exit_program("ERROR: Could not find file key \"$filekey\" in file collector.", "analyze_msimsp_logfile"); } + } + } + + foreach my $onedest ( sort keys %destinationcollector ) { push(@installer::globals::patchfilecollector, "$onedest\n"); } + +} + +#################################################################### +# Creating msp patch files for Windows +#################################################################### + +sub create_msp_patch +{ + my ($installationdir, $includepatharrayref, $allvariables, $languagestringref, $filesarray) = @_; + + my $force = 1; # print this message even in 'quiet' mode + installer::logger::print_message( "\n******************************************\n" ); + installer::logger::print_message( "... creating msp installation set ...\n", $force ); + installer::logger::print_message( "******************************************\n" ); + + $installer::globals::creating_windows_installer_patch = 1; + + my @needed_files = ("msimsp.exe"); # only required for patch creation process + installer::control::check_needed_files_in_path(\@needed_files); + + installer::logger::include_header_into_logfile("Creating msp installation sets:"); + + my $firstdir = $installationdir; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$firstdir); + + my $lastdir = $installationdir; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$lastdir); + + if ( $lastdir =~ /\./ ) { $lastdir =~ s/\./_msp_inprogress\./ } + else { $lastdir = $lastdir . "_msp_inprogress"; } + + # Removing existing directory "_native_packed_inprogress" and "_native_packed_witherror" and "_native_packed" + + my $mspdir = $firstdir . $lastdir; + if ( -d $mspdir ) { installer::systemactions::remove_complete_directory($mspdir); } + + my $olddir = $mspdir; + $olddir =~ s/_inprogress/_witherror/; + if ( -d $olddir ) { installer::systemactions::remove_complete_directory($olddir); } + + $olddir = $mspdir; + $olddir =~ s/_inprogress//; + if ( -d $olddir ) { installer::systemactions::remove_complete_directory($olddir); } + + # Creating the new directory for new installation set + installer::systemactions::create_directory($mspdir); + + $installer::globals::saveinstalldir = $mspdir; + + installer::logger::include_timestamp_into_logfile("\nPerformance Info: Starting product installation"); + + # Installing both installation sets + installer::logger::print_message( "... installing products ...\n" ); + my ($olddatabase, $newdatabase) = install_installation_sets($installationdir); + + installer::logger::include_timestamp_into_logfile("\nPerformance Info: Starting pcp file creation"); + + # Create pcp file + installer::logger::print_message( "... creating pcp file ...\n" ); + + my $localmspdir = installer::systemactions::create_directories("msp", $languagestringref); + + if ( ! $allvariables->{'PCPFILENAME'} ) { installer::exiter::exit_program("ERROR: Property \"PCPFILENAME\" has to be defined.", "create_msp_patch"); } + my $pcpfilename = $allvariables->{'PCPFILENAME'}; + + if ( $installer::globals::languagepack ) { $pcpfilename =~ s/.pcp\s*$/languagepack.pcp/; } + + # Searching the pcp file in the include pathes + my $fullpcpfilenameref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$pcpfilename, $includepatharrayref, 1); + if ( $$fullpcpfilenameref eq "" ) { installer::exiter::exit_program("ERROR: pcp file not found: $pcpfilename !", "create_msp_patch"); } + my $fullpcpfilenamesource = $$fullpcpfilenameref; + + # Copying pcp file + my $fullpcpfilename = $localmspdir . $installer::globals::separator . $pcpfilename; + installer::systemactions::copy_one_file($fullpcpfilenamesource, $fullpcpfilename); + + # a. Extracting tables from msi database: msidb.exe -d <msifile> -f <directory> -e File Media, ... + # b. Changing content of msi database in tables: File, Media, Directory, FeatureComponent + # c. Including tables into msi database: msidb.exe -d <msifile> -f <directory> -i File Media, ... + + # Unpacking tables from pcp file + extract_all_tables_from_pcpfile($fullpcpfilename, $localmspdir); + + # Tables, that need to be edited + my $tablelist = "Properties TargetImages UpgradedImages ImageFamilies PatchMetadata PatchSequence"; # required tables + + # Saving all tables + check_and_save_tables($tablelist, $localmspdir); + + # Setting the name of the new msp file + my $mspfilename = set_mspfilename($allvariables, $mspdir); + + # Editing tables + edit_tables($tablelist, $localmspdir, $olddatabase, $newdatabase, $mspfilename, $allvariables, $languagestringref); + + # Adding edited tables into pcp file + include_tables_into_pcpfile($fullpcpfilename, $localmspdir, $tablelist); + + # Start msimsp.exe + installer::logger::include_timestamp_into_logfile("\nPerformance Info: Starting msimsp.exe"); + my $msimsplogfile = execute_msimsp($fullpcpfilename, $mspfilename, $localmspdir); + + # Copy final installation set next to msp file + installer::logger::include_timestamp_into_logfile("\nPerformance Info: Copying installation set"); + installer::logger::print_message( "... copying installation set ...\n" ); + + my $oldinstallationsetpath = $installer::globals::updatedatabasepath; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$oldinstallationsetpath); + installer::systemactions::copy_complete_directory($oldinstallationsetpath, $mspdir); + + # Copying additional patches into the installation set, if required + if (( $allvariables->{'ADDITIONALREQUIREDPATCHES'} ) && ( $allvariables->{'ADDITIONALREQUIREDPATCHES'} ne "" ) && ( ! $installer::globals::languagepack )) + { + my $filename = $allvariables->{'ADDITIONALREQUIREDPATCHES'}; + + my $fullfilenameref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$filename, $includepatharrayref, 1); + if ( $$fullfilenameref eq "" ) { installer::exiter::exit_program("ERROR: Could not find file with required patches, although it is defined: $filename !", "create_msp_patch"); } + my $fullfilename = $$fullfilenameref; + + # Reading list file + my $listfile = installer::files::read_file($fullfilename); + + # Get name and path of reference database + my $requiredpatchfile = get_requiredpatchfile_from_list($listfile, $languagestringref, $fullfilename); + if ( $requiredpatchfile eq "" ) { installer::exiter::exit_program("ERROR: Could not find path to required patch in file $fullfilename for language(s) $$languagestringref!", "create_msp_patch"); } + + # Copying patch file + installer::systemactions::copy_one_file($requiredpatchfile, $mspdir); + # my $infoline = "Copy $requiredpatchfile to $mspdir\n"; + # push( @installer::globals::logfileinfo, $infoline); + } + + # Find all files included into the patch + # Analyzing the msimsp log file $msimsplogfile + analyze_msimsp_logfile($msimsplogfile, $filesarray); + + # Done + installer::logger::include_timestamp_into_logfile("\nPerformance Info: msp creation done"); + + return $mspdir; +} + +1; diff --git a/solenv/bin/modules/installer/windows/patch.pm b/solenv/bin/modules/installer/windows/patch.pm new file mode 100644 index 000000000000..25f8fab6caa2 --- /dev/null +++ b/solenv/bin/modules/installer/windows/patch.pm @@ -0,0 +1,159 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: patch.pm,v $ +# +# $Revision: 1.6 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::patch; + +use installer::exiter; +use installer::files; +use installer::globals; +use installer::windows::idtglobal; + +#################################################################################### +# Creating the file Upgrade.idt dynamically +# Content: +# UpgradeCode VersionMin VersionMax Language Attributes Remove ActionProperty +#################################################################################### + +sub update_patch_tables +{ + my ($basedir, $allvariables) = @_; + + my $reglocatfile = ""; + my $appsearchfile = ""; + + my $reglocatfilename = $basedir . $installer::globals::separator . "RegLocat.idt"; + my $appsearchfilename = $basedir . $installer::globals::separator . "AppSearc.idt"; + my $signaturefilename = $basedir . $installer::globals::separator . "Signatur.idt"; + + if ( -f $reglocatfilename ) + { + $reglocatfile = installer::files::read_file($reglocatfilename); + } + else + { + my @reglocattable = (); + $reglocatfile = \@reglocattable; + installer::windows::idtglobal::write_idt_header($reglocatfile, "reglocat"); + } + + if ( -f $appsearchfilename ) + { + $appsearchfile = installer::files::read_file($appsearchfilename); + } + else + { + my @appsearchtable = (); + $appsearchfile = \@appsearchtable; + installer::windows::idtglobal::write_idt_header($appsearchfile, "appsearch"); + } + + if ( -f $signaturefilename ) + { + $signaturefile = installer::files::read_file($signaturefilename); + } + else + { + my @signaturetable = (); + $signaturefile = \@signaturetable; + installer::windows::idtglobal::write_idt_header($signaturefile, "signatur"); + } + + # Writing content into this tables + + if ( ! $allvariables->{'PATCHCODEFILE'} ) { installer::exiter::exit_program("ERROR: Variable PATCHCODEFILE must be defined for Windows patches!", "update_patch_tables"); } + my $patchcodesfilename = $installer::globals::idttemplatepath . $installer::globals::separator . $allvariables->{'PATCHCODEFILE'}; + my $patchcodefile = installer::files::read_file($patchcodesfilename); + + my $number = 0; + + for ( my $i = 0; $i <= $#{$patchcodefile}; $i++ ) + { + my $oneline = ${$patchcodefile}[$i]; + + if ( $oneline =~ /^\s*\#/ ) { next; } # this is a comment line + if ( $oneline =~ /^\s*$/ ) { next; } + + my $code = ""; + if ( $oneline =~ /^\s*(\S+)\s/ ) { $code = $1; } + + foreach my $name ( sort keys %installer::globals::installlocations ) + { + $number++; + my $signature = "dir" . $number . "user"; + my $rootvalue = "1"; + my $registryname = ""; + my $registryversion = ""; + + if ( $allvariables->{'SEARCHPRODUCTNAME'} ) { $registryname = $allvariables->{'SEARCHPRODUCTNAME'}; } + else { $registryname = $allvariables->{'PRODUCTNAME'}; } + + if ( $allvariables->{'SEARCHPRODUCTVERSION'} ) { $registryversion = $allvariables->{'SEARCHPRODUCTVERSION'}; } + else { $registryversion = $allvariables->{'PRODUCTVERSION'}; } + + my $key = "Software\\" . $allvariables->{'MANUFACTURER'} . "\\" . $registryname . "\\" . $registryversion . "\\" . $code; + + my $type = 2; + my $property = $name; + + $oneline = $signature . "\t" . $rootvalue . "\t" . $key . "\t" . $name . "\t" . $type . "\n"; + push(@{$reglocatfile}, $oneline); + + $oneline = $property . "\t" . $signature . "\n"; + push(@{$appsearchfile}, $oneline); + + $signature = "dir" . $number . "mach"; + $rootvalue = "2"; + + $oneline = $signature . "\t" . $rootvalue . "\t" . $key . "\t" . $name . "\t" . $type . "\n"; + push(@{$reglocatfile}, $oneline); + + $oneline = $property . "\t" . $signature . "\n"; + push(@{$appsearchfile}, $oneline); + } + } + + # Saving the files + + installer::files::save_file($reglocatfilename ,$reglocatfile); + my $infoline = "Updated idt file: $reglocatfilename\n"; + push(@installer::globals::logfileinfo, $infoline); + + installer::files::save_file($appsearchfilename ,$appsearchfile); + $infoline = "Updated idt file: $appsearchfilename\n"; + push(@installer::globals::logfileinfo, $infoline); + + installer::files::save_file($signaturefilename ,$signaturefile); + $infoline = "Updated idt file: $signaturefilename\n"; + push(@installer::globals::logfileinfo, $infoline); + +} + +1; diff --git a/solenv/bin/modules/installer/windows/property.pm b/solenv/bin/modules/installer/windows/property.pm new file mode 100644 index 000000000000..beb485caa193 --- /dev/null +++ b/solenv/bin/modules/installer/windows/property.pm @@ -0,0 +1,648 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: property.pm,v $ +# +# $Revision: 1.31 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::property; + +use installer::exiter; +use installer::files; +use installer::globals; +use installer::windows::idtglobal; +use installer::windows::language; + +############################################# +# Setting the properties dynamically +# for the table Property.idt +############################################# + +sub get_arpcomments_for_property_table +{ + my ( $allvariables, $languagestringref ) = @_; + + my $name = $allvariables->{'PRODUCTNAME'}; + my $version = $allvariables->{'PRODUCTVERSION'}; + my $comment = $name . " " . $version; + + my $postversionextension = ""; + if ( $allvariables->{'POSTVERSIONEXTENSION'} ) + { + $postversionextension = $allvariables->{'POSTVERSIONEXTENSION'}; + $comment = $comment . " " . $postversionextension; + } + + if ( $installer::globals::languagepack ) { $comment = $comment . " " . "Language Pack"; } + + if ( $installer::globals::patch ) + { + if ( ! $allvariables->{'WINDOWSPATCHLEVEL'} ) { installer::exiter::exit_program("ERROR: No Patch level defined for Windows patch: WINDOWSPATCHLEVEL", "get_arpcomments_for_property_table"); } + my $patchstring = "Product Update" . " " . $allvariables->{'WINDOWSPATCHLEVEL'}; + $comment = $comment . " " . $patchstring; + } + + my $languagestring = $$languagestringref; + $languagestring =~ s/\_/\,/g; + + $comment = $comment . " ($languagestring)"; + + my $localminor = ""; + if ( $installer::globals::updatepack ) { $localminor = $installer::globals::lastminor; } + else { $localminor = $installer::globals::minor; } + + my $buildidstring = "(" . $installer::globals::build . $localminor . "(Build:" . $installer::globals::buildid . "))"; + + # the environment variable CWS_WORK_STAMP is set only in CWS + if ( $ENV{'CWS_WORK_STAMP'} ) { $buildidstring = $buildidstring . "\[CWS\:" . $ENV{'CWS_WORK_STAMP'} . "\]"; } + + $comment = $comment . " " . $buildidstring; + + return $comment; +} + +sub get_installlevel_for_property_table +{ + my $installlevel = "100"; + return $installlevel; +} + +sub get_ischeckforproductupdates_for_property_table +{ + my $ischeckforproductupdates = "1"; + return $ischeckforproductupdates; +} + +sub get_manufacturer_for_property_table +{ + return $installer::globals::manufacturer; +} + +sub get_productlanguage_for_property_table +{ + my ($language) = @_; + my $windowslanguage = installer::windows::language::get_windows_language($language); + return $windowslanguage; +} + +sub get_language_string +{ + my $langstring = ""; + + for ( my $i = 0; $i <= $#installer::globals::languagenames; $i++ ) + { + $langstring = $langstring . $installer::globals::languagenames[$i] . ", "; + } + + $langstring =~ s/\,\s*$//; + $langstring = "(" . $langstring . ")"; + + return $langstring; +} + +sub get_english_language_string +{ + my $langstring = ""; + + # Sorting value not keys, therefore collecting all values + my %helper = (); + foreach my $lang ( keys %installer::globals::all_required_english_languagestrings ) + { + $helper{$installer::globals::all_required_english_languagestrings{$lang}} = 1; + } + + foreach my $lang ( sort keys %helper ) + { + $langstring = $langstring . $lang . ", "; + } + + $langstring =~ s/\,\s*$//; + $langstring = "(" . $langstring . ")"; + + return $langstring; +} + +sub get_productname_for_property_table +{ + my ( $allvariables ) = @_; + + my $name = $allvariables->{'PRODUCTNAME'}; + my $version = $allvariables->{'PRODUCTVERSION'}; + my $productname = $name . " " . $version; + + my $postversionextension = ""; + if ( $allvariables->{'POSTVERSIONEXTENSION'} ) + { + $postversionextension = $allvariables->{'POSTVERSIONEXTENSION'}; + $productname = $productname . " " . $postversionextension; + } + + my $productextension = ""; + if ( $allvariables->{'PRODUCTEXTENSION'} ) + { + $productextension = $allvariables->{'PRODUCTEXTENSION'}; + $productname = $productname . " " . $productextension; + } + + if ( $installer::globals::languagepack ) + { + # my $langstring = get_language_string(); # Example (English, Deutsch) + my $langstring = get_english_language_string(); # New: (English, German) + $productname = $name . " " . $version . " Language Pack" . " " . $langstring; + } + + if ( $installer::globals::patch ) + { + if ( ! $allvariables->{'WINDOWSPATCHLEVEL'} ) { installer::exiter::exit_program("ERROR: No Patch level defined for Windows patch: WINDOWSPATCHLEVEL", "get_productname_for_property_table"); } + my $patchstring = "Product Update" . " " . $allvariables->{'WINDOWSPATCHLEVEL'}; + $productname = $productname . " " . $patchstring; + } + + # Saving this name in hash $allvariables for further usage + $allvariables->{'PROPERTYTABLEPRODUCTNAME'} = $productname; + my $infoline = "Defined variable PROPERTYTABLEPRODUCTNAME: $productname\n"; + push(@installer::globals::logfileinfo, $infoline); + + return $productname; +} + +sub get_quickstarterlinkname_for_property_table +{ + my ( $allvariables ) = @_; + + # no usage of POSTVERSIONEXTENSION for Quickstarter link name! + + my $name = $allvariables->{'PRODUCTNAME'}; + my $version = $allvariables->{'PRODUCTVERSION'}; + my $quickstartername = $name . " " . $version; + + my $infoline = "Defined Quickstarter Link name: $quickstartername\n"; + push(@installer::globals::logfileinfo, $infoline); + + return $quickstartername; +} + +sub get_productversion_for_property_table +{ + return $installer::globals::msiproductversion; +} + +####################################################### +# Setting all feature names as Properties. This is +# required for the Windows patch process. +####################################################### + +sub set_featurename_properties_for_patch +{ + ($propertyfile) = @_; + + for ( my $i = 0; $i <= $#installer::globals::featurecollector; $i++ ) + { + my $onepropertyline = $installer::globals::featurecollector[$i] . "\t" . "1" . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + +} + +####################################################### +# Setting some important properties +# (for finding the product in deinstallation process) +####################################################### + +sub set_important_properties +{ + my ($propertyfile, $allvariables, $languagestringref) = @_; + + # Setting new variables with the content of %PRODUCTNAME and %PRODUCTVERSION + if ( $allvariables->{'PRODUCTNAME'} ) + { + my $onepropertyline = "DEFINEDPRODUCT" . "\t" . $allvariables->{'PRODUCTNAME'} . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + if ( $allvariables->{'PRODUCTVERSION'} ) + { + my $onepropertyline = "DEFINEDVERSION" . "\t" . $allvariables->{'PRODUCTVERSION'} . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + if (( $allvariables->{'PRODUCTNAME'} ) && ( $allvariables->{'PRODUCTVERSION'} ) && ( $allvariables->{'MANUFACTURER'} ) && ( $allvariables->{'PRODUCTCODE'} )) + { + my $onepropertyline = "FINDPRODUCT" . "\t" . "Software\\" . $allvariables->{'MANUFACTURER'} . "\\" . $allvariables->{'PRODUCTNAME'} . $allvariables->{'PRODUCTADDON'} . "\\" . $allvariables->{'PRODUCTVERSION'} . "\\" . $allvariables->{'PRODUCTCODE'} . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + if ( $allvariables->{'PRODUCTMAJOR'} ) + { + my $onepropertyline = "PRODUCTMAJOR" . "\t" . $allvariables->{'PRODUCTMAJOR'} . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + if ( $allvariables->{'PRODUCTMINOR'} ) + { + my $onepropertyline = "PRODUCTMINOR" . "\t" . $allvariables->{'PRODUCTMINOR'} . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + if ( $allvariables->{'PRODUCTBUILDID'} ) + { + my $onepropertyline = "PRODUCTBUILDID" . "\t" . $allvariables->{'PRODUCTBUILDID'} . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + if ( $allvariables->{'OOOBASEVERSION'} ) + { + my $onepropertyline = "OOOBASEVERSION" . "\t" . $allvariables->{'OOOBASEVERSION'} . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + if ( $allvariables->{'URELAYERVERSION'} ) + { + my $onepropertyline = "URELAYERVERSION" . "\t" . $allvariables->{'URELAYERVERSION'} . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + if ( $allvariables->{'BRANDPACKAGEVERSION'} ) + { + my $onepropertyline = "BRANDPACKAGEVERSION" . "\t" . $allvariables->{'BRANDPACKAGEVERSION'} . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + if ( $allvariables->{'BASISROOTNAME'} ) + { + my $onepropertyline = "BASISROOTNAME" . "\t" . $allvariables->{'BASISROOTNAME'} . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + if ( $allvariables->{'PREREQUIREDPATCH'} ) + { + my $onepropertyline = "PREREQUIREDPATCH" . "\t" . $allvariables->{'PREREQUIREDPATCH'} . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + my $onepropertyline = "IGNOREPREREQUIREDPATCH" . "\t" . "0" . "\n"; + push(@{$propertyfile}, $onepropertyline); + + if ( $installer::globals::sundirexists ) + { + my $onepropertyline = "SUNDIREXISTS" . "\t" . "1" . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + if ( $installer::globals::officedirhostname ) + { + my $onepropertyline = "OFFICEDIRHOSTNAME" . "\t" . $installer::globals::officedirhostname . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + if ( $installer::globals::basisdirhostname ) + { + my $onepropertyline = "BASISDIRHOSTNAME" . "\t" . $installer::globals::basisdirhostname . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + if ( $installer::globals::uredirhostname ) + { + my $onepropertyline = "UREDIRHOSTNAME" . "\t" . $installer::globals::uredirhostname . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + if ( $installer::globals::sundirhostname ) + { + my $onepropertyline = "SUNDIRHOSTNAME" . "\t" . $installer::globals::sundirhostname . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + if ( $installer::globals::desktoplinkexists ) + { + my $onepropertyline = "DESKTOPLINKEXISTS" . "\t" . "1" . "\n"; + push(@{$propertyfile}, $onepropertyline); + + $onepropertyline = "CREATEDESKTOPLINK" . "\t" . "1" . "\n"; # Setting the default + push(@{$propertyfile}, $onepropertyline); + } + + if ( $installer::globals::patch ) + { + my $onepropertyline = "ISPATCH" . "\t" . "1" . "\n"; + push(@{$propertyfile}, $onepropertyline); + + $onepropertyline = "SETUP_USED" . "\t" . "0" . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + if ( $installer::globals::languagepack ) + { + my $onepropertyline = "ISLANGUAGEPACK" . "\t" . "1" . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + my $languagesline = "PRODUCTALLLANGUAGES" . "\t" . $$languagestringref . "\n"; + push(@{$propertyfile}, $languagesline); + + if (( $allvariables->{'PRODUCTEXTENSION'} ) && ( $allvariables->{'PRODUCTEXTENSION'} eq "Beta" )) + { + my $registryline = "WRITE_REGISTRY" . "\t" . "0" . "\n"; + push(@{$propertyfile}, $registryline); + my $betainfoline = "BETAPRODUCT" . "\t" . "1" . "\n"; + push(@{$propertyfile}, $betainfoline); + } + elsif ( $allvariables->{'DEVELOPMENTPRODUCT'} ) + { + my $registryline = "WRITE_REGISTRY" . "\t" . "0" . "\n"; + push(@{$propertyfile}, $registryline); + } + else + { + my $registryline = "WRITE_REGISTRY" . "\t" . "1" . "\n"; # Default: Write complete registry + push(@{$propertyfile}, $registryline); + } + + # Adding also used tree conditions for multilayer products. + # These are saved in %installer::globals::usedtreeconditions + foreach my $treecondition (keys %installer::globals::usedtreeconditions) + { + my $onepropertyline = $treecondition . "\t" . "1" . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + # No more license dialog for selected products + if ( $allvariables->{'HIDELICENSEDIALOG'} ) + { + my $onepropertyline = "HIDEEULA" . "\t" . "1" . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + # Setting .NET requirements + if ( $installer::globals::required_dotnet_version ne "" ) + { + my $onepropertyline = "REQUIRED_DOTNET_VERSION" . "\t" . $installer::globals::required_dotnet_version . "\n"; + push(@{$propertyfile}, $onepropertyline); + + $onepropertyline = "DOTNET_SUFFICIENT" . "\t" . "1" . "\n"; # default value for found .NET + push(@{$propertyfile}, $onepropertyline); + } + +} + +####################################################### +# Setting properties needed for ms file type registration +####################################################### + +sub set_ms_file_types_properties +{ + my ($propertyfile) = @_; + + push(@{$propertyfile}, "REGISTER_PPS" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_PPSX" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_PPSM" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_PPAM" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_PPT" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_PPTX" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_PPTM" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_POT" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_POTX" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_POTM" . "\t" . "0" . "\n"); + + push(@{$propertyfile}, "REGISTER_DOC" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_DOCX" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_DOCM" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_DOT" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_DOTX" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_DOTM" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_RTF" . "\t" . "0" . "\n"); + + push(@{$propertyfile}, "REGISTER_XLS" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_XLSX" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_XLSM" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_XLSB" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_XLAM" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_XLT" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_XLTX" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_XLTM" . "\t" . "0" . "\n"); + + push(@{$propertyfile}, "REGISTER_NO_MSO_TYPES" . "\t" . "0" . "\n"); + push(@{$propertyfile}, "REGISTER_ALL_MSO_TYPES" . "\t" . "0" . "\n"); +} + +#################################################################################### +# Updating the file Property.idt dynamically +# Content: +# Property Value +#################################################################################### + +sub update_property_table +{ + my ($basedir, $language, $allvariables, $languagestringref) = @_; + + my $properyfilename = $basedir . $installer::globals::separator . "Property.idt"; + + my $propertyfile = installer::files::read_file($properyfilename); + + # Getting the new values + # Some values (arpcomments, arpcontacts, ...) are inserted from the Property.mlf + + my $arpcomments = get_arpcomments_for_property_table($allvariables, $languagestringref); + my $installlevel = get_installlevel_for_property_table(); + my $ischeckforproductupdates = get_ischeckforproductupdates_for_property_table(); + my $manufacturer = get_manufacturer_for_property_table(); + my $productlanguage = get_productlanguage_for_property_table($language); + my $productname = get_productname_for_property_table($allvariables); + my $productversion = get_productversion_for_property_table(); + my $quickstarterlinkname = get_quickstarterlinkname_for_property_table($allvariables); + + # Updating the values + + for ( my $i = 0; $i <= $#{$propertyfile}; $i++ ) + { + ${$propertyfile}[$i] =~ s/\bARPCOMMENTSTEMPLATE\b/$arpcomments/; + ${$propertyfile}[$i] =~ s/\bINSTALLLEVELTEMPLATE\b/$installlevel/; + ${$propertyfile}[$i] =~ s/\bISCHECKFORPRODUCTUPDATESTEMPLATE\b/$ischeckforproductupdates/; + ${$propertyfile}[$i] =~ s/\bMANUFACTURERTEMPLATE\b/$manufacturer/; + ${$propertyfile}[$i] =~ s/\bPRODUCTLANGUAGETEMPLATE\b/$productlanguage/; + ${$propertyfile}[$i] =~ s/\bPRODUCTNAMETEMPLATE\b/$productname/; + ${$propertyfile}[$i] =~ s/\bPRODUCTVERSIONTEMPLATE\b/$productversion/; + ${$propertyfile}[$i] =~ s/\bQUICKSTARTERLINKNAMETEMPLATE\b/$quickstarterlinkname/; + } + + # Setting variables into propertytable + set_important_properties($propertyfile, $allvariables, $languagestringref); + + # Setting feature names as properties for Windows patch mechanism + if ( $installer::globals::patch ) { set_featurename_properties_for_patch($propertyfile); } + + # Setting variables for register for ms file types + set_ms_file_types_properties($propertyfile); + + # Saving the file + + installer::files::save_file($properyfilename ,$propertyfile); + my $infoline = "Updated idt file: $properyfilename\n"; + push(@installer::globals::logfileinfo, $infoline); + +} + +#################################################################################### +# Setting language specific Properties in file Property.idt dynamically +# Adding: +# is1033 = 1 +# isMulti = 1 +#################################################################################### + +sub set_languages_in_property_table +{ + my ($basedir, $languagesarrayref) = @_; + + my $properyfilename = $basedir . $installer::globals::separator . "Property.idt"; + my $propertyfile = installer::files::read_file($properyfilename); + + # Setting the component properties saved in %installer::globals::languageproperties + foreach my $localproperty ( keys %installer::globals::languageproperties ) + { + $onepropertyline = $localproperty . "\t" . $installer::globals::languageproperties{$localproperty} . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + # Setting the info about multilingual installation in property "isMulti" + + my $propertyname = "isMulti"; + my $ismultivalue = 0; + + if ( $installer::globals::ismultilingual ) { $ismultivalue = 1; } + + my $onepropertyline = $propertyname . "\t" . $ismultivalue . "\n"; + push(@{$propertyfile}, $onepropertyline); + + # setting the ARPPRODUCTICON + + if ($installer::globals::sofficeiconadded) # set in shortcut.pm + { + $onepropertyline = "ARPPRODUCTICON" . "\t" . "soffice.exe" . "\n"; + push(@{$propertyfile}, $onepropertyline); + } + + # Saving the file + + installer::files::save_file($properyfilename ,$propertyfile); + my $infoline = "Added language content into idt file: $properyfilename\n"; + push(@installer::globals::logfileinfo, $infoline); + +} + +############################################################ +# Setting the ProductCode and the UpgradeCode +# into the Property table. Both have to be stored +# in the global file $installer::globals::codefilename +############################################################ + +sub set_codes_in_property_table +{ + my ($basedir) = @_; + + # Reading the property file + + my $properyfilename = $basedir . $installer::globals::separator . "Property.idt"; + my $propertyfile = installer::files::read_file($properyfilename); + + # Updating the values + + for ( my $i = 0; $i <= $#{$propertyfile}; $i++ ) + { + ${$propertyfile}[$i] =~ s/\bPRODUCTCODETEMPLATE\b/$installer::globals::productcode/; + ${$propertyfile}[$i] =~ s/\bUPGRADECODETEMPLATE\b/$installer::globals::upgradecode/; + } + + # Saving the property file + + installer::files::save_file($properyfilename ,$propertyfile); + my $infoline = "Added language content into idt file: $properyfilename\n"; + push(@installer::globals::logfileinfo, $infoline); + +} + +############################################################ +# Setting the variable REGKEYPRODPATH, that is used +# by the language packs. +############################################################ + +sub set_regkeyprodpath_in_property_table +{ + my ($basedir, , $allvariables) = @_; + + # Reading the property file + + my $properyfilename = $basedir . $installer::globals::separator . "Property.idt"; + my $propertyfile = installer::files::read_file($properyfilename); + + my $name = $allvariables->{'PRODUCTNAME'}; + my $version = $allvariables->{'PRODUCTVERSION'}; + + my $onepropertyline = "REGKEYPRODPATH" . "\t" . "Software" . "\\" . $installer::globals::manufacturer . "\\". $name; + + push(@{$propertyfile}, $onepropertyline); + + # Saving the property file + + installer::files::save_file($properyfilename ,$propertyfile); + my $infoline = "Added language content into idt file: $properyfilename\n"; + push(@installer::globals::logfileinfo, $infoline); + +} + +############################################################ +# Changing default for MS file type registration +# in Beta products. +############################################################ + +sub update_checkbox_table +{ + my ($basedir, $allvariables) = @_; + + if (( $allvariables->{'PRODUCTEXTENSION'} ) && ( $allvariables->{'PRODUCTEXTENSION'} eq "Beta" )) + { + my $checkboxfilename = $basedir . $installer::globals::separator . "CheckBox.idt"; + + if ( -f $checkboxfilename ) + { + my $checkboxfile = installer::files::read_file($checkboxfilename); + + my $checkboxline = "SELECT_WORD" . "\t" . "0" . "\n"; + push(@{$checkboxfile}, $checkboxline); + $checkboxline = "SELECT_EXCEL" . "\t" . "0" . "\n"; + push(@{$checkboxfile}, $checkboxline); + $checkboxline = "SELECT_POWERPOINT" . "\t" . "0" . "\n"; + push(@{$checkboxfile}, $checkboxline); + + # Saving the property file + installer::files::save_file($checkboxfilename ,$checkboxfile); + my $infoline = "Added ms file type defaults into idt file: $checkboxfilename\n"; + push(@installer::globals::logfileinfo, $infoline); + } + } +} + +1; diff --git a/solenv/bin/modules/installer/windows/registry.pm b/solenv/bin/modules/installer/windows/registry.pm new file mode 100644 index 000000000000..832fd213a9f0 --- /dev/null +++ b/solenv/bin/modules/installer/windows/registry.pm @@ -0,0 +1,366 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: registry.pm,v $ +# +# $Revision: 1.18 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::registry; + +use installer::files; +use installer::globals; +use installer::worker; +use installer::windows::idtglobal; + +##################################################### +# Generating the component name from a registryitem +##################################################### + +sub get_registry_component_name +{ + my ($registryref, $allvariables) = @_; + + # In this function exists the rule to create components from registryitems + # Rule: + # The componentname can be directly taken from the ModuleID. + # All registryitems belonging to one module can get the same component. + + my $componentname = ""; + my $isrootmodule = 0; + + if ( $registryref->{'ModuleID'} ) { $componentname = $registryref->{'ModuleID'}; } + + $componentname =~ s/\\/\_/g; + $componentname =~ s/\//\_/g; + $componentname =~ s/\-/\_/g; + $componentname =~ s/\_\s*$//g; + + $componentname = lc($componentname); # componentnames always lowercase + + if ( $componentname eq "gid_module_root" ) { $isrootmodule = 1; } + + # Attention: Maximum length for the componentname is 72 + + $componentname =~ s/gid_module_/g_m_/g; + $componentname =~ s/_optional_/_o_/g; + $componentname =~ s/_javafilter_/_jf_/g; + + $componentname = $componentname . "_registry"; # identifying this component as registryitem component + + # This componentname must be more specific + my $addon = "_"; + if ( $allvariables->{'PRODUCTNAME'} ) { $addon = $addon . $allvariables->{'PRODUCTNAME'}; } + if ( $allvariables->{'PRODUCTVERSION'} ) { $addon = $addon . $allvariables->{'PRODUCTVERSION'}; } + $addon = lc($addon); + $addon =~ s/ //g; + $addon =~ s/-//g; + $addon =~ s/\.//g; + + my $styles = ""; + if ( $registryref->{'Styles'} ) { $styles = $registryref->{'Styles'}; } + + # Layer links must have unique Component GUID for all products. This is necessary, because only the + # uninstallation of the last product has to delete registry keys. + if ( $styles =~ /\bLAYER_REGISTRY\b/ ) + { + $componentname = "g_m_root_registry_layer_ooo_reglayer"; + # Styles USE_URELAYERVERSION, USE_OOOBASEVERSION + if ( $styles =~ /\bUSE_URELAYERVERSION\b/ ) { $addon = "_ure_" . $allvariables->{'URELAYERVERSION'}; } + if ( $styles =~ /\bUSE_OOOBASEVERSION\b/ ) { $addon = "_basis_" . $allvariables->{'OOOBASEVERSION'}; } + $addon =~ s/\.//g; + } + + $componentname = $componentname . $addon; + + if (( $styles =~ /\bLANGUAGEPACK\b/ ) && ( $installer::globals::languagepack )) { $componentname = $componentname . "_lang"; } + if ( $styles =~ /\bALWAYS_REQUIRED\b/ ) { $componentname = $componentname . "_forced"; } + + if ( $isrootmodule ) { $installer::globals::registryrootcomponent = $componentname; } + + return $componentname; +} + +############################################################## +# Returning identifier for registry table. +############################################################## + +sub get_registry_identifier +{ + my ($registry) = @_; + + my $identifier = ""; + + if ( $registry->{'gid'} ) { $identifier = $registry->{'gid'}; } + + $identifier = lc($identifier); # always lower case + + # Attention: Maximum length is 72 + + $identifier =~ s/gid_regitem_/g_r_/; + $identifier =~ s/_soffice_/_s_/; + $identifier =~ s/_clsid_/_c_/; + $identifier =~ s/_currentversion_/_cv_/; + $identifier =~ s/_microsoft_/_ms_/; + $identifier =~ s/_staroffice_/_so_/; + $identifier =~ s/_classpath_/_cp_/; + $identifier =~ s/__/_/g; + + # Saving this in the registry collector + + $registry->{'uniquename'} = $identifier; + + return $identifier; +} + +################################################################## +# Returning root value for registry table. +################################################################## + +sub get_registry_root +{ + my ($registry) = @_; + + my $rootvalue = 0; # Default: Parent is KKEY_CLASSES_ROOT + my $scproot = ""; + + if ( $registry->{'ParentID'} ) { $scproot = $registry->{'ParentID'}; } + + if ( $scproot eq "PREDEFINED_HKEY_LOCAL_MACHINE" ) { $rootvalue = -1; } + + if ( $scproot eq "PREDEFINED_HKEY_CLASSES_ROOT" ) { $rootvalue = 0; } + + if ( $scproot eq "PREDEFINED_HKEY_CURRENT_USER_ONLY" ) { $rootvalue = 1; } + + if ( $scproot eq "PREDEFINED_HKEY_LOCAL_MACHINE_ONLY" ) { $rootvalue = 2; } + + return $rootvalue; +} + +############################################################## +# Returning key for registry table. +############################################################## + +sub get_registry_key +{ + my ($registry, $allvariableshashref) = @_; + + my $key = ""; + + if ( $registry->{'Subkey'} ) { $key = $registry->{'Subkey'}; } + + if ( $key =~ /\%/ ) { $key = installer::worker::replace_variables_in_string($key, $allvariableshashref); } + + return $key; +} + +############################################################## +# Returning name for registry table. +############################################################## + +sub get_registry_name +{ + my ($registry, $allvariableshashref) = @_; + + my $name = ""; + + if ( $registry->{'Name'} ) { $name = $registry->{'Name'}; } + + if ( $name =~ /\%/ ) { $name = installer::worker::replace_variables_in_string($name, $allvariableshashref); } + + return $name; +} + +############################################################## +# Returning value for registry table. +############################################################## + +sub get_registry_value +{ + my ($registry, $allvariableshashref) = @_; + + my $value = ""; + + if ( $registry->{'Value'} ) { $value = $registry->{'Value'}; } + + $value =~ s/\\\"/\"/g; # no more masquerading of '"' + $value =~ s/\<progpath\>/\[OFFICEINSTALLLOCATION\]/; + $value =~ s/\[OFFICEINSTALLLOCATION\]\\/\[OFFICEINSTALLLOCATION\]/; # removing "\" after "[OFFICEINSTALLLOCATION]" + + if ( $value =~ /\%/ ) { $value = installer::worker::replace_variables_in_string($value, $allvariableshashref); } + + return $value; +} + +############################################################## +# Returning component for registry table. +############################################################## + +sub get_registry_component +{ + my ($registry, $allvariables) = @_; + + # All registry items belonging to one module can + # be included into one component + + my $componentname = get_registry_component_name($registry, $allvariables); + + # saving componentname in the registryitem collector + + $registry->{'componentname'} = $componentname; + + return $componentname; +} + +###################################################### +# Adding the content of +# @installer::globals::userregistrycollector +# to the registry table. The content was collected +# in create_files_table() in file.pm. +###################################################### + +sub add_userregs_to_registry_table +{ + my ( $registrytable, $allvariables ) = @_; + + for ( my $i = 0; $i <= $#installer::globals::userregistrycollector; $i++ ) + { + my $onefile = $installer::globals::userregistrycollector[$i]; + + my $styles = ""; + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } + + my %registry = (); + + $registry{'Registry'} = $onefile->{'userregkeypath'}; + $registry{'Root'} = "1"; # always HKCU + $registry{'Key'} = "Software\\$allvariables->{'MANUFACTURER'}\\$allvariables->{'PRODUCTNAME'} $allvariables->{'PRODUCTVERSION'}\\"; + if ( $onefile->{'needs_user_registry_key'} ) { $registry{'Key'} = $registry{'Key'} . "StartMenu"; } + else { $registry{'Key'} = $registry{'Key'} . "ShellNew"; } + $registry{'Name'} = $onefile->{'Name'}; + $registry{'Value'} = "1"; + $registry{'Component_'} = $onefile->{'componentname'}; + + my $oneline = $registry{'Registry'} . "\t" . $registry{'Root'} . "\t" . $registry{'Key'} . "\t" + . $registry{'Name'} . "\t" . $registry{'Value'} . "\t" . $registry{'Component_'} . "\n"; + + push(@{$registrytable}, $oneline); + } +} + +###################################################### +# Creating the file Registry.idt dynamically +# Content: +# Registry Root Key Name Value Component_ +###################################################### + +sub create_registry_table +{ + my ($registryref, $allregistrycomponentsref, $basedir, $languagesarrayref, $allvariableshashref) = @_; + + for ( my $m = 0; $m <= $#{$languagesarrayref}; $m++ ) + { + my $onelanguage = ${$languagesarrayref}[$m]; + + my @registrytable = (); + + installer::windows::idtglobal::write_idt_header(\@registrytable, "registry"); + + for ( my $i = 0; $i <= $#{$registryref}; $i++ ) + { + my $oneregistry = ${$registryref}[$i]; + + # Controlling the language! + # Only language independent folderitems or folderitems with the correct language + # will be included into the table + + if (! (!(( $oneregistry->{'ismultilingual'} )) || ( $oneregistry->{'specificlanguage'} eq $onelanguage )) ) { next; } + + my %registry = (); + + $registry{'Registry'} = get_registry_identifier($oneregistry); + $registry{'Root'} = get_registry_root($oneregistry); + $registry{'Key'} = get_registry_key($oneregistry, $allvariableshashref); + $registry{'Name'} = get_registry_name($oneregistry, $allvariableshashref); + $registry{'Value'} = get_registry_value($oneregistry, $allvariableshashref); + $registry{'Component_'} = get_registry_component($oneregistry, $allvariableshashref); + + # Collecting all components + if (!(installer::existence::exists_in_array($registry{'Component_'}, $allregistrycomponentsref))) + { + push(@{$allregistrycomponentsref}, $registry{'Component_'}); + } + + # Collecting all components with DONT_DELETE style + my $style = ""; + if ( $oneregistry->{'Styles'} ) { $style = $oneregistry->{'Styles'}; } + if ( $style =~ /\bDONT_DELETE\b/ ) { $installer::globals::dontdeletecomponents{$registry{'Component_'}} = 1; } + + # Saving upgradekey to write this into setup.ini for minor upgrades + if ( $style =~ /\bUPGRADEKEY\b/ ) { $installer::globals::minorupgradekey = $registry{'Key'}; } + + # Collecting all registry components with ALWAYS_REQUIRED style + if ( ! ( $style =~ /\bALWAYS_REQUIRED\b/ )) + { + # Setting a component condition for unforced registry components! + # Only write into registry, if WRITE_REGISTRY is set. + if ( $oneregistry->{'ComponentCondition'} ) { $oneregistry->{'ComponentCondition'} = "(" . $oneregistry->{'ComponentCondition'} . ") AND (WRITE_REGISTRY=1)"; } + else { $oneregistry->{'ComponentCondition'} = "WRITE_REGISTRY=1"; } + } + + # Collecting all component conditions + if ( $oneregistry->{'ComponentCondition'} ) + { + if ( ! exists($installer::globals::componentcondition{$registry{'Component_'}})) + { + $installer::globals::componentcondition{$registry{'Component_'}} = $oneregistry->{'ComponentCondition'}; + } + } + + my $oneline = $registry{'Registry'} . "\t" . $registry{'Root'} . "\t" . $registry{'Key'} . "\t" + . $registry{'Name'} . "\t" . $registry{'Value'} . "\t" . $registry{'Component_'} . "\n"; + + push(@registrytable, $oneline); + } + + # If there are added user registry keys for files collected in + # @installer::globals::userregistrycollector (file.pm), then + # this registry keys have to be added now. This is necessary for + # files in PREDEFINED_OSSHELLNEWDIR, because their component + # needs as KeyPath a RegistryItem in HKCU. + + if ( $installer::globals::addeduserregitrykeys ) { add_userregs_to_registry_table(\@registrytable, $allvariableshashref); } + + # Saving the file + + my $registrytablename = $basedir . $installer::globals::separator . "Registry.idt" . "." . $onelanguage; + installer::files::save_file($registrytablename ,\@registrytable); + my $infoline = "Created idt file: $registrytablename\n"; + push(@installer::globals::logfileinfo, $infoline); + } +} + +1; diff --git a/solenv/bin/modules/installer/windows/removefile.pm b/solenv/bin/modules/installer/windows/removefile.pm new file mode 100644 index 000000000000..73c276a44310 --- /dev/null +++ b/solenv/bin/modules/installer/windows/removefile.pm @@ -0,0 +1,156 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: removefile.pm,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::removefile; + +use installer::files; +use installer::globals; +use installer::windows::idtglobal; + +######################################################################## +# Returning the FileKey for a folderitem for removefile table. +######################################################################## + +sub get_removefile_filekey +{ + my ($folderitem) = @_; + + # returning the unique identifier + + my $identifier = "remove_" . $folderitem->{'directory'}; + + $identifier = lc($identifier); + + return $identifier; +} + +######################################################################## +# Returning the Component for a folderitem for removefile table. +######################################################################## + +sub get_removefile_component +{ + my ($folderitem) = @_; + + return $folderitem->{'component'}; +} + +######################################################################## +# Returning the FileName for a folderitem for removefile table. +######################################################################## + +sub get_removefile_filename +{ + my ($folderitem) = @_; + + # return nothing: The assigned directory will be removed + + return ""; +} + +######################################################################## +# Returning the DirProperty for a folderitem for removefile table. +######################################################################## + +sub get_removefile_dirproperty +{ + my ($folderitem) = @_; + + return $folderitem->{'directory'}; +} + +######################################################################## +# Returning the InstallMode for a folderitem for removefile table. +######################################################################## + +sub get_removefile_installmode +{ + my ($folderitem) = @_; + + # always returning "2": The file is only removed, if the assigned + # component is removed. Name: msidbRemoveFileInstallModeOnRemove + + return 2; +} + +########################################################################################################### +# Creating the file RemoveFi.idt dynamically +# Content: +# FileKey Component_ FileName DirProperty InstallMode +########################################################################################################### + +sub create_removefile_table +{ + my ($folderitemsref, $basedir) = @_; + + my @removefiletable = (); + + installer::windows::idtglobal::write_idt_header(\@removefiletable, "removefile"); + + # Only the directories created for the FolderItems have to be deleted + # with the information in the table RemoveFile + + my @directorycollector = (); + + for ( my $i = 0; $i <= $#{$folderitemsref}; $i++ ) + { + my $onelink = ${$folderitemsref}[$i]; + + if ( $onelink->{'used'} == 0 ) { next; } + + if ( installer::existence::exists_in_array($onelink->{'directory'}, \@directorycollector)) { next; } + + push(@directorycollector, $onelink->{'directory'}); + + my %removefile = (); + + $removefile{'FileKey'} = get_removefile_filekey($onelink); + $removefile{'Component_'} = get_removefile_component($onelink); + $removefile{'FileName'} = get_removefile_filename($onelink); + $removefile{'DirProperty'} = get_removefile_dirproperty($onelink); + $removefile{'InstallMode'} = get_removefile_installmode($onelink); + + my $oneline = $removefile{'FileKey'} . "\t" . $removefile{'Component_'} . "\t" . $removefile{'FileName'} . "\t" + . $removefile{'DirProperty'} . "\t" . $removefile{'InstallMode'} . "\n"; + + push(@removefiletable, $oneline); + } + + # Saving the file + + my $removefiletablename = $basedir . $installer::globals::separator . "RemoveFi.idt"; + installer::files::save_file($removefiletablename ,\@removefiletable); + my $infoline = "Created idt file: $removefiletablename\n"; + push(@installer::globals::logfileinfo, $infoline); + +} + +1;
\ No newline at end of file diff --git a/solenv/bin/modules/installer/windows/selfreg.pm b/solenv/bin/modules/installer/windows/selfreg.pm new file mode 100644 index 000000000000..821eae4dceb4 --- /dev/null +++ b/solenv/bin/modules/installer/windows/selfreg.pm @@ -0,0 +1,92 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: selfreg.pm,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::selfreg; + +use installer::exiter; +use installer::files; +use installer::globals; +use installer::worker; +use installer::windows::idtglobal; + +############################################################## +# Returning the cost for the selfreg table. +############################################################## + +sub get_selfreg_cost +{ + my ( $onefile ) = @_; + + return "0"; +} + +#################################################################################### +# Creating the file SelfReg.idt dynamically +# Content: +# File_ Cost +# UpgradeCode VersionMin VersionMax Language Attributes Remove ActionProperty +#################################################################################### + +sub create_selfreg_table +{ + my ($filesref, $basedir) = @_; + + my @selfregtable = (); + + installer::windows::idtglobal::write_idt_header(\@selfregtable, "selfreg"); + + # Registering all libraries with flag "SELFREG" + + my $selfregfiles = installer::worker::collect_all_items_with_special_flag($filesref, "SELFREG"); + + for ( my $i = 0; $i <= $#{$selfregfiles}; $i++ ) + { + my $onefile = ${$selfregfiles}[$i]; + + my %selfreg = (); + + $selfreg{'File_'} = $onefile->{'uniquename'}; + $selfreg{'Cost'} = get_selfreg_cost($onefile); + + my $oneline = $selfreg{'File_'} . "\t" . $selfreg{'Cost'} . "\n"; + + push(@selfregtable, $oneline); + } + + # Saving the file + + my $selfregtablename = $basedir . $installer::globals::separator . "SelfReg.idt"; + installer::files::save_file($selfregtablename ,\@selfregtable); + my $infoline = "Created idt file: $selfregtablename\n"; + push(@installer::globals::logfileinfo, $infoline); +} + +1;
\ No newline at end of file diff --git a/solenv/bin/modules/installer/windows/shortcut.pm b/solenv/bin/modules/installer/windows/shortcut.pm new file mode 100644 index 000000000000..acc0f7484910 --- /dev/null +++ b/solenv/bin/modules/installer/windows/shortcut.pm @@ -0,0 +1,716 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: shortcut.pm,v $ +# +# $Revision: 1.15 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::shortcut; + +use installer::existence; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::windows::idtglobal; + +############################################################## +# Returning the file object for the msiassembly table. +############################################################## + +sub get_file_by_name +{ + my ( $filesref, $filename ) = @_; + + my $foundfile = 0; + my $onefile; + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + $onefile = ${$filesref}[$i]; + my $name = $onefile->{'Name'}; + + if ( $name eq $filename ) + { + $foundfile = 1; + last; + } + } + + if (! $foundfile ) { $onefile = ""; } + + return $onefile; +} + +############################################################## +# Returning identifier for shortcut table. +############################################################## + +sub get_shortcut_identifier +{ + my ($shortcut) = @_; + + my $identifier = $shortcut->{'gid'}; + + return $identifier; +} + +############################################################## +# Returning directory for shortcut table. +############################################################## + +sub get_shortcut_directory +{ + my ($shortcut, $dirref) = @_; + + # For shortcuts it is easy to convert the gid_Dir_Abc into the unique name in + # the directory table, for instance help_en_simpressidx. + # For files (components) this is not so easy, because files can be included + # in zip files with subdirectories that are not defined in scp. + + my $onedir; + my $shortcutdirectory = $shortcut->{'Dir'}; + my $directory = ""; + my $found = 0; + + for ( my $i = 0; $i <= $#{$dirref}; $i++ ) + { + $onedir = ${$dirref}[$i]; + my $directorygid = $onedir->{'Dir'}; + + if ( $directorygid eq $shortcutdirectory ) + { + $found = 1; + last; + } + } + + if (!($found)) + { + installer::exiter::exit_program("ERROR: Did not find DirectoryID $shortcutdirectory in directory collection for shortcut", "get_shortcut_directory"); + } + + $directory = $onedir->{'uniquename'}; + + if ($directory eq "") { $directory = "OFFICEINSTALLLOCATION"; } # Shortcuts in the root directory + + return $directory; +} + +############################################################## +# Returning name for shortcut table. +############################################################## + +sub get_shortcut_name +{ + my ($shortcut, $shortnamesref, $onelanguage) = @_; + + my $returnstring; + + my $name = $shortcut->{'Name'}; + + my $shortstring = installer::windows::idtglobal::make_eight_three_conform($name, "shortcut", $shortnamesref); + $shortstring =~ s/\s/\_/g; # replacing white spaces with underline + + if ( $shortstring eq $name ) { $returnstring = $name; } # nothing changed + else {$returnstring = $shortstring . "\|" . $name; } + + return $returnstring; +} + +############################################################## +# Returning component for shortcut table. +############################################################## + +sub get_shortcut_component +{ + my ($shortcut, $filesref) = @_; + + my $onefile; + my $component = ""; + my $found = 0; + my $shortcut_fileid = $shortcut->{'FileID'}; + + my $absolute_filename = 0; + if ( $shortcut->{'Styles'} ) { $styles = $shortcut->{'Styles'}; } + if ( $styles =~ /\bABSOLUTE_FILENAME\b/ ) { $absolute_filename = 1; } # FileID contains an absolute filename + if ( $styles =~ /\bUSE_HELPER_FILENAME\b/ ) { $absolute_filename = 1; } # ComponentIDFile contains id of a helper file + + # if the FileID contains an absolute filename, therefore the entry for "ComponentIDFile" has to be used. + if ( $absolute_filename ) { $shortcut_fileid = $shortcut->{'ComponentIDFile'}; } + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + $onefile = ${$filesref}[$i]; + my $filegid = $onefile->{'gid'}; + + if ( $filegid eq $shortcut_fileid ) + { + $found = 1; + last; + } + } + + if (!($found)) + { + installer::exiter::exit_program("ERROR: Did not find FileID $shortcut_fileid in file collection for shortcut", "get_shortcut_component"); + } + + $component = $onefile->{'componentname'}; + + # finally saving the componentname in the folderitem collector + + $shortcut->{'component'} = $component; + + return $component; +} + +############################################################## +# Returning target for shortcut table. +############################################################## + +sub get_shortcut_target +{ + my ($shortcut, $filesref) = @_; + + my $target = ""; + my $found = 0; + my $shortcut_fileid = $shortcut->{'FileID'}; + my $onefile; + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + $onefile = ${$filesref}[$i]; + my $filegid = $onefile->{'gid'}; + + if ( $filegid eq $shortcut_fileid ) + { + $found = 1; + last; + } + } + + if (!($found)) + { + installer::exiter::exit_program("ERROR: Did not find FileID $shortcut_fileid in file collection for shortcut", "get_shortcut_target"); + } + + if ( $onefile->{'Name'} ) + { + $target = $onefile->{'Name'}; + } + + $target = "\[\#" . $target . "\]"; # format for Non-Advertised shortcuts + + return $target; +} + +############################################################## +# Returning arguments for shortcut table. +############################################################## + +sub get_shortcut_arguments +{ + my ($shortcut) = @_; + + return ""; +} + +############################################################## +# Returning the localized description for shortcut table. +############################################################## + +sub get_shortcut_description +{ + my ($shortcut, $onelanguage) = @_; + + my $description = ""; + if ( $shortcut->{'Tooltip'} ) { $description = $shortcut->{'Tooltip'}; } + + return $description; +} + +############################################################## +# Returning hotkey for shortcut table. +############################################################## + +sub get_shortcut_hotkey +{ + my ($shortcut) = @_; + + return ""; +} + +############################################################## +# Returning icon for shortcut table. +############################################################## + +sub get_shortcut_icon +{ + my ($shortcut) = @_; + + return ""; +} + +############################################################## +# Returning iconindex for shortcut table. +############################################################## + +sub get_shortcut_iconindex +{ + my ($shortcut) = @_; + + return ""; +} + +############################################################## +# Returning show command for shortcut table. +############################################################## + +sub get_shortcut_showcmd +{ + my ($shortcut) = @_; + + return ""; +} + +############################################################## +# Returning working directory for shortcut table. +############################################################## + +sub get_shortcut_wkdir +{ + my ($shortcut) = @_; + + return ""; +} + +#################################################################### +# Returning working directory for shortcut table for FolderItems. +#################################################################### + +sub get_folderitem_wkdir +{ + my ($onelink, $dirref) = @_; + + # For shortcuts it is easy to convert the gid_Dir_Abc into the unique name in + # the directory table, for instance help_en_simpressidx. + + my $onedir; + my $workingdirectory = ""; + if ( $onelink->{'WkDir'} ) { $workingdirectory = $onelink->{'WkDir'}; } + my $directory = ""; + + if ( $workingdirectory ) + { + my $found = 0; + + for ( my $i = 0; $i <= $#{$dirref}; $i++ ) + { + $onedir = ${$dirref}[$i]; + my $directorygid = $onedir->{'Dir'}; + + if ( $directorygid eq $workingdirectory ) + { + $found = 1; + last; + } + } + + if (!($found)) + { + installer::exiter::exit_program("ERROR: Did not find DirectoryID $workingdirectory in directory collection for FolderItem", "get_folderitem_wkdir"); + } + + $directory = $onedir->{'uniquename'}; + + if ($directory eq "") { $directory = "OFFICEINSTALLLOCATION"; } + } + + return $directory; +} + +################################################################### +# Returning the directory for a folderitem for shortcut table. +################################################################### + +sub get_folderitem_directory +{ + my ($shortcut) = @_; + + # my $directory = "$installer::globals::programmenufolder"; # default + my $directory = "$installer::globals::officemenufolder"; # default + + # The value $installer::globals::programmenufolder is not correct for the + # PREDEFINED folders, like PREDEFINED_AUTOSTART + + if ( $shortcut->{'FolderID'} eq "PREDEFINED_AUTOSTART" ) + { + $directory = $installer::globals::startupfolder; + } + + if ( $shortcut->{'FolderID'} eq "PREDEFINED_DESKTOP" ) + { + $directory = $installer::globals::desktopfolder; + $installer::globals::desktoplinkexists = 1; + } + + if ( $shortcut->{'FolderID'} eq "PREDEFINED_STARTMENU" ) + { + $directory = $installer::globals::startmenufolder; + } + + # saving the directory in the folderitems collector + + $shortcut->{'directory'} = $directory; + + return $directory; +} + +######################################################################## +# Returning the target (feature) for a folderitem for shortcut table. +# For non-advertised shortcuts this is a formatted string. +######################################################################## + +sub get_folderitem_target +{ + my ($shortcut, $filesref) = @_; + + my $onefile; + my $target = ""; + my $found = 0; + my $shortcut_fileid = $shortcut->{'FileID'}; + + my $styles = ""; + my $nonadvertised = 0; + my $absolute_filename = 0; + if ( $shortcut->{'Styles'} ) { $styles = $shortcut->{'Styles'}; } + if ( $styles =~ /\bNON_ADVERTISED\b/ ) { $nonadvertised = 1; } # this is a non-advertised shortcut + if ( $styles =~ /\bABSOLUTE_FILENAME\b/ ) { $absolute_filename = 1; } # FileID contains an absolute filename + + # if the FileID contains an absolute filename this can simply be returned as target for the shortcut table. + if ( $absolute_filename ) + { + $shortcut->{'target'} = $shortcut_fileid; + return $shortcut_fileid; + } + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + $onefile = ${$filesref}[$i]; + my $filegid = $onefile->{'gid'}; + + if ( $filegid eq $shortcut_fileid ) + { + $found = 1; + last; + } + } + + if (!($found)) + { + installer::exiter::exit_program("ERROR: Did not find FileID $shortcut_fileid in file collection for folderitem", "get_folderitem_target"); + } + + # Non advertised shortcuts do not return the feature, but the path to the file + if ( $nonadvertised ) + { + $target = "\[" . $onefile->{'uniquedirname'} . "\]" . "\\" . $onefile->{'Name'}; + $shortcut->{'target'} = $target; + return $target; + } + + # the rest only for advertised shortcuts, which contain the feature in the shortcut table. + + if ( $onefile->{'modules'} ) { $target = $onefile->{'modules'}; } + + # If modules contains a list of modules, only taking the first one. + # But this should never be needed + + if ( $target =~ /^\s*(.*?)\,/ ) { $target = $1; } + + # Attention: Maximum feature length is 38! + installer::windows::idtglobal::shorten_feature_gid(\$target); + + # and finally saving the target in the folderitems collector + + $shortcut->{'target'} = $target; + + return $target; +} + +######################################################################## +# Returning the arguments for a folderitem for shortcut table. +######################################################################## + +sub get_folderitem_arguments +{ + my ($shortcut) = @_; + + my $parameter = ""; + + if ( $shortcut->{'Parameter'} ) { $parameter = $shortcut->{'Parameter'}; } + + return $parameter; +} + +######################################################################## +# Returning the icon for a folderitem for shortcut table. +# The returned value has to be defined in the icon table. +######################################################################## + +sub get_folderitem_icon +{ + my ($shortcut, $filesref, $iconfilecollector) = @_; + + my $styles = ""; + if ( $shortcut->{'Styles'} ) { $styles = $shortcut->{'Styles'}; } + if ( $styles =~ /\bNON_ADVERTISED\b/ ) { return ""; } # no icon for non-advertised shortcuts + + my $iconfilegid = ""; + + if ( $shortcut->{'IconFile'} ) { $iconfilegid = $shortcut->{'IconFile'}; } + else { $iconfilegid = $shortcut->{'FileID'}; } + + my $onefile; + my $found = 0; + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + $onefile = ${$filesref}[$i]; + my $filegid = $onefile->{'gid'}; + + if ( $filegid eq $iconfilegid ) + { + $found = 1; + last; + } + } + + if (!($found)) + { + installer::exiter::exit_program("ERROR: Did not find FileID $iconfilegid in file collection", "get_folderitem_icon"); + } + + $iconfile = $onefile->{'Name'}; + + # collecting all icon files to copy them into the icon directory + + my $sourcepath = $onefile->{'sourcepath'}; + + if (! installer::existence::exists_in_array($sourcepath, $iconfilecollector)) + { + push(@{$iconfilecollector}, $sourcepath); + } + + return $iconfile; +} + +######################################################################## +# Returning the iconindex for a folderitem for shortcut table. +######################################################################## + +sub get_folderitem_iconindex +{ + my ($shortcut) = @_; + + my $styles = ""; + if ( $shortcut->{'Styles'} ) { $styles = $shortcut->{'Styles'}; } + if ( $styles =~ /\bNON_ADVERTISED\b/ ) { return ""; } # no iconindex for non-advertised shortcuts + + my $iconid = 0; + + if ( $shortcut->{'IconID'} ) { $iconid = $shortcut->{'IconID'}; } + + return $iconid; +} + +######################################################################## +# Returning the show command for a folderitem for shortcut table. +######################################################################## + +sub get_folderitem_showcmd +{ + my ($shortcut) = @_; + + return "1"; +} + +########################################################################################################### +# Creating the file Shortcut.idt dynamically +# Content: +# Shortcut Directory_ Name Component_ Target Arguments Description Hotkey Icon_ IconIndex ShowCmd WkDir +########################################################################################################### + +sub create_shortcut_table +{ + my ($filesref, $linksref, $folderref, $folderitemsref, $dirref, $basedir, $languagesarrayref, $includepatharrayref, $iconfilecollector) = @_; + + for ( my $m = 0; $m <= $#{$languagesarrayref}; $m++ ) + { + my $onelanguage = ${$languagesarrayref}[$m]; + + my @shortcuttable = (); + + my @shortnames = (); # to collect all short names + + installer::windows::idtglobal::write_idt_header(\@shortcuttable, "shortcut"); + + # First the links, defined in scp as ShortCut + + for ( my $i = 0; $i <= $#{$linksref}; $i++ ) + { + my $onelink = ${$linksref}[$i]; + + # Controlling the language! + # Only language independent folderitems or folderitems with the correct language + # will be included into the table + + if (! (!(( $onelink->{'ismultilingual'} )) || ( $onelink->{'specificlanguage'} eq $onelanguage )) ) { next; } + + my %shortcut = (); + + $shortcut{'Shortcut'} = get_shortcut_identifier($onelink); + $shortcut{'Directory_'} = get_shortcut_directory($onelink, $dirref); + $shortcut{'Name'} = get_shortcut_name($onelink, \@shortnames, $onelanguage); # localized name + $shortcut{'Component_'} = get_shortcut_component($onelink, $filesref); + $shortcut{'Target'} = get_shortcut_target($onelink, $filesref); + $shortcut{'Arguments'} = get_shortcut_arguments($onelink); + $shortcut{'Description'} = get_shortcut_description($onelink, $onelanguage); # localized description + $shortcut{'Hotkey'} = get_shortcut_hotkey($onelink); + $shortcut{'Icon_'} = get_shortcut_icon($onelink); + $shortcut{'IconIndex'} = get_shortcut_iconindex($onelink); + $shortcut{'ShowCmd'} = get_shortcut_showcmd($onelink); + $shortcut{'WkDir'} = get_shortcut_wkdir($onelink); + + my $oneline = $shortcut{'Shortcut'} . "\t" . $shortcut{'Directory_'} . "\t" . $shortcut{'Name'} . "\t" + . $shortcut{'Component_'} . "\t" . $shortcut{'Target'} . "\t" . $shortcut{'Arguments'} . "\t" + . $shortcut{'Description'} . "\t" . $shortcut{'Hotkey'} . "\t" . $shortcut{'Icon_'} . "\t" + . $shortcut{'IconIndex'} . "\t" . $shortcut{'ShowCmd'} . "\t" . $shortcut{'WkDir'} . "\n"; + + push(@shortcuttable, $oneline); + } + + # Second the entries into the start menu, defined in scp as Folder and Folderitem + # These shortcuts will fill the icons table. + + for ( my $i = 0; $i <= $#{$folderref}; $i++ ) + { + my $foldergid = ${$folderref}[$i]->{'gid'}; + + # iterating over all folderitems for this folder + + for ( my $j = 0; $j <= $#{$folderitemsref}; $j++ ) + { + my $onelink = ${$folderitemsref}[$j]; + + # Controlling the language! + # Only language independent folderitems or folderitems with the correct language + # will be included into the table + + if (! (!(( $onelink->{'ismultilingual'} )) || ( $onelink->{'specificlanguage'} eq $onelanguage )) ) { next; } + + # controlling the folder + + my $localused = 0; + + if ( $onelink->{'used'} ) { $localused = $onelink->{'used'}; } + + if (!($localused == 1)) { $onelink->{'used'} = "0"; } # no resetting + + if (!( $onelink->{'FolderID'} eq $foldergid )) { next; } + + $onelink->{'used'} = "1"; + + my %shortcut = (); + + $shortcut{'Shortcut'} = get_shortcut_identifier($onelink); + $shortcut{'Directory_'} = get_folderitem_directory($onelink); + $shortcut{'Name'} = get_shortcut_name($onelink, \@shortnames, $onelanguage); # localized name + $shortcut{'Component_'} = get_shortcut_component($onelink, $filesref); + $shortcut{'Target'} = get_folderitem_target($onelink, $filesref); + $shortcut{'Arguments'} = get_folderitem_arguments($onelink); + $shortcut{'Description'} = get_shortcut_description($onelink, $onelanguage); # localized description + $shortcut{'Hotkey'} = get_shortcut_hotkey($onelink); + $shortcut{'Icon_'} = get_folderitem_icon($onelink, $filesref, $iconfilecollector); + $shortcut{'IconIndex'} = get_folderitem_iconindex($onelink); + $shortcut{'ShowCmd'} = get_folderitem_showcmd($onelink); + $shortcut{'WkDir'} = get_folderitem_wkdir($onelink, $dirref); + + my $oneline = $shortcut{'Shortcut'} . "\t" . $shortcut{'Directory_'} . "\t" . $shortcut{'Name'} . "\t" + . $shortcut{'Component_'} . "\t" . $shortcut{'Target'} . "\t" . $shortcut{'Arguments'} . "\t" + . $shortcut{'Description'} . "\t" . $shortcut{'Hotkey'} . "\t" . $shortcut{'Icon_'} . "\t" + . $shortcut{'IconIndex'} . "\t" . $shortcut{'ShowCmd'} . "\t" . $shortcut{'WkDir'} . "\n"; + + push(@shortcuttable, $oneline); + } + } + + # if it is part of the product, the soffice.exe has to be included into the icon table + # as icon for the ARP applet + + my $sofficefile = "soffice.exe"; + my $onefile = get_file_by_name($filesref, $sofficefile); + + if ( $onefile ne "" ) + { + my $sourcepath = $onefile->{'sourcepath'}; + if (! installer::existence::exists_in_array($sourcepath, $iconfilecollector)) + { + unshift(@{$iconfilecollector}, $sourcepath); + $installer::globals::sofficeiconadded = 1; + } + } + + # For language packs and patches the soffice.exe has to be included, even if it is not part of the product. + # Also as part of the ARP applet (no substitution needed for ProductName, because the file is not installed!) + + if (( $onefile eq "" ) && (( $installer::globals::languagepack ) || ( $installer::globals::patch ))) + { + my $sourcepathref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$sofficefile, $includepatharrayref, 1); + if ($$sourcepathref eq "") { installer::exiter::exit_program("ERROR: Could not find $sofficefile as icon in language pack!", "create_shortcut_table"); } + + if (! installer::existence::exists_in_array($$sourcepathref, $iconfilecollector)) + { + unshift(@{$iconfilecollector}, $$sourcepathref); + $installer::globals::sofficeiconadded = 1; + } + + my $localinfoline = "Added icon file $$sourcepathref for language pack into icon file collector.\n"; + push(@installer::globals::logfileinfo, $localinfoline); + } + + # Saving the file + + my $shortcuttablename = $basedir . $installer::globals::separator . "Shortcut.idt" . "." . $onelanguage; + installer::files::save_file($shortcuttablename ,\@shortcuttable); + my $infoline = "Created idt file: $shortcuttablename\n"; + push(@installer::globals::logfileinfo, $infoline); + } +} + + +1;
\ No newline at end of file diff --git a/solenv/bin/modules/installer/windows/sign.pm b/solenv/bin/modules/installer/windows/sign.pm new file mode 100644 index 000000000000..b1abbbfb73a7 --- /dev/null +++ b/solenv/bin/modules/installer/windows/sign.pm @@ -0,0 +1,438 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: binary.pm,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::sign; + +use Cwd; +use installer::converter; +use installer::existence; +use installer::files; +use installer::globals; +use installer::scriptitems; +use installer::worker; +use installer::windows::admin; + +######################################################## +# Copying an existing Windows installation set. +######################################################## + +sub copy_install_set +{ + my ( $installsetpath ) = @_; + + installer::logger::include_header_into_logfile("Start: Copying installation set $installsetpath"); + + my $infoline = ""; + + my $dirname = $installsetpath; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$dirname); + + my $path = $installsetpath; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$path); + + $path =~ s/\Q$installer::globals::separator\E\s*$//; + + if ( $dirname =~ /\./ ) { $dirname =~ s/\./_signed_inprogress./; } + else { $dirname = $dirname . "_signed_inprogress"; } + + my $newpath = $path . $installer::globals::separator . $dirname; + my $removepath = $newpath; + $removepath =~ s/_inprogress/_witherror/; + + if ( -d $newpath ) { installer::systemactions::remove_complete_directory($newpath, 1); } + if ( -d $removepath ) { installer::systemactions::remove_complete_directory($removepath, 1); } + + $infoline = "Copy installation set from $installsetpath to $newpath\n"; + push( @installer::globals::logfileinfo, $infoline); + + $installsetpath = installer::systemactions::copy_complete_directory($installsetpath, $newpath); + + installer::logger::include_header_into_logfile("End: Copying installation set $installsetpath"); + + return $newpath; +} + +######################################################## +# Renaming an existing Windows installation set. +######################################################## + +sub rename_install_set +{ + my ( $installsetpath ) = @_; + + my $infoline = ""; + + my $dirname = $installsetpath; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$dirname); + + my $path = $installsetpath; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$path); + + $path =~ s/\Q$installer::globals::separator\E\s*$//; + + if ( $dirname =~ /\./ ) { $dirname =~ s/\./_inprogress./; } + else { $dirname = $dirname . "_inprogress"; } + + my $newpath = $path . $installer::globals::separator . $dirname; + my $removepath = $newpath; + $removepath =~ s/_inprogress/_witherror/; + + if ( -d $newpath ) { installer::systemactions::remove_complete_directory($newpath, 1); } + if ( -d $removepath ) { installer::systemactions::remove_complete_directory($removepath, 1); } + + $installsetpath = installer::systemactions::rename_directory($installsetpath, $newpath); + + return $newpath; +} + +######################################################### +# Checking the local system +# Checking existence of needed files in include path +######################################################### + +sub check_system_path +{ + # The following files have to be found in the environment variable PATH + # Only, if \"-sign\" is used. + # Windows : "msicert.exe", "msidb.exe", "signtool.exe" + + my @needed_files_in_path = ("msicert.exe", "msidb.exe", "signtool.exe"); + + my $onefile; + my $error = 0; + my $pathvariable = $ENV{'PATH'}; + my $local_pathseparator = $installer::globals::pathseparator; + + if( $^O =~ /cygwin/i ) + { # When using cygwin's perl the PATH variable is POSIX style and ... + $pathvariable = qx{cygpath -mp "$pathvariable"} ; + # has to be converted to DOS style for further use. + $local_pathseparator = ';'; + } + + my $patharrayref = installer::converter::convert_stringlist_into_array(\$pathvariable, $local_pathseparator); + + $installer::globals::patharray = $patharrayref; + + foreach my $onefile ( @needed_files_in_path ) + { + installer::logger::print_message( "...... searching $onefile ..." ); + + my $fileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath_classic(\$onefile, $patharrayref , 0); + + if ( $$fileref eq "" ) + { + $error = 1; + installer::logger::print_error( "$onefile not found\n" ); + } + else + { + installer::logger::print_message( "\tFound: $$fileref\n" ); + } + } + + $installer::globals::signfiles_checked = 1; + + if ( $error ) { installer::exiter::exit_program("ERROR: Could not find all needed files in path!", "check_system_path"); } +} + +###################################################### +# Making systemcall +###################################################### + +sub make_systemcall +{ + my ($systemcall, $displaysystemcall) = @_; + + installer::logger::print_message( "... $displaysystemcall ...\n" ); + + my $success = 1; + my $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $displaysystemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$displaysystemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + $success = 0; + } + else + { + $infoline = "Success: Executed \"$displaysystemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + return $success; +} + +######################################################## +# Reading first line of pw file. +######################################################## + +sub get_pw +{ + my ( $file ) = @_; + + my $filecontent = installer::files::read_file($file); + + my $pw = ${$filecontent}[0]; + $pw =~ s/^\s*//; + $pw =~ s/\s*$//; + + return $pw; +} + +######################################################## +# Counting the keys of a hash. +######################################################## + +sub get_hash_count +{ + my ($hashref) = @_; + + my $counter = 0; + + foreach my $key ( keys %{$hashref} ) { $counter++; } + + return $counter; +} + +############################################################ +# Collect all DiskIds to the corresponding cabinet files. +############################################################ + +sub analyze_media_file +{ + my ($filecontent) = @_; + + my %diskidhash = (); + + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if ( $i < 3 ) { next; } + + if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) + { + my $diskid = $1; + my $cabfile = $4; + + $diskidhash{$cabfile} = $diskid; + } + } + + return \%diskidhash; +} + +######################################################## +# Collect all DiskIds from database table "Media". +######################################################## + +sub collect_diskid +{ + my ($msidatabase, $languagestring) = @_; + + # creating working directory + my $workdir = installer::systemactions::create_directories("media", \$languagestring); + installer::windows::admin::extract_tables_from_pcpfile($msidatabase, $workdir, "Media"); + + # Reading tables + my $filename = $workdir . $installer::globals::separator . "Media.idt"; + if ( ! -f $filename ) { installer::exiter::exit_program("ERROR: Could not find required file: $filename !", "collect_diskid"); } + my $filecontent = installer::files::read_file($filename); + my $diskidhash = analyze_media_file($filecontent); + + return $diskidhash; +} + +######################################################## +# Collecting all files in an installation set. +######################################################## + +sub analyze_installset_content +{ + my ( $installsetpath ) = @_; + + my @sourcefiles = (); + my $pathstring = ""; + installer::systemactions::read_complete_directory($installsetpath, $pathstring, \@sourcefiles); + + if ( ! ( $#sourcefiles > -1 )) { installer::exiter::exit_program("ERROR: No file in installation set. Path: $installsetpath !", "analyze_installset_content"); } + + my %allcabfileshash = (); + my %allmsidatabaseshash = (); + my %allfileshash = (); + my $contains_cab_file = 0; + my $msidatabase = ""; + + for ( my $j = 0; $j <= $#sourcefiles; $j++ ) + { + if ( $sourcefiles[$j] =~ /\.cab\s*$/ ) { $allcabfileshash{$sourcefiles[$j]} = 1; } + else + { + if ( $sourcefiles[$j] =~ /instmsi\w+.exe\s*$/ ) { next; } # no signing of instmsia.exe and instmsiw.exe + if ( $sourcefiles[$j] =~ /jre[-\w]+.exe\s*$/ ) { next; } # no signing of java executable + if ( $sourcefiles[$j] =~ /\.txt\s*$/ ) { next; } + if ( $sourcefiles[$j] =~ /\.html\s*$/ ) { next; } + if ( $sourcefiles[$j] =~ /\.ini\s*$/ ) { next; } + if ( $sourcefiles[$j] =~ /\.msi\s*$/ ) + { + if ( $msidatabase eq "" ) { $msidatabase = $sourcefiles[$j]; } + else { installer::exiter::exit_program("ERROR: There is more than one msi database in installation set. Path: $installsetpath !", "analyze_installset_content"); } + } + $allfileshash{$sourcefiles[$j]} = 1; + } + } + + # Is there at least one cab file in the installation set? + my $cabcounter = get_hash_count(\%allcabfileshash); + if ( $cabcounter > 0 ) { $contains_cab_file = 1; } + + # How about a cab file without a msi database? + if (( $cabcounter > 0 ) && ( $msidatabase eq "" )) { installer::exiter::exit_program("ERROR: There is no msi database in the installation set, but an external cabinet file. Path: $installsetpath !", "collect_installset_content"); } + + return (\%allcabfileshash, \%allfileshash, $msidatabase, $contains_cab_file); +} + +######################################################## +# Adding content of external cabinet files into the +# msi database +######################################################## + +sub msicert_database +{ + my ($msidatabase, $allcabfiles, $languagestring) = @_; + + # exclude media table from msi database and get all diskids. + my $cabfilehash = collect_diskid($msidatabase, $languagestring); + + my $fullsuccess = 1; + + foreach my $cabfile ( keys %{$allcabfiles} ) + { + if ( ! exists($cabfilehash->{$cabfile}) ) { installer::exiter::exit_program("ERROR: Could not determine DiskId from media table for cabinet file \"$cabfile\" !", "msicert_database"); } + my $diskid = $cabfilehash->{$cabfile}; + my $systemcall = "msicert.exe -d $msidatabase -m $diskid -c $cabfile -h"; + $success = make_systemcall($systemcall, $systemcall); + if ( ! $success ) { $fullsuccess = 0; } + } + + return $fullsuccess; +} + +######################################################## +# Signing a list of files +######################################################## + +sub sign_files +{ + my ( $followmeinfohash, $allfiles, $pw ) = @_; + + my $infoline = ""; + my $fullsuccess = 1; + + my $productname = ""; + if ( $followmeinfohash->{'allvariableshash'}->{'PRODUCTNAME'} ) { $productname = "/d " . "\"$followmeinfohash->{'allvariableshash'}->{'PRODUCTNAME'}\""; } + my $url = ""; + if ( $followmeinfohash->{'allvariableshash'}->{'OPENSOURCE'} == 0 ) { $url = "/du " . "\"http://www.sun.com\""; } + else { $url = "/du " . "\"http://www.openoffice.org\""; } + my $timestampurl = "http://timestamp.verisign.com/scripts/timestamp.dll"; + + foreach my $onefile ( keys %{$allfiles} ) + { + my $systemcall = "signtool.exe sign /f \"$installer::globals::pfxfile\" /p $pw $productname $url /t \"$timestampurl\" \"$onefile\""; + my $displaysystemcall = "signtool.exe sign /f \"$installer::globals::pfxfile\" /p ***** $productname $url /t \"$timestampurl\" \"$onefile\""; + my $success = make_systemcall($systemcall, $displaysystemcall); + if ( ! $success ) { $fullsuccess = 0; } + } + + return $fullsuccess; +} + +######################################################## +# Signing an existing Windows installation set. +######################################################## + +sub sign_install_set +{ + my ($followmeinfohash, $make_copy) = @_; + + my $installsetpath = $followmeinfohash->{'finalinstalldir'}; + + installer::logger::include_header_into_logfile("Start: Signing installation set $installsetpath"); + + my $complete_success = 1; + my $success = 1; + + my $infoline = "Signing installation set in $installsetpath\n"; + push( @installer::globals::logfileinfo, $infoline); + + # check required files. + if ( ! $installer::globals::signfiles_checked ) { check_system_path(); } + + # get cerficate information + my $pw = get_pw($installer::globals::pwfile); + + # making a copy of the installation set, if required + if ( $make_copy ) { $installsetpath = copy_install_set($installsetpath); } + else { $installsetpath = rename_install_set($installsetpath); } + + # collecting all files in the installation set + my ($allcabfiles, $allfiles, $msidatabase, $contains_cab_file) = analyze_installset_content($installsetpath); + + # changing into installation set + my $from = cwd(); + chdir($installsetpath); + + # Warning: There might be a problem with very big cabinet files + # signing all external cab files first + if ( $contains_cab_file ) + { + $success = sign_files($followmeinfohash, $allcabfiles, $pw); + if ( ! $success ) { $complete_success = 0; } + $success = msicert_database($msidatabase, $allcabfiles, $followmeinfohash->{'languagestring'}); + if ( ! $success ) { $complete_success = 0; } + } + + # finally all other files can be signed + $success = sign_files($followmeinfohash, $allfiles, $pw); + if ( ! $success ) { $complete_success = 0; } + + # and changing back + chdir($from); + + installer::logger::include_header_into_logfile("End: Signing installation set $installsetpath"); + + return ($installsetpath); +} + +1; diff --git a/solenv/bin/modules/installer/windows/strip.pm b/solenv/bin/modules/installer/windows/strip.pm new file mode 100644 index 000000000000..c7e5e883596c --- /dev/null +++ b/solenv/bin/modules/installer/windows/strip.pm @@ -0,0 +1,163 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: strip.pm,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::strip; + +use File::Temp qw(tmpnam); +use installer::converter; +use installer::existence; +use installer::globals; +use installer::logger; +use installer::pathanalyzer; +use installer::systemactions; + +##################################################################### +# Checking whether a file has to be stripped +##################################################################### + +sub need_to_strip +{ + my ( $filename ) = @_; + + my $strip = 0; + + # Check using the "nm" command + + $filename =~ s/\\/\\\\/g; + + open (FILE, "nm $filename 2>&1 |"); + my $nmoutput = <FILE>; + close (FILE); + + if ( $nmoutput && !( $nmoutput =~ /no symbols/i || $nmoutput =~ /not recognized/i )) { $strip = 1; } + + return $strip +} + +##################################################################### +# Checking whether a file has to be stripped +##################################################################### + +sub do_strip +{ + my ( $filename ) = @_; + + my $systemcall = "strip" . " " . $filename; + + my $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not strip $filename!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "SUCCESS: Stripped library $filename!\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +##################################################################### +# Resolving all variables in the packagename. +##################################################################### + +sub strip_binaries +{ + my ( $filelist, $languagestringref ) = @_; + + installer::logger::include_header_into_logfile("Stripping files:"); + + my $strippeddirbase = installer::systemactions::create_directories("stripped", $languagestringref); + + if (! installer::existence::exists_in_array($strippeddirbase, \@installer::globals::removedirs)) + { + push(@installer::globals::removedirs, $strippeddirbase); + } + + my ($tmpfilehandle, $tmpfilename) = tmpnam(); + open SOURCEPATHLIST, ">$tmpfilename" or die "oops...\n"; + for ( my $i = 0; $i <= $#{$filelist}; $i++ ) + { + print SOURCEPATHLIST "${$filelist}[$i]->{'sourcepath'}\n"; + } + close SOURCEPATHLIST; + my @filetypelist = qx{file -f "$tmpfilename"}; + chomp @filetypelist; + unlink "$tmpfilename" or die "oops\n"; + for ( my $i = 0; $i <= $#{$filelist}; $i++ ) + { + ${$filelist}[$i]->{'is_executable'} = ( $filetypelist[$i] =~ /:.*PE executable/ ); + } + + if ( $^O =~ /cygwin/i ) { installer::worker::generate_cygwin_pathes($filelist); } + + for ( my $i = 0; $i <= $#{$filelist}; $i++ ) + { + my $sourcefilename = ${$filelist}[$i]->{'cyg_sourcepath'}; + + if ( ${$filelist}[$i]->{'is_executable'} && need_to_strip($sourcefilename) ) + { + my $shortfilename = $sourcefilename; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$shortfilename); + + $infoline = "Strip: $shortfilename\n"; + push( @installer::globals::logfileinfo, $infoline); + + # copy file into directory for stripped libraries + + my $onelanguage = ${$filelist}[$i]->{'specificlanguage'}; + + # files without language into directory "00" + + if ($onelanguage eq "") { $onelanguage = "00"; } + + my $strippeddir = $strippeddirbase . $installer::globals::separator . $onelanguage; + installer::systemactions::create_directory($strippeddir); # creating language specific subdirectories + + my $destfilename = $strippeddir . $installer::globals::separator . $shortfilename; + installer::systemactions::copy_one_file($sourcefilename, $destfilename); + + # change sourcepath in files collector + + ${$filelist}[$i]->{'sourcepath'} = $destfilename; + + # strip file + + do_strip($destfilename); + } + } +} + +1; diff --git a/solenv/bin/modules/installer/windows/update.pm b/solenv/bin/modules/installer/windows/update.pm new file mode 100644 index 000000000000..a20e84d1f1d3 --- /dev/null +++ b/solenv/bin/modules/installer/windows/update.pm @@ -0,0 +1,596 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: update.pm,v $ +# +# $Revision: 1.2 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::update; + +use installer::converter; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::pathanalyzer; +use installer::systemactions; + +################################################################################# +# Extracting all tables from an msi database +################################################################################# + +sub extract_all_tables_from_msidatabase +{ + my ($fulldatabasepath, $workdir) = @_; + + my $msidb = "msidb.exe"; # Has to be in the path + my $infoline = ""; + my $systemcall = ""; + my $returnvalue = ""; + + # Export of all tables by using "*" + + $systemcall = $msidb . " -d " . $fulldatabasepath . " -f " . $workdir . " -e \*"; + $returnvalue = system($systemcall); + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute $systemcall !\n"; + push( @installer::globals::logfileinfo, $infoline); + installer::exiter::exit_program("ERROR: Could not exclude tables from msi database: $fulldatabasepath !", "extract_all_tables_from_msidatabase"); + } + else + { + $infoline = "Success: Executed $systemcall successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +################################################################################# +# Collecting the keys from the first line of the idt file +################################################################################# + +sub collect_all_keys +{ + my ($line) = @_; + + my @allkeys = (); + my $rownumber = 0; + my $onekey = ""; + + while ( $line =~ /^\s*(\S+?)\t(.*)$/ ) + { + $onekey = $1; + $line = $2; + $rownumber++; + push(@allkeys, $onekey); + } + + # and the last key + + $onekey = $line; + $onekey =~ s/^\s*//g; + $onekey =~ s/\s*$//g; + + $rownumber++; + push(@allkeys, $onekey); + + return (\@allkeys, $rownumber); +} + +################################################################################# +# Analyzing the content of one line of an idt file +################################################################################# + +sub get_oneline_hash +{ + my ($line, $allkeys, $rownumber) = @_; + + my $counter = 0; + my %linehash = (); + + $line =~ s/^\s*//; + $line =~ s/\s*$//; + + my $value = ""; + my $onekey = ""; + + while ( $line =~ /^(.*?)\t(.*)$/ ) + { + $value = $1; + $line = $2; + $onekey = ${$allkeys}[$counter]; + $linehash{$onekey} = $value; + $counter++; + } + + # the last column + + $value = $line; + $onekey = ${$allkeys}[$counter]; + + $linehash{$onekey} = $value; + + return \%linehash; +} + +################################################################################# +# Analyzing the content of an idt file +################################################################################# + +sub analyze_idt_file +{ + my ($filecontent) = @_; + + my %table = (); + # keys are written in first line + my ($allkeys, $rownumber) = collect_all_keys(${$filecontent}[0]); + + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; } + + my $onelinehash = get_oneline_hash(${$filecontent}[$i], $allkeys, $rownumber); + my $linekey = $i - 2; # ! : The linenumber is the unique key !? Always decrease by two, because of removed first three lines. + $table{$linekey} = $onelinehash; + } + + return \%table; +} + +################################################################################# +# Reading all idt files in a specified directory +################################################################################# + +sub read_all_tables_from_msidatabase +{ + my ($workdir) = @_; + + my %database = (); + + my $ext = "idt"; + + my $allidtfiles = installer::systemactions::find_file_with_file_extension($ext, $workdir); + + for ( my $i = 0; $i <= $#{$allidtfiles}; $i++ ) + { + my $onefilename = ${$allidtfiles}[$i]; + my $longonefilename = $workdir . $installer::globals::separator . $onefilename; + if ( ! -f $longonefilename ) { installer::exiter::exit_program("ERROR: Could not find idt file: $longonefilename!", "read_all_tables_from_msidatabase"); } + my $filecontent = installer::files::read_file($longonefilename); + my $idtcontent = analyze_idt_file($filecontent); + my $key = $onefilename; + $key =~ s/\.idt\s*$//; + $database{$key} = $idtcontent; + } + + return \%database; +} + +################################################################################# +# Checking, if this is the correct database. +################################################################################# + +sub correct_database +{ + my ($product, $pro, $langs, $languagestringref) = @_; + + my $correct_database = 0; + + # Comparing $product with $installer::globals::product and + # $pro with $installer::globals::pro and + # $langs with $languagestringref + + my $product_is_good = 0; + + my $localproduct = $installer::globals::product; + if ( $installer::globals::languagepack ) { $localproduct = $localproduct . "LanguagePack"; } + + if ( $product eq $localproduct ) { $product_is_good = 1; } + + if ( $product_is_good ) + { + my $pro_is_good = 0; + + if ((( $pro eq "pro" ) && ( $installer::globals::pro )) || (( $pro eq "nonpro" ) && ( ! $installer::globals::pro ))) { $pro_is_good = 1; } + + if ( $pro_is_good ) + { + my $langlisthash = installer::converter::convert_stringlist_into_hash(\$langs, ","); + my $langstringhash = installer::converter::convert_stringlist_into_hash($languagestringref, "_"); + + my $not_included = 0; + foreach my $onelang ( keys %{$langlisthash} ) + { + if ( ! exists($langstringhash->{$onelang}) ) + { + $not_included = 1; + last; + } + } + + if ( ! $not_included ) + { + foreach my $onelanguage ( keys %{$langstringhash} ) + { + if ( ! exists($langlisthash->{$onelanguage}) ) + { + $not_included = 1; + last; + } + } + + if ( ! $not_included ) { $correct_database = 1; } + } + } + } + + return $correct_database; +} + +################################################################################# +# Searching for the path to the reference database for this special product. +################################################################################# + +sub get_databasename_from_list +{ + my ($filecontent, $languagestringref, $filename) = @_; + + my $databasepath = ""; + + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + my $line = ${$filecontent}[$i]; + if ( $line =~ /^\s*$/ ) { next; } # empty line + if ( $line =~ /^\s*\#/ ) { next; } # comment line + + if ( $line =~ /^\s*(.+?)\s*\t+\s*(.+?)\s*\t+\s*(.+?)\s*\t+\s*(.+?)\s*$/ ) + { + my $product = $1; + my $pro = $2; + my $langs = $3; + my $path = $4; + + if (( $pro ne "pro" ) && ( $pro ne "nonpro" )) { installer::exiter::exit_program("ERROR: Wrong syntax in file: $filename. Only \"pro\" or \"nonpro\" allowed in column 1! Line: \"$line\"", "get_databasename_from_list"); } + + if ( correct_database($product, $pro, $langs, $languagestringref) ) + { + $databasepath = $path; + last; + } + } + else + { + installer::exiter::exit_program("ERROR: Wrong syntax in file: $filename! Line: \"$line\"", "get_databasename_from_list"); + } + } + + return $databasepath; +} + +################################################################################# +# Reading an existing database completely +################################################################################# + +sub readdatabase +{ + my ($allvariables, $languagestringref, $includepatharrayref) = @_; + + my $database = ""; + my $infoline = ""; + + if ( ! $allvariables->{'UPDATE_DATABASE_LISTNAME'} ) { installer::exiter::exit_program("ERROR: If \"UPDATE_DATABASE\" is set, \"UPDATE_DATABASE_LISTNAME\" is required.", "Main"); } + my $listfilename = $allvariables->{'UPDATE_DATABASE_LISTNAME'}; + + # Searching the list in the include pathes + my $listname = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$listfilename, $includepatharrayref, 1); + if ( $$listname eq "" ) { installer::exiter::exit_program("ERROR: List file not found: $listfilename !", "readdatabase"); } + my $completelistname = $$listname; + + # Reading list file + my $listfile = installer::files::read_file($completelistname); + + # Get name and path of reference database + my $databasename = get_databasename_from_list($listfile, $languagestringref, $completelistname); + + # If the correct database was not found, this is not necessarily an error. But in this case, this is not an update packaging process! + if (( $databasename ) && ( $databasename ne "" )) # This is an update packaging process! + { + $installer::globals::updatedatabase = 1; + installer::logger::print_message( "... update process, using database $databasename ...\n" ); + $infoline = "\nDatabase found in $completelistname: \"$databasename\"\n\n"; + # Saving in global variable + $installer::globals::updatedatabasepath = $databasename; + } + else + { + # installer::logger::print_message( "... no update process, no database found ...\n" ); + $infoline = "\nNo database found in $completelistname. This is no update process!\n\n"; + } + push( @installer::globals::logfileinfo, $infoline); + + if ( $installer::globals::updatedatabase ) + { + if ( ! -f $databasename ) { installer::exiter::exit_program("ERROR: Could not find reference database: $databasename!", "readdatabase"); } + + my $msifilename = $databasename; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$msifilename); + + installer::logger::include_timestamp_into_logfile("Performance Info: readdatabase start"); + + # create directory for unpacking + my $databasedir = installer::systemactions::create_directories("database", $languagestringref); + + # copy database + my $fulldatabasepath = $databasedir . $installer::globals::separator . $msifilename; + installer::systemactions::copy_one_file($databasename, $fulldatabasepath); + + installer::logger::include_timestamp_into_logfile("Performance Info: readdatabase: before extracting tables"); + + # extract all tables from database + extract_all_tables_from_msidatabase($fulldatabasepath, $databasedir); + + installer::logger::include_timestamp_into_logfile("Performance Info: readdatabase: before reading tables"); + + # read all tables + $database = read_all_tables_from_msidatabase($databasedir); + + # Test output: + + # foreach my $key1 ( keys %{$database} ) + # { + # print "Test1: $key1\n"; + # foreach my $key2 ( keys %{$database->{$key1}} ) + # { + # print "\tTest2: $key2\n"; + # foreach my $key3 ( keys %{$database->{$key1}->{$key2}} ) + # { + # print "\t\tTest3: $key3: $database->{$key1}->{$key2}->{$key3}\n"; + # } + # } + # } + + # Example: File table + + # my $filetable = $database->{'File'}; + # foreach my $linenumber ( keys %{$filetable} ) + # { + # print "Test Filenumber: $linenumber\n"; + # foreach my $key ( keys %{$filetable->{$linenumber}} ) + # { + # print "\t\tTest: $key: $filetable->{$linenumber}->{$key}\n"; + # } + # } + + # Example: Searching for ProductCode in table Property + + # my $column1 = "Property"; + # my $column2 = "Value"; + # my $searchkey = "ProductCode"; + # my $propertytable = $database->{'Property'}; + # foreach my $linenumber ( keys %{$propertytable} ) + # { + # if ( $propertytable->{$linenumber}->{$column1} eq $searchkey ) + # { + # print("Test: $searchkey : $propertytable->{$linenumber}->{$column2}\n"); + # } + # } + + installer::logger::include_timestamp_into_logfile("Performance Info: readdatabase end"); + } + + return $database; +} + +################################################################################# +# Files can be included in merge modules. This is also important for update. +################################################################################# + +sub readmergedatabase +{ + my ( $mergemodules, $languagestringref, $includepatharrayref ) = @_; + + installer::logger::include_timestamp_into_logfile("Performance Info: readmergedatabase start"); + + my $mergemoduledir = installer::systemactions::create_directories("mergedatabase", $languagestringref); + + my %allmergefiles = (); + + $installer::globals::mergemodulenumber = $#{$mergemodules} + 1; + + foreach my $mergemodule ( @{$mergemodules} ) + { + my $filename = $mergemodule->{'Name'}; + my $mergefile = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$filename, $includepatharrayref, 1); + + if ( $$mergefile eq "" ) { installer::exiter::exit_program("ERROR: msm file not found: $filename !", "readmergedatabase"); } + my $completesource = $$mergefile; + + my $mergegid = $mergemodule->{'gid'}; + my $workdir = $mergemoduledir . $installer::globals::separator . $mergegid; + if ( ! -d $workdir ) { installer::systemactions::create_directory($workdir); } + + my $completedest = $workdir . $installer::globals::separator . $filename; + installer::systemactions::copy_one_file($completesource, $completedest); + if ( ! -f $completedest ) { installer::exiter::exit_program("ERROR: msm file not found: $completedest !", "readmergedatabase"); } + + # extract all tables from database + extract_all_tables_from_msidatabase($completedest, $workdir); + + # read all tables + my $onemergefile = read_all_tables_from_msidatabase($workdir); + + $allmergefiles{$mergegid} = $onemergefile; + } + + foreach my $mergefilegid ( keys %allmergefiles ) + { + my $onemergefile = $allmergefiles{$mergefilegid}; + my $filetable = $onemergefile->{'File'}; + + foreach my $linenumber ( keys %{$filetable} ) + { + # Collecting all files from merge modules in global hash + $installer::globals::mergemodulefiles{$filetable->{$linenumber}->{'File'}} = 1; + } + } + + installer::logger::include_timestamp_into_logfile("Performance Info: readmergedatabase end"); +} + +################################################################################# +# Creating several useful hashes from old database +################################################################################# + +sub create_database_hashes +{ + my ( $database ) = @_; + + # 1. Hash ( Component -> UniqueFileName ), required in File table. + # Read from File table. + + my %uniquefilename = (); + my %allupdatesequences = (); + my %allupdatecomponents = (); + my %allupdatefileorder = (); + my %allupdatecomponentorder = (); + my %revuniquefilename = (); + my %revshortfilename = (); + my %shortdirname = (); + my %componentid = (); + my %componentidkeypath = (); + my %alloldproperties = (); + my %allupdatelastsequences = (); + my %allupdatediskids = (); + + my $filetable = $database->{'File'}; + + foreach my $linenumber ( keys %{$filetable} ) + { + my $comp = $filetable->{$linenumber}->{'Component_'}; + my $uniquename = $filetable->{$linenumber}->{'File'}; + my $filename = $filetable->{$linenumber}->{'FileName'}; + my $sequence = $filetable->{$linenumber}->{'Sequence'}; + + my $shortname = ""; + if ( $filename =~ /^\s*(.*?)\|\s*(.*?)\s*$/ ) + { + $shortname = $1; + $filename = $2; + } + + # unique is the combination of $component and $filename + my $key = "$comp/$filename"; + + if ( exists($uniquefilename{$key}) ) { installer::exiter::exit_program("ERROR: Component/FileName \"$key\" is not unique in table \"File\" !", "create_database_hashes"); } + + my $value = $uniquename; + if ( $shortname ne "" ) { $value = "$uniquename;$shortname"; } + $uniquefilename{$key} = $value; # saving the unique keys and short names in hash + + # Saving reverse keys too + $revuniquefilename{$uniquename} = $key; + if ( $shortname ne "" ) { $revshortfilename{$shortname} = $key; } + + # Saving Sequences for unique names (and also components) + $allupdatesequences{$uniquename} = $sequence; + $allupdatecomponents{$uniquename} = $comp; + + # Saving unique names and components for sequences + $allupdatefileorder{$sequence} = $uniquename; + $allupdatecomponentorder{$sequence} = $comp; + } + + # 2. Hash, required in Directory table. + + my $dirtable = $database->{'Directory'}; + + foreach my $linenumber ( keys %{$dirtable} ) + { + my $dir = $dirtable->{$linenumber}->{'Directory'}; # this is a unique name + my $defaultdir = $dirtable->{$linenumber}->{'DefaultDir'}; + + my $shortname = ""; + if ( $defaultdir =~ /^\s*(.*?)\|\s*(.*?)\s*$/ ) + { + $shortname = $1; + $shortdirname{$dir} = $shortname; # collecting only the short names + } + } + + # 3. Hash, collecting info from Component table. + # ComponentID and KeyPath have to be reused. + + my $comptable = $database->{'Component'}; + + foreach my $linenumber ( keys %{$comptable} ) + { + my $comp = $comptable->{$linenumber}->{'Component'}; + my $compid = $comptable->{$linenumber}->{'ComponentId'}; + my $keypath = $comptable->{$linenumber}->{'KeyPath'}; + + $componentid{$comp} = $compid; + $componentidkeypath{$comp} = $keypath; + } + + # 4. Hash, property table, required for ProductCode and Installlocation. + + my $proptable = $database->{'Property'}; + + foreach my $linenumber ( keys %{$proptable} ) + { + my $prop = $proptable->{$linenumber}->{'Property'}; + my $value = $proptable->{$linenumber}->{'Value'}; + + $alloldproperties{$prop} = $value; + } + + # 5. Media table, getting last sequence + + my $mediatable = $database->{'Media'}; + $installer::globals::updatelastsequence = 0; + + foreach my $linenumber ( keys %{$mediatable} ) + { + my $cabname = $mediatable->{$linenumber}->{'Cabinet'}; + my $lastsequence = $mediatable->{$linenumber}->{'LastSequence'}; + my $diskid = $mediatable->{$linenumber}->{'DiskId'}; + $allupdatelastsequences{$cabname} = $lastsequence; + $allupdatediskids{$cabname} = $diskid; + + if ( $lastsequence > $installer::globals::updatelastsequence ) { $installer::globals::updatelastsequence = $lastsequence; } + } + + $installer::globals::updatesequencecounter = $installer::globals::updatelastsequence; + + return (\%uniquefilename, \%revuniquefilename, \%revshortfilename, \%allupdatesequences, \%allupdatecomponents, \%allupdatefileorder, \%allupdatecomponentorder, \%shortdirname, \%componentid, \%componentidkeypath, \%alloldproperties, \%allupdatelastsequences, \%allupdatediskids); +} + + +1;
\ No newline at end of file diff --git a/solenv/bin/modules/installer/windows/upgrade.pm b/solenv/bin/modules/installer/windows/upgrade.pm new file mode 100644 index 000000000000..5e3d5379579a --- /dev/null +++ b/solenv/bin/modules/installer/windows/upgrade.pm @@ -0,0 +1,171 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: upgrade.pm,v $ +# +# $Revision: 1.16 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::windows::upgrade; + +use installer::exiter; +use installer::files; +use installer::globals; +use installer::windows::idtglobal; + +#################################################################################### +# Creating the file Upgrade.idt dynamically +# Content: +# UpgradeCode VersionMin VersionMax Language Attributes Remove ActionProperty +#################################################################################### + +sub create_upgrade_table +{ + my ($basedir, $allvariableshashref) = @_; + + my @upgradetable = (); + + # fix for problematic OOo 1.9 versions + my $include_ooo_fix = 0; + my $ooomaxnew = ""; + if (($installer::globals::product =~ /OpenOffice/i ) && ( ! ( $installer::globals::product =~ /SDK/i )) && ( ! $installer::globals::languagepack )) + { + $include_ooo_fix = 1; + $ooomaxnew = "34.0.0"; + } + + installer::windows::idtglobal::write_idt_header(\@upgradetable, "upgrade"); + + # Setting also $installer::globals::msimajorproductversion, that is for example "3.0.0", to differ between old products for OOo 2.x and + # older products from OOo 3.x. The latter must be removed always, the removal of the first is controlled with a checkbox. + my $newline = $installer::globals::upgradecode . "\t" . "\t" . $installer::globals::msimajorproductversion . "\t" . "\t" . "0" . "\t" . "\t" . "OLDPRODUCTS" . "\n"; + push(@upgradetable, $newline); + + # Setting all products, that must be removed. + $newline = $installer::globals::upgradecode . "\t" . $installer::globals::msimajorproductversion . "\t" . $installer::globals::msiproductversion . "\t" . "\t" . "257" . "\t" . "\t" . "OLDPRODUCTSSAMEMAJOR" . "\n"; + push(@upgradetable, $newline); + + if ( ! $installer::globals::patch ) + { + # preventing downgrading + $newline = $installer::globals::upgradecode . "\t" . $installer::globals::msiproductversion . "\t" . $ooomaxnew . "\t" . "\t" . "2" . "\t" . "\t" . "NEWPRODUCTS" . "\n"; + push(@upgradetable, $newline); + + $newline = $installer::globals::upgradecode . "\t" . $installer::globals::msiproductversion . "\t" . $ooomaxnew . "\t" . "\t" . "258" . "\t" . "\t" . "SAMEPRODUCTS" . "\n"; + push(@upgradetable, $newline); + + if ( $include_ooo_fix ) + { + $newline = $installer::globals::upgradecode . "\t" . "35.0.0" . "\t" . "36.0.0" . "\t" . "\t" . "1" . "\t" . "\t" . "OLDPRODUCTS2" . "\n"; + push(@upgradetable, $newline); + } + + # if (( $allvariableshashref->{'PATCHUPGRADECODE'} ) && ( ! $installer::globals::languagepack )) + # { + # $newline = $allvariableshashref->{'PATCHUPGRADECODE'} . "\t" . "\t" . $installer::globals::msiproductversion . "\t" . "\t" . "1" . "\t" . "\t" . "OLDPRODUCTSPATCH" . "\n"; + # push(@upgradetable, $newline); + # + # $newline = $allvariableshashref->{'PATCHUPGRADECODE'} . "\t" . $installer::globals::msiproductversion . "\t" . "\t" . "\t" . "2" . "\t" . "\t" . "NEWPRODUCTSPATCH" . "\n"; + # push(@upgradetable, $newline); + # + # $newline = $allvariableshashref->{'PATCHUPGRADECODE'} . "\t" . $installer::globals::msiproductversion . "\t" . "\t" . "\t" . "258" . "\t" . "\t" . "SAMEPRODUCTSPATCH" . "\n"; + # push(@upgradetable, $newline); + # } + + # also searching for the beta + + if (( $allvariableshashref->{'BETAUPGRADECODE'} ) && ( ! $installer::globals::languagepack )) + { + $newline = $allvariableshashref->{'BETAUPGRADECODE'} . "\t" . "1.0" . "\t" . "\t" . "\t" . "1" . "\t" . "\t" . "BETAPRODUCTS" . "\n"; + push(@upgradetable, $newline); + } + + # also searching for the stub + + if (( $allvariableshashref->{'STUBUPGRADECODE'} ) && ( ! $installer::globals::languagepack )) + { + $newline = $allvariableshashref->{'STUBUPGRADECODE'} . "\t" . "1.0" . "\t" . "\t" . "\t" . "1" . "\t" . "\t" . "STUBPRODUCTS" . "\n"; + push(@upgradetable, $newline); + } + + # searching for all older patches and languagepacks (defined in a extra file) + + if (( $allvariableshashref->{'REMOVE_UPGRADE_CODE_FILE'} ) && ( ! $installer::globals::languagepack )) + { + my $filename = $allvariableshashref->{'REMOVE_UPGRADE_CODE_FILE'}; + my $langpackcodefilename = $installer::globals::idttemplatepath . $installer::globals::separator . $filename; + if ( ! -f $langpackcodefilename ) { installer::exiter::exit_program("ERROR: Could not find file \"$langpackcodefilename\".", "create_upgrade_table"); } + + my $filecontent = installer::files::read_file($langpackcodefilename); + my $newlines = analyze_file_for_upgrade_table($filecontent); + + for ( my $i = 0; $i <= $#{$newlines}; $i++ ) { push(@upgradetable, ${$newlines}[$i]); } + } + } + + # No upgrade for Beta versions! + + if (( $allvariableshashref->{'PRODUCTEXTENSION'} eq "Beta" ) && ( ! $installer::globals::patch ) && ( ! $installer::globals::languagepack )) + { + @upgradetable = (); + installer::windows::idtglobal::write_idt_header(\@upgradetable, "upgrade"); + my $infoline = "Beta product -> empty Upgrade table\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + # Saving the file + + my $upgradetablename = $basedir . $installer::globals::separator . "Upgrade.idt"; + installer::files::save_file($upgradetablename ,\@upgradetable); + my $infoline = "Created idt file: $upgradetablename\n"; + push(@installer::globals::logfileinfo, $infoline); +} + +############################################################## +# Reading the file with UpgradeCodes of old products, +# that can be removed, if the user wants to remove them. +############################################################## + +sub analyze_file_for_upgrade_table +{ + my ($filecontent) = @_; + + my @allnewlines = (); + + for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) + { + my $line = ${$filecontent}[$i]; + if ( $line =~ /^\s*$/ ) { next; } # empty lines can be ignored + if ( $line =~ /^\s*\#/ ) { next; } # comment lines starting with a hash + + if ( $line =~ /^(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)$/ ) { push(@allnewlines, $line); } + else { installer::exiter::exit_program("ERROR: Wrong syntax in file for upgrade table", "analyze_file_for_upgrade_table"); } + } + + return \@allnewlines; +} + +1; diff --git a/solenv/bin/modules/installer/worker.pm b/solenv/bin/modules/installer/worker.pm new file mode 100644 index 000000000000..5d9147409385 --- /dev/null +++ b/solenv/bin/modules/installer/worker.pm @@ -0,0 +1,3316 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: worker.pm,v $ +# +# $Revision: 1.65.56.1 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::worker; + +use Cwd; +use File::Copy; +use File::stat; +use File::Temp qw(tmpnam); +use installer::control; +use installer::converter; +use installer::existence; +use installer::exiter; +use installer::files; +use installer::globals; +use installer::logger; +use installer::mail; +use installer::pathanalyzer; +use installer::scpzipfiles; +use installer::scriptitems; +use installer::sorter; +use installer::systemactions; +use installer::windows::language; + +##################################################################### +# Unpacking all files ending with tar.gz in a specified directory +##################################################################### + +sub unpack_all_targzfiles_in_directory +{ + my ( $directory ) = @_; + + installer::logger::include_header_into_logfile("Unpacking tar.gz files:"); + + installer::logger::print_message( "... unpacking tar.gz files ... \n" ); + + my $localdirectory = $directory . $installer::globals::separator . "packages"; + my $alltargzfiles = installer::systemactions::find_file_with_file_extension("tar.gz", $localdirectory); + + for ( my $i = 0; $i <= $#{$alltargzfiles}; $i++ ) + { + my $onefile = $localdirectory . $installer::globals::separator . ${$alltargzfiles}[$i]; + + my $systemcall = "cd $localdirectory; cat ${$alltargzfiles}[$i] \| gunzip \| tar -xf -"; + $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } +} + +######################################### +# Copying installation sets to ship +######################################### + +sub copy_install_sets_to_ship +{ + my ( $destdir, $shipinstalldir ) = @_; + + installer::logger::include_header_into_logfile("Copying installation set to ship:"); + + my $dirname = $destdir; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$dirname); + $dirname = $dirname . "_inprogress"; + my $localshipinstalldir = $shipinstalldir . $installer::globals::separator . $dirname; + if ( ! -d $localshipinstalldir ) { installer::systemactions::create_directory_structure($localshipinstalldir); } + + # copy installation set to /ship ($localshipinstalldir) + installer::logger::print_message( "... copy installation set from " . $destdir . " to " . $localshipinstalldir . "\n" ); + installer::systemactions::copy_complete_directory($destdir, $localshipinstalldir); + + if (( ! $installer::globals::iswindowsbuild ) && ( $installer::globals::addjavainstaller )) + { + # Setting Unix rights for Java starter ("setup") + my $localcall = "chmod 775 $localshipinstalldir/setup \>\/dev\/null 2\>\&1"; + system($localcall); + } + + # unpacking the tar.gz file for Solaris + if ( $installer::globals::issolarisbuild ) { unpack_all_targzfiles_in_directory($localshipinstalldir); } + + $localshipinstalldir = installer::systemactions::rename_string_in_directory($localshipinstalldir, "_inprogress", ""); + + return $localshipinstalldir; +} + +######################################### +# Copying installation sets to ship +######################################### + +sub link_install_sets_to_ship +{ + my ( $destdir, $shipinstalldir ) = @_; + + installer::logger::include_header_into_logfile("Linking installation set to ship:"); + + my $infoline = "... destination directory: $shipinstalldir ...\n"; + installer::logger::print_message( $infoline ); + push( @installer::globals::logfileinfo, $infoline); + + if ( ! -d $shipinstalldir) + { + $infoline = "Creating directory: $shipinstalldir\n"; + push( @installer::globals::logfileinfo, $infoline); + installer::systemactions::create_directory_structure($shipinstalldir); + $infoline = "Created directory: $shipinstalldir\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + my $dirname = $destdir; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$dirname); + + my $localshipinstalldir = $shipinstalldir . $installer::globals::separator . $dirname; + + # link installation set to /ship ($localshipinstalldir) + installer::logger::print_message( "... linking installation set from " . $destdir . " to " . $localshipinstalldir . "\n" ); + + my $systemcall = "ln -s $destdir $localshipinstalldir"; + + $returnvalue = system($systemcall); + + $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not create link \"$localshipinstalldir\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Created link \"$localshipinstalldir\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + return $localshipinstalldir; +} + +######################################### +# Create checksum file +######################################### + +sub make_checksum_file +{ + my ( $filesref, $includepatharrayref ) = @_; + + my @checksum = (); + + my $checksumfileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$installer::globals::checksumfile, $includepatharrayref, 1); + if ( $$checksumfileref eq "" ) { installer::exiter::exit_program("ERROR: Could not find file $installer::globals::checksumfile !", "make_checksum_file"); } + +# # very slow on Windows +# for ( my $i = 0; $i <= $#{$filesref}; $i++ ) +# { +# my $onefile = ${$filesref}[$i]; +# my $systemcall = "$$checksumfileref $onefile->{'sourcepath'} |"; +# open (CHECK, "$systemcall"); +# my $localchecksum = <CHECK>; +# close (CHECK); +# push(@checksum, $localchecksum); +# } + + my $systemcall = "$$checksumfileref"; + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + $systemcall = $systemcall . " " . $onefile->{'sourcepath'}; # very very long systemcall + + if ((( $i > 0 ) && ( $i%100 == 0 )) || ( $i == $#{$filesref} )) # limiting to 100 files + { + $systemcall = $systemcall . " \|"; + + my @localchecksum = (); + open (CHECK, "$systemcall"); + @localchecksum = <CHECK>; + close (CHECK); + + for ( my $j = 0; $j <= $#localchecksum; $j++ ) { push(@checksum, $localchecksum[$j]); } + + $systemcall = "$$checksumfileref"; # reset the system call + } + } + + return \@checksum; +} + +######################################### +# Saving the checksum file +######################################### + +sub save_checksum_file +{ + my ($current_install_number, $installchecksumdir, $checksumfile) = @_; + + my $numberedchecksumfilename = $installer::globals::checksumfilename; + $numberedchecksumfilename =~ s/\./_$current_install_number\./; # checksum.txt -> checksum_01.txt + installer::files::save_file($installchecksumdir . $installer::globals::separator . $numberedchecksumfilename, $checksumfile); +} + +################################################# +# Writing some global information into +# the list of files without flag PATCH +################################################# + +sub write_nopatchlist_header +{ + my ( $content ) = @_; + + my @header = (); + my $infoline = "This is a list of files, that are defined in scp-projects without\n"; + push(@header, $infoline); + $infoline = "flag \"PATCH\". Important: This does not mean in any case, that \n"; + push(@header, $infoline); + $infoline = "this files are included into or excluded from a patch. \n\n"; + push(@header, $infoline); + $infoline = "Exception Linux: A patch rpm is a complete rpm. This means that all \n"; + push(@header, $infoline); + $infoline = "files are included into a patch rpm, if only one file of the rpm has the \n"; + push(@header, $infoline); + $infoline = "style \"PATCH\". \n\n"; + push(@header, $infoline); + + for ( my $i = 0; $i <= $#header; $i++ ) { push(@{$content},$header[$i]); } +} + +################################################# +# Creating the content of the list of files +# without flag PATCH. +# All files are saved in +# @{$installer::globals::nopatchfilecollector} +################################################# + +sub create_nopatchlist +{ + my @content =(); + + write_nopatchlist_header(\@content); + + for ( my $i = 0; $i <= $#{$installer::globals::nopatchfilecollector}; $i++ ) + { + my $onefile = ${$installer::globals::nopatchfilecollector}[$i]; + my $oneline = $onefile->{'destination'}; + if ( $onefile->{'zipfilename'} ) { $oneline = $oneline . " (" . $onefile->{'zipfilename'} . ")"; } + $oneline = $oneline . "\n"; + push(@content, $oneline); + } + + return \@content; +} + +######################################### +# Saving the patchlist file +######################################### + +sub save_patchlist_file +{ + my ($installlogdir, $patchlistfilename) = @_; + + my $installpatchlistdir = installer::systemactions::create_directory_next_to_directory($installlogdir, "patchlist"); + $patchlistfilename =~ s/log\_/patchfiles\_/; + $patchlistfilename =~ s/\.log/\.txt/; + installer::files::save_file($installpatchlistdir . $installer::globals::separator . $patchlistfilename, \@installer::globals::patchfilecollector); + installer::logger::print_message( "... creating patchlist file $patchlistfilename \n" ); + + if (( $installer::globals::patch ) && ( ! $installer::globals::creating_windows_installer_patch )) # only for non-Windows patches + { + $patchlistfilename =~ s/patchfiles\_/nopatchfiles\_/; + my $nopatchlist = create_nopatchlist(); + installer::files::save_file($installpatchlistdir . $installer::globals::separator . $patchlistfilename, $nopatchlist); + installer::logger::print_message( "... creating patch exclusion file $patchlistfilename \n" ); + } + +} + +############################################################### +# Removing all directories of a special language +# in the directory $basedir +############################################################### + +sub remove_old_installation_sets +{ + my ($basedir) = @_; + + installer::logger::print_message( "... removing old installation directories ...\n" ); + + my $removedir = $basedir; + + if ( -d $removedir ) { installer::systemactions::remove_complete_directory($removedir, 1); } + + # looking for non successful old installation sets + + $removedir = $basedir . "_witherror"; + if ( -d $removedir ) { installer::systemactions::remove_complete_directory($removedir, 1); } + + $removedir = $basedir . "_inprogress"; + if ( -d $removedir ) { installer::systemactions::remove_complete_directory($removedir, 1); } + + # finally the $basedir can be created empty + + if ( $installer::globals::localinstalldirset ) { installer::systemactions::create_directory_structure($basedir); } + + installer::systemactions::create_directory($basedir); +} + +############################################################### +# Removing all non successful installation sets on ship +############################################################### + +sub remove_old_ship_installation_sets +{ + my ($fulldir, $counter) = @_; + + installer::logger::print_message( "... removing old installation directories ...\n" ); + + my $basedir = $fulldir; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$basedir); + + # collecting all directories next to the new installation directory + my $alldirs = installer::systemactions::get_all_directories($basedir); + + if ( $fulldir =~ /^\s*(.*?inprogress\-)(\d+)(.*?)\s*$/ ) + { + my $pre_inprogress = $1; # $pre still contains "inprogress" + my $number = $2; + my $post = $3; + my $pre_witherror = $pre_inprogress; + $pre_witherror =~ s/inprogress/witherror/; + + for ( my $i = 0; $i <= $#{$alldirs}; $i++ ) + { + if ( ${$alldirs}[$i] eq $fulldir ) { next; } # do not delete the newly created directory + + if ( ${$alldirs}[$i] =~ /^\s*\Q$pre_inprogress\E\d+\Q$post\E\s*$/ ) # removing old "inprogress" directories + { + installer::systemactions::remove_complete_directory(${$alldirs}[$i], 1); + } + + if ( ${$alldirs}[$i] =~ /^\s*\Q$pre_witherror\E\d+\Q$post\E\s*$/ ) # removing old "witherror" directories + { + installer::systemactions::remove_complete_directory(${$alldirs}[$i], 1); + } + } + } +} + +############################################################### +# Creating the installation directory structure +############################################################### + +sub create_installation_directory +{ + my ($shipinstalldir, $languagestringref, $current_install_number_ref) = @_; + + my $installdir = ""; + + my $languageref = $languagestringref; + + if ( $installer::globals::updatepack ) + { + $installdir = $shipinstalldir; + installer::systemactions::create_directory_structure($installdir); + $$current_install_number_ref = installer::systemactions::determine_maximum_number($installdir, $languageref); + $installdir = installer::systemactions::rename_string_in_directory($installdir, "number", $$current_install_number_ref); + remove_old_ship_installation_sets($installdir); + } + else + { + $installdir = installer::systemactions::create_directories("install", $languageref); + if ( $installer::globals::localinstalldir ) + { + $installdir = $installer::globals::localinstalldir; + $installer::globals::localinstalldirset = 1; + } + installer::logger::print_message( "... creating installation set in $installdir ...\n" ); + remove_old_installation_sets($installdir); + my $inprogressinstalldir = $installdir . "_inprogress"; + installer::systemactions::rename_directory($installdir, $inprogressinstalldir); + $installdir = $inprogressinstalldir; + } + + $installer::globals::saveinstalldir = $installdir; # saving directory globally, in case of exiting + + return $installdir; +} + +############################################################### +# Analyzing and creating the log file +############################################################### + +sub analyze_and_save_logfile +{ + my ($loggingdir, $installdir, $installlogdir, $allsettingsarrayref, $languagestringref, $current_install_number) = @_; + + my $is_success = 1; + my $finalinstalldir = ""; + + installer::logger::print_message( "... checking log file " . $loggingdir . $installer::globals::logfilename . "\n" ); + + my $contains_error = installer::control::check_logfile(\@installer::globals::logfileinfo); + + # Dependent from the success, the installation directory can be renamed and mails can be send. + + if ( $contains_error ) + { + my $errordir = installer::systemactions::rename_string_in_directory($installdir, "_inprogress", "_witherror"); + if ( $installer::globals::updatepack ) { installer::mail::send_fail_mail($allsettingsarrayref, $languagestringref, $errordir); } + # Error output to STDERR + for ( my $j = 0; $j <= $#installer::globals::errorlogfileinfo; $j++ ) + { + my $line = $installer::globals::errorlogfileinfo[$j]; + $line =~ s/\s*$//g; + installer::logger::print_error( $line ); + } + $is_success = 0; + + $finalinstalldir = $errordir; + } + else + { + my $destdir = ""; + + if ( $installer::globals::updatepack ) + { + if ( $installdir =~ /_download_inprogress/ ) { $destdir = installer::systemactions::rename_string_in_directory($installdir, "_download_inprogress", "_download"); } + elsif ( $installdir =~ /_jds_inprogress/ ) { $destdir = installer::systemactions::rename_string_in_directory($installdir, "_jds_inprogress", "_jds"); } + elsif ( $installdir =~ /_msp_inprogress/ ) { $destdir = installer::systemactions::rename_string_in_directory($installdir, "_msp_inprogress", "_msp"); } + else + { + if ( $installdir =~ /_packed/ ) { $destdir = installer::systemactions::rename_string_in_directory($installdir, "_inprogress", ""); } + else { $destdir = installer::systemactions::rename_string_in_directory($installdir, "_inprogress", "_packed"); } + } + installer::mail::send_success_mail($allsettingsarrayref, $languagestringref, $destdir); + } + else + { + $destdir = installer::systemactions::rename_string_in_directory($installdir, "_inprogress", ""); + } + + $finalinstalldir = $destdir; + } + + # Saving the logfile in the log file directory and additionally in a log directory in the install directory + + my $numberedlogfilename = $installer::globals::logfilename; + if ( $installer::globals::updatepack ) { $numberedlogfilename =~ s /log_/log_$current_install_number\_/; } + installer::logger::print_message( "... creating log file $numberedlogfilename \n" ); + installer::files::save_file($loggingdir . $numberedlogfilename, \@installer::globals::logfileinfo); + installer::files::save_file($installlogdir . $installer::globals::separator . $numberedlogfilename, \@installer::globals::logfileinfo); + + # Saving the checksumfile in a checksum directory in the install directory + # installer::worker::save_checksum_file($current_install_number, $installchecksumdir, $checksumfile); + + # Saving the list of patchfiles in a patchlist directory in the install directory + if (( $installer::globals::patch ) || ( $installer::globals::creating_windows_installer_patch )) { installer::worker::save_patchlist_file($installlogdir, $numberedlogfilename); } + + if ( $installer::globals::creating_windows_installer_patch ) { $installer::globals::creating_windows_installer_patch = 0; } + + return ($is_success, $finalinstalldir); +} + +############################################################### +# Analyzing and creating the log file +############################################################### + +sub save_logfile_after_linking +{ + my ($loggingdir, $installlogdir, $current_install_number) = @_; + + # Saving the logfile in the log file directory and additionally in a log directory in the install directory + my $numberedlogfilename = $installer::globals::logfilename; + if ( $installer::globals::updatepack ) { $numberedlogfilename =~ s /log_/log_$current_install_number\_/; } + installer::logger::print_message( "... creating log file $numberedlogfilename \n" ); + installer::files::save_file($loggingdir . $numberedlogfilename, \@installer::globals::logfileinfo); + installer::files::save_file($installlogdir . $installer::globals::separator . $numberedlogfilename, \@installer::globals::logfileinfo); +} + +############################################################### +# Removing all directories that are saved in the +# global directory @installer::globals::removedirs +############################################################### + +sub clean_output_tree +{ + installer::logger::print_message( "... cleaning the output tree ...\n" ); + + for ( my $i = 0; $i <= $#installer::globals::removedirs; $i++ ) + { + if ( -d $installer::globals::removedirs[$i] ) + { + installer::logger::print_message( "... removing directory $installer::globals::removedirs[$i] ...\n" ); + installer::systemactions::remove_complete_directory($installer::globals::removedirs[$i], 1); + } + } + + # Last try to remove the ship test directory + + if ( $installer::globals::shiptestdirectory ) + { + if ( -d $installer::globals::shiptestdirectory ) + { + my $infoline = "Last try to remove $installer::globals::shiptestdirectory . \n"; + push(@installer::globals::logfileinfo, $infoline); + my $systemcall = "rmdir $installer::globals::shiptestdirectory"; + my $returnvalue = system($systemcall); + } + } +} + +############################################################### +# Removing all directories that are saved in the +# global directory @installer::globals::jdsremovedirs +############################################################### + +sub clean_jds_temp_dirs +{ + installer::logger::print_message( "... cleaning jds directories ...\n" ); + + for ( my $i = 0; $i <= $#installer::globals::jdsremovedirs; $i++ ) + { + if ( -d $installer::globals::jdsremovedirs[$i] ) + { + installer::logger::print_message( "... removing directory $installer::globals::jdsremovedirs[$i] ...\n" ); + installer::systemactions::remove_complete_directory($installer::globals::jdsremovedirs[$i], 1); + } + } +} + +########################################################### +# Copying a reference array +########################################################### + +sub copy_array_from_references +{ + my ( $arrayref ) = @_; + + my @newarray = (); + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + push(@newarray, ${$arrayref}[$i]); + } + + return \@newarray; +} + +########################################################### +# Copying a reference hash +########################################################### + +sub copy_hash_from_references +{ + my ($hashref) = @_; + + my %newhash = (); + my $key; + + foreach $key (keys %{$hashref}) + { + $newhash{$key} = $hashref->{$key}; + } + + return \%newhash; +} + +########################################################### +# Setting one language in the language independent +# array of include pathes with $(LANG) +########################################################### + +sub get_language_specific_include_pathes +{ + my ( $patharrayref, $onelanguage ) = @_; + + my @patharray = (); + + for ( my $i = 0; $i <= $#{$patharrayref}; $i++ ) + { + my $line = ${$patharrayref}[$i]; + $line =~ s/\$\(LANG\)/$onelanguage/g; + push(@patharray ,$line); + } + + return \@patharray; +} + +############################################################## +# Returning the first item with a defined flag +############################################################## + +sub return_first_item_with_special_flag +{ + my ($itemsref, $flag) = @_; + + my $firstitem = ""; + + for ( my $i = 0; $i <= $#{$itemsref}; $i++ ) + { + my $oneitem = ${$itemsref}[$i]; + my $styles = ""; + if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'} }; + + if ( $styles =~ /\b$flag\b/ ) + { + $firstitem = $oneitem; + last; + } + } + + return $firstitem; +} + +############################################################## +# Collecting all items with a defined flag +############################################################## + +sub collect_all_items_with_special_flag +{ + my ($itemsref, $flag) = @_; + + my @allitems = (); + + for ( my $i = 0; $i <= $#{$itemsref}; $i++ ) + { + my $oneitem = ${$itemsref}[$i]; + my $styles = ""; + if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'} }; + + if ( $styles =~ /\b$flag\b/ ) + { + push( @allitems, $oneitem ); + } + } + + return \@allitems; +} + +############################################################## +# Collecting all files without patch flag in +# $installer::globals::nopatchfilecollector +############################################################## + +sub collect_all_files_without_patch_flag +{ + my ($filesref) = @_; + + my $newfiles = collect_all_items_without_special_flag($filesref, "PATCH"); + + for ( my $i = 0; $i <= $#{$newfiles}; $i++ ) { push(@{$installer::globals::nopatchfilecollector}, ${$newfiles}[$i]); } +} + +############################################################## +# Collecting all items without a defined flag +############################################################## + +sub collect_all_items_without_special_flag +{ + my ($itemsref, $flag) = @_; + + my @allitems = (); + + for ( my $i = 0; $i <= $#{$itemsref}; $i++ ) + { + my $oneitem = ${$itemsref}[$i]; + my $styles = ""; + if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'} }; + + if ( !( $styles =~ /\b$flag\b/ )) + { + push( @allitems, $oneitem ); + } + } + + return \@allitems; +} + +############################################################## +# Removing all items with a defined flag from collector +############################################################## + +sub remove_all_items_with_special_flag +{ + my ($itemsref, $flag) = @_; + + my @allitems = (); + + for ( my $i = 0; $i <= $#{$itemsref}; $i++ ) + { + my $oneitem = ${$itemsref}[$i]; + my $styles = ""; + if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'} }; + if ( $styles =~ /\b$flag\b/ ) + { + my $infoline = "Attention: Removing from collector: $oneitem->{'Name'} !\n"; + push( @installer::globals::logfileinfo, $infoline); + if ( $flag eq "BINARYTABLE_ONLY" ) { push(@installer::globals::binarytableonlyfiles, $oneitem); } + next; + } + push( @allitems, $oneitem ); + } + + return \@allitems; +} + +########################################################### +# Mechanism for simple installation without packing +########################################################### + +sub install_simple ($$$$$$) +{ + my ($packagename, $languagestring, $directoriesarray, $filesarray, $linksarray, $unixlinksarray) = @_; + + # locate GNU cp on the system + my $gnucp = 'cp'; + if ( $ENV{'GNUCOPY'} ) { $gnucp = $ENV{'GNUCOPY'}; } + my $copyopts = '-af'; + $copyopts = '-PpRf' unless ( $ENV{'GNUCOPY'} ); # if not gnucopy, assume POSIX copy + + installer::logger::print_message( "... installing module $packagename ...\n" ); + + my $destdir = $installer::globals::destdir; + my @lines = (); + + installer::logger::print_message( "DestDir: $destdir \n" ); + installer::logger::print_message( "Rootpath: $installer::globals::rootpath \n" ); + + `mkdir -p $destdir` if $destdir ne ""; + `mkdir -p $destdir$installer::globals::rootpath`; + + # Create Directories + for ( my $i = 0; $i <= $#{$directoriesarray}; $i++ ) + { + my $onedir = ${$directoriesarray}[$i]; + my $dir = ""; + + if ( $onedir->{'Dir'} ) { $dir = $onedir->{'Dir'}; } + + if ((!($dir =~ /\bPREDEFINED_/ )) || ( $dir =~ /\bPREDEFINED_PROGDIR\b/ )) + { + # printf "mkdir $destdir$onedir->{'HostName'}\n"; + mkdir $destdir . $onedir->{'HostName'}; + push @lines, "%dir " . $onedir->{'HostName'} . "\n"; + } + } + + for ( my $i = 0; $i <= $#{$filesarray}; $i++ ) + { + my $onefile = ${$filesarray}[$i]; + my $unixrights = $onefile->{'UnixRights'}; + my $destination = $onefile->{'destination'}; + my $sourcepath = $onefile->{'sourcepath'}; + + # This is necessary to install SDK that includes files with $ in its name + # Otherwise, the following shell commands does not work and the file list + # is not correct + $destination =~ s/\$\$/\$/; + $sourcepath =~ s/\$\$/\$/; + + push @lines, "$destination\n"; + # printf "cp $sourcepath $destdir$destination\n"; + copy ("$sourcepath", "$destdir$destination") || die "Can't copy file: $sourcepath -> $destdir$destination $!"; + my $sourcestat = stat($sourcepath); + utime ($sourcestat->atime, $sourcestat->mtime, "$destdir$destination"); + chmod (oct($unixrights), "$destdir$destination") || die "Can't change permissions: $!"; + push @lines, "$destination\n"; + } + + for ( my $i = 0; $i <= $#{$linksarray}; $i++ ) + { + my $onelink = ${$linksarray}[$i]; + my $destination = $onelink->{'destination'}; + my $destinationfile = $onelink->{'destinationfile'}; + + # print "link $destinationfile -> $destdir$destination\n"; + symlink ("$destinationfile", "$destdir$destination") || die "Can't create symlink: $!"; + push @lines, "$destination\n"; + } + + for ( my $i = 0; $i <= $#{$unixlinksarray}; $i++ ) + { + my $onelink = ${$unixlinksarray}[$i]; + my $target = $onelink->{'Target'}; + my $destination = $onelink->{'destination'}; + + # print "Unix link $target -> $destdir$destination\n"; + `ln -sf '$target' '$destdir$destination'`; + push @lines, "$destination\n"; + } + + if ( $destdir ne "" ) + { + my $filelist; + my $fname = $installer::globals::destdir . "/$packagename"; + if ($installer::globals::languagepack) { $fname .= ".$languagestring"; } + open ($filelist, ">$fname") || die "Can't open $fname: $!"; + print $filelist @lines; + close ($filelist); + } + +} + +########################################################### +# Adding shellnew files into files collector for +# user installation +########################################################### + +sub add_shellnewfile_into_filesarray +{ + my ($filesref, $onefile, $inffile) = @_; + + my %shellnewfile = (); + my $shellnewfileref = \%shellnewfile; + + installer::converter::copy_item_object($inffile, $shellnewfileref); + + $shellnewfileref->{'Name'} = $onefile->{'Name'}; + $shellnewfileref->{'sourcepath'} = $onefile->{'sourcepath'}; + $shellnewfileref->{'gid'} = $onefile->{'gid'} . "_Userinstall"; + + # the destination has to be adapted + my $destination = $inffile->{'destination'}; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$destination); + $destination = $destination . $onefile->{'Name'}; + $shellnewfileref->{'destination'} = $destination; + + # add language specific inffile into filesarray + push(@{$filesref}, $shellnewfileref); +} + +########################################################### +# Replacing one placehoder in template file +########################################################### + +sub replace_in_template_file +{ + my ($templatefile, $placeholder, $newstring) = @_; + + for ( my $i = 0; $i <= $#{$templatefile}; $i++ ) + { + ${$templatefile}[$i] =~ s/\Q$placeholder\E/$newstring/g; + } +} + +########################################################### +# Replacing one placehoder with an array in template file +########################################################### + +sub replace_array_in_template_file +{ + my ($templatefile, $placeholder, $arrayref) = @_; + + for ( my $i = 0; $i <= $#{$templatefile}; $i++ ) + { + if ( ${$templatefile}[$i] =~ /\Q$placeholder\E/ ) + { + my @return = splice(@{$templatefile}, $i, 1, @{$arrayref}); + } + } +} + +########################################################### +# Collecting all modules from registry items +########################################################### + +sub collect_all_modules +{ + my ($registryitemsref) = @_; + + my @allmodules = (); + + for ( my $i = 0; $i <= $#{$registryitemsref}; $i++ ) + { + $registryitem = ${$registryitemsref}[$i]; + my $module = $registryitem->{'ModuleID'}; + + if ( ! installer::existence::exists_in_array($module, \@allmodules) ) + { + push(@allmodules, $module); + } + } + + return \@allmodules; +} + +########################################################### +# Changing the content of the inf file +########################################################### + +sub write_content_into_inf_file +{ + my ($templatefile, $filesref, $registryitemsref, $folderref, $folderitemsref, $modulesref, $onelanguage, $inffile, $firstlanguage, $allvariableshashref) = @_; + + # First part: Shellnew files + # SHELLNEWFILESPLACEHOLDER + + my $rootmodule = 0; + # inf files can be assigned to "gid_Module_Root_Files_2" + if ( $inffile->{'modules'} =~ /Module_Root/i ) { $rootmodule = 1; } + + if ( $rootmodule ) + { + my $shellnewstring = ""; + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + my $directory = $onefile->{'Dir'}; + + if ( $directory =~ /\bPREDEFINED_OSSHELLNEWDIR\b/ ) + { + $shellnewstring = $shellnewstring . $onefile->{'Name'} . "\n"; + if (( $firstlanguage ) && ( ! $installer::globals::shellnewfilesadded )) { add_shellnewfile_into_filesarray($filesref, $onefile, $inffile); } + } + } + + $shellnewstring =~ s/\s*$//; + replace_in_template_file($templatefile, "SHELLNEWFILESPLACEHOLDER", $shellnewstring); + + $installer::globals::shellnewfilesadded = 1; + } + + # Second part: Start menu entries + + # The OfficeMenuFolder is defined as: $productname . " " . $productversion; + + my $productname = $allvariableshashref->{'PRODUCTNAME'}; + my $productversion = $allvariableshashref->{'PRODUCTVERSION'}; + my $productkey = $productname . " " . $productversion; + + replace_in_template_file($templatefile, "OFFICEFOLDERPLACEHOLDER", $productkey); + + # Setting name target and infotip for all applications + + for ( my $i = 0; $i <= $#{$folderitemsref}; $i++ ) + { + my $folderitem = ${$folderitemsref}[$i]; + + my $styles = ""; + if ( $folderitem->{'Styles'} ) { $styles = $folderitem->{'Styles'}; } + if ( $styles =~ /\bNON_ADVERTISED\b/ ) { next; } # no entry for non-advertised shortcuts + + if (( ! $folderitem->{'ismultilingual'} ) || (( $folderitem->{'ismultilingual'} ) && ( $folderitem->{'specificlanguage'} eq $onelanguage ))) + { + my $gid = $folderitem->{'gid'}; + my $app = $gid; + $app =~ s/gid_Folderitem_//; + $app = uc($app); + + my $name = $folderitem->{'Name'}; + my $placeholder = "PLACEHOLDER_FOLDERITEM_NAME_" . $app; + replace_in_template_file($templatefile, $placeholder, $name); + + my $tooltip = $folderitem->{'Tooltip'}; + $placeholder = "PLACEHOLDER_FOLDERITEM_TOOLTIP_" . $app; + replace_in_template_file($templatefile, $placeholder, $tooltip); + + my $executablegid = $folderitem->{'FileID'}; + my $exefile = installer::existence::get_specified_file($filesref, $executablegid); + my $exefilename = $exefile->{'Name'}; + $placeholder = "PLACEHOLDER_FOLDERITEM_TARGET_" . $app; + replace_in_template_file($templatefile, $placeholder, $exefilename); + } + } + + # Third part: Windows registry entries + + # collecting all modules + + my $allmodules = collect_all_modules($registryitemsref); + + my @registryitems = (); + my $allsectionsstring = ""; + + for ( my $j = 0; $j <= $#{$allmodules}; $j++ ) + { + my $moduleid = ${$allmodules}[$j]; + + my $inffilemodule = $inffile->{'modules'}; + # inf files can be assigned to "gid_Module_Root_Files_2", but RegistryItems to "gid_Module_Root" + if ( $inffilemodule =~ /Module_Root/i ) { $inffilemodule = $installer::globals::rootmodulegid; } + + if ( ! ( $moduleid eq $inffilemodule )) { next; } + + my $shortmodulename = $moduleid; + $shortmodulename =~ s/gid_Module_//; + my $sectionname = "InstRegKeys." . $shortmodulename; + $allsectionsstring = $allsectionsstring . $sectionname . ","; + my $sectionheader = "\[" . $sectionname . "\]" . "\n"; + push(@registryitems, $sectionheader); + + for ( my $i = 0; $i <= $#{$registryitemsref}; $i++ ) + { + my $registryitem = ${$registryitemsref}[$i]; + + if ( ! ( $registryitem->{'ModuleID'} eq $moduleid )) { next; } + + if (( ! $registryitem->{'ismultilingual'} ) || (( $registryitem->{'ismultilingual'} ) && ( $registryitem->{'specificlanguage'} eq $onelanguage ))) + { + # Syntax: HKCR,".bau",,,"soffice.StarConfigFile.6" + + my $regroot = ""; + my $parentid = ""; + if ( $registryitem->{'ParentID'} ) { $parentid = $registryitem->{'ParentID'}; } + if ( $parentid eq "PREDEFINED_HKEY_CLASSES_ROOT" ) { $regroot = "HKCR"; } + if ( $parentid eq "PREDEFINED_HKEY_LOCAL_MACHINE" ) { $regroot = "HKCU"; } + + my $subkey = ""; + if ( $registryitem->{'Subkey'} ) { $subkey = $registryitem->{'Subkey'}; } + if ( $subkey ne "" ) { $subkey = "\"" . $subkey . "\""; } + + my $valueentryname = ""; + if ( $registryitem->{'Name'} ) { $valueentryname = $registryitem->{'Name'}; } + if ( $valueentryname ne "" ) { $valueentryname = "\"" . $valueentryname . "\""; } + + my $flag = ""; + + my $value = ""; + if ( $registryitem->{'Value'} ) { $value = $registryitem->{'Value'}; } + if ( $value =~ /\<progpath\>/ ) { $value =~ s/\\\"/\"\"/g; } # Quoting for INF is done by double "" + $value =~ s/\\\"/\"/g; # no more masquerading of '"' + $value =~ s/\<progpath\>/\%OFFICEINSTALLLOCATION\%/g; + # $value =~ s/\%OFFICEINSTALLLOCATION\%\\/\%OFFICEINSTALLLOCATION\%/g; # removing "\" after "%OFFICEINSTALLLOCATION%" + if ( $value ne "" ) { $value = "\"" . $value . "\""; } + + my $oneline = $regroot . "," . $subkey . "," . $valueentryname . "," . $flag . "," . $value . "\n"; + + push(@registryitems, $oneline); + } + } + + push(@registryitems, "\n"); # empty line after each section + } + + # replacing the $allsectionsstring + $allsectionsstring =~ s/\,\s*$//; + replace_in_template_file($templatefile, "ALLREGISTRYSECTIONSPLACEHOLDER", $allsectionsstring); + + # replacing the placeholder for all registry keys + replace_array_in_template_file($templatefile, "REGISTRYKEYSPLACEHOLDER", \@registryitems); + +} + +########################################################### +# Creating inf files for local user system integration +########################################################### + +sub create_inf_file +{ + my ($filesref, $registryitemsref, $folderref, $folderitemsref, $modulesref, $languagesarrayref, $languagestringref, $allvariableshashref) = @_; + + # collecting all files with flag INFFILE + + my $inf_files = collect_all_items_with_special_flag($filesref ,"INFFILE"); + + if ( $#{$inf_files} > -1 ) + { + # create new language specific inffile + installer::logger::include_header_into_logfile("Creating inf files:"); + + my $infdirname = "inffiles"; + my $infdir = installer::systemactions::create_directories($infdirname, $languagestringref); + + my $infoline = "Number of inf files: $#{$inf_files} + 1 \n"; + push( @installer::globals::logfileinfo, $infoline); + + # there are inffiles for all modules + + for ( my $i = 0; $i <= $#{$inf_files}; $i++ ) + { + my $inffile = ${$inf_files}[$i]; + my $inf_file_name = $inffile->{'Name'}; + + my $templatefilename = $inffile->{'sourcepath'}; + + if ( ! -f $templatefilename ) { installer::exiter::exit_program("ERROR: Could not find file $templatefilename !", "create_inf_file"); } + + # iterating over all languages + + for ( my $j = 0; $j <= $#{$languagesarrayref}; $j++ ) # iterating over all languages + { + my $firstlanguage = 0; + if ( $j == 0 ) { $firstlanguage = 1; } + + my $onelanguage = ${$languagesarrayref}[$j]; + + $infoline = "Templatefile: $inf_file_name, Language: $onelanguage \n"; + push( @installer::globals::logfileinfo, $infoline); + + my $templatefile = installer::files::read_file($templatefilename); + + my $linesbefore = $#{$templatefile}; + + write_content_into_inf_file($templatefile, $filesref, $registryitemsref, $folderref, $folderitemsref, $modulesref, $onelanguage, $inffile, $firstlanguage, $allvariableshashref); + + $infoline = "Lines change: From $linesbefore to $#{$templatefile}.\n"; + push( @installer::globals::logfileinfo, $infoline); + + # rename language specific inffile + my $language_inf_file_name = $inf_file_name; + my $windowslanguage = installer::windows::language::get_windows_language($onelanguage); + $language_inf_file_name =~ s/\.inf/_$windowslanguage\.inf/; + + my $sourcepath = $infdir . $installer::globals::separator . $language_inf_file_name; + installer::files::save_file($sourcepath, $templatefile); + + $infoline = "Saving file: $sourcepath\n"; + push( @installer::globals::logfileinfo, $infoline); + + # creating new file object + + my %languageinffile = (); + my $languageinifileref = \%languageinffile; + + if ( $j < $#{$languagesarrayref} ) { installer::converter::copy_item_object($inffile, $languageinifileref); } + else { $languageinifileref = $inffile; } + + $languageinifileref->{'Name'} = $language_inf_file_name; + $languageinifileref->{'sourcepath'} = $sourcepath; + # destination and gid also have to be adapted + $languageinifileref->{'gid'} = $languageinifileref->{'gid'} . "_" . $onelanguage; + my $destination = $languageinifileref->{'destination'}; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$destination); + $destination = $destination . $language_inf_file_name; + $languageinifileref->{'destination'} = $destination; + + # add language specific inffile into filesarray + if ( $j < $#{$languagesarrayref} ) { push(@{$filesref}, $languageinifileref); } + } + } + } +} + +########################################################### +# Selecting patch items +########################################################### + +sub select_patch_items +{ + my ( $itemsref, $itemname ) = @_; + + installer::logger::include_header_into_logfile("Selecting items for patches. Item: $itemname"); + + my @itemsarray = (); + + for ( my $i = 0; $i <= $#{$itemsref}; $i++ ) + { + my $oneitem = ${$itemsref}[$i]; + + my $name = $oneitem->{'Name'}; + if (( $name =~ /\bLICENSE/ ) || ( $name =~ /\bREADME/ )) + { + push(@itemsarray, $oneitem); + next; + } + + # Items with style "PATCH" have to be included into the patch + my $styles = ""; + if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; } + if ( $styles =~ /\bPATCH\b/ ) { push(@itemsarray, $oneitem); } + } + + return \@itemsarray; +} + +########################################################### +# Selecting patch items +########################################################### + +sub select_patch_items_without_name +{ + my ( $itemsref, $itemname ) = @_; + + installer::logger::include_header_into_logfile("Selecting RegistryItems for patches"); + + my @itemsarray = (); + + for ( my $i = 0; $i <= $#{$itemsref}; $i++ ) + { + my $oneitem = ${$itemsref}[$i]; + + # Items with style "PATCH" have to be included into the patch + my $styles = ""; + if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; } + if ( $styles =~ /\bPATCH\b/ ) { push(@itemsarray, $oneitem); } + } + + return \@itemsarray; +} + +########################################################### +# Selecting patch items +########################################################### + +sub select_langpack_items +{ + my ( $itemsref, $itemname ) = @_; + + installer::logger::include_header_into_logfile("Selecting RegistryItems for Language Packs"); + + my @itemsarray = (); + + for ( my $i = 0; $i <= $#{$itemsref}; $i++ ) + { + my $oneitem = ${$itemsref}[$i]; + + # Items with style "LANGUAGEPACK" have to be included into the patch + my $styles = ""; + if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; } + if (( $styles =~ /\bLANGUAGEPACK\b/ ) || ( $styles =~ /\bFORCELANGUAGEPACK\b/ )) { push(@itemsarray, $oneitem); } + } + + return \@itemsarray; +} + +########################################################### +# Searching if LICENSE and README, which are not removed +# in select_patch_items are really needed for the patch. +# If not, they are removed now. +########################################################### + +sub analyze_patch_files +{ + my ( $filesref ) = @_; + + installer::logger::include_header_into_logfile("Analyzing patch files"); + + my @filesarray = (); + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + my $styles = ""; + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } + if ( !( $styles =~ /\bPATCH\b/) ) { next; } # removing all files without flag PATCH (LICENSE, README, ...) + + if ( $installer::globals::iswindowsbuild ) + { + # all files of the Windows patch belong to the root module + $onefile->{'modules'} = $installer::globals::rootmodulegid; + } + + push(@filesarray, $onefile); + } + + return \@filesarray; +} + +########################################################### +# Sorting an array +########################################################### + +sub sort_array +{ + my ( $arrayref ) = @_; + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + my $under = ${$arrayref}[$i]; + + for ( my $j = $i + 1; $j <= $#{$arrayref}; $j++ ) + { + my $over = ${$arrayref}[$j]; + + if ( $under gt $over) + { + ${$arrayref}[$i] = $over; + ${$arrayref}[$j] = $under; + $under = $over; + } + } + } +} + +########################################################### +# Renaming linux files with flag LINUXLINK +########################################################### + +sub prepare_linuxlinkfiles +{ + my ( $filesref ) = @_; + + @installer::globals::linuxlinks = (); # empty this array, because it could be already used + @installer::globals::linuxpatchfiles = (); # empty this array, because it could be already used + @installer::globals::allfilessav = (); # empty this array, because it could be already used. Required for forced links + + my @filesarray = (); + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + my %linkfilehash = (); + my $linkfile = \%linkfilehash; + installer::converter::copy_item_object($onefile, $linkfile); + + my $ispatchfile = 0; + my $styles = ""; + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } + if ( $styles =~ /\bPATCH\b/ ) { $ispatchfile = 1; } + + # Collecting all files for the mechanism with forced links + # Saving a copy + my %copyfilehash = (); + my $copyfile = \%copyfilehash; + installer::converter::copy_item_object($onefile, $copyfile); + push( @installer::globals::allfilessav, $copyfile); + + my $original_destination = $onefile->{'destination'}; + # $onefile->{'destination'} is used in the epm list file. This value can be changed now! + + if ( $ispatchfile ) { $onefile->{'destination'} = $onefile->{'destination'} . "\.$installer::globals::linuxlibrarypatchlevel"; } + else { $onefile->{'destination'} = $onefile->{'destination'} . "\.$installer::globals::linuxlibrarybaselevel"; } + + my $infoline = "LINUXLINK: Changing file destination from $original_destination to $onefile->{'destination'} !\n"; + push( @installer::globals::logfileinfo, $infoline); + + # all files without PATCH flag are included into the RPM + if ( ! $ispatchfile ) { push( @filesarray, $onefile); } + else { push( @installer::globals::linuxpatchfiles, $onefile); } + + # Preparing the collector for the links + # Setting the new file name as destination of the link + my $linkdestination = $linkfile->{'Name'}; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$linkdestination); + if ( $ispatchfile ) { $linkfile->{'destinationfile'} = $linkdestination . "\.$installer::globals::linuxlibrarypatchlevel"; } + else { $linkfile->{'destinationfile'} = $linkdestination . "\.$installer::globals::linuxlibrarybaselevel"; } + push( @installer::globals::linuxlinks, $linkfile ); + + $infoline = "LINUXLINK: Created link: $linkfile->{'destination'} pointing to $linkfile->{'destinationfile'} !\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + return \@filesarray; +} + +########################################################### +# Adding links into "u-RPMs", that have the flag +# FORCE_INTO_UPDATE_PACKAGE +# This is only relevant for Linux +########################################################### + +sub prepare_forced_linuxlinkfiles +{ + my ( $linksref ) = @_; + + my @linksarray = (); + + for ( my $i = 0; $i <= $#{$linksref}; $i++ ) + { + my $onelink = ${$linksref}[$i]; + + my $isforcedlink = 0; + my $styles = ""; + if ( $onelink->{'Styles'} ) { $styles = $onelink->{'Styles'}; } + if ( $styles =~ /\bFORCE_INTO_UPDATE_PACKAGE\b/ ) { $isforcedlink = 1; } + + if ( $isforcedlink ) + { + my $fileid = ""; + + if ( $onelink->{'ShortcutID'} ) + { + $fileid = $onelink->{'ShortcutID'}; + + my $searchedlinkfile = find_file_by_id($linksref, $fileid); + + # making a copy! + my %linkfilehash = (); + my $linkfile = \%linkfilehash; + installer::converter::copy_item_object($searchedlinkfile, $linkfile); + + $linkfile->{'Name'} = $onelink->{'Name'}; + $linkfile->{'destinationfile'} = $linkfile->{'destination'}; + my $linkdestination = $linkfile->{'destinationfile'}; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$linkdestination); + $linkfile->{'destinationfile'} = $linkdestination; + + my $localdestination = $linkfile->{'destination'}; + # Getting the path + installer::pathanalyzer::get_path_from_fullqualifiedname(\$localdestination); + $localdestination =~ s/\Q$installer::globals::separator\E\s*$//; + $linkfile->{'destination'} = $localdestination . $installer::globals::separator . $onelink->{'Name'}; + + $infoline = "Forced link into update file: $linkfile->{'destination'} pointing to $linkfile->{'destinationfile'} !\n"; + push( @installer::globals::logfileinfo, $infoline); + + # The file, defined by the link, has to be included into the + # link array @installer::globals::linuxlinks + push( @installer::globals::linuxlinks, $linkfile ); + } + + if ( $onelink->{'FileID'} ) + { + $fileid = $onelink->{'FileID'}; + + my $searchedlinkfile = find_file_by_id(\@installer::globals::allfilessav, $fileid); + + # making a copy! + my %linkfilehash = (); + my $linkfile = \%linkfilehash; + installer::converter::copy_item_object($searchedlinkfile, $linkfile); + + $linkfile->{'Name'} = $onelink->{'Name'}; + $linkfile->{'destinationfile'} = $linkfile->{'destination'}; + my $linkdestination = $linkfile->{'destinationfile'}; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$linkdestination); + $linkfile->{'destinationfile'} = $linkdestination; + + my $localdestination = $linkfile->{'destination'}; + # Getting the path + installer::pathanalyzer::get_path_from_fullqualifiedname(\$localdestination); + $localdestination =~ s/\Q$installer::globals::separator\E\s*$//; + $linkfile->{'destination'} = $localdestination . $installer::globals::separator . $onelink->{'Name'}; + + $infoline = "Forced link into update file: $linkfile->{'destination'} pointing to $linkfile->{'destinationfile'} !\n"; + push( @installer::globals::logfileinfo, $infoline); + + # The file, defined by the link, has to be included into the + # link array @installer::globals::linuxlinks + push( @installer::globals::linuxlinks, $linkfile ); + } + + if ( $fileid eq "" ) { installer::exiter::exit_program("ERROR: No FileID assigned to forced link $onelink->{'gid'} !", "prepare_forced_linuxlinkfiles"); } + + } + else + { + # Links with flag FORCE_INTO_UPDATE_PACKAGE are forced into "u"-RPM. All other + # links are included into the non-"u"-package. + push( @linksarray, $onelink ); + } + } + + return \@linksarray; +} + +########################################################### +# reorganizing the patchfile content, +# sorting for directory to decrease the file size +########################################################### + +sub reorg_patchfile +{ + my ($patchfiles, $patchfiledirectories) = @_; + + my @patchfilesarray = (); + my $line = ""; + my $directory = ""; + + # iterating over all directories, writing content into new patchfiles list + + for ( my $i = 0; $i <= $#{$patchfiledirectories}; $i++ ) + { + $directory = ${$patchfiledirectories}[$i]; + $line = "[" . $directory . "]" . "\n"; + push(@patchfilesarray, $line); + + for ( my $j = 0; $j <= $#{$patchfiles}; $j++ ) + { + # "\tXXXXX\t" . $olddestination . "\n"; + if ( ${$patchfiles}[$j] =~ /^\s*(.*?)\s*\tXXXXX\t\Q$directory\E\s*$/ ) + { + $line = $1 . "\n"; + push(@patchfilesarray, $line); + } + } + } + + return \@patchfilesarray; +} + +########################################################### +# One special file has to be the last in patchfile.txt. +# Controlling this file, guarantees, that all files were +# patch correctly. Using version.ini makes it easy to +# control this by looking into the about box +# -> shifting one section to the end +########################################################### + +sub shift_section_to_end +{ + my ($patchfilelist) = @_; + + my @patchfile = (); + my @lastsection = (); + my $lastsection = "program"; + my $notlastsection = "Basis\\program"; + my $record = 0; + + for ( my $i = 0; $i <= $#{$patchfilelist}; $i++ ) + { + my $line = ${$patchfilelist}[$i]; + + if (( $record ) && ( $line =~ /^\s*\[/ )) { $record = 0; } + + if (( $line =~ /^\s*\[\Q$lastsection\E\\\]\s*$/ ) && ( ! ( $line =~ /\Q$notlastsection\E\\\]\s*$/ ))) { $record = 1; } + + if ( $record ) { push(@lastsection, $line); } + else { push(@patchfile, $line); } + } + + if ( $#lastsection > -1 ) + { + for ( my $i = 0; $i <= $#lastsection; $i++ ) + { + push(@patchfile, $lastsection[$i]); + } + } + + return \@patchfile; +} + +########################################################### +# One special file has to be the last in patchfile.txt. +# Controlling this file, guarantees, that all files were +# patch correctly. Using version.ini makes it easy to +# control this by looking into the about box +# -> shifting one file of the last section to the end +########################################################### + +sub shift_file_to_end +{ + my ($patchfilelist) = @_; + + my @patchfile = (); + my $lastfilename = "version.ini"; + my $lastfileline = ""; + my $foundfile = 0; + + # Only searching this file in the last section + my $lastsectionname = ""; + + for ( my $i = 0; $i <= $#{$patchfilelist}; $i++ ) + { + my $line = ${$patchfilelist}[$i]; + if ( $line =~ /^\s*\[(.*?)\]\s*$/ ) { $lastsectionname = $1; } + } + + my $record = 0; + for ( my $i = 0; $i <= $#{$patchfilelist}; $i++ ) + { + my $line = ${$patchfilelist}[$i]; + + if ( $line =~ /^\s*\[\Q$lastsectionname\E\]\s*$/ ) { $record = 1; } + + if (( $line =~ /^\s*\"\Q$lastfilename\E\"\=/ ) && ( $record )) + { + $lastfileline = $line; + $foundfile = 1; + $record = 0; + next; + } + + push(@patchfile, $line); + } + + if ( $foundfile ) { push(@patchfile, $lastfileline); } + + return \@patchfile; +} + +########################################################### +# Putting hash content into array and sorting it +########################################################### + +sub sort_hash +{ + my ( $hashref ) = @_; + + my $item = ""; + my @sortedarray = (); + + foreach $item (keys %{$hashref}) { push(@sortedarray, $item); } + installer::sorter::sorting_array_of_strings(\@sortedarray); + + return \@sortedarray; +} + +########################################################### +# Renaming Windows files in Patch and creating file +# patchfiles.txt +########################################################### + +sub prepare_windows_patchfiles +{ + my ( $filesref, $languagestringref, $allvariableshashref ) = @_; + + my @patchfiles = (); + my %patchfiledirectories = (); + my $patchfilename = "patchlist.txt"; + my $patchfilename2 = "patchmsi.dll"; + + if ( ! $allvariableshashref->{'WINDOWSPATCHLEVEL'} ) { installer::exiter::exit_program("ERROR: No Windows patch level defined in list file (WINDOWSPATCHLEVEL) !", "prepare_windows_patchfiles"); } + # my $windowspatchlevel = $allvariableshashref->{'WINDOWSPATCHLEVEL'}; + my $windowspatchlevel = $installer::globals::buildid; + + # the environment variable CWS_WORK_STAMP is set only in CWS + if ( $ENV{'CWS_WORK_STAMP'} ) { $windowspatchlevel = $ENV{'CWS_WORK_STAMP'} . $windowspatchlevel; } + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + my $onefile = ${$filesref}[$i]; + + my $filename = $onefile->{'Name'}; + if (( $filename eq $patchfilename ) || ( $filename eq $patchfilename2 )) { next; } + + my $styles = ""; + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } + if ( $styles =~ /\bDONTRENAMEINPATCH\b/ ) { next; } + + # special handling for files with flag DONTSHOW. This files get the extension ".dontshow" to be filtered by dialogs. + my $localwindowspatchlevel = $windowspatchlevel; + if ( $styles =~ /\bDONTSHOW\b/ ) { $localwindowspatchlevel = $localwindowspatchlevel . "\.dontshow"; } + + my $olddestination = $onefile->{'destination'}; + my $newdestination = $olddestination . "." . $localwindowspatchlevel; + my $localfilename = $olddestination; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$localfilename); # file name part + my $line = "\"" . $localfilename . "\"" . "=" . "\"" . "\." . $localwindowspatchlevel . "\""; + $onefile->{'destination'} = $newdestination; + + my $newfilename = $onefile->{'Name'} . "." . $localwindowspatchlevel; + $onefile->{'Name'} = $newfilename; + + # adding section information (section is the directory) + my $origolddestination = $olddestination; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$olddestination); # directory part + if ( ! $olddestination ) { $olddestination = "_root"; } + if ( ! exists($patchfiledirectories{$olddestination}) ) { $patchfiledirectories{$olddestination} = 1; } + $line = $line . "\tXXXXX\t" . $olddestination . "\n"; + + push(@patchfiles, $line); + + # also collecting all files from patch in @installer::globals::patchfilecollector + my $patchfileline = $origolddestination . "\n"; + push(@installer::globals::patchfilecollector, $patchfileline); + } + + my $winpatchdirname = "winpatch"; + my $winpatchdir = installer::systemactions::create_directories($winpatchdirname, $languagestringref); + + my $patchlistfile = installer::existence::get_specified_file_by_name($filesref, $patchfilename); + + # reorganizing the patchfile content, sorting for directory to decrease the file size + my $sorteddirectorylist = sort_hash(\%patchfiledirectories); + my $patchfilelist = reorg_patchfile(\@patchfiles, $sorteddirectorylist); + + # shifting version.ini to the end of the list, to guarantee, that all files are patched + # if the correct version is shown in the about box + $patchfilelist = shift_section_to_end($patchfilelist); + $patchfilelist = shift_file_to_end($patchfilelist); + + # saving the file + $patchfilename = $winpatchdir . $installer::globals::separator . $patchfilename; + installer::files::save_file($patchfilename, $patchfilelist); + + my $infoline = "\nCreated list of patch files: $patchfilename\n"; + push( @installer::globals::logfileinfo, $infoline); + + # and assigning the new source + $patchlistfile->{'sourcepath'} = $patchfilename; + + # and finally checking the file size + if ( -f $patchfilename ) # test of existence + { + my $filesize = ( -s $patchfilename ); + $infoline = "Size of patch file list: $filesize\n\n"; + push( @installer::globals::logfileinfo, $infoline); + installer::logger::print_message( "... size of patch list file: $filesize Byte ... \n" ); + + # Win 98: Maximum size of ini file is 65 kB + # if ( $filesize > 64000 ) { installer::exiter::exit_program("ERROR: Maximum size of patch file list is 65 kB (Win98), now reached: $filesize Byte !", "prepare_windows_patchfiles"); } + } + +} + +########################################################### +# Replacing %-variables with the content +# of $allvariableshashref +########################################################### + +sub replace_variables_in_string +{ + my ( $string, $variableshashref ) = @_; + + if ( $string =~ /^.*\%\w+.*$/ ) + { + my $key; + + foreach $key (keys %{$variableshashref}) + { + my $value = $variableshashref->{$key}; + $key = "\%" . $key; + $string =~ s/\Q$key\E/$value/g; + } + } + + return $string; +} + +########################################################### +# Replacing %-variables with the content +# of $allvariableshashref +########################################################### + +sub replace_dollar_variables_in_string +{ + my ( $string, $variableshashref ) = @_; + + if ( $string =~ /^.*\$\{\w+\}.*$/ ) + { + my $key; + + foreach $key (keys %{$variableshashref}) + { + my $value = $variableshashref->{$key}; + $key = "\$\{" . $key . "\}"; + $string =~ s/\Q$key\E/$value/g; + } + } + + return $string; +} + +########################################################### +# The list file contains the list of packages/RPMs that +# have to be copied. +########################################################### + +sub get_all_files_from_filelist +{ + my ( $listfile, $section ) = @_; + + my @allpackages = (); + + for ( my $i = 0; $i <= $#{$listfile}; $i++ ) + { + my $line = ${$listfile}[$i]; + if ( $line =~ /^\s*\#/ ) { next; } # this is a comment line + if ( $line =~ /^\s*$/ ) { next; } # empty line + $line =~ s/^\s*//; + $line =~ s/\s*$//; + push(@allpackages, $line); + } + + return \@allpackages; +} + +########################################################### +# Getting one section from a file. Section begins with +# [xyz] and ends with file end or next [abc]. +########################################################### + +sub get_section_from_file +{ + my ($file, $sectionname) = @_; + + my @section = (); + my $record = 0; + + for ( my $i = 0; $i <= $#{$file}; $i++ ) + { + my $line = ${$file}[$i]; + + if (( $record ) && ( $line =~ /^\s*\[/ )) + { + $record = 0; + last; + } + + if ( $line =~ /^\s*\[\Q$sectionname\E\]\s*$/ ) { $record = 1; } + + if ( $line =~ /^\s*\[/ ) { next; } # this is a section line + if ( $line =~ /^\s*\#/ ) { next; } # this is a comment line + if ( $line =~ /^\s*$/ ) { next; } # empty line + $line =~ s/^\s*//; + $line =~ s/\s*$//; + if ( $record ) { push(@section, $line); } + } + + return \@section; + +} + +####################################################### +# Substituting one variable in the xml file +####################################################### + +sub replace_one_dollar_variable +{ + my ($file, $variable, $searchstring) = @_; + + for ( my $i = 0; $i <= $#{$file}; $i++ ) + { + ${$file}[$i] =~ s/\$\{$searchstring\}/$variable/g; + } +} + +####################################################### +# Substituting the variables in the xml file +####################################################### + +sub substitute_dollar_variables +{ + my ($file, $variableshashref) = @_; + + my $key; + + foreach $key (keys %{$variableshashref}) + { + my $value = $variableshashref->{$key}; + replace_one_dollar_variable($file, $value, $key); + } +} + +############################################################################# +# Collecting all packages or rpms located in the installation directory +############################################################################# + +sub get_all_packages_in_installdir +{ + my ($directory) = @_; + + my $infoline = ""; + + my @allpackages = (); + my $allpackages = \@allpackages; + + if ( $installer::globals::islinuxrpmbuild ) + { + $allpackages = installer::systemactions::find_file_with_file_extension("rpm", $directory); + } + + if ( $installer::globals::issolarisbuild ) + { + $allpackages = installer::systemactions::get_all_directories($directory); + } + + return $allpackages; +} + +############################################################### +# The list of exclude packages can contain the +# beginning of the package name, not the complete name. +############################################################### + +sub is_matching +{ + my ($onepackage, $allexcludepackages ) = @_; + + my $matches = 0; + + for ( my $i = 0; $i <= $#{$allexcludepackages}; $i++ ) + { + my $oneexcludepackage = ${$allexcludepackages}[$i]; + + if ( $onepackage =~ /^\s*$oneexcludepackage/ ) + { + $matches = 1; + last; + } + } + + return $matches; +} + +############################################################### +# Copying all Solaris packages or RPMs from installation set +############################################################### + +sub copy_all_packages +{ + my ($allexcludepackages, $sourcedir, $destdir) = @_; + + my $infoline = ""; + + $sourcedir =~ s/\/\s*$//; + $destdir =~ s/\/\s*$//; + + # $allexcludepackages is a list of RPMs and packages, that shall NOT be included into jds product + my $allpackages = get_all_packages_in_installdir($sourcedir); + + for ( my $i = 0; $i <= $#{$allpackages}; $i++ ) + { + my $onepackage = ${$allpackages}[$i]; + + my $packagename = $onepackage; + + if ( $installer::globals::issolarispkgbuild ) # on Solaris $onepackage contains the complete path + { + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$packagename); + } + + if ( ! installer::existence::exists_in_array($packagename, $allexcludepackages)) + { + if ( ! is_matching($packagename, $allexcludepackages ) ) + { + + if ( $installer::globals::islinuxrpmbuild ) + { + my $sourcepackage = $sourcedir . $installer::globals::separator . $packagename; + my $destfile = $destdir . $installer::globals::separator . $packagename; + if ( ! -f $sourcepackage ) { installer::exiter::exit_program("ERROR: Could not find RPM $sourcepackage!", "copy_all_packages"); } + installer::systemactions::hardlink_one_file($sourcepackage, $destfile); + } + + if ( $installer::globals::issolarispkgbuild ) + { + my $destinationdir = $destdir . $installer::globals::separator . $packagename; + if ( ! -d $onepackage ) { installer::exiter::exit_program("ERROR: Could not find Solaris package $onepackage!", "copy_all_packages"); } + # installer::systemactions::hardlink_complete_directory($onepackage, $destinationdir); + # installer::systemactions::copy_complete_directory($onepackage, $destinationdir); + + my $systemcall = "cp -p -R $onepackage $destinationdir"; + make_systemcall($systemcall); + } + } + else + { + $infoline = "Excluding package (matching): $onepackage\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + else + { + $infoline = "Excluding package (precise name): $onepackage\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } +} + +###################################################### +# Making systemcall +###################################################### + +sub make_systemcall +{ + my ($systemcall) = @_; + + my $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +########################################################### +# Copying all Solaris packages or RPMs from solver +########################################################### + +sub copy_additional_packages +{ + my ($allcopypackages, $destdir, $includepatharrayref) = @_; + + my $infoline = "Copy additional packages into installation set.\n"; + push( @installer::globals::logfileinfo, $infoline); + + $destdir =~ s/\/\s*$//; + + for ( my $i = 0; $i <= $#{$allcopypackages}; $i++ ) + { + my $onepackage = ${$allcopypackages}[$i]; + $infoline = "Copy package: $onepackage\n"; + push( @installer::globals::logfileinfo, $infoline); + + # this package must be delivered into the solver + + my $packagesourceref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$onepackage, $includepatharrayref, 0); + if ($$packagesourceref eq "") { installer::exiter::exit_program("ERROR: Could not find jds file $onepackage!", "copy_additional_packages"); } + + if ( $onepackage =~ /\.tar\.gz\s*$/ ) + { + my $systemcall = "cd $destdir; cat $$packagesourceref | gunzip | tar -xf -"; + make_systemcall($systemcall); + } + else + { + my $destfile = $destdir . $installer::globals::separator . $onepackage; + installer::systemactions::copy_one_file($$packagesourceref, $destfile); + } + } +} + +########################################################### +# Creating jds installation sets +########################################################### + +sub create_jds_sets +{ + my ($installationdir, $allvariableshashref, $languagestringref, $languagesarrayref, $includepatharrayref) = @_; + + installer::logger::print_message( "\n******************************************\n" ); + installer::logger::print_message( "... creating jds installation set ...\n" ); + installer::logger::print_message( "******************************************\n" ); + + installer::logger::include_header_into_logfile("Creating jds installation sets:"); + + my $firstdir = $installationdir; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$firstdir); + + my $lastdir = $installationdir; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$lastdir); + + if ( $lastdir =~ /\./ ) { $lastdir =~ s/\./_jds_inprogress\./ } + else { $lastdir = $lastdir . "_jds_inprogress"; } + + # removing existing directory "_native_packed_inprogress" and "_native_packed_witherror" and "_native_packed" + + my $jdsdir = $firstdir . $lastdir; + if ( -d $jdsdir ) { installer::systemactions::remove_complete_directory($jdsdir); } + + my $olddir = $jdsdir; + $olddir =~ s/_inprogress/_witherror/; + if ( -d $olddir ) { installer::systemactions::remove_complete_directory($olddir); } + + $olddir = $jdsdir; + $olddir =~ s/_inprogress//; + if ( -d $olddir ) { installer::systemactions::remove_complete_directory($olddir); } + + # creating the new directory + + installer::systemactions::create_directory($jdsdir); + + $installer::globals::saveinstalldir = $jdsdir; + + # find and read jds files list + my $filelistname = $installer::globals::jdsexcludefilename; + + my $filelistnameref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$filelistname, "", 0); + if ($$filelistnameref eq "") { installer::exiter::exit_program("ERROR: Could not find jds list file $filelistname!", "create_jds_sets"); } + + my $listfile = installer::files::read_file($$filelistnameref); + + my $infoline = "Found jds list file: $$filelistnameref\n"; + push( @installer::globals::logfileinfo, $infoline); + + # substituting the variables + substitute_dollar_variables($listfile, $allvariableshashref); + + # determining the packages/RPMs to copy + my $allexcludepackages = get_section_from_file($listfile, "excludefiles"); + my $allcopypackages = get_section_from_file($listfile, "copyfiles"); + + # determining the source directory + my $alldirs = installer::systemactions::get_all_directories($installationdir); + my $sourcedir = ${$alldirs}[0]; # there is only one directory + + if ( $installer::globals::issolarisbuild ) { $sourcedir = $installer::globals::saved_packages_path; } + + # copy all packages/RPMs + copy_all_packages($allexcludepackages, $sourcedir, $jdsdir); + copy_additional_packages($allcopypackages, $jdsdir, $includepatharrayref); + + return $jdsdir; +} + +############################################################################# +# Checking, whether this installation set contains the correct languages +############################################################################# + +sub check_jds_language +{ + my ($allvariableshashref, $languagestringref) = @_; + + my $infoline = ""; + + # languagesarrayref and $allvariableshashref->{'JDSLANG'} + + if ( ! $allvariableshashref->{'JDSLANG'} ) { installer::exiter::exit_program("ERROR: For building JDS installation sets \"JDSLANG\" must be defined!", "check_jds_language"); } + my $languagestring = $allvariableshashref->{'JDSLANG'}; + + my $sortedarray1 = installer::converter::convert_stringlist_into_array(\$languagestring, ","); + + installer::sorter::sorting_array_of_strings($sortedarray1); + + my $sortedarray2 = installer::converter::convert_stringlist_into_array($languagestringref, "_"); + installer::sorter::sorting_array_of_strings($sortedarray2); + + my $string1 = installer::converter::convert_array_to_comma_separated_string($sortedarray1); + my $string2 = installer::converter::convert_array_to_comma_separated_string($sortedarray2); + + my $arrays_are_equal = compare_arrays($sortedarray1, $sortedarray2); + + return $arrays_are_equal; +} + +################################################################################### +# Comparing two arrays. The arrays are equal, if the complete content is equal. +################################################################################### + +sub compare_arrays +{ + my ($array1, $array2) = @_; + + my $arrays_are_equal = 1; + + # checking the size + + if ( ! ( $#{$array1} == $#{$array2} )) { $arrays_are_equal = 0; } # different size + + if ( $arrays_are_equal ) # only make further investigations if size is equal + { + for ( my $i = 0; $i <= $#{$array1}; $i++ ) + { + # ingnoring whitespaces at end and beginning + ${$array1}[$i] =~ s/^\s*//; + ${$array2}[$i] =~ s/^\s*//; + ${$array1}[$i] =~ s/\s*$//; + ${$array2}[$i] =~ s/\s*$//; + + if ( ! ( ${$array1}[$i] eq ${$array2}[$i] )) + { + $arrays_are_equal = 0; + last; + } + } + } + + return $arrays_are_equal; +} + +################################################################# +# Copying the files defined as ScpActions into the +# installation set. +################################################################# + +sub put_scpactions_into_installset +{ + my ($installdir) = @_; + + installer::logger::include_header_into_logfile("Start: Copying scp action files into installation set"); + + for ( my $i = 0; $i <= $#installer::globals::allscpactions; $i++ ) + { + my $onescpaction = $installer::globals::allscpactions[$i]; + + my $subdir = ""; + if ( $onescpaction->{'Subdir'} ) { $subdir = $onescpaction->{'Subdir'}; } + + if ( $onescpaction->{'Name'} eq "loader.exe" ) { next; } # do not copy this ScpAction loader + + my $destdir = $installdir; + $destdir =~ s/\Q$installer::globals::separator\E\s*$//; + if ( $subdir ) { $destdir = $destdir . $installer::globals::separator . $subdir; } + + my $sourcefile = $onescpaction->{'sourcepath'}; + my $destfile = $destdir . $installer::globals::separator . $onescpaction->{'DestinationName'}; + + my $styles = ""; + if ( $onescpaction->{'Styles'} ) { $styles = $onescpaction->{'Styles'}; } + if (( $styles =~ /\bFILE_CAN_MISS\b/ ) && ( $sourcefile eq "" )) { next; } + + if (( $subdir =~ /\// ) || ( $subdir =~ /\\/ )) + { + installer::systemactions::create_directory_structure($destdir); + } + else + { + installer::systemactions::create_directory($destdir); + } + + installer::systemactions::copy_one_file($sourcefile, $destfile); + + if ( $onescpaction->{'UnixRights'} ) + { + my $localcall = "chmod $onescpaction->{'UnixRights'} $destfile \>\/dev\/null 2\>\&1"; + system($localcall); + } + + } + + installer::logger::include_header_into_logfile("End: Copying scp action files into installation set"); + +} + +################################################################# +# Collecting scp actions for all languages +################################################################# + +sub collect_scpactions +{ + my ($allscpactions) = @_; + + for ( my $i = 0; $i <= $#{$allscpactions}; $i++ ) + { + push(@installer::globals::allscpactions, ${$allscpactions}[$i]); + } +} + +################################################################# +# Setting the platform name for download +################################################################# + +sub get_platform_name +{ + my $platformname = ""; + + if (( $installer::globals::islinuxintelrpmbuild ) || ( $installer::globals::islinuxinteldebbuild )) + { + $platformname = "LinuxIntel"; + } + elsif (( $installer::globals::islinuxppcrpmbuild ) || ( $installer::globals::islinuxppcdebbuild )) + { + $platformname = "LinuxPowerPC"; + } + elsif (( $installer::globals::islinuxx86_64rpmbuild ) || ( $installer::globals::islinuxx86_64debbuild )) + { + $platformname = "LinuxX86-64"; + } + elsif ( $installer::globals::issolarissparcbuild ) + { + $platformname = "SolarisSparc"; + } + elsif ( $installer::globals::issolarisx86build ) + { + $platformname = "Solarisx86"; + } + elsif ( $installer::globals::iswindowsbuild ) + { + $platformname = "Win32Intel"; + } + elsif ( $installer::globals::compiler =~ /^unxmacxi/ ) + { + $platformname = "MacOSXIntel"; + } + elsif ( $installer::globals::compiler =~ /^unxmacxp/ ) + { + $platformname = "MacOSXPowerPC"; + } + else + { + # $platformname = $installer::globals::packageformat; + $platformname = $installer::globals::compiler; + } + + return $platformname; +} + +########################################################### +# Adding additional variables into the variableshashref, +# that are defined in include files in the solver. The +# names of the include files are stored in +# ADD_INCLUDE_FILES (comma separated list). +########################################################### + +sub add_variables_from_inc_to_hashref +{ + my ($allvariables, $includepatharrayref) = @_; + + my $infoline = ""; + my $includefilelist = ""; + if ( $allvariables->{'ADD_INCLUDE_FILES'} ) { $includefilelist = $allvariables->{'ADD_INCLUDE_FILES'}; } + + my $includefiles = installer::converter::convert_stringlist_into_array_without_linebreak_and_quotes(\$includefilelist, ","); + + for ( my $i = 0; $i <= $#{$includefiles}; $i++ ) + { + my $includefilename = ${$includefiles}[$i]; + $includefilename =~ s/^\s*//; + $includefilename =~ s/\s*$//; + $includefilenameref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$includefilename, $includepatharrayref, 1); + if ( $$includefilenameref eq "" ) { installer::exiter::exit_program("Include file $includefilename not found!\nADD_INCLUDE_FILES = $allvariables->{'ADD_INCLUDE_FILES'}", "add_variables_from_inc_to_hashref"); } + + $infoline = "Including inc file: $$includefilenameref \n"; + push( @installer::globals::globallogfileinfo, $infoline); + + my $includefile = installer::files::read_file($$includefilenameref); + + for ( my $j = 0; $j <= $#{$includefile}; $j++ ) + { + # Analyzing all "key=value" lines + my $oneline = ${$includefile}[$j]; + + if ( $oneline =~ /^\s*(\S+)\s*\=\s*(.*?)\s*$/ ) # no white space allowed in key + { + my $key = $1; + my $value = $2; + $allvariables->{$key} = $value; + $infoline = "Setting of variable: $key = $value\n"; + push( @installer::globals::globallogfileinfo, $infoline); + } + } + } + + # Allowing different Java versions for Windows and Unix. Instead of "JAVAVERSION" + # the property "WINDOWSJAVAVERSION" has to be used, if it is set. + + if ( $installer::globals::iswindowsbuild ) + { + if (( exists($allvariables->{'WINDOWSJAVAVERSION'})) && ( $allvariables->{'WINDOWSJAVAVERSION'} ne "" )) + { + $allvariables->{'JAVAVERSION'} = $allvariables->{'WINDOWSJAVAVERSION'}; + $infoline = "Changing value of property \"JAVAVERSION\" to $allvariables->{'JAVAVERSION'} (property \"WINDOWSJAVAVERSION\").\n"; + push( @installer::globals::globallogfileinfo, $infoline); + } + } +} + +############################################## +# Collecting all files from include pathes +############################################## + +sub collect_all_files_from_includepathes +{ + my ($patharrayref) = @_; + + installer::logger::globallog("Reading all directories: Start"); + installer::logger::print_message( "... reading include pathes ...\n" ); + # empty the global + + @installer::globals::allincludepathes =(); + my $infoline; + + for ( my $i = 0; $i <= $#{$patharrayref}; $i++ ) + { + $includepath = ${$patharrayref}[$i]; + installer::remover::remove_leading_and_ending_whitespaces(\$includepath); + + if ( ! -d $includepath ) + { + $infoline = "$includepath does not exist. (Can be removed from include path list?)\n"; + push( @installer::globals::globallogfileinfo, $infoline); + next; + } + + my @sourcefiles = (); + my $pathstring = ""; + installer::systemactions::read_complete_directory($includepath, $pathstring, \@sourcefiles); + + if ( ! ( $#sourcefiles > -1 )) + { + $infoline = "$includepath is empty. (Can be removed from include path list?)\n"; + push( @installer::globals::globallogfileinfo, $infoline); + } + else + { + my $number = $#sourcefiles + 1; + $infoline = "Directory $includepath contains $number files (including subdirs)\n"; + push( @installer::globals::globallogfileinfo, $infoline); + + my %allfileshash = (); + $allfileshash{'includepath'} = $includepath; + + for ( my $j = 0; $j <= $#sourcefiles; $j++ ) + { + $allfileshash{$sourcefiles[$j]} = 1; + } + + push(@installer::globals::allincludepathes, \%allfileshash); + } + } + + installer::logger::globallog("Reading all directories: End"); + push( @installer::globals::globallogfileinfo, "\n"); +} + +############################################## +# Searching for a file with the gid +############################################## + +sub find_file_by_id +{ + my ( $filesref, $gid ) = @_; + + my $foundfile = 0; + my $onefile; + + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + $onefile = ${$filesref}[$i]; + my $filegid = $onefile->{'gid'}; + + if ( $filegid eq $gid ) + { + $foundfile = 1; + last; + } + } + + # It does not need to exist. For example products that do not contain the libraries. + # if (! $foundfile ) { installer::exiter::exit_program("ERROR: No unique file name found for $filename !", "get_selfreg_file"); } + + if (! $foundfile ) { $onefile = ""; } + + return $onefile; +} + +############################################## +# Searching for an item with the gid +############################################## + +sub find_item_by_gid +{ + my ( $itemsref, $gid ) = @_; + + my $founditem = 0; + my $oneitem = ""; + + for ( my $i = 0; $i <= $#{$itemsref}; $i++ ) + { + my $localitem = ${$itemsref}[$i]; + my $itemgid = $localitem->{'gid'}; + + if ( $itemgid eq $gid ) + { + $oneitem = $localitem; + $founditem = 1; + last; + } + } + + return $oneitem; +} + +######################################################### +# Calling sum +######################################################### + +sub call_sum +{ + my ($filename) = @_; + + $sumfile = "/usr/bin/sum"; + + if ( ! -f $sumfile ) { installer::exiter::exit_program("ERROR: No file /usr/bin/sum", "call_sum"); } + + my $systemcall = "$sumfile $filename |"; + + my $sumoutput = ""; + + open (SUM, "$systemcall"); + $sumoutput = <SUM>; + close (SUM); + + my $returnvalue = $?; # $? contains the return value of the systemcall + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + return $sumoutput; +} + +######################################################### +# Calling wc +# wc -c pkginfo | cut -f6 -d' ' +######################################################### + +sub call_wc +{ + my ($filename) = @_; + + $wcfile = "/usr/bin/wc"; + + if ( ! -f $wcfile ) { installer::exiter::exit_program("ERROR: No file /usr/bin/wc", "call_wc"); } + + my $systemcall = "$wcfile -c $filename |"; + + my $wcoutput = ""; + + open (WC, "$systemcall"); + $wcoutput = <WC>; + close (WC); + + my $returnvalue = $?; # $? contains the return value of the systemcall + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + return $wcoutput; +} + +############################################## +# Setting architecture ARCH=i86pc +# instead of ARCH=i386. +############################################## + +sub set_old_architecture_string +{ + my ($pkginfofile) = @_; + + for ( my $i = 0; $i <= $#{$pkginfofile}; $i++ ) + { + if ( ${$pkginfofile}[$i] =~ /^\s*ARCH=i386\s*$/ ) + { + ${$pkginfofile}[$i] =~ s/i386/i86pc/; + last; + } + } +} + +############################################## +# For the new copied package, it is necessary +# that a value for the key SUNW_REQUIRES +# is set. Otherwise this copied package +# with ARCH=i86pc would be useless. +############################################## + +sub check_requires_setting +{ + my ($pkginfofile) = @_; + + my $found = 0; + my $patchid = ""; + + for ( my $i = 0; $i <= $#{$pkginfofile}; $i++ ) + { + if ( ${$pkginfofile}[$i] =~ /^\s*SUNW_REQUIRES=(\S*?)\s*$/ ) + { + $patchid = $1; + $found = 1; + last; + } + } + + if (( ! $found ) || ( $patchid eq "" )) { installer::exiter::exit_program("ERROR: No patch id defined for SUNW_REQUIRES in patch pkginfo file!", "check_requires_setting"); } +} + +############################################## +# Setting checksum and wordcount for changed +# pkginfo file into pkgmap. +############################################## + +sub set_pkginfo_line +{ + my ($pkgmapfile, $pkginfofilename) = @_; + + # 1 i pkginfo 442 34577 1166716297 + # -> + # 1 i pkginfo 443 34737 1166716297 + # + # wc -c pkginfo | cut -f6 -d' ' -> 442 (variable) + # sum pkginfo | cut -f1 -d' ' -> 34577 (variable) + # grep 'pkginfo' pkgmap | cut -f6 -d' ' -> 1166716297 (fix) + + my $checksum = call_sum($pkginfofilename); + if ( $checksum =~ /^\s*(\d+)\s+.*$/ ) { $checksum = $1; } + + my $wordcount = call_wc($pkginfofilename); + if ( $wordcount =~ /^\s*(\d+)\s+.*$/ ) { $wordcount = $1; } + + for ( my $i = 0; $i <= $#{$pkgmapfile}; $i++ ) + { + if ( ${$pkgmapfile}[$i] =~ /(^.*\bpkginfo\b\s+)(\d+)(\s+)(\d+)(\s+)(\d+)(\s*$)/ ) + { + my $newline = $1 . $wordcount . $3 . $checksum . $5 . $6 . $7; + ${$pkgmapfile}[$i] = $newline; + last; + } + } +} + +############################################## +# Setting time stamp of copied files to avoid +# errors from pkgchk. +############################################## + +sub set_time_stamp +{ + my ($olddir, $newdir, $copyfiles) = @_; + + for ( my $i = 0; $i <= $#{$copyfiles}; $i++ ) + { + my $sourcefile = $olddir . $installer::globals::separator . ${$copyfiles}[$i]; + my $destfile = $newdir . $installer::globals::separator . ${$copyfiles}[$i]; + + my $systemcall = "touch -r $sourcefile $destfile"; + + my $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: \"$systemcall\" failed!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: \"$systemcall\" !\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } +} + +############################################## +# Include only files from install directory +# in pkgmap file. +############################################## +######################################## +# Generating pathes for cygwin. +######################################## + +sub generate_cygwin_pathes +{ + my ($filesref) = @_; + + my ($tmpfilehandle, $tmpfilename) = tmpnam(); + open SOURCEPATHLIST, ">$tmpfilename" or die "oops...\n"; + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + print SOURCEPATHLIST "${$filesref}[$i]->{'sourcepath'}\n"; + } + close SOURCEPATHLIST; + my @cyg_sourcepathlist = qx{cygpath -w -f "$tmpfilename"}; + chomp @cyg_sourcepathlist; + unlink "$tmpfilename" or die "oops\n"; + for ( my $i = 0; $i <= $#{$filesref}; $i++ ) + { + ${$filesref}[$i]->{'cyg_sourcepath'} = $cyg_sourcepathlist[$i]; + } +} + + +sub filter_pkgmapfile +{ + my ($pkgmapfile) = @_; + + my @pkgmap = (); + + my $line = ": 1 10\n"; + push(@pkgmap, $line); + + for ( my $i = 0; $i <= $#{$pkgmapfile}; $i++ ) + { + $line = ${$pkgmapfile}[$i]; + if ( $line =~ /^\s*1\si\s/ ) { push(@pkgmap, $line); } + } + + return \@pkgmap; +} + +############################################## +# Creating double packages for Solaris x86. +# One package with ARCH=i386 and one with +# ARCH=i86pc. +############################################## + +sub fix_solaris_x86_patch +{ + my ($packagename, $subdir) = @_; + + # changing into directory of packages, important for soft linking + my $startdir = cwd(); + chdir($subdir); + + # $packagename is: "SUNWstaroffice-core01" + # Current working directory is: "<path>/install/en-US_inprogress" + + # create new folder in "packages": $packagename . ".i" + my $newpackagename = $packagename . "\.i"; + my $newdir = $newpackagename; + installer::systemactions::create_directory($newdir); + + # collecting all directories in the package + my $olddir = $packagename; + my $allsubdirs = installer::systemactions::get_all_directories_without_path($olddir); + + # link all directories from $packagename to $packagename . ".i" + for ( my $i = 0; $i <= $#{$allsubdirs}; $i++ ) + { + my $sourcedir = $olddir . $installer::globals::separator . ${$allsubdirs}[$i]; + my $destdir = $newdir . $installer::globals::separator . ${$allsubdirs}[$i]; + my $directory_depth = 2; # important for soft links, two directories already exist + installer::systemactions::softlink_complete_directory($sourcedir, $destdir, $directory_depth); + } + + # copy "pkginfo" and "pkgmap" from $packagename to $packagename . ".i" + my @allcopyfiles = ("pkginfo", "pkgmap"); + for ( my $i = 0; $i <= $#allcopyfiles; $i++ ) + { + my $sourcefile = $olddir . $installer::globals::separator . $allcopyfiles[$i]; + my $destfile = $newdir . $installer::globals::separator . $allcopyfiles[$i]; + installer::systemactions::copy_one_file($sourcefile, $destfile); + } + + # change in pkginfo in $packagename . ".i" the value for ARCH from i386 to i86pc + my $pkginfofilename = "pkginfo"; + $pkginfofilename = $newdir . $installer::globals::separator . $pkginfofilename; + + my $pkginfofile = installer::files::read_file($pkginfofilename); + set_old_architecture_string($pkginfofile); + installer::files::save_file($pkginfofilename, $pkginfofile); + + # adapt the values in pkgmap for pkginfo file, because this file was edited + my $pkgmapfilename = "pkgmap"; + $pkgmapfilename = $newdir . $installer::globals::separator . $pkgmapfilename; + + my $pkgmapfile = installer::files::read_file($pkgmapfilename); + set_pkginfo_line($pkgmapfile, $pkginfofilename); + installer::files::save_file($pkgmapfilename, $pkgmapfile); + + # changing back to startdir + chdir($startdir); +} + +################################################### +# Creating double core01 package for Solaris x86. +# One package with ARCH=i386 and one with +# ARCH=i86pc. This is necessary, to inform the +# user about the missing "small patch", if +# packages with ARCH=i86pc are installed. +################################################### + +sub fix2_solaris_x86_patch +{ + my ($packagename, $subdir) = @_; + + if ( $packagename =~ /-core01\s*$/ ) # only this one package needs to be duplicated + { + my $startdir = cwd(); + chdir($subdir); + + # $packagename is: "SUNWstaroffice-core01" + # Current working directory is: "<path>/install/en-US_inprogress" + + # create new package in "packages": $packagename . ".i" + my $olddir = $packagename; + my $newpackagename = $packagename . "\.i"; + my $newdir = $newpackagename; + + installer::systemactions::create_directory($newdir); + + my $oldinstalldir = $olddir . $installer::globals::separator . "install"; + my $newinstalldir = $newdir . $installer::globals::separator . "install"; + + installer::systemactions::copy_complete_directory($oldinstalldir, $newinstalldir); + + # setting time stamp of all copied files to avoid errors from pkgchk + my $allinstallfiles = installer::systemactions::get_all_files_from_one_directory_without_path($newinstalldir); + set_time_stamp($oldinstalldir, $newinstalldir, $allinstallfiles); + + # copy "pkginfo" and "pkgmap" from $packagename to $packagename . ".i" + my @allcopyfiles = ("pkginfo", "pkgmap"); + for ( my $i = 0; $i <= $#allcopyfiles; $i++ ) + { + my $sourcefile = $olddir . $installer::globals::separator . $allcopyfiles[$i]; + my $destfile = $newdir . $installer::globals::separator . $allcopyfiles[$i]; + installer::systemactions::copy_one_file($sourcefile, $destfile); + } + + # change in pkginfo in $packagename . ".i" the value for ARCH from i386 to i86pc + my $pkginfofilename = "pkginfo"; + $pkginfofilename = $newdir . $installer::globals::separator . $pkginfofilename; + + my $pkginfofile = installer::files::read_file($pkginfofilename); + set_old_architecture_string($pkginfofile); + check_requires_setting($pkginfofile); + installer::files::save_file($pkginfofilename, $pkginfofile); + + # adapt the values in pkgmap for pkginfo file, because this file was edited + my $pkgmapfilename = "pkgmap"; + $pkgmapfilename = $newdir . $installer::globals::separator . $pkgmapfilename; + + my $pkgmapfile = installer::files::read_file($pkgmapfilename); + set_pkginfo_line($pkgmapfile, $pkginfofilename); + $pkgmapfile = filter_pkgmapfile($pkgmapfile); + installer::files::save_file($pkgmapfilename, $pkgmapfile); + + # setting time stamp of all copied files to avoid errors from pkgchk + set_time_stamp($olddir, $newdir, \@allcopyfiles); + + # changing back to startdir + chdir($startdir); + } +} + +################################################ +# Files with flag HIDDEN get a dot at the +# beginning of the file name. This cannot be +# defined in scp2 project, because tooling +# cannot handle files with beginning dot +# correctly. +################################################ + +sub resolving_hidden_flag +{ + my ($filesarrayref, $variableshashref, $item, $languagestringref) = @_; + + my $diritem = lc($item); + my $infoline = ""; + + my $hiddendirbase = installer::systemactions::create_directories("hidden_$diritem", $languagestringref); + + installer::logger::include_header_into_logfile("$item with flag HIDDEN:"); + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + my $onefile = ${$filesarrayref}[$i]; + my $styles = ""; + + if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } + + if ( $styles =~ /\bHIDDEN\b/ ) + { + # Language specific subdirectory + + my $onelanguage = $onefile->{'specificlanguage'}; + + if ($onelanguage eq "") + { + $onelanguage = "00"; # files without language into directory "00" + } + + my $hiddendir = $hiddendirbase . $installer::globals::separator . $onelanguage . $installer::globals::separator; + installer::systemactions::create_directory($hiddendir); # creating language specific directories + + # copy files and edit them with the variables defined in the zip.lst + + my $onefilename = $onefile->{'Name'}; + my $newfilename = "\." . $onefilename; + my $sourcefile = $onefile->{'sourcepath'}; + my $destfile = $hiddendir . $newfilename; + + my $copysuccess = installer::systemactions::copy_one_file($sourcefile, $destfile); + + if ( $copysuccess ) + { + # $onefile->{'Name'} = $newfilename; + $onefile->{'sourcepath'} = $destfile; + $destination = $onefile->{'destination'}; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$destination); + if ( $destination eq "" ) { $onefile->{'destination'} = $newfilename; } + else { $onefile->{'destination'} = $destination . $installer::globals::separator . $newfilename; } + + $infoline = "Success: Using file with flag HIDDEN from \"$onefile->{'sourcepath'}\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Error: Failed to copy HIDDEN file from \"$sourcefile\" to \"$destfile\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + } + + $infoline = "\n"; + push( @installer::globals::logfileinfo, $infoline); +} + +################################################ +# Controlling that all keys in hash A are +# also key in hash B. +################################################ + +sub key_in_a_is_also_key_in_b +{ + my ( $hashref_a, $hashref_b) = @_; + + my $returnvalue = 1; + + my $key; + foreach $key ( keys %{$hashref_a} ) + { + if ( ! exists($hashref_b->{$key}) ) + { + print "*****\n"; + foreach $keyb ( keys %{$hashref_b} ) { print "$keyb : $hashref_b->{$keyb}\n"; } + print "*****\n"; + $returnvalue = 0; + } + } + + return $returnvalue; +} + +################################################ +# Setting all spellchecker languages +################################################ + +sub set_spellcheckerlanguages +{ + my ( $productlanguagesarrayref, $allvariables ) = @_; + + my %productlanguages = (); + for ( my $i = 0; $i <= $#{$productlanguagesarrayref}; $i++ ) { $productlanguages{${$productlanguagesarrayref}[$i]} = 1; } + + my $spellcheckfilename = $allvariables->{'SPELLCHECKERFILE'}; + + my $spellcheckfileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$spellcheckfilename, "", 1); + + if ($$spellcheckfileref eq "") { installer::exiter::exit_program("ERROR: Could not find $spellcheckfilename!", "set_spellcheckerlanguages"); } + + my $infoline = "Using spellchecker file: $$spellcheckfileref \n"; + push( @installer::globals::globallogfileinfo, $infoline); + + my $spellcheckfile = installer::files::read_file($$spellcheckfileref); + my %spellcheckhash = (); + + for ( my $j = 0; $j <= $#{$spellcheckfile}; $j++ ) + { + # Analyzing all "key=value" lines + my $oneline = ${$spellcheckfile}[$j]; + + if ( $oneline =~ /^\s*(\S+)\s*\=\s*\"(.*?)\"\s*$/ ) # no white space allowed in key + { + my $onelang = $1; + my $languagelist = $2; + $spellcheckhash{$onelang} = $languagelist; + + # Special handling for language packs. Do only include that one language of the language pack, no further language. + # And this only, if the language of the language pack is also already part of the language list + + if ( $installer::globals::languagepack ) + { + if ( $languagelist =~ /\b$onelang\b/ ) { $spellcheckhash{$onelang} = $onelang; } + else { $spellcheckhash{$onelang} = ""; } + } + } + } + + # Collecting all required languages in %installer::globals::spellcheckerlanguagehash + + foreach my $lang (keys %productlanguages) + { + my $languagelist = ""; + if ( exists($spellcheckhash{$lang}) ) { $languagelist = $spellcheckhash{$lang}; } + else { $languagelist = $spellcheckhash{'en-US'}; } # defaulting to English + + my $langlisthash = installer::converter::convert_stringlist_into_hash(\$languagelist, ","); + foreach my $onelang ( keys %{$langlisthash} ) { $installer::globals::spellcheckerlanguagehash{$onelang} = 1; } + } + + $installer::globals::analyze_spellcheckerlanguage = 1; + + # Logging + + my $langstring = ""; + foreach my $lang (sort keys %installer::globals::spellcheckerlanguagehash) { $langstring = $langstring . "," . $lang } + $langstring =~ s/^\s*,//; + + $infoline = "Collected spellchecker languages for spellchecker: $langstring \n"; + push( @installer::globals::globallogfileinfo, $infoline); +} + +################################################ +# Including a license text into setup script +################################################ + +sub put_license_into_setup +{ + my ($installdir, $includepatharrayref) = @_; + + # find and read english license file + my $licenselanguage = "en-US"; # always english ! + my $licensefilename = "LICENSE_" . $licenselanguage; + my $licenseincludepatharrayref = get_language_specific_include_pathes($includepatharrayref, $licenselanguage); + + my $licenseref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$licensefilename, $licenseincludepatharrayref, 0); + if ($$licenseref eq "") { installer::exiter::exit_program("ERROR: Could not find License file $licensefilename!", "put_license_into_setup"); } + my $licensefile = installer::files::read_file($$licenseref); + + # Read setup + my $setupfilename = $installdir . $installer::globals::separator . "setup"; + my $setupfile = installer::files::read_file($setupfilename); + + # Replacement + my $infoline = "Adding licensefile into setup script\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $includestring = ""; + for ( my $i = 0; $i <= $#{$licensefile}; $i++ ) { $includestring = $includestring . ${$licensefile}[$i]; } + for ( my $i = 0; $i <= $#{$setupfile}; $i++ ) { ${$setupfile}[$i] =~ s/LICENSEFILEPLACEHOLDER/$includestring/; } + + # Write setup + installer::files::save_file($setupfilename, $setupfile); +} + +################################################ +# Setting global path to getuid.so library +################################################ + +sub set_getuid_path +{ + my ($includepatharrayref) = @_; + + my $getuidlibraryname = "getuid.so"; + my $getuidlibraryref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$getuidlibraryname, $includepatharrayref, 0); + if ($$getuidlibraryref eq "") { installer::exiter::exit_program("ERROR: Could not find $getuidlibraryname!", "set_getuid_path"); } + + $installer::globals::getuidpath = $$getuidlibraryref; + $installer::globals::getuidpathset = 1; +} + +######################################################### +# Create a tar file from the binary package +######################################################### + +sub tar_package +{ + my ( $installdir, $packagename, $tarfilename, $getuidlibrary) = @_; + + my $ldpreloadstring = ""; + if ( $getuidlibrary ne "" ) { $ldpreloadstring = "LD_PRELOAD=" . $getuidlibrary; } + + my $systemcall = "cd $installdir; $ldpreloadstring tar -cf - $packagename > $tarfilename"; + # my $systemcall = "cd $installdir; $ldpreloadstring tar -cf - * > $tarfilename"; + + my $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + my $localcall = "chmod 775 $tarfilename \>\/dev\/null 2\>\&1"; + $returnvalue = system($localcall); + + my $fulltarfile = $installdir . $installer::globals::separator . $tarfilename; + my $filesize = ( -s $fulltarfile ); + + return $filesize; +} + +######################################################### +# Create a tar file from the binary package +######################################################### + +sub untar_package +{ + my ( $installdir, $tarfilename, $getuidlibrary) = @_; + + my $ldpreloadstring = ""; + if ( $getuidlibrary ne "" ) { $ldpreloadstring = "LD_PRELOAD=" . $getuidlibrary; } + + my $systemcall = "cd $installdir; $ldpreloadstring tar -xf $tarfilename"; + + my $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: Executed \"$systemcall\" successfully!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + my $localcall = "chmod 775 $tarfilename \>\/dev\/null 2\>\&1"; + $returnvalue = system($localcall); +} + +######################################################### +# Shuffle an array (Fisher Yates shuffle) +######################################################### + +sub shuffle_array +{ + my ( $arrayref ) = @_; + + # my $counter = 0; + # my $infoline = "Old package order: \n"; + # push( @installer::globals::logfileinfo, $infoline); + # foreach my $onepackage ( @{$arrayref} ) + # { + # $counter++; + # $infoline = "$counter: $onepackage->{'module'}\n"; + # push( @installer::globals::logfileinfo, $infoline); + # } + + my $i = @$arrayref; + while (--$i) + { + my $j = int rand ($i+1); + @$arrayref[$i,$j] = @$arrayref[$j,$i]; + } + + # $counter = 0; + # $infoline = "New package order: \n"; + # push( @installer::globals::logfileinfo, $infoline); + # foreach my $onepackage ( @{$arrayref} ) + # { + # $counter++; + # $infoline = "$counter: $onepackage->{'module'}\n"; + # push( @installer::globals::logfileinfo, $infoline); + # } +} + +################################################ +# Defining the English license text to add +# it into Solaris packages. +################################################ + +sub set_english_license +{ + my $additional_license_name = $installer::globals::englishsolarislicensename; # always the English file + my $licensefileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$additional_license_name, "" , 0); + if ( $$licensefileref eq "" ) { installer::exiter::exit_program("ERROR: Could not find license file $additional_license_name!", "set_english_license"); } + $installer::globals::englishlicenseset = 1; + $installer::globals::englishlicense = installer::files::read_file($$licensefileref); + installer::scpzipfiles::replace_all_ziplistvariables_in_file($installer::globals::englishlicense, $variableshashref); +} + +############################################## +# Setting time stamp of copied files to avoid +# errors from pkgchk. +############################################## + +sub set_time_stamp_for_file +{ + my ($sourcefile, $destfile) = @_; + + my $systemcall = "touch -r $sourcefile $destfile"; + + my $returnvalue = system($systemcall); + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ($returnvalue) + { + $infoline = "ERROR: \"$systemcall\" failed!\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Success: \"$systemcall\" !\n"; + push( @installer::globals::logfileinfo, $infoline); + } +} + +############################################## +# Setting checksum and wordcount for changed +# pkginfo file into pkgmap. +############################################## + +sub change_onefile_in_pkgmap +{ + my ($pkgmapfile, $fullfilename, $shortfilename) = @_; + + # 1 i pkginfo 442 34577 1166716297 + # -> + # 1 i pkginfo 443 34737 1166716297 + # + # wc -c pkginfo | cut -f6 -d' ' -> 442 (variable) + # sum pkginfo | cut -f1 -d' ' -> 34577 (variable) + # grep 'pkginfo' pkgmap | cut -f6 -d' ' -> 1166716297 (fix) + + my $checksum = call_sum($fullfilename); + if ( $checksum =~ /^\s*(\d+)\s+.*$/ ) { $checksum = $1; } + + my $wordcount = call_wc($fullfilename); + if ( $wordcount =~ /^\s*(\d+)\s+.*$/ ) { $wordcount = $1; } + + for ( my $i = 0; $i <= $#{$pkgmapfile}; $i++ ) + { + if ( ${$pkgmapfile}[$i] =~ /(^.*\b\Q$shortfilename\E\b\s+)(\d+)(\s+)(\d+)(\s+)(\d+)(\s*$)/ ) + { + my $newline = $1 . $wordcount . $3 . $checksum . $5 . $6 . $7; + ${$pkgmapfile}[$i] = $newline; + last; + } + } +} + +################################################ +# Adding the content of the English license +# file into the system integration packages. +################################################ + +sub add_license_into_systemintegrationpackages +{ + my ($destdir, $packages) = @_; + + for ( my $i = 0; $i <= $#{$packages}; $i++ ) + { + my $copyrightfilename = ${$packages}[$i] . $installer::globals::separator . "install" . $installer::globals::separator . "copyright"; + if ( ! -f $copyrightfilename ) { installer::exiter::exit_program("ERROR: Could not find license file in system integration package: $copyrightfilename!", "add_license_into_systemintegrationpackages"); } + my $copyrightfile = installer::files::read_file($copyrightfilename); + + # Saving time stamp of old copyrightfile + my $savcopyrightfilename = $copyrightfilename . ".sav"; + installer::systemactions::copy_one_file($copyrightfilename, $savcopyrightfilename); + set_time_stamp_for_file($copyrightfilename, $savcopyrightfilename); # now $savcopyrightfile has the time stamp of $copyrightfile + + # Adding license content to copyright file + push(@{$copyrightfile}, "\n"); + for ( my $i = 0; $i <= $#{$installer::globals::englishlicense}; $i++ ) { push(@{$copyrightfile}, ${$installer::globals::englishlicense}[$i]); } + installer::files::save_file($copyrightfilename, $copyrightfile); + + # Setting the old time stamp saved with $savcopyrightfilename + set_time_stamp_for_file($savcopyrightfilename, $copyrightfilename); # now $copyrightfile has the time stamp of $savcopyrightfile + unlink($savcopyrightfilename); + + # Changing content of copyright file in pkgmap + my $pkgmapfilename = ${$packages}[$i] . $installer::globals::separator . "pkgmap"; + if ( ! -f $pkgmapfilename ) { installer::exiter::exit_program("ERROR: Could not find pkgmap in system integration package: $pkgmapfilename!", "add_license_into_systemintegrationpackages"); } + my $pkgmap = installer::files::read_file($pkgmapfilename); + change_onefile_in_pkgmap($pkgmap, $copyrightfilename, "copyright"); + installer::files::save_file($pkgmapfilename, $pkgmap); + } +} + +######################################################### +# Collecting all pkgmap files from an installation set +######################################################### + +sub collectpackagemaps +{ + my ( $installdir, $languagestringref, $allvariables ) = @_; + + installer::logger::include_header_into_logfile("Collecing all packagemaps (pkgmap):"); + + my $pkgmapdir = installer::systemactions::create_directories("pkgmap", $languagestringref); + my $subdirname = $allvariables->{'UNIXPRODUCTNAME'} . "_pkgmaps"; + my $pkgmapsubdir = $pkgmapdir . $installer::globals::separator . $subdirname; + if ( -d $pkgmapsubdir ) { installer::systemactions::remove_complete_directory($pkgmapsubdir); } + if ( ! -d $pkgmapsubdir ) { installer::systemactions::create_directory($pkgmapsubdir); } + + $installdir =~ s/\/\s*$//; + # Collecting all packages in $installdir and its sub package ("packages") + my $searchdir = $installdir . $installer::globals::separator . $installer::globals::epmoutpath; + + my $allpackages = installer::systemactions::get_all_directories_without_path($searchdir); + + for ( my $i = 0; $i <= $#{$allpackages}; $i++ ) + { + my $pkgmapfile = $searchdir . $installer::globals::separator . ${$allpackages}[$i] . $installer::globals::separator . "pkgmap"; + my $destfilename = $pkgmapsubdir . $installer::globals::separator . ${$allpackages}[$i] . "_pkgmap"; + installer::systemactions::copy_one_file($pkgmapfile, $destfilename); + } + + # Create a tar gz file with all package maps + my $tarfilename = $subdirname . ".tar"; + my $targzname = $tarfilename . ".gz"; + # my $systemcall = "cd $pkgmapdir; tar -cf - $subdirname > $tarfilename"; + $systemcall = "cd $pkgmapdir; tar -cf - $subdirname | gzip > $targzname"; + make_systemcall($systemcall); + installer::systemactions::remove_complete_directory($pkgmapsubdir, 1); +} + +1; diff --git a/solenv/bin/modules/installer/xpdinstaller.pm b/solenv/bin/modules/installer/xpdinstaller.pm new file mode 100644 index 000000000000..6611012985be --- /dev/null +++ b/solenv/bin/modules/installer/xpdinstaller.pm @@ -0,0 +1,1732 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: xpdinstaller.pm,v $ +# +# $Revision: 1.19 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +package installer::xpdinstaller; + +use Cwd; +use installer::converter; +use installer::exiter; +use installer::globals; +use installer::languages; +use installer::logger; +use installer::pathanalyzer; +use installer::remover; +use installer::systemactions; + + +####################################################### +# Searching for the module name and description in the +# modules collector +####################################################### + +sub get_module_name_description +{ + my ($modulesarrayref, $onelanguage, $gid, $type) = @_; + + my $found = 0; + + my $newstring = ""; + + for ( my $i = 0; $i <= $#{$modulesarrayref}; $i++ ) + { + my $onemodule = ${$modulesarrayref}[$i]; + + if ( $onemodule->{'gid'} eq $gid ) + { + my $typestring = $type . " " . "(" . $onelanguage . ")"; + if ( $onemodule->{$typestring} ) { $newstring = $onemodule->{$typestring}; } + $found = 1; + } + + if ( $found ) { last; } + } + + # defaulting to english + + if ( ! $found ) + { + my $defaultlanguage = "en-US"; + + for ( my $i = 0; $i <= $#{$modulesarrayref}; $i++ ) + { + my $onemodule = ${$modulesarrayref}[$i]; + + if ( $onemodule->{'gid'} eq $gid ) + { + my $typestring = $type . " " . "(" . $defaultlanguage . ")"; + if ( $onemodule->{$typestring} ) { $newstring = $onemodule->{$typestring}; } + $found = 1; + } + + if ( $found ) { last; } + } + } + + return $newstring; +} + +################################################### +# Finding module, specified by the gid +################################################### + +sub get_module +{ + my ($modulegid, $modulesarrayref) = @_; + + my $found = 0; + my $searchmodule = ""; + + for ( my $i = 0; $i <= $#{$modulesarrayref}; $i++ ) + { + my $onemodule = ${$modulesarrayref}[$i]; + + if ( $onemodule->{'gid'} eq $modulegid ) + { + $searchmodule = $onemodule; + $found = 1; + last; + } + + # if ( ! $found ) { installer::exiter::exit_program("ERROR: Could not find module belonging to gid $modulegid!", "get_module (xpdinstaller)"); } + } + + return $searchmodule; +} + +################################################### +# Creating package start tag +################################################### + +sub get_package_tag +{ + my ( $module, $indent, $linkpackage ) = @_; + + my $modulegid = $module->{'gid'}; + if ( $linkpackage ) { $modulegid = $modulegid . "u"; } + my $parentgid = ""; + if ( $module->{'ParentID'} ) { $parentgid = $module->{'ParentID'}; } + if ( $parentgid eq "" ) { $parentgid = "root"; } + if ( $module->{'XPDParentID'} ) { $parentgid = $module->{'XPDParentID'}; } # changing parent of "Prg" and "Opt" to "root" + + my $tag = $indent . "<package " . "name=" . "\"" . $modulegid . "\" " . "parent=" . "\"" . $parentgid . "\">" . "\n"; + + return ( $tag, $parentgid ); +} + +################################################### +# Creating display start tag +################################################### + +sub get_display_tag +{ + my ( $module, $indent ) = @_; + + # Styles=(HIDDEN_ROOT) + my $styles = ""; + my $type = ""; + if ( $module->{'Styles'} ) { $styles = $module->{'Styles'}; } + if ( $styles =~ /\bHIDDEN_ROOT\b/ ) { $type = "hidden"; } + else { $type = "show"; } + + # special handling for language modules. Only visible in multilingual installation set. + if (( $styles =~ /\bSHOW_MULTILINGUAL_ONLY\b/ ) && ( ! $installer::globals::ismultilingual )) { $type = "hidden"; } + + # special handling for the root module, which has no parent + my $parentgid = ""; + if ( $module->{'ParentID'} ) { $parentgid = $module->{'ParentID'}; } + if ( $parentgid eq "" ) { $type = "hidden"; } + + my $tag = $indent . "<display " . "type=" . "\"" . $type . "\"" . ">" . "\n"; + + return $tag; +} + +################################################### +# Creating installunit start tag +################################################### + +sub get_installunit_tag +{ + my ( $indent ) = @_; + + my $type = $installer::globals::packageformat; + + my $tag = $indent . "<installunit " . "type=" . "\"" . $type . "\"" . ">" . "\n"; + + return $tag; +} + +################################################### +# Creating simple start tags +################################################### + +sub get_start_tag +{ + my ( $tag, $indent ) = @_; + + my $starttag = $indent . "<" . $tag . ">" . "\n"; + return $starttag; +} + +################################################### +# Creating end tags +################################################### + +sub get_end_tag +{ + my ( $tag, $indent ) = @_; + + my $endtag = $indent . "</" . $tag . ">" . "\n"; + return $endtag; +} + +################################################### +# Creating simple complete tag +################################################### + +sub get_tag_line +{ + my ( $indent, $name, $value ) = @_; + $value = '' unless defined $value; + + my $line = $indent . "<" . $name . ">" . $value . "</" . $name . ">" . "\n"; + +} + +################################################### +# Asking module for sortkey entry +################################################### + +sub get_sortkey_value +{ + my ( $module ) = @_; + + my $value = "9999"; + + if ( $module->{'Sortkey'} ) { $value = $module->{'Sortkey'}; } + + return $value; +} + +################################################### +# Asking module for default entry +################################################### + +sub get_default_value +{ + my ( $module ) = @_; + + my $value = ""; + + if ( $module->{'Default'} ) { $value = $module->{'Default'}; } # is YES or NO + + if ( $value =~ /\bNO\b/i ) { $value = "false"; } + else { $value = "true"; } + + return $value; +} + +################################################### +# Asking module for showinuserinstall entry +# scp style: DONTSHOWINUSERINSTALL +################################################### + +sub get_showinuserinstall_value +{ + my ( $module ) = @_; + + my $value = "true"; + + my $styles = ""; + if ( $module->{'Styles'} ) { $styles = $module->{'Styles'}; } + if ( $styles =~ /\bDONTSHOWINUSERINSTALL\b/ ) { $value = "false"; } + + return $value; +} + +################################################### +# Asking module for showinuserinstall entry +# scp style: USERINSTALLONLY +################################################### + +sub get_userinstallonly_value +{ + my ( $module ) = @_; + + my $value = "false"; + + my $styles = ""; + if ( $module->{'Styles'} ) { $styles = $module->{'Styles'}; } + if ( $styles =~ /\bUSERINSTALLONLY\b/ ) { $value = "true"; } + + return $value; +} + +################################################### +# Asking module for dontuninstall entry +# scp style: DONTUNINSTALL +################################################### + +sub get_dontuninstall_value +{ + my ( $module ) = @_; + + my $value = "false"; + + my $styles = ""; + if ( $module->{'Styles'} ) { $styles = $module->{'Styles'}; } + if ( $styles =~ /\bDONTUNINSTALL\b/ ) { $value = "true"; } + + return $value; +} + +################################################### +# Asking module for XpdCheckSolaris entry +# (belongs to scp module) +################################################### + +sub get_checksolaris_value +{ + my ( $module ) = @_; + + my $value = ""; + if ( $module->{'XpdCheckSolaris'} ) { $value = $module->{'XpdCheckSolaris'}; } + + return $value; +} + +################################################### +# Asking module for isupdatepackage entry +# scp style: ISUPDATEPACKAGE +################################################### + +sub get_isupdatepackage_value +{ + my ( $module ) = @_; + + my $value = "false"; + + my $styles = ""; + if ( $module->{'Styles'} ) { $styles = $module->{'Styles'}; } + if ( $styles =~ /\bISUPDATEPACKAGE\b/ ) { $value = "true"; } + + return $value; +} + +################################################### +# Asking module for showmultilingualonly entry +# scp style: SHOW_MULTILINGUAL_ONLY +################################################### + +sub get_showmultilingualonly_value +{ + my ( $module ) = @_; + + my $value = "false"; + + my $styles = ""; + if ( $module->{'Styles'} ) { $styles = $module->{'Styles'}; } + if ( $styles =~ /\bSHOW_MULTILINGUAL_ONLY\b/ ) { $value = "true"; } + + return $value; +} + +################################################### +# Asking module for showmultilingualonly entry +# scp style: SHOW_MULTILINGUAL_ONLY +################################################### + +sub get_applicationmodule_value +{ + my ( $module ) = @_; + + my $value = "false"; + + my $styles = ""; + if ( $module->{'Styles'} ) { $styles = $module->{'Styles'}; } + if ( $styles =~ /\bAPPLICATIONMODULE\b/ ) { $value = "true"; } + + return $value; +} + +################################################### +# Asking module for java module entry +# scp style: JAVAMODULE +################################################### + +sub get_isjavamodule_value +{ + my ( $module ) = @_; + + my $value = "false"; + + my $styles = ""; + if ( $module->{'Styles'} ) { $styles = $module->{'Styles'}; } + if ( $styles =~ /\bJAVAMODULE\b/ ) { $value = "true"; } + + return $value; +} + +##################################################################### +# Asking module, if installation shall use --force +# scp style: USEFORCE (Linux only) +##################################################################### + +sub get_useforce_value +{ + my ( $module ) = @_; + + my $value = "false"; + + my $styles = ""; + if ( $module->{'Styles'} ) { $styles = $module->{'Styles'}; } + if ( $styles =~ /\bUSEFORCE\b/ ) { $value = "true"; } + + return $value; +} + +################################################### +# Asking module, if installation can fail +# scp style: INSTALLCANFAIL +################################################### + +sub get_installcanfail_value +{ + my ( $module ) = @_; + + my $value = "false"; + + my $styles = ""; + if ( $module->{'Styles'} ) { $styles = $module->{'Styles'}; } + if ( $styles =~ /\bINSTALLCANFAIL\b/ ) { $value = "true"; } + + return $value; +} + +################################################### +# Asking module, if installation can fail +# scp style: INSTALLCANFAIL +################################################### + +sub get_forceintoupdate_value +{ + my ( $module ) = @_; + + my $value = "false"; + + my $styles = ""; + if ( $module->{'Styles'} ) { $styles = $module->{'Styles'}; } + if ( $styles =~ /\bFORCEINTOUPDATE\b/ ) { $value = "true"; } + + return $value; +} + +################################################### +# Substituting all occurences of "\uUXYZ" by +# "&#xUXYZ;", because the use xml saxparser does +# not know anything about this encoding. Therfore +# the xml file can keep standard encoding "UTF-8" +# and all strings with "\uUXYZ" do not need to +# be converted from the Java installer. +################################################### + +sub replace_javaencoding_in_string +{ + my ( $string ) = @_; + + while ( $string =~ /(\\u\w\w\w\w)/ ) + { + my $oldvalue = $1; + my $newvalue = ""; + if ( $oldvalue =~ /\\u(\w\w\w\w)/ ) + { + my $number = $1; + $newvalue = "&#x" . $number . ";"; + } + + $string =~ s/\Q$oldvalue\E/$newvalue/; + } + + return $string; +} + +################################################### +# Collecting language dependent entries from scp +# (Name and Description) +################################################### + +sub collect_lang_values +{ + my ($indent, $module, $xpdfile, $searchentry, $saveentry) = @_; + + foreach $key (keys %{$module}) + { + my $write_line = 0; + my $javalanguage = ""; + + if ( $key =~ /^\s*\Q$searchentry\E\s+\((\S+)\)\s*$/ ) # this are the language dependent keys + { + $language = $1; + $javalanguage = installer::languages::get_java_language($language); + $write_line = 1; + } + elsif ( $key =~ /^\s*\Q$searchentry\E\s*$/ ) # this are the language independent keys + { + $javalanguage = "en_US"; + $write_line = 1; + } + + if ( $write_line ) + { + my $value = $module->{$key}; + $value = replace_javaencoding_in_string($value); + my $line = $indent . "<" . $saveentry . " lang=" . "\"" . $javalanguage . "\"" . ">" . $value . "<\/" . $saveentry . ">" . "\n"; + push(@{$xpdfile}, $line); + } + } +} + +################################################### +# Removing language dependent entries from +# module hash (Name and Description) +################################################### + +sub remove_lang_values +{ + my ($module, $searchentry) = @_; + + my $key = ""; + + foreach $key (keys %{$module}) + { + if ( $key =~ /^\s*\Q$searchentry\E\s+\((\S+)\)\s*$/ ) # this are the language dependent keys + { + delete($module->{$key}); + } + } +} + +################################################### +# Setting package install order +################################################### + +sub get_order_value +{ + my ( $module ) = @_; + + my $value = "1000"; # Setting the default value + + if ( $module->{'InstallOrder'} ) { $value = $module->{'InstallOrder'}; } + + return $value; +} + +################################################### +# Checking size of package +################################################### + +sub get_size_value +{ + my ( $packagename, $xpdinfo ) = @_; + + my $value = ""; + + if ( $xpdinfo->{'FileSize'} ) + { + $value = $xpdinfo->{'FileSize'}; + return $value; + } + + my $isrpmfile = 0; + if ( $packagename =~ /\.rpm\s*$/ ) { $isrpmfile = 1; } + + if (( $installer::globals::islinuxrpmbuild ) && ( $isrpmfile )) + { + # if ( ! $installer::globals::rpmquerycommand ) { installer::exiter::exit_program("ERROR: rpm not found for querying packages!", "get_size_value"); } + if ( ! $installer::globals::rpmquerycommand ) { $installer::globals::rpmquerycommand = "rpm"; } # For queries "rpm" is used, not "rpmbuild" + + my $systemcall = "$installer::globals::rpmquerycommand -qp --queryformat \"\[\%\{FILESIZES\}\\n\]\" $packagename 2\>\&1 |"; + my $rpmout = make_systemcall($systemcall, 0); + $value = do_sum($rpmout); # adding all filesizes in bytes + $value = $value/1000; + + my $ganzzahl = int $value; + if ($ganzzahl < $value) { $value = $ganzzahl + 1; } + else { $value = $ganzzahl; } + + my $rpmname = $packagename; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$rpmname); + $infoline = "Filesize $rpmname : $value\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + if ( $installer::globals::issolarispkgbuild ) + { + my $filename = "pkgmap"; + $filename = $packagename . $installer::globals::separator . $filename; + $file = installer::files::read_file($filename); + + for ( my $i = 0; $i <= $#{$file}; $i++ ) + { + my $line = ${$file}[$i]; + if ( $line =~ /^\s*\:\s+\d+\s+(\d+?)\s+/ ) + { + $value = $1; + if ( ! ( $value%2 == 0 )) { $value = $value + 1; } + $value = $value/2; # not blocks, but kB + last; + } + } + } + + if ( $value eq "" ) { $value = "0"; } + + return $value; +} + +################################################### +# Checking md5 of package +################################################### + +sub get_md5_value +{ + my ( $packagename, $xpdinfo ) = @_; + + my $value = ""; + + if ( $xpdinfo->{'md5sum'} ) + { + $value = $xpdinfo->{'md5sum'}; + return $value; + } + + if ( $installer::globals::islinuxrpmbuild ) + { + my $md5file = "/usr/bin/md5sum"; + + if ( -x $md5file ) + { + my $systemcall = "$md5file $packagename 2\>\&1 |"; + my $md5out = make_systemcall($systemcall, 1); + $value = ${$md5out}[0]; + if ( $value =~ /^\s*(\S+?)\s+.*$/ ) + { + $value = $1; + } + + my $rpmname = $packagename; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$rpmname); + $infoline = "md5sum of $rpmname : $value\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + + return $value; +} + +################################################### +# Checking name of package +################################################### + +sub get_name_value +{ + my ( $packagename ) = @_; + + my $value = $packagename; + + # $packagename contains the complete path to the package + # Only the name of file or directory is required + + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$value); + + return $value; +} + +################################################### +# Checking full package name (Linux only) +################################################### + +sub get_fullpkgname_value +{ + my ( $packagename, $xpdinfo ) = @_; + + my $value = ""; + my $isrpmfile = 0; + if ( $packagename =~ /\.rpm\s*$/ ) { $isrpmfile = 1; } + + if (( $installer::globals::islinuxrpmbuild ) && ( $isrpmfile )) + { + if ( $xpdinfo->{'FullPackageName'} ) + { + $value = $xpdinfo->{'FullPackageName'}; + return $value; + } + + # if ( ! $installer::globals::rpmquerycommand ) { installer::exiter::exit_program("ERROR: rpm not found for querying packages!", "get_fullpkgname_value"); } + if ( ! $installer::globals::rpmquerycommand ) { $installer::globals::rpmquerycommand = "rpm"; } # For queries "rpm" is used, not "rpmbuild" + my $systemcall = "$installer::globals::rpmquerycommand -qp $packagename |"; + my $returnarray = make_systemcall($systemcall, 0); + $value = ${$returnarray}[0]; + installer::remover::remove_leading_and_ending_whitespaces(\$value); + + my $rpmname = $packagename; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$rpmname); + + $infoline = "Full package name from $rpmname: $value\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + return $value; +} + +################################################### +# Checking package version (Solaris only) +################################################### + +sub get_pkgversion_value +{ + my ( $completepackagename, $xpdinfo ) = @_; + + my $value = ""; + + if ( $xpdinfo->{'PkgVersion'} ) + { + $value = $xpdinfo->{'PkgVersion'}; + return $value; + } + + if ( $installer::globals::issolarispkgbuild ) + { + my $pkgfile = "pkgparam"; + my $packagepath = $completepackagename; + installer::pathanalyzer::get_path_from_fullqualifiedname(\$packagepath); + + my $packagename = $completepackagename; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$packagename); + + my $systemcall = "$pkgfile -d $packagepath $packagename param VERSION 2\>\&1 |"; + my $returnarray = make_systemcall($systemcall, 0); + + $value = ${$returnarray}[0]; + installer::remover::remove_leading_and_ending_whitespaces(\$value); + } + + return $value; +} + +################################################### +# Writing subdirectory into xpd file +################################################### + +sub get_subdir_value +{ + my ( $packagename, $subdir, $module ) = @_; + + my $value = ""; + + if ( $subdir ) { $value = $subdir; } + + if ( $module->{'Subdir'} ) { $value = $module->{'Subdir'}; } + + return $value; +} + +################################################### +# Checking if package is relocatable +################################################### + +sub get_relocatable_value +{ + my ( $module ) = @_; + + my $value = "true"; + + my $styles = ""; + if ( $module->{'Styles'} ) { $styles = $module->{'Styles'}; } + if ( $styles =~ /\bNOTRELOCATABLE\b/ ) { $value = "false"; } + + return $value; +} + +################################################### +# Checking if package is relocatable +################################################### + +sub get_languagespecific_value +{ + my ( $islanguagemodule ) = @_; + + my $value = "false"; + + if ( defined $islanguagemodule && $islanguagemodule == 1 ) { $value = "true"; } + + return $value; +} + +####################################################### +# Adding the values of the array +####################################################### + +sub do_sum +{ + my ( $allnumbers ) = @_; + + my $sum = 0; + + for ( my $i = 0; $i <= $#{$allnumbers}; $i++ ) + { + $sum = $sum + ${$allnumbers}[$i]; + } + + return $sum; +} + +####################################################### +# Executing one system call +####################################################### + +sub make_systemcall +{ + my ( $systemcall, $logreturn ) = @_; + + my @returns = (); + + installer::logger::print_message( "... $systemcall ...\n" ); + + open (REG, "$systemcall"); + while (<REG>) {push(@returns, $_); } + close (REG); + + my $returnvalue = $?; # $? contains the return value of the systemcall + + my $infoline = "Systemcall: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ( $logreturn ) + { + for ( my $j = 0; $j <= $#returns; $j++ ) { push( @installer::globals::logfileinfo, "$returns[$j]"); } + } + + if ($returnvalue) + { + $infoline = "ERROR: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + $error_occured = 1; + } + else + { + $infoline = "SUCCESS: $systemcall\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + return \@returns; +} + +################################################### +# Setting product name tag +################################################### + +sub get_product_tag +{ + my ($allvariables, $indent) = @_; + + my $productname = $allvariables->{'LCONEWORDPRODUCTNAME'}; + my $tag = $indent . "<product " . "name=" . "\"" . $productname . "\">" . "\n"; + + return $tag; +} + +################################################### +# Macro tags +################################################### + +sub set_macro_tag +{ + my ($allvariables, $indent, $key) = @_; + + my $property = ""; + my $value = ""; + + if ( $key eq "product_name" ) { $property = "PRODUCTNAME"; } + elsif ( $key eq "product_version" ) { $property = "PRODUCTVERSION"; } + elsif ( $key eq "product_suffix" ) { $property = "PRODUCTEXTENSION"; } + elsif ( $key eq "product_fullname" ) { $property = "FULLPRODUCTNAME"; } + + if (( $property eq "PRODUCTNAME" ) || ( $property eq "PRODUCTVERSION" ) || ( $property eq "PRODUCTEXTENSION" )) + { + $value = $allvariables->{$property}; + } + + if ( $property eq "FULLPRODUCTNAME" ) + { + $value = $allvariables->{"PRODUCTNAME"} . " " . $allvariables->{"PRODUCTVERSION"}; + if ( $allvariables->{"PRODUCTEXTENSION"} ) { $value = $value . " " . $allvariables->{"PRODUCTEXTENSION"}; } + } + + my $tag = $indent . "<macro " . "key=" . "\"" . $key . "\">" . $value . "\<\/macro\>" . "\n"; + + return $tag; + +} + +################################################### +# Setting the minor of the product version +# Required to check for Major Upgrades. +################################################### + +sub set_minor_tag +{ + my ($allvariables, $indent) = @_; + + my $productminor = 0; + if ( $allvariables->{"PACKAGEVERSION"} ) + { + if ( $allvariables->{"PACKAGEVERSION"} =~ /^\s*\d+\.(\d+)/ ) { $productminor = $1; } + } + my $tag = $indent . "<productminor>" . $productminor . "</productminor>" . "\n"; + + return $tag; +} + +################################################### +# Setting the update behaviour +################################################### + +sub set_update_tag +{ + my ($allvariables, $indent) = @_; + + my $updateflag = "false"; + if ( $allvariables->{"DONTUPDATE"} ) { $updateflag = "true"; } + my $tag = $indent . "<dontupdate>" . $updateflag . "</dontupdate>" . "\n"; + + return $tag; +} + +################################################### +# Setting the license dialog behaviour +################################################### + +sub set_hideeula_tag +{ + my ($allvariables, $indent) = @_; + + my $hidelicenseflag = "false"; + if ( $allvariables->{"HIDELICENSEDIALOG"} ) { $hidelicenseflag = "true"; } + my $tag = $indent . "<hideeula>" . $hidelicenseflag . "</hideeula>" . "\n"; + + return $tag; +} + +################################################### +# Setting default directory +################################################### + +sub set_defaultdir_tag +{ + my ($allvariables, $indent) = @_; + + my $defaultdir = ""; + if ( $allvariables->{"DEFAULTDESTPATH"} ) { $defaultdir = $allvariables->{"DEFAULTDESTPATH"}; } + my $tag = $indent . "<defaultdir>" . $defaultdir . "</defaultdir>" . "\n"; + + return $tag; +} + +################################################### +# Setting product directory +################################################### + +sub set_productdir_tag +{ + my ($allvariables, $indent) = @_; + + my $productdir = ""; + if ( $allvariables->{"UNIXPRODUCTNAME"} ) + { + $productdir = $allvariables->{"UNIXPRODUCTNAME"}; + + if ( $allvariables->{"BRANDPACKAGEVERSION"} ) + { + $productdir = $productdir . $allvariables->{"BRANDPACKAGEVERSION"}; +# if ( $allvariables->{"LCPRODUCTEXTENSION"} ) { $productdir = $productdir . $allvariables->{"LCPRODUCTEXTENSION"}; } + } + else + { + if ( $allvariables->{"PRODUCTVERSION"} ) + { + $productdir = $productdir . $allvariables->{"PRODUCTVERSION"}; + } + } + } + my $tag = $indent . "<productdir>" . $productdir . "</productdir>" . "\n"; + + return $tag; +} + +##################################################### +# Setting the package directory in installation set +##################################################### + +sub set_packagedir_tag +{ + my ($indent) = @_; + + my $tag = $indent . "<packagedirectory>" . $installer::globals::epmoutpath . "</packagedirectory>" . "\n"; + + return $tag; +} + +################################################### +# Setting the packagetype of installation set +################################################### + +sub set_packagetype_tag +{ + my ($indent) = @_; + + my $tag = $indent . "<packageformat>" . $installer::globals::packageformat . "</packageformat>" . "\n"; + + return $tag; +} + +################################################### +# Setting the architecture of installation set +################################################### + +sub set_architecture_tag +{ + my ($indent) = @_; + + my $architecture = ""; + if ( $installer::globals::issolarissparcbuild ) { $architecture = "sparc"; } + if ( $installer::globals::issolarisx86build ) { $architecture = "i386"; } + + my $tag = $indent . "<architecture>" . $architecture . "</architecture>" . "\n"; + + return $tag; +} + +################################################### +# Setting the multi language tag +################################################### + +sub set_multilanguage_tag +{ + my ($indent) = @_; + + my $value = "false"; + if ( $installer::globals::ismultilingual == 1 ) { $value = "true"; } + + my $tag = $indent . "<multilingual>" . $value . "</multilingual>" . "\n"; + + return $tag; +} + +################################################### +# Setting the language tag +################################################### + +sub set_language_tag +{ + my ($languagestringref, $indent) = @_; + + my $tag = $indent . "<languages>" . $$languagestringref . "</languages>" . "\n"; + + return $tag; +} + +################################################### +# Collecting content for product xpd file +################################################### + +# <?xml version='1.0' encoding='utf-8'?> +# +# <!-- General application description --> +# +# <product name="openoffice"> +# <macro key="product_name">Sun OpenOffice.org</macro> +# <macro key="product_version">1.0</macro> +# <macro key="product_suffix">Mephisto</macro> +# <macro key="product_fullname">Sun OpenOffice.org 1.0 Mephisto</macro> +# <defaultdir>/opt/Sun/OpenOffice.org-Mephisto</defaultdir> +# </product> + +sub get_setup_file_content +{ + my ($allvariables, $languagestringref) = @_; + + my @xpdfile = (); + my $noindent = ""; + my $singleindent = " "; + + my $line = "<?xml version='1.0' encoding='utf-8'?>\n\n"; + push(@xpdfile, $line); + $line = "<!-- General application description -->\n\n"; + push(@xpdfile, $line); + + my $tag = get_product_tag($allvariables, $noindent); + push(@xpdfile, $tag); + + $tag = set_macro_tag($allvariables, $singleindent, "product_name"); + push(@xpdfile, $tag); + $tag = set_macro_tag($allvariables, $singleindent, "product_version"); + push(@xpdfile, $tag); + $tag = set_macro_tag($allvariables, $singleindent, "product_suffix"); + push(@xpdfile, $tag); + $tag = set_macro_tag($allvariables, $singleindent, "product_fullname"); + push(@xpdfile, $tag); + + $tag = set_defaultdir_tag($allvariables, $singleindent); + push(@xpdfile, $tag); + + $tag = set_productdir_tag($allvariables, $singleindent); + push(@xpdfile, $tag); + + $tag = set_minor_tag($allvariables, $singleindent); + push(@xpdfile, $tag); + + $tag = set_update_tag($allvariables, $singleindent); + push(@xpdfile, $tag); + + $tag = set_packagedir_tag($singleindent); + push(@xpdfile, $tag); + + $tag = set_packagetype_tag($singleindent); + push(@xpdfile, $tag); + + $tag = set_architecture_tag($singleindent); + push(@xpdfile, $tag); + + $tag = set_multilanguage_tag($singleindent); + push(@xpdfile, $tag); + + $tag = set_language_tag($languagestringref, $singleindent); + push(@xpdfile, $tag); + + $tag = set_hideeula_tag($allvariables, $singleindent); + push(@xpdfile, $tag); + + $tag = get_end_tag("product", $noindent); + push(@xpdfile, $tag); + + return \@xpdfile; +} + +################################################### +# Collecting content for xpd file +################################################### + +sub get_file_content +{ + my ( $module, $packagename, $solslanguage, $linkpackage, $isemptyparent, $subdir, $islanguagemodule, $onelanguage, $xpdinfo ) = @_; + + my @xpdfile = (); + my $value = ""; + my $line = ""; + my $noindent = ""; + my $singleindent = " "; + my $doubleindent = $singleindent . $singleindent; + + my ( $tag, $parentgid ) = get_package_tag($module, $noindent, $linkpackage); + push(@xpdfile, $tag); + + # start of installunit tag -> using info from scp module + + $tag = get_display_tag($module, $singleindent); + push(@xpdfile, $tag); + + $value = get_sortkey_value($module); + $line = get_tag_line($doubleindent, "sortkey", $value); + push(@xpdfile, $line); + + $value = get_default_value($module); + $line = get_tag_line($doubleindent, "default", $value); + push(@xpdfile, $line); + + $value = get_showinuserinstall_value($module); + $line = get_tag_line($doubleindent, "showinuserinstall", $value); + push(@xpdfile, $line); + + $value = get_userinstallonly_value($module); + $line = get_tag_line($doubleindent, "showinuserinstallonly", $value); + push(@xpdfile, $line); + + $value = get_dontuninstall_value($module); + $line = get_tag_line($doubleindent, "dontuninstall", $value); + push(@xpdfile, $line); + + $value = get_checksolaris_value($module); + $line = get_tag_line($doubleindent, "checksolaris", $value); + push(@xpdfile, $line); + + $value = get_isupdatepackage_value($module); + $line = get_tag_line($doubleindent, "isupdatepackage", $value); + push(@xpdfile, $line); + + $value = get_showmultilingualonly_value($module); + $line = get_tag_line($doubleindent, "showmultilingualonly", $value); + push(@xpdfile, $line); + + $value = get_applicationmodule_value($module); + $line = get_tag_line($doubleindent, "applicationmodule", $value); + push(@xpdfile, $line); + + $value = get_isjavamodule_value($module); + $line = get_tag_line($doubleindent, "isjavapackage", $value); + push(@xpdfile, $line); + + $value = get_installcanfail_value($module); + $line = get_tag_line($doubleindent, "installcanfail", $value); + push(@xpdfile, $line); + + $value = get_forceintoupdate_value($module); + $line = get_tag_line($doubleindent, "forceintoupdate", $value); + push(@xpdfile, $line); + + $value = get_useforce_value($module); + $line = get_tag_line($doubleindent, "useforce", $value); + push(@xpdfile, $line); + + # iterating over all languages to get names and descriptions + collect_lang_values($doubleindent, $module, \@xpdfile, "Name", "name"); + collect_lang_values($doubleindent, $module, \@xpdfile, "Description", "description"); + + $tag = get_end_tag("display", $singleindent); + push(@xpdfile, $tag); + + # end of display tag + + if ( ! $isemptyparent ) + { + # start of installunit tag -> using info from package defined in packagelist + + $tag = get_installunit_tag($singleindent); + push(@xpdfile, $tag); + + $value = get_size_value($packagename, $xpdinfo); + $line = get_tag_line($doubleindent, "size", $value); + push(@xpdfile, $line); + + $value = get_order_value($module); + $line = get_tag_line($doubleindent, "installorder", $value); + push(@xpdfile, $line); + + $value = get_md5_value($packagename, $xpdinfo); + $line = get_tag_line($doubleindent, "md5", $value); + push(@xpdfile, $line); + + $value = get_name_value($packagename); + $line = get_tag_line($doubleindent, "name", $value); + push(@xpdfile, $line); + + $value = get_fullpkgname_value($packagename, $xpdinfo); + $line = get_tag_line($doubleindent, "fullpkgname", $value); + push(@xpdfile, $line); + + $value = get_pkgversion_value($packagename, $xpdinfo); + $line = get_tag_line($doubleindent, "pkgversion", $value); + push(@xpdfile, $line); + + $value = get_subdir_value($packagename, $subdir, $module); + $line = get_tag_line($doubleindent, "subdir", $value); + push(@xpdfile, $line); + + $value = get_relocatable_value($module); + $line = get_tag_line($doubleindent, "relocatable", $value); + push(@xpdfile, $line); + + $value = get_languagespecific_value($islanguagemodule); + $line = get_tag_line($doubleindent, "languagespecific", $value); + push(@xpdfile, $line); + + $value = $onelanguage; + $line = get_tag_line($doubleindent, "language", $value); + push(@xpdfile, $line); + + $line = get_tag_line($doubleindent, "solarislanguage", $solslanguage); + push(@xpdfile, $line); + + $tag = get_end_tag("installunit", $singleindent); + push(@xpdfile, $tag); + + # end of installunit tag + } + + $tag = get_end_tag("package", $noindent); + push(@xpdfile, $tag); + + return ( \@xpdfile, $parentgid ); +} + +################################################### +# Setting xpd file name +################################################### + +sub get_xpd_filename +{ + my ($modulegid, $linkpackage) = @_; + + if ( $linkpackage ) { $modulegid = $modulegid . "u"; } + + my $filename = $modulegid . ".xpd"; + + return $filename; +} + +################################################### +# Determine, which package was created newly +################################################### + +sub determine_new_packagename +{ + my ( $installdir, $subdir, $xpdinfo ) = @_; + + my $newpackage = ""; + $installdir =~ s/\Q$installer::globals::separator\E\s*$//; + my $directory = $installdir . $installer::globals::separator . $subdir; + $directory =~ s/\Q$installer::globals::separator\E\s*$//; + + if ( $xpdinfo->{'RealPackageName'} ) + { + $newpackage = $directory . $installer::globals::separator . $xpdinfo->{'RealPackageName'}; + push(@installer::globals::currentcontent, $newpackage); + return $newpackage; + } + + my ($newcontent, $allcontent) = installer::systemactions::find_new_content_in_directory($directory, \@installer::globals::currentcontent); + @installer::globals::currentcontent = (); + foreach my $element ( @{$allcontent} ) { push(@installer::globals::currentcontent, $element); } + + my $newentriesnumber = $#{$newcontent} + 1; + if ( $newentriesnumber > 1 ) { installer::exiter::exit_program("ERROR: More than one new package in directory $directory", "determine_new_packagename (xpdinstaller)"); } + elsif ( $newentriesnumber < 1 ) { installer::exiter::exit_program("ERROR: No new package in directory $directory", "determine_new_packagename (xpdinstaller)"); } + $newpackage = ${$newcontent}[0]; + + return $newpackage; +} + +################################################### +# Checking, if the parentgid is defined in +# another package +################################################### + +sub is_empty_parent +{ + my ($gid, $packages) = @_; + + my $is_empty_parent = 1; + + for ( my $k = 0; $k <= $#{$packages}; $k++ ) + { + my $onepackage = ${$packages}[$k]; + my $packagegid = $onepackage->{'module'}; + + if ( $packagegid eq $gid ) + { + $is_empty_parent = 0; + last; + } + } + + return $is_empty_parent; +} + +################################################### +# Creating additional xpd files for empty parents +################################################### + +sub create_emptyparents_xpd_file +{ + my ($parentgid, $modulesarrayref, $xpddir) = @_; + + my $module = get_module($parentgid, $modulesarrayref); + my $grandpagid = ""; + + if ( $module ne "" ) + { + my $packagename = ""; + # all content saved in scp is now available and can be used to create the xpd file + my ( $xpdfile, $newparentgid ) = get_file_content($module, $packagename, "", 0, 1, "", 0, "", ""); + + $grandpagid = $newparentgid; + + my $xpdfilename = get_xpd_filename($parentgid, 0); + $xpdfilename = $xpddir . $installer::globals::separator . $xpdfilename; + + installer::files::save_file($xpdfilename, $xpdfile); + push(@installer::globals::allxpdfiles, $xpdfilename); + my $infoline = "Saving xpd file: $xpdfilename\n"; + push(@installer::globals::logfileinfo, $infoline); + } + + # push(@installer::globals::emptyxpdparents, $parentgid); + push( @installer::globals::createdxpdfiles, $parentgid); + + return $grandpagid; +} + +################################################### +# Creating additional xpd files for empty parents +################################################### + +sub filter_content_from_xpdfile +{ + my ($xpdfile) = @_; + + my @newxpdfile = (); + + my $include = 1; + + for ( my $i = 0; $i <= $#{$xpdfile}; $i++ ) + { + my $line = ${$xpdfile}[$i]; + + if (( $line =~ /^\s*\<installunit/ ) && ( $include )) { $include = 0; } + if ( $include ) { push(@newxpdfile, $line); } + if (( $line =~ /^\s*\<\/installunit/ ) && ( ! $include )) { $include = 1; } + } + + return \@newxpdfile; +} + +########################################################################## +# Changing the parent inside the xpd file +# Old: <package name="gid_Module_Root" parent="root"> +# New: <package name="gid_Module_Root_Files_1" parent="gid_Module_Root"> +########################################################################## + +sub change_parent_in_xpdfile +{ + my ($xpdfile, $modulename) = @_; + + for ( my $i = 0; $i <= $#{$xpdfile}; $i++ ) + { + if ( ${$xpdfile}[$i] =~ /^\s*\<package name\s*=\s*\"(\S+?)\"\s+parent\s*=\s*\"(\S+?)\"\s*\>\s*$/ ) + { + my $oldname = $1; + my $oldparent = $2; + + my $newname = $modulename; + my $newparent = $oldname; + + ${$xpdfile}[$i] =~ s/\"\Q$oldname\E\"/\"$newname\"/; + ${$xpdfile}[$i] =~ s/\"\Q$oldparent\E\"/\"$newparent\"/; + + last; + } + } +} + +################################################### +# Creating one xpd file for each package +################################################### + +sub create_xpd_file +{ + my ($onepackage, $allpackages, $languagestringref, $allvariables, $modulesarrayref, $installdir, $subdir, $linkpackage, $xpdinfo) = @_; + + my $infoline = ""; + # creating the directory + my $xpddir = installer::systemactions::create_directories("xpdinstaller", $languagestringref); + $xpddir =~ s/\/\s*$//; + $installer::globals::xpddir = $xpddir; + # push(@installer::globals::removedirs, $xpddir); + + my $modulegid = $onepackage->{'module'}; + + my $onelanguage = ""; # + my $solslanguage = ""; # + my $islanguagemodule = 0; # + if ( $onepackage->{'islanguagemodule'} ) { $islanguagemodule = $onepackage->{'islanguagemodule'}; } # + if ( $islanguagemodule ) # + { + $onelanguage = $onepackage->{'language'}; # + if ( $installer::globals::issolarispkgbuild ) { $solslanguage = installer::epmfile::get_solaris_language_for_langpack($onelanguage); } # + } + + installer::logger::include_header_into_logfile("Creating xpd file ($modulegid):"); + + my $module = get_module($modulegid, $modulesarrayref); + + if ( $module ne "" ) + { + my $packagename = determine_new_packagename($installdir, $subdir, $xpdinfo); + + # all content saved in scp is now available and can be used to create the xpd file + my ( $xpdfile, $parentgid ) = get_file_content($module, $packagename, $solslanguage, $linkpackage, 0, "", $islanguagemodule, $onelanguage, $xpdinfo); + + my $xpdfilename = get_xpd_filename($modulegid, $linkpackage); + $xpdfilename = $xpddir . $installer::globals::separator . $xpdfilename; + + # Very special handling for Root module: + # Because packages should only be assigned to leaves and not to knods, + # the root module is divided into a knod without package and a new + # leave with package. The name of the leave is defined at $module->{'XpdPackageName'}. + if ( $module->{'XpdPackageName'} ) + { + my $newxpdfilename = get_xpd_filename($module->{'XpdPackageName'}, 0); + $newxpdfilename = $xpddir . $installer::globals::separator . $newxpdfilename; + my $emptyfilecontent = filter_content_from_xpdfile($xpdfile); + + installer::files::save_file($xpdfilename, $emptyfilecontent); + push(@installer::globals::allxpdfiles, $xpdfilename); + $infoline = "Saving xpd file: $xpdfilename\n"; + push( @installer::globals::logfileinfo, $infoline); + + $xpdfilename = $newxpdfilename; + change_parent_in_xpdfile($xpdfile, $module->{'XpdPackageName'}); + } + + installer::files::save_file($xpdfilename, $xpdfile); + push( @installer::globals::createdxpdfiles, $modulegid); + push(@installer::globals::allxpdfiles, $xpdfilename); + $infoline = "Saving xpd file: $xpdfilename\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $grandpagid = "root"; + if ( $parentgid ne "root" ) + { + my $create_missing_parent = is_empty_parent($parentgid, $allpackages); + + # if (( $create_missing_parent ) && ( ! installer::existence::exists_in_array($parentgid, \@installer::globals::emptyxpdparents) )) + if (( $create_missing_parent ) && ( ! installer::existence::exists_in_array($parentgid, \@installer::globals::createdxpdfiles) )) + { + $grandpagid = create_emptyparents_xpd_file($parentgid, $modulesarrayref, $xpddir); + } + } + + if ( $grandpagid ne "root" ) + { + my $create_missing_parent = is_empty_parent($grandpagid, $allpackages); + + # if (( $create_missing_parent ) && ( ! installer::existence::exists_in_array($parentgid, \@installer::globals::emptyxpdparents) )) + if (( $create_missing_parent ) && ( ! installer::existence::exists_in_array($grandpagid, \@installer::globals::createdxpdfiles) )) + { + create_emptyparents_xpd_file($grandpagid, $modulesarrayref, $xpddir); + } + } + } + else + { + installer::exiter::exit_program("ERROR: No module definition found for gid: $modulegid", "create_xpd_file (xpdinstaller)"); + } + +} + +################################################### +# Creating a xpd file for a copied package +################################################### + +sub create_xpd_file_for_childproject +{ + my ($module, $destdir, $packagename, $allvariableshashref, $modulesarrayref) = @_; + + my $modulegid = $module->{'gid'}; + + my $currentdir = cwd(); + $destdir =~ s/\/\s*$//; + $currentdir =~ s/\/\s*$//; + + my $completepackage = $currentdir . $installer::globals::separator . $destdir . $installer::globals::separator . $packagename; + + # all content saved in scp is now available and can be used to create the xpd file + my ( $xpdfile, $parentgid ) = get_file_content($module, $completepackage, "", 0, 0, "", 0, "", ""); + + my $xpdfilename = get_xpd_filename($modulegid, 0); + $xpdfilename = $installer::globals::xpddir . $installer::globals::separator . $xpdfilename; + + installer::files::save_file($xpdfilename, $xpdfile); + push( @installer::globals::createdxpdfiles, $modulegid); + push(@installer::globals::allxpdfiles, $xpdfilename); + my $infoline = "Saving xpd file: $xpdfilename\n"; + push( @installer::globals::logfileinfo, $infoline); + + if ( $parentgid ne "root" ) + { + # my $create_missing_parent = is_empty_parent($parentgid, $allpackages); + my $create_missing_parent = 1; # -> Always missing parent by child projects! + # Parent is now created, if it was not created before. Attention: Parent module must not come later. + if (( $create_missing_parent ) && ( ! installer::existence::exists_in_array($parentgid, \@installer::globals::createdxpdfiles) )) + { + create_emptyparents_xpd_file($parentgid, $modulesarrayref, $installer::globals::xpddir); + } + } +} + +############################################################## +# Creating a xpd file for copied system integration package +############################################################## + +sub create_xpd_file_for_systemintegration +{ + my ($module, $newcontent, $modulesarrayref, $subdir) = @_; + + my $parentgid = $module->{'gid'}; + + # Create new visible module from scp info and create + # new hidden module for each package inside in tar file + + for ( my $i = 0; $i <= $#{$newcontent}; $i++ ) + { + my $newpackagename = ${$newcontent}[$i]; + + # installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$newpackagename); + + my $infoline = "Creating xpd file for package: $newpackagename\n"; + push( @installer::globals::logfileinfo, $infoline); + + my $childmodule = installer::worker::copy_hash_from_references($module); + $childmodule->{'ParentID'} = $module->{'gid'}; # the module gid is the new parent + $childmodule->{'InstallOrder'} = $installer::globals::defaultsystemintinstallorder; + my $number = $i + 1; + my $modulegid = $module->{'gid'} . "_child_" . $number; # setting a dynamic new gid + $childmodule->{'gid'} = $modulegid; + $childmodule->{'Styles'} =~ s/\)/\,HIDDEN_ROOT\)/; + # iterating over all languages to get names and descriptions + remove_lang_values($childmodule, "Name"); + remove_lang_values($childmodule, "Description"); + + my $shortpackagename = $newpackagename; + installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$shortpackagename); + $childmodule->{'PackageName'} = $shortpackagename; + $childmodule->{'Name'} = $modulegid; + $childmodule->{'Description'} = $modulegid; + + # Checking, if installorder can be set: + # scp syntax: InstallOrder = "desktop:1050, suse:1060"; + # The string before the number can be compared with $shortpackagename + if ( $module->{'InstallOrder'} ) + { + my $installorder = $module->{'InstallOrder'}; + $installorder =~ s/^\s*\"//g; + $installorder =~ s/\"\s*$//g; + # $installorder is comma separated list + my $allorders = installer::converter::convert_stringlist_into_array(\$installorder, ","); + for ( my $j = 0; $j <= $#{$allorders}; $j++ ) + { + my $oneitem = ${$allorders}[$j]; + if ( $oneitem =~ /^\s*(\S+?)\s*:\s*(\S+?)\s*$/ ) + { + my $name = $1; + my $order = $2; + + if ( $shortpackagename =~ /\Q$name\E/ ) { $childmodule->{'InstallOrder'} = $order; } + } + } + } + + # all content saved in scp is now available and can be used to create the xpd file + my ( $xpdfile, $parentgid_ ) = get_file_content($childmodule, $newpackagename, "", 0, 0, $subdir, 0, "", ""); + + my $xpdfilename = get_xpd_filename($modulegid, 0); + $xpdfilename = $installer::globals::xpddir . $installer::globals::separator . $xpdfilename; + + installer::files::save_file($xpdfilename, $xpdfile); + push(@installer::globals::allxpdfiles, $xpdfilename); + $infoline = "Saving xpd file: $xpdfilename\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + # Creating the top level visible xpd file + create_emptyparents_xpd_file($parentgid, $modulesarrayref, $installer::globals::xpddir); +} + +############################################################## +# Copying xpd files into installation set +############################################################## + +sub copy_xpd_files +{ + my ( $destdir ) = @_; + + for ( my $i = 0; $i <= $#installer::globals::allxpdfiles; $i++ ) + { + if ( ! -f $installer::globals::allxpdfiles[$i] ) { installer::exiter::exit_program("ERROR: Could not find xpd file: $installer::globals::allxpdfiles[$i]!", "copy_xpd_files"); } + installer::systemactions::copy_one_file($installer::globals::allxpdfiles[$i], $destdir); + } +} + +############################################################## +# Copying all xpd files into the installation set +############################################################## + +sub copy_xpd_files_into_installset +{ + my ($installdir) = @_; + + $installdir =~ s/\Q$installer::globals::separator\E\s*$//; + + my $instdir = $installdir . $installer::globals::separator . "installdata"; + installer::systemactions::create_directory($instdir); + + my $xpddir = $instdir . $installer::globals::separator . "xpd"; + installer::systemactions::create_directory($xpddir); + copy_xpd_files($xpddir); +} + +############################################################## +# Creating base xpd file with product information +############################################################## + +sub create_setup_xpd +{ + my ($allvariables, $languagestringref) = @_; + + my ( $xpdfile ) = get_setup_file_content($allvariables, $languagestringref); + + my $xpdfilename = $installer::globals::productxpdfile; + $xpdfilename = $installer::globals::xpddir . $installer::globals::separator . $xpdfilename; + + installer::files::save_file($xpdfilename, $xpdfile); + push(@installer::globals::allxpdfiles, $xpdfilename); + my $infoline = "Saving xpd file: $xpdfilename\n"; + push( @installer::globals::logfileinfo, $infoline); +} + +################################################### +# Copying the files needed by the xpd installer +# into the installation directory +################################################### + +sub create_xpd_installer +{ + my ( $installdir, $allvariables, $languagestringref) = @_; + + installer::logger::include_header_into_logfile("Creating xpd installer:"); + + # create setup.xpd file + create_setup_xpd($allvariables, $languagestringref); + + # copy xpd files into installation set + copy_xpd_files_into_installset($installdir); +} + +1; diff --git a/solenv/bin/modules/installer/ziplist.pm b/solenv/bin/modules/installer/ziplist.pm new file mode 100644 index 000000000000..c1f1efbf98a8 --- /dev/null +++ b/solenv/bin/modules/installer/ziplist.pm @@ -0,0 +1,795 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: ziplist.pm,v $ +# +# $Revision: 1.22 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package installer::ziplist; + +use installer::existence; +use installer::exiter; +use installer::globals; +use installer::logger; +use installer::parameter; +use installer::remover; +use installer::systemactions; + +################################################# +# Getting data from path file and zip list file +################################################# + +sub getproductblock +{ + my ($fileref, $search, $inheritance) = @_; + + my @searchblock = (); + my $searchexists = 0; + my $record = 0; + my $count = 0; + my $line; + my $inh = $inheritance ? '(?::\s*(\S+)\s*)?' : ""; + my $parent; + + for ( my $i = 0; $i <= $#{$fileref}; $i++ ) + { + $line = ${$fileref}[$i]; + + if ( $line =~ /^\s*\Q$search\E\s*$inh$/i ) # case insensitive + { + $record = 1; + $searchexists = 1; + $parent = $1 if $inheritance; + } + + if ($record) + { + push(@searchblock, $line); + } + + if ( ($record) && ($line =~ /\{/) ) + { + $count++; + } + + if ( ($record) && ($line =~ /\}/) ) + { + $count--; + } + + if ( ($record) && ($line =~ /\}/) && ( $count == 0 ) ) + { + $record = 0; + } + } + + if (( ! $searchexists ) && ( $search ne $installer::globals::globalblock )) + { + if ($search eq $installer::globals::product ) + { + installer::exiter::exit_program("ERROR: Product $installer::globals::product not defined in $installer::globals::ziplistname", "getproductblock"); + } + elsif ($search eq $installer::globals::compiler ) + { + installer::exiter::exit_program("ERROR: Compiler $installer::globals::compiler not defined in $installer::globals::pathfilename", "getproductblock"); + } + else # this is not possible + { + installer::exiter::exit_program("ERROR: Unknown value for $search in getproductblock()", "getproductblock"); + } + } + + return (\@searchblock, $parent); +} + +############################################### +# Analyzing the settings in the zip list file +############################################### + +sub analyze_settings_block +{ + my ($blockref) = @_; + + my @newsettingsblock = (); + my $compilerstring = ""; + my $record = 1; + my $counter = 0; + + # Allowed values in settings block: + # "Settings", "Variables", "unix" (for destination path and logfile) + # Furthermore allowed values are $installer::globals::build (srx645) and $installer::globals::compiler (pro and nonpro (unxsols4.pro)) + + # Comment line in settings block begin with "#" or ";" + + if ( $installer::globals::pro ) + { + $compilerstring = $installer::globals::compiler . ".pro"; + } + else + { + $compilerstring = $installer::globals::compiler; + } + + for ( my $i = 0; $i <= $#{$blockref}; $i++ ) + { + my $line = ${$blockref}[$i]; + my $nextline = ""; + + if ( ${$blockref}[$i+1] ) { $nextline = ${$blockref}[$i+1]; } + + # removing comment lines + + if (($line =~ /^\s*\#/) || ($line =~ /^\s*\;/)) + { + next; + } + + # complete blocks of unknows strings are not recorded + + if ((!($line =~ /^\s*\Q$compilerstring\E\s*$/i)) && + (!($line =~ /^\s*\Q$installer::globals::build\E\s*$/i)) && + (!($line =~ /^\s*\bSettings\b\s*$/i)) && + (!($line =~ /^\s*\bVariables\b\s*$/i)) && + (!($line =~ /^\s*\bunix\b\s*$/i)) && + ($nextline =~ /^\s*\{\s*$/i)) + { + $record = 0; + next; # continue with next $i + } + + if (!( $record )) + { + if ($line =~ /^\s*\{\s*$/i) + { + $counter++; + } + + if ($line =~ /^\s*\}\s*$/i) + { + $counter--; + } + + if ($counter == 0) + { + $record = 1; + next; # continue with next $i + } + } + + if ($record) + { + push(@newsettingsblock, $line); + } + } + + return \@newsettingsblock; +} + +######################################## +# Settings in zip list file +######################################## + +sub get_settings_from_ziplist +{ + my ($blockref) = @_; + + my @allsettings = (); + my $isvariables = 0; + my $counter = 0; + my $variablescounter = 0; + + # Take all settings from the settings block + # Do not take the variables from the settings block + # If a setting is defined more than once, take the + # setting with the largest counter (open brackets) + + for ( my $i = 0; $i <= $#{$blockref}; $i++ ) + { + my $line = ${$blockref}[$i]; + my $nextline = ""; + + if ( ${$blockref}[$i+1] ) { $nextline = ${$blockref}[$i+1]; } + + if (($line =~ /^\s*\S+\s*$/i) && + ($nextline =~ /^\s*\{\s*$/i) && + (!($line =~ /^\s*Variables\s*$/i))) + { + next; + } + + if ($line =~ /^\s*Variables\s*$/i) + { + # This is a block of variables + + $isvariables = 1; + next; + } + + if ($line =~ /^\s*\{\s*$/i) + { + if ($isvariables) + { + $variablescounter++; + } + else + { + $counter++; + } + + next; + } + + if ($line =~ /^\s*\}\s*$/i) + { + if ($isvariables) + { + $variablescounter--; + + if ($variablescounter == 0) + { + $isvariables = 0; + } + } + else + { + $counter--; + } + + next; + } + + if ($isvariables) + { + next; + } + + installer::remover::remove_leading_and_ending_whitespaces(\$line); + + $line .= "\t##$counter##\n"; + + push(@allsettings, $line); + } + + return \@allsettings; +} + +####################################### +# Variables from zip list file +####################################### + +sub get_variables_from_ziplist +{ + my ($blockref) = @_; + + my @allvariables = (); + my $isvariables = 0; + my $counter = 0; + my $variablescounter = 0; + my $countersum = 0; + + # Take all variables from the settings block + # Do not take the other settings from the settings block + # If a variable is defined more than once, take the + # variable with the largest counter (open brackets) + + for ( my $i = 0; $i <= $#{$blockref}; $i++ ) + { + my $line = ${$blockref}[$i]; + my $nextline = ${$blockref}[$i+1]; + + if ($line =~ /^\s*Variables\s*$/i) + { + # This is a block of variables + + $isvariables = 1; + next; + } + + if ($line =~ /^\s*\{\s*$/i) + { + if ($isvariables) + { + $variablescounter++; + } + else + { + $counter++; + } + + next; + } + + if ($line =~ /^\s*\}\s*$/i) + { + if ($isvariables) + { + $variablescounter--; + + if ($variablescounter == 0) + { + $isvariables = 0; + } + } + else + { + $counter--; + } + + next; + } + + if (!($isvariables)) + { + next; + } + + $countersum = $counter + $variablescounter; + + installer::remover::remove_leading_and_ending_whitespaces(\$line); + + $line .= "\t##$countersum##\n"; + + push(@allvariables, $line); + } + + return \@allvariables; +} + +####################################################################### +# Removing multiple variables and settings, defined in zip list file +####################################################################### + +sub remove_multiples_from_ziplist +{ + my ($blockref) = @_; + + # remove all definitions of settings and variables + # that occur more than once in the zip list file. + # Take the one with the most open brackets. This + # number is stored at the end of the string. + + my @newarray = (); + my @itemarray = (); + my ($line, $itemname, $itemnumber); + + # first collecting all variables and settings names + + for ( my $i = 0; $i <= $#{$blockref}; $i++ ) + { + $line = ${$blockref}[$i]; + + if ($line =~ /^\s*\b(\S*)\b\s+.*\#\#\d+\#\#\s*$/i) + { + $itemname = $1; + } + + if (! installer::existence::exists_in_array($itemname, \@itemarray)) + { + push(@itemarray, $itemname); + } + } + + # and now all $items can be selected with the highest number + + for ( my $i = 0; $i <= $#itemarray; $i++ ) + { + $itemname = $itemarray[$i]; + + my $itemnumbermax = 0; + my $printline = ""; + + for ( my $j = 0; $j <= $#{$blockref}; $j++ ) + { + $line = ${$blockref}[$j]; + + if ($line =~ /^\s*\Q$itemname\E\s+.*\#\#(\d+)\#\#\s*$/) + { + $itemnumber = $1; + + if ($itemnumber >= $itemnumbermax) + { + $printline = $line; + $itemnumbermax = $itemnumber; + } + } + } + + # removing the ending number from the printline + # and putting it into the array + + $printline =~ s/\#\#\d+\#\#//; + installer::remover::remove_leading_and_ending_whitespaces(\$line); + push(@newarray, $printline); + } + + return \@newarray; +} + +######################################################### +# Reading one variable defined in the zip list file +######################################################### + +sub getinfofromziplist +{ + my ($blockref, $variable) = @_; + + my $searchstring = ""; + my $line; + + for ( my $i = 0; $i <= $#{$blockref}; $i++ ) + { + $line = ${$blockref}[$i]; + + if ( $line =~ /^\s*\Q$variable\E\s+(.+?)\s*$/ ) # "?" for minimal matching + { + $searchstring = $1; + last; + } + } + + return \$searchstring; +} + +#################################################### +# Replacing variables in include path +#################################################### + +sub replace_all_variables_in_pathes +{ + my ( $patharrayref, $variableshashref ) = @_; + + for ( my $i = 0; $i <= $#{$patharrayref}; $i++ ) + { + my $line = ${$patharrayref}[$i]; + + my $key; + + foreach $key (keys %{$variableshashref}) + { + my $value = $variableshashref->{$key}; + + if (( $line =~ /\{$key\}/ ) && ( $value eq "" )) { $line = ".\n"; } + + $line =~ s/\{\Q$key\E\}/$value/g; + } + + ${$patharrayref}[$i] = $line; + } +} + +#################################################### +# Replacing minor in include path +#################################################### + +sub replace_minor_in_pathes +{ + my ( $patharrayref ) = @_; + + for ( my $i = 0; $i <= $#{$patharrayref}; $i++ ) + { + my $line = ${$patharrayref}[$i]; + + if ( $installer::globals::minor ) + { + $line =~ s/\{minor\}/$installer::globals::minor/g; + # no difference for minor and minornonpre (ToDo ?) + $line =~ s/\{minornonpre\}/$installer::globals::minor/g; + } + else # building without a minor + { + $line =~ s/\.\{minor\}//g; + $line =~ s/\.\{minornonpre\}//g; + } + + ${$patharrayref}[$i] = $line; + } +} + +#################################################### +# Replacing packagetype in include path +#################################################### + +sub replace_packagetype_in_pathes +{ + my ( $patharrayref ) = @_; + + for ( my $i = 0; $i <= $#{$patharrayref}; $i++ ) + { + my $line = ${$patharrayref}[$i]; + + if (( $installer::globals::installertypedir ) && ( $line =~ /\{pkgtype\}/ )) + { + $line =~ s/\{pkgtype\}/$installer::globals::installertypedir/g; + } + + ${$patharrayref}[$i] = $line; + } +} + +#################################################### +# Removing ending separators in pathes +#################################################### + +sub remove_ending_separator +{ + my ( $patharrayref ) = @_; + + for ( my $i = 0; $i <= $#{$patharrayref}; $i++ ) + { + my $line = ${$patharrayref}[$i]; + + installer::remover::remove_ending_pathseparator(\$line); + + $line =~ s/\s*$//; + $line = $line . "\n"; + + ${$patharrayref}[$i] = $line; + } +} + +#################################################### +# Replacing languages in include path +#################################################### + +sub replace_languages_in_pathes +{ + my ( $patharrayref, $languagesref ) = @_; + + installer::logger::include_header_into_logfile("Replacing languages in include pathes:"); + + my @patharray = (); + my $infoline = ""; + + for ( my $i = 0; $i <= $#{$patharrayref}; $i++ ) + { + my $line = ${$patharrayref}[$i]; + + if ( $line =~ /\$\(LANG\)/ ) + { + my $originalline = $line; + my $newline = ""; + + for ( my $j = 0; $j <= $#{$languagesref}; $j++ ) + { + my $language = ${$languagesref}[$j]; + $line =~ s/\$\(LANG\)/$language/g; + push(@patharray ,$line); + $newdir = $line; + $line = $originalline; + + installer::remover::remove_leading_and_ending_whitespaces(\$newline); + + # Is it necessary to refresh the global array, containing all files of all include pathes? + if ( -d $newdir ) + { + # Checking if $newdir is empty + if ( ! installer::systemactions::is_empty_dir($newdir) ) + { + $installer::globals::refresh_includepathes = 1; + $infoline = "Directory $newdir exists and is not empty. Refreshing global file array is required.\n"; + push( @installer::globals::logfileinfo, $infoline); + } + else + { + $infoline = "Directory $newdir is empty. No refresh of global file array required.\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + else + { + $infoline = "Directory $newdir does not exist. No refresh of global file array required.\n"; + push( @installer::globals::logfileinfo, $infoline); + } + } + } + else # not language dependent include path + { + push(@patharray ,$line); + } + } + + return \@patharray; +} + +##################################################### +# Collecting all files from all include paths +##################################################### + +sub list_all_files_from_include_path +{ + my ( $patharrayref) = @_; + + installer::logger::include_header_into_logfile("Include pathes:"); + + for ( my $i = 0; $i <= $#{$patharrayref}; $i++ ) + { + my $path = ${$patharrayref}[$i]; + installer::remover::remove_leading_and_ending_whitespaces(\$path); + my $infoline = "$path\n"; + push( @installer::globals::logfileinfo, $infoline); + } + + push( @installer::globals::logfileinfo, "\n"); + + return \@filesarray; +} + +##################################################### +# Collecting all files from all include paths +##################################################### + +sub set_manufacturer +{ + my ($allvariables) = @_; + + my $openofficeproductname = "OpenOffice.org"; + my $sunname = "Sun Microsystems"; + + if ( $allvariables->{'OPENSOURCE'} && $allvariables->{'OPENSOURCE'} == 1 ) + { + $installer::globals::isopensourceproduct = 1; + $installer::globals::manufacturer = $openofficeproductname; + $installer::globals::longmanufacturer = $openofficeproductname; + } + else + { + $installer::globals::isopensourceproduct = 0; + $installer::globals::manufacturer = $sunname; + $installer::globals::longmanufacturer = $sunname . ", Inc."; + } + + $allvariables->{'MANUFACTURER'} = $installer::globals::manufacturer; +} + +############################################################## +# A ProductVersion has to be defined. If it is not set in +# zip.lst, it is set now to "1" +############################################################## + +sub set_default_productversion_if_required +{ + my ($allvariables) = @_; + + if (!($allvariables->{'PRODUCTVERSION'})) + { + $allvariables->{'PRODUCTVERSION'} = 1; # FAKE + } + + # Creating differentiators for BUILD_SPECIAL in layering + if ( ! $ENV{'BUILD_SPECIAL'} ) + { + if ( $allvariables->{'REGISTRYLAYERNAME'} ) { $allvariables->{'REGISTRYLAYERNAME'} = $allvariables->{'REGISTRYLAYERNAME'} . "_"; } + if (( $installer::globals::iswindowsbuild ) && ( $allvariables->{'BASISROOTNAME'} )) { $allvariables->{'BASISROOTNAME'} = $allvariables->{'BASISROOTNAME'} . "_"; } + } +} + +#################################################### +# Removing .. in pathes +#################################################### + +sub simplify_path +{ + my ( $pathref ) = @_; + + my $oldpath = $$pathref; + + my $change = 0; + + while ( $oldpath =~ /(^.*)(\Q$installer::globals::separator\E.*\w+?)(\Q$installer::globals::separator\E\.\.)(\Q$installer::globals::separator\E.*$)/ ) + { + my $part1 = $1; + my $part2 = $4; + $oldpath = $part1 . $part2; + $change = 1; + } + + if ( $change ) { $$pathref = $oldpath . "\n"; } +} + +#################################################### +# Removing ending separators in pathes +#################################################### + +sub resolve_relative_pathes +{ + my ( $patharrayref ) = @_; + + for ( my $i = 0; $i <= $#{$patharrayref}; $i++ ) + { + installer::parameter::make_path_absolute(\${$patharrayref}[$i]); + simplify_path(\${$patharrayref}[$i]); + } +} + +#################################################### +# Replacing variables inside zip list variables +# Example: {milestone} to be replaced by +# $installer::globals::lastminor +#################################################### + +sub replace_variables_in_ziplist_variables +{ + my ($blockref) = @_; + + my $milestonevariable = $installer::globals::lastminor; + $milestonevariable =~ s/m//; + $milestonevariable =~ s/s/\./; + + my $localminor = $installer::globals::lastminor; + if ( $installer::globals::minor ) { $localminor = $installer::globals::minor; } + + for ( my $i = 0; $i <= $#{$blockref}; $i++ ) + { + if ($installer::globals::lastminor) { ${$blockref}[$i] =~ s/\{milestone\}/$milestonevariable/; } + else { ${$blockref}[$i] =~ s/\{milestone\}//; } + if ( $localminor ) { ${$blockref}[$i] =~ s/\{minor\}/$localminor/; } + else { ${$blockref}[$i] =~ s/\{minor\}//; } + if ( $installer::globals::buildid ) { ${$blockref}[$i] =~ s/\{buildid\}/$installer::globals::buildid/; } + else { ${$blockref}[$i] =~ s/\{buildid\}//; } + if ( $installer::globals::build ) { ${$blockref}[$i] =~ s/\{buildsource\}/$installer::globals::build/; } + else { ${$blockref}[$i] =~ s/\{build\}//; } + } +} + +########################################################### +# Adding the lowercase variables into the variableshashref +########################################################### + +sub add_variables_to_allvariableshashref +{ + my ($variableshashref) = @_; + + my $lcvariable = lc($variableshashref->{'PRODUCTNAME'}); + $variableshashref->{'LCPRODUCTNAME'} = $lcvariable; + + if ($variableshashref->{'SHORT_PRODUCTEXTENSION'}) + { + $variableshashref->{'LCPRODUCTEXTENSION'} = "\-" . lc($variableshashref->{'SHORT_PRODUCTEXTENSION'}); # including the "-" ! + } + else + { + $variableshashref->{'LCPRODUCTEXTENSION'} = ""; + } + + if ( $installer::globals::patch ) { $variableshashref->{'PRODUCTADDON'} = $installer::globals::patchaddon; } + elsif ( $installer::globals::languagepack ) { $variableshashref->{'PRODUCTADDON'} = $installer::globals::languagepackaddon; } + else { $variableshashref->{'PRODUCTADDON'} = ""; } + + my $localbuild = $installer::globals::build; + if ( $localbuild =~ /^\s*(\w+?)(\d+)\s*$/ ) { $localbuild = $2; } # using "680" instead of "src680" + $variableshashref->{'PRODUCTMAJOR'} = $localbuild; + + my $localminor = ""; + if ( $installer::globals::minor ne "" ) { $localminor = $installer::globals::minor; } + else { $localminor = $installer::globals::lastminor; } + if ( $localminor =~ /^\s*\w(\d+)\w*\s*$/ ) { $localminor = $1; } + $variableshashref->{'PRODUCTMINOR'} = $localminor; + + $variableshashref->{'PRODUCTBUILDID'} = $installer::globals::buildid; +} + +1; diff --git a/solenv/bin/modules/macosxotoolhelper.pm b/solenv/bin/modules/macosxotoolhelper.pm new file mode 100644 index 000000000000..9c787f372dc0 --- /dev/null +++ b/solenv/bin/modules/macosxotoolhelper.pm @@ -0,0 +1,48 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: macosxotoolhelper.pm,v $ +# +# $Revision: 1.3 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package macosxotoolhelper; +require Exporter; +our @ISA = Exporter; +our @EXPORT = otoolD; + +sub otoolD($) { + my ($file) = @_; + my $call = "otool -D $file"; + open(IN, "-|", $call) or die "cannot $call"; + my $line = <IN>; + $line =~ /^$file:\n$/ or + die "unexpected otool -D output (\"$line\", expecting \"$file:\")"; + $line = <IN> or die "unexpected otool -D output"; + <IN> == undef or die "unexpected otool -D output"; + close(IN); + return $line; +} diff --git a/solenv/bin/modules/osarch.pm b/solenv/bin/modules/osarch.pm new file mode 100755 index 000000000000..8c3a87e4ddc5 --- /dev/null +++ b/solenv/bin/modules/osarch.pm @@ -0,0 +1,198 @@ +#!/usr/bin/perl -w + +# *********************************************************************** +# Description: +# Filename: osarch.pm +# Autor: EG +# Date: 28.10.96 +# $Header: /zpool/svn/migration/cvs_rep_09_09_08/code/solenv/bin/modules/osarch.pm,v 1.3 2008-08-18 13:11:04 vg Exp $ +# Copyright: STAR DIVISION +# **********************************************************************/ + +package osarch; + +$m_str = `uname -m`; +$s_str = `uname -s`; +chop( $m_str, $s_str ); + +%osTable = ("SunOS", "solaris", + "HP-UX", "hpux", + "AIX", "aix", + "OS/390", "s390", + "Linux", "linux", + "FreeBSD", "freebsd", + "NetBSD", "netbsd", + "OSF1", "decunix", + "SCO_SV", "scoosr5", +# "SCO_SV", "scouw21", + "Darwin", "macosxp", + "Mac OS", "macosxp", + "SINIX-N", "sinix", + "IRIX", "irix" + ); + +%osDefTable = ("SunOS", "-DSYSV -DSOLARIS", + "HP-UX", "-DSYSV -DHPUX", + "AIX", "-DSYSV -DAIX", + "Linux", "-DLINUX", + "FreeBSD", "-DFREEBSD", + "NetBSD", "-DNETBSD", + "OSF1", "-DSYSV -DDECUNIX", + "SCO_SV", "-DSYSV -DSCO -DSCO_OSR5", +# "SCO_SV", "-DSYSV -DSCO -DSCO_UW21", + "Darwin", "-DBSD -DMACOSX", + "Mac OS", "-DBSD -DMACOSX", + "SINIX-N", "-DSYSV -DSINIX", + "IRIX", "-DSYSV -DIRIX" + ); + +%osDosTable = ("SunOS", "sol", + "HP-UX", "hpx", + "AIX", "aix", + "OS/390", "mvs", + "Linux", "lng", + "FreeBSD", "fbsd", + "NetBSD", "bsd", + "SCO_SV", "sco", + "Darwin", "macx", + "Mac OS", "macx", + "SINIX-N", "sni", + "IRIX", "irx" + ); + +%archTable = ("sun4c", "sparc", + "sun4m", "sparc", + "sun4u", "sparc", + "9000/712", "hp9000", + "9000/715", "hp9000", + "9000/778", "hp9000", + "000029484600", "rs6000", # salsa + "000328144600", "rs6000", # lambada + "00245D29E000", "rs6000", # segv + "00245C46E000", "rs6000", # bus + "002012974600", "rs6000", # tango + "0006404C4C00", "rs6000", # jive + "2003", "g3", # ezopen4 + "i86pc", "x86", # blauwal + "i386", "x86", # SCO_SV, NetBSD, FreeBSD + "i486", "x86", # tiger + "i586", "x86", # blauwal + "i686", "x86", + "prep", "ppc", # hooge + "ppc", "ppc", # ppc-linux + "alpha", "alpha", + "RM400", "rm400", # garbo + "IP22", "mips", # voyager + "IP32", "mips", # giotto + "Power Macintosh", "ppc", # NetBSD/arm32 + "arm32", "arm32" # NetBSD/arm32 + ); + +%archDefTable=("sun4c", "-DSPARC -DSUN -DSUN4", # hawai + "sun4m", "-DSPARC -DSUN -DSUN4", # broccoli + "sun4u", "-DSPARC -DSUN -DSUN4", # broccoli + "9000/712", "-DHP9000", # tuborg + "9000/715", "-DHP9000", # koepi + "9000/778", "-DHP9000", # jever, flens + "000029484600", "-DRS6000", # salsa + "000328144600", "-DRS6000", # lambada + "00245D29E000", "-DRS6000", # segv + "00245C46E000", "-DRS6000", # segv + "002012974600", "-DRS6000", # tango + "0006404C4C00", "-DRS6000", # jive + "2003", "-DG3", # ezopen4 + "i86pc", "-DX86 -DINTEL",# gepard + "i386", "-DX86", # SCO_SV, NetBSD, FreeBSD + "i486", "-DX86", # tiger + "i586", "-DX86", # blauwal + "i686", "-DX86", # + "prep", "-DPPC", # hooge + "ppc", "-DPPC", # ppc-linux + "alpha", "-DALPHA", # mars + "RM400", "-DMIPS -DRM400", # ekberg, garbo + "IP22", "-DMIPS", # voyager + "IP32", "-DMIPS", # giotto + "Power Macintosh", "-DPPC", # NetBSD/arm32 + "arm32", "-DARM32" # NetBSD/arm32 + ); + +%archDosTable=("sun4c", "s", # hawai + "sun4m", "s", # broccoli + "sun4u", "s", # broccoli + "9000/712", "r", # tuborg + "9000/715", "r", # koepi + "9000/778", "r", # jever, flens + "000029484600", "p", # salsa + "000328144600", "p", # lambada + "00245D29E000", "p", # segv + "00245C46E000", "p", # segv + "002012974600", "p", # tango + "0006404C4C00", "p", # jive + "2003", "g", # ezopen4 + "i86pc", "i", # gepard + "i386", "i", # SCO_SV, NetBSD, FreeBSD + "i486", "i", # tiger + "i586", "i", # blauwal + "i686", "i", + "prep", "p", # hooge + "ppc", "p", # ppc-linux + "alpha", "a", # mars + "RM400", "m", # ekberg, garbo + "IP22", "m", # voyager + "IP32", "m", # giotto + "Power Macintosh", "p", # NetBSD/arm32 + "arm32", "a" # NetBSD/arm32 + ); + +$main::solarDef = $osDefTable{ $s_str }.' '.$archDefTable{ $m_str }; + +$main::solarOS = $osTable{ $s_str }; +$main::solarMT = $archTable{ $m_str }; + +$main::solarArch = $main::solarOS.$main::solarMT; +$main::solarOldArch = $main::solarArch; # for compatibility + +$main::solarDOS = 'unx'.$osDosTable{ $s_str }. $archDosTable{ $m_str }; + +sub main::osarch +{ + local ( $flag ) = @_; + + $perlFlag = $flag eq 'perl'; + $defFlag = $flag eq 'def'; + $oldFlag = $flag eq 'old'; + $dirFlag = $flag eq 'dir'; + $dosFlag = $flag eq 'dos'; + + local( $result ) = ( '' ); + + if ( $perlFlag ) + { + $result .= '$solarDef = '."'$main::solarDef';\n"; + $result .= '$solarArch = '."'$main::solarArch';\n"; + $result .= '$solarOldArch = '."'$main::solarOldArch';\n"; + $result .= '$solarOS = '."'$main::solarOS';\n"; + $result .= '$solarMT = '."'$main::solarMT';\n"; + $result .= '$solarDOS = '."'$main::solarDOS';"; + } + elsif ( $defFlag ) + { + $result = $main::solarDef; + } + elsif ( $dirFlag ) + { + $result = "$main::solarOS-$main::solarMT"; + } + elsif ( $dosFlag ) + { + $result = $main::solarDOS; + } + else + { + $result = $oldFlag ? $main::solarOldArch : $main::solarArch; + } + + return $result; +} + +1; diff --git a/solenv/bin/modules/packager/check.pm b/solenv/bin/modules/packager/check.pm new file mode 100644 index 000000000000..1b1aaedab46f --- /dev/null +++ b/solenv/bin/modules/packager/check.pm @@ -0,0 +1,92 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: check.pm,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package packager::check; + +use packager::exiter; +use packager::globals; + +############################################## +# Check 1: The package list has to exist +############################################## + +sub check_packlist +{ + my $projectdir = $ENV{'PRJ'}; + $projectdir =~ s/$packager::globals::separator\s*$//; + $packager::globals::packlistname = $projectdir . $packager::globals::separator . "util" . $packager::globals::separator . $packager::globals::packlistname; + + if ( ! -f $packager::globals::packlistname ) + { + packager::exiter::exit_program("ERROR: Package list not found: $packager::globals::packlistname", "check_packlist"); + } +} + +############################################################# +# Check 2: The environment variable OUTPATH has to be set +############################################################# + +sub check_environment +{ + if ( ! $ENV{'OUTPATH'} ) + { + packager::exiter::exit_program("ERROR: Environment variable OUTPATH not set!", "check_environment"); + } + + if ( ! $ENV{'PRJ'} ) + { + packager::exiter::exit_program("ERROR: Environment variable PRJ not set!", "check_environment"); + } +} + +############################################################# +# Check 3: Checking the parameter. Only "-i" is valid +############################################################# + +sub check_parameter +{ + while ( $#ARGV >= 0 ) + { + my $param = shift(@ARGV); + + if ($param eq "-i") { $packager::globals::ignoreerrors = 1; } + else + { + print("\n*************************************\n"); + print("Sorry, unknown parameter: $param"); + print("\n*************************************\n"); + usage(); + exit(-1); + } + } +} + +1; diff --git a/solenv/bin/modules/packager/existence.pm b/solenv/bin/modules/packager/existence.pm new file mode 100644 index 000000000000..e3b3d99d4e35 --- /dev/null +++ b/solenv/bin/modules/packager/existence.pm @@ -0,0 +1,56 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: existence.pm,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package packager::existence; + +############################# +# Test of existence +############################# + +sub exists_in_array +{ + my ($searchstring, $arrayref) = @_; + + my $alreadyexists = 0; + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + if ( ${$arrayref}[$i] eq $searchstring) + { + $alreadyexists = 1; + last; + } + } + + return $alreadyexists; +} + +1; diff --git a/solenv/bin/modules/packager/exiter.pm b/solenv/bin/modules/packager/exiter.pm new file mode 100644 index 000000000000..fbbbbbc719ec --- /dev/null +++ b/solenv/bin/modules/packager/exiter.pm @@ -0,0 +1,75 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: exiter.pm,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +package packager::exiter; + +use packager::files; +use packager::globals; + +############################################ +# Exiting the program with an error +# This function is used instead of "die" +############################################ + +sub exit_program +{ + my ($message, $function) = @_; + + my $infoline; + + $infoline = "\n***************************************************************\n"; + push(@packager::globals::logfileinfo, $infoline); + print("$infoline"); + + $infoline = "$message\n"; + push(@packager::globals::logfileinfo, $infoline); + print("$infoline"); + + $infoline = "in function: $function\n"; + push(@packager::globals::logfileinfo, $infoline); + print("$infoline"); + + $infoline = "***************************************************************\n"; + push(@packager::globals::logfileinfo, $infoline); + + if ( $packager::globals::logging ) + { + packager::files::save_file($packager::globals::logfilename ,\@packager::globals::logfileinfo); + print("Saved logfile: $packager::globals::logfilename\n"); + } + + print("$infoline"); + + exit(-1); +} + +1; diff --git a/solenv/bin/modules/packager/files.pm b/solenv/bin/modules/packager/files.pm new file mode 100644 index 000000000000..d2054838fa12 --- /dev/null +++ b/solenv/bin/modules/packager/files.pm @@ -0,0 +1,188 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: files.pm,v $ +# +# $Revision: 1.8 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +package packager::files; + +use packager::exiter; + +############################################ +# File Operations +############################################ + +sub check_file +{ + my ($arg) = @_; + + if(!( -f $arg )) + { + packager::exiter::exit_program("ERROR: Cannot find file $arg", "check_file"); + } +} + +sub read_file +{ + my ($localfile) = @_; + + if ( ! open( IN, $localfile ) ) { + # try again - sometimes we get errors caused by race conditions in parallel builds + sleep 5; + open( IN, $localfile ) or packager::exiter::exit_program("ERROR: Cannot open file: $localfile", "read_file"); + } + my @localfile = <IN>; + close( IN ); + + return \@localfile; +} + +########################################### +# Saving files +########################################### + +sub save_file +{ + my ($savefile, $savecontent) = @_; + open( OUT, ">$savefile" ); + print OUT @{$savecontent}; + close( OUT); + if (! -f $savefile) { packager::exiter::exit_program("ERROR: Cannot write file: $savefile", "save_file"); } +} + +###################################################### +# Creating a new direcotory +###################################################### + +sub create_directory +{ + my ($directory) = @_; + + my $returnvalue = 1; + + if (!(-d $directory)) + { + $returnvalue = mkdir($directory, 0775); + + if ($returnvalue) + { + $infoline = "\nCreated directory: $directory\n"; + push(@packager::globals::logfileinfo, $infoline); + + if ($packager::globals::isunix) + { + my $localcall = "chmod 775 $directory \>\/dev\/null 2\>\&1"; + system($localcall); + } + } + else + { + packager::exiter::exit_program("ERROR: Could not create directory: $directory", "create_directory"); + } + } +} + +###################################################### +# Creating a unique directory with number extension +###################################################### + +sub create_unique_directory +{ + my ($directory) = @_; + + $directory =~ s/\Q$packager::globals::separator\E\s*$//; + $directory = $directory . "_INCREASINGNUMBER"; + + my $counter = 1; + my $created = 0; + my $localdirectory = ""; + + do + { + $localdirectory = $directory; + $localdirectory =~ s/INCREASINGNUMBER/$counter/; + $counter++; + + if ( ! -d $localdirectory ) + { + create_directory($localdirectory); + $created = 1; + } + } + while ( ! $created ); + + return $localdirectory; +} + +###################################################### +# Removing a complete directory with subdirectories +###################################################### + +sub remove_complete_directory +{ + my ($directory) = @_; + + my @content = (); + + $directory =~ s/\Q$packager::globals::separator\E\s*$//; + + if ( -d $directory ) + { + opendir(DIR, $directory); + @content = readdir(DIR); + closedir(DIR); + + my $oneitem; + + foreach $oneitem (@content) + { + if ((!($oneitem eq ".")) && (!($oneitem eq ".."))) + { + my $item = $directory . $packager::globals::separator . $oneitem; + + if ( -f $item ) # deleting files + { + unlink($item); + } + + if ( -d $item ) # recursive + { + remove_complete_directory($item, 0); + } + } + } + + # try to remove empty directory + + rmdir $directory; + + } +} + +1; diff --git a/solenv/bin/modules/packager/globals.pm b/solenv/bin/modules/packager/globals.pm new file mode 100644 index 000000000000..f1581126ef24 --- /dev/null +++ b/solenv/bin/modules/packager/globals.pm @@ -0,0 +1,67 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: globals.pm,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package packager::globals; + +############################################ +# Global settings +############################################ + +BEGIN +{ + $prog="packager"; + + $packlistname = "pack.lst"; + $compiler = ""; + $ignoreerrors = 0; + + $logging = 0; + $logfilename = "packager_logfile.log"; # the default logfile name for global errors + @logfileinfo = (); + + $plat = $^O; + + if (( $plat =~ /MSWin/i ) || (( $plat =~ /cygwin/i ) && ( $ENV{'USE_SHELL'} eq "4nt" ))) + { + $separator = "\\"; + $iswin = 1; + $isunix = 0; + } + else + { + $separator = "/"; + $iswin = 0; + $isunix = 1; + } + +} + +1; diff --git a/solenv/bin/modules/packager/work.pm b/solenv/bin/modules/packager/work.pm new file mode 100644 index 000000000000..43a1ae2abe77 --- /dev/null +++ b/solenv/bin/modules/packager/work.pm @@ -0,0 +1,331 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: work.pm,v $ +# +# $Revision: 1.11 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +package packager::work; + +use packager::exiter; +use packager::existence; +use packager::files; +use packager::globals; + +########################################### +# Setting global variables +########################################### + +sub set_global_variable +{ + my $compiler = $ENV{'OUTPATH'}; + + if ( $ENV{'PROEXT'} ) { $compiler = $compiler . $ENV{'PROEXT'}; } + + $packager::globals::compiler = $compiler; +} + +############################################################################# +# Converting a string list with separator $listseparator +# into an array +############################################################################# + +sub convert_stringlist_into_array +{ + my ( $includestringref, $listseparator ) = @_; + + my @newarray = (); + my $first; + my $last = ${$includestringref}; + + while ( $last =~ /^\s*(.+?)\Q$listseparator\E(.+)\s*$/) # "$" for minimal matching + { + $first = $1; + $last = $2; + push(@newarray, "$first"); + } + + push(@newarray, "$last"); + + return \@newarray; +} + +########################################### +# Generating a list of package calls +# corresponding to the package list +########################################### + +sub create_package_todos +{ + my ( $packagelist ) = @_; + + my @targets = (); # only used, if the build server is not used + + for ( my $i = 0; $i <= $#{$packagelist}; $i++ ) + { + my $line = ${$packagelist}[$i]; + + if ( $line =~ /^\s*\#/ ) { next; } # comment line + + if ( $line =~ /^\s*(\w+?)\s+(\S+?)\s+(\S+?)\s+(\w+?)\s*$/ ) + { + my $product = $1; + my $compilerlist = $2; + my $languagelist = $3; + my $target = $4; + + $product =~ s/\s//g; + $compilerlist =~ s/\s//g; + $languagelist =~ s/\s//g; + $target =~ s/\s//g; + + my $compilers = convert_stringlist_into_array(\$compilerlist, ","); + + # is the compiler of this "build" part of the compiler list in pack.lst ? + + if ( packager::existence::exists_in_array($packager::globals::compiler, $compilers) ) + { + # products are separated in pack.lst by "|" + + my $languagesets = convert_stringlist_into_array(\$languagelist, "\|"); + + # now all information is available to create the targets for the systemcalls + + for ( my $j = 0; $j <= $#{$languagesets}; $j++ ) + { + my $languagestring = ${$languagesets}[$j]; + $languagestring =~ s/\,/\_/g; # comma in pack.lst becomes "_" in dmake command + + my $target = $target . "_" . $languagestring; + push(@targets, $target); + + my $insertline = $target . "\n"; + push( @packager::globals::logfileinfo, $insertline); + } + } + } + } + + return \@targets; +} + +########################################### +# Executing the generated system calls +########################################### + +sub execute_system_calls +{ + my ( $targets ) = @_; + + for ( my $i = 0; $i <= $#{$targets}; $i++ ) + { + my $systemcall = "dmake " . ${$targets}[$i]; + + my $infoline = "Packager: $systemcall\n"; + print $infoline; + push( @packager::globals::logfileinfo, $infoline); + + my $returnvalue = system($systemcall); + + $infoline = "Packager finished: $systemcall\n"; + print $infoline; + push( @packager::globals::logfileinfo, $infoline); + + if ( $returnvalue ) + { + $infoline = "\nERROR: Packager $systemcall\n"; + print $infoline; + push( @packager::globals::logfileinfo, $infoline); + if (!($packager::globals::ignoreerrors)) { packager::exiter::exit_program("ERROR: Packing not successful : $systemcall", "execute_system_calls"); } + } + } +} + +############################################################## +# Starting the build server with the generated system calls +############################################################## + +sub start_build_server +{ + my ( $targets ) = @_; + + # preparing the directory structure + + my $prj = $ENV{PRJ}; # for example ".."; + my $platform = $ENV{INPATH}; # wntmsci10.pro, unxsols4.pro + my $platformpath = $prj . $packager::globals::separator . $platform; + if ( ! -d $platformpath ) { packager::files::create_directory($miscpath); } + my $miscpath = $platformpath . $packager::globals::separator . "misc"; + if ( ! -d $miscpath ) { packager::files::create_directory($miscpath); } + $miscpath = $miscpath . $packager::globals::separator . "temp"; + if ( -d $miscpath ) { packager::files::remove_complete_directory($miscpath); } # removing old files ! + if ( ! -d $miscpath ) { packager::files::create_directory($miscpath); } + + my $prjroot = ".." . $packager::globals::separator . ".." . $packager::globals::separator . ".." . $packager::globals::separator . ".."; # platform/misc/temp/uniquetempdir + + my $makefilepath = $prj . $packager::globals::separator . "util" . $packager::globals::separator . "makefile.mk"; + + if ( ! $ENV{'PRJNAME'} ) { packager::exiter::exit_program("ERROR: Environment variable PRJNAME not set!", "do_broadcast"); } + my $prjname = $ENV{PRJNAME}; + + my $pkgformat = $ENV{PKGFORMAT}; + + my $prjdep = $prjname . "\\" . "util"; # always windows like path + my @targetdirs; + my @targetlines = (); + # iterating over all targets + for ( my $i = 0; $i <= $#{$targets}; $i++ ) + { + my $target = ${$targets}[$i]; + my $tempdir = $miscpath . $packager::globals::separator . $target; + $tempdir = packager::files::create_unique_directory ($tempdir); + @targetlines=(); + push( @targetlines, "\ngenerated_target : $target\n\n"); # to be included into the makefile.mk + + if ( defined $pkgformat ) { + push( @targetlines, "\n$target : ".'$$@{$(PKGFORMAT:^".")}'."\n\n"); # to be included into the makefile.mk + } + + generate_makefile($tempdir, $makefilepath, $prjroot, $target, \@targetlines); + + do_broadcast($tempdir, $prjname, $prj, $platform, $prjdep); + push @targetdirs, $tempdir; + } +} + +############################################################## +# Generating the makefile in the temporary directory +############################################################## + +sub generate_makefile +{ + my ( $tempdir, $makefilepath, $prjroot, $target, $targetlines_ref ) = @_; + + my $makefile = packager::files::read_file($makefilepath); + + my @targetlines = (); + push( @targetlines, @{$targetlines_ref}); # to be included into the makefile.mk + + $prjroot = $prjroot . "\n"; + + my $uniquename = $tempdir; + get_filename_from_path(\$uniquename); + $uniquename = $uniquename . "\n"; + + my $counter = 0; + my $increase = 1; + + for ( my $i = 0; $i <= $#{$makefile}; $i++ ) + { + if ( ${$makefile}[$i] =~ /^\s*TARGET\s*=.*/ ) { ${$makefile}[$i] = "TARGET=" . $uniquename; } # setting the new project root + + if ( ${$makefile}[$i] =~ /^\s*PRJ\s*=.*/ ) { ${$makefile}[$i] = "PRJ=" . $prjroot; } # setting the new project root + + if ( ${$makefile}[$i] =~ /^\s*\.INCLUDE[\t ]*:[\t ]*target.mk[\t ]*$/ ) { $increase = 0; } # no more increase of the counter + + if ( $increase ) { $counter++; } + } + + splice(@{$makefile}, $counter, 0, @targetlines); # including the new target lines at position $counter + + my $newmakefilepath = $tempdir . $packager::globals::separator . "makefile.mk"; + packager::files::save_file($newmakefilepath, $makefile); +} + +############################################################## +# Generating the broadcasts for the build server +############################################################## + +sub do_broadcast +{ + use File::Temp; + + my ( $tempdir, $prjname, $prj, $platform, $prjdep ) = @_; + + # Syntax: cmd_bcst -s 18 "Version;Environment;Project;Verzeichnis;Restriction[;Abhaengigkeit1][;Abhaengigkeit n]..." + # Example: cmd_bcst -s 18 "SRC680;wntmsci10.pro;instsetoo_native;;instsetoo_native\bla1;instsetoo_native\util" + + if ( ! $ENV{'WORK_STAMP'} ) { packager::exiter::exit_program("ERROR: Environment variable WORK_STAMP not set!", "do_broadcast"); } + my $workstamp = $ENV{WORK_STAMP}; + my $cwsworkstamp = $ENV{CWS_WORK_STAMP}; + + my $prjdir = $tempdir; + $prjdir =~ s/$prj/$prjname/; + $prjdir =~ s/\//\\/g; # convert to windows path syntax + + my $tempfiledir = $ENV{TMP}; + $tempfiledir = $tempdir if ( ! defined $tempfiledir ); + my ( $tmpfile_handle, $tmpfile_name ) = mkstemp( $tempfiledir . $packager::globals::separator . "packagerXXXXX"); + if ( ! $tmpfile_handle ) { + packager::exiter::exit_program("ERROR: Couldn't open temporary file \"$tmpfile_name\"!", "do_broadcast"); + } + if (defined($cwsworkstamp)) { + print $tmpfile_handle "\"$cwsworkstamp;$platform;$prjname;$prjdir;nobase;$prjdep\""; + print "to tmpfile: \"$cwsworkstamp;$platform;$prjname;$prjdir;nobase;$prjdep\"\n"; + } + else { + print $tmpfile_handle "\"$workstamp;$platform;$prjname;$prjdir;nobase;$prjdep\""; + print "to tmpfile: \"$workstamp;$platform;$prjname;$prjdir;nobase;$prjdep\"\n"; + } + close $tmpfile_handle; + my $returnvalue = system("cmd_bcst -s 18 \@$tmpfile_name"); + print "cmd_bcst -s 18 \@$tmpfile_name\n"; + unlink "$tmpfile_name"; + + if ( $returnvalue ) # an error occured + { + if (!($packager::globals::ignoreerrors)) { packager::exiter::exit_program("ERROR: Packing not successful!", "do_broadcast"); } + } +} + +############################################################## +# Returning the name of file or directory from complete path +############################################################## + +sub get_filename_from_path +{ + my ($longfilenameref) = @_; + + if ( $packager::globals::isunix ) + { + if ( $$longfilenameref =~ /^.*\/(\S.+\S?)/ ) + { + $$longfilenameref = $1; + } + } + + if ( $packager::globals::iswin ) + { + if ( $$longfilenameref =~ /^.*\\(\S.+\S?)/ ) + { + $$longfilenameref = $1; + } + } +} + +1; diff --git a/solenv/bin/modules/par2script/check.pm b/solenv/bin/modules/par2script/check.pm new file mode 100644 index 000000000000..70b557f94d25 --- /dev/null +++ b/solenv/bin/modules/par2script/check.pm @@ -0,0 +1,400 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: check.pm,v $ +# +# $Revision: 1.8 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package par2script::check; + +use par2script::globals; + +################################ +# Checks of the setup script +################################ + +######################################################## +# Checking if all defined directories are needed +######################################################## + +sub check_needed_directories +{ + my $allfiles = $par2script::globals::definitions{'File'}; + my $alldirs = $par2script::globals::definitions{'Directory'}; + + # checking if all defined directories are needed + + my $dir; + foreach $dir ( keys %{$alldirs} ) + { + # I. directory has create flag + if (( exists($alldirs->{$dir}->{'Styles'}) ) && ( $alldirs->{$dir}->{'Styles'} =~ /\bCREATE\b/ )) { next; } + + # II. there is at least one file in the directory + my $fileinside = 0; + my $file; + foreach $file ( keys %{$allfiles} ) + { + if (( $allfiles->{$file}->{'Dir'} eq $dir ) || ( $allfiles->{$file}->{'NetDir'} eq $dir )) + { + $fileinside = 1; + last; + } + } + if ( $fileinside ) { next; } + + # III. the directory is parent for another directory + my $isparent = 0; + my $onedir; + foreach $onedir ( keys %{$alldirs} ) + { + if ( $alldirs->{$onedir}->{'ParentID'} eq $dir ) + { + $isparent = 1; + last; + } + } + if ( $isparent ) { next; } + + # no condition is true -> directory definition is superfluous + my $infoline = "\tINFO: Directory definition $dir is superfluous\n"; + # print $infoline; + push(@par2script::globals::logfileinfo, $infoline); + } +} + +################################################## +# Checking if the directories in the item +# definitions are defined. +################################################## + +sub check_directories_in_item_definitions +{ + my $item; + foreach $item ( @par2script::globals::items_with_directories ) + { + my $allitems = $par2script::globals::definitions{$item}; + + my $onegid; + foreach $onegid ( keys %{$allitems} ) + { + if ( ! exists($allitems->{$onegid}->{'Dir'}) ) { die "\nERROR: No directory defined for item: $onegid!\n\n"; } + my $dir = $allitems->{$onegid}->{'Dir'}; + if (( $dir eq "PD_PROGDIR" ) || ( $dir =~ /PREDEFINED_/ )) { next; } + + # checking if this directoryid is defined + if ( ! exists($par2script::globals::definitions{'Directory'}->{$dir}) ) + { + die "\nERROR: Directory $dir in item $onegid not defined!\n\n"; + } + } + } +} + +######################################################## +# Checking for all Items, that know their modules, +# whether these modules exist. +######################################################## + +sub check_module_existence +{ + my $item; + foreach $item ( @par2script::globals::items_with_moduleid ) + { + my $allitems = $par2script::globals::definitions{$item}; + + my $onegid; + foreach $onegid ( keys %{$allitems} ) + { + if ( ! exists($allitems->{$onegid}->{'ModuleID'}) ) { die "\nERROR: No ModuleID defined for item: $onegid!\n\n"; } + my $moduleid = $allitems->{$onegid}->{'ModuleID'}; + + # checking if this directoryid is defined + if ( ! exists($par2script::globals::definitions{'Module'}->{$moduleid}) ) + { + die "\nERROR: ModuleID $moduleid in item $onegid not defined!\n\n"; + } + } + } +} + +######################################################## +# If the StarRegistry is not defined in the script, +# it has to be removed from the file definition. +######################################################## + +sub check_registry_at_files +{ + my %starregistrygid = (); + + my $item; + foreach $item ( keys %{$par2script::globals::definitions{'File'}} ) + { + if (( exists($par2script::globals::definitions{'File'}->{$item}->{'Styles'}) ) && + ( $par2script::globals::definitions{'File'}->{$item}->{'Styles'} =~ /\bSTARREGISTRY\b/ )) + { + $starregistrygid{$item} = 1; + } + } + + foreach $item ( keys %{$par2script::globals::definitions{'File'}} ) + { + if ( exists($par2script::globals::definitions{'File'}->{$item}->{'RegistryID'}) ) + { + my $registryid = $par2script::globals::definitions{'File'}->{$item}->{'RegistryID'}; + if ( ! exists($starregistrygid{$registryid}) ) + { + die "\nERROR: No definition found for $registryid at file $item\n\n"; + } + + # if ( ! ( $par2script::globals::definitions{'File'}->{$item}->{'Styles'} =~ /\bUNO_COMPONENT\b/ )) + # { + # die "\nERROR: Flag UNO_COMPONENT required for file $item\n\n"; + # } + # -> also possible, that Regmergefile is defined (does not require flag UNO_COMPONENT) + } + + # and also vice versa + + if (( exists($par2script::globals::definitions{'File'}->{$item}->{'Styles'}) ) && + ( $par2script::globals::definitions{'File'}->{$item}->{'Styles'} =~ /\bUNO_COMPONENT\b/ )) + { + if ( ! exists($par2script::globals::definitions{'File'}->{$item}->{'RegistryID'}) ) + { + die "\nERROR: Flag UNO_COMPONENT defined, but no file as \"RegistryID\" at file $item !\n\n"; + } + } + } +} + +######################################################## +# Every script has to contain exactly one root module. +# This module has no ParentID or an empty ParentID. +######################################################## + +sub check_rootmodule +{ + my $rootgid = ""; + my $foundroot = 0; + + my $allmodules = $par2script::globals::definitions{'Module'}; + + my $modulegid = ""; + foreach $modulegid (keys %{$allmodules} ) + { + if (( ! exists($allmodules->{$modulegid}->{'ParentID'}) ) || ( $allmodules->{$modulegid}->{'ParentID'} eq "" )) + { + if ( $foundroot ) + { + die "\nERROR: More than one Root module. Only one module without ParentID or with empty ParentID allowed ($rootgid and $modulegid).\n"; + } + $rootgid = $modulegid; + $foundroot = 1; + } + } + + if ( ! $foundroot ) + { + die "\nERROR: Could not find Root module. Did not find module without ParentID or with empty ParentID.\n"; + } + + print " $rootgid\n"; + +} + +######################################################## +# File, Shortcut, Directory, Unixlink must not +# contain a ModuleID +######################################################## + +sub check_moduleid_at_items +{ + my $item; + foreach $item ( @par2script::globals::items_without_moduleid ) + { + my $allitems = $par2script::globals::definitions{$item}; + + my $onegid; + foreach $onegid ( keys %{$allitems} ) + { + if ( exists($allitems->{$onegid}->{'ModuleID'}) ) + { + die "\nERROR: ModuleID assigned to $onegid! No module assignment to $item!\n\n"; + } + } + } +} + +######################################################## +# Controlling existence of multi assignments +######################################################## + +sub check_multiple_assignments +{ + my @multiassignments = (); + my $error; + + my $topitem; + foreach $topitem ( keys %par2script::globals::assignedgids ) + { + my $item; + foreach $item ( keys %{$par2script::globals::assignedgids{$topitem}} ) + { + if ( $par2script::globals::assignedgids{$topitem}->{$item} > 1 ) + { + $error = 1; + my $string = "\tGID: $item Assignments: $par2script::globals::assignedgids{$topitem}->{$item}"; + push(@multiassignments, $string); + } + } + } + + if ( $error ) { par2script::exiter::multiassignmenterror(\@multiassignments); } +} + +######################################################## +# Check, if a defined directory has a flag CREATE +######################################################## + +sub contains_create_flag +{ + my ($gid) = @_; + + my $createflag = 0; + + if (( exists($par2script::globals::definitions{'Directory'}->{$gid}->{'Styles'}) ) && + ( $par2script::globals::definitions{'Directory'}->{$gid}->{'Styles'} =~ /\bCREATE\b/ )) + { + $createflag = 1; + } + + return $createflag; +} + +######################################################## +# Controlling existence of definitions without +# any assignment +######################################################## + +sub check_missing_assignments +{ + # If defined gids for "File", "Directory" or "Unixlink" are not assigned, + # this causes an error. + # Directories only have to be assigned, if they have the flag "CREATE". + + my @missingassignments = (); + $error = 0; + + my $item; + foreach $item ( @par2script::globals::items_assigned_at_modules ) + { + my $assignedgids = $par2script::globals::assignedgids{$item}; + my $definedgids = $par2script::globals::definitions{$item}; + + my $gid; + foreach $gid ( keys %{$definedgids} ) + { + if ( $item eq "Directory" ) { if ( ! contains_create_flag($gid) ) { next; } } + + if ( ! exists( $assignedgids->{$gid} )) + { + $error = 1; + push(@missingassignments, $gid); + } + } + } + + if ( $error ) { par2script::exiter::missingassignmenterror(\@missingassignments); } +} + +############################################################# +# Controlling if for all shortcuts with file assignment +# the file is defined. And for all shortcuts with +# shortcut assignment the shortcut has to be defined. +############################################################# + +sub check_shortcut_assignments +{ + my $allshortcuts = $par2script::globals::definitions{'Shortcut'}; + my $allfiles = $par2script::globals::definitions{'File'}; + + my $shortcut; + foreach $shortcut ( keys %{$allshortcuts} ) + { + if (( exists($allshortcuts->{$shortcut}->{'FileID'}) ) && + ( ! exists($allfiles->{$allshortcuts->{$shortcut}->{'FileID'}}) )) + { + # die "\nERROR: FileID $allshortcuts->{$shortcut}->{'FileID'} has no definition at shortcut $shortcut !\n"; + print "\n\tWARNING: FileID $allshortcuts->{$shortcut}->{'FileID'} has no definition at shortcut $shortcut !\n"; + } + + if (( exists($allshortcuts->{$shortcut}->{'ShortcutID'}) ) && + ( ! exists($allshortcuts->{$allshortcuts->{$shortcut}->{'ShortcutID'}}) )) + { + die "\nERROR: ShortcutID $allshortcuts->{$shortcut}->{'ShortcutID'} has no definition at shortcut $shortcut !\n"; + } + + if (( ! exists($allshortcuts->{$shortcut}->{'ShortcutID'}) ) && + ( ! exists($allshortcuts->{$shortcut}->{'FileID'}) )) + { + die "\nERROR: Shortcut requires assignment to \"ShortcutID\" or \"FileID\". Missing at shortcut $shortcut !\n"; + } + } +} + +############################################################# +# Controlling if for Modules and Directories, the parents +# are defined. If not, this can lead to a problem during +# script creation, because only recursively added +# Modules or Directories are added to the script. +############################################################# + +sub check_missing_parents +{ + my @parentitems = ("Module", "Directory"); + my %rootparents = ("PREDEFINED_PROGDIR" => "1"); + + my $oneitem; + foreach $oneitem ( @parentitems ) + { + my $alldefinitions = $par2script::globals::definitions{$oneitem}; + + my $onegid; + foreach $onegid ( keys %{$alldefinitions} ) + { + # If there is a ParentID used, it must be defined + if (( exists($alldefinitions->{$onegid}->{'ParentID'}) ) && + ( ! exists($alldefinitions->{$alldefinitions->{$onegid}->{'ParentID'}}) ) && + ( ! exists($rootparents{$alldefinitions->{$onegid}->{'ParentID'}}) )) + { + die "\nERROR: Parent \"$alldefinitions->{$onegid}->{'ParentID'}\" at $oneitem \"$onegid\" is not defined!\n"; + } + } + } +} + +1; diff --git a/solenv/bin/modules/par2script/converter.pm b/solenv/bin/modules/par2script/converter.pm new file mode 100644 index 000000000000..1adff9b2bf0b --- /dev/null +++ b/solenv/bin/modules/par2script/converter.pm @@ -0,0 +1,146 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: converter.pm,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +package par2script::converter; + +use par2script::remover; + +############################# +# Converter +############################# + +sub convert_array_to_hash +{ + my ($arrayref) = @_; + + my ($line, $key, $value); + + my %newhash = (); + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + $line = ${$arrayref}[$i]; + + if ( $line =~ /^\s*(\w+?)\s+(.*?)\s*$/ ) + { + $key = $1; + $value = $2; + $newhash{$key} = $value; + } + } + + return \%newhash; +} + +sub convert_hash_into_array +{ + my ($hashref) = @_; + + my @array = (); + my ($key, $value, $input); + + foreach $key (keys %{$hashref}) + { + $value = $hashref->{$key}; + $input = "$key = $value\n"; + push(@array ,$input); + } + + return \@array +} + +sub convert_stringlist_into_array_2 +{ + my ( $input, $separator ) = @_; + + my @newarray = (); + my $first = ""; + my $last = ""; + + $last = $input; + + while ( $last =~ /^\s*(.+?)\s*\Q$separator\E\s*(.+)\s*$/) # "$" for minimal matching + { + $first = $1; + $last = $2; + par2script::remover::remove_leading_and_ending_whitespaces(\$first); + if ( $first ) { push(@newarray, $first); } + } + + par2script::remover::remove_leading_and_ending_whitespaces(\$last); + if ( $last ) { push(@newarray, $last); } + + return \@newarray; +} + +sub convert_stringlist_into_array +{ + my ( $includestringref, $separator ) = @_; + + my @newarray = (); + my ($first, $last); + + $last = ${$includestringref}; + + while ( $last =~ /^\s*(.+?)\s*\Q$separator\E\s*(.+)\s*$/) # "$" for minimal matching + { + $first = $1; + $last = $2; + par2script::remover::remove_leading_and_ending_whitespaces(\$first); + push(@newarray, $first); + } + + par2script::remover::remove_leading_and_ending_whitespaces(\$last); + push(@newarray, $last); + + return \@newarray; +} + +############################################################################# +# The file name contains for some files "/". If this programs runs on +# a windows platform, this has to be converted to "\". +############################################################################# + +sub convert_slash_to_backslash +{ + my ($filesarrayref) = @_; + + my ($onefile, $filename); + + for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ ) + { + $onefile = ${$filesarrayref}[$i]; + $onefile->{'Name'} =~ s/\//\\/g; + } +} + +1; diff --git a/solenv/bin/modules/par2script/existence.pm b/solenv/bin/modules/par2script/existence.pm new file mode 100644 index 000000000000..a557020647ee --- /dev/null +++ b/solenv/bin/modules/par2script/existence.pm @@ -0,0 +1,78 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: existence.pm,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +package par2script::existence; + +############################# +# Test of existence +############################# + +sub exists_in_array +{ + my ($searchstring, $arrayref) = @_; + + my $alreadyexists = 0; + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + if ( ${$arrayref}[$i] eq $searchstring) + { + $alreadyexists = 1; + last; + } + } + + return $alreadyexists; +} + +sub exists_in_array_of_hashes +{ + my ($searchkey, $searchvalue, $arrayref) = @_; + + my $hashref; + my $valueexists = 0; + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + $hashref = ${$arrayref}[$i]; + + if ( $hashref->{$searchkey} eq $searchvalue ) + { + $valueexists = 1; + last; + } + } + + return $valueexists; +} + +1; diff --git a/solenv/bin/modules/par2script/exiter.pm b/solenv/bin/modules/par2script/exiter.pm new file mode 100644 index 000000000000..ddfe5a9d499b --- /dev/null +++ b/solenv/bin/modules/par2script/exiter.pm @@ -0,0 +1,126 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: exiter.pm,v $ +# +# $Revision: 1.6 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +package par2script::exiter; + +use par2script::files; +use par2script::globals; + +############################################ +# Exiting the program with an error +# This function is used instead of "die" +############################################ + +sub exit_program +{ + my ($message, $function) = @_; + + my $infoline; + + $infoline = "\n***************************************************************\n"; + push(@par2script::globals::logfileinfo, $infoline); + print("$infoline"); + + $infoline = "$message\n"; + push(@par2script::globals::logfileinfo, $infoline); + print("$infoline"); + + $infoline = "in function: $function\n"; + push(@par2script::globals::logfileinfo, $infoline); + print("$infoline"); + + $infoline = "***************************************************************\n"; + push(@par2script::globals::logfileinfo, $infoline); + + if ($par2script::globals::logging) + { + par2script::files::save_file($par2script::globals::logfilename, \@par2script::globals::logfileinfo); + print("Saved logfile: $par2script::globals::logfilename\n"); + } + + print("$infoline"); + + exit(-1); +} + +##################################### +# Error, because a gid is defined +# more than once +##################################### + +sub multidefinitionerror +{ + my ( $multidefinitiongids ) = @_; + print "************************************************\n"; + print "ERROR: multiple definition of gids:\n"; + print "************************************************\n"; + + my $gid; + foreach $gid ( @{$multidefinitiongids} ) { print "\t$gid\n"; } + exit(-1); +} + +##################################### +# Error, because a gid is assigned +# more than once +##################################### + +sub multiassignmenterror +{ + my ( $multiassignmentgids ) = @_; + #print "************************************************\n"; + #print "ERROR: multiple assignments of gids:\n"; + #print "************************************************\n"; + + my $line; + foreach $line ( @{$multiassignmentgids} ) { print "\t$line\n"; } + # exit(-1); +} + +##################################### +# Error, because a defined gid +# is not assigned +##################################### + +sub missingassignmenterror +{ + my ( $missingassignmentgids ) = @_; + print "********************************************************\n"; + print "ERROR: Missing assignments for the following GIDs:\n"; + print "********************************************************\n"; + + my $gid; + foreach $gid ( @{$missingassignmentgids} ) { print "\t$gid\n"; } + exit(-1); +} + +1; diff --git a/solenv/bin/modules/par2script/files.pm b/solenv/bin/modules/par2script/files.pm new file mode 100644 index 000000000000..c781b6f9a3bc --- /dev/null +++ b/solenv/bin/modules/par2script/files.pm @@ -0,0 +1,128 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: files.pm,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +package par2script::files; + +use par2script::exiter; + +############################################ +# File Operations +############################################ + +sub check_file +{ + my ($arg) = @_; + + if(!( -f $arg )) + { + par2script::exiter::exit_program("ERROR: Cannot find file $arg", "check_file"); + } +} + +sub read_file +{ + my ($localfile) = @_; + + my @localfile = (); + + open( IN, "<$localfile" ) || par2script::exiter::exit_program("ERROR: Cannot open file: $localfile", "read_file"); + while ( <IN> ) { push(@localfile, $_); } + close( IN ); + + return \@localfile; +} + +########################################### +# Saving files, arrays and hashes +########################################### + +sub save_file +{ + my ($savefile, $savecontent) = @_; + open( OUT, ">$savefile" ); + print OUT @{$savecontent}; + close( OUT); + if (! -f $savefile) { pre2par::exiter::exit_program("ERROR: Cannot write file: $savefile", "save_file"); } +} + +sub save_hash +{ + my ($savefile, $hashref) = @_; + + my @printcontent = (); + + my ($itemkey, $itemvalue, $line); + + foreach $itemkey ( keys %{$hashref} ) + { + $line = ""; + $itemvalue = $hashref->{$itemkey}; + $line = $itemkey . "=" . $itemvalue . "\n"; + push(@printcontent, $line); + } + + open( OUT, ">$savefile" ); + print OUT @printcontent; + close( OUT); +} + +sub save_array_of_hashes +{ + my ($savefile, $arrayref) = @_; + + my @printcontent = (); + + my ($itemkey, $itemvalue, $line, $hashref); + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + $line = ""; + $hashref = ${$arrayref}[$i]; + + foreach $itemkey ( keys %{$hashref} ) + { + $itemvalue = $hashref->{$itemkey}; + + $line = $line . $itemkey . "=" . $itemvalue . "\t"; + } + + $line = $line . "\n"; + + push(@printcontent, $line); + } + + open( OUT, ">$savefile" ); + print OUT @printcontent; + close( OUT); +} + +1; diff --git a/solenv/bin/modules/par2script/globals.pm b/solenv/bin/modules/par2script/globals.pm new file mode 100644 index 000000000000..dbadb5462f06 --- /dev/null +++ b/solenv/bin/modules/par2script/globals.pm @@ -0,0 +1,95 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: globals.pm,v $ +# +# $Revision: 1.11 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +package par2script::globals; + +############################################ +# Global settings +############################################ + +BEGIN +{ + $prog="par2script"; + + $includepathlist = ""; + $scriptname = ""; + $parfilelistorig = ""; + $parfilelist = ""; + + @allitems = ("Installation", "ScpAction", "Directory", "File", + "Shortcut", "Unixlink", "Module", "Profile", "ProfileItem", + "Folder", "FolderItem", "RegistryItem", "WindowsCustomAction", + "MergeModule"); + + @items_assigned_at_modules = ("File", "Directory", "Unixlink"); + @items_with_directories = ("File", "Profile", "Shortcut", "Unixlink"); + @items_with_moduleid = ("Profile", "ProfileItem", "FolderItem", "RegistryItem"); + @items_without_moduleid = ("File", "Directory", "Shortcut", "Unixlink"); + + %searchkeys = ("File" => "Files", "Directory" => "Dirs", "Unixlink" => "Unixlinks"); + + $logging = 0; + $logfilename = "logfile.log"; # the default logfile name for global errors + @logfileinfo = (); + + $multidefinitionerror = 0; + $multiassignmenterror = 0; + + %definitions; + %assignedgids; + + $plat = $^O; + + if (( $plat =~ /MSWin/i ) || (( $plat =~ /cygwin/i ) && ( $ENV{'USE_SHELL'} eq "4nt" ))) + { + $separator = "\\"; + $pathseparator = "\;"; + $isunix = 0; + $iswin = 1; + } + else + { + $separator = "/"; + $pathseparator = "\:"; + $isunix = 1; + $iswin = 0; + } + + $islinux = 0; + $issolaris = 0; + + if ( $plat =~ /linux/i ) { $islinux = 1; } + if ( $plat =~ /solaris/i ) { $issolaris = 1; } + +} + +1; diff --git a/solenv/bin/modules/par2script/module.pm b/solenv/bin/modules/par2script/module.pm new file mode 100644 index 000000000000..f58022564f09 --- /dev/null +++ b/solenv/bin/modules/par2script/module.pm @@ -0,0 +1,268 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: module.pm,v $ +# +# $Revision: 1.8 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package par2script::module; + +use par2script::converter; +use par2script::exiter; + +########################################### +# Removing undefined gids +# from modules +########################################### + +sub remove_from_modules +{ + my ($gid, $item) = @_; + + my $counter = 0; + + if ( ! exists($par2script::globals::searchkeys{$item}) ) { par2script::exiter::exit_program("ERROR: Unknown type \"$item\" at modules.", "remove_from_modules"); } + my $searchkey = $par2script::globals::searchkeys{$item}; + + my $allmodules = $par2script::globals::definitions{'Module'}; + + my $onemodule; + foreach $onemodule (keys %{$allmodules}) + { + if (( exists($allmodules->{$onemodule}->{$searchkey}) ) && ( $allmodules->{$onemodule}->{$searchkey} =~ /\b$gid\b/ )) + { + my $infoline = "WARNING: Removing $gid because of missing definition\n"; + # print $infoline; + push(@par2script::globals::logfileinfo, $infoline); + + $allmodules->{$onemodule}->{$searchkey} =~ s/\b$gid\b//; + $allmodules->{$onemodule}->{$searchkey} =~ s/\,\s*\,/\,/; + $allmodules->{$onemodule}->{$searchkey} =~ s/\(\s*\,\s*/\(/; + $allmodules->{$onemodule}->{$searchkey} =~ s/\s*\,\s*\)/\)/; + + if (( $allmodules->{$onemodule}->{$searchkey} =~ /\(\s*\,\s*\)/ ) || + ( $allmodules->{$onemodule}->{$searchkey} =~ /\(\s*\)/ )) + { + delete($allmodules->{$onemodule}->{$searchkey}); + } + + $counter++; + } + } + + return $counter; +} + +########################################### +# Removing undefined gids automatically +# from modules +########################################### + +sub remove_undefined_gids_from_modules +{ + # If assigned gids for "File", "Directory" or "Unixlink" are not defined, + # they are automatically removed from the module + + foreach $item ( @par2script::globals::items_assigned_at_modules ) + { + my $assignedgids = $par2script::globals::assignedgids{$item}; + my $definedgids = $par2script::globals::definitions{$item}; + + my $gid; + foreach $gid ( keys %{$assignedgids} ) + { + if ( ! exists( $definedgids->{$gid} )) + { + # deleting entry in module definition + my $number_of_removals = remove_from_modules($gid, $item); + # decreasing counter in assignments + if ( $assignedgids->{$gid} > $number_of_removals ) { $assignedgids->{$gid} = $assignedgids->{$gid} - $number_of_removals; } + else { delete($assignedgids->{$gid}); } + } + } + } +} + +############################################ +# Getting the gid of the root module. The +# root module has no ParentID or an empty +# ParentID. +############################################ + +sub get_rootmodule_gid +{ + my $rootgid = ""; + my $foundroot = 0; + + my $allmodules = $par2script::globals::definitions{'Module'}; + + my $modulegid = ""; + foreach $modulegid (keys %{$allmodules} ) + { + # print "Module $modulegid\n"; + # my $content = ""; + # foreach $content (sort keys %{$allmodules->{$modulegid}}) { print "\t$content = $allmodules->{$modulegid}->{$content};\n"; } + # print "End\n"; + # print "\n"; + + if (( ! exists($allmodules->{$modulegid}->{'ParentID'})) || ( $allmodules->{$modulegid}->{'ParentID'} eq "" )) + { + if ( $foundroot ) { par2script::exiter::exit_program("ERROR: More than one Root module. Only one module without ParentID or with empty ParentID allowed ($rootgid and $modulegid).", "get_rootmodule_gid"); } + $rootgid = $modulegid; + $foundroot = 1; + } + } + + if ( ! $foundroot ) { par2script::exiter::exit_program("ERROR: Could not find Root module. Did not find module without ParentID or with empty ParentID.", "get_rootmodule_gid"); } + + return $rootgid; +} + +#################################### +# Adding defined items without +# assignment to the root module. +#################################### + +sub add_to_root_module +{ + # If defined gids for "File", "Directory" or "Unixlink" are not assigned, + # they are automatically assigned to the root module + + my $rootmodulegid = get_rootmodule_gid(); + + my $item; + foreach $item ( @par2script::globals::items_assigned_at_modules ) + { + my $assignedgids = $par2script::globals::assignedgids{$item}; + my $definedgids = $par2script::globals::definitions{$item}; + + my $gidstring = ""; + + # Perhaps there are already items assigned to the root + if ( ! exists($par2script::globals::searchkeys{$item}) ) { par2script::exiter::exit_program("ERROR: Unknown type \"$item\" at modules.", "remove_from_modules"); } + my $modulekey = $par2script::globals::searchkeys{$item}; + if ( exists($par2script::globals::definitions{'Module'}->{$rootmodulegid}->{$modulekey}) ) + { + $gidstring = $par2script::globals::definitions{'Module'}->{$rootmodulegid}->{$modulekey}; + $gidstring =~ s/\(//; + $gidstring =~ s/\)//; + } + + my $gid; + foreach $gid ( keys %{$definedgids} ) + { + if ( ! exists( $assignedgids->{$gid} )) + { + if ( $gidstring eq "" ) + { + $gidstring = $gid; + } + else + { + $gidstring = "$gidstring,$gid"; + } + + $assignedgids->{$gid} = 1; + } + } + + if ( $gidstring ne "" ) + { + $gidstring = "\($gidstring\)"; + $par2script::globals::definitions{'Module'}->{$rootmodulegid}->{$modulekey} = $gidstring; + } + } +} + +################################################### +# Including \n in a very long string +################################################### + +sub include_linebreaks +{ + my ($allgidstring) = @_; + + my $newline = ""; + my $newlength = 0; + + $allgidstring =~ s/\(//; + $allgidstring =~ s/\)//; + + my $allgids = par2script::converter::convert_stringlist_into_array_2($allgidstring, ","); + + if ( $#{$allgids} > -1 ) + { + my $onegid; + foreach $onegid ( @{$allgids} ) + { + $newline = "$newline$onegid,"; + $newlength = $newlength + length($onegid) + 1; # +1 for the comma + + if ( $newlength > 80 ) + { + $newline = $newline . "\n\t\t\t\t"; + $newlength = 0; + } + } + } + + $newline =~ s/,\s*$//; + $newline = "($newline)"; + + return $newline; +} + +################################################### +# Shorten the lines that belong to modules, if +# the length of the line is greater 100 +################################################### + +sub shorten_lines_at_modules +{ + my $item; + foreach $item ( @par2script::globals::items_assigned_at_modules ) + { + if ( ! exists($par2script::globals::searchkeys{$item}) ) { par2script::exiter::exit_program("ERROR: Unknown type \"$item\" at modules.", "shorten_lines_at_modules"); } + my $searchkey = $par2script::globals::searchkeys{$item}; + + my $allmodules = $par2script::globals::definitions{'Module'}; + + my $onemodule; + foreach $onemodule (keys %{$allmodules}) + { + if (( exists($allmodules->{$onemodule}->{$searchkey}) ) && + ( length($allmodules->{$onemodule}->{$searchkey}) > 100 )) + { + # including "\n\t\t\t\t" + my $newstring = include_linebreaks($allmodules->{$onemodule}->{$searchkey}); + $allmodules->{$onemodule}->{$searchkey} = $newstring; + } + } + } +} + +1; diff --git a/solenv/bin/modules/par2script/parameter.pm b/solenv/bin/modules/par2script/parameter.pm new file mode 100644 index 000000000000..982a4ae51b6b --- /dev/null +++ b/solenv/bin/modules/par2script/parameter.pm @@ -0,0 +1,158 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: parameter.pm,v $ +# +# $Revision: 1.6 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +package par2script::parameter; + +use Cwd; +use par2script::files; +use par2script::globals; +use par2script::systemactions; + +############################################ +# Parameter Operations +############################################ + +############################################################################### +# Usage: +# perl par2script.pl -i ..\wntmsci8.pro\par,o:\SRX645\wntmsci8.pro\par.m24 +# @@C:\DOCUMEN~1\is\LOCALS~1\Temp\mk6pd +# -o ..\wntmsci8.pro\bin\osl\setup_osl.inf +############################################################################### + +sub usage +{ + print <<Ende; + +-------------------------------------------------------------- +$par2script::globals::prog V1.0 (c) Ingo Schmidt 2003 +The following parameter are needed: +-i: include pathes, comma separated list +-o: setup script file name +-v: writing logfile.txt (optional) +\@\@list: list of all par files + +Example: + perl par2script.pl -i ..\\wntmsci8\\par\,o\:\\SRX645\\wntmsci8\\par.m24 + \@\@C\:\\DOCUMEN\~1\\is\\LOCALS\~1\\Temp\\mk6pd + -o ..\\wntmsci8.pro\\bin\\osl\\setup_osl.inf \[-v\] + +-------------------------------------------------------------- +Ende + exit(-1); +} + +##################################### +# Reading parameter +##################################### + +sub getparameter +{ + while ( $#ARGV >= 0 ) + { + my $param = shift(@ARGV); + + if ($param eq "-o") { $par2script::globals::scriptname = shift(@ARGV); } + elsif ($param eq "-v") { $par2script::globals::logging = 1; } + elsif ($param =~ /\@\@/) { $par2script::globals::parfilelistorig = $param; } + elsif ($param eq "-i") { $par2script::globals::includepathlist = shift(@ARGV); } + elsif (($param =~ /\//) || ($param =~ /\\/)) # another include parameter! + { + $par2script::globals::includepathlist = $par2script::globals::includepathlist . "," . $param; + } + else + { + print("\n*************************************\n"); + print("Sorry, unknown parameter: $param"); + print("\n*************************************\n"); + usage(); + exit(-1); + } + } +} + +############################################ +# Controlling the fundamental parameter +# (required for every process) +############################################ + +sub control_parameter +{ + if ($par2script::globals::includepathlist eq "") + { + print "\n************************************************\n"; + print "Error: Include pathes not set not set (-i)!"; + print "\n************************************************\n"; + usage(); + exit(-1); + } + + if ($par2script::globals::scriptname eq "") + { + print "\n************************************************\n"; + print "Error: Name of the setup script not set (-o)!"; + print "\n************************************************\n"; + usage(); + exit(-1); + } + + if ($par2script::globals::parfilelistorig eq "") + { + print "\n************************************************\n"; + print "Error: List of par files not set!"; + print "\n************************************************\n"; + usage(); + exit(-1); + } + + # The par file list has to exist + + $par2script::globals::parfilelist = $par2script::globals::parfilelistorig; + $par2script::globals::parfilelist =~ s/\@\@//; + par2script::files::check_file($par2script::globals::parfilelist); +} + +##################################### +# Writing parameter to shell +##################################### + +sub outputparameter +{ + my $outputline = "\n$par2script::globals::prog -i $par2script::globals::includepathlist $par2script::globals::parfilelistorig -o $par2script::globals::scriptname"; + + if ($par2script::globals::logging) { $outputline .= " -v"; } + + $outputline .= "\n"; + + print $outputline; +} + +1; diff --git a/solenv/bin/modules/par2script/remover.pm b/solenv/bin/modules/par2script/remover.pm new file mode 100644 index 000000000000..b6b94d124403 --- /dev/null +++ b/solenv/bin/modules/par2script/remover.pm @@ -0,0 +1,79 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: remover.pm,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +package par2script::remover; + +############################################ +# Remover +############################################ + +sub remove_leading_and_ending_whitespaces +{ + my ( $stringref ) = @_; + + $$stringref =~ s/^\s*//g; + $$stringref =~ s/\s*$//g; +} + +sub remove_leading_and_ending_comma +{ + my ( $stringref ) = @_; + + $$stringref =~ s/^\s*\,//g; + $$stringref =~ s/\,\s*$//g; +} + +sub remove_leading_and_ending_quotationmarks +{ + my ( $stringref ) = @_; + + $$stringref =~ s/^\s*\"//g; + $$stringref =~ s/\"\s*$//g; +} + +sub remove_leading_and_ending_slashes +{ + my ( $stringref ) = @_; + + $$stringref =~ s/^\s*\///g; + $$stringref =~ s/\/\s*$//g; +} + +sub remove_leading_and_ending_backslashes +{ + my ( $stringref ) = @_; + + $$stringref =~ s/^\s*\\//g; + $$stringref =~ s/\\\s*$//g; +} + +1; diff --git a/solenv/bin/modules/par2script/shortcut.pm b/solenv/bin/modules/par2script/shortcut.pm new file mode 100644 index 000000000000..49063c3162f5 --- /dev/null +++ b/solenv/bin/modules/par2script/shortcut.pm @@ -0,0 +1,79 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: shortcut.pm,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +package par2script::shortcut; + +use par2script::work; + +############################################################ +# Writing shortcuts to files behind the correct files and +# then shortcuts to shortcuts behind these shortcuts. +############################################################ + +sub shift_shortcut_positions +{ + my ($script) = @_; + + my $allshortcutgids = par2script::work::get_all_gids_from_script($script, "Shortcut"); + + # first all shortcuts that are assigned to files + + for ( my $i = 0; $i <= $#{$allshortcutgids}; $i++ ) + { + my $codeblock = par2script::work::get_definitionblock_from_script($script, ${$allshortcutgids}[$i]); + + my $filegid = par2script::work::get_value_from_definitionblock($codeblock, "FileID"); + + if (!($filegid eq "")) + { + par2script::work::remove_definitionblock_from_script($script, ${$allshortcutgids}[$i]); + par2script::work::add_definitionblock_into_script($script, $codeblock, $filegid); + } + } + + # secondly all shortcuts that are assigned to other shortcuts + + for ( my $i = 0; $i <= $#{$allshortcutgids}; $i++ ) + { + my $codeblock = par2script::work::get_definitionblock_from_script($script, ${$allshortcutgids}[$i]); + my $shortcutgid = par2script::work::get_value_from_definitionblock($codeblock, "ShortcutID"); + + if (!($shortcutgid eq "")) + { + par2script::work::remove_definitionblock_from_script($script, ${$allshortcutgids}[$i]); + par2script::work::add_definitionblock_into_script($script, $codeblock, $shortcutgid); + } + } +} + + +1; diff --git a/solenv/bin/modules/par2script/systemactions.pm b/solenv/bin/modules/par2script/systemactions.pm new file mode 100644 index 000000000000..e51565a01f02 --- /dev/null +++ b/solenv/bin/modules/par2script/systemactions.pm @@ -0,0 +1,188 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: systemactions.pm,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +package par2script::systemactions; + +use File::Copy; +use par2script::exiter; +use par2script::globals; + +###################################################### +# Creating a new direcotory +###################################################### + +sub create_directory +{ + my ($directory) = @_; + + my $returnvalue = 1; + + if (!(-d $directory)) + { + $returnvalue = mkdir($directory, 0775); + + if ($returnvalue) + { + $infoline = "Created directory: $directory\n"; + push(@par2script::globals::logfileinfo, $infoline); + + if ($par2script::globals::isunix) + { + my $localcall = "chmod 775 $directory \>\/dev\/null 2\>\&1"; + system($localcall); + } + } + else + { + par2script::exiter::exit_program("Error: Could not create directory: $directory", "create_directory"); + } + } +} + +####################################################################### +# Creating the directories, in which files are generated or unzipped +####################################################################### + +sub create_directories +{ + my ($directory, $languagesref) =@_; + + $par2script::globals::unpackpath =~ s/\Q$par2script::globals::separator\E\s*$//; # removing ending slashes and backslashes + + my $path = $par2script::globals::unpackpath; # this path already exists + + $path = $path . $par2script::globals::separator . $par2script::globals::build . $par2script::globals::separator; + create_directory($path); + + $path = $path . $par2script::globals::minor . $par2script::globals::separator; + create_directory($path); + + if ($directory eq "unzip" ) + { + $path = $path . "common" . $par2script::globals::productextension . $par2script::globals::separator; + create_directory($path); + + $path = $path . $directory . $par2script::globals::separator; + create_directory($path); + } + else + { + $path = $path . $par2script::globals::compiler . $par2script::globals::productextension . $par2script::globals::separator; + create_directory($path); + + $path = $path . $par2script::globals::product . $par2script::globals::separator; + create_directory($path); + + $path = $path . $directory . $par2script::globals::separator; + create_directory($path); + + if (!($$languagesref eq "" )) # this will be a path like "01_49", for Profiles and ConfigurationFiles, idt-Files + { + $path = $path . $$languagesref . $par2script::globals::separator; + create_directory($path); + } + } + + $path =~ s/\Q$par2script::globals::separator\E\s*$//; + + return $path; +} + +######################## +# Copying one file +######################## + +sub copy_one_file +{ + my ($source, $dest) = @_; + + my ($copyreturn, $returnvalue); + my $infoline; + + $copyreturn = copy($source, $dest); + + if ($copyreturn) + { + $infoline = "Copy: $source to $dest\n"; + $returnvalue = 1; + } + else + { + $infoline = "Error: Could not copy $source to $dest\n"; + $returnvalue = 0; + } + + push(@par2script::globals::logfileinfo, $infoline); + + return $returnvalue; +} + +########################################## +# Copying all files from one directory +# to another directory +########################################## + +sub copy_directory +{ + my ($sourcedir, $destdir) = @_; + + my ($onefile, $sourcefile, $destfile); + my @sourcefiles = (); + + $sourcedir =~ s/\Q$par2script::globals::separator\E\s*$//; + $destdir =~ s/\Q$par2script::globals::separator\E\s*$//; + + $infoline = "\n"; + push(@par2script::globals::logfileinfo, $infoline); + $infoline = "Copying files from directory $sourcedir to directory $destdir\n"; + push(@par2script::globals::logfileinfo, $infoline); + + opendir(DIR, $sourcedir); + @sourcefiles = readdir(DIR); + closedir(DIR); + + foreach $onefile (@sourcefiles) + { + if ((!($onefile eq ".")) && (!($onefile eq ".."))) + { + $sourcefile = $sourcedir . $par2script::globals::separator . $onefile; + $destfile = $destdir . $par2script::globals::separator . $onefile; + if ( -f $sourcefile ) # only files, no directories + { + copy_one_file($sourcefile, $destfile); + } + } + } +} + + +1; diff --git a/solenv/bin/modules/par2script/undefine.pm b/solenv/bin/modules/par2script/undefine.pm new file mode 100644 index 000000000000..e6c1c586502f --- /dev/null +++ b/solenv/bin/modules/par2script/undefine.pm @@ -0,0 +1,148 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: undefine.pm,v $ +# +# $Revision: 1.6 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package par2script::undefine; + +use par2script::globals; + +########################################################## +# Removing in the script all the gids, that are listed +# in undefine scp files +########################################################## + +sub undefine_gids +{ + my ($parfilecontent) = @_; + + my $item; + foreach $item ( @par2script::globals::allitems ) + { + my $unitem = "Un$item"; + + for ( my $i = 0; $i <= $#{$parfilecontent}; $i++ ) + { + if ( ${$parfilecontent}[$i] =~ /^\s*$unitem\s*(\w+?)\s*$/ ) + { + my $gid = $1; + delete($par2script::globals::definitions{$item}->{$gid}); + } + } + } +} + +########################################################## +# Collecting all subdirectories of a specified directory +########################################################## + +sub collect_children_dirs +{ + my ($gid, $collector) = @_; + + my $diritem = "Directory"; + my $parentkey = "ParentID"; + + if ( exists($par2script::globals::definitions{$diritem}) ) + { + my $onedefinition; + + foreach $onedefinition (keys %{$par2script::globals::definitions{$diritem}}) + { + if ( $par2script::globals::definitions{$diritem}->{$onedefinition}->{$parentkey} eq $gid ) + { + push(@{$collector}, $onedefinition); + collect_children_dirs($onedefinition, $collector); + } + } + } +} + +########################################################## +# Removing in the script complete profiles. +# This includes the Profile and its ProfileItems. +########################################################## + +sub remove_complete_item +{ + my ($item, $parfilecontent) = @_; + + my $removeitem = "Remove$item"; + my $dependentkey = ""; + my $collect_children = 0; + my @gidcollector = (); + my @dependentitems = (); + + if ( $item eq "Profile" ) + { + @dependentitems = ("ProfileItem"); + $dependentkey = "ProfileID"; + } + elsif ( $item eq "Directory" ) + { + @dependentitems = ("File", "Shortcut", "Unixlink"); + $dependentkey = "Dir"; + $collect_children = 1; + } + + for ( my $i = 0; $i <= $#{$parfilecontent}; $i++ ) + { + if ( ${$parfilecontent}[$i] =~ /^\s*$removeitem\s*(\w+?)\s*$/ ) + { + my $onegid = $1; + push(@gidcollector, $onegid); + if ( $collect_children ) { collect_children_dirs($onegid, \@gidcollector); } + + my $gid; + foreach $gid (@gidcollector) + { + delete($par2script::globals::definitions{$item}->{$gid}); + + # also deleting all dependent items, for example "ProfileItems" whose "ProfileID" is this "Profile" + my $depitem; + foreach $depitem ( @dependentitems ) + { + if ( exists($par2script::globals::definitions{$depitem}) ) + { + my $onedefinition; + foreach $onedefinition (keys %{$par2script::globals::definitions{$depitem}}) + { + if ( $par2script::globals::definitions{$depitem}->{$onedefinition}->{$dependentkey} eq $gid ) + { + delete($par2script::globals::definitions{$depitem}->{$onedefinition}); + } + } + } + } + } + } + } +} + +1; diff --git a/solenv/bin/modules/par2script/work.pm b/solenv/bin/modules/par2script/work.pm new file mode 100644 index 000000000000..e37ce9c6dcdd --- /dev/null +++ b/solenv/bin/modules/par2script/work.pm @@ -0,0 +1,420 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: work.pm,v $ +# +# $Revision: 1.8 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +package par2script::work; + +use par2script::existence; +use par2script::globals; +use par2script::remover; + +############################################ +# par2script working module +############################################ + +sub analyze_comma_separated_list +{ + my ($list, $listref) = @_; # second parameter is optional + + my @list = (); + my $locallistref; + + if (!( $listref )) { $locallistref = \@list; } + else { $locallistref = $listref; } + + par2script::remover::remove_leading_and_ending_comma(\$list); + par2script::remover::remove_leading_and_ending_whitespaces(\$list); + + while ( $list =~ /^\s*(.*?)\s*\,\s*(.*)\s*$/ ) + { + my $oneentry = $1; + $list = $2; + par2script::remover::remove_leading_and_ending_whitespaces(\$oneentry); + push(@{$locallistref}, $oneentry); + } + + # the last entry + + par2script::remover::remove_leading_and_ending_whitespaces(\$list); + push(@{$locallistref}, $list); + + return $locallistref; +} + +############################################ +# setting list of include pathes +############################################ + +sub setincludes +{ + my ($list) = @_; + + # input is the comma separated list of include pathes + + my $includes = analyze_comma_separated_list($list); + + return $includes; +} + +############################################ +# setting list of all par files +############################################ + +sub setparfiles +{ + my ($filename) = @_; + + # input is the name of the list file + $filename =~ s/\@//; # removing the leading \@ + + my $filecontent = par2script::files::read_file($filename); + + my @parfiles = (); + my $parfilesref = \@parfiles; + + foreach ( @{$filecontent} ) { $parfilesref = analyze_comma_separated_list($_, $parfilesref); } + + return $parfilesref; +} + +############################################ +# finding the correct include path +# for the par files +############################################ + +sub make_complete_pathes_for_parfiles +{ + my ($parfiles, $includes) = @_; + + my $oneparfile; + + foreach $oneparfile ( @{$parfiles} ) + { + my $foundparfile = 0; + my $includepath; + + foreach $includepath ( @{$includes} ) + { + my $parfile = "$includepath/$oneparfile"; + + if ( -f $parfile ) + { + $foundparfile = 1; + $oneparfile = $parfile; + last; + } + } + + if ( ! $foundparfile ) + { + die "ERROR: Could not find parfile ${$parfiles}[$i] in includes pathes: $par2script::globals::includepathlist !\n"; + } + } +} + +###################################################### +# collecting one special item in the par files and +# including it into the "definitions" hash +###################################################### + +sub collect_definitions +{ + my ($parfilecontent) = @_; + + my $multidefinitionerror = 0; + my @multidefinitiongids = (); + + + foreach $oneitem ( @par2script::globals::allitems ) + { + my $docollect = 0; + my $gid = ""; + my %allitemhash = (); + + for ( my $i = 0; $i <= $#{$parfilecontent}; $i++ ) + { + my $line = ${$parfilecontent}[$i]; + + if ( $line =~ /^\s*$oneitem\s+(\w+)\s*$/ ) + { + $gid = $1; + $docollect = 1; + } + else + { + $docollect = 0; + } + + if ( $docollect ) + { + my $currentline = $i; + my %oneitemhash; + + while (! ( ${$parfilecontent}[$currentline] =~ /^\s*End\s*$/i ) ) + { + if ( ${$parfilecontent}[$currentline] =~ /^\s*(.+?)\s*\=\s*(.+?)\s*\;\s*$/ ) # only oneliner! + { + $itemkey = $1; + $itemvalue = $2; + + if ( $oneitem eq "Directory" ) { if ( $itemkey =~ "DosName" ) { $itemkey =~ s/DosName/HostName/; } } + if (( $oneitem eq "Directory" ) || ( $oneitem eq "File" ) || ( $oneitem eq "Unixlink" )) { if ( $itemvalue eq "PD_PROGDIR" ) { $itemvalue = "PREDEFINED_PROGDIR"; }} + if (( $itemkey eq "Styles" ) && ( $itemvalue =~ /^\s*(\w+)(\s*\;\s*)$/ )) { $itemvalue = "($1)$2"; } + + $oneitemhash{$itemkey} = $itemvalue; + } + + $currentline++; + } + + # no hyphen allowed in gids -> cannot happen here because (\w+) is required for gids + if ( $gid =~ /-/ ) { par2script::exiter::exit_program("ERROR: No hyphen allowed in global id: $gid", "test_of_hyphen"); } + + # test of uniqueness + if ( exists($allitemhash{$gid}) ) + { + $multidefinitionerror = 1; + push(@multidefinitiongids, $gid); + } + + $allitemhash{$gid} = \%oneitemhash; + } + } + + $par2script::globals::definitions{$oneitem} = \%allitemhash; + } + + if ( $multidefinitionerror ) { par2script::exiter::multidefinitionerror(\@multidefinitiongids); } + + # foreach $key (keys %par2script::globals::definitions) + # { + # print "Key: $key \n"; + # + # foreach $key (keys %{$par2script::globals::definitions{$key}}) + # { + # print "\t$key \n"; + # } + # } +} + +###################################################### +# Filling content into the script +###################################################### + +sub put_oneitem_into_script +{ + my ( $script, $item, $itemhash, $itemkey ) = @_; + + push(@{$script}, "$item $itemkey\n" ); + my $content = ""; + foreach $content (sort keys %{$itemhash->{$itemkey}}) { push(@{$script}, "\t$content = $itemhash->{$itemkey}->{$content};\n" ); } + push(@{$script}, "End\n" ); + push(@{$script}, "\n" ); +} + +###################################################### +# Creating the script +###################################################### + +sub create_script +{ + my @script = (); + my $oneitem; + + foreach $oneitem ( @par2script::globals::allitems ) + { + if ( exists($par2script::globals::definitions{$oneitem}) ) + { + if ( $oneitem eq "Shortcut" ) { next; } # "Shortcuts" after "Files" + + if (( $oneitem eq "Module" ) || ( $oneitem eq "Directory" )) { write_sorted_items(\@script, $oneitem); } + else { write_unsorted_items(\@script, $oneitem); } + } + } + + return \@script; +} + +###################################################### +# Adding script content for the unsorted items +###################################################### + +sub write_unsorted_items +{ + my ( $script, $oneitem ) = @_; + + my $itemhash = $par2script::globals::definitions{$oneitem}; + + my $itemkey = ""; + foreach $itemkey (sort keys %{$itemhash}) + { + put_oneitem_into_script($script, $oneitem, $itemhash, $itemkey); + + # special handling for Shortcuts after Files + if (( $oneitem eq "File" ) && ( exists($par2script::globals::definitions{"Shortcut"}) )) + { + my $shortcutkey; + foreach $shortcutkey ( keys %{$par2script::globals::definitions{"Shortcut"}} ) + { + if ( $par2script::globals::definitions{"Shortcut"}->{$shortcutkey}->{'FileID'} eq $itemkey ) + { + put_oneitem_into_script($script, "Shortcut", $par2script::globals::definitions{"Shortcut"}, $shortcutkey); + + # and Shortcut to Shortcut also + my $internshortcutkey; + foreach $internshortcutkey ( keys %{$par2script::globals::definitions{"Shortcut"}} ) + { + if ( $par2script::globals::definitions{"Shortcut"}->{$internshortcutkey}->{'ShortcutID'} eq $shortcutkey ) + { + put_oneitem_into_script($script, "Shortcut", $par2script::globals::definitions{"Shortcut"}, $internshortcutkey); + } + } + } + } + } + } +} + +###################################################### +# Collecting all children of a specified parent +###################################################### + +sub collect_children +{ + my ( $itemhash, $parent, $order ) = @_; + + my $item; + foreach $item ( keys %{$itemhash} ) + { + if ( $itemhash->{$item}->{'ParentID'} eq $parent ) + { + push(@{$order}, $item); + my $newparent = $item; + collect_children($itemhash, $newparent, $order); + } + } +} + +###################################################### +# Adding script content for the sorted items +###################################################### + +sub write_sorted_items +{ + my ( $script, $oneitem ) = @_; + + my $itemhash = $par2script::globals::definitions{$oneitem}; + + my @itemorder = (); + my @startparents = (); + + if ( $oneitem eq "Module" ) { push(@startparents, ""); } + elsif ( $oneitem eq "Directory" ) { push(@startparents, "PREDEFINED_PROGDIR"); } + else { die "ERROR: No root parent defined for item type $oneitem !\n"; } + + # supporting more than one toplevel item + my $parent; + foreach $parent ( @startparents ) { collect_children($itemhash, $parent, \@itemorder); } + + my $itemkey; + foreach $itemkey ( @itemorder ) { put_oneitem_into_script($script, $oneitem, $itemhash, $itemkey); } +} + +####################################################################### +# Collecting all assigned gids of the type "item" from the modules +# in the par files. Using a hash! +####################################################################### + +sub collect_assigned_gids +{ + my $allmodules = $par2script::globals::definitions{'Module'}; + + my $item; + foreach $item ( @par2script::globals::items_assigned_at_modules ) + { + if ( ! exists($par2script::globals::searchkeys{$item}) ) { par2script::exiter::exit_program("ERROR: Unknown type \"$item\" at modules.", "collect_assigned_gids"); } + + my $searchkey = $par2script::globals::searchkeys{$item}; + + my %assignitems = (); + my $modulegid = ""; + + foreach $modulegid (keys %{$allmodules} ) + { + # print "Module $modulegid\n"; + # my $content = ""; + # foreach $content (sort keys %{$allmodules->{$modulegid}}) { print "\t$content = $allmodules->{$modulegid}->{$content};\n"; } + # print "End\n"; + # print "\n"; + + if ( exists($allmodules->{$modulegid}->{$searchkey}) ) + { + my $list = $allmodules->{$modulegid}->{$searchkey}; + if ( $list =~ /^\s*\((.*?)\)\s*(.*?)\s*$/ ) { $list = $1; } + else { par2script::exiter::exit_program("ERROR: Invalid module list: $list", "collect_assigned_gids"); } + my $allassigneditems = par2script::converter::convert_stringlist_into_array_2($list, ","); + + my $gid; + foreach $gid ( @{$allassigneditems} ) + { + if ( exists($assignitems{$gid}) ) { $assignitems{$gid} = $assignitems{$gid} + 1; } + else { $assignitems{$gid} = 1; } + } + } + } + + $par2script::globals::assignedgids{$item} = \%assignitems; + } +} + +################################################## +# Collecting the content of all par files. +# Then the files do not need to be opened twice. +################################################## + +sub read_all_parfiles +{ + my ($parfiles) = @_; + + my @parfilecontent = (); + my $parfilename; + + foreach $parfilename ( @{$parfiles} ) + { + my $parfile = par2script::files::read_file($parfilename); + foreach ( @{$parfile} ) { push(@parfilecontent, $_); } + push(@parfilecontent, "\n"); + } + + return \@parfilecontent; +} + +1; diff --git a/solenv/bin/modules/pre2par/directory.pm b/solenv/bin/modules/pre2par/directory.pm new file mode 100644 index 000000000000..e09223d037f6 --- /dev/null +++ b/solenv/bin/modules/pre2par/directory.pm @@ -0,0 +1,58 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: directory.pm,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package pre2par::directory; + +use pre2par::pathanalyzer; +use pre2par::systemactions; + +############################################ +# Checking, whether the output directories +# exist. If not, they are created. +############################################ + +sub check_directory +{ + my ($parfilename) = @_; + + my $productdirectory = $parfilename; + pre2par::pathanalyzer::get_path_from_fullqualifiedname(\$productdirectory); + $productdirectory =~ s/\Q$pre2par::globals::separator\E\s*$//; + + my $pardirectory = $productdirectory; + pre2par::pathanalyzer::get_path_from_fullqualifiedname(\$pardirectory); + $pardirectory =~ s/\Q$pre2par::globals::separator\E\s*$//; + + if ( ! -d $pardirectory ) { pre2par::systemactions::create_directory($pardirectory); } + if ( ! -d $productdirectory ) { pre2par::systemactions::create_directory($productdirectory); } +} + +1;
\ No newline at end of file diff --git a/solenv/bin/modules/pre2par/existence.pm b/solenv/bin/modules/pre2par/existence.pm new file mode 100644 index 000000000000..6ae1f6500fcf --- /dev/null +++ b/solenv/bin/modules/pre2par/existence.pm @@ -0,0 +1,78 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: existence.pm,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +package pre2par::existence; + +############################# +# Test of existence +############################# + +sub exists_in_array +{ + my ($searchstring, $arrayref) = @_; + + my $alreadyexists = 0; + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + if ( ${$arrayref}[$i] eq $searchstring) + { + $alreadyexists = 1; + last; + } + } + + return $alreadyexists; +} + +sub exists_in_array_of_hashes +{ + my ($searchkey, $searchvalue, $arrayref) = @_; + + my $hashref; + my $valueexists = 0; + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + $hashref = ${$arrayref}[$i]; + + if ( $hashref->{$searchkey} eq $searchvalue ) + { + $valueexists = 1; + last; + } + } + + return $valueexists; +} + +1; diff --git a/solenv/bin/modules/pre2par/exiter.pm b/solenv/bin/modules/pre2par/exiter.pm new file mode 100644 index 000000000000..2c6c755494b7 --- /dev/null +++ b/solenv/bin/modules/pre2par/exiter.pm @@ -0,0 +1,74 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: exiter.pm,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package pre2par::exiter; + +use pre2par::files; +use pre2par::globals; + +############################################ +# Exiting the program with an error +# This function is used instead of "die" +############################################ + +sub exit_program +{ + my ($message, $function) = @_; + + my $infoline; + + $infoline = "\n***************************************************************\n"; + push(@pre2par::globals::logfileinfo, $infoline); + print("$infoline"); + + $infoline = "$message\n"; + push(@pre2par::globals::logfileinfo, $infoline); + print("$infoline"); + + $infoline = "in function: $function\n"; + push(@pre2par::globals::logfileinfo, $infoline); + print("$infoline"); + + $infoline = "***************************************************************\n"; + push(@pre2par::globals::logfileinfo, $infoline); + + if ($pre2par::globals::logging) + { + pre2par::files::save_file($pre2par::globals::logfilename ,\@pre2par::globals::logfileinfo); + print("Saved logfile: $pre2par::globals::logfilename\n"); + } + + print("$infoline"); + + exit(-1); +} + +1; diff --git a/solenv/bin/modules/pre2par/files.pm b/solenv/bin/modules/pre2par/files.pm new file mode 100644 index 000000000000..e01c25fd4af9 --- /dev/null +++ b/solenv/bin/modules/pre2par/files.pm @@ -0,0 +1,129 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: files.pm,v $ +# +# $Revision: 1.6 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package pre2par::files; + +use pre2par::exiter; + +############################################ +# File Operations +############################################ + +sub check_file +{ + my ($arg) = @_; + + if(!( -f $arg )) + { + pre2par::exiter::exit_program("ERROR: Cannot find file $arg", "check_file"); + } +} + +sub read_file +{ + my ($localfile) = @_; + + my @localfile = (); + + open( IN, "<$localfile" ) || pre2par::exiter::exit_program("ERROR: Cannot open file: $localfile", "read_file"); + while ( <IN> ) { push(@localfile, $_); } + close( IN ); + + return \@localfile; +} + +########################################### +# Saving files, arrays and hashes +########################################### + +sub save_file +{ + my ($savefile, $savecontent) = @_; + if (-f $savefile) { unlink $savefile }; + if (-f $savefile) { pre2par::exiter::exit_program("ERROR: Cannot delete existing file: $savefile", "save_file"); }; + open( OUT, ">$savefile" ); + print OUT @{$savecontent}; + close( OUT); + if (! -f $savefile) { pre2par::exiter::exit_program("ERROR: Cannot write file: $savefile", "save_file"); } +} + +sub save_hash +{ + my ($savefile, $hashref) = @_; + + my @printcontent = (); + + my ($itemkey, $itemvalue, $line); + + foreach $itemkey ( keys %{$hashref} ) + { + $line = ""; + $itemvalue = $hashref->{$itemkey}; + $line = $itemkey . "=" . $itemvalue . "\n"; + push(@printcontent, $line); + } + + open( OUT, ">$savefile" ); + print OUT @printcontent; + close( OUT); +} + +sub save_array_of_hashes +{ + my ($savefile, $arrayref) = @_; + + my @printcontent = (); + + my ($itemkey, $itemvalue, $line, $hashref); + + for ( my $i = 0; $i <= $#{$arrayref}; $i++ ) + { + $line = ""; + $hashref = ${$arrayref}[$i]; + + foreach $itemkey ( keys %{$hashref} ) + { + $itemvalue = $hashref->{$itemkey}; + + $line = $line . $itemkey . "=" . $itemvalue . "\t"; + } + + $line = $line . "\n"; + + push(@printcontent, $line); + } + + open( OUT, ">$savefile" ); + print OUT @printcontent; + close( OUT); +} + +1; diff --git a/solenv/bin/modules/pre2par/globals.pm b/solenv/bin/modules/pre2par/globals.pm new file mode 100644 index 000000000000..215cd3b10bcf --- /dev/null +++ b/solenv/bin/modules/pre2par/globals.pm @@ -0,0 +1,81 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: globals.pm,v $ +# +# $Revision: 1.13 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +package pre2par::globals; + +############################################ +# Global settings +############################################ + +BEGIN +{ + $prog="pre2par"; + + $prefilename = ""; + $parfilename = ""; + $langfilename = ""; + + @allitems = ("Installation", "ScpAction", "HelpText", "Directory", "DataCarrier", "StarRegistry", "File", + "Shortcut", "Custom", "Unixlink", "Procedure", "Module", "Profile", "ProfileItem", + "Folder", "FolderItem", "RegistryItem", "StarRegistryItem", "WindowsCustomAction", + "MergeModule"); + + $logging = 0; + $logfilename = "logfile.log"; # the default logfile name for global errors + @logfileinfo = (); + + $plat = $^O; + + if (( $plat =~ /MSWin/i ) || (( $plat =~ /cygwin/i ) && ( $ENV{'USE_SHELL'} eq "4nt" ))) + { + $separator = "\\"; + $pathseparator = "\;"; + $isunix = 0; + $iswin = 1; + } + else + { + $separator = "/"; + $pathseparator = "\:"; + $isunix = 1; + $iswin = 0; + } + + $islinux = 0; + $issolaris = 0; + + if ( $plat =~ /linux/i ) { $islinux = 1; } + if ( $plat =~ /solaris/i ) { $issolaris = 1; } + +} + +1; diff --git a/solenv/bin/modules/pre2par/language.pm b/solenv/bin/modules/pre2par/language.pm new file mode 100644 index 000000000000..2686dbb3fdee --- /dev/null +++ b/solenv/bin/modules/pre2par/language.pm @@ -0,0 +1,176 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: language.pm,v $ +# +# $Revision: 1.8 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +package pre2par::language; + +use pre2par::existence; + +############################################################## +# Returning a specific language string from the block +# of all translations +############################################################## + +sub get_language_string_from_language_block +{ + my ($language_block, $language) = @_; + + my $newstring = ""; + + for ( my $i = 0; $i <= $#{$language_block}; $i++ ) + { + + if ( ${$language_block}[$i] =~ /^\s*$language\s*\=\s*\"(.*)\"\s*$/ ) + { + $newstring = $1; + $newstring =~ s/\"/\\\"/g; # masquerading all '"' in the string + $newstring = "\"" . $newstring . "\""; + last; + } + } + + # defaulting to english! + + if ( $newstring eq "" ) + { + $language = "en-US"; # defaulting to english + + for ( my $i = 0; $i <= $#{$language_block}; $i++ ) + { + if ( ${$language_block}[$i] =~ /^\s*$language\s*\=\s*(\".*\")\s*$/ ) + { + $newstring = $1; + last; + } + } + } + + return $newstring; +} + +############################################################## +# Returning the complete block in all languages +# for a specified string +############################################################## + +sub get_language_block_from_language_file +{ + my ($searchstring, $langfile) = @_; + + my @language_block = (); + + for ( my $i = 0; $i <= $#{$langfile}; $i++ ) + { + if ( ${$langfile}[$i] =~ /^\s*\[\s*$searchstring\s*\]\s*$/ ) + { + my $counter = $i; + + push(@language_block, ${$langfile}[$counter]); + $counter++; + + while (( $counter <= $#{$langfile} ) && (!( ${$langfile}[$counter] =~ /^\s*\[/ ))) + { + push(@language_block, ${$langfile}[$counter]); + $counter++; + } + + last; + } + } + + return \@language_block; +} + +############################################ +# collecting all replace strings +# in a language file +############################################ + +sub get_all_replace_strings +{ + my ($langfile) = @_; + + my @allstrings = (); + + for ( my $i = 0; $i <= $#{$langfile}; $i++ ) + { + if ( ${$langfile}[$i] =~ /^\s*\[\s*(.*?)\s*\]\s*$/ ) + { + my $replacestring = $1; + if (! pre2par::existence::exists_in_array($replacestring, \@allstrings)) + { + push(@allstrings, $replacestring); + } + } + } + + return \@allstrings; +} + +############################################ +# localizing the par file with the +# corresponding language file +############################################ + +sub localize +{ + my ($parfile, $langfile) = @_; + + my $allreplacestrings = get_all_replace_strings($langfile); + + for ( my $i = 0; $i <= $#{$parfile}; $i++ ) + { + my $oneline = ${$parfile}[$i]; + + for ( my $j = 0; $j <= $#{$allreplacestrings}; $j++ ) + { + if ( $oneline =~ /\b${$allreplacestrings}[$j]\b/ ) # Not for basic scripts + { + my $oldstring = ${$allreplacestrings}[$j]; + + if ( $oneline =~ /^\s*\w+\s*\(([\w-]+)\)\s*\=/ ) + { + my $language = $1; # can be "01" or "en" or "en-US" or ... + + my $languageblock = get_language_block_from_language_file($oldstring, $langfile); + my $newstring = get_language_string_from_language_block($languageblock, $language); + + if ( $newstring eq "" ) { $newstring = "\"" . $oldstring . "\""; } + + $oneline =~ s/$oldstring/$newstring/g; + + ${$parfile}[$i] = $oneline; + } + } + } + } +} + +1; diff --git a/solenv/bin/modules/pre2par/parameter.pm b/solenv/bin/modules/pre2par/parameter.pm new file mode 100644 index 000000000000..64129187adc3 --- /dev/null +++ b/solenv/bin/modules/pre2par/parameter.pm @@ -0,0 +1,182 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: parameter.pm,v $ +# +# $Revision: 1.8 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +package pre2par::parameter; + +use Cwd; +use pre2par::files; +use pre2par::globals; +use pre2par::systemactions; + +############################################ +# Parameter Operations +############################################ + +sub usage +{ + print <<Ende; +--------------------------------------------------------- +$pre2par::globals::prog V1.0 (c) Ingo Schmidt 2003 +The following parameter are needed: +-s: path to the pre file +-o: path to the par file +-l: path to the ulf file (mlf or jlf file) +-v: log process (optional) + +Example: + +perl pre2par.pl -l test.mlf -s readme.pre -o readme.par -v + +--------------------------------------------------------- +Ende + exit(-1); +} + +##################################### +# Reading parameter +##################################### + +sub getparameter +{ + while ( $#ARGV >= 0 ) + { + my $param = shift(@ARGV); + + if ($param eq "-s") { $pre2par::globals::prefilename = shift(@ARGV); } + elsif ($param eq "-o") { $pre2par::globals::parfilename = shift(@ARGV); } + elsif ($param eq "-l") { $pre2par::globals::langfilename = shift(@ARGV); } + elsif ($param eq "-v") { $pre2par::globals::logging = 1; } + else + { + print("\n*************************************\n"); + print("Sorry, unknown parameter: $param"); + print("\n*************************************\n"); + usage(); + exit(-1); + } + } +} + +############################################ +# Controlling the fundamental parameter +# (required for every process) +############################################ + +sub control_parameter +{ + if ($pre2par::globals::prefilename eq "") + { + print "\n************************************************\n"; + print "Error: Name of the input file not set (-s)!"; + print "\n************************************************\n"; + usage(); + exit(-1); + } + + if ($pre2par::globals::parfilename eq "") + { + print "\n************************************************\n"; + print "Error: Name of the output file not set (-o)!"; + print "\n************************************************\n"; + usage(); + exit(-1); + } + + if (!($pre2par::globals::prefilename =~ /\.pre\s*$/)) + { + print "\n************************************************\n"; + print "Error: Input file is no .pre file!"; + print "\n************************************************\n"; + usage(); + exit(-1); + } + + if (!($pre2par::globals::parfilename =~ /\.par\s*$/)) + { + print "\n************************************************\n"; + print "Error: Output file is no .par file!"; + print "\n************************************************\n"; + usage(); + exit(-1); + } + + # The input file has to exist + + pre2par::files::check_file($pre2par::globals::prefilename); +} + +########################################################## +# The path parameters can be relative or absolute. +# This function creates absolute pathes. +########################################################## + +sub make_path_absolute +{ + my ($pathref) = @_; + + if ( $pre2par::globals::isunix ) + { + if (!($$pathref =~ /^\s*\//)) # this is a relative unix path + { + $$pathref = cwd() . $pre2par::globals::separator . $$pathref; + } + } + + if ( $pre2par::globals::iswin ) + { + if (!($$pathref =~ /^\s*\w\:/)) # this is a relative windows path + { + $$pathref = cwd() . $pre2par::globals::separator . $$pathref; + $$pathref =~ s/\//\\/g; + } + } + + $$pathref =~ s/\Q$pre2par::globals::separator\E\s*$//; # removing ending slashes +} + +##################################### +# Writing parameter to shell +##################################### + +sub outputparameter +{ + $pre2par::globals::logging ? ($logoption = " -v") : ($logoption = ""); + print "\n$pre2par::globals::prog -l $pre2par::globals::langfilename -s $pre2par::globals::prefilename -o $pre2par::globals::parfilename$logoption\n"; + +# print "\n********************************************************\n"; +# print "This is $pre2par::globals::prog, version 1.0\n"; +# print "Input file: $pre2par::globals::prefilename\n"; +# print "Output file: $pre2par::globals::parfilename\n"; +# print "********************************************************\n"; +} + +1; diff --git a/solenv/bin/modules/pre2par/pathanalyzer.pm b/solenv/bin/modules/pre2par/pathanalyzer.pm new file mode 100644 index 000000000000..116adb6dde76 --- /dev/null +++ b/solenv/bin/modules/pre2par/pathanalyzer.pm @@ -0,0 +1,79 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: pathanalyzer.pm,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +package pre2par::pathanalyzer; + +use pre2par::globals; + +########################################### +# Path analyzer +########################################### + +sub get_path_from_fullqualifiedname +{ + my ($longfilenameref) = @_; + + if ( $$longfilenameref =~ /\Q$pre2par::globals::separator\E/ ) # Is there a separator in the path? Otherwise the path is empty. + { + if ( $$longfilenameref =~ /^\s*(\S.*\S\Q$pre2par::globals::separator\E)(\S.+?\S)/ ) + { + $$longfilenameref = $1; + } + } + else + { + $$longfilenameref = ""; # there is no path + } +} + +sub make_absolute_filename_to_relative_filename +{ + my ($longfilenameref) = @_; + + if ( $pre2par::globals::isunix ) + { + if ( $$longfilenameref =~ /^.*\/(\S.+\S?)/ ) + { + $$longfilenameref = $1; + } + } + + if ( $pre2par::globals::iswin ) + { + if ( $$longfilenameref =~ /^.*\\(\S.+\S?)/ ) + { + $$longfilenameref = $1; + } + } +} + +1; diff --git a/solenv/bin/modules/pre2par/remover.pm b/solenv/bin/modules/pre2par/remover.pm new file mode 100644 index 000000000000..5c71c964bd6d --- /dev/null +++ b/solenv/bin/modules/pre2par/remover.pm @@ -0,0 +1,71 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: remover.pm,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +package pre2par::remover; + +############################################ +# Remover +############################################ + +sub remove_leading_and_ending_whitespaces +{ + my ( $stringref ) = @_; + + $$stringref =~ s/^\s*//g; + $$stringref =~ s/\s*$//g; +} + +sub remove_leading_and_ending_quotationmarks +{ + my ( $stringref ) = @_; + + $$stringref =~ s/^\s*\"//g; + $$stringref =~ s/\"\s*$//g; +} + +sub remove_leading_and_ending_slashes +{ + my ( $stringref ) = @_; + + $$stringref =~ s/^\s*\///g; + $$stringref =~ s/\/\s*$//g; +} + +sub remove_leading_and_ending_backslashes +{ + my ( $stringref ) = @_; + + $$stringref =~ s/^\s*\\//g; + $$stringref =~ s/\\\s*$//g; +} + +1; diff --git a/solenv/bin/modules/pre2par/systemactions.pm b/solenv/bin/modules/pre2par/systemactions.pm new file mode 100644 index 000000000000..a45d5f234905 --- /dev/null +++ b/solenv/bin/modules/pre2par/systemactions.pm @@ -0,0 +1,205 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: systemactions.pm,v $ +# +# $Revision: 1.6 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +package pre2par::systemactions; + +use File::Copy; +use pre2par::exiter; +use pre2par::globals; + +###################################################### +# Creating a new direcotory +###################################################### + +sub create_directory +{ + my ($directory) = @_; + + my $returnvalue = 1; + my $infoline = ""; + + if (!(-d $directory)) + { + $returnvalue = mkdir($directory, 0775); + + if ($returnvalue) + { + $infoline = "Created directory: $directory\n"; + push(@pre2par::globals::logfileinfo, $infoline); + + if ($pre2par::globals::isunix) + { + my $localcall = "chmod 775 $directory \>\/dev\/null 2\>\&1"; + system($localcall); + } + } + else + { + # New solution in parallel packing: It is possible, that the directory now exists, although it + # was not created in this process. There is only an important error, if the directory does not + # exist now. + + if (!(-d $directory)) + { + pre2par::exiter::exit_program("Error: Could not create directory: $directory", "create_directory"); + } + else + { + $infoline = "\nAnother process created this directory in exactly this moment :-) : $directory\n"; + push(@pre2par::globals::logfileinfo, $infoline); + } + } + } + else + { + $infoline = "\nAlready existing directory, did not create: $directory\n"; + push(@pre2par::globals::logfileinfo, $infoline); + } +} + +####################################################################### +# Creating the directories, in which files are generated or unzipped +####################################################################### + +sub create_directories +{ + my ($directory, $languagesref) =@_; + + $pre2par::globals::unpackpath =~ s/\Q$pre2par::globals::separator\E\s*$//; # removing ending slashes and backslashes + + my $path = $pre2par::globals::unpackpath; # this path already exists + + $path = $path . $pre2par::globals::separator . $pre2par::globals::build . $pre2par::globals::separator; + create_directory($path); + + $path = $path . $pre2par::globals::minor . $pre2par::globals::separator; + create_directory($path); + + if ($directory eq "unzip" ) + { + $path = $path . "common" . $pre2par::globals::productextension . $pre2par::globals::separator; + create_directory($path); + + $path = $path . $directory . $pre2par::globals::separator; + create_directory($path); + } + else + { + $path = $path . $pre2par::globals::compiler . $pre2par::globals::productextension . $pre2par::globals::separator; + create_directory($path); + + $path = $path . $pre2par::globals::product . $pre2par::globals::separator; + create_directory($path); + + $path = $path . $directory . $pre2par::globals::separator; + create_directory($path); + + if (!($$languagesref eq "" )) # this will be a path like "01_49", for Profiles and ConfigurationFiles, idt-Files + { + $path = $path . $$languagesref . $pre2par::globals::separator; + create_directory($path); + } + } + + $path =~ s/\Q$pre2par::globals::separator\E\s*$//; + + return $path; +} + +######################## +# Copying one file +######################## + +sub copy_one_file +{ + my ($source, $dest) = @_; + + my ($copyreturn, $returnvalue, $infoline); + + $copyreturn = copy($source, $dest); + + if ($copyreturn) + { + $infoline = "Copy: $source to $dest\n"; + $returnvalue = 1; + } + else + { + $infoline = "Error: Could not copy $source to $dest\n"; + $returnvalue = 0; + } + + push(@pre2par::globals::logfileinfo, $infoline); + + return $returnvalue; +} + +########################################## +# Copying all files from one directory +# to another directory +########################################## + +sub copy_directory +{ + my ($sourcedir, $destdir) = @_; + + my ($onefile, $sourcefile, $destfile); + my @sourcefiles = (); + + $sourcedir =~ s/\Q$pre2par::globals::separator\E\s*$//; + $destdir =~ s/\Q$pre2par::globals::separator\E\s*$//; + + $infoline = "\n"; + push(@pre2par::globals::logfileinfo, $infoline); + $infoline = "Copying files from directory $sourcedir to directory $destdir\n"; + push(@pre2par::globals::logfileinfo, $infoline); + + opendir(DIR, $sourcedir); + @sourcefiles = readdir(DIR); + closedir(DIR); + + foreach $onefile (@sourcefiles) + { + if ((!($onefile eq ".")) && (!($onefile eq ".."))) + { + $sourcefile = $sourcedir . $pre2par::globals::separator . $onefile; + $destfile = $destdir . $pre2par::globals::separator . $onefile; + if ( -f $sourcefile ) # only files, no directories + { + copy_one_file($sourcefile, $destfile); + } + } + } +} + + +1; diff --git a/solenv/bin/modules/pre2par/work.pm b/solenv/bin/modules/pre2par/work.pm new file mode 100644 index 000000000000..c08313cc3b7f --- /dev/null +++ b/solenv/bin/modules/pre2par/work.pm @@ -0,0 +1,367 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: work.pm,v $ +# +# $Revision: 1.13 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + + +package pre2par::work; + +use pre2par::exiter; +use pre2par::remover; +use pre2par::pathanalyzer; + +############################################ +# pre2par working module +############################################ + +############################################ +# procedure to split a line, that contains +# more than one par file lines +############################################ + +sub split_line +{ + my ($line, $parfile) = @_; + + while ( $line =~ /^((?:[^"]|\"(?:[^"\\]|\\.)*\")*?\;\s+)\s*(.*)$/ ) + { + my $oneline = $1; + $line = $2; + pre2par::remover::remove_leading_and_ending_whitespaces(\$oneline); + $oneline = $oneline . "\n"; + push(@{$parfile}, $oneline); + + if ( $line =~ /^\s*End\s+(\w+.*$)/i ) + { + $line = $1; + push(@{$parfile}, "End\n\n"); + } + } + + # the last line + + pre2par::remover::remove_leading_and_ending_whitespaces(\$line); + $line = $line . "\n"; + push(@{$parfile}, $line); + + if ( $line =~ /^\s*End\s*$/i ) { push(@{$parfile}, "\n"); } +} + +################################################################### +# Preprocessing the pre file to split all lines with semicolon +################################################################### + +sub preprocess_macros +{ + my ($prefile) = @_; + + my @newprefile = (); + + for ( my $i = 0; $i <= $#{$prefile}; $i++ ) + { + my $oneline = ${$prefile}[$i]; + if ( $oneline =~ /\;\s*\w+/ ) + { + split_line($oneline, \@newprefile); + } + else + { + push(@newprefile, $oneline); + } + } + + return \@newprefile; +} + +############################################ +# main working procedure +############################################ + +sub convert +{ + my ($prefile) = @_; + + my @parfile = (); + + my $iscodesection = 0; + my $ismultiliner = 0; + my $globalline = ""; + + # Preprocessing the pre file to split all lines with semicolon + $prefile = preprocess_macros($prefile); + + for ( my $i = 0; $i <= $#{$prefile}; $i++ ) + { + my $oneline = ${$prefile}[$i]; + + if ($iscodesection) + { + if ( $oneline =~ /^\s*\}\;\s*$/ ) + { + $iscodesection = 0; + } + else # nothing to do for code inside a code section + { + push(@parfile, $oneline); + next; + } + } + + if ( $oneline =~ /^\s*$/ ) { next; } + + if ( $oneline =~ /^\s*Code\s+\=\s+\{/ ) + { + $iscodesection = 1; + } + + pre2par::remover::remove_leading_and_ending_whitespaces(\$oneline); + + my $insertemptyline = 0; + + if ( $oneline =~ /^\s*End\s*$/i ) { $insertemptyline = 1; } + + # Sometimes the complete file is in one line, then the gid line has to be separated + + if ( $oneline =~ /^\s*(\w+\s+\w+)\s+(\w+\s+\=.*$)/ ) # three words before the equal sign + { + my $gidline = $1; + $oneline = $2; + $gidline = $gidline . "\n"; + + push(@parfile, $gidline); + } + + if ( $oneline =~ /\;\s*\w+/ ) + { + split_line($oneline, \@parfile); + next; + } + + # searching for lines with brackets, like Customs = { ..., which can be parted above several lines + + if ( $oneline =~ /^\s*\w+\s+\=\s*\(.*\)\s*\;\s*$/ ) # only one line + { + if (( ! ( $oneline =~ /^\s*Assignment\d+\s*\=/ )) && ( ! ( $oneline =~ /^\s*PatchAssignment\d+\s*\=/ ))) + { + $oneline =~ s/\s//g; # removing whitespaces in lists + $oneline =~ s/\=/\ \=\ /; # adding whitespace around equals sign + } + } + + if ( $oneline =~ /^\s*\w+\s+\=\s*$/ ) + { + $oneline =~ s/\s*$//; + pre2par::exiter::exit_program("Error: Illegal syntax, no line break after eqals sign allowed. Line: \"$oneline\"", "convert"); + } + + if (( $oneline =~ /^\s*\w+\s+\=\s*\(/ ) && (!( $oneline =~ /\)\s*\;\s*$/ ))) # several lines + { + $ismultiliner = 1; + $oneline =~ s/\s//g; + $globalline .= $oneline; + next; # not including yet + } + + if ( $ismultiliner ) + { + $oneline =~ s/\s//g; + $globalline .= $oneline; + + if ( $oneline =~ /\)\s*\;\s*$/ ) { $ismultiliner = 0; } + + if (! ( $ismultiliner )) + { + $globalline =~ s/\=/\ \=\ /; # adding whitespace around equals sign + $globalline .= "\n"; + push(@parfile, $globalline); + $globalline = ""; + } + + next; + } + + $oneline = $oneline . "\n"; + + $oneline =~ s/\s*\=\s*/ \= /; # nice, to have only one whitespace around equal signs + + # Concatenate adjacent string literals: + while ($oneline =~ + s/^((?:[^"]* + \"(?:[^\\"]|\\.)*\" + (?:[^"]*[^[:blank:]"][^"]*\"(?:[^\\"]|\\.)*\")*)* + [^"]* + \"(?:[^\\"]|\\.)*) + \"[[:blank:]]*\" + ((?:[^\\"]|\\.)*\") + /\1\2/x) + {} + + push(@parfile, $oneline); + + if ($insertemptyline) { push(@parfile, "\n"); } + + } + + return \@parfile; +} + +############################################ +# formatting the par file +############################################ + +sub formatter +{ + my ($parfile) = @_; + + my $iscodesection = 0; + + my $tabcounter = 0; + my $isinsideitem = 0; + my $currentitem; + + for ( my $i = 0; $i <= $#{$parfile}; $i++ ) + { + my $oneline = ${$parfile}[$i]; + my $isitemline = 0; + + if (! $isinsideitem ) + { + for ( my $j = 0; $j <= $#pre2par::globals::allitems; $j++ ) + { + if ( $oneline =~ /^\s*$pre2par::globals::allitems[$j]\s+\w+\s*$/ ) + { + $currentitem = $pre2par::globals::allitems[$j]; + $isitemline = 1; + $isinsideitem = 1; + $tabcounter = 0; + last; + } + } + } + + if ( $isitemline ) + { + next; # nothing to do + } + + if ( $oneline =~ /^\s*end\s*$/i ) + { + $isinsideitem = 0; + $tabcounter--; + } + + if ( $isinsideitem ) + { + $oneline = "\t" . $oneline; + ${$parfile}[$i] = $oneline; + } + } +} + +################################################### +# Returning the language file name +################################################### + +sub getlangfilename +{ + return $pre2par::globals::langfilename; +} + +################################################### +# Creating the ulf file name from the +# corresponding pre file name +################################################### + +sub getulffilename +{ + my ($prefilename) = @_; + + my $ulffilename = $prefilename; + $ulffilename =~ s/\.pre\s*$/\.ulf/; + pre2par::pathanalyzer::make_absolute_filename_to_relative_filename(\$ulffilename); + + return $ulffilename; +} + +############################################ +# Checking if a file exists +############################################ + +sub fileexists +{ + my ($langfilename) = @_; + + my $fileexists = 0; + + if( -f $langfilename ) { $fileexists = 1; } + + return $fileexists; +} + +############################################ +# Checking the existence of ulf and +# jlf/mlf files +############################################ + +sub check_existence_of_langfiles +{ + my ($langfilename, $ulffilename) = @_; + + my $do_localize = 0; + + if (( fileexists($ulffilename) ) && ( ! fileexists($langfilename) )) { pre2par::exiter::exit_program("Error: Did not find language file $langfilename", "check_existence_of_langfiles"); } + if (( fileexists($ulffilename) ) && ( fileexists($langfilename) )) { $do_localize = 1; } + + return $do_localize; +} + +############################################ +# Checking that the pre file has content +############################################ + +sub check_content +{ + my ($filecontent, $filename) = @_; + + if ( $#{$filecontent} < 0 ) { pre2par::exiter::exit_program("Error: $filename has no content!", "check_content"); } +} + +############################################ +# Checking content of par files. +# Currently only size. +############################################ + +sub diff_content +{ + my ($content1, $content2, $filename) = @_; + + if ( $#{$content1} != $#{$content2} ) { pre2par::exiter::exit_program("Error: $filename was not saved correctly!", "diff_content"); } +} + +1; diff --git a/solenv/bin/msg_filter b/solenv/bin/msg_filter new file mode 100755 index 000000000000..a7149c35a699 --- /dev/null +++ b/solenv/bin/msg_filter @@ -0,0 +1,61 @@ +: # -*- perl -*- +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +# This is a script to get rid of bogus error messages that are spit out +# by the compiler - sub 30/11/1999 + +# Lines that contain `xxxx' where xxxx belongs to the list knownMessages +# and is surrounded by a backtick (`) and a forward tick (') +# will not be seen in the compiler output + + +@knownMessages = ( +"__pure_virtual", +"__vt_9bad_alloc", +"__vt_9exception", +"_._9bad_alloc", +"__cp_push_exception", +"__uncatch_exception", +"__rtti_user", +"__rtti_si", +"__throw", +"terminate__Fv", +"__cp_pop_exception", +"__builtin_vec_new", +"__cmpdi2", +"__builtin_vec_delete", +"__cp_eh_info", +"__builtin_delete", +"__builtin_new", +"__eh_alloc", +"__check_eh_spec", +"_type_match_rtti", +"__rtti_class", +"set_new_handler_FPFv_v", +"__throw_type_match_rtti", +"__check_eh_spec", +"exception_type_info", +"exception type_info function", +"exception type_info node", +"exception virtual table", +"terminate(void)" +); + +# Create a hash %msgHash from list @knownMessages +foreach $msg (@knownMessages) { + $msgHash {$msg}++; +} +while ( <STDIN> ) { + + if (/\`([\s\w]+)\'/) { + $entry = $1; + if (defined($entry)) { + if (!exists $msgHash{$entry}) { + print $_; + } + } + } + else { + print $_; + } +} diff --git a/solenv/bin/newfolderforce b/solenv/bin/newfolderforce new file mode 100644 index 000000000000..8f77f3990acc --- /dev/null +++ b/solenv/bin/newfolderforce @@ -0,0 +1 @@ +#rg 16.6.98
if {#} != 1
echo emuliert "mkdir -p"
echo d.h. des gesamte Directory-Baum wird angelegt
exit
end
set wo "{1}"
set regex ""
set exit 0
for i in in 1 2 3 4 5 6 7 8 9 10
set regex "{regex}[Â:]+:"
(evaluate "{wo}" =~ /([:]+{regex})¨1Å/) > Dev:null
if not `exists -d "{¨1}"`
newfolder "{¨1}"
end
end
set exit 1
\ No newline at end of file diff --git a/solenv/bin/oochkpatch b/solenv/bin/oochkpatch new file mode 100755 index 000000000000..719f0765bcff --- /dev/null +++ b/solenv/bin/oochkpatch @@ -0,0 +1,6 @@ +#!/bin/sh +if [ x${SOLARENV}x = xx ]; then + echo No environment found, please use 'configure' or 'setsolar' + exit 1 +fi +exec perl -w $SOLARENV/bin/oochkpatch.pl "$@" diff --git a/solenv/bin/oochkpatch.btm b/solenv/bin/oochkpatch.btm new file mode 100755 index 000000000000..9d17c2f76e79 --- /dev/null +++ b/solenv/bin/oochkpatch.btm @@ -0,0 +1,2 @@ +@echo off +call perl5 %SOLARENV\bin\oochkpatch.pl %1& diff --git a/solenv/bin/oochkpatch.pl b/solenv/bin/oochkpatch.pl new file mode 100644 index 000000000000..a15a6ba6fcc7 --- /dev/null +++ b/solenv/bin/oochkpatch.pl @@ -0,0 +1,305 @@ +: + eval 'exec perl -S $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: oochkpatch.pl,v $ +# +# $Revision: 1.3 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +# +# oochkpatch - check patch flags against CWS modules +# + +require File::Temp; +require File::Find; +require Getopt::Long; +require Pod::Usage; +use Pod::Usage; +use Getopt::Long; +use File::Temp qw/ tempfile tempdir /; +use File::Find; + + +# configuration goes here +########################################################## + +# uncomment this, if in pure OOo environment +#my $toplevel_module = "instsetoo_native"; +#my $scp_module = "scp2"; +#my $setup_file = "setup_osl"; + +# uncomment this, if within the StarOffice environment +my $toplevel_module = "instset_native"; +my $scp_module = "scp2so"; +my $setup_file = "setup"; + +my $deliver = "solenv/bin/deliver.pl"; +my $build = "solenv/bin/build.pl"; + +# list of hardcoded exceptions (files that are _never_ considered +# missing from the patch) +my %hardcoded_exceptions = ('build.lst' => 1); + + +# no configuration below this point, please! +########################################################## + +# defaults +my $from_module = ""; +my $verbose = ''; +my $help = ''; +my $man = ''; +my $modules = ''; +my $from = ''; +my $perl = ''; + +GetOptions('help|?' => \$help, + 'man' => \$man, + 'verbose' => \$verbose, + 'from=s' => \$from_module ) or pod2usage(2); +pod2usage(1) if $help; +pod2usage(-exitstatus => 0, -verbose => 2) if $man; + +# process remaining args +print "Processing args...\n" if $verbose; +foreach my $argument (@ARGV) +{ + print " Checking module ", $argument, "\n" if $verbose; + push @modules, $argument; +} + +# platform-dependent stuff +if( $^O eq 'MSWin32' ) +{ + $perl = "$ENV{COMSPEC} -c $ENV{PERL}"; + $setup_file = $setup_file . ".inf"; +} +else +{ + $perl = 'perl'; + $setup_file = $setup_file . ".ins"; +}; + +# read some SOLAR stuff from env +my $SRC_ROOT = $ENV{"SRC_ROOT"}; +my $INPATH = $ENV{"INPATH"}; + +# process --from modules +if( $from_module ) +{ + print "Checking all modules upwards and including ", $from_module, "\n" if $verbose; + + # append build.pl-generated list of modules + chdir "$SRC_ROOT/$toplevel_module" or + chdir "$SRC_ROOT/$toplevel_module.lnk" or die "ERROR: cannot cd to $SRC_ROOT/$toplevel_module!"; + open(ALLMODULES, + "$perl $SRC_ROOT/$build --all:$from_module --show 2>&1 |") or die "ERROR: cannot build --show!\n"; + while(<ALLMODULES>) + { + if( /Building project/ ) + { + my @module = split( /\s+/, $_ ); + print " which is ", $module[2], "\n" if $verbose; + push(@modules,$module[2]); + } + } +} + +die "ERROR: no modules to check!\n" if !@modules; + +$tempdir = tempdir( TMPDIR => 1, CLEANUP => 1); + +# generate list of files with PATCH flag +print "Generating list of files which have the PATCH flag...\n" if $verbose; + +my $path_to_setup_file = $SRC_ROOT."/".$scp_module."/".$INPATH."/bin/osl/".$setup_file; +my $alternate_path_to_setup_file = $SRC_ROOT."/".$scp_module.".lnk/".$INPATH."/bin/osl/".$setup_file; +my $in_file_block=0; +my $patch_flag=0; +my $file_name=''; +my $base; +my $ext; +my %pack_files; +open(SETUP, "<".$path_to_setup_file) or + open(SETUP, "<".$alternate_path_to_setup_file) or die "ERROR: cannot open $path_to_setup_file!\n"; +while(<SETUP>) +{ + if( /^File\s+/ && !$in_file_block ) + { + $in_file_block = 1; + $patch_flag=0; + $file_name=''; + } + elsif( /^End/ && $file_name ne '' && $in_file_block ) + { + $file_name =~ s/["']//g; + $pack_files{$file_name} = $patch_flag; + + if( $patch_flag ) + { + print( " File $file_name included in patch\n") if $verbose; + } + else + { + print( " File $file_name NOT included in patch\n") if $verbose; + } + + $in_file_block = 0; + } + elsif( /^\s+Styles\s*=\s*.*PATCH/ && $in_file_block ) + { + $patch_flag = 1; + } + elsif( ($res) = /^\s+Name\s*=\s*(.*);/ ) + { + $file_name = $res; + } +} + +# generate list of delivered files +print "Generating list of delivered libs...\n" if $verbose; + +# first, deliver all modules to tempdir +foreach my $module (@modules) +{ + print " dummy-delivering $module...\n" if $verbose; + chdir "$SRC_ROOT/$module" or + chdir "$SRC_ROOT/$module.lnk" or die "ERROR: cannot cd to $SRC_ROOT/$module!"; + `$perl $SRC_ROOT/$deliver $tempdir`; +} + +# now, check all files in delivered dirs for containedness in PATCH +# set +print "Checking against delivered files...\n" if $verbose; +find(\&wanted, $tempdir ); + +sub wanted +{ + my $fname; + + if( -f ) + { + $fname = $_; + if( !exists $pack_files{$fname} ) + { + print " File $fname is not packed.\n" if $verbose; + } + elsif( $pack_files{$fname} == 0 ) + { + if( !$hardcoded_exceptions{ $fname } ) + { + # file not in patch set, and not in exception list + print " File $fname is packed, but NOT included in patch set and part of delivered output\n" if $verbose; + print "$fname\n" if !$verbose; + } + else + { + print " File $fname is NOT included in patch set, but member of hardcoded exception list\n" if $verbose; + } + } + elsif( $pack_files{$fname} == 1 ) + { + print " File $fname packed and patched.\n" if $verbose; + } + } +} + + +__END__ + +=head1 NAME + +oochkpatch.pl - Verify patch flags against module libraries + +=head1 SYNOPSIS + +oochkpatch.pl [options] [module-name ...] + + Options: + --help|-h brief help message + --man|-m full documentation + --verbose|-v tell what's happening + --from=module check all modules from + given one upwards + +=head1 OPTIONS + +=over 8 + +=item B<--help> + +Print a brief help message and exits. + +=item B<--man> + +Prints the manual page and exits. + +=item B<--verbose> + +Verbosely tell what's currently happening + +=item B<--from=module> + +Assumes OOo was built incompatibly from given module +upwards, and check against all libs from all upwards modules. +Further modules can be given at the command line, which are merged +with the ones generated from this option + +=back + +=head1 DESCRIPTION + +B<This program> will compare all libs delivered from the specified modules +against the set of files marked with the B<patch> flag in scp2. Useful to check +if the patch set is complete. Please note that this program needs to be run in +a solar shell, i.e. the OOo build environment needs to be set up in the shell. + +There's kind of a heuristic involved, to determine exactly which files +to check against includedness in the patch set (since e.g. all headers +are delivered, but clearly need not be checked against patch +flags). It works by first collecting all files that are mentioned in +the pack master file, and then checking all files delivered from the +specified modules against that pack list: if the file is not packed, +or if it's packed and has the patch flag set, all is well. Otherwise, +the file in question potentially misses the patch flag (because one of +the modified modules contains it). + +=head1 EXAMPLE + +To determine the set of libs not yet carrying the patch flag for a CWS +containing sfx2, svx, and vcl, which is incompatible from sfx2 +upwards, use something like this: + +oochkpatch.pl --from=sfx2 `cwsquery modules` + +This puts every module upwards and including sfx2 in the check list, +plus vcl. Note that with this approach, you'll usually get a larger +set of files for the patch than necessary - but at least you get all +files that might have changed theoretically. + +=cut diff --git a/solenv/bin/packager.pl b/solenv/bin/packager.pl new file mode 100644 index 000000000000..aca8a48cc9b6 --- /dev/null +++ b/solenv/bin/packager.pl @@ -0,0 +1,65 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: packager.pl,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +use lib ("$ENV{SOLARENV}/bin/modules"); + +use Cwd; +use packager::check; +use packager::files; +use packager::globals; +use packager::work; + +#################################### +# Main program +#################################### + +packager::check::check_environment(); +packager::check::check_packlist(); +packager::check::check_parameter(); + +packager::work::set_global_variable(); + +my $packagelist = packager::files::read_file($packager::globals::packlistname); + +my $targets = packager::work::create_package_todos($packagelist); + +if ( $ENV{'BSCLIENT'} ) { packager::work::start_build_server($targets); } +else { packager::work::execute_system_calls($targets); } + +if ( $packager::globals::logging ) +{ + packager::files::save_file($packager::globals::logfilename, \@packager::globals::logfileinfo); + print "Log file written: $packager::globals::logfilename\n"; +} + +#################################### +# End main program +#################################### diff --git a/solenv/bin/packimages.pl b/solenv/bin/packimages.pl new file mode 100755 index 000000000000..16cf2a113e8a --- /dev/null +++ b/solenv/bin/packimages.pl @@ -0,0 +1,441 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: packimages.pl,v $ +# +# $Revision: 1.17 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +# +# packimages.pl - pack images into archives +# + +use strict; +use Getopt::Long; +use File::Find; +use File::Basename; +use Archive::Zip qw(:ERROR_CODES :CONSTANTS); + +#### globals #### + +my $img_global = '%GLOBALRES%'; # 'global' image prefix +my $img_module = '%MODULE%'; # 'module' image prefix + +my $out_file; # path to output archive +my $tmp_out_file; # path to temporary output file +my $global_path; # path to global images directory +my $module_path; # path to module images directory +my $sort_file; # path to file containing sorting data +my @custom_path; # path to custom images directory +my @imagelist_path; # pathes to directories containing the image lists +my $verbose; # be verbose +my $extra_verbose; # be extra verbose +my $do_rebuild = 0; # is rebuilding zipfile required? + +my @custom_list; +#### script id ##### + +( my $script_name = $0 ) =~ s/^.*\b(\w+)\.pl$/$1/; + +my $script_rev; +my $id_str = ' $Revision: 1.17 $ '; +$id_str =~ /Revision:\s+(\S+)\s+\$/ + ? ($script_rev = $1) : ($script_rev = "-"); + +print "$script_name -- version: $script_rev\n"; + +#### main ##### + +parse_options(); +my $image_lists_ref = get_image_lists(); +my %image_lists_hash; +foreach ( @{$image_lists_ref} ) { + $image_lists_hash{$_}=""; +} +$do_rebuild = is_file_newer(\%image_lists_hash) if $do_rebuild == 0; +my ($global_hash_ref, $module_hash_ref, $custom_hash_ref) = iterate_image_lists($image_lists_ref); +# custom_hash filled from filesystem lookup +find_custom($custom_hash_ref); +my $zip_hash_ref = create_zip_list($global_hash_ref, $module_hash_ref, $custom_hash_ref); +$do_rebuild = is_file_newer($zip_hash_ref) if $do_rebuild == 0; +if ( $do_rebuild == 1 ) { + create_zip_archive($zip_hash_ref); + replace_file($tmp_out_file, $out_file); + print_message("packing $out_file finished."); +} else { + print_message("$out_file up to date. nothing to do."); +} + +exit(0); + +#### subroutines #### + +sub parse_options +{ + my $opt_help; + my $p = Getopt::Long::Parser->new(); + my @custom_path_list; + my $custom_path_extended; + my $success =$p->getoptions( + '-h' => \$opt_help, + '-o=s' => \$out_file, + '-g=s' => \$global_path, + '-s=s' => \$sort_file, + '-m=s' => \$module_path, + '-c=s' => \@custom_path_list, + '-e=s' => \$custom_path_extended, + '-l=s' => \@imagelist_path, + '-v' => \$verbose, + '-vv' => \$extra_verbose + ); + push @custom_path_list, $custom_path_extended if ($custom_path_extended); + if ( $opt_help || !$success || !$out_file || !$global_path + || !$module_path || !@custom_path_list || !@imagelist_path ) + { + usage(); + exit(1); + } + #define intermediate output file + $tmp_out_file="$out_file"."$$".$ENV{INPATH}; + # Sanity checks. + + # Check if out_file can be written. + my $out_dir = dirname($out_file); + + # Check paths. + foreach ($out_dir, $global_path, $module_path, @imagelist_path) { + print_error("no such directory: '$_'", 2) if ! -d $_; + print_error("can't search directory: '$_'", 2) if ! -x $_; + } + print_error("directory is not writable: '$out_dir'", 2) if ! -w $out_dir; + + # Use just the working paths + @custom_path = (); + foreach (@custom_path_list) { + if ( ! -d $_ ) { + print_warning("skipping non-existing directory: '$_'", 2); + } + elsif ( ! -x $_ ) { + print_error("can't search directory: '$_'", 2); + } + else { + push @custom_path, $_; + } + } +} + +sub get_image_lists +{ + my @image_lists; + my $glob_imagelist_path; + + foreach ( @imagelist_path ) { + $glob_imagelist_path = $_; + # cygwin perl + chomp( $glob_imagelist_path = qx{cygpath -u "$glob_imagelist_path"} ) if "$^O" eq "cygwin"; + push @image_lists, glob("$glob_imagelist_path/*.ilst"); + } + if ( !@image_lists ) { + print_error("can't find any image lists in '@imagelist_path'", 3); + } + + return wantarray ? @image_lists : \@image_lists; +} + +sub iterate_image_lists +{ + my $image_lists_ref = shift; + + my %global_hash; + my %module_hash; + my %custom_hash; + + foreach my $i ( @{$image_lists_ref} ) { + parse_image_list($i, \%global_hash, \%module_hash, \%custom_hash); + } + + return (\%global_hash, \%module_hash, \%custom_hash); +} + +sub parse_image_list +{ + my $image_list = shift; + my $global_hash_ref = shift; + my $module_hash_ref = shift; + my $custom_hash_ref = shift; + + print_message("parsing '$image_list' ...") if $verbose; + my $linecount = 0; + open(IMAGE_LIST, "< $image_list") or die "ERROR: can't open $image_list: $!"; + while ( <IMAGE_LIST> ) { + $linecount++; + next if /^\s*#/; + next if /^\s*$/; + # clean up trailing whitespace + tr/\r\n//d; + s/\s+$//; + # clean up backslashes and double slashes + tr{\\}{/}s; + tr{/}{}s; + # hack "res" back into globals + if ( /^\Q$img_global\E\/(.*)$/o ) { + $global_hash_ref->{"res/".$1}++; + next; + } + if ( /^\Q$img_module\E\/(.*)$/o ) { + $module_hash_ref->{$1}++; + next; + } + # parse failed if we reach this point, bail out + close(IMAGE_LIST); + print_error("can't parse line $linecount from file '$image_list'", 4); + } + close(IMAGE_LIST); + + return ($global_hash_ref, $module_hash_ref, $custom_hash_ref); +} + +sub find_custom +{ + my $custom_hash_ref = shift; + my $keep_back; + for my $path (@custom_path) { + find({ wanted => \&wanted, no_chdir => 0 }, $path); + foreach ( @custom_list ) { + if ( /^\Q$path\E\/(.*)$/ ) { + $keep_back=$1; + if (!defined $custom_hash_ref->{$keep_back}) { + $custom_hash_ref->{$keep_back} = $path; + } + } + } + } +} + +sub wanted +{ + my $file = $_; + + if ( $file =~ /.*\.png$/ && -f $file ) { + push @custom_list, $File::Find::name; + } +} + +sub create_zip_list +{ + my $global_hash_ref = shift; + my $module_hash_ref = shift; + my $custom_hash_ref = shift; + + my %zip_hash; + my @warn_list; + + print_message("assemble image list ...") if $verbose; + foreach ( keys %{$global_hash_ref} ) { + # check if in 'global' and in 'module' list and add to warn list + if ( exists $module_hash_ref->{$_} ) { + push(@warn_list, $_); + next; + } + if ( exists $custom_hash_ref->{$_} ) { + $zip_hash{$_} = $custom_hash_ref->{$_}; + next; + } + # it's neither in 'module' nor 'custom', record it in zip hash + $zip_hash{$_} = $global_path; + } + foreach ( keys %{$module_hash_ref} ) { + if ( exists $custom_hash_ref->{$_} ) { + $zip_hash{$_} = $custom_hash_ref->{$_}; + next; + } + # it's not in 'custom', record it in zip hash + $zip_hash{$_} = $module_path; + } + + if ( @warn_list ) { + foreach ( @warn_list ) { + print_warning("$_ is duplicated in 'global' and 'module' list"); + } + } + + return \%zip_hash +} + +sub is_file_newer +{ + my $test_hash_ref = shift; + my $reference_stamp = 0; + + print_message("checking timestamps ...") if $verbose; + if ( -e $out_file ) { + $reference_stamp = (stat($out_file))[9]; + print_message("found $out_file with $reference_stamp ...") if $verbose; + } + return 1 if $reference_stamp == 0; + + foreach ( sort keys %{$test_hash_ref} ) { + my $path = $test_hash_ref->{$_}; + $path .= "/" if "$path" ne ""; + $path .= "$_"; + print_message("checking '$path' ...") if $extra_verbose; + my $mtime = (stat($path))[9]; + return 1 if $reference_stamp < $mtime; + } + return 0; +} + +sub optimize_zip_layout($) +{ + my $zip_hash_ref = shift; + + if (!defined $sort_file) { + print_message("no sort file - sorting alphabetically ...") if $verbose; + return sort keys %{$zip_hash_ref}; + } + print_message("sorting from $sort_file ...") if $verbose; + + my $orderh; + my %included; + my @sorted; + open ($orderh, $sort_file) || die "Can't open $sort_file: $!"; + while (<$orderh>) { + /^\#.*/ && next; # comments + s/[\r\n]*$//; + /^\s*$/ && next; + my $file = $_; + if (!defined $zip_hash_ref->{$file}) { + print "unknown file '$file'\n" if ($extra_verbose); + } else { + push @sorted, $file; + $included{$file} = 1; + } + } + close ($orderh); + + for my $img (sort keys %{$zip_hash_ref}) { + push @sorted, $img if (!$included{$img}); + } + + print_message("done sort ...") if $verbose; + + return @sorted; +} + +sub create_zip_archive +{ + my $zip_hash_ref = shift; + + print_message("creating image archive ...") if $verbose; + my $zip = Archive::Zip->new(); + +# FIXME: test - $member = addfile ... $member->desiredCompressionMethod( COMPRESSION_STORED ); +# any measurable performance win/loss ? + foreach ( optimize_zip_layout($zip_hash_ref) ) { + my $path = $zip_hash_ref->{$_} . "/$_"; + print_message("zipping '$path' ...") if $extra_verbose; + my $member = $zip->addFile($path, $_); + if ( !$member ) { + print_error("can't add file '$path' to image zip archive: $!", 5); + } + } + my $status = $zip->writeToFileNamed($tmp_out_file); + if ( $status != AZ_OK ) { + print_error("write image zip archive '$tmp_out_file' failed. Reason: $status", 6); + } + return; +} + +sub replace_file +{ + my $source_file = shift; + my $dest_file = shift; + my $result = 0; + + $result = unlink($dest_file) if -f $dest_file; + if ( $result != 1 && -f $dest_file ) { + unlink $source_file; + print_error("couldn't remove '$dest_file'",1); + } else { + if ( !rename($source_file, $dest_file)) { + unlink $source_file; + print_error("couldn't rename '$source_file'",1); + } + } + return; +} + +sub usage +{ + print STDERR "Usage: packimages.pl [-h] -o out_file -g g_path -m m_path -c c_path -l imagelist_path\n"; + print STDERR "Creates archive of images\n"; + print STDERR "Options:\n"; + print STDERR " -h print this help\n"; + print STDERR " -o out_file path to output archive\n"; + print STDERR " -g g_path path to global images directory\n"; + print STDERR " -m m_path path to module images directory\n"; + print STDERR " -c c_path path to custom images directory\n"; + print STDERR " -s sort_file path to image sort order file\n"; + print STDERR " -l imagelist_path path to directory containing image lists (may appear mutiple times)\n"; + print STDERR " -v verbose\n"; + print STDERR " -vv very verbose\n"; +} + +sub print_message +{ + my $message = shift; + + print "$script_name: "; + print "$message\n"; + return; +} + +sub print_warning +{ + my $message = shift; + + print STDERR "$script_name: "; + print STDERR "WARNING $message\n"; + return; +} + +sub print_error +{ + my $message = shift; + my $error_code = shift; + + print STDERR "$script_name: "; + print STDERR "ERROR: $message\n"; + + if ( $error_code ) { + print STDERR "\nFAILURE: $script_name aborted.\n"; + exit($error_code); + } + return; +} diff --git a/solenv/bin/par2script.pl b/solenv/bin/par2script.pl new file mode 100644 index 000000000000..e7d89964df5e --- /dev/null +++ b/solenv/bin/par2script.pl @@ -0,0 +1,121 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: par2script.pl,v $ +# +# $Revision: 1.9 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +use lib ("$ENV{SOLARENV}/bin/modules"); + +use Cwd; +use par2script::check; +use par2script::files; +use par2script::globals; +use par2script::parameter; +use par2script::module; +use par2script::undefine; +use par2script::work; + +#################################### +# Main program +#################################### + +par2script::parameter::getparameter(); +par2script::parameter::control_parameter(); +par2script::parameter::outputparameter(); + +my $includes = par2script::work::setincludes($par2script::globals::includepathlist); +my $parfiles = par2script::work::setparfiles($par2script::globals::parfilelist); + +par2script::work::make_complete_pathes_for_parfiles($parfiles, $includes); + +print "Reading par files\n"; +my $parfilecontent = par2script::work::read_all_parfiles($parfiles); + +print "Collecting items\n"; +par2script::work::collect_definitions($parfilecontent); + +print "Collecting assigned items\n"; +par2script::work::collect_assigned_gids(); + +# print "First control of multiple assignments\n"; +# par2script::check::check_multiple_assignments(); + +print "Searching for Undefinitions\n"; +par2script::undefine::undefine_gids($parfilecontent); +par2script::undefine::remove_complete_item("Directory", $parfilecontent); +par2script::undefine::remove_complete_item("Profile", $parfilecontent); + +print "Removing assigned GIDs without definitions\n"; +par2script::module::remove_undefined_gids_from_modules(); + +print "Adding definitions without assignment to the root\n"; +par2script::module::add_to_root_module(); + +print "Control of multiple assignments\n"; +par2script::check::check_multiple_assignments(); + +print "Control of definitions with missing assignments\n"; +par2script::check::check_missing_assignments(); + +# checking the setup script +print "Checking directory definitions ...\n"; +par2script::check::check_needed_directories(); +par2script::check::check_directories_in_item_definitions(); +print "Checking module definitions ...\n"; +par2script::check::check_module_existence(); +print "Checking module assignments ...\n"; +par2script::check::check_moduleid_at_items(); +print "Checking StarRegistry ...\n"; +par2script::check::check_registry_at_files(); +print "Checking Root Module ..."; +par2script::check::check_rootmodule(); +print "Checking Shortcut assignments ...\n"; +par2script::check::check_shortcut_assignments(); +print "Checking missing parents ...\n"; +par2script::check::check_missing_parents(); + +print "Shorten lines at modules\n"; +par2script::module::shorten_lines_at_modules(); + +# Now the script can be created +print "Creating setup script\n"; +my $setupscript = par2script::work::create_script(); + +print "Saving script\n"; +par2script::files::save_file($par2script::globals::scriptname, $setupscript); + +# logging, if set +if ($par2script::globals::logging) +{ + par2script::files::save_file($par2script::globals::logfilename, \@par2script::globals::logfileinfo); + print "Log file written: $par2script::globals::logfilename\n"; +} + +#################################### +# End main program +#################################### diff --git a/solenv/bin/patch_sanitizer.pl b/solenv/bin/patch_sanitizer.pl new file mode 100755 index 000000000000..d7297f772497 --- /dev/null +++ b/solenv/bin/patch_sanitizer.pl @@ -0,0 +1,130 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: patch_sanitizer.pl,v $ +# +# $Revision: 1.6 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +use utf8; +use warnings; +use strict; + +# command line arguments +my $oldpatchfile = shift; +my $newpatchfile = shift; +my $sortedfile = shift; + +show_help() unless defined $oldpatchfile and defined $newpatchfile and defined $sortedfile; + +my %oldpatchfile = parse_patch($oldpatchfile); +my %newpatchfile = parse_patch($newpatchfile); + +open SORTEDPATCH, "> $sortedfile"; + +foreach my $file (sort (keys %newpatchfile)) { + print SORTEDPATCH $file."\t"; + if (defined($oldpatchfile{$file})) { + if ( (join '', @{$oldpatchfile{$file}{'data'}}) eq (join '', @{$newpatchfile{$file}{'data'}}) ) { + # patch data for the file hasn't been modified, use the header from + # the old patch, to reduce noise (keep the old timestamps) + print SORTEDPATCH $oldpatchfile{$file}{'origtimestamp'}."\n"; + print SORTEDPATCH $oldpatchfile{$file}{'patchedfilename'}."\t"; + print SORTEDPATCH $oldpatchfile{$file}{'patchedtimestamp'}."\n"; + print SORTEDPATCH @{$oldpatchfile{$file}{'data'}}; + next; + } + } + # either file wasn't patched before, or the patchset changed, so use the new + # values for it.. + print SORTEDPATCH $newpatchfile{$file}{'origtimestamp'}."\n"; + print SORTEDPATCH $newpatchfile{$file}{'patchedfilename'}."\t"; + print SORTEDPATCH $newpatchfile{$file}{'patchedtimestamp'}."\n"; + print SORTEDPATCH @{$newpatchfile{$file}{'data'}}; +} +close SORTEDPATCH; + +############### +# Helper subs +############### +sub show_help { + print "Usage: $0 oldpatch newpatch outputfilename\n"; + print "oldpatch and newpatch can be the very same file\n"; + print "will output a sanitized form of newpatch to outputfilename\n"; + print "if outputfilename is '-', the patch will be printed to stdout\n"; + print "sanitized means: It will avoid all unnecessary changes\n"; + exit 1; +} +sub parse_patch { + my $patchfile = shift; + my $patchtype; + my $pfirst; + my $psecond; + + my %hunks = (); + my $origfilename; + open PATCHFILE, "< $patchfile" or die "Cannot open file $patchfile $!"; + my @patchfile = <PATCHFILE>; + close PATCHFILE; + return %hunks if ( $#patchfile == -1 ); + if ( $patchfile[0] =~ /^---/ ) { + $patchtype = "unified"; + $pfirst = '^--- [^\*]*$'; + $psecond = '^\+\+\+ [^\*]*$'; + } elsif ( $patchfile[0] =~ /^\*\*\*/ ) { + $patchtype = "content"; + $pfirst = '^\*\*\* [^\*]*$'; + $psecond = '^--- .*\t.*$'; + } else { + die "unknown patch format\n"; + } + + foreach (@patchfile) { + if ( /$pfirst/ ) { + my $timestamp; + # extract the filename, to be able to compare the old + # with the new file... + ($origfilename, $timestamp) = split(/\t/, $_, 2); + chomp $timestamp; + # ideally convert the timestamp to iso-format... + $hunks{$origfilename}{'origtimestamp'} = $timestamp; + next; + } elsif ( $_ =~ /$psecond/ ) { + my ($filename, $timestamp) = split(/\t/, $_, 2); + chomp $timestamp; + # ideally convert the timestamp to iso-format... + $hunks{$origfilename}{'patchedfilename'} = $filename; + $hunks{$origfilename}{'patchedtimestamp'} = $timestamp; + next; + } + push (@{$hunks{$origfilename}{'data'}}, $_); + + } + return %hunks; +} diff --git a/solenv/bin/pchdelta b/solenv/bin/pchdelta new file mode 100755 index 000000000000..e33db2f96c84 --- /dev/null +++ b/solenv/bin/pchdelta @@ -0,0 +1,4 @@ +#!/bin/sh + +# Wrapper around the pchdelta.py script +bash -c "unset PYTHONHOME PYTHONPATH; /usr/bin/python ../solenv/bin/pchdelta.py $*" diff --git a/solenv/bin/pchdelta.py b/solenv/bin/pchdelta.py new file mode 100755 index 000000000000..52a0df4ecc5d --- /dev/null +++ b/solenv/bin/pchdelta.py @@ -0,0 +1,149 @@ +#!/usr/bin/python + +# ------------------------------------------------------------------------------ +# Hacky little delta debug tool to figure out the proper includes for a pch file +# +# Usage: +# +# pchdelta.py <pch_target> <dir1> [<dir2> <dir3> ...] +# +# <pch_target> File to perform delta debugging on. The section to test +# is delimeted by '//---MARKER---' lines. +# <dir1> .. <dirn> Sequence of directories to run dmake in to test if the +# modification works +# +# Examples: +# +# pchdelta.py inc/pch/precompiled_sfx2.hxx inc source/dialog +# +# Run pchdelta inside sfx2 first building the pch files and then files in +# source/dialog +# +# ------------------------------------------------------------------------------ + +import os +import os.path +import sys + +# C++ +MARKER="//---MARKER---\n" + +# dmake +#MARKER="#---MARKER---\n" + +# ------------------------------------------------------------------------------ +# Sequentially build all argument directories from scratch + +def testSequenceBuild(dirlist): + cwd = os.path.abspath(os.getcwd()) + for path in dirlist: + os.chdir(path) + buildcommand = "dmake -u" + buildcommand += " >>" + cwd + "/buildlog.txt 2>&1" + buildresult = os.system(buildcommand) + os.chdir(cwd) + if buildresult != 0: + return False + return True + +# ------------------------------------------------------------------------------ +# Dump out the delta file with corresponding markers + +def writePch(pchname, header, footer, acceptedlines, testlines): + outputfile = file(pchname, "w") + outputfile.write(header) + outputfile.write(MARKER) + outputfile.write("\n".join(acceptedlines)) + if len(testlines) > 0: + outputfile.write("\n\n//---Candidate marker---\n") + outputfile.write("\n".join(testlines) + "\n") + outputfile.write("//---Candidate marker end---\n") + outputfile.write(MARKER) + outputfile.write(footer) + outputfile.close() + + +# ------------------------------------------------------------------------------ +# Recursive tester routine. Test the segment given and if an error is +# encountered splits the segment into <fanout> subsegment and recurses. Failing +# one liners are rejected. The set of accepted lines are built sequentially from +# the beginning. + +def binaryTest(dirlist, lines, pchname, header, footer, acceptedlines, indent, startpoint): + linecount = len(lines) + if linecount == 0: + return + # Test if this slice passes the buildtest + writePch(pchname, header, footer, acceptedlines, lines) + if testSequenceBuild(dirlist): + return acceptedlines + lines + + # Reject one liners + if linecount == 1: + print indent + "Rejected: " + lines[0] + return acceptedlines + + # Recurse with multiline slices + fanout = 4 + splits = [] + for i in range(3): + splits.append(linecount * (i + 1) / fanout) + splits.append(linecount) + + splitstart = 0 + for splitend in splits: + # avoid splitting in case we have no resulting lines + if (splitend - splitstart) == 0: + continue + splitslice = lines[splitstart:splitend] + print indent + "[" + str(startpoint + splitstart) + ":" + str(startpoint + splitend) + "] (" + str(splitend - splitstart) + ")" + acceptedlines = binaryTest(dirlist, splitslice, pchname, header, footer, acceptedlines, indent + " ", startpoint + splitstart) + splitstart = splitend + + return acceptedlines + +# ------------------------------------------------------------------------------ +# Main entry point + +if len(sys.argv) < 3: + print "Usage: " + sys.argv[0] + " <pch_target> <dir1> [<dir2> <dir3> ...]" + sys.exit(1) + +pchname = os.path.abspath(sys.argv[1]) +dirlist = sys.argv[2:] + +# remove old build log file +if os.path.exists("buildlog.txt"): + os.remove("buildlog.txt") + +# test for corner case of everything working from the start +if testSequenceBuild(dirlist): + print "pch working, nothing to do." + sys.exit(0) + +# Open the header file for reading +inputfile = file(pchname, "r+") +inputdata = inputfile.read() +inputfile.close() + +segments = inputdata.split(MARKER) +header = segments[0] +footer = segments[2] +lines = segments[1].split("\n") + +writePch(pchname + "_backup", header, footer, lines, []) + +# test for corner case of no convergence possible +writePch(pchname, header, footer, [], []) +if not testSequenceBuild(dirlist): + writePch(pchname, header, footer, lines, []) + print "Building with no candidate lines failed. Convergence questionable, aborting." + sys.exit(0) + +# Starting pruning +print "Starting evaluation of " + str(len(lines)) + " lines" +acceptedlines = binaryTest(dirlist, lines, pchname, header, footer, [], "", 0) +writePch(pchname, header, footer, acceptedlines, []) + + + diff --git a/solenv/bin/pre2par.pl b/solenv/bin/pre2par.pl new file mode 100644 index 000000000000..2c243ce7bb48 --- /dev/null +++ b/solenv/bin/pre2par.pl @@ -0,0 +1,78 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: pre2par.pl,v $ +# +# $Revision: 1.8 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +use lib ("$ENV{SOLARENV}/bin/modules"); + +use Cwd; +use pre2par::directory; +use pre2par::files; +use pre2par::globals; +use pre2par::language; +use pre2par::parameter; +use pre2par::work; + +#################################### +# Main program +#################################### + +pre2par::parameter::getparameter(); +pre2par::parameter::control_parameter(); + +pre2par::directory::check_directory($pre2par::globals::parfilename); + +my $prefile = pre2par::files::read_file($pre2par::globals::prefilename); + +pre2par::work::check_content($prefile, $pre2par::globals::prefilename); + +my $parfile = pre2par::work::convert($prefile); + +pre2par::work::formatter($parfile); + +my $langfilename = pre2par::work::getlangfilename(); +my $ulffilename = pre2par::work::getulffilename($pre2par::globals::prefilename); + +my $dolocalization = pre2par::work::check_existence_of_langfiles($langfilename, $ulffilename); + +if ( $dolocalization ) +{ + my $langfile = pre2par::files::read_file($langfilename); + pre2par::language::localize($parfile, $langfile); +} + +pre2par::files::save_file($pre2par::globals::parfilename, $parfile); + +# checking of par file was written correctly +my $parfilecomp = pre2par::files::read_file($pre2par::globals::parfilename); +pre2par::work::diff_content($parfile, $parfilecomp, $pre2par::globals::parfilename); + +#################################### +# End main program +#################################### diff --git a/solenv/bin/receditor b/solenv/bin/receditor new file mode 100755 index 000000000000..f5d00bfb23fa --- /dev/null +++ b/solenv/bin/receditor @@ -0,0 +1,6 @@ +#!/bin/sh +if [ x${SOLARENV}x = xx ]; then + echo No environment found, please use 'configure' or 'setsolar' + exit 1 +fi +exec java -DSOLARSRC=${SOLARSRC} -DWORK_STAMP=${WORK_STAMP} -DUSE_SHELL= -jar ${SOLARVER}/${INPATH}/bin.${UPDMINOR}/receditor.jar diff --git a/solenv/bin/relocate b/solenv/bin/relocate new file mode 100755 index 000000000000..4b19a578636e --- /dev/null +++ b/solenv/bin/relocate @@ -0,0 +1,237 @@ +: + eval 'exec perl -S $0 ${1+"$@"}' + if 0; + +#************************************************************************* +# +# This tool makes it easy to cleanly re-locate a +# build, eg. after you have copied or moved it to a new +# path. It tries to re-write all the hard-coded path logic +# internally. +# +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: relocate,v $ +# +# $Revision: 1.6 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +sub sniff_set($) +{ + my $build_dir = shift; + my ($dirhandle, $fname); + + opendir ($dirhandle, $build_dir) || die "Can't open $build_dir"; + while ($fname = readdir ($dirhandle)) { + $fname =~ /[Ss]et.sh$/ && last; + } + closedir ($dirhandle); + + return $fname; +} + +sub sed_file($$$) +{ + my ($old_fname, $function, $state) = @_; + my $tmp_fname = "$old_fname.new"; + my $old_file; + my $new_file; + + open ($old_file, $old_fname) || die "Can't open $old_fname: $!"; + open ($new_file, ">$tmp_fname") || die "Can't open $tmp_fname: $!"; + + while (<$old_file>) { + my $value = &$function($state, $_); + print $new_file $value; + } + + close ($new_file) || die "Failed to close $tmp_fname: $!"; + close ($old_file) || die "Failed to close $old_fname: $!"; + + rename $tmp_fname, $old_fname || die "Failed to replace $old_fname: $!"; +} + +sub rewrite_value($$) +{ + my ($state, $value) = @_; + + $value =~ s/$state->{'old_root'}/$state->{'new_root'}/g; + $value =~ s/$state->{'win32_old_root'}/$state->{'win32_new_root'}/g; + + return $value; +} + +sub rewrite_set($$$) +{ + my $new_root = shift; + my $old_root = shift; + my $set = shift; + my $tmp; + my %state; + + print " $set\n"; + +# unix style + $state{'old_root'} = $old_root; + $state{'new_root'} = $new_root; +# win32 style + $tmp = $old_root; + $tmp =~ s/\//\\\\\\\\\\\\\\\\/g; + $state{'win32_old_root'} = $tmp; + $tmp = $new_root; + $tmp =~ s/\//\\\\\\\\/g; + $state{'win32_new_root'} = $tmp; + + sed_file ("$new_root/$set", \&rewrite_value, \%state); + + my $tcsh_set = $set; + $tcsh_set =~ s/\.sh$//; + + print " $tcsh_set\n"; + + sed_file ("$new_root/$tcsh_set", \&rewrite_value, \%state); +} + +sub find_old_root($$) +{ + my $new_root = shift; + my $set = shift; + my $fname = "$new_root/$set"; + my $old_root; + my $file; + + open ($file, $fname) || die "Can't open $fname: $!"; + + while (<$file>) { + if (/\s*([^=]+)\s*=\s*\"([^\"]+)\"/) { + my ($name, $value) = ($1, $2); + + if ($name eq 'SRC_ROOT') { + $old_root = $value; + last; + } + } + } + + close ($file) || die "Failed to close $fname: $!"; + + return $old_root; +} + +sub rewrite_product_deps($$$) +{ + my $new_root = shift; + my $product_path = shift; + my $old_root = shift; + + my $path = "$new_root/$product_path/misc"; + my $misc_dir; + opendir ($misc_dir, $path) || return; + my $name; + while ($name = readdir ($misc_dir)) { +# Should try re-writing these - but perhaps this would +# screw with timestamps ? + if ($name =~ m/\.dpcc$/ || $name =~ m/\.dpslo$/ || $name =~ m/\.dpobj$/) { + unlink ("$path/$name"); + } + } + closedir ($misc_dir); +} + +sub rewrite_dpcc($$) +{ + my $new_root = shift; + my $old_root = shift; + + my $top_dir; + my $idx = 0; + opendir ($top_dir, $new_root) || die "Can't open $new_root: $!"; + my $name; + while ($name = readdir ($top_dir)) { + my $sub_dir; + opendir ($sub_dir, "$new_root/$name") || next; + my $sub_name; + while ($sub_name = readdir ($sub_dir)) { + if ($sub_name =~ /\.pro$/) { + $idx || print "\n "; + if ($idx++ == 6) { + $idx = 0; + } + print "$name "; + rewrite_product_deps ($new_root, "$name/$sub_name", $old_root); + } + } + closedir ($sub_dir); + } + closedir ($top_dir); +} + +sub rewrite_bootstrap($$) +{ + my $new_root = shift; + my $old_root = shift; + + print " bootstrap\n"; + + my %state; + $state{'old_root'} = $old_root; + $state{'new_root'} = $new_root; + + my $rewrite = sub { my $state = shift; my $value = shift; + $value =~ s/$state->{'old_root'}/$state->{'new_root'}/g; + return $value; }; + sed_file ("$new_root/bootstrap", $rewrite, \%state); + `chmod +x $new_root/bootstrap`; +} + +for $a (@ARGV) { + if ($a eq '--help' || $a eq '-h') { + print "relocate: syntax\n"; + print " relocate /path/to/new/ooo/source_root\n"; + } +} + +$OOO_BUILD = shift (@ARGV) || die "Pass path to relocated source tree"; +substr ($OOO_BUILD, 0, 1) eq '/' || die "relocate requires absolute paths"; + +my $set; + +$set = sniff_set($OOO_BUILD) || die "Can't find env. set"; +$OLD_ROOT = find_old_root($OOO_BUILD, $set); + +print "Relocate: $OLD_ROOT -> $OOO_BUILD\n"; + +print "re-writing environment:\n"; + +rewrite_set($OOO_BUILD, $OLD_ROOT, $set); +rewrite_bootstrap($OOO_BUILD, $OLD_ROOT); + +print "re-writing dependencies:\n"; + +rewrite_dpcc($OOO_BUILD, $OLD_ROOT); + +print "done.\n"; diff --git a/solenv/bin/rmdir.pl b/solenv/bin/rmdir.pl new file mode 100644 index 000000000000..01b817eb9e59 --- /dev/null +++ b/solenv/bin/rmdir.pl @@ -0,0 +1,50 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: rmdir.pl,v $ +# +# $Revision: 1.2 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +my $r_code=0; +if ( ! defined $ARGV[0] || "$ARGV[0]" eq "" ) { + print STDERR "Nothing to delete\n"; + exit 1; +} +while ( defined $ARGV[0] ) { +if ( rmdir $ARGV[0] ) { +# exit 0; +} else { + print STDERR "ERROR removing $ARGV[0]: $!\n"; + $r_code = 1; +} +shift @ARGV; +} +exit $r_code; + diff --git a/solenv/bin/rpm-wrapper b/solenv/bin/rpm-wrapper new file mode 100755 index 000000000000..1b523bb9b130 --- /dev/null +++ b/solenv/bin/rpm-wrapper @@ -0,0 +1,45 @@ +#!/bin/bash +#************************************************************************* +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +#***********************************************************************/ + +# At least on v20z-so3, when /so/env/bt_linux_libc2.11/DEV300/bin/rpm is called +# and internally looks for a ld-linux.so.2, it picks up +# /lib/tls/i686/cmov/ld-linux.so.2 and SIGSEGVs. This is prevented by +# adding /so/env/bt_linux_libc2.11/DEV300/lib to the LD_LIBRARY_PATH, thus +# picking up the ld-linux.so.2 from there: + +set -e +if [ "$OUTPATH" = "unxlngi6" ] +then +LD_LIBRARY_PATH=${LD_LIBRARY_PATH+${LD_LIBRARY_PATH}:}${LIBRARY_PATH?} \ + ${BUILD_TOOLS?}/rpmbuild "$@" +else +LD_LIBRARY_PATH=${LD_LIBRARY_PATH+${LD_LIBRARY_PATH}:}${COMPATH?}/lib \ + ${BUILD_TOOLS?}/rpm "$@" +fi diff --git a/solenv/bin/slfl.pl b/solenv/bin/slfl.pl new file mode 100755 index 000000000000..b5d8987af4f3 --- /dev/null +++ b/solenv/bin/slfl.pl @@ -0,0 +1,180 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: slfl.pl,v $ +# +# $Revision: 1.3 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +# Description: Wrapper script to change '/' to '\' in command-line +# arguments. + +#--------------------------------------------------------------------------- +# external modules +use Text::ParseWords; + +# global vars +@params = (); + +#--------------------------------------------------------------------------- +# procedures + + +#---------------------------------------------------------- +# Function name: WinFormat +# Description: Format variables to Windows Format. +# Arguments: 1. Variable (string) with one token +# Return value: Reformatted String +#---------------------------------------------------------- +sub WinFormat { + my $variable = shift @_; + + $variable =~ s!(.)/!$1\\!g; # Replace all but the leading slashes with backslashes + + if ( defined $debug ) { + print(STDERR "WinFormat:\nresult:$variable\n"); + } + + return $variable; +} + +#---------------------------------------------------------- +# Function name: replace_cyg +# Description: Process all arguments and change them to Windows Format. +# Arguments: Reference to array with arguments +# Return value: - +#---------------------------------------------------------- +sub replace_cyg { + my $args = shift; + my( @cmd_file, @cmd_temp ); + my $atchars; + foreach my $para ( @$args ) { + if ( $para =~ "^@" ) { + # it's a command file + if ( defined $debug ) { + print(STDERR "----------------------------\n"); + } + ; + # Workaround, iz28717, keep number of @'s. + $para =~ s/(^\@+)//; + $atchars = $1; + $filename = $para; + if ( defined $debug ) { + print(STDERR "filename = $filename \n"); + } + ; + # open this command file for reading + open(CMD, "$filename"); + while ( <CMD> ) { + # Remove DOS lineendings. Bug in Cygwin / Perl? + $_ =~ s/\r//g; + # Remove lineendings and trailing spaces. ( Needed by &parse_line ) + $_ =~ s/\n$//g; + $_ =~ s/\s+$//g; + # Fill all tokens into array + @cmd_temp = &parse_line('\s+', 1, $_ ); + if ( $#cmd_temp > -1 ) { + push( @cmd_file, @cmd_temp); + } + } + close(CMD); + # reformat all tokens + replace_cyg(\@cmd_file); + if ( defined $debug ) { + print(STDERR "Tokens processed:\n"); + } + ; + foreach $i (@cmd_file) { + if ( defined $debug ) { + print(STDERR "!".$i."!\n"); + } + ; + } + # open this filename for writing (truncate) Textmode? + open(CMD, '>', $filename); + # write all tokens back into this file + print(CMD join(' ', @cmd_file)); + close(CMD); + # convert '@filename' to dos style + $para = WinFormat( $para ); + if ( defined $debug ) { + print(STDERR "----------------------------\n"); + } + ; + if ( (defined $debug_light) or (defined $debug) ) { + print(STDERR "\nParameter in File:".join(' ', @cmd_file).":\n"); + } + $para = $atchars.$para; + } else { + # it's just a parameter + if ( defined $debug ) { + print(STDERR "\nParameter:---${para}---\n"); + } + ; + # If $tmp1 is empty then $para is a parameter. + my $is_no_para = 1; + # remove .exe and convert to lower case + $shortcommand = lc $command ; + $shortcommand =~ s/\.exe$//; + $shortcommand =~ /([^\/]+$)/; + $shortcommand = $1; + if ( $is_no_para ) { + $para = WinFormat($para); + } + if ( defined $debug ) { + print(STDERR "Converted line:${para}:\n" ); + } + } # else + } # foreach loop +} + + +#--------------------------------------------------------------------------- +# main +@params = @ARGV; + +$command = shift(@params); + +while ( $command =~ /^-/ ) +{ + if ( $command eq "-dbg" ) { + $debug="true"; + } + elsif ( $command eq "-ldbg" ) { + $debug_light="true"; + } + + $command = shift(@params); +} + +if ( (defined $debug_light) or (defined $debug) ) { print( STDERR "Command: $command\n" ); } + +replace_cyg(\@params); +if ( (defined $debug_light) or (defined $debug) ) { print(STDERR "\n---------------------\nExecute: $command @params\n----------------\n");}; +exec( "$command", @params) or die( "\nError: slfl.pl: executing $command failed!\n" ); + diff --git a/solenv/bin/sort.pl b/solenv/bin/sort.pl new file mode 100644 index 000000000000..9e88552651f5 --- /dev/null +++ b/solenv/bin/sort.pl @@ -0,0 +1,54 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: sort.pl,v $ +# +# $Revision: 1.3 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +# +# sort.pl - Simply sort the input from stdin and pipe it to stdout. +# The sort needs to be *independent* of the settings of +# LC_ALL resp. LC_COLLATE +# + +use strict; +# be explicit: we want the perl standard sorting regardless the locale +no locale; + + +my @buffer; + +while(<>) { + push(@buffer, $_); +} + +foreach (sort @buffer) { + print $_; +} diff --git a/solenv/bin/touch.pl b/solenv/bin/touch.pl new file mode 100644 index 000000000000..2747dd822cea --- /dev/null +++ b/solenv/bin/touch.pl @@ -0,0 +1,46 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: touch.pl,v $ +# +# $Revision: 1.3 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +# +# workaround for broken 4nt +# internal touch command +# + +foreach my $filename (@ARGV) { + open KKK, ">>$filename" or die "ERROR: cannot open $filename!\n"; + $size=(stat($filename))[7]; + print KKK "x"; + truncate KKK, $size; + close KKK; +} + diff --git a/solenv/bin/unxmap-to-macosx-explist.awk b/solenv/bin/unxmap-to-macosx-explist.awk new file mode 100644 index 000000000000..4f8bd93035a9 --- /dev/null +++ b/solenv/bin/unxmap-to-macosx-explist.awk @@ -0,0 +1,67 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: unxmap-to-macosx-explist.awk,v $ +# +# $Revision: 1.3 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +# Generate an exported symbols list out of a map file (as use on Linux/Solaris) in order to +# build shared libraries on Mac OS X +# +# The below code fails may fail with 'perverted' mapfiles (using a strange line layout etc.) + +# Skip 'SECTION_NAME {' lines +/^[\t ]*.*[\t ]*\{/ { next } + +# Skip 'global:' or 'local:' lines +/global:/ || /local:/ { next } + +# Skip '*;' lines +/^[\t ]*\*;[\t ]*/ { next } + +# Skip section end '}?;' lines +/^[\t ]*\}[\t ]*.*[;]*/ { next } + +# Skip comment or empty lines +/^[\t ]*#.*/ || /^[\t ]*$/ || /^$/ { next } + +# Echo all lines containing symbol names and prefix them with '_' +# because symbols on Mac OS X start always with '__' +{ + # There may appear multiple symbols in one line + # e.g. "sym1; sym2; # and finally a comment" + # take this into account + for (i = 1; i <= NF ; i++) { + if ($i !~ /^[\t ]*#.*/) { # as long as the current field doesn't start with '#' + gsub(/[\t ;]/, "", $i) # Remove leading spaces and trailing ';' + printf("_%s\n",$i) + } + else { # ignore everything after a '#' (comment) sign + break + } + } +} diff --git a/solenv/bin/update_module_ignore_lists.pl b/solenv/bin/update_module_ignore_lists.pl new file mode 100644 index 000000000000..e4e4c2abe4e3 --- /dev/null +++ b/solenv/bin/update_module_ignore_lists.pl @@ -0,0 +1,259 @@ +: + eval 'exec perl -S $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: hicontrast-to-theme.pl,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +use Cwd; +use File::Temp qw/ tempfile tempdir /; + +my $verbosity = 1; # will be adjusted to the value of $Env{VERBOSE} below + +# platforms which are not supported anymore, and thus can be filtered from the svn:ignore list +my %obsolete_platforms = ( + ); + # (none so far) + +# platforms whose output trees should appear in all modules' svn:ignore list +my @platforms = ( + "common", + "unxlngi6", + "unxlngx6", + "unxsols4", + "unxsolu4", + "unxsoli4", + "wntmsci12", + "unxmacxi", + "unxubit8", + "unxaixp", + "unxbsda", + "unxbsdi2", + "unxbsdi", + "unxbsds", + "unxfbsdi", + "unxfbsd", + "unxfbsdx", + "unxhpgr", + "unxhpxr", + "unxirgm", + "unxirxm3", + "unxirxm", + "unxlnga", + "unxlngm68k", + "unxlngmips", + "unxlngp", + "unxlngppc4", + "unxlngppc64", + "unxlngppc", + "unxlngr", + "unxlngs3904", + "unxlngs390x", + "unxlngs", + "unxlnxi", + "unxmacxp", + "unxsogi", + "unxsogs" + ); + + +# ......................................................................... +# retrieves the repository URL of the SVN working copy in the current directory +sub retrieve_repo_url +{ + open( SVN, "svn info 2>&1 |" ); + my @result = <SVN>; + close( SVN ); + + foreach (@result) + { + chomp; + next if ( ! /^URL: / ); + s/^URL: //; + return $_; + } + return undef; +} + +# ......................................................................... +# gets the "modules" below the given SVN repository URL, by calling "svn list" +sub get_modules +{ + my @modules = (); + + open( SVN, "svn list $_ 2>&1 |" ); + my @result = <SVN>; + close( SVN ); + + foreach (@result) + { + chomp; + s/\/$//; + push @modules, $_; + } + + return @modules; +} + +# ......................................................................... +sub set_ignore_property +{ + my ($repo_url, @modules) = @_; + + # max length of a module name + my $max_len = 0; + foreach ( @modules ) { $max_len = length( $_ ) if ( length( $_ ) > $max_len ); } + + my $updated = 0; + + my $current = 0; + my $count = $#modules + 1; + foreach $module ( @modules ) + { + ++$current; + + # print progress + if ( $verbosity > 1 ) + { + my $progress = "$module "; + $progress .= "(" . $current . "/" . $count . ")"; + + my $dots = 3 + ( $max_len - length($module) ); + $dots += int( digits( $count ) ) - int( digits( $current ) ); + + $progress .= ( "." x $dots ); + $progress .= " "; + + print STDOUT $progress; + } + elsif ( $verbosity > 0 ) + { + print STDOUT "."; + } + + # retrieve the current ignore list + open( SVN, "svn propget svn:ignore $module 2>&1 |" ); + my @ignore_list = <SVN>; + close( SVN ); + + # the last item in the list is an empty string, usually. Don't let it confuse the below + # code + my $supposed_empty = pop @ignore_list; + chomp( $supposed_empty ); + push( @ignore_list, $supposed_empty ) if ( !( $supposed_empty =~ /^$/ ) ); + + # filter out obsolte entries + my @stripped_ignore_list = (); + foreach $ignore_entry (@ignore_list) + { + chomp( $ignore_entry ); + next if ( $ignore_entry =~ /^$/ ); + + if ( ( exists $obsolete_platforms{$ignore_entry} ) + || ( exists $obsolete_platforms{"$ignore_entry.pro"} ) + ) + { + next; + } + push @stripped_ignore_list, $ignore_entry; + } + my $removed = $#ignore_list - $#stripped_ignore_list; + @ignore_list = @stripped_ignore_list; + + # append the platforms which should appear in the ignore list + my %ignore_list = (); + foreach (@ignore_list) { $ignore_list{$_} = 1; } + foreach $platform_entry ( @platforms ) + { + $ignore_list{$platform_entry} = 1; + $ignore_list{"$platform_entry.pro"} = 1; + } + my @extended_ignore_list = keys %ignore_list; + my $added = $#extended_ignore_list - $#ignore_list; + @ignore_list = @extended_ignore_list; + + if ( $removed || $added ) + { + # create a temporary file taking the new content of the svn_ignore property + my $temp_dir = tempdir( CLEANUP => 1 ); + my ($fh, $filename) = tempfile( DIR => $dir ); + open( IGNORE, ">$filename" ); + print IGNORE join "\n", @ignore_list; + close( IGNORE ); + + # actually set the property + open( SVN, "svn propset -F $filename svn:ignore $module 2>&1 |" ); + + ++$updated; + } + + # statistics + print STDOUT "done (removed/added: $removed/$added)\n" if $verbosity > 1; + } + + print STDOUT "\n" if $verbosity eq 1; + print STDOUT "$updated module(s) updated\n" if $verbosity > 0; +} + +# ......................................................................... +sub digits +{ + my ($number, $base) = @_; + $base = 10 if !defined $base; + return log($number)/log($base); +} + +# ......................................................................... +# 'main' + +# initialize verbosity +my $verbose = $ENV{VERBOSE}; +if ( defined $verbose ) +{ + $verbose = uc( $verbose ); + $verbosity = 2 if ( $verbose eq "TRUE" ); + $verbosity = 0 if ( $verbose eq "FALSE" ); +} + +# work on the current directory +my $working_copy_root = cwd(); +die "current directory does not contain an SVN working copy" if !-d $working_copy_root . "/\.svn"; + +# retrieve repository URL +my $repo_url = retrieve_repo_url(); +die "unable to retrieve repository URL" if !defined $repo_url; +print STDOUT "repository URL: $repo_url\n" if $verbosity > 1; + +# list modules +my @modules = get_modules( $repo_url ); +print STDOUT "processing " . ( $#modules + 1 ) . " modules\n" if $verbosity > 0; + +# process modules, by setting the svn:ignore property +set_ignore_property( $repo_url, @modules ); diff --git a/solenv/bin/zipdep.pl b/solenv/bin/zipdep.pl new file mode 100755 index 000000000000..c83f4d32ef73 --- /dev/null +++ b/solenv/bin/zipdep.pl @@ -0,0 +1,341 @@ +: +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: header.hxx,v $ +# +# $Revision: 1.1 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +# +# mapgen - generate a dependencies file for zip commando +# +use Cwd; + +#### script id ##### + +( $script_name = $0 ) =~ s/^.*\b(\w+)\.pl$/$1/; + +$id_str = ' $Revision: 1.12 $ '; +$id_str =~ /Revision:\s+(\S+)\s+\$/ + ? ($script_rev = $1) : ($script_rev = "-"); + +print STDERR "$script_name -- version: $script_rev\n"; +print STDERR "Multi Platform Enabled Edition\n"; + +######################### +# # +# Globale Variablen # +# # +######################### + +$zip_file = ''; +$R = ''; +$r = ''; +$exclude = ''; +$include = ''; +@given_patterns = (); # patterns(files) list from command line +%files_in_arch = (); +@exc_patterns = (); # array of all patterns for files to be excluded +@inc_patterns = (); # array of all patterns for files to be included +%exc_files_hash = (); # hash of files to be excluded (according to @exc_patterns) +%inc_files_hash = (); # hash of files to be included (according to @inc_patterns) +$prefix = ''; + +#### main #### + +&get_options; +&get_zip_content; +&write_zip_file; + +#### end of main procedure #### + +######################### +# # +# Procedures # +# # +######################### + +# +# procedure writes zipdep file +# +sub write_zip_file { + my @dependencies = keys %files_in_arch; + if ($#dependencies != -1) { + print "\n". &convert_slashes($zip_file) . ' :'; + foreach (@dependencies) { + next if (-d); + print " \\\n\t" . $prefix . &convert_slashes($_); + }; + print "\n\n"; + }; +}; + +# +# convert slashes +# +sub convert_slashes { + my $path = shift; + $path =~ s/\//\$\//g; + $path =~ s/\\/\$\//g; + return $path; +}; + +# +# convert slashes to internal perl representation +# +sub perled_slashes { + my $path = shift; + $path =~ s/\\/\//g; + $path =~ s/\/+/\//g; + return $path; +}; + +# +# Collect all files to zip in @patterns_array array +# +sub get_zip_content { + &get_zip_entries(\@given_patterns); + my $file_name = ''; + foreach $file_name (keys %files_in_arch) { + if (-d $file_name) { + &get_dir_content($file_name, \%files_in_arch) if ($r || $R); + undef $files_in_arch{$file_name}; + }; + }; + &remove_uncompliant(\@given_patterns) if ($R); + &get_patterns_files(\@exc_patterns, \%exc_files_hash) if ($exclude); + &get_patterns_files(\@inc_patterns, \%inc_files_hash) if ($include); + foreach my $file_name (keys %exc_files_hash) { + if (defined $files_in_arch{$file_name}) { + delete $files_in_arch{$file_name}; + #print STDERR "excluded $file_name\n"; + }; + }; + if ($include) { + foreach my $file_name (keys %files_in_arch) { + if (!(defined $inc_files_hash{$file_name})) { + delete $files_in_arch{$file_name}; + }; + }; + } +}; + +# +# Procedure removes from %files_in_arch all files which +# are not compliant to patterns in @given_patterns +# +sub remove_uncompliant { + my $given_patterns = shift; + my @reg_exps = (); + my $pattern = ''; + foreach $pattern (@$given_patterns) { + push(@reg_exps, &make_reg_exp($pattern)); + }; + # write file name as a value for the path(key) + foreach my $file (keys %files_in_arch) { + next if (-d $file); + #print "$file\n"; + if ($file =~ /[\\ | \/](.+)$/) { + $files_in_arch{$file} = $1; + } else { + $files_in_arch{$file} = $file; + }; + }; + foreach $pattern (@reg_exps) { + foreach my $file (keys %files_in_arch) { + if (!($files_in_arch{$file} =~ /$pattern/)) { + delete $files_in_arch{$file}; + #} else { + # print "Complient: $file\n"; + }; + }; + }; +}; + +# +# Procedure adds/removes to/from %files_in_arch all files, that are +# compliant to the patterns in array passed +# +sub get_zip_entries { + if ($R) { + opendir DIR, '.'; + my @dir_content = readdir(DIR); + close DIR; + foreach my $file_name(@dir_content) { + $file_name =~ /^\.$/ and next; + $file_name =~ /^\.\.$/ and next; + $files_in_arch{$file_name}++; + #print "included $file_name\n"; + }; + } else { + my $patterns_array = shift; + my $pattern = ''; + foreach $pattern (@$patterns_array) { + if ((-d $pattern) || (-f $pattern)) { + $files_in_arch{$pattern}++; + next; + } + my $file_name = ''; + foreach $file_name (glob $pattern) { + #next if (!(-d $file_name) || !(-f $file_name)); + $files_in_arch{$file_name}++; + }; + }; + } +}; + +# +# Procedure converts given parameter to a regular expression +# +sub make_reg_exp { + my $arg = shift; + $arg =~ s/\\/\\\\/g; + $arg =~ s/\//\\\//g; + $arg =~ s/\./\\\./g; + $arg =~ s/\+/\\\+/g; + $arg =~ s/\{/\\\{/g; + $arg =~ s/\}/\\\}/g; + $arg =~ s/\*/\.\*/g; + $arg =~ s/\?/\./g; + #$arg = '/'.$arg.'/'; + #print "Regular expression: $arg\n"; + return $arg; +}; + +# +# Procedure retrieves shell pattern and converts them into regular expressions +# +sub get_patterns { + my $patterns = shift; + my $arg = ''; + while ($arg = shift @ARGV) { + $arg =~ /^-/ and unshift(@ARGV, $arg) and return; + if (!$zip_file) { + $zip_file = $arg; + next; + }; + $arg = &make_reg_exp($arg); + push(@$patterns, $arg); + }; +}; + +# +# Get all options passed +# +sub get_options { + my ($arg); + &usage() && exit(0) if ($#ARGV == -1); + while ($arg = shift @ARGV) { + $arg = &perled_slashes($arg); + #print STDERR "$arg\n"; + $arg =~ /^-R$/ and $R = 1 and next; + $arg =~ /^-r$/ and $r = 1 and next; + $arg =~ /^-x$/ and $exclude = 1 and &get_patterns(\@exc_patterns) and next; + $arg =~ /^-i$/ and $include = 1 and &get_patterns(\@inc_patterns) and next; + $arg =~ /^-prefix$/ and $prefix = shift @ARGV and next; + $arg =~ /^-b$/ and shift @ARGV and next; + $arg =~ /^-n$/ and shift @ARGV and next; + $arg =~ /^-t$/ and shift @ARGV and next; + $arg =~ /^-tt$/ and shift @ARGV and next; + $arg =~ /^-h$/ and &usage and exit(0); + $arg =~ /^--help$/ and &usage and exit(0); + $arg =~ /^-?$/ and &usage and exit(0); + if ($arg =~ /^-(\w)(\w+)$/) { + unshift (@ARGV, '-'.$1); + unshift (@ARGV, '-'.$2); + next; + }; +# just ignore other switches... + $arg =~ /^-(\w+)$/ and next; + $arg =~ /^\/\?$/ and &usage and exit(0); + $zip_file = $arg and next if (!$zip_file); + push(@given_patterns, $arg); + }; + &print_error('error: Invalid command arguments (do not specify both -r and -R)') if ($r && $R); + if ($r && ($#given_patterns == -1)) { + &print_error('no list specified'); + }; +}; + +# +# Procedure fills out passed hash with files from passed dir +# compliant to the pattern from @$patterns +# +sub get_patterns_files { + my $patterns_array = shift; + my $files_hash = shift; + my @zip_files = keys %files_in_arch; + foreach my $pattern (@$patterns_array) { + my @fit_pattern = grep /$pattern/, @zip_files; + foreach my $entry (@fit_pattern) { + $$files_hash{$entry}++; + #print "$entry\n"; + }; + }; +}; + +# +# Get dir stuff to pack +# +sub get_dir_content { + my $dir = shift; + my $dir_hash_ref = shift; + my $entry = ''; + if (opendir(DIR, $dir)) { + my @prj_dir_list = readdir(DIR); + closedir (DIR); + foreach $entry (@prj_dir_list) { + $entry =~ /^\.$/ and next; + $entry =~ /^\.\.$/ and next; + + $entry = $dir . '/' . $entry; + # if $enry is a dir - read all its files, + # otherwise store $entry itself + if (-d $entry) { + &get_dir_content($entry, $dir_hash_ref); + } else { + $$dir_hash_ref{$entry}++; + }; + }; + }; + return '1'; +}; + +sub print_error { + my $message = shift; + print STDERR "\nERROR: $message\n"; + exit (1); +}; + +sub usage { + print STDERR " zipdep [-aABcdDeEfFghjklLmoqrRSTuvVwXyz] [-b path]\n"; + print STDERR " [-n suffixes] [-t mmddyyyy] [-tt mmddyyyy] [ zipfile [\n"; + print STDERR " file1 file2 ...]] [-xi list]\n"; +} + |