xref: /trunk/main/solenv/bin/modules/installer/windows/component.pm (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1#*************************************************************************
2#
3# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4#
5# Copyright 2000, 2010 Oracle and/or its affiliates.
6#
7# OpenOffice.org - a multi-platform office productivity suite
8#
9# This file is part of OpenOffice.org.
10#
11# OpenOffice.org is free software: you can redistribute it and/or modify
12# it under the terms of the GNU Lesser General Public License version 3
13# only, as published by the Free Software Foundation.
14#
15# OpenOffice.org is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18# GNU Lesser General Public License version 3 for more details
19# (a copy is included in the LICENSE file that accompanied this code).
20#
21# You should have received a copy of the GNU Lesser General Public License
22# version 3 along with OpenOffice.org.  If not, see
23# <http://www.openoffice.org/license.html>
24# for a copy of the LGPLv3 License.
25#
26#*************************************************************************
27
28package installer::windows::component;
29
30use installer::converter;
31use installer::existence;
32use installer::exiter;
33use installer::files;
34use installer::globals;
35use installer::windows::idtglobal;
36use installer::windows::language;
37
38##############################################################
39# Returning a globally unique ID (GUID) for a component
40# If the component is new, a unique guid has to be created.
41# If the component already exists, the guid has to be
42# taken from a list component <-> guid
43# Sample for a guid: {B68FD953-3CEF-4489-8269-8726848056E8}
44##############################################################
45
46sub get_component_guid
47{
48    my ( $componentname, $componentidhashref ) = @_;
49
50    # At this time only a template
51    my $returnvalue = "\{COMPONENTGUID\}";
52
53    if (( $installer::globals::updatedatabase ) && ( exists($componentidhashref->{$componentname}) ))
54    {
55        $returnvalue = $componentidhashref->{$componentname};
56    }
57
58    # Returning a ComponentID, that is assigned in scp project
59    if ( exists($installer::globals::componentid{$componentname}) )
60    {
61        $returnvalue = "\{" . $installer::globals::componentid{$componentname} . "\}";
62    }
63
64    return $returnvalue;
65}
66
67##############################################################
68# Returning the directory for a file component.
69##############################################################
70
71sub get_file_component_directory
72{
73    my ($componentname, $filesref, $dirref) = @_;
74
75    my ($onefile, $component, $onedir, $hostname, $uniquedir);
76    my $found = 0;
77
78    for ( my $i = 0; $i <= $#{$filesref}; $i++ )
79    {
80        $onefile =  ${$filesref}[$i];
81        $component = $onefile->{'componentname'};
82
83        if ( $component eq $componentname )
84        {
85            $found = 1;
86            last;
87        }
88    }
89
90    if (!($found))
91    {
92        # This component can be ignored, if it exists in a version with extension "_pff" (this was renamed in file::get_sequence_for_file() )
93        my $ignore_this_component = 0;
94        my $origcomponentname = $componentname;
95        my $componentname = $componentname . "_pff";
96
97        for ( my $j = 0; $j <= $#{$filesref}; $j++ )
98        {
99            $onefile =  ${$filesref}[$j];
100            $component = $onefile->{'componentname'};
101
102            if ( $component eq $componentname )
103            {
104                $ignore_this_component = 1;
105                last;
106            }
107        }
108
109        if ( $ignore_this_component ) { return "IGNORE_COMP"; }
110        else { installer::exiter::exit_program("ERROR: Did not find component \"$origcomponentname\" in file collection", "get_file_component_directory"); }
111    }
112
113    my $localstyles = "";
114
115    if ( $onefile->{'Styles'} ) { $localstyles = $onefile->{'Styles'}; }
116
117    if ( $localstyles =~ /\bFONT\b/ )   # special handling for font files
118    {
119        return $installer::globals::fontsfolder;
120    }
121
122    my $destdir = "";
123
124    if ( $onefile->{'Dir'} ) { $destdir = $onefile->{'Dir'}; }
125
126    if ( $destdir =~ /\bPREDEFINED_OSSHELLNEWDIR\b/ )   # special handling for shellnew files
127    {
128        return $installer::globals::templatefolder;
129    }
130
131    my $destination = $onefile->{'destination'};
132
133    installer::pathanalyzer::get_path_from_fullqualifiedname(\$destination);
134
135    $destination =~ s/\Q$installer::globals::separator\E\s*$//;
136
137    # This path has to be defined in the directory collection at "HostName"
138
139    if ($destination eq "")     # files in the installation root
140    {
141        $uniquedir = "INSTALLLOCATION";
142    }
143    else
144    {
145        $found = 0;
146
147        for ( my $i = 0; $i <= $#{$dirref}; $i++ )
148        {
149            $onedir =   ${$dirref}[$i];
150            $hostname = $onedir->{'HostName'};
151
152            if ( $hostname eq $destination )
153            {
154                $found = 1;
155                last;
156            }
157        }
158
159        if (!($found))
160        {
161            installer::exiter::exit_program("ERROR: Did not find destination $destination in directory collection", "get_file_component_directory");
162        }
163
164        $uniquedir = $onedir->{'uniquename'};
165
166        if ( $uniquedir eq $installer::globals::officeinstalldirectory )
167        {
168            $uniquedir = "INSTALLLOCATION";
169        }
170    }
171
172    $onefile->{'uniquedirname'} = $uniquedir;       # saving it in the file collection
173
174    return $uniquedir
175}
176
177##############################################################
178# Returning the directory for a registry component.
179# This cannot be a useful value
180##############################################################
181
182sub get_registry_component_directory
183{
184    my $componentdir = "INSTALLLOCATION";
185
186    return $componentdir;
187}
188
189##############################################################
190# Returning the attributes for a file component.
191# Always 8 in this first try?
192##############################################################
193
194sub get_file_component_attributes
195{
196    my ($componentname, $filesref, $allvariables) = @_;
197
198    my $attributes;
199
200    $attributes = 2;
201
202    # special handling for font files
203
204    my $onefile;
205    my $found = 0;
206
207    for ( my $i = 0; $i <= $#{$filesref}; $i++ )
208    {
209        $onefile =  ${$filesref}[$i];
210        my $component = $onefile->{'componentname'};
211
212        if ( $component eq $componentname )
213        {
214            $found = 1;
215            last;
216        }
217    }
218
219    if (!($found))
220    {
221        installer::exiter::exit_program("ERROR: Did not find component in file collection", "get_file_component_attributes");
222    }
223
224    my $localstyles = "";
225
226    if ( $onefile->{'Styles'} ) { $localstyles = $onefile->{'Styles'}; }
227
228    if ( $localstyles =~ /\bFONT\b/ )
229    {
230        $attributes = 16;   # font files will not be deinstalled
231    }
232
233    if ( $localstyles =~ /\bASSEMBLY\b/ )
234    {
235        $attributes = 0;    # Assembly files cannot run from source
236    }
237
238    if (( $onefile->{'Dir'} =~ /\bPREDEFINED_OSSHELLNEWDIR\b/ ) || ( $onefile->{'needs_user_registry_key'} ))
239    {
240        $attributes = 4;    # Files in shellnew dir and in non advertised startmenu entries must have user registry key as KeyPath
241    }
242
243    # Adding 256, if this is a 64 bit installation set.
244    if (( $allvariables->{'64BITPRODUCT'} ) && ( $allvariables->{'64BITPRODUCT'} == 1 )) { $attributes = $attributes + 256; }
245
246    return $attributes
247}
248
249##############################################################
250# Returning the attributes for a registry component.
251# Always 4, indicating, the keypath is a defined in
252# table registry
253##############################################################
254
255sub get_registry_component_attributes
256{
257    my ($componentname, $allvariables) = @_;
258
259    my $attributes;
260
261    $attributes = 4;
262
263    # Adding 256, if this is a 64 bit installation set.
264    if (( $allvariables->{'64BITPRODUCT'} ) && ( $allvariables->{'64BITPRODUCT'} == 1 )) { $attributes = $attributes + 256; }
265
266    if ( exists($installer::globals::dontdeletecomponents{$componentname}) ) { $attributes = $attributes + 16; }
267
268    return $attributes
269}
270
271##############################################################
272# Returning the conditions for a component.
273# This is important for language dependent components
274# in multilingual installation sets.
275##############################################################
276
277sub get_file_component_condition
278{
279    my ($componentname, $filesref) = @_;
280
281    my $condition = "";
282
283    if (exists($installer::globals::componentcondition{$componentname}))
284    {
285        $condition = $installer::globals::componentcondition{$componentname};
286    }
287
288    # there can be also tree conditions for multilayer products
289    if (exists($installer::globals::treeconditions{$componentname}))
290    {
291        if ( $condition eq "" )
292        {
293            $condition = $installer::globals::treeconditions{$componentname};
294        }
295        else
296        {
297            $condition = "($condition) And ($installer::globals::treeconditions{$componentname})";
298        }
299    }
300
301    return $condition
302}
303
304##############################################################
305# Returning the conditions for a registry component.
306##############################################################
307
308sub get_component_condition
309{
310    my ($componentname) = @_;
311
312    my $condition;
313
314    $condition = "";    # Always ?
315
316    if (exists($installer::globals::componentcondition{$componentname}))
317    {
318        $condition = $installer::globals::componentcondition{$componentname};
319    }
320
321    return $condition
322}
323
324####################################################################
325# Returning the keypath for a component.
326# This will be the name of the first file/registry, found in the
327# collection $itemsref
328# Attention: This has to be the unique (file)name, not the
329# real filename!
330####################################################################
331
332sub get_component_keypath
333{
334    my ($componentname, $itemsref, $componentidkeypathhashref) = @_;
335
336    my $oneitem;
337    my $found = 0;
338    my $infoline = "";
339
340    for ( my $i = 0; $i <= $#{$itemsref}; $i++ )
341    {
342        $oneitem =  ${$itemsref}[$i];
343        my $component = $oneitem->{'componentname'};
344
345        if ( $component eq $componentname )
346        {
347            $found = 1;
348            last;
349        }
350    }
351
352    if (!($found))
353    {
354        installer::exiter::exit_program("ERROR: Did not find component in file/registry collection, function get_component_keypath", "get_component_keypath");
355    }
356
357    my $keypath = $oneitem->{'uniquename'}; # "uniquename", not "Name"
358
359    # Special handling for updates from existing databases, because KeyPath must not change
360    if (( $installer::globals::updatedatabase ) && ( exists($componentidkeypathhashref->{$componentname}) ))
361    {
362        $keypath = $componentidkeypathhashref->{$componentname};
363        # -> check, if this is a valid key path?!
364        if ( $keypath ne $oneitem->{'uniquename'} )
365        {
366            # Warning: This keypath was changed because of info from old database
367            $infoline = "WARNING: The KeyPath for component \"$componentname\" was changed from \"$oneitem->{'uniquename'}\" to \"$keypath\" because of information from update database";
368            push(@installer::globals::logfileinfo, $infoline);
369        }
370    }
371
372    # Special handling for components in PREDEFINED_OSSHELLNEWDIR. These components
373    # need as KeyPath a RegistryItem in HKCU
374    if ( $oneitem->{'userregkeypath'} ) { $keypath = $oneitem->{'userregkeypath'}; }
375
376    # saving it in the file and registry collection
377    $oneitem->{'keypath'} = $keypath;
378
379    return $keypath
380}
381
382###################################################################
383# Creating the file Componen.idt dynamically
384# Content:
385# Component ComponentId Directory_ Attributes Condition KeyPath
386###################################################################
387
388sub create_component_table
389{
390    my ($filesref, $registryref, $dirref, $allfilecomponentsref, $allregistrycomponents, $basedir, $componentidhashref, $componentidkeypathhashref, $allvariables) = @_;
391
392    my @componenttable = ();
393
394    my ($oneline, $infoline);
395
396    installer::windows::idtglobal::write_idt_header(\@componenttable, "component");
397
398    # collect_layer_conditions();
399
400
401    # File components
402
403    for ( my $i = 0; $i <= $#{$allfilecomponentsref}; $i++ )
404    {
405        my %onecomponent = ();
406
407        $onecomponent{'name'} = ${$allfilecomponentsref}[$i];
408        $onecomponent{'guid'} = get_component_guid($onecomponent{'name'}, $componentidhashref);
409        $onecomponent{'directory'} = get_file_component_directory($onecomponent{'name'}, $filesref, $dirref);
410        if ( $onecomponent{'directory'} eq "IGNORE_COMP" ) { next; }
411        $onecomponent{'attributes'} = get_file_component_attributes($onecomponent{'name'}, $filesref, $allvariables);
412        $onecomponent{'condition'} = get_file_component_condition($onecomponent{'name'}, $filesref);
413        $onecomponent{'keypath'} = get_component_keypath($onecomponent{'name'}, $filesref, $componentidkeypathhashref);
414
415        $oneline = $onecomponent{'name'} . "\t" . $onecomponent{'guid'} . "\t" . $onecomponent{'directory'} . "\t"
416                . $onecomponent{'attributes'} . "\t" . $onecomponent{'condition'} . "\t" . $onecomponent{'keypath'} . "\n";
417
418        push(@componenttable, $oneline);
419    }
420
421    # Registry components
422
423    for ( my $i = 0; $i <= $#{$allregistrycomponents}; $i++ )
424    {
425        my %onecomponent = ();
426
427        $onecomponent{'name'} = ${$allregistrycomponents}[$i];
428        $onecomponent{'guid'} = get_component_guid($onecomponent{'name'}, $componentidhashref);
429        $onecomponent{'directory'} = get_registry_component_directory();
430        $onecomponent{'attributes'} = get_registry_component_attributes($onecomponent{'name'}, $allvariables);
431        $onecomponent{'condition'} = get_component_condition($onecomponent{'name'});
432        $onecomponent{'keypath'} = get_component_keypath($onecomponent{'name'}, $registryref, $componentidkeypathhashref);
433
434        $oneline = $onecomponent{'name'} . "\t" . $onecomponent{'guid'} . "\t" . $onecomponent{'directory'} . "\t"
435                . $onecomponent{'attributes'} . "\t" . $onecomponent{'condition'} . "\t" . $onecomponent{'keypath'} . "\n";
436
437        push(@componenttable, $oneline);
438    }
439
440    # Saving the file
441
442    my $componenttablename = $basedir . $installer::globals::separator . "Componen.idt";
443    installer::files::save_file($componenttablename ,\@componenttable);
444    $infoline = "Created idt file: $componenttablename\n";
445    push(@installer::globals::logfileinfo, $infoline);
446}
447
448####################################################################################
449# Returning a component for a scp module gid.
450# Pairs are saved in the files collector.
451####################################################################################
452
453sub get_component_name_from_modulegid
454{
455    my ($modulegid, $filesref) = @_;
456
457    my $componentname = "";
458
459    for ( my $i = 0; $i <= $#{$filesref}; $i++ )
460    {
461        my $onefile = ${$filesref}[$i];
462
463        if ( $onefile->{'modules'} )
464        {
465            my $filemodules = $onefile->{'modules'};
466            my $filemodulesarrayref = installer::converter::convert_stringlist_into_array_without_newline(\$filemodules, ",");
467
468            if (installer::existence::exists_in_array($modulegid, $filemodulesarrayref))
469            {
470                $componentname = $onefile->{'componentname'};
471                last;
472            }
473        }
474    }
475
476    return $componentname;
477}
478
479####################################################################################
480# Updating the file Environm.idt dynamically
481# Content:
482# Environment Name Value Component_
483####################################################################################
484
485sub set_component_in_environment_table
486{
487    my ($basedir, $filesref) = @_;
488
489    my $infoline = "";
490
491    my $environmentfilename = $basedir . $installer::globals::separator . "Environm.idt";
492
493    if ( -f $environmentfilename )  # only do something, if file exists
494    {
495        my $environmentfile = installer::files::read_file($environmentfilename);
496
497        for ( my $i = 3; $i <= $#{$environmentfile}; $i++ ) # starting in line 4 of Environm.idt
498        {
499            if ( ${$environmentfile}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ )
500            {
501                my $modulegid = $4; # in Environment table a scp module gid can be used as component replacement
502
503                my $componentname = get_component_name_from_modulegid($modulegid, $filesref);
504
505                if ( $componentname )   # only do something if a component could be found
506                {
507                    $infoline = "Updated Environment table:\n";
508                    push(@installer::globals::logfileinfo, $infoline);
509                    $infoline = "Old line: ${$environmentfile}[$i]\n";
510                    push(@installer::globals::logfileinfo, $infoline);
511
512                    ${$environmentfile}[$i] =~ s/$modulegid/$componentname/;
513
514                    $infoline = "New line: ${$environmentfile}[$i]\n";
515                    push(@installer::globals::logfileinfo, $infoline);
516
517                }
518            }
519        }
520
521        # Saving the file
522
523        installer::files::save_file($environmentfilename ,$environmentfile);
524        $infoline = "Updated idt file: $environmentfilename\n";
525        push(@installer::globals::logfileinfo, $infoline);
526
527    }
528}
529
5301;