2 # This file is part of the LibreOffice project.
4 # This Source Code Form is subject to the terms of the Mozilla Public
5 # License, v. 2.0. If a copy of the MPL was not distributed with this
6 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 # This file incorporates work covered by the following license notice:
10 # Licensed to the Apache Software Foundation (ASF) under one or more
11 # contributor license agreements. See the NOTICE file distributed
12 # with this work for additional information regarding copyright
13 # ownership. The ASF licenses this file to you under the Apache
14 # License, Version 2.0 (the "License"); you may not use this file
15 # except in compliance with the License. You may obtain a copy of
16 # the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 package installer
::windows
::component
;
24 use installer
::exiter
;
26 use installer
::globals
;
27 use installer
::windows
::idtglobal
;
28 use installer
::windows
::language
;
30 ##############################################################
31 # Returning a globally unique ID (GUID) for a component
32 # If the component is new, a unique guid has to be created.
33 # If the component already exists, the guid has to be
34 # taken from a list component <-> guid
35 # Sample for a guid: {B68FD953-3CEF-4489-8269-8726848056E8}
36 ##############################################################
38 sub get_component_guid
40 my ( $componentname, $componentidhashref ) = @_;
42 # At this time only a template
43 my $returnvalue = "\{COMPONENTGUID\}";
45 if (( $installer::globals
::updatedatabase
) && ( exists($componentidhashref->{$componentname}) ))
47 $returnvalue = $componentidhashref->{$componentname};
50 # Returning a ComponentID, that is assigned in scp project
51 if ( exists($installer::globals
::componentid
{$componentname}) )
53 $returnvalue = "\{" . $installer::globals
::componentid
{$componentname} . "\}";
59 ##############################################################
60 # Returning the directory for a file component.
61 ##############################################################
63 sub get_file_component_directory
65 my ($componentname, $filesref, $dirref) = @_;
67 my ($onefile, $component, $onedir, $hostname, $uniquedir);
70 for ( my $i = 0; $i <= $#{$filesref}; $i++ )
72 $onefile = ${$filesref}[$i];
73 $component = $onefile->{'componentname'};
75 if ( $component eq $componentname )
84 # This component can be ignored, if it exists in a version with extension "_pff" (this was renamed in file::get_sequence_for_file() )
85 my $ignore_this_component = 0;
86 my $origcomponentname = $componentname;
87 my $componentname = $componentname . "_pff";
89 for ( my $j = 0; $j <= $#{$filesref}; $j++ )
91 $onefile = ${$filesref}[$j];
92 $component = $onefile->{'componentname'};
94 if ( $component eq $componentname )
96 $ignore_this_component = 1;
101 if ( $ignore_this_component ) { return "IGNORE_COMP"; }
102 else { installer
::exiter
::exit_program
("ERROR: Did not find component \"$origcomponentname\" in file collection", "get_file_component_directory"); }
105 my $localstyles = "";
107 if ( $onefile->{'Styles'} ) { $localstyles = $onefile->{'Styles'}; }
109 if ( $localstyles =~ /\bFONT\b/ ) # special handling for font files
111 return $installer::globals
::fontsfolder
;
116 if ( $onefile->{'Dir'} ) { $destdir = $onefile->{'Dir'}; }
118 my $destination = $onefile->{'destination'};
120 installer
::pathanalyzer
::get_path_from_fullqualifiedname
(\
$destination);
122 $destination =~ s/\Q$installer::globals::separator\E\s*$//;
124 # This path has to be defined in the directory collection at "HostName"
126 if ($destination eq "") # files in the installation root
128 $uniquedir = "INSTALLLOCATION";
134 for ( my $i = 0; $i <= $#{$dirref}; $i++ )
136 $onedir = ${$dirref}[$i];
137 $hostname = $onedir->{'HostName'};
139 if ( $hostname eq $destination )
148 installer
::exiter
::exit_program
("ERROR: Did not find destination $destination in directory collection", "get_file_component_directory");
151 $uniquedir = $onedir->{'uniquename'};
153 if ( $uniquedir eq $installer::globals
::officeinstalldirectory
)
155 $uniquedir = "INSTALLLOCATION";
159 $onefile->{'uniquedirname'} = $uniquedir; # saving it in the file collection
164 ##############################################################
165 # Returning the directory for a registry component.
166 # This cannot be a useful value
167 ##############################################################
169 sub get_registry_component_directory
171 my $componentdir = "INSTALLLOCATION";
173 return $componentdir;
176 ##############################################################
177 # Returning the attributes for a file component.
178 ##############################################################
180 sub get_file_component_attributes
182 my ($componentname, $filesref, $allvariables) = @_;
188 # special handling for font files
193 for ( my $i = 0; $i <= $#{$filesref}; $i++ )
195 $onefile = ${$filesref}[$i];
196 my $component = $onefile->{'componentname'};
198 if ( $component eq $componentname )
207 installer
::exiter
::exit_program
("ERROR: Did not find component in file collection", "get_file_component_attributes");
210 my $localstyles = "";
212 if ( $onefile->{'Styles'} ) { $localstyles = $onefile->{'Styles'}; }
214 if ( $localstyles =~ /\bFONT\b/ )
216 $attributes = 8; # font files will be deinstalled if the ref count is 0
219 if ( $localstyles =~ /\bASSEMBLY\b/ )
221 $attributes = 0; # Assembly files cannot run from source
224 if ( $onefile->{'needs_user_registry_key'} )
226 $attributes = 4; # Files in non advertised startmenu entries must have user registry key as KeyPath
229 # Setting msidbComponentAttributes64bit, if this is a 64 bit installation set.
230 if (( $allvariables->{'64BITPRODUCT'} ) && ( $allvariables->{'64BITPRODUCT'} == 1 )) { $attributes |= 256; }
235 ##############################################################
236 # Returning the attributes for a registry component.
237 # Always 4, indicating, the keypath is a defined in
239 ##############################################################
241 sub get_registry_component_attributes
243 my ($componentname, $allvariables) = @_;
249 # Setting msidbComponentAttributes64bit, if this is a 64 bit installation set.
250 if (( $allvariables->{'64BITPRODUCT'} ) && ( $allvariables->{'64BITPRODUCT'} == 1 )) { $attributes |= 256; }
252 # Setting msidbComponentAttributes64bit for 64 bit shell extension in 32 bit installer, too
253 if ( $componentname =~ m/winexplorerext_x64/ ) { $attributes |= 256; }
258 ##############################################################
259 # Returning the conditions for a component.
260 # This is important for language dependent components
261 # in multilingual installation sets.
262 ##############################################################
264 sub get_file_component_condition
266 my ($componentname, $filesref) = @_;
270 if (exists($installer::globals
::componentcondition
{$componentname}))
272 $condition = $installer::globals
::componentcondition
{$componentname};
275 # there can be also tree conditions for multilayer products
276 if (exists($installer::globals
::treeconditions
{$componentname}))
278 if ( $condition eq "" )
280 $condition = $installer::globals
::treeconditions
{$componentname};
284 $condition = "($condition) And ($installer::globals::treeconditions{$componentname})";
291 ##############################################################
292 # Returning the conditions for a registry component.
293 ##############################################################
295 sub get_component_condition
297 my ($componentname) = @_;
301 $condition = ""; # Always ?
303 if (exists($installer::globals
::componentcondition
{$componentname}))
305 $condition = $installer::globals
::componentcondition
{$componentname};
311 ####################################################################
312 # Returning the keypath for a component.
313 # This will be the name of the first file/registry, found in the
314 # collection $itemsref
315 # Attention: This has to be the unique (file)name, not the
317 ####################################################################
319 sub get_component_keypath
321 my ($componentname, $itemsref, $componentidkeypathhashref) = @_;
327 for ( my $i = 0; $i <= $#{$itemsref}; $i++ )
329 $oneitem = ${$itemsref}[$i];
330 my $component = $oneitem->{'componentname'};
332 if ( $component eq $componentname )
341 installer
::exiter
::exit_program
("ERROR: Did not find component in file/registry collection, function get_component_keypath", "get_component_keypath");
344 my $keypath = $oneitem->{'uniquename'}; # "uniquename", not "Name"
346 # Special handling for updates from existing databases, because KeyPath must not change
347 if (( $installer::globals
::updatedatabase
) && ( exists($componentidkeypathhashref->{$componentname}) ))
349 $keypath = $componentidkeypathhashref->{$componentname};
350 # -> check, if this is a valid key path?!
351 if ( $keypath ne $oneitem->{'uniquename'} )
353 # Warning: This keypath was changed because of info from old database
354 $infoline = "WARNING: The KeyPath for component \"$componentname\" was changed from \"$oneitem->{'uniquename'}\" to \"$keypath\" because of information from update database";
355 push(@installer::globals
::logfileinfo
, $infoline);
359 if ( $oneitem->{'userregkeypath'} ) { $keypath = $oneitem->{'userregkeypath'}; }
361 # saving it in the file and registry collection
362 $oneitem->{'keypath'} = $keypath;
367 ###################################################################
368 # Creating the file Componen.idt dynamically
370 # Component ComponentId Directory_ Attributes Condition KeyPath
371 ###################################################################
373 sub create_component_table
375 my ($filesref, $registryref, $dirref, $allfilecomponentsref, $allregistrycomponents, $basedir, $componentidhashref, $componentidkeypathhashref, $allvariables) = @_;
377 my @componenttable = ();
379 my ($oneline, $infoline);
381 installer
::windows
::idtglobal
::write_idt_header
(\
@componenttable, "component");
385 for ( my $i = 0; $i <= $#{$allfilecomponentsref}; $i++ )
387 my %onecomponent = ();
389 $onecomponent{'name'} = ${$allfilecomponentsref}[$i];
390 $onecomponent{'guid'} = get_component_guid
($onecomponent{'name'}, $componentidhashref);
391 $onecomponent{'directory'} = get_file_component_directory
($onecomponent{'name'}, $filesref, $dirref);
392 if ( $onecomponent{'directory'} eq "IGNORE_COMP" ) { next; }
393 $onecomponent{'attributes'} = get_file_component_attributes
($onecomponent{'name'}, $filesref, $allvariables);
394 $onecomponent{'condition'} = get_file_component_condition
($onecomponent{'name'}, $filesref);
395 $onecomponent{'keypath'} = get_component_keypath
($onecomponent{'name'}, $filesref, $componentidkeypathhashref);
397 $oneline = $onecomponent{'name'} . "\t" . $onecomponent{'guid'} . "\t" . $onecomponent{'directory'} . "\t"
398 . $onecomponent{'attributes'} . "\t" . $onecomponent{'condition'} . "\t" . $onecomponent{'keypath'} . "\n";
400 push(@componenttable, $oneline);
403 # Registry components
405 for ( my $i = 0; $i <= $#{$allregistrycomponents}; $i++ )
407 my %onecomponent = ();
409 $onecomponent{'name'} = ${$allregistrycomponents}[$i];
410 $onecomponent{'guid'} = get_component_guid
($onecomponent{'name'}, $componentidhashref);
411 $onecomponent{'directory'} = get_registry_component_directory
();
412 $onecomponent{'attributes'} = get_registry_component_attributes
($onecomponent{'name'}, $allvariables);
413 $onecomponent{'condition'} = get_component_condition
($onecomponent{'name'});
414 $onecomponent{'keypath'} = get_component_keypath
($onecomponent{'name'}, $registryref, $componentidkeypathhashref);
416 $oneline = $onecomponent{'name'} . "\t" . $onecomponent{'guid'} . "\t" . $onecomponent{'directory'} . "\t"
417 . $onecomponent{'attributes'} . "\t" . $onecomponent{'condition'} . "\t" . $onecomponent{'keypath'} . "\n";
419 push(@componenttable, $oneline);
424 my $componenttablename = $basedir . $installer::globals
::separator
. "Componen.idt";
425 installer
::files
::save_file
($componenttablename ,\
@componenttable);
426 $infoline = "Created idt file: $componenttablename\n";
427 push(@installer::globals
::logfileinfo
, $infoline);
430 ####################################################################################
431 # Returning a component for a scp module gid.
432 # Pairs are saved in the files collector.
433 ####################################################################################
435 sub get_component_name_from_modulegid
437 my ($modulegid, $filesref) = @_;
439 my $componentname = "";
441 for my $file ( @
{$filesref} )
443 next if ( ! $file->{'modules'} );
445 my @filemodules = split /,\s*/, $file->{'modules'};
447 if (grep {$_ eq $modulegid} @filemodules)
449 $componentname = $file->{'componentname'};
454 return $componentname;
457 ####################################################################################
458 # Updating the file Environm.idt dynamically
460 # Environment Name Value Component_
461 ####################################################################################
463 sub set_component_in_environment_table
465 my ($basedir, $filesref) = @_;
469 my $environmentfilename = $basedir . $installer::globals
::separator
. "Environm.idt";
471 if ( -f
$environmentfilename ) # only do something, if file exists
473 my $environmentfile = installer
::files
::read_file
($environmentfilename);
475 for ( my $i = 3; $i <= $#{$environmentfile}; $i++ ) # starting in line 4 of Environm.idt
477 if ( ${$environmentfile}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ )
479 my $modulegid = $4; # in Environment table a scp module gid can be used as component replacement
481 my $componentname = get_component_name_from_modulegid
($modulegid, $filesref);
483 if ( $componentname ) # only do something if a component could be found
485 $infoline = "Updated Environment table:\n";
486 push(@installer::globals
::logfileinfo
, $infoline);
487 $infoline = "Old line: ${$environmentfile}[$i]\n";
488 push(@installer::globals
::logfileinfo
, $infoline);
490 ${$environmentfile}[$i] =~ s/$modulegid/$componentname/;
492 $infoline = "New line: ${$environmentfile}[$i]\n";
493 push(@installer::globals
::logfileinfo
, $infoline);
501 installer
::files
::save_file
($environmentfilename ,$environmentfile);
502 $infoline = "Updated idt file: $environmentfilename\n";
503 push(@installer::globals
::logfileinfo
, $infoline);