1c9b362f6SAndre Fischer#************************************************************** 2c9b362f6SAndre Fischer# 3c9b362f6SAndre Fischer# Licensed to the Apache Software Foundation (ASF) under one 4c9b362f6SAndre Fischer# or more contributor license agreements. See the NOTICE file 5c9b362f6SAndre Fischer# distributed with this work for additional information 6c9b362f6SAndre Fischer# regarding copyright ownership. The ASF licenses this file 7c9b362f6SAndre Fischer# to you under the Apache License, Version 2.0 (the 8c9b362f6SAndre Fischer# "License"); you may not use this file except in compliance 9c9b362f6SAndre Fischer# with the License. You may obtain a copy of the License at 10c9b362f6SAndre Fischer# 11c9b362f6SAndre Fischer# http://www.apache.org/licenses/LICENSE-2.0 12c9b362f6SAndre Fischer# 13c9b362f6SAndre Fischer# Unless required by applicable law or agreed to in writing, 14c9b362f6SAndre Fischer# software distributed under the License is distributed on an 15c9b362f6SAndre Fischer# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16c9b362f6SAndre Fischer# KIND, either express or implied. See the License for the 17c9b362f6SAndre Fischer# specific language governing permissions and limitations 18c9b362f6SAndre Fischer# under the License. 19c9b362f6SAndre Fischer# 20c9b362f6SAndre Fischer#************************************************************** 21c9b362f6SAndre Fischer 22c9b362f6SAndre Fischerpackage installer::patch::MsiTable; 23c9b362f6SAndre Fischer 24c9b362f6SAndre Fischer=head1 NAME 25c9b362f6SAndre Fischer 26c9b362f6SAndre Fischer package installer::patch::MsiTable - Class that represents one table of an Msi file. 27c9b362f6SAndre Fischer 28c9b362f6SAndre Fischer=cut 29c9b362f6SAndre Fischer 30c9b362f6SAndre Fischeruse installer::patch::MsiRow; 31c9b362f6SAndre Fischer 32c9b362f6SAndre Fischeruse strict; 33c9b362f6SAndre Fischer 34c9b362f6SAndre Fischer=head new ($class, $filename, $table_name) 35c9b362f6SAndre Fischer 36c9b362f6SAndre Fischer Create a new MsiTable object from the output of a previous 37c9b362f6SAndre Fischer msidb.exe run. The table is named $table_name, its data is read 38c9b362f6SAndre Fischer from $filename. 39c9b362f6SAndre Fischer 40c9b362f6SAndre Fischer=cut 41c9b362f6SAndre Fischersub new ($$$) 42c9b362f6SAndre Fischer{ 43c9b362f6SAndre Fischer my ($class, $filename, $table_name) = @_; 44c9b362f6SAndre Fischer 45c9b362f6SAndre Fischer my $self = { 46c9b362f6SAndre Fischer 'name' => $table_name, 47*9f91b7e3SAndre Fischer 'filename' => $filename, 48*9f91b7e3SAndre Fischer 'columns' => undef, 49*9f91b7e3SAndre Fischer 'column_specs' => undef, 50*9f91b7e3SAndre Fischer 'codepage' => undef, 51*9f91b7e3SAndre Fischer 'is_valid' => 1, 52*9f91b7e3SAndre Fischer 'is_modified' => 0 53c9b362f6SAndre Fischer }; 54c9b362f6SAndre Fischer bless($self, $class); 55c9b362f6SAndre Fischer 56*9f91b7e3SAndre Fischer if (defined $filename && -f $filename) 57c9b362f6SAndre Fischer { 58c9b362f6SAndre Fischer $self->ReadFile($filename); 59c9b362f6SAndre Fischer } 60c9b362f6SAndre Fischer return $self; 61c9b362f6SAndre Fischer} 62c9b362f6SAndre Fischer 63c9b362f6SAndre Fischer 64c9b362f6SAndre Fischer 65c9b362f6SAndre Fischer 66*9f91b7e3SAndre Fischersub SetColumnData ($@) 67*9f91b7e3SAndre Fischer{ 68*9f91b7e3SAndre Fischer my ($self, @data) = @_; 69*9f91b7e3SAndre Fischer 70*9f91b7e3SAndre Fischer if (((scalar @data) % 2) != 0) 71*9f91b7e3SAndre Fischer { 72*9f91b7e3SAndre Fischer installer::logger::PrintError("column data has to have an even number of elements: (<column-name> <data-spec>)+)\n"); 73*9f91b7e3SAndre Fischer $self->{'is_valid'} = 0; 74*9f91b7e3SAndre Fischer return; 75*9f91b7e3SAndre Fischer } 76*9f91b7e3SAndre Fischer 77*9f91b7e3SAndre Fischer $self->{'columns'} = []; 78*9f91b7e3SAndre Fischer $self->{'column_specs'} = []; 79*9f91b7e3SAndre Fischer while (scalar @data > 0) 80*9f91b7e3SAndre Fischer { 81*9f91b7e3SAndre Fischer my $name = shift @data; 82*9f91b7e3SAndre Fischer my $spec = shift @data; 83*9f91b7e3SAndre Fischer push @{$self->{'columns'}}, $name; 84*9f91b7e3SAndre Fischer push @{$self->{'column_specs'}}, $spec; 85*9f91b7e3SAndre Fischer } 86*9f91b7e3SAndre Fischer} 87*9f91b7e3SAndre Fischer 88*9f91b7e3SAndre Fischer 89*9f91b7e3SAndre Fischer 90*9f91b7e3SAndre Fischer 91*9f91b7e3SAndre Fischersub SetIndexColumns ($@) 92*9f91b7e3SAndre Fischer{ 93*9f91b7e3SAndre Fischer my ($self, @index_columns) = @_; 94*9f91b7e3SAndre Fischer 95*9f91b7e3SAndre Fischer $self->{'index_columns'} = [@index_columns]; 96*9f91b7e3SAndre Fischer} 97*9f91b7e3SAndre Fischer 98*9f91b7e3SAndre Fischer 99*9f91b7e3SAndre Fischer 100*9f91b7e3SAndre Fischer 101*9f91b7e3SAndre Fischersub SetCodepage ($$) 102*9f91b7e3SAndre Fischer{ 103*9f91b7e3SAndre Fischer my ($self, $codepage) = @_; 104*9f91b7e3SAndre Fischer 105*9f91b7e3SAndre Fischer $self->{'codepage'} = $codepage; 106*9f91b7e3SAndre Fischer} 107*9f91b7e3SAndre Fischer 108*9f91b7e3SAndre Fischer 109*9f91b7e3SAndre Fischer 110*9f91b7e3SAndre Fischer 111c9b362f6SAndre Fischersub IsValid ($) 112c9b362f6SAndre Fischer{ 113c9b362f6SAndre Fischer my ($self) = @_; 114c9b362f6SAndre Fischer return $self->{'is_valid'}; 115c9b362f6SAndre Fischer} 116c9b362f6SAndre Fischer 117c9b362f6SAndre Fischer 118c9b362f6SAndre Fischer 119c9b362f6SAndre Fischer 120c9b362f6SAndre Fischersub Trim ($) 121c9b362f6SAndre Fischer{ 122c9b362f6SAndre Fischer my $line = shift; 123c9b362f6SAndre Fischer 124c9b362f6SAndre Fischer $line =~ s/(^\s+|\s+$)//g; 125c9b362f6SAndre Fischer 126c9b362f6SAndre Fischer return $line; 127c9b362f6SAndre Fischer} 128c9b362f6SAndre Fischer 129c9b362f6SAndre Fischer 130c9b362f6SAndre Fischer 131c9b362f6SAndre Fischer=head2 ReadFile($self, $filename) 132c9b362f6SAndre Fischer 133c9b362f6SAndre Fischer Read the content of the table from the specified .idt file. 134c9b362f6SAndre Fischer For each row a MsiRow object is appended to $self->{'rows'}. 135c9b362f6SAndre Fischer 136c9b362f6SAndre Fischer=cut 137c9b362f6SAndre Fischersub ReadFile ($$) 138c9b362f6SAndre Fischer{ 139c9b362f6SAndre Fischer my ($self, $filename) = @_; 140c9b362f6SAndre Fischer 141c9b362f6SAndre Fischer if ( ! (-f $filename && -r $filename)) 142c9b362f6SAndre Fischer { 143c9b362f6SAndre Fischer printf STDERR ("can not open idt file %s for reading\n", $filename); 144c9b362f6SAndre Fischer $self->{'is_valid'} = 0; 145c9b362f6SAndre Fischer return; 146c9b362f6SAndre Fischer } 147c9b362f6SAndre Fischer 148c9b362f6SAndre Fischer open my $in, "<", $filename; 149c9b362f6SAndre Fischer 150c9b362f6SAndre Fischer my $columns = Trim(<$in>); 151c9b362f6SAndre Fischer $self->{'columns'} = [split(/\t/, $columns)]; 152c9b362f6SAndre Fischer 153c9b362f6SAndre Fischer my $column_specs = Trim(<$in>); 154c9b362f6SAndre Fischer $self->{'column_specs'} = [split(/\t/, $column_specs)]; 155c9b362f6SAndre Fischer 156c9b362f6SAndre Fischer # Table name, index columns. 157c9b362f6SAndre Fischer my $line = Trim(<$in>); 158c9b362f6SAndre Fischer my @items = split(/\t/, $line); 159*9f91b7e3SAndre Fischer my $item_count = scalar @items; 160*9f91b7e3SAndre Fischer if ($item_count>=1 && $items[0] eq $self->{'name'}) 161*9f91b7e3SAndre Fischer { 162*9f91b7e3SAndre Fischer # No codepage. 163*9f91b7e3SAndre Fischer } 164*9f91b7e3SAndre Fischer elsif ($item_count>=2 && $items[1] eq $self->{'name'}) 165c9b362f6SAndre Fischer { 166c9b362f6SAndre Fischer $self->{'codepage'} = shift @items; 167c9b362f6SAndre Fischer } 168*9f91b7e3SAndre Fischer else 169c9b362f6SAndre Fischer { 170*9f91b7e3SAndre Fischer printf STDERR ("reading wrong table data for table '%s' (got %s)\n", $self->{'name'}, $items[0]); 171c9b362f6SAndre Fischer $self->{'is_valid'} = 0; 172c9b362f6SAndre Fischer return; 173c9b362f6SAndre Fischer } 174*9f91b7e3SAndre Fischer shift @items; 175c9b362f6SAndre Fischer $self->{'index_columns'} = [@items]; 176c9b362f6SAndre Fischer $self->{'index_column_index'} = $self->GetColumnIndex($items[0]); 177c9b362f6SAndre Fischer 178c9b362f6SAndre Fischer my $rows = []; 179c9b362f6SAndre Fischer while (<$in>) 180c9b362f6SAndre Fischer { 181c9b362f6SAndre Fischer # Remove all trailing returns and newlines. Keep trailing spaces and tabs. 182c9b362f6SAndre Fischer s/[\r\n]+$//g; 183c9b362f6SAndre Fischer 184c9b362f6SAndre Fischer my @items = split(/\t/, $_); 185c9b362f6SAndre Fischer push @$rows, new installer::patch::MsiRow($self, @items); 186c9b362f6SAndre Fischer } 187c9b362f6SAndre Fischer $self->{'rows'} = $rows; 188c9b362f6SAndre Fischer 189c9b362f6SAndre Fischer return $self; 190c9b362f6SAndre Fischer} 191c9b362f6SAndre Fischer 192c9b362f6SAndre Fischer 193c9b362f6SAndre Fischer 194*9f91b7e3SAndre Fischer 195*9f91b7e3SAndre Fischer=head WriteFile($self, $filename) 196*9f91b7e3SAndre Fischer 197*9f91b7e3SAndre Fischer Write a text file containing the current table content. 198*9f91b7e3SAndre Fischer 199*9f91b7e3SAndre Fischer=cut 200*9f91b7e3SAndre Fischersub WriteFile ($$) 201*9f91b7e3SAndre Fischer{ 202*9f91b7e3SAndre Fischer my ($self, $filename) = @_; 203*9f91b7e3SAndre Fischer 204*9f91b7e3SAndre Fischer open my $out, ">".$self->{'filename'}; 205*9f91b7e3SAndre Fischer 206*9f91b7e3SAndre Fischer print $out join("\t", @{$self->{'columns'}})."\r\n"; 207*9f91b7e3SAndre Fischer print $out join("\t", @{$self->{'column_specs'}})."\r\n"; 208*9f91b7e3SAndre Fischer if (defined $self->{'codepage'}) 209*9f91b7e3SAndre Fischer { 210*9f91b7e3SAndre Fischer print $out $self->{'codepage'} . "\t"; 211*9f91b7e3SAndre Fischer } 212*9f91b7e3SAndre Fischer print $out $self->{'name'} . "\t"; 213*9f91b7e3SAndre Fischer print $out join("\t",@{$self->{'index_columns'}})."\r\n"; 214*9f91b7e3SAndre Fischer 215*9f91b7e3SAndre Fischer foreach my $row (@{$self->{'rows'}}) 216*9f91b7e3SAndre Fischer { 217*9f91b7e3SAndre Fischer print $out $row->Format("\t")."\r\n"; 218*9f91b7e3SAndre Fischer } 219*9f91b7e3SAndre Fischer 220*9f91b7e3SAndre Fischer close $out; 221*9f91b7e3SAndre Fischer} 222*9f91b7e3SAndre Fischer 223*9f91b7e3SAndre Fischer 224*9f91b7e3SAndre Fischer 225*9f91b7e3SAndre Fischer 226*9f91b7e3SAndre Fischersub UpdateTimestamp ($) 227*9f91b7e3SAndre Fischer{ 228*9f91b7e3SAndre Fischer my $self = shift; 229*9f91b7e3SAndre Fischer 230*9f91b7e3SAndre Fischer utime(undef,undef, $self->{'filename'}); 231*9f91b7e3SAndre Fischer} 232*9f91b7e3SAndre Fischer 233*9f91b7e3SAndre Fischer 234*9f91b7e3SAndre Fischer 235*9f91b7e3SAndre Fischer 236*9f91b7e3SAndre Fischersub GetName ($) 237*9f91b7e3SAndre Fischer{ 238*9f91b7e3SAndre Fischer my $self = shift; 239*9f91b7e3SAndre Fischer 240*9f91b7e3SAndre Fischer return $self->{'name'}; 241*9f91b7e3SAndre Fischer} 242*9f91b7e3SAndre Fischer 243*9f91b7e3SAndre Fischer 244*9f91b7e3SAndre Fischer 245*9f91b7e3SAndre Fischer 246c9b362f6SAndre Fischer=head2 GetColumnCount($self) 247c9b362f6SAndre Fischer 248c9b362f6SAndre Fischer Return the number of columns in the table. 249c9b362f6SAndre Fischer 250c9b362f6SAndre Fischer=cut 251c9b362f6SAndre Fischersub GetColumnCount ($) 252c9b362f6SAndre Fischer{ 253c9b362f6SAndre Fischer my ($self) = @_; 254c9b362f6SAndre Fischer 255c9b362f6SAndre Fischer return scalar @{$self->{'columns'}}; 256c9b362f6SAndre Fischer} 257c9b362f6SAndre Fischer 258c9b362f6SAndre Fischer 259c9b362f6SAndre Fischer 260c9b362f6SAndre Fischer 261c9b362f6SAndre Fischer=head2 GetRowCount($self) 262c9b362f6SAndre Fischer 263c9b362f6SAndre Fischer Return the number of rows in the table. 264c9b362f6SAndre Fischer 265c9b362f6SAndre Fischer=cut 266c9b362f6SAndre Fischersub GetRowCount ($) 267c9b362f6SAndre Fischer{ 268c9b362f6SAndre Fischer my ($self) = @_; 269c9b362f6SAndre Fischer 270c9b362f6SAndre Fischer return scalar @{$self->{'rows'}}; 271c9b362f6SAndre Fischer} 272c9b362f6SAndre Fischer 273c9b362f6SAndre Fischer 274c9b362f6SAndre Fischer 275c9b362f6SAndre Fischer 276c9b362f6SAndre Fischer=head2 GetColumnIndx($self, $column_name) 277c9b362f6SAndre Fischer 278c9b362f6SAndre Fischer Return the 0 based index of the column named $column_name. Use 279c9b362f6SAndre Fischer this to speed up (slightly) access to column values when accessing 280c9b362f6SAndre Fischer many or all rows of a table. 281c9b362f6SAndre Fischer 282c9b362f6SAndre Fischer=cut 283c9b362f6SAndre Fischersub GetColumnIndex ($$) 284c9b362f6SAndre Fischer{ 285c9b362f6SAndre Fischer my ($self, $column_name) = @_; 286c9b362f6SAndre Fischer 287c9b362f6SAndre Fischer my $index = 0; 288c9b362f6SAndre Fischer foreach my $name (@{$self->{'columns'}}) 289c9b362f6SAndre Fischer { 290c9b362f6SAndre Fischer if ($name eq $column_name) 291c9b362f6SAndre Fischer { 292c9b362f6SAndre Fischer return $index; 293c9b362f6SAndre Fischer } 294c9b362f6SAndre Fischer ++$index; 295c9b362f6SAndre Fischer } 296c9b362f6SAndre Fischer 297c9b362f6SAndre Fischer printf STDERR ("did not find column %s in %s\n", $column_name, join(" and ", @{$self->{'columns'}})); 298c9b362f6SAndre Fischer return -1; 299c9b362f6SAndre Fischer} 300c9b362f6SAndre Fischer 301c9b362f6SAndre Fischer 302c9b362f6SAndre Fischer 303*9f91b7e3SAndre Fischer=head2 GetRowIndex($self, $index_column_index, $index_column_value) 304*9f91b7e3SAndre Fischer 305*9f91b7e3SAndre Fischer Return the index, starting at 0, of the (first) row that has value $index_column_value 306*9f91b7e3SAndre Fischer in column with index $index_column_index. 307*9f91b7e3SAndre Fischer 308*9f91b7e3SAndre Fischer Return -1 if now such row is found. 309*9f91b7e3SAndre Fischer 310*9f91b7e3SAndre Fischer=cut 311*9f91b7e3SAndre Fischersub GetRowIndex ($$$) 312*9f91b7e3SAndre Fischer{ 313*9f91b7e3SAndre Fischer my ($self, $index_column_index, $index_column_value) = @_; 314*9f91b7e3SAndre Fischer 315*9f91b7e3SAndre Fischer my $rows = $self->{'rows'}; 316*9f91b7e3SAndre Fischer for (my ($row_index,$row_count)=(0,scalar @$rows); $row_index<$row_count; ++$row_index) 317*9f91b7e3SAndre Fischer { 318*9f91b7e3SAndre Fischer my $row = $rows->[$row_index]; 319*9f91b7e3SAndre Fischer if ($row->GetValue($index_column_index) eq $index_column_value) 320*9f91b7e3SAndre Fischer { 321*9f91b7e3SAndre Fischer return $row_index; 322*9f91b7e3SAndre Fischer } 323*9f91b7e3SAndre Fischer } 324*9f91b7e3SAndre Fischer 325*9f91b7e3SAndre Fischer return -1; 326*9f91b7e3SAndre Fischer} 327*9f91b7e3SAndre Fischer 328*9f91b7e3SAndre Fischer 329*9f91b7e3SAndre Fischer 330c9b362f6SAndre Fischer 331c9b362f6SAndre Fischer=head2 GetValue($self, $selector_column, $selector_column_value, $value_column) 332c9b362f6SAndre Fischer 333c9b362f6SAndre Fischer Find the row in which the $selector_column has value 334c9b362f6SAndre Fischer $selector_column_value and return its value in the $value_column. 335c9b362f6SAndre Fischer 336c9b362f6SAndre Fischer=cut 337c9b362f6SAndre Fischer 338c9b362f6SAndre Fischersub GetValue ($$$$) 339c9b362f6SAndre Fischer{ 340c9b362f6SAndre Fischer my ($self, $selector_column, $selector_column_value, $value_column) = @_; 341c9b362f6SAndre Fischer 342c9b362f6SAndre Fischer my $row = $self->GetRow($selector_column, $selector_column_value); 343c9b362f6SAndre Fischer if (defined $row) 344c9b362f6SAndre Fischer { 345c9b362f6SAndre Fischer return $row->GetValue($value_column); 346c9b362f6SAndre Fischer } 347c9b362f6SAndre Fischer else 348c9b362f6SAndre Fischer { 349c9b362f6SAndre Fischer return undef; 350c9b362f6SAndre Fischer } 351c9b362f6SAndre Fischer} 352c9b362f6SAndre Fischer 353c9b362f6SAndre Fischer 354c9b362f6SAndre Fischer 355c9b362f6SAndre Fischer 356c9b362f6SAndre Fischer=head2 GetRow($self, $column, $value) 357c9b362f6SAndre Fischer 358c9b362f6SAndre Fischer Return the (first) row which has $value in $column. 359c9b362f6SAndre Fischer 360c9b362f6SAndre Fischer=cut 361c9b362f6SAndre Fischersub GetRow ($$$) 362c9b362f6SAndre Fischer{ 363c9b362f6SAndre Fischer my ($self, $column, $value) = @_; 364c9b362f6SAndre Fischer 365c9b362f6SAndre Fischer my $column_index = $self->GetColumnIndex($column); 366c9b362f6SAndre Fischer if ($column_index<0) 367c9b362f6SAndre Fischer { 368c9b362f6SAndre Fischer printf STDERR "ERROR: unknown column $column in table $self->{'name'}\n"; 369c9b362f6SAndre Fischer return undef; 370c9b362f6SAndre Fischer } 371c9b362f6SAndre Fischer 372c9b362f6SAndre Fischer foreach my $row (@{$self->{'rows'}}) 373c9b362f6SAndre Fischer { 374c9b362f6SAndre Fischer if ($row->GetValue($column_index) eq $value) 375c9b362f6SAndre Fischer { 376c9b362f6SAndre Fischer return $row; 377c9b362f6SAndre Fischer } 378c9b362f6SAndre Fischer } 379c9b362f6SAndre Fischer 380c9b362f6SAndre Fischer printf STDERR ("ERROR: did not find row for %s->%s in %s\n", 381c9b362f6SAndre Fischer $column, 382c9b362f6SAndre Fischer $value, 383c9b362f6SAndre Fischer table $self->{'name'}); 384c9b362f6SAndre Fischer 385c9b362f6SAndre Fischer return undef; 386c9b362f6SAndre Fischer} 387c9b362f6SAndre Fischer 388c9b362f6SAndre Fischer 389c9b362f6SAndre Fischer 390c9b362f6SAndre Fischer 391c9b362f6SAndre Fischer=head2 GetAllRows ($self) 392c9b362f6SAndre Fischer 393c9b362f6SAndre Fischer Return the reference to an array that contains all rows of the table. 394c9b362f6SAndre Fischer 395c9b362f6SAndre Fischer=cut 396c9b362f6SAndre Fischer 397c9b362f6SAndre Fischersub GetAllRows ($) 398c9b362f6SAndre Fischer{ 399c9b362f6SAndre Fischer my $self = shift; 400c9b362f6SAndre Fischer 401c9b362f6SAndre Fischer return $self->{'rows'}; 402c9b362f6SAndre Fischer} 403c9b362f6SAndre Fischer 404c9b362f6SAndre Fischer 405c9b362f6SAndre Fischer 406c9b362f6SAndre Fischer 407*9f91b7e3SAndre Fischer=head2 SetRow($self, {$key, $value}*) 408*9f91b7e3SAndre Fischer 409*9f91b7e3SAndre Fischer Replace an existing row. If no matching row is found then add the row. 410*9f91b7e3SAndre Fischer 411*9f91b7e3SAndre Fischer The row is defined by a set of key/value pairs. Their order is defined by the keys (column names) 412*9f91b7e3SAndre Fischer and their indices as defined in $self->{'columns'}. 413*9f91b7e3SAndre Fischer 414*9f91b7e3SAndre Fischer Rows are compared by their values of the index column. By default this is the first element of 415*9f91b7e3SAndre Fischer $self->{'index_columns'} but is overruled by the last key that starts with a '*'. 416*9f91b7e3SAndre Fischer 417*9f91b7e3SAndre Fischer=cut 418*9f91b7e3SAndre Fischersub SetRow ($@) 419*9f91b7e3SAndre Fischer{ 420*9f91b7e3SAndre Fischer my $self = shift; 421*9f91b7e3SAndre Fischer my @data = @_; 422*9f91b7e3SAndre Fischer 423*9f91b7e3SAndre Fischer my @items = (); 424*9f91b7e3SAndre Fischer my $index_column = $self->{'index_columns'}->[0]; 425*9f91b7e3SAndre Fischer 426*9f91b7e3SAndre Fischer # Key/Value has to have an even number of entries. 427*9f91b7e3SAndre Fischer MsiTools::Die("invalid arguments given to MsiTable::SetRow()\n") if (scalar @data%2) != 0; 428*9f91b7e3SAndre Fischer 429*9f91b7e3SAndre Fischer # Find column indices for column names. 430*9f91b7e3SAndre Fischer while (scalar @data > 0) 431*9f91b7e3SAndre Fischer { 432*9f91b7e3SAndre Fischer my $column_name = shift @data; 433*9f91b7e3SAndre Fischer if ($column_name =~ /^\*(.*)$/) 434*9f91b7e3SAndre Fischer { 435*9f91b7e3SAndre Fischer # Column name starts with a '*'. Use it as index column. 436*9f91b7e3SAndre Fischer $column_name = $1; 437*9f91b7e3SAndre Fischer $index_column = $1; 438*9f91b7e3SAndre Fischer } 439*9f91b7e3SAndre Fischer my $value = shift @data; 440*9f91b7e3SAndre Fischer my $column_index = $self->GetColumnIndex($column_name); 441*9f91b7e3SAndre Fischer $items[$column_index] = $value; 442*9f91b7e3SAndre Fischer } 443*9f91b7e3SAndre Fischer 444*9f91b7e3SAndre Fischer my $index_column_index = $self->GetColumnIndex($index_column); 445*9f91b7e3SAndre Fischer my $row_index = $self->GetRowIndex($index_column_index, $items[$index_column_index]); 446*9f91b7e3SAndre Fischer 447*9f91b7e3SAndre Fischer if ($row_index < 0) 448*9f91b7e3SAndre Fischer { 449*9f91b7e3SAndre Fischer # Row does not yet exist. Add it. 450*9f91b7e3SAndre Fischer push @{$self->{'rows'}}, installer::patch::MsiRow->new($self, @items); 451*9f91b7e3SAndre Fischer } 452*9f91b7e3SAndre Fischer else 453*9f91b7e3SAndre Fischer { 454*9f91b7e3SAndre Fischer # Row does already exist. Replace it. 455*9f91b7e3SAndre Fischer $self->{'rows'}->[$row_index] = installer::patch::MsiRow->new($self, @items); 456*9f91b7e3SAndre Fischer } 457*9f91b7e3SAndre Fischer 458*9f91b7e3SAndre Fischer $self->MarkAsModified(); 459*9f91b7e3SAndre Fischer} 460*9f91b7e3SAndre Fischer 461*9f91b7e3SAndre Fischer 462*9f91b7e3SAndre Fischer 463*9f91b7e3SAndre Fischer 464*9f91b7e3SAndre Fischersub MarkAsModified ($) 465*9f91b7e3SAndre Fischer{ 466*9f91b7e3SAndre Fischer my $self = shift; 467*9f91b7e3SAndre Fischer 468*9f91b7e3SAndre Fischer $self->{'is_modified'} = 1; 469*9f91b7e3SAndre Fischer} 470*9f91b7e3SAndre Fischer 471*9f91b7e3SAndre Fischer 472*9f91b7e3SAndre Fischer 473*9f91b7e3SAndre Fischer 474*9f91b7e3SAndre Fischersub MarkAsUnmodified ($) 475*9f91b7e3SAndre Fischer{ 476*9f91b7e3SAndre Fischer my $self = shift; 477*9f91b7e3SAndre Fischer 478*9f91b7e3SAndre Fischer $self->{'is_modified'} = 0; 479*9f91b7e3SAndre Fischer} 480*9f91b7e3SAndre Fischer 481*9f91b7e3SAndre Fischer 482*9f91b7e3SAndre Fischer 483*9f91b7e3SAndre Fischer 484*9f91b7e3SAndre Fischersub IsModified ($) 485*9f91b7e3SAndre Fischer{ 486*9f91b7e3SAndre Fischer my $self = shift; 487*9f91b7e3SAndre Fischer 488*9f91b7e3SAndre Fischer return $self->{'is_modified'}; 489*9f91b7e3SAndre Fischer} 490*9f91b7e3SAndre Fischer 491c9b362f6SAndre Fischer 492c9b362f6SAndre Fischer1; 493