Msi.pm (60b96b8d) Msi.pm (677600b0)
1#**************************************************************
2#
3# Licensed to the Apache Software Foundation (ASF) under one
4# or more contributor license agreements. See the NOTICE file
5# distributed with this work for additional information
6# regarding copyright ownership. The ASF licenses this file
7# to you under the Apache License, Version 2.0 (the
8# "License"); you may not use this file except in compliance

--- 62 unchanged lines hidden (view full) ---

71
72 Create a new object of the Msi class. The values of $version, $language, and $product_name define
73 where to look for the msi file.
74
75 If construction fails then IsValid() will return false.
76
77=cut
78
1#**************************************************************
2#
3# Licensed to the Apache Software Foundation (ASF) under one
4# or more contributor license agreements. See the NOTICE file
5# distributed with this work for additional information
6# regarding copyright ownership. The ASF licenses this file
7# to you under the Apache License, Version 2.0 (the
8# "License"); you may not use this file except in compliance

--- 62 unchanged lines hidden (view full) ---

71
72 Create a new object of the Msi class. The values of $version, $language, and $product_name define
73 where to look for the msi file.
74
75 If construction fails then IsValid() will return false.
76
77=cut
78
79sub new ($$$$$$)
79sub new ($$;$$$$)
80{
81 my ($class, $filename, $version, $is_current_version, $language, $product_name) = @_;
82
83 if ( ! -f $filename)
84 {
85 installer::logger::PrintError("can not find the .msi file for version %s and language %s at '%s'\n",
86 $version,
87 $language,

--- 9 unchanged lines hidden (view full) ---

97 'language' => $language,
98 'package_format' => "msi",
99 'product_name' => $product_name,
100 'tmpdir' => File::Temp->newdir(CLEANUP => 1),
101 'is_valid' => -f $filename
102 };
103 bless($self, $class);
104
80{
81 my ($class, $filename, $version, $is_current_version, $language, $product_name) = @_;
82
83 if ( ! -f $filename)
84 {
85 installer::logger::PrintError("can not find the .msi file for version %s and language %s at '%s'\n",
86 $version,
87 $language,

--- 9 unchanged lines hidden (view full) ---

97 'language' => $language,
98 'package_format' => "msi",
99 'product_name' => $product_name,
100 'tmpdir' => File::Temp->newdir(CLEANUP => 1),
101 'is_valid' => -f $filename
102 };
103 bless($self, $class);
104
105 # Fill in some missing values from the 'Properties' table.
106 if ( ! (defined $version && defined $language && defined $product_name))
107 {
108 my $property_table = $self->GetTable("Property");
109
110 $self->{'version'} = $property_table->GetValue("Property", "DEFINEDVERSION", "Value")
111 unless defined $self->{'version'};
112 $self->{'product_name'} = $property_table->GetValue("Property", "DEFINEDPRODUCT", "Value")
113 unless defined $self->{'product_name'};
114
115 my $language = $property_table->GetValue("Property", "ProductLanguage", "Value");
116 # TODO: Convert numerical language id to language name.
117 $self->{'language'} = $language
118 unless defined $self->{'language'};
119 }
120
105 return $self;
106}
107
108
109
110
111sub IsValid ($)
112{

--- 63 unchanged lines hidden (view full) ---

176 # Extract table from database to text file on disk.
177 my $truncated_table_name = length($table_name)>8 ? substr($table_name,0,8) : $table_name;
178 my $command = join(" ",
179 "msidb.exe",
180 "-d", installer::patch::Tools::ToEscapedWindowsPath($self->{'filename'}),
181 "-f", installer::patch::Tools::ToEscapedWindowsPath($self->{'tmpdir'}),
182 "-e", $table_name);
183 my $result = qx($command);
121 return $self;
122}
123
124
125
126
127sub IsValid ($)
128{

--- 63 unchanged lines hidden (view full) ---

192 # Extract table from database to text file on disk.
193 my $truncated_table_name = length($table_name)>8 ? substr($table_name,0,8) : $table_name;
194 my $command = join(" ",
195 "msidb.exe",
196 "-d", installer::patch::Tools::ToEscapedWindowsPath($self->{'filename'}),
197 "-f", installer::patch::Tools::ToEscapedWindowsPath($self->{'tmpdir'}),
198 "-e", $table_name);
199 my $result = qx($command);
184 print $result;
185 }
186
187 # Read table into memory.
188 $table = new installer::patch::MsiTable($table_filename, $table_name);
189 $self->{'tables'}->{$table_name} = $table;
190 }
191
192 return $table;

--- 125 unchanged lines hidden (view full) ---

318 else
319 {
320 my ($long,$short) = installer::patch::Msi::SplitLongShortName($name);
321 return ($long,$short,$long,$short);
322 }
323}
324
325
200 }
201
202 # Read table into memory.
203 $table = new installer::patch::MsiTable($table_filename, $table_name);
204 $self->{'tables'}->{$table_name} = $table;
205 }
206
207 return $table;

--- 125 unchanged lines hidden (view full) ---

333 else
334 {
335 my ($long,$short) = installer::patch::Msi::SplitLongShortName($name);
336 return ($long,$short,$long,$short);
337 }
338}
339
340
341
342
343sub SetupFullNames ($$);
344sub SetupFullNames ($$)
345{
346 my ($item, $directory_map) = @_;
347
348 # Don't process any item twice.
349 return if defined $item->{'full_source_name'};
350
351 my $parent = $item->{'parent'};
352 if (defined $parent)
353 {
354 # Process the parent first.
355 if ( ! defined $parent->{'full_source_long_name'})
356 {
357 SetupFullNames($parent, $directory_map);
358 }
359
360 # Prepend the full names of the parent to our names.
361 $item->{'full_source_long_name'}
362 = $parent->{'full_source_long_name'} . "/" . $item->{'source_long_name'};
363 $item->{'full_source_short_name'}
364 = $parent->{'full_source_short_name'} . "/" . $item->{'source_short_name'};
365 $item->{'full_target_long_name'}
366 = $parent->{'full_target_long_name'} . "/" . $item->{'target_long_name'};
367 $item->{'full_target_short_name'}
368 = $parent->{'full_target_short_name'} . "/" . $item->{'target_short_name'};
369 }
370 else
371 {
372 # Directory has no parent => full names are the same as the name.
373 $item->{'full_source_long_name'} = $item->{'source_long_name'};
374 $item->{'full_source_short_name'} = $item->{'source_short_name'};
375 $item->{'full_target_long_name'} = $item->{'target_long_name'};
376 $item->{'full_target_short_name'} = $item->{'target_short_name'};
377 }
378}
379
380
381
382
326=head2 GetDirectoryMap($self)
327
328 Return a map that maps directory unique names (column 'Directory' in table 'Directory')
329 to hashes that contains short and long source and target names.
330
331=cut
332
333sub GetDirectoryMap ($)
334{
335 my ($self) = @_;
336
337 if (defined $self->{'DirectoryMap'})
338 {
339 return $self->{'DirectoryMap'};
340 }
341
383=head2 GetDirectoryMap($self)
384
385 Return a map that maps directory unique names (column 'Directory' in table 'Directory')
386 to hashes that contains short and long source and target names.
387
388=cut
389
390sub GetDirectoryMap ($)
391{
392 my ($self) = @_;
393
394 if (defined $self->{'DirectoryMap'})
395 {
396 return $self->{'DirectoryMap'};
397 }
398
399 # Initialize the directory map.
342 my $directory_table = $self->GetTable("Directory");
400 my $directory_table = $self->GetTable("Directory");
343 my %dir_map = ();
401 my $directory_map = ();
344 foreach my $row (@{$directory_table->GetAllRows()})
345 {
346 my ($target_long_name, $target_short_name, $source_long_name, $source_short_name)
347 = installer::patch::Msi::SplitTargetSourceLongShortName($row->GetValue("DefaultDir"));
348 my $unique_name = $row->GetValue("Directory");
402 foreach my $row (@{$directory_table->GetAllRows()})
403 {
404 my ($target_long_name, $target_short_name, $source_long_name, $source_short_name)
405 = installer::patch::Msi::SplitTargetSourceLongShortName($row->GetValue("DefaultDir"));
406 my $unique_name = $row->GetValue("Directory");
349 $dir_map{$unique_name} =
407 $directory_map->{$unique_name} =
350 {
351 'unique_name' => $unique_name,
408 {
409 'unique_name' => $unique_name,
352 'parent' => $row->GetValue("Directory_Parent"),
410 'parent_name' => $row->GetValue("Directory_Parent"),
353 'default_dir' => $row->GetValue("DefaultDir"),
354 'source_long_name' => $source_long_name,
355 'source_short_name' => $source_short_name,
356 'target_long_name' => $target_long_name,
357 'target_short_name' => $target_short_name
358 };
359 }
360
411 'default_dir' => $row->GetValue("DefaultDir"),
412 'source_long_name' => $source_long_name,
413 'source_short_name' => $source_short_name,
414 'target_long_name' => $target_long_name,
415 'target_short_name' => $target_short_name
416 };
417 }
418
361 # Set up full names for all directories.
362 my @todo = map {$_} (keys %dir_map);
363 while (scalar @todo > 0)
419 # Add references to parent directories.
420 foreach my $item (values %$directory_map)
364 {
421 {
365 my $key = shift @todo;
366 my $item = $dir_map{$key};
367 next if defined $item->{'full_source_name'};
422 $item->{'parent'} = $directory_map->{$item->{'parent_name'}};
423 }
368
424
369 if ($item->{'parent'} eq "")
370 {
371 # Directory has no parent => full names are the same as the name.
372 $item->{'full_source_long_name'} = $item->{'source_long_name'};
373 $item->{'full_source_short_name'} = $item->{'source_short_name'};
374 $item->{'full_target_long_name'} = $item->{'target_long_name'};
375 $item->{'full_target_short_name'} = $item->{'target_short_name'};
376 }
377 else
378 {
379 my $parent = $dir_map{$item->{'parent'}};
380 if ( defined $parent->{'full_source_long_name'})
381 {
382 # Parent aleady has full names => we can create the full name of the current item.
383 $item->{'full_source_long_name'}
384 = $parent->{'full_source_long_name'} . "/" . $item->{'source_long_name'};
385 $item->{'full_source_short_name'}
386 = $parent->{'full_source_short_name'} . "/" . $item->{'source_short_name'};
387 $item->{'full_target_long_name'}
388 = $parent->{'full_target_long_name'} . "/" . $item->{'target_long_name'};
389 $item->{'full_target_short_name'}
390 = $parent->{'full_target_short_name'} . "/" . $item->{'target_short_name'};
391 }
392 else
393 {
394 # Parent has to be processed before the current item can be processed.
395 # Push both to the head of the list.
396 unshift @todo, $key;
397 unshift @todo, $item->{'parent'};
398 }
399 }
425 # Set up full names for all directories.
426 foreach my $item (values %$directory_map)
427 {
428 SetupFullNames($item, $directory_map);
400 }
401
429 }
430
402 # Postprocess the path names for cleanup.
403 foreach my $item (values %dir_map)
431 # Cleanup the names.
432 foreach my $item (values %$directory_map)
404 {
405 foreach my $id (
406 'full_source_long_name',
407 'full_source_short_name',
408 'full_target_long_name',
409 'full_target_short_name')
410 {
411 $item->{$id} =~ s/\/(\.\/)+/\//g;
412 $item->{$id} =~ s/^SourceDir\///;
413 $item->{$id} =~ s/^\.$//;
414 }
415 }
416
433 {
434 foreach my $id (
435 'full_source_long_name',
436 'full_source_short_name',
437 'full_target_long_name',
438 'full_target_short_name')
439 {
440 $item->{$id} =~ s/\/(\.\/)+/\//g;
441 $item->{$id} =~ s/^SourceDir\///;
442 $item->{$id} =~ s/^\.$//;
443 }
444 }
445
417 $self->{'DirectoryMap'} = \%dir_map;
446 $self->{'DirectoryMap'} = $directory_map;
418 return $self->{'DirectoryMap'};
419}
420
421
422
423
424=head2 GetFileMap ($)
425

--- 24 unchanged lines hidden (view full) ---

450 map
451 {$_->GetValue('Component') => $_->GetValue('Directory_')}
452 @{$component_table->GetAllRows()};
453
454 # Finally, create the map from files to directories.
455 my $file_map = {};
456 my $file_component_index = $file_table->GetColumnIndex("Component_");
457 my $file_file_index = $file_table->GetColumnIndex("File");
447 return $self->{'DirectoryMap'};
448}
449
450
451
452
453=head2 GetFileMap ($)
454

--- 24 unchanged lines hidden (view full) ---

479 map
480 {$_->GetValue('Component') => $_->GetValue('Directory_')}
481 @{$component_table->GetAllRows()};
482
483 # Finally, create the map from files to directories.
484 my $file_map = {};
485 my $file_component_index = $file_table->GetColumnIndex("Component_");
486 my $file_file_index = $file_table->GetColumnIndex("File");
487 my $file_filename_index = $file_table->GetColumnIndex("FileName");
458 foreach my $file_row (@{$file_table->GetAllRows()})
459 {
460 my $component_name = $file_row->GetValue($file_component_index);
461 my $directory_name = $component_to_directory_map{$component_name};
462 my $unique_name = $file_row->GetValue($file_file_index);
488 foreach my $file_row (@{$file_table->GetAllRows()})
489 {
490 my $component_name = $file_row->GetValue($file_component_index);
491 my $directory_name = $component_to_directory_map{$component_name};
492 my $unique_name = $file_row->GetValue($file_file_index);
493 my $file_name = $file_row->GetValue($file_filename_index);
494 my ($long_name, $short_name) = SplitLongShortName($file_name);
463 $file_map->{$unique_name} = {
464 'directory' => $dir_map->{$directory_name},
495 $file_map->{$unique_name} = {
496 'directory' => $dir_map->{$directory_name},
465 'component_name' => $component_name
497 'component_name' => $component_name,
498 'file_name' => $file_name,
499 'long_name' => $long_name,
500 'short_name' => $short_name
466 };
467 }
468
469 $self->{'FileMap'} = $file_map;
470 return $file_map;
471}
472
473
4741;
501 };
502 }
503
504 $self->{'FileMap'} = $file_map;
505 return $file_map;
506}
507
508
5091;