1*c6dedb65SAndre Fischer#************************************************************** 2*c6dedb65SAndre Fischer# 3*c6dedb65SAndre Fischer# Licensed to the Apache Software Foundation (ASF) under one 4*c6dedb65SAndre Fischer# or more contributor license agreements. See the NOTICE file 5*c6dedb65SAndre Fischer# distributed with this work for additional information 6*c6dedb65SAndre Fischer# regarding copyright ownership. The ASF licenses this file 7*c6dedb65SAndre Fischer# to you under the Apache License, Version 2.0 (the 8*c6dedb65SAndre Fischer# "License"); you may not use this file except in compliance 9*c6dedb65SAndre Fischer# with the License. You may obtain a copy of the License at 10*c6dedb65SAndre Fischer# 11*c6dedb65SAndre Fischer# http://www.apache.org/licenses/LICENSE-2.0 12*c6dedb65SAndre Fischer# 13*c6dedb65SAndre Fischer# Unless required by applicable law or agreed to in writing, 14*c6dedb65SAndre Fischer# software distributed under the License is distributed on an 15*c6dedb65SAndre Fischer# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*c6dedb65SAndre Fischer# KIND, either express or implied. See the License for the 17*c6dedb65SAndre Fischer# specific language governing permissions and limitations 18*c6dedb65SAndre Fischer# under the License. 19*c6dedb65SAndre Fischer# 20*c6dedb65SAndre Fischer#************************************************************** 21*c6dedb65SAndre Fischer 22*c6dedb65SAndre Fischerpackage ExtensionsLst; 23*c6dedb65SAndre Fischer 24*c6dedb65SAndre Fischeruse File::Spec; 25*c6dedb65SAndre Fischeruse LWP::UserAgent; 26*c6dedb65SAndre Fischeruse Digest::MD5; 27*c6dedb65SAndre Fischer 28*c6dedb65SAndre Fischeruse base 'Exporter'; 29*c6dedb65SAndre Fischerour @EXPORT = qw(DownloadExtensions GetExtensionList); 30*c6dedb65SAndre Fischer 31*c6dedb65SAndre Fischer 32*c6dedb65SAndre Fischer=head1 NAME 33*c6dedb65SAndre Fischer 34*c6dedb65SAndre Fischer ExtensionLst.pm - Functionality for the interpretation of the main/extensions.lst file. 35*c6dedb65SAndre Fischer 36*c6dedb65SAndre Fischer=head1 SYNOPSIS 37*c6dedb65SAndre Fischer 38*c6dedb65SAndre Fischer For downloading extensions during build setup: 39*c6dedb65SAndre Fischer 40*c6dedb65SAndre Fischer use ExtensionsLst; 41*c6dedb65SAndre Fischer ExtensionsLst::DownloadExtensions(); 42*c6dedb65SAndre Fischer 43*c6dedb65SAndre Fischer For including extensions into the pack set: 44*c6dedb65SAndre Fischer 45*c6dedb65SAndre Fischer use ExtensionsLst; 46*c6dedb65SAndre Fischer ExtensionsLst::GetExtensionList(@language_list); 47*c6dedb65SAndre Fischer 48*c6dedb65SAndre Fischer=head1 DESCRIPTION 49*c6dedb65SAndre Fischer 50*c6dedb65SAndre Fischer The contents of the extensions.lst file are used at two times in 51*c6dedb65SAndre Fischer the process of building pack sets. 52*c6dedb65SAndre Fischer 53*c6dedb65SAndre Fischer Once at the beginning right after configure is run the 54*c6dedb65SAndre Fischer DownloadExtensions() function determines the list of extensions 55*c6dedb65SAndre Fischer that are not present locally and downloads them. 56*c6dedb65SAndre Fischer 57*c6dedb65SAndre Fischer The second time is after all modules are built (and the locally 58*c6dedb65SAndre Fischer built extensions are present) and the pack sets are created. For 59*c6dedb65SAndre Fischer every language (or sets of lanugages) a set of extensions is 60*c6dedb65SAndre Fischer collected and included into the pack set. 61*c6dedb65SAndre Fischer 62*c6dedb65SAndre Fischer The content of the extensions.lst file is ignored when the --with-extensions option is given to configure. 63*c6dedb65SAndre Fischer 64*c6dedb65SAndre Fischer=cut 65*c6dedb65SAndre Fischer 66*c6dedb65SAndre Fischer 67*c6dedb65SAndre Fischer# Number of the line in extensions.lst that is currently being processed. 68*c6dedb65SAndre Fischermy $LineNo = 0; 69*c6dedb65SAndre Fischer 70*c6dedb65SAndre Fischer 71*c6dedb65SAndre Fischer=head3 Prepare 72*c6dedb65SAndre Fischer Check that some environment variables are properly set and then return the file name 73*c6dedb65SAndre Fischer of the 'extensions.lst' file, typically located in main/ beside 'ooo.lst'. 74*c6dedb65SAndre Fischer=cut 75*c6dedb65SAndre Fischersub Prepare () 76*c6dedb65SAndre Fischer{ 77*c6dedb65SAndre Fischer die "can not access environment varianle SRC_ROOT" if ! defined $ENV{'SRC_ROOT'}; 78*c6dedb65SAndre Fischer die "can not determine the platform: INPATH is not set" if ! defined $ENV{'INPATH'}; 79*c6dedb65SAndre Fischer die "can not determine solver directory: OUTDIR is not set" if ! defined $ENV{'OUTDIR'}; 80*c6dedb65SAndre Fischer die "can not determine download directory: TARFILE_LOCATION is not set" if ! defined $ENV{'TARFILE_LOCATION'}; 81*c6dedb65SAndre Fischer 82*c6dedb65SAndre Fischer my $candidate = File::Spec->catfile($ENV{SRC_ROOT}, "extensions.lst"); 83*c6dedb65SAndre Fischer die "can not read file $candidate" if ! -r $candidate; 84*c6dedb65SAndre Fischer return $candidate; 85*c6dedb65SAndre Fischer} 86*c6dedb65SAndre Fischer 87*c6dedb65SAndre Fischer 88*c6dedb65SAndre Fischer 89*c6dedb65SAndre Fischer=head 3 EvaluateOperator 90*c6dedb65SAndre Fischer Evaluate a single test statement like 'language = en.*'. 91*c6dedb65SAndre Fischer Special handling for operators '=', '==', and 'eq' which are all mapped to '=~'. 92*c6dedb65SAndre Fischer Therefore the right hand side may be a perl regexp. It is prefixed with '^'. 93*c6dedb65SAndre Fischer 94*c6dedb65SAndre Fischer Other operators are at the moment only supported in the way that they are evaluated via eval(). 95*c6dedb65SAndre Fischer=cut 96*c6dedb65SAndre Fischersub EvaluateOperator ($$$) 97*c6dedb65SAndre Fischer{ 98*c6dedb65SAndre Fischer my ($left,$operator,$right) = @_; 99*c6dedb65SAndre Fischer 100*c6dedb65SAndre Fischer my $result; 101*c6dedb65SAndre Fischer 102*c6dedb65SAndre Fischer if ($operator =~ /^(=|==|eq)$/) 103*c6dedb65SAndre Fischer { 104*c6dedb65SAndre Fischer if ($left =~ /^$right$/) 105*c6dedb65SAndre Fischer { 106*c6dedb65SAndre Fischer $result = 1; 107*c6dedb65SAndre Fischer } 108*c6dedb65SAndre Fischer else 109*c6dedb65SAndre Fischer { 110*c6dedb65SAndre Fischer $result = 0; 111*c6dedb65SAndre Fischer } 112*c6dedb65SAndre Fischer } 113*c6dedb65SAndre Fischer elsif (eval($left.$operator.$right)) 114*c6dedb65SAndre Fischer { 115*c6dedb65SAndre Fischer $result = 1; 116*c6dedb65SAndre Fischer } 117*c6dedb65SAndre Fischer else 118*c6dedb65SAndre Fischer { 119*c6dedb65SAndre Fischer $result = 0; 120*c6dedb65SAndre Fischer } 121*c6dedb65SAndre Fischer 122*c6dedb65SAndre Fischer return $result; 123*c6dedb65SAndre Fischer} 124*c6dedb65SAndre Fischer 125*c6dedb65SAndre Fischer 126*c6dedb65SAndre Fischer 127*c6dedb65SAndre Fischer 128*c6dedb65SAndre Fischer=head EvaluateTerm 129*c6dedb65SAndre Fischer Evaluate a string that contains a simple test term of the form 130*c6dedb65SAndre Fischer left operator right 131*c6dedb65SAndre Fischer with arbitrary spacing allowed around and between the three parts. 132*c6dedb65SAndre Fischer 133*c6dedb65SAndre Fischer The left hand side is specially handled: 134*c6dedb65SAndre Fischer 135*c6dedb65SAndre Fischer - When the left hand side is 'language' then it is replaced by 136*c6dedb65SAndre Fischer any of the given languages in turn. When the term evaluates to true for any of the languages then 137*c6dedb65SAndre Fischer true is returned. False is returned only when none of the given languages matches. 138*c6dedb65SAndre Fischer 139*c6dedb65SAndre Fischer - When the left hand side consists only of upper case letters, digits, and '_' then it is 140*c6dedb65SAndre Fischer interpreted as the name of a environment variable. It is replaced by its value before the term 141*c6dedb65SAndre Fischer is evaluated. 142*c6dedb65SAndre Fischer 143*c6dedb65SAndre Fischer - Any other left hand side is an error (at the moment.) 144*c6dedb65SAndre Fischer=cut 145*c6dedb65SAndre Fischersub EvaluateTerm ($$) 146*c6dedb65SAndre Fischer{ 147*c6dedb65SAndre Fischer my $term = shift; 148*c6dedb65SAndre Fischer my $languages = shift; 149*c6dedb65SAndre Fischer 150*c6dedb65SAndre Fischer my $result; 151*c6dedb65SAndre Fischer 152*c6dedb65SAndre Fischer if ($term =~ /^\s*(\w+)\s*(\W+)\s*(.*?)\s*$/) 153*c6dedb65SAndre Fischer { 154*c6dedb65SAndre Fischer my ($left,$operator,$right) = ($1,$2,$3); 155*c6dedb65SAndre Fischer 156*c6dedb65SAndre Fischer if ($operator !~ /^=|==|eq$/) 157*c6dedb65SAndre Fischer { 158*c6dedb65SAndre Fischer die "unsupported operator $operator on line $LineNo"; 159*c6dedb65SAndre Fischer } 160*c6dedb65SAndre Fischer 161*c6dedb65SAndre Fischer die "no right side in condition on line $LineNo ($term)" if ! defined $right; 162*c6dedb65SAndre Fischer 163*c6dedb65SAndre Fischer if ($left =~ /^[A-Z_0-9]+$/) 164*c6dedb65SAndre Fischer { 165*c6dedb65SAndre Fischer # Uppercase words are interpreted as environment variables. 166*c6dedb65SAndre Fischer my $left_value = $ENV{$left}; 167*c6dedb65SAndre Fischer $left_value = "" if ! defined $left_value; 168*c6dedb65SAndre Fischer 169*c6dedb65SAndre Fischer # We can check whether the condition is fullfilled right now. 170*c6dedb65SAndre Fischer $result = EvaluateOperator($left_value, $operator, $right); 171*c6dedb65SAndre Fischer } 172*c6dedb65SAndre Fischer elsif ($left eq "language") 173*c6dedb65SAndre Fischer { 174*c6dedb65SAndre Fischer if ($right eq "all") 175*c6dedb65SAndre Fischer { 176*c6dedb65SAndre Fischer $result = 1; 177*c6dedb65SAndre Fischer } 178*c6dedb65SAndre Fischer elsif ($#$languages>=0) 179*c6dedb65SAndre Fischer { 180*c6dedb65SAndre Fischer $result = 0; 181*c6dedb65SAndre Fischer for my $language (@$languages) 182*c6dedb65SAndre Fischer { 183*c6dedb65SAndre Fischer # Unify naming schemes. 184*c6dedb65SAndre Fischer $language =~ s/_/-/g; 185*c6dedb65SAndre Fischer $right =~ s/_/-/g; 186*c6dedb65SAndre Fischer 187*c6dedb65SAndre Fischer # Evaluate language regexp. 188*c6dedb65SAndre Fischer $result = EvaluateOperator($language, $operator, $right) ? 1 : 0; 189*c6dedb65SAndre Fischer last if $result; 190*c6dedb65SAndre Fischer } 191*c6dedb65SAndre Fischer } 192*c6dedb65SAndre Fischer else 193*c6dedb65SAndre Fischer { 194*c6dedb65SAndre Fischer # The set of languages is not yet known. Return true 195*c6dedb65SAndre Fischer # to include the following entries. 196*c6dedb65SAndre Fischer $result = 1; 197*c6dedb65SAndre Fischer } 198*c6dedb65SAndre Fischer } 199*c6dedb65SAndre Fischer elsif ($left eq "platform") 200*c6dedb65SAndre Fischer { 201*c6dedb65SAndre Fischer if ($right eq "all") 202*c6dedb65SAndre Fischer { 203*c6dedb65SAndre Fischer $result = 1; 204*c6dedb65SAndre Fischer } 205*c6dedb65SAndre Fischer else 206*c6dedb65SAndre Fischer { 207*c6dedb65SAndre Fischer # Evaluate platform regexp. 208*c6dedb65SAndre Fischer $result = EvaluateOperator($ENV{'INPATH'}, $operator, $right) ? 1 : 0; 209*c6dedb65SAndre Fischer } 210*c6dedb65SAndre Fischer } 211*c6dedb65SAndre Fischer else 212*c6dedb65SAndre Fischer { 213*c6dedb65SAndre Fischer die "can not handle left hand side $left on line $LineNo"; 214*c6dedb65SAndre Fischer } 215*c6dedb65SAndre Fischer } 216*c6dedb65SAndre Fischer else 217*c6dedb65SAndre Fischer { 218*c6dedb65SAndre Fischer die "syntax error in expression on line $LineNo"; 219*c6dedb65SAndre Fischer } 220*c6dedb65SAndre Fischer 221*c6dedb65SAndre Fischer return $result; 222*c6dedb65SAndre Fischer} 223*c6dedb65SAndre Fischer 224*c6dedb65SAndre Fischer 225*c6dedb65SAndre Fischer 226*c6dedb65SAndre Fischer 227*c6dedb65SAndre Fischer=head3 EvaluateSelector 228*c6dedb65SAndre Fischer Evaluate the given expression that is expected to be list of terms of the form 229*c6dedb65SAndre Fischer left-hand-side operator right-hand-side 230*c6dedb65SAndre Fischer that are separated by logical operators 231*c6dedb65SAndre Fischer && || 232*c6dedb65SAndre Fischer The expression is lazy evaluated left to right. 233*c6dedb65SAndre Fischer=cut 234*c6dedb65SAndre Fischersub EvaluateSelector($$); 235*c6dedb65SAndre Fischersub EvaluateSelector($$) 236*c6dedb65SAndre Fischer{ 237*c6dedb65SAndre Fischer my $expression = shift; 238*c6dedb65SAndre Fischer my $languages = shift; 239*c6dedb65SAndre Fischer 240*c6dedb65SAndre Fischer my $result = ""; 241*c6dedb65SAndre Fischer 242*c6dedb65SAndre Fischer if ($expression =~ /^\s*$/) 243*c6dedb65SAndre Fischer { 244*c6dedb65SAndre Fischer # Empty selector is always true. 245*c6dedb65SAndre Fischer return 1; 246*c6dedb65SAndre Fischer } 247*c6dedb65SAndre Fischer elsif ($expression =~ /^\s*(.*?)(&&|\|\|)\s*(.*)$/) 248*c6dedb65SAndre Fischer { 249*c6dedb65SAndre Fischer my ($term, $operator) = ($1,$2); 250*c6dedb65SAndre Fischer $expression = $3; 251*c6dedb65SAndre Fischer 252*c6dedb65SAndre Fischer my $left_result = EvaluateTerm($term, $languages); 253*c6dedb65SAndre Fischer # Lazy evaluation of && 254*c6dedb65SAndre Fischer return 0 if ($operator eq "&&" && !$left_result); 255*c6dedb65SAndre Fischer # Lazy evaluation of || 256*c6dedb65SAndre Fischer return 1 if ($operator eq "||" && $left_result); 257*c6dedb65SAndre Fischer my $right_result = EvaluateSelector($expression, $languages); 258*c6dedb65SAndre Fischer 259*c6dedb65SAndre Fischer if ($operator eq "&&") 260*c6dedb65SAndre Fischer { 261*c6dedb65SAndre Fischer return $left_result && $right_result; 262*c6dedb65SAndre Fischer } 263*c6dedb65SAndre Fischer else 264*c6dedb65SAndre Fischer { 265*c6dedb65SAndre Fischer return $left_result || $right_result; 266*c6dedb65SAndre Fischer } 267*c6dedb65SAndre Fischer } 268*c6dedb65SAndre Fischer elsif ($expression =~ /^\s*(.+?)\s$/) 269*c6dedb65SAndre Fischer { 270*c6dedb65SAndre Fischer return EvaluateTerm($1, $languages); 271*c6dedb65SAndre Fischer } 272*c6dedb65SAndre Fischer else 273*c6dedb65SAndre Fischer { 274*c6dedb65SAndre Fischer die "invalid expression syntax on line $LineNo ($expression)"; 275*c6dedb65SAndre Fischer } 276*c6dedb65SAndre Fischer} 277*c6dedb65SAndre Fischer 278*c6dedb65SAndre Fischer 279*c6dedb65SAndre Fischer 280*c6dedb65SAndre Fischer 281*c6dedb65SAndre Fischer=head3 ProcessURL 282*c6dedb65SAndre Fischer Check that the given line contains an optional MD5 sum followed by 283*c6dedb65SAndre Fischer a URL for one of the protocols file, http, https 284*c6dedb65SAndre Fischer Return an array that contains the protocol, the name, the original 285*c6dedb65SAndre Fischer URL, and the MD5 sum from the beginning of the line. 286*c6dedb65SAndre Fischer The name of the URL depends on its protocol: 287*c6dedb65SAndre Fischer - for http(s) the part of the URL after the last '/'. 288*c6dedb65SAndre Fischer - for file URLS it is everything after the protocol:// 289*c6dedb65SAndre Fischer=cut 290*c6dedb65SAndre Fischersub ProcessURL ($) 291*c6dedb65SAndre Fischer{ 292*c6dedb65SAndre Fischer my $line = shift; 293*c6dedb65SAndre Fischer 294*c6dedb65SAndre Fischer # Check that we are looking at a valid URL. 295*c6dedb65SAndre Fischer if ($line =~ /^\s*(\w{32}\s+)?([a-zA-Z]+)(:\/\/.*?\/)([^\/ \t]+)\s*$/) 296*c6dedb65SAndre Fischer { 297*c6dedb65SAndre Fischer my ($md5, $protocol, $name) = ($1,$2,$4); 298*c6dedb65SAndre Fischer my $URL = $2.$3.$4; 299*c6dedb65SAndre Fischer 300*c6dedb65SAndre Fischer die "invalid URL protocol on line $LineNo:\n$line\n" if $protocol !~ /(file|http|https)/; 301*c6dedb65SAndre Fischer 302*c6dedb65SAndre Fischer # For file URLs we use everything after :// as name. 303*c6dedb65SAndre Fischer if ($protocol eq "file") 304*c6dedb65SAndre Fischer { 305*c6dedb65SAndre Fischer $URL =~ /:\/\/(.*)$/; 306*c6dedb65SAndre Fischer $name = $1; 307*c6dedb65SAndre Fischer } 308*c6dedb65SAndre Fischer 309*c6dedb65SAndre Fischer return [$protocol, $name, $URL, $md5]; 310*c6dedb65SAndre Fischer } 311*c6dedb65SAndre Fischer else 312*c6dedb65SAndre Fischer { 313*c6dedb65SAndre Fischer die "invalid URL at line $LineNo:\n$line\n"; 314*c6dedb65SAndre Fischer } 315*c6dedb65SAndre Fischer} 316*c6dedb65SAndre Fischer 317*c6dedb65SAndre Fischer 318*c6dedb65SAndre Fischer 319*c6dedb65SAndre Fischer 320*c6dedb65SAndre Fischer=head3 ParseExtensionsLst 321*c6dedb65SAndre Fischer Parse the extensions.lst file. 322*c6dedb65SAndre Fischer 323*c6dedb65SAndre Fischer Lines that contain only spaces or comments or are empty are 324*c6dedb65SAndre Fischer ignored. 325*c6dedb65SAndre Fischer 326*c6dedb65SAndre Fischer Lines that contain a selector, ie a test enclosed in brackets, are 327*c6dedb65SAndre Fischer evaluated. The following lines, until the next selector, are 328*c6dedb65SAndre Fischer ignored when the selector evaluates to false. When an empty list 329*c6dedb65SAndre Fischer of languages is given then any 'language=...' test is evaluated as 330*c6dedb65SAndre Fischer true. 331*c6dedb65SAndre Fischer 332*c6dedb65SAndre Fischer All other lines are expected to contain a URL optionally preceded 333*c6dedb65SAndre Fischer by an MD5 sum. 334*c6dedb65SAndre Fischer=cut 335*c6dedb65SAndre Fischersub ParseExtensionsLst ($$) 336*c6dedb65SAndre Fischer{ 337*c6dedb65SAndre Fischer my $file_name = shift; 338*c6dedb65SAndre Fischer my $languages = shift; 339*c6dedb65SAndre Fischer 340*c6dedb65SAndre Fischer open my $in, "$file_name"; 341*c6dedb65SAndre Fischer 342*c6dedb65SAndre Fischer my $current_selector_value = 1; 343*c6dedb65SAndre Fischer my @URLs = (); 344*c6dedb65SAndre Fischer 345*c6dedb65SAndre Fischer while (<$in>) 346*c6dedb65SAndre Fischer { 347*c6dedb65SAndre Fischer my $line = $_; 348*c6dedb65SAndre Fischer $line =~ s/[\r\n]+//g; 349*c6dedb65SAndre Fischer ++$LineNo; 350*c6dedb65SAndre Fischer 351*c6dedb65SAndre Fischer # Strip away comments. 352*c6dedb65SAndre Fischer next if $line =~ /^\s*#/; 353*c6dedb65SAndre Fischer 354*c6dedb65SAndre Fischer # Ignore empty lines. 355*c6dedb65SAndre Fischer next if $line =~ /^\s*$/; 356*c6dedb65SAndre Fischer 357*c6dedb65SAndre Fischer # Process selectors 358*c6dedb65SAndre Fischer if ($line =~ /^\s*\[\s*(.*)\s*\]\s*$/) 359*c6dedb65SAndre Fischer { 360*c6dedb65SAndre Fischer $current_selector_value = EvaluateSelector($1, $languages); 361*c6dedb65SAndre Fischer } 362*c6dedb65SAndre Fischer else 363*c6dedb65SAndre Fischer { 364*c6dedb65SAndre Fischer if ($current_selector_value) 365*c6dedb65SAndre Fischer { 366*c6dedb65SAndre Fischer push @URLs, ProcessURL($line); 367*c6dedb65SAndre Fischer } 368*c6dedb65SAndre Fischer } 369*c6dedb65SAndre Fischer } 370*c6dedb65SAndre Fischer 371*c6dedb65SAndre Fischer close $in; 372*c6dedb65SAndre Fischer 373*c6dedb65SAndre Fischer return @URLs; 374*c6dedb65SAndre Fischer} 375*c6dedb65SAndre Fischer 376*c6dedb65SAndre Fischer 377*c6dedb65SAndre Fischer 378*c6dedb65SAndre Fischer 379*c6dedb65SAndre Fischer=head3 Download 380*c6dedb65SAndre Fischer Download a set of files that are specified via URLs. 381*c6dedb65SAndre Fischer 382*c6dedb65SAndre Fischer File URLs are ignored here because they point to extensions that have not yet been built. 383*c6dedb65SAndre Fischer 384*c6dedb65SAndre Fischer For http URLs there may be an optional MD5 checksum. If it is present then downloaded 385*c6dedb65SAndre Fischer files that do not match that checksum are an error and lead to abortion of the current process. 386*c6dedb65SAndre Fischer Files that have already been downloaded are not downloaded again. 387*c6dedb65SAndre Fischer=cut 388*c6dedb65SAndre Fischersub Download (@) 389*c6dedb65SAndre Fischer{ 390*c6dedb65SAndre Fischer my @urls = @_; 391*c6dedb65SAndre Fischer 392*c6dedb65SAndre Fischer my @missing = (); 393*c6dedb65SAndre Fischer my $download_path = $ENV{'TARFILE_LOCATION'}; 394*c6dedb65SAndre Fischer 395*c6dedb65SAndre Fischer # First check which (if any) extensions have already been downloaded. 396*c6dedb65SAndre Fischer for my $entry (@urls) 397*c6dedb65SAndre Fischer { 398*c6dedb65SAndre Fischer my ($protocol, $name, $URL, $md5sum) = @{$entry}; 399*c6dedb65SAndre Fischer 400*c6dedb65SAndre Fischer # We can not check the existence of file URLs because they point to extensions that 401*c6dedb65SAndre Fischer # have yet to be built. 402*c6dedb65SAndre Fischer 403*c6dedb65SAndre Fischer next if $protocol ne "http"; 404*c6dedb65SAndre Fischer my $candidate = File::Spec->catfile($download_path, $name); 405*c6dedb65SAndre Fischer if ( ! -f $candidate) 406*c6dedb65SAndre Fischer { 407*c6dedb65SAndre Fischer push @missing, $entry; 408*c6dedb65SAndre Fischer } 409*c6dedb65SAndre Fischer } 410*c6dedb65SAndre Fischer if ($#missing >= 0) 411*c6dedb65SAndre Fischer { 412*c6dedb65SAndre Fischer printf "downloading %d missing extension%s\n", $#missing+1, $#missing>0 ? "s" : ""; 413*c6dedb65SAndre Fischer if ( ! -d $download_path) 414*c6dedb65SAndre Fischer { 415*c6dedb65SAndre Fischer mkdir File::Spec->catpath($download_path, "tmp") 416*c6dedb65SAndre Fischer || die "can not create tmp subdirectory of $download_path"; 417*c6dedb65SAndre Fischer } 418*c6dedb65SAndre Fischer } 419*c6dedb65SAndre Fischer else 420*c6dedb65SAndre Fischer { 421*c6dedb65SAndre Fischer print "all downloadable extensions present\n"; 422*c6dedb65SAndre Fischer return; 423*c6dedb65SAndre Fischer } 424*c6dedb65SAndre Fischer 425*c6dedb65SAndre Fischer # Download the missing files. 426*c6dedb65SAndre Fischer for my $entry (@missing) 427*c6dedb65SAndre Fischer { 428*c6dedb65SAndre Fischer my ($protocol, $name, $URL, $md5sum) = @{$entry}; 429*c6dedb65SAndre Fischer 430*c6dedb65SAndre Fischer # Open a .part file for writing. 431*c6dedb65SAndre Fischer my $filename = File::Spec->catfile($download_path, $name); 432*c6dedb65SAndre Fischer my $temporary_filename = $filename . ".part"; 433*c6dedb65SAndre Fischer open my $out, ">$temporary_filename"; 434*c6dedb65SAndre Fischer binmode($out); 435*c6dedb65SAndre Fischer 436*c6dedb65SAndre Fischer # Prepare md5 437*c6dedb65SAndre Fischer my $md5 = Digest::MD5->new(); 438*c6dedb65SAndre Fischer 439*c6dedb65SAndre Fischer # Download the extension. 440*c6dedb65SAndre Fischer my $agent = LWP::UserAgent->new(); 441*c6dedb65SAndre Fischer $agent->timeout(10); 442*c6dedb65SAndre Fischer $agent->show_progress(1); 443*c6dedb65SAndre Fischer $agent->add_handler('response_data' 444*c6dedb65SAndre Fischer => sub{ 445*c6dedb65SAndre Fischer my($response,$agent,$h,$data)=@_; 446*c6dedb65SAndre Fischer print $out $data; 447*c6dedb65SAndre Fischer $md5->add($data); 448*c6dedb65SAndre Fischer }); 449*c6dedb65SAndre Fischer my $response = $agent->get($URL); 450*c6dedb65SAndre Fischer close $out; 451*c6dedb65SAndre Fischer 452*c6dedb65SAndre Fischer # When download was successfull then check the md5 checksum and rename the .part file 453*c6dedb65SAndre Fischer # into the actual extension name. 454*c6dedb65SAndre Fischer if ($response->is_success()) 455*c6dedb65SAndre Fischer { 456*c6dedb65SAndre Fischer if (defined $md5sum && length($md5sum)==32) 457*c6dedb65SAndre Fischer { 458*c6dedb65SAndre Fischer if ($md5sum eq $md5->digest()) 459*c6dedb65SAndre Fischer { 460*c6dedb65SAndre Fischer print "md5 is OK\n"; 461*c6dedb65SAndre Fischer } 462*c6dedb65SAndre Fischer else 463*c6dedb65SAndre Fischer { 464*c6dedb65SAndre Fischer unlink($temporary_filename); 465*c6dedb65SAndre Fischer die "downloaded file has the wrong md5 checksum"; 466*c6dedb65SAndre Fischer } 467*c6dedb65SAndre Fischer } 468*c6dedb65SAndre Fischer 469*c6dedb65SAndre Fischer rename($temporary_filename, $filename) || die "can not rename $temporary_filename to $filename"; 470*c6dedb65SAndre Fischer } 471*c6dedb65SAndre Fischer else 472*c6dedb65SAndre Fischer { 473*c6dedb65SAndre Fischer die "failed to download $URL"; 474*c6dedb65SAndre Fischer } 475*c6dedb65SAndre Fischer } 476*c6dedb65SAndre Fischer} 477*c6dedb65SAndre Fischer 478*c6dedb65SAndre Fischer 479*c6dedb65SAndre Fischer 480*c6dedb65SAndre Fischer 481*c6dedb65SAndre Fischer=head3 DownloadExtensions 482*c6dedb65SAndre Fischer This function is intended to be called during bootstrapping. It extracts the set of extensions 483*c6dedb65SAndre Fischer that will be used later, when the installation sets are built. 484*c6dedb65SAndre Fischer=cut 485*c6dedb65SAndre Fischersub DownloadExtensions () 486*c6dedb65SAndre Fischer{ 487*c6dedb65SAndre Fischer my $full_file_name = Prepare(); 488*c6dedb65SAndre Fischer my @urls = ParseExtensionsLst($full_file_name, []); 489*c6dedb65SAndre Fischer Download(@urls); 490*c6dedb65SAndre Fischer} 491*c6dedb65SAndre Fischer 492*c6dedb65SAndre Fischer 493*c6dedb65SAndre Fischer 494*c6dedb65SAndre Fischer 495*c6dedb65SAndre Fischer=head3 GetExtensionList 496*c6dedb65SAndre Fischer This function is intended to be called when installation sets are built. 497*c6dedb65SAndre Fischer It expects two arguments: 498*c6dedb65SAndre Fischer - A protocol selector. Http URLs reference remotely located 499*c6dedb65SAndre Fischer extensions that will be bundled as-is into the installation 500*c6dedb65SAndre Fischer sets due to legal reasons. They are installed on first start 501*c6dedb65SAndre Fischer of the office. 502*c6dedb65SAndre Fischer File URLs reference extensions whose source code is part of 503*c6dedb65SAndre Fischer the repository. They are pre-registered when installation 504*c6dedb65SAndre Fischer sets are created. Their installation is finished when the 505*c6dedb65SAndre Fischer office is first started. 506*c6dedb65SAndre Fischer - A set of languages. This set determines which extensions 507*c6dedb65SAndre Fischer are returned and then included in an installation set. 508*c6dedb65SAndre Fischer=cut 509*c6dedb65SAndre Fischersub GetExtensionList ($@) 510*c6dedb65SAndre Fischer{ 511*c6dedb65SAndre Fischer my $protocol_selector = shift; 512*c6dedb65SAndre Fischer my @language_list = @_; 513*c6dedb65SAndre Fischer 514*c6dedb65SAndre Fischer my $full_file_name = Prepare(); 515*c6dedb65SAndre Fischer my @urls = ParseExtensionsLst($full_file_name, \@language_list); 516*c6dedb65SAndre Fischer 517*c6dedb65SAndre Fischer my @result = (); 518*c6dedb65SAndre Fischer for my $entry (@urls) 519*c6dedb65SAndre Fischer { 520*c6dedb65SAndre Fischer my ($protocol, $name, $URL, $md5sum) = @{$entry}; 521*c6dedb65SAndre Fischer if ($protocol =~ /^$protocol_selector$/) 522*c6dedb65SAndre Fischer { 523*c6dedb65SAndre Fischer push @result, $name; 524*c6dedb65SAndre Fischer } 525*c6dedb65SAndre Fischer } 526*c6dedb65SAndre Fischer 527*c6dedb65SAndre Fischer return @result; 528*c6dedb65SAndre Fischer} 529*c6dedb65SAndre Fischer 530*c6dedb65SAndre Fischer 531*c6dedb65SAndre Fischer1; 532