Commits

Anonymous committed 19581e5

CWS-TOOLING: integrate CWS native197_DEV300

Comments (0)

Files changed (15)

instsetoo_native/util/openoffice.lst

 			PROGRESSPOSITION 14,230
 			PROGRESSFRAMECOLOR 58,159,232
 			REGISTRYLAYERNAME Layers
+            SERVICEPACK 1
+            UPDATE_DATABASE 1
+            CREATE_MSP_INSTALLSET 0
+            UPDATE_DATABASE_LISTNAME finals_instsetoo.txt
 			WINDOWSPATCHLEVEL 2
 		}
 	}
 			USERDIRPRODUCTVERSION 3
 			ABOUTBOXPRODUCTVERSION 3.1.0
 			BASEPRODUCTVERSION 3.1
+            PCPFILENAME openoffice.pcp
 			UPDATEURL http://update32.services.openoffice.org/ProductUpdateService/check.Update
             ODFNOTIFYURL http://odfnotify.services.openoffice.org/OOo3.0/notification.jsp?version=ODF
 			ADD_INCLUDE_FILES cliureversion.mk,clioootypesversion.mk,userland.txt
             SETSTATICPATH 1
             NOVERSIONINDIRNAME 1
             PROGRAMFILESROOT 1
+            PCPFILENAME ure.pcp
             GLOBALFILEGID gid_File_Dl_Cppu
             DOWNLOADBANNER urebanner.bmp
             DOWNLOADBITMAP urebitmap.bmp

setup_native/prj/d.lst

 ..\source\java\javaversion.dat %_DEST%\bin%_EXT%\javaversion.dat
 ..\source\packinfo\solariscopyrightfile %_DEST%\bin%_EXT%\solariscopyrightfile
 ..\source\packinfo\*.txt %_DEST%\bin%_EXT%\*.txt
+..\source\packinfo\*.pcp %_DEST%\bin%_EXT%\*.pcp
+..\scripts\admin.pl %_DEST%\bin%_EXT%\admin.pl
 ..\scripts\*.txt %_DEST%\bin%_EXT%\*.txt
 
 ..\%__SRC%\lib\getuid.so %_DEST%\bin%_EXT%\getuid.so

setup_native/scripts/admin.pl

+#*************************************************************************
+#
+# 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.pl,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.
+#
+#*************************************************************************
+
+use File::Copy;
+
+#################################################################################
+# Global settings
+#################################################################################
+
+BEGIN
+{
+	$prog = "msi installer";
+	$targetdir = "";
+	$databasepath = "";
+	$starttime = "";
+	$globaltempdirname = "ooopackaging";
+	$savetemppath = "";
+	$msiinfo_available = 0;
+
+	$plat = $^O;
+
+	if ( $plat =~ /cygwin/i )
+	{
+		$separator = "/";
+		$pathseparator = "\:";
+	}
+	else
+	{
+		$separator = "\\";
+		$pathseparator = "\;";
+	}
+}
+
+#################################################################################
+# Program information
+#################################################################################
+
+sub usage
+{
+	print <<Ende;
+----------------------------------------------------------------------
+$prog V1.0 (c) Sun Microsystems 2008
+This program installs a Windows Installer installation set
+without using msiexec.exe. The installation is comparable
+with an administrative installation using the Windows Installer
+service.
+Required parameter:
+-d Path to installation set or msi database
+-t Target directory
+---------------------------------------------------------------------
+Ende
+	exit(-1);
+}
+
+#################################################################################
+# Collecting parameter
+#################################################################################
+
+sub getparameter
+{
+	if (( $#ARGV < 3 ) || ( $#ARGV > 3 )) { usage(); }
+
+	while ( $#ARGV >= 0 )
+	{
+		my $param = shift(@ARGV);
+		
+		if ($param eq "-t") { $targetdir = shift(@ARGV); }
+		elsif ($param eq "-d") { $databasepath = shift(@ARGV); }
+		else
+		{
+			print "\n**********************************************\n";
+			print "Error: Unknows parameter: $param";
+			print "\n**********************************************\n";
+			usage();
+			exit(-1);
+		}
+	}
+}
+
+#################################################################################
+# Checking content of parameter
+#################################################################################
+
+sub controlparameter
+{
+	if ( $targetdir eq "" )
+	{
+		print "\n******************************************************\n";
+		print "Error: Target directory not defined (parameter -t)!";
+		print "\n******************************************************\n";
+		usage();
+		exit(-1);
+	}
+
+	if ( $databasepath eq "" )
+	{
+		print "\n******************************************************\n";
+		print "Error: Path to msi database not defined (parameter -d)!";
+		print "\n******************************************************\n";
+		usage();
+		exit(-1);
+	}
+	
+	if ( -d $databasepath )
+	{
+		$databasepath =~ s/\\\s*$//;
+		$databasepath =~ s/\/\s*$//;
+		
+		my $msifiles = find_file_with_file_extension("msi", $databasepath);
+	
+		if ( $#{$msifiles} < 0 ) { exit_program("ERROR: Did not find msi database in directory $installationdir"); }
+		if ( $#{$msifiles} > 0 ) { exit_program("ERROR: Did find more than one msi database in directory $installationdir"); }
+
+		$databasepath = $databasepath . $separator . ${$msifiles}[0];
+	}
+
+	if ( ! -f $databasepath ) { exit_program("ERROR: Did not find msi database in directory $databasepath."); }
+	
+	if ( ! -d $targetdir ) { create_directories($targetdir); }
+}
+
+#############################################################################
+# 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;
+}
+
+#########################################################
+# Checking the local system
+# Checking existence of needed files in include path
+#########################################################
+
+sub check_system_path
+{
+	my $onefile;	
+	my $error = 0;
+	my $pathvariable = $ENV{'PATH'};
+	my $local_pathseparator = $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 = convert_stringlist_into_array(\$pathvariable, $local_pathseparator);
+	
+	my @needed_files_in_path = ("msidb.exe", "expand.exe");
+	my @optional_files_in_path = ("msiinfo.exe");
+
+	print("\nChecking required files:\n");
+
+	foreach $onefile ( @needed_files_in_path )
+	{
+		print("...... searching $onefile ...");
+
+		my $fileref = get_sourcepath_from_filename_and_includepath(\$onefile, $patharrayref);
+
+		if ( $$fileref eq "" )
+		{
+			$error = 1;
+			print( "$onefile not found\n" );
+		}
+		else
+		{
+			print( "\tFound: $$fileref\n" );
+		}		
+	}
+
+	if ( $error ) { exit_program("ERROR: Could not find all needed files in path (using setsolar should help)!"); }
+
+	print("\nChecking optional files:\n");
+
+	foreach $onefile ( @optional_files_in_path )
+	{
+		print("...... searching $onefile ...");
+
+		my $fileref = get_sourcepath_from_filename_and_includepath(\$onefile, $patharrayref);
+
+		if ( $$fileref eq "" )
+		{
+			print( "$onefile not found\n" );
+			if ( $onefile eq "msiinfo.exe" ) { $msiinfo_available = 0; }
+		}
+		else
+		{
+			print( "\tFound: $$fileref\n" );
+			if ( $onefile eq "msiinfo.exe" ) { $msiinfo_available = 1; }
+		}		
+	}
+
+}
+
+##########################################################################
+# Searching a file in a list of pathes
+##########################################################################
+
+sub get_sourcepath_from_filename_and_includepath
+{
+	my ($searchfilenameref, $includepatharrayref) = @_;
+
+	my $onefile = "";
+	my $foundsourcefile = 0;
+		
+	for ( my $j = 0; $j <= $#{$includepatharrayref}; $j++ )
+	{
+		my $includepath = ${$includepatharrayref}[$j];
+		$includepath =~ s/^\s*//;
+		$includepath =~ s/\s*$//;
+
+		$onefile = $includepath . $separator . $$searchfilenameref;
+
+		if ( -f $onefile )
+		{
+			$foundsourcefile = 1;
+			last;
+		}
+	}
+
+	if (!($foundsourcefile)) { $onefile = ""; }
+	
+	return \$onefile;
+}
+
+########################################################
+# Finding all files with a specified file extension
+# in a specified directory.
+########################################################
+
+sub find_file_with_file_extension
+{
+	my ($extension, $dir) = @_;
+	
+	my @allfiles = ();
+	my @sourcefiles = ();
+
+	$dir =~ s/\Q$separator\E\s*$//;
+
+	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 directory with all parent directories
+##############################################################
+
+sub create_directories
+{
+	my ($directory) = @_;
+
+	if ( ! try_to_create_directory($directory) )
+	{
+		my $parentdir = $directory;
+		get_path_from_fullqualifiedname(\$parentdir);
+		create_directories($parentdir);   # recursive
+	}
+	
+	create_directory($directory);	# now it has to succeed
+}
+
+##############################################################
+# Creating one directory
+##############################################################
+
+sub create_directory
+{
+	my ($directory) = @_;
+
+	if ( ! -d $directory ) { mkdir($directory, 0775); }
+}
+
+##############################################################
+# 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;
+	
+            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;
+}
+
+###########################################
+# Getting path from full file name
+###########################################
+
+sub get_path_from_fullqualifiedname
+{
+	my ($longfilenameref) = @_;
+
+	if ( $$longfilenameref =~ /\Q$separator\E/ )	# Is there a separator in the path? Otherwise the path is empty.
+	{	
+		if ( $$longfilenameref =~ /^\s*(\S.*\S\Q$separator\E)(\S.+\S?)/ )
+		{
+			$$longfilenameref = $1;
+		}
+	}
+	else
+	{
+		$$longfilenameref = "";	# there is no path
+	}	
+}
+
+##############################################################
+# Getting file name from full file name
+##############################################################
+
+sub make_absolute_filename_to_relative_filename
+{
+	my ($longfilenameref) = @_;
+	
+	# Either '/' or '\'.
+	if ( $$longfilenameref =~ /^.*[\/\\](\S.+\S?)/ )
+	{
+		$$longfilenameref = $1;
+	}
+}
+
+############################################
+# Exiting the program with an error
+# This function is used instead of "die"
+############################################
+
+sub exit_program
+{
+	my ($message) = @_;
+
+	print "\n***************************************************************\n";
+	print "$message\n";
+	print "***************************************************************\n";
+	remove_complete_directory($savetemppath, 1);
+	print "\n" . get_time_string();
+	exit(-1);	
+}
+
+#################################################################################
+# Unpacking cabinet files with expand
+#################################################################################
+
+sub unpack_cabinet_file
+{
+	my ($cabfilename, $unpackdir) = @_;
+	
+	my $expandfile = "expand.exe";	# Has to be in the path
+	my $expandlogfile = $unpackdir . $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);
+
+	if ($returnvalue) { exit_program("ERROR: Could not execute $systemcall !"); }
+}
+
+#################################################################################
+# Extracting tables from msi database
+#################################################################################
+
+sub extract_tables_from_database
+{
+	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";
+	print "\nAnalyzing msi database\n";
+	$returnvalue = system($systemcall);
+
+	if ($returnvalue)
+	{
+		$infoline = "ERROR: Could not execute $systemcall !\n";
+		exit_program($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 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 . $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) = @_;
+
+	print "Creating directories\n";
+	
+	my %fullpathhash = ();
+	
+	my @startparents = ("TARGETDIR", "INSTALLLOCATION");
+	
+	foreach $dir (@startparents) { create_directory_tree($dir, \%fullpathhash, $targetdir, $dirhash); }
+	
+	return \%fullpathhash;
+}
+
+######################################################
+# Creating a new directory 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)
+		{	
+            if ( defined $ENV{'USE_SHELL'} && $ENV{'USE_SHELL'} ne "4nt" )
+			{
+				my $localcall = "chmod $privileges $directory \>\/dev\/null 2\>\&1";
+				system($localcall);
+			}			
+		}
+	}
+	else
+	{
+		if ( defined $ENV{'USE_SHELL'} && $ENV{'USE_SHELL'} ne "4nt" )
+		{
+			my $localcall = "chmod $privileges $directory \>\/dev\/null 2\>\&1";
+			system($localcall);
+		}			
+	}
+}
+
+######################################################
+# Creating a unique directory with pid extension	
+######################################################
+
+sub create_pid_directory
+{
+	my ($directory) = @_;
+	
+	$directory =~ s/\Q$separator\E\s*$//;
+	my $pid = $$;			# process id
+	my $time = time();		# time
+	
+	$directory = $directory . "_" . $pid . $time;
+
+	if ( ! -d $directory ) { create_directory($directory); }		
+	else { exit_program("ERROR: Directory $directory already exists!"); }
+	
+	return $directory;
+}
+
+####################################################################################
+# Copying files into installation set
+####################################################################################
+
+sub copy_files_into_directory_structure
+{
+	my ($fileorder, $filehash, $componenthash, $fullpathhash, $maxsequence, $unpackdir, $installdir, $dirhash) = @_;
+
+	print "Copying files\n";
+
+	my $unopkgfile = "";
+	my @extensions = ();
+	
+	for ( my $i = 1; $i <= $maxsequence; $i++ )
+	{
+		if ( exists($fileorder->{$i}) )
+		{
+			my $file = $fileorder->{$i};
+			if ( ! exists($filehash->{$file}->{'Component'}) ) { exit_program("ERROR: Did not find component for file: \"$file\"."); }
+			my $component = $filehash->{$file}->{'Component'};
+			if ( ! exists($componenthash->{$component}) ) { exit_program("ERROR: Did not find directory for component: \"$component\"."); }
+			my $dirname = $componenthash->{$component};
+			if ( ! exists($fullpathhash->{$dirname}) ) { exit_program("ERROR: Did not find full directory path for dir: \"$dirname\"."); }
+			my $destdir = $fullpathhash->{$dirname};
+			if ( ! exists($filehash->{$file}->{'FileName'}) ) { exit_program("ERROR: Did not find \"FileName\" for file: \"$file\"."); }
+			my $destfile = $filehash->{$file}->{'FileName'};
+
+			$destfile = $destdir . $separator . $destfile;
+			my $sourcefile = $unpackdir . $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'} . $separator; }
+				my $realfilename = $filehash->{$file}->{'FileName'};
+				my $localinstalldir = $installdir;
+				
+				$localinstalldir =~ s/\\\s*$//;
+				$localinstalldir =~ s/\/\s*$//;
+				
+				$sourcefile = $localinstalldir . $separator . $subdir . $realfilename;
+				
+				if ( ! -f $sourcefile ) { exit_program("ERROR: File not found: \"$oldsourcefile\" (or \"$sourcefile\")."); }
+			}
+
+			my $copyreturn = copy($sourcefile, $destfile);
+
+			if ( ! $copyreturn) { exit_program("ERROR: Could not copy $source to $dest\n"); }
+
+			# Collecting all extensions
+			if ( $destfile =~ /\.oxt\s*$/ ) { push(@extensions, $destfile); }
+			# Searching unopkg.exe
+			if ( $destfile =~ /unopkg\.exe\s*$/ ) { $unopkgfile = $destfile; }
+		}
+		# else	# allowing missing sequence numbers ?
+		# {
+		# 	exit_program("ERROR: No file assigned to sequence $i");
+		# }
+	}
+	
+	return ($unopkgfile, \@extensions);
+}
+
+######################################################
+# Removing a complete directory with subdirectories
+######################################################
+
+sub remove_complete_directory
+{
+	my ($directory, $start) = @_;
+
+	my @content = ();
+	my $infoline = "";
+	
+	$directory =~ s/\Q$separator\E\s*$//;
+
+	if ( -d $directory )
+	{
+		if ( $start ) { print "Removing directory $directory\n"; }
+	
+		opendir(DIR, $directory);
+		@content = readdir(DIR);
+		closedir(DIR);
+
+		my $oneitem;
+	
+		foreach $oneitem (@content)
+		{
+			if ((!($oneitem eq ".")) && (!($oneitem eq "..")))
+			{
+				my $item = $directory . $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 ) { print "Warning: Problem with removing empty dir $directory\n"; }
+	}	
+}
+
+####################################################################################
+# Defining a temporary path
+####################################################################################
+
+sub get_temppath
+{
+	my $temppath = "";
+	
+	if (( $ENV{'TMP'} ) || ( $ENV{'TEMP'} ))
+	{
+		if ( $ENV{'TMP'} ) { $temppath = $ENV{'TMP'}; }
+		elsif ( $ENV{'TEMP'} )  { $temppath = $ENV{'TEMP'}; }
+
+		$temppath =~ s/\Q$separator\E\s*$//;	# removing ending slashes and backslashes
+		$temppath = $temppath . $separator . $globaltempdirname;
+		create_directory_with_privileges($temppath, "777");
+
+		my $dirsave = $temppath;
+
+		$temppath = $temppath . $separator . "a";
+		$temppath = create_pid_directory($temppath);
+
+		if ( ! -d $temppath ) { exit_program("ERROR: Failed to create directory $temppath ! Possible reason: Wrong privileges in directory $dirsave."); }
+
+		if ( $^O =~ /cygwin/i )
+		{
+			$temppath =~ s/\\/\\\\/g;
+			chomp( $temppath = qx{cygpath -w "$temppath"} ); 
+		}
+		
+		$savetemppath = $temppath;
+	}
+	else
+	{
+		exit_program("ERROR: Could not set temporary directory (TMP and TEMP not set!).");
+	}
+	
+	return $temppath;
+}
+
+####################################################################################
+# Registering one extension
+####################################################################################
+
+sub register_one_extension
+{
+	my ($unopkgfile, $extension, $temppath) = @_;
+
+	print "... $extension\n";
+
+	$temppath =~ s/\\/\//g;
+	$temppath = "/".$temppath;
+
+	my $systemcall = "\"" . $unopkgfile . "\"" . " add --shared --verbose " . "\"" . $extension . "\"" . " -env:UserInstallation=file://" . "\"" . $temppath . "\"" . " 2\>\&1 |";
+
+	my @unopkgoutput = ();
+
+	open (UNOPKG, $systemcall);
+	while (<UNOPKG>) {push(@unopkgoutput, $_); }
+	close (UNOPKG);
+
+	my $returnvalue = $?;	# $? contains the return value of the systemcall
+
+	if ($returnvalue)
+	{
+		print "ERROR: Could not execute \"$systemcall\"!\nExitcode: '$returnvalue'\n";
+		for ( my $j = 0; $j <= $#unopkgoutput; $j++ ) { print "$unopkgoutput[$j]"; }
+		exit_program("ERROR: $systemcall failed!");
+	}
+}
+
+####################################################################################
+# Registering all extensions located in /share/extension/install
+####################################################################################
+
+sub register_extensions
+{
+	my ($unopkgfile, $extensions, $temppath) = @_;
+	
+	if ( $#{$extensions} > -1 )
+	{
+		print "Registering extensions:\n"; 
+
+		if (( ! -f $unopkgfile ) || ( $unopkgfile eq "" )) { exit_program("ERROR: Could not find unopkg.exe!"); }
+
+		foreach $extension ( @{$extensions} ) { register_one_extension($unopkgfile, $extension, $temppath); }
+		
+		remove_complete_directory($temppath, 1)
+	}
+	else
+	{
+		print "No extensions to register.\n"; 
+	}
+}
+
+####################################################################################
+# Reading one file
+####################################################################################
+
+sub read_file
+{
+	my ($localfile) = @_;
+
+	my @localfile = ();
+
+	open( IN, "<$localfile" ) || exit_program("ERROR: Cannot open file $localfile for reading");
+
+	#	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;
+}
+
+###############################################################
+# 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];
+	
+	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;
+}
+
+###############################################################
+# 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) = @_ ;
+
+	print "Setting SIS in msi database\n";
+	
+	if ( ! -f $msidatabase ) { exit_program("ERROR: Cannot find file $msidatabase"); }
+
+	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";
+	$returnvalue = system($systemcall);
+
+	if ($returnvalue)
+	{
+		$infoline = "ERROR: Could not execute $systemcall !\n";
+		exit_program($infoline);
+	}	
+}
+
+###############################################################
+# 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 - $starttime;
+	$currenttime = convert_timestring($currenttime);
+	$currenttime = localtime() . " \(" . $currenttime . "\)\n";
+	return $currenttime;
+}
+
+####################################################################################
+# Simulating an administrative installation
+####################################################################################
+
+$starttime = time();
+
+getparameter();
+controlparameter();
+check_system_path();
+my $temppath = get_temppath();
+
+print("\nmsi database: $databasepath\n");
+print("Destination directory: $targetdir\n" );
+
+my $helperdir = $temppath . $separator . "installhelper";
+create_directory($helperdir);
+	
+# Get File.idt, Component.idt and Directory.idt from database
+	
+my $tablelist = "File Directory Component";
+extract_tables_from_database($databasepath, $helperdir, $tablelist);
+	
+# Unpack all cab files into $helperdir, cab files must be located next to msi database
+my $installdir = $databasepath;
+get_path_from_fullqualifiedname(\$installdir);
+my $databasefilename = $databasepath;
+make_absolute_filename_to_relative_filename(\$databasefilename);
+
+my $cabfiles = find_file_with_file_extension("cab", $installdir);
+	
+if ( $#{$cabfiles} < 0 ) { exit_program("ERROR: Did not find any cab file in directory $installdir"); }
+
+# Set unpackdir
+my $unpackdir = $helperdir . $separator . "unpack";
+create_directory($unpackdir);
+
+print "Unpacking files from cabinet file(s)\n";
+for ( my $i = 0; $i <= $#{$cabfiles}; $i++ )
+{
+	my $cabfile = $installdir . $separator . ${$cabfiles}[$i];
+	unpack_cabinet_file($cabfile, $unpackdir);
+}
+	
+# Reading tables
+my $filename = $helperdir . $separator . "Directory.idt";
+my $filecontent = read_file($filename);
+my $dirhash = analyze_directory_file($filecontent);
+	
+$filename = $helperdir . $separator . "Component.idt";
+$filecontent = read_file($filename);
+my $componenthash = analyze_component_file($filecontent);
+	
+$filename = $helperdir . $separator . "File.idt";
+$filecontent = read_file($filename);
+my ( $filehash, $fileorder, $maxsequence ) = analyze_file_file($filecontent);
+
+# Creating the directory structure
+my $fullpathhash = create_directory_structure($dirhash, $targetdir);
+
+# Copying files
+my ($unopkgfile, $extensions) = copy_files_into_directory_structure($fileorder, $filehash, $componenthash, $fullpathhash, $maxsequence, $unpackdir, $installdir, $dirhash);
+	
+my $msidatabase = $targetdir . $separator . $databasefilename;
+my $copyreturn = copy($databasepath, $msidatabase);
+if ( ! $copyreturn) { exit_program("ERROR: Could not copy $source to $dest\n"); }
+
+# Registering extensions
+register_extensions($unopkgfile, $extensions, $temppath);
+
+# Saving info in Summary Information Stream of msi database (required for following patches)
+if ( $msiinfo_available ) { write_sis_info($msidatabase); }
+
+# Removing the helper directory
+remove_complete_directory($temppath, 1);
+
+print "\nSuccessful installation: " . get_time_string();

setup_native/source/packinfo/finals_instsetoo.txt

+# Comment line
+# Syntax:
+# Column 1: Product
+# Column 2: pro or nonpro
+# Column 3: languages, comma separated list
+# Column 4: path to msi database in installation set
+# Separator between columns is one or more than one tabulator
+
+# Examples:
+# OpenOffice	pro		en-US		\\<server>\<path>\msi\OOO300_m6_native_packed-1_en-US.9352\openofficeorg30.msi
+# OpenOffice	pro		en-US,de,es	\\<server>\<path>\msi\OOO300_m6_native_packed-1_en-US_de_es.9352\openofficeorg30.msi
+# OpenOffice	pro		de			\\<server>\<path>\msi\OOO300_m6_native_packed-1_de.9352\openofficeorg30.msi
+# OpenOfficeLanguagePack	pro	es	\\<server>\<path>\msi\OOO300_m6_native_packed-1_es.9352\openofficeorg30.msi
+# URE			pro		en-US		\\<server>\<path>\msi\OOO300_m6_native_packed-1_en-US.9352\ure14.msi

setup_native/source/packinfo/openoffice.pcp

+��ࡱ�

setup_native/source/packinfo/openofficelanguagepack.pcp

+��ࡱ�

setup_native/source/packinfo/ure.pcp

+��ࡱ�

solenv/bin/make_installer.pl

 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;
 		if ( $allvariableshashref->{'UPDATE_DATABASE'} )
 		{
 			installer::logger::print_message( "... analyzing update database ...\n" );
-
-			$installer::globals::updatedatabase = 1;
-			$refdatabase = installer::windows::update::readdatabase($allvariableshashref->{'UPDATE_DATABASE'}, $languagestringref);
-			($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); }
+			$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); }
+			}
 		}
 	}
 
 		($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);
+			($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
 		#######################################################
 

solenv/bin/modules/installer/control.pm

 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
 #########################################################
 		$local_pathseparator = ';';
 	}
 	my $patharrayref = installer::converter::convert_stringlist_into_array(\$pathvariable, $local_pathseparator);
+	
+	$installer::globals::patharray = $patharrayref;
 
 	my @needed_files_in_path = ();
 

solenv/bin/modules/installer/globals.pm

 	$globalblock = "Globals";
 	$rootmodulegid = "";
 	%alllangmodules = ();
+	$patharray = "";
 	
 	$is_special_epm = 0;
 	$epm_in_path = 0;
 	$updatelastsequence = 0;
 	$updatesequencecounter = 0;
 	$updatedatabase = 0;
+	$updatedatabasepath = "";
 	$pfffileexists = 0;
 	$pffcabfilename = "ooobasis3.0_pff.cab";
 	$mergemodulenumber = 0;

solenv/bin/modules/installer/windows/admin.pm

+#*************************************************************************
+#
+# 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);
+	}
+}
+
+#################################################################################
+# 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: $fullpcpfilepath !", "extract_all_tables_from_msidatabase");
+	}
+	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 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 $source to $dest\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];
+
+	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;
+}
+
+###############################################################
+# 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";
+	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";
+	$filecontent = installer::files::read_file($filename);
+	my $componenthash = analyze_component_file($filecontent);
+	
+	$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);
+	
+	# Saving info in Summary Information Stream of msi database (required for following patches)
+	write_sis_info($msidatabase);
+
+	return $msidatabase;
+}
+
+1;

solenv/bin/modules/installer/windows/mergemodule.pm

 
 		my $returnvalue = system($systemcall);
 
-		my $infoline = "Systemcall: $systemcall\n";
+		$infoline = "Systemcall: $systemcall\n";
 		push( @installer::globals::logfileinfo, $infoline);
 
 		if ($returnvalue)

solenv/bin/modules/installer/windows/msp.pm

+#*************************************************************************
+#
+# 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";
+
+	# 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
+
+	$systemcall = $msimsp . " -s " . $fullpcpfilename . " -p " . $mspfilename . " -l " . $logfilename;
+	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);
+	}
+}
+
+####################################################################
+# 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