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::directory;
29
30use installer::exiter;
31use installer::files;
32use installer::globals;
33use installer::pathanalyzer;
34use installer::windows::idtglobal;
35
36##############################################################
37# Collecting all directory trees in global hash
38##############################################################
39
40sub collectdirectorytrees
41{
42	my ( $directoryref ) = @_;
43
44	for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
45	{
46		my $onedir = ${$directoryref}[$i];
47		my $styles = "";
48		if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; }
49
50		if ( $styles ne "" )
51		{
52			foreach my $treestyle ( keys %installer::globals::treestyles )
53			{
54				if ( $styles =~ /\b$treestyle\b/ )
55				{
56					my $hostname = $onedir->{'HostName'};
57					# -> hostname is the key, the style the value!
58					$installer::globals::hostnametreestyles{$hostname} = $treestyle;
59				}
60			}
61		}
62	}
63}
64
65##############################################################
66# Overwriting global programfilesfolder, if required
67##############################################################
68
69sub overwrite_programfilesfolder
70{
71	my ( $allvariables ) = @_;
72
73	if ( $allvariables->{'PROGRAMFILESFOLDERNAME'} )
74	{
75		$installer::globals::programfilesfolder = $allvariables->{'PROGRAMFILESFOLDERNAME'};
76	}
77}
78
79##############################################################
80# Maximum length of directory name is 72.
81# Taking care of underlines, which are the separator.
82##############################################################
83
84sub make_short_dir_version
85{
86	my ($longstring, $length, $displayname) = @_;
87
88	my $shortstring = "";
89	my $infoline = "";
90	my $savestring = $longstring;
91
92	# Splitting the string at each "underline" and allowing only $length characters per directory name.
93	# Checking also uniqueness and length.
94
95	my $stringarray = installer::converter::convert_stringlist_into_array_without_newline(\$longstring, "_");
96
97	foreach my $onestring ( @{$stringarray} )
98	{
99		my $partstring = "";
100
101		if ( $onestring =~ /\-/ )
102		{
103			my $localstringarray = installer::converter::convert_stringlist_into_array_without_newline(\$onestring, "-");
104			foreach my $onelocalstring ( @{$localstringarray} )
105			{
106				if ( length($onelocalstring) > $length ) { $onelocalstring = substr($onelocalstring, 0, $length); }
107				$partstring = $partstring . "-" . $onelocalstring;
108			}
109			$partstring =~ s/^\s*\-//;
110		}
111		else
112		{
113			if ( length($onestring) > $length ) { $partstring = substr($onestring, 0, $length); }
114			else { $partstring = $onestring; }
115		}
116
117		$shortstring = $shortstring . "_" . $partstring;
118	}
119
120	$shortstring =~ s/^\s*\_//;
121
122	if ( length($shortstring) > 72 )
123	{
124		my $shortlength = length($shortstring);
125		$infoline = "WARNING: Failed to create unique directory name with less than 72 characters: \"$displayname\" ($shortstring ($shortlength)).\n";
126		push(@installer::globals::logfileinfo, $infoline);
127	}
128
129	return $shortstring;
130}
131
132##############################################################
133# Adding unique directory names to the directory collection
134##############################################################
135
136sub create_unique_directorynames
137{
138	my ($directoryref, $allvariables) = @_;
139
140	$installer::globals::officeinstalldirectoryset = 0;
141
142	my %conversionhash = ();
143	my $infoline = "";
144	my $errorcount = 0;
145
146	for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
147	{
148		my $onedir = ${$directoryref}[$i];
149		my $hostname = $onedir->{'HostName'};
150
151		my $uniquename = $hostname;
152		my $styles = "";
153		if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; }
154		# get_path_from_fullqualifiedname(\$uniqueparentname);
155		# making /registry/schema/org/openoffice/VCL.xcs to VCL.xcs
156
157		$uniquename =~ s/^\s*//g;				# removing beginning white spaces
158		$uniquename =~ s/\s*$//g;				# removing ending white spaces
159		$uniquename =~ s/\s//g;					# removing white spaces
160		$uniquename =~ s/\_//g;					# removing existing underlines
161		$uniquename =~ s/\.//g;					# removing dots in directoryname
162		$uniquename =~ s/\Q$installer::globals::separator\E/\_/g;	# replacing slash and backslash with underline
163		$uniquename =~ s/OpenOffice/OO/g;
164		$uniquename =~ s/_registry/_rgy/g;
165		$uniquename =~ s/_registration/_rgn/g;
166		$uniquename =~ s/_extension/_ext/g;
167		$uniquename =~ s/_frame/_frm/g;
168		$uniquename =~ s/_table/_tbl/g;
169		$uniquename =~ s/_chart/_crt/g;
170
171		my $startlength = 5;
172
173		if ( ! $allvariables->{'NOSHORTDIRECTORYNAMES'} )
174		{
175			# This process does not work for SDK, because of its long and similar pathes
176			$uniquename = make_short_dir_version($uniquename, $startlength, $hostname); # taking care of underlines!
177		}
178
179		if ( exists($installer::globals::alluniquedirectorynames{$uniquename}) )
180		{
181			# This is an error, that must stop the packaging process
182			$errorcount++;
183
184			$infoline = "$errorcount: Already existing unique directory: $uniquename\n";
185			push( @installer::globals::logfileinfo, $infoline);
186			$infoline = "$errorcount: First full directory: $conversionhash{$uniquename}\n";
187			push( @installer::globals::logfileinfo, $infoline);
188			$infoline = "$errorcount: Current full directory: $hostname\n";
189			push( @installer::globals::logfileinfo, $infoline);
190		}
191
192		$conversionhash{$uniquename} = $hostname;
193
194		$installer::globals::alluniquedirectorynames{$uniquename} = 1;
195
196		# Important: The unique parent is generated from the string $uniquename. Therefore counters
197		# like adding "_1" is not allowed to achive uniqueness, because this depends from other directories
198		# and does not deliver always the same result.
199
200		my $uniqueparentname = $uniquename;
201
202		if ( $uniqueparentname =~ /^\s*(.*)\_(.*?)\s*$/ )	# the underline is now the separator
203		{
204			$uniqueparentname = $1;
205		}
206		else
207		{
208			$uniqueparentname = $installer::globals::programfilesfolder;
209		}
210
211		if ( $styles =~ /\bPROGRAMFILESFOLDER\b/ ) { $uniqueparentname = $installer::globals::programfilesfolder; }
212		if ( $styles =~ /\bCOMMONFILESFOLDER\b/ ) { $uniqueparentname = $installer::globals::commonfilesfolder; }
213		if ( $styles =~ /\bCOMMONAPPDATAFOLDER\b/ ) { $uniqueparentname = $installer::globals::commonappdatafolder; }
214		if ( $styles =~ /\bLOCALAPPDATAFOLDER\b/ ) { $uniqueparentname = $installer::globals::localappdatafolder; }
215
216		if ( $styles =~ /\bSHAREPOINTPATH\b/ )
217		{
218			$uniqueparentname = "SHAREPOINTPATH";
219			$installer::globals::usesharepointpath = 1;
220		}
221
222		$uniquename =~ s/\-/\_/g;			# making "-" to "_"
223		$uniqueparentname =~ s/\-/\_/g;		# making "-" to "_"
224
225		$onedir->{'uniquename'} = $uniquename;
226		$onedir->{'uniqueparentname'} = $uniqueparentname;
227
228		# setting the installlocation directory
229		if ( $styles =~ /\bISINSTALLLOCATION\b/ )
230		{
231			if ( $installer::globals::installlocationdirectoryset ) { installer::exiter::exit_program("ERROR: Directory with flag ISINSTALLLOCATION alread set: \"$installer::globals::installlocationdirectory\".", "create_unique_directorynames"); }
232			$installer::globals::installlocationdirectory = $uniquename;
233			$installer::globals::installlocationdirectoryset = 1;
234			if ( $installer::globals::installlocationdirectory =~ /oracle_/i ) { $installer::globals::sundirexists = 1; }
235		}
236
237		# setting the sundirectory
238		if ( $styles =~ /\bSUNDIRECTORY\b/ )
239		{
240			if ( $installer::globals::vendordirectoryset ) { installer::exiter::exit_program("ERROR: Directory with flag SUNDIRECTORY alread set: \"$installer::globals::vendordirectory\".", "create_unique_directorynames"); }
241			$installer::globals::vendordirectory = $uniquename;
242			$installer::globals::vendordirectoryset = 1;
243		}
244	}
245
246	if ( $errorcount > 0 )
247	{
248		installer::exiter::exit_program("ERROR: Failed to create unique directory names.", "create_unique_directorynames");
249	}
250}
251
252#####################################################
253# Adding ":." to selected default directory names
254#####################################################
255
256sub check_sourcedir_addon
257{
258	my ( $onedir, $allvariableshashref ) = @_;
259
260	if (($installer::globals::addchildprojects) ||
261		($installer::globals::patch) ||
262		($installer::globals::languagepack) ||
263		($allvariableshashref->{'CHANGETARGETDIR'}))
264	{
265		my $sourcediraddon = "\:\.";
266		$onedir->{'defaultdir'} = $onedir->{'defaultdir'} . $sourcediraddon;
267	}
268
269}
270
271#####################################################
272# The directory with the style ISINSTALLLOCATION
273# will be replaced by INSTALLLOCATION
274#####################################################
275
276sub set_installlocation_directory
277{
278	my ( $directoryref, $allvariableshashref ) = @_;
279
280	if ( ! $installer::globals::installlocationdirectoryset ) { installer::exiter::exit_program("ERROR: Directory with flag ISINSTALLLOCATION not set!", "set_installlocation_directory"); }
281
282	for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
283	{
284		my $onedir = ${$directoryref}[$i];
285
286		if ( $onedir->{'uniquename'} eq $installer::globals::installlocationdirectory )
287		{
288			$onedir->{'uniquename'} = "INSTALLLOCATION";
289			check_sourcedir_addon($onedir, $allvariableshashref);
290		}
291
292		if ( $onedir->{'uniquename'} eq $installer::globals::vendordirectory )
293		{
294			check_sourcedir_addon($onedir, $allvariableshashref);
295		}
296
297		if ( $onedir->{'uniqueparentname'} eq $installer::globals::installlocationdirectory )
298		{
299			$onedir->{'uniqueparentname'} = "INSTALLLOCATION";
300		}
301	}
302}
303
304#####################################################
305# Getting the name of the top level directory. This
306# can have only one letter
307#####################################################
308
309sub get_last_directory_name
310{
311	my ($completepathref) = @_;
312
313	if ( $$completepathref =~ /^.*[\/\\](.+?)\s*$/ )
314	{
315		$$completepathref = $1;
316	}
317}
318
319#####################################################
320# Creating the defaultdir for the file Director.idt
321#####################################################
322
323sub create_defaultdir_directorynames
324{
325	my ($directoryref, $shortdirnamehashref) = @_;
326
327	my @shortnames = ();
328	if ( $installer::globals::updatedatabase ) { @shortnames = values(%{$shortdirnamehashref}); }
329	elsif ( $installer::globals::prepare_winpatch ) { @shortnames = values(%installer::globals::saved83dirmapping); }
330
331	for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
332	{
333		my $onedir = ${$directoryref}[$i];
334		my $hostname = $onedir->{'HostName'};
335
336		$hostname =~ s/\Q$installer::globals::separator\E\s*$//;
337		get_last_directory_name(\$hostname);
338		# installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$hostname);	# making program/classes to classes
339		my $uniquename = $onedir->{'uniquename'};
340		my $shortstring;
341		if (( $installer::globals::updatedatabase ) && ( exists($shortdirnamehashref->{$uniquename}) ))
342		{
343			$shortstring = $shortdirnamehashref->{$uniquename};
344		}
345		elsif (( $installer::globals::prepare_winpatch ) && ( exists($installer::globals::saved83dirmapping{$uniquename}) ))
346		{
347			$shortstring = $installer::globals::saved83dirmapping{$uniquename};
348		}
349		else
350		{
351			$shortstring = installer::windows::idtglobal::make_eight_three_conform($hostname, "dir", \@shortnames);
352		}
353
354		my $defaultdir;
355
356		if ( $shortstring eq $hostname )
357		{
358			$defaultdir = $hostname;
359		}
360		else
361		{
362			$defaultdir = $shortstring . "|" . $hostname;
363		}
364
365		$onedir->{'defaultdir'} = $defaultdir;
366
367		my $fontdir = "";
368		if ( $onedir->{'Dir'} ) { $fontdir = $onedir->{'Dir'}; }
369
370		my $fontdefaultdir = "";
371		if ( $onedir->{'defaultdir'} ) { $fontdefaultdir = $onedir->{'defaultdir'}; }
372
373		if (( $fontdir eq "PREDEFINED_OSSYSTEMFONTDIR" ) && ( $fontdefaultdir eq $installer::globals::fontsdirhostname ))
374		{
375			$installer::globals::fontsdirname = $onedir->{'defaultdir'};
376			$installer::globals::fontsdirparent = $onedir->{'uniqueparentname'};
377		}
378	}
379}
380
381###############################################
382# Fill content into the directory table
383###############################################
384
385sub create_directorytable_from_collection
386{
387	my ($directorytableref, $directoryref) = @_;
388
389	for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
390	{
391		my $onedir = ${$directoryref}[$i];
392		my $hostname = $onedir->{'HostName'};
393		my $dir = "";
394
395		if ( $onedir->{'Dir'} ) { $dir = $onedir->{'Dir'}; }
396
397		if (( $dir eq "PREDEFINED_PROGDIR" ) && ( $hostname eq "" )) { next; }	# removing files from root directory
398
399		my $oneline = $onedir->{'uniquename'} . "\t" . $onedir->{'uniqueparentname'} . "\t" . $onedir->{'defaultdir'} . "\n";
400
401		push(@{$directorytableref}, $oneline);
402	}
403}
404
405###############################################
406# Defining the root installation structure
407###############################################
408
409sub add_root_directories
410{
411	my ($directorytableref, $allvariableshashref) = @_;
412
413#	my $sourcediraddon = "";
414#	if (($installer::globals::addchildprojects) ||
415#		($installer::globals::patch) ||
416#		($installer::globals::languagepack) ||
417#		($allvariableshashref->{'CHANGETARGETDIR'}))
418#	{
419#		$sourcediraddon = "\:\.";
420#	}
421
422	my $oneline = "";
423
424	if (( ! $installer::globals::patch ) && ( ! $installer::globals::languagepack ) && ( ! $allvariableshashref->{'DONTUSESTARTMENUFOLDER'} ))
425	{
426		my $productname = $allvariableshashref->{'PRODUCTNAME'};
427		my $productversion = $allvariableshashref->{'PRODUCTVERSION'};
428		my $baseproductversion = $productversion;
429
430		if (( $installer::globals::prepare_winpatch ) && ( $allvariableshashref->{'BASEPRODUCTVERSION'} ))
431		{
432			$baseproductversion = $allvariableshashref->{'BASEPRODUCTVERSION'};  # for example "2.0" for OOo
433		}
434
435		my $realproductkey = $productname . " " . $productversion;
436		my $productkey = $productname . " " . $baseproductversion;
437
438		if (( $allvariableshashref->{'POSTVERSIONEXTENSION'} ) && ( ! $allvariableshashref->{'DONTUSEEXTENSIONINDEFAULTDIR'} ))
439		{
440			$productkey = $productkey . " " . $allvariableshashref->{'POSTVERSIONEXTENSION'};
441			$realproductkey = $realproductkey . " " . $allvariableshashref->{'POSTVERSIONEXTENSION'};
442		}
443		if ( $allvariableshashref->{'NOVERSIONINDIRNAME'} )
444		{
445			$productkey = $productname;
446			$realproductkey = $realproductname;
447		}
448		if ( $allvariableshashref->{'NOSPACEINDIRECTORYNAME'} )
449		{
450			$productkey =~ s/\ /\_/g;
451			$realproductkey =~ s/\ /\_/g;
452		}
453
454		my $shortproductkey = installer::windows::idtglobal::make_eight_three_conform($productkey, "dir");		# third parameter not used
455		$shortproductkey =~ s/\s/\_/g;									# changing empty space to underline
456
457		$oneline = "$installer::globals::officemenufolder\t$installer::globals::programmenufolder\t$shortproductkey|$realproductkey\n";
458		push(@{$directorytableref}, $oneline);
459	}
460
461	$oneline = "TARGETDIR\t\tSourceDir\n";
462	push(@{$directorytableref}, $oneline);
463
464	$oneline = "$installer::globals::programfilesfolder\tTARGETDIR\t.\n";
465	push(@{$directorytableref}, $oneline);
466
467	$oneline = "$installer::globals::programmenufolder\tTARGETDIR\t.\n";
468	push(@{$directorytableref}, $oneline);
469
470	$oneline = "$installer::globals::startupfolder\tTARGETDIR\t.\n";
471	push(@{$directorytableref}, $oneline);
472
473	$oneline = "$installer::globals::desktopfolder\tTARGETDIR\t.\n";
474	push(@{$directorytableref}, $oneline);
475
476	$oneline = "$installer::globals::startmenufolder\tTARGETDIR\t.\n";
477	push(@{$directorytableref}, $oneline);
478
479	$oneline = "$installer::globals::commonfilesfolder\tTARGETDIR\t.\n";
480	push(@{$directorytableref}, $oneline);
481
482	$oneline = "$installer::globals::commonappdatafolder\tTARGETDIR\t.\n";
483	push(@{$directorytableref}, $oneline);
484
485	$oneline = "$installer::globals::localappdatafolder\tTARGETDIR\t.\n";
486	push(@{$directorytableref}, $oneline);
487
488	if ( $installer::globals::usesharepointpath )
489	{
490		$oneline = "SHAREPOINTPATH\tTARGETDIR\t.\n";
491		push(@{$directorytableref}, $oneline);
492	}
493
494	$oneline = "$installer::globals::systemfolder\tTARGETDIR\t.\n";
495	push(@{$directorytableref}, $oneline);
496
497	my $localtemplatefoldername = $installer::globals::templatefoldername;
498	my $directorytableentry = $localtemplatefoldername;
499	my $shorttemplatefoldername = installer::windows::idtglobal::make_eight_three_conform($localtemplatefoldername, "dir");
500	if ( $shorttemplatefoldername ne $localtemplatefoldername ) { $directorytableentry = "$shorttemplatefoldername|$localtemplatefoldername"; }
501	$oneline = "$installer::globals::templatefolder\tTARGETDIR\t$directorytableentry\n";
502	push(@{$directorytableref}, $oneline);
503
504	if ( $installer::globals::fontsdirname )
505	{
506		$oneline = "$installer::globals::fontsfolder\t$installer::globals::fontsdirparent\t$installer::globals::fontsfoldername\:$installer::globals::fontsdirname\n";
507	}
508	else
509	{
510		$oneline = "$installer::globals::fontsfolder\tTARGETDIR\t$installer::globals::fontsfoldername\n";
511	}
512
513	push(@{$directorytableref}, $oneline);
514
515}
516
517###############################################
518# Creating the file Director.idt dynamically
519###############################################
520
521sub create_directory_table
522{
523	my ($directoryref, $basedir, $allvariableshashref, $shortdirnamehashref, $loggingdir) = @_;
524
525	# Structure of the directory table:
526	# Directory Directory_Parent DefaultDir
527	# Directory is a unique identifier
528	# Directory_Parent is the unique identifier of the parent
529	# DefaultDir is .:APPLIC~1|Application Data with
530	# Before ":" : [sourcedir]:[destdir] (not programmed yet)
531	# After ":" : 8+3 and not 8+3 the destination directory name
532
533	my @directorytable = ();
534	my $infoline;
535
536	overwrite_programfilesfolder($allvariableshashref);
537	if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforidt_local_1.log", $directoryref); }
538	create_unique_directorynames($directoryref, $allvariableshashref);
539	if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforidt_local_1a.log", $directoryref); }
540	create_defaultdir_directorynames($directoryref, $shortdirnamehashref);	# only destdir!
541	if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforidt_local_2.log", $directoryref); }
542	set_installlocation_directory($directoryref, $allvariableshashref);
543	if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforidt_local_3.log", $directoryref); }
544	installer::windows::idtglobal::write_idt_header(\@directorytable, "directory");
545	add_root_directories(\@directorytable, $allvariableshashref);
546	create_directorytable_from_collection(\@directorytable, $directoryref);
547
548	# Saving the file
549
550	my $directorytablename = $basedir . $installer::globals::separator . "Director.idt";
551	installer::files::save_file($directorytablename ,\@directorytable);
552	$infoline = "Created idt file: $directorytablename\n";
553	push(@installer::globals::logfileinfo, $infoline);
554
555}
556
5571;
558