Upgrade to Archive-Extract-0.26
Steve Peters [Mon, 28 Jan 2008 20:04:40 +0000 (20:04 +0000)]
p4raw-id: //depot/perl@33098

MANIFEST
lib/Archive/Extract.pm
lib/Archive/Extract/t/01_Archive-Extract.t
lib/Archive/Extract/t/src/x.lzma.packed [new file with mode: 0644]

index e251bb4..2c3dd58 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1410,6 +1410,7 @@ lib/Archive/Extract/t/src/double_dir.zip.packed   Archive::Extract tests
 lib/Archive/Extract/t/src/x.bz2.packed Archive::Extract tests
 lib/Archive/Extract/t/src/x.gz.packed  Archive::Extract tests
 lib/Archive/Extract/t/src/x.jar.packed Archive::Extract tests
+lib/Archive/Extract/t/src/x.lzma.packed        Archive::Extract tests
 lib/Archive/Extract/t/src/x.par.packed Archive::Extract tests
 lib/Archive/Extract/t/src/x.tar.gz.packed      Archive::Extract tests
 lib/Archive/Extract/t/src/x.tar.packed Archive::Extract tests
index 1aafd23..d0cba4e 100644 (file)
@@ -28,14 +28,15 @@ use constant ZIP            => 'zip';
 use constant BZ2            => 'bz2';
 use constant TBZ            => 'tbz';
 use constant Z              => 'Z';
+use constant LZMA           => 'lzma';
 
 use vars qw[$VERSION $PREFER_BIN $PROGRAMS $WARN $DEBUG];
 
-$VERSION        = '0.24';
+$VERSION        = '0.26';
 $PREFER_BIN     = 0;
 $WARN           = 1;
 $DEBUG          = 0;
-my @Types       = ( TGZ, TAR, GZ, ZIP, BZ2, TBZ, Z ); # same as all constants
+my @Types       = ( TGZ, TAR, GZ, ZIP, BZ2, TBZ, Z, LZMA ); # same as all constants
 
 local $Params::Check::VERBOSE = $Params::Check::VERBOSE = 1;
 
@@ -75,6 +76,7 @@ Archive::Extract - A generic archive extracting mechanism
     $ae->is_zip;    # is it a .zip file?
     $ae->is_bz2;    # is it a .bz2 file?
     $ae->is_tbz;    # is it a .tar.bz2 or .tbz file?
+    $ae->is_lzma;   # is it a .lzma file?
 
     ### absolute path to the archive you provided ###
     $ae->archive;
@@ -84,13 +86,14 @@ Archive::Extract - A generic archive extracting mechanism
     $ae->bin_gzip    # path to /bin/gzip, if found
     $ae->bin_unzip   # path to /bin/unzip, if found
     $ae->bin_bunzip2 # path to /bin/bunzip2 if found
+    $ae->bin_unlzma  # path to /bin/unlzma if found
 
 =head1 DESCRIPTION
 
 Archive::Extract is a generic archive extraction mechanism.
 
 It allows you to extract any archive file of the type .tar, .tar.gz,
-.gz, .Z, tar.bz2, .tbz, .bz2 or .zip without having to worry how it 
+.gz, .Z, tar.bz2, .tbz, .bz2, .zip or .lzma without having to worry how it 
 does so, or use different interfaces for each type by using either 
 perl modules, or commandline tools on your system.
 
@@ -101,7 +104,7 @@ See the C<HOW IT WORKS> section further down for details.
 
 ### see what /bin/programs are available ###
 $PROGRAMS = {};
-for my $pgm (qw[tar unzip gzip bunzip2 uncompress]) {
+for my $pgm (qw[tar unzip gzip bunzip2 uncompress unlzma]) {
     $PROGRAMS->{$pgm} = can_run($pgm);
 }
 
@@ -114,6 +117,7 @@ my $Mapping = {
     is_tbz  => '_untar',
     is_bz2  => '_bunzip2',
     is_Z    => '_uncompress',
+    is_lzma => '_unlzma',
 };
 
 {
@@ -183,6 +187,11 @@ Corresponds to a C<.bz2> suffix.
 Bzip2 compressed tar file, as produced by, for exmample C</bin/tar -j>.
 Corresponds to a C<.tbz> or C<.tar.bz2> suffix.
 
+=item lzma
+
+Lzma compressed file, as produced by C</bin/lzma>.
+Corresponds to a C<.lzma> suffix.
+
 =back
 
 Returns a C<Archive::Extract> object on success, or false on failure.
@@ -209,6 +218,7 @@ Returns a C<Archive::Extract> object on success, or false on failure.
                 $ar =~ /.+?\.(?:tbz2?|tar\.bz2?)$/i ? TBZ   :
                 $ar =~ /.+?\.bz2$/i                 ? BZ2   :
                 $ar =~ /.+?\.Z$/                    ? Z     :
+                $ar =~ /.+?\.lzma$/                 ? LZMA  :
                 '';
 
         }
@@ -283,9 +293,9 @@ sub extract {
     ### to.
     my $dir;
     {   ### a foo.gz file
-        if( $self->is_gz or $self->is_bz2 or $self->is_Z) {
+        if( $self->is_gz or $self->is_bz2 or $self->is_Z or $self->is_lzma ) {
     
-            my $cp = $self->archive; $cp =~ s/\.(?:gz|bz2?|Z)$//i;
+            my $cp = $self->archive; $cp =~ s/\.(?:gz|bz2?|Z|lzma)$//i;
         
             ### to is a dir?
             if ( -d $to ) {
@@ -418,6 +428,11 @@ See the C<new()> method for details.
 Returns true if the file is of type C<.zip>.
 See the C<new()> method for details.
 
+=head2 $ae->is_lzma
+
+Returns true if the file is of type C<.lzma>.
+See the C<new()> method for details.
+
 =cut
 
 ### quick check methods ###
@@ -428,6 +443,7 @@ sub is_zip  { return $_[0]->type eq ZIP }
 sub is_tbz  { return $_[0]->type eq TBZ }
 sub is_bz2  { return $_[0]->type eq BZ2 }
 sub is_Z    { return $_[0]->type eq Z   }
+sub is_lzma { return $_[0]->type eq LZMA }
 
 =pod
 
@@ -443,6 +459,10 @@ Returns the full path to your gzip binary, if found
 
 Returns the full path to your unzip binary, if found
 
+=head2 $ae->bin_unlzma
+
+Returns the full path to your unlzma binary, if found
+
 =cut
 
 ### paths to commandline tools ###
@@ -452,6 +472,8 @@ sub bin_tar         { return $PROGRAMS->{'tar'}     if $PROGRAMS->{'tar'}   }
 sub bin_bunzip2     { return $PROGRAMS->{'bunzip2'} if $PROGRAMS->{'bunzip2'} }
 sub bin_uncompress  { return $PROGRAMS->{'uncompress'} 
                                                  if $PROGRAMS->{'uncompress'} }
+sub bin_unlzma      { return $PROGRAMS->{'unlzma'}  if $PROGRAMS->{'unlzma'} }
+
 =head2 $bool = $ae->have_old_bunzip2
 
 Older versions of C</bin/bunzip2>, from before the C<bunzip2 1.0> release,
@@ -478,8 +500,16 @@ sub have_old_bunzip2 {
     ### $ echo $?
     ### 1
     ### HATEFUL!
+    
+    ### double hateful: bunzip2 --version also hangs if input is a pipe
+    ### See #32370: Archive::Extract will hang if stdin is a pipe [+PATCH]
+    ### So, we have to provide *another* argument which is a fake filename,
+    ### just so it wont try to read from stdin to print it's version..
+    ### *sigh*
+    ### Even if the file exists, it won't clobber or change it.
     my $buffer;
-    scalar run( command => [$self->bin_bunzip2, '--version'],
+    scalar run( 
+         command => [$self->bin_bunzip2, '--version', 'NoSuchFile'],
          verbose => 0,
          buffer  => \$buffer
     );
@@ -499,7 +529,6 @@ sub have_old_bunzip2 {
 #
 #################################
 
-
 ### untar wrapper... goes to either Archive::Tar or /bin/tar
 ### depending on $PREFER_BIN
 sub _untar {
@@ -1141,6 +1170,96 @@ sub _bunzip2_cz2 {
 
 #################################
 #
+# unlzma code
+#
+#################################
+
+### unlzma wrapper... goes to either Compress::unLZMA or /bin/unlzma
+### depending on $PREFER_BIN
+sub _unlzma {
+    my $self = shift;
+
+    my @methods = qw[_unlzma_cz _unlzma_bin];
+       @methods = reverse @methods if $PREFER_BIN;
+
+    for my $method (@methods) {
+        $self->_extractor($method) && return 1 if $self->$method();
+    }
+
+    return $self->_error(loc("Unable to unlzma file '%1'", $self->archive));
+}
+
+sub _unlzma_bin {
+    my $self = shift;
+
+    ### check for /bin/unlzma -- we need it ###
+    return $self->_error(loc("No '%1' program found", '/bin/unlzma'))
+        unless $self->bin_unlzma;
+
+    my $fh = FileHandle->new('>'. $self->_gunzip_to) or
+        return $self->_error(loc("Could not open '%1' for writing: %2",
+                            $self->_gunzip_to, $! ));
+
+    my $cmd = [ $self->bin_unlzma, '-c', $self->archive ];
+
+    my $buffer;
+    unless( scalar run( command => $cmd,
+                        verbose => $DEBUG,
+                        buffer  => \$buffer )
+    ) {
+        return $self->_error(loc("Unable to unlzma '%1': %2",
+                                    $self->archive, $buffer));
+    }
+
+    ### no buffers available?
+    if( !IPC::Cmd->can_capture_buffer and !$buffer ) {
+        $self->_error( $self->_no_buffer_content( $self->archive ) );
+    }
+
+    print $fh $buffer if defined $buffer;
+
+    close $fh;
+
+    ### set what files where extract, and where they went ###
+    $self->files( [$self->_gunzip_to] );
+    $self->extract_path( File::Spec->rel2abs(cwd()) );
+
+    return 1;
+}
+
+sub _unlzma_cz {
+    my $self = shift;
+
+    my $use_list = { 'Compress::unLZMA' => '0.0' };
+    unless( can_load( modules => $use_list ) ) {
+        return $self->_error(loc("You do not have '%1' installed - Please " .
+                       "install it as soon as possible.", 'Compress::unLZMA'));
+    }
+
+    my $fh = FileHandle->new('>'. $self->_gunzip_to) or
+        return $self->_error(loc("Could not open '%1' for writing: %2",
+                            $self->_gunzip_to, $! ));
+
+    my $buffer;
+    $buffer = Compress::unLZMA::uncompressfile( $self->archive );
+    unless ( defined $buffer ) {
+        return $self->_error(loc("Could not unlzma '%1': %2",
+                                    $self->archive, $@));
+    }
+
+    print $fh $buffer if defined $buffer;
+
+    close $fh;
+
+    ### set what files where extract, and where they went ###
+    $self->files( [$self->_gunzip_to] );
+    $self->extract_path( File::Spec->rel2abs(cwd()) );
+
+    return 1;
+}
+
+#################################
+#
 # Error code
 #
 #################################
@@ -1208,7 +1327,7 @@ C<Archive::Extract> will not be able to extract the archive for you.
 
 C<Archive::Extract> can use either pure perl modules or command line
 programs under the hood. Some of the pure perl modules (like 
-C<Archive::Tar> take the entire contents of the archive into memory,
+C<Archive::Tar> and Compress::unLZMA) take the entire contents of the archive into memory,
 which may not be feasible on your system. Consider setting the global
 variable C<$Archive::Extract::PREFER_BIN> to C<1>, which will prefer
 the use of command line programs and won't consume so much memory.
index 4595a35..90abf20 100644 (file)
@@ -58,6 +58,7 @@ use_ok($Class);
 $Archive::Extract::VERBOSE  = $Archive::Extract::VERBOSE = $Debug;
 $Archive::Extract::WARN     = $Archive::Extract::WARN    = $Debug ? 1 : 0;
 
+
 my $tmpl = {
     ### plain files
     'x.bz2' => {    programs    => [qw[bunzip2]],
@@ -105,6 +106,11 @@ my $tmpl = {
                     method      => 'is_zip',
                     outfile     => 'a',
                 },                
+    'x.lzma' => {   programs    => [qw[unlzma]],
+                    modules     => [qw[Compress::unLZMA]],
+                    method      => 'is_lzma',
+                    outfile     => 'a',
+                },
     ### with a directory
     'y.tbz'     => {    programs    => [qw[bunzip2 tar]],
                         modules     => [qw[Archive::Tar 
@@ -291,7 +297,7 @@ for my $switch (0,1) {
         ### where to extract to -- try both dir and file for gz files
         ### XXX test me!
         #my @outs = $ae->is_gz ? ($abs_path, $OutDir) : ($OutDir);
-        my @outs = $ae->is_gz || $ae->is_bz2 || $ae->is_Z 
+        my @outs = $ae->is_gz || $ae->is_bz2 || $ae->is_Z || $ae->is_lzma
                         ? ($abs_path) 
                         : ($OutDir);
 
diff --git a/lib/Archive/Extract/t/src/x.lzma.packed b/lib/Archive/Extract/t/src/x.lzma.packed
new file mode 100644 (file)
index 0000000..5558011
--- /dev/null
@@ -0,0 +1,207 @@
+#########################################################################
+This is a binary file that was packed with the 'uupacktool.pl' which
+is included in the Perl distribution.
+
+To unpack this file use the following command:
+
+     uupacktool.pl -u lib/Archive/Extract/t/src/x.lzma.packed lib/Archive/Extract/t/src/x.lzma
+
+To recreate it use the following command:
+
+     uupacktool.pl -p lib/Archive/Extract/t/src/x.lzma lib/Archive/Extract/t/src/x.lzma.packed
+
+Created at Mon Jan 28 14:00:38 2008
+#########################################################################
+__UU__
+M(R,C(R,C(R,C(R,C(R,C(R,C(R,C(R,C(R,C(R,C(R,C(R,C(R,C(R,C(R,C
+M(R,C(R,C(R,C(R,C(R,C(R,C(R,C(R,C(R,C(PI4:&ES(&ES(&$@8FEN87)Y
+M(&9I;&4@=&AA="!W87,@<&%C:V5D('=I=&@@=&AE("=U=7!A8VMT;V]L+G!L
+M)R!W:&EC:`II<R!I;F-L=61E9"!I;B!T:&4@4&5R;"!D:7-T<FEB=71I;VXN
+M"@I4;R!U;G!A8VL@=&AI<R!F:6QE('5S92!T:&4@9F]L;&]W:6YG(&-O;6UA
+M;F0Z"@H@("`@('5U<&%C:W1O;VPN<&P@+74@;&EB+T%R8VAI=F4O17AT<F%C
+M="]T+W-R8R]X+FQZ;6$@=75P86-K=&]O;"YP;`H*5&\@<F5C<F5A=&4@:70@
+M=7-E('1H92!F;VQL;W=I;F<@8V]M;6%N9#H*"B`@("`@=75P86-K=&]O;"YP
+M;"`M<"!U=7!A8VMT;V]L+G!L(&QI8B]!<F-H:79E+T5X=')A8W0O="]S<F,O
+M>"YL>FUA"@I#<F5A=&5D(&%T($UO;B!*86X@,C@@,3,Z-3DZ,S<@,C`P.`HC
+M(R,C(R,C(R,C(R,C(R,C(R,C(R,C(R,C(R,C(R,C(R,C(R,C(R,C(R,C(R,C
+M(R,C(R,C(R,C(R,C(R,C(R,C(R,C(R,C(R,C"E]?555?7PI-*%(E4#DW*4PB
+M0$E5/%8T0#Q7,5(Z-BU4+E!)53Q6-$`]5B52.T9%3CE7+%LB1S53.3(A)SDW
+M,4\\)S!:"DTN1%%/.T8\6R)'-5,Y,B$F.C9112Y#22(X-RU%.T8E33DS3"H]
+M-RU%*"0Y23LF-%HN12U0.38L6R)`22(*33$T/2DS0B%;(D)@0"@B(4DY0F!(
+M*259+R@F-5$H(CTV,S4L1RHR(5LB0F!`*")@0"@B8$`\1C51/39%4@I-.3(A
+M-C,U+%HN1#E).R8U4SPF-4,N4$A`*")@0"@B8$`H)D5-/"9=4CTB(38S-2Q:
+M+D0Y23LF-5,\)C5#"DTN4$A`*")@0#\P25TB0$DG.3<Q3SPG,%HN1%%/.T8\
+M6BY$+4\[1CE).5<U4CDR0$<[1ET_.C8]3CM7*44*33=6+4$\5C1'*C-,*B)&
+M754\0F!$,R8E4STE-5`Y)B54.3)@72@B52TH(C!0+E!(*CQ7-4(H)D%!.T8Q
+M3`I-.35=1CHV444H)TPJ*")@0"@F55DH(C%//"<Q4R@B8$`H(U1`/%9!23E'
+M,%LB0F!`*"(A33XR8$0Y1D5,"DTY,F!`*")@72@G+4@Z-CE4*"9=4B@F,4DY
+M,F!",T8U13DB(48Z-E%%-R980BM"(54\5B5'.3)`22Y02$`*32@B8$`[-T1`
+M*29=53TF.4D[)C1`+S(A4SHF148](B%</R)@1RE33"HH(F!`*"(Q1CHV444H
+M(U1`/4954PI--U8M2#DV+4LW5EE!.S8T2"DF.4D[)C1)*"9%1B@B,3XS4B%%
+M/#)@1S5$53,I4TPJ*")@0"@F55DH(C%-"DT[5C%%*")@0"@C5$`J)RU4.#<P
+M2"DF.4D[)C1)*C5,4C<R8$8H(V!7+5,\5RY02"HH(F!`*"9=4#DV6$`*33LW
+M1$`I)CE(*R)@0B\B*$PH(C%&.C9112)"8$`H(F!`*")@0#M7*$`Y)EQ`/E(A
+M5S@W*4XH(BDC.U<U3`I-.2(A3CM7,$`[5R%%.T(A23M'(54](B%&.C9112@B
+M,48Z-E%%+D)@1"@R*%LH)C58.C<P0"PB(5TN4$A`"DTH(F!`.S=$0"DG+50\
+M0F!=*"8Q3R@G3$`[)EU#.#900"DB7%LH(U!$.49`7B@G5%LB0$A`*")@0"A2
+M+$,*32@G-4X\)B5#.E-<*B@B8$`H)E59*"(Q3STW,5,])RA;(D)@0"@B(4DY
+M0D!`*29=4#TG+$TO1TU5/S)@20I-*"=,*B@B8$`H(F!`*"(A23E"0$`H,C%/
+M/3<Q1CHV444H(D1`/E!(0"@B8$`H(F!`*")@0"@B8$0[5S54"DTY1D5,.3)@
+M72@B,48Z-E%%+E!(0"@B8$`H(F!`*")@0"@B8$0[5S54.49%3#DR8%T_0B%3
+M*U503CPF)4,*33I6-40W)TA/*U-,*B@B8$`H(F!`*"(A72)"8$`H(F!`*")@
+M0#LW1$`J(C%(.38E1"LB8$0X1EU$/C)$0`I-+S(A4SPF44D](F!/-U5=-34U
+M73\W)EA/*R)@1#Q7,5(N4$A`*")@0"@B8$`H)C%).3)@0C!6)4XI5S!`"DT]
+M-EE0.#8M2R@F54$[)CE//$9513DB(40X-S%!*"9%3B@B/$0Y1D5,.3(]/#M"
+M*"HH(F!`*")@0"@B8$`*32@B8$`Z-CA`*#(Q2#DV)40N4$A`*")@0"@B8$`H
+M(C%//3<Q4STG*$`O,B%5.T<A03A63$`I5S1'*R)@1`I-.$9=1#XS3"HB0F!`
+M*"(A72@F-4P\5C1`/E!(0"@B8$`H(F!`*"(Q3STW,48Z-E%%*"=17"\R8$0Y
+M1D5,"DTY,F!.*"(\3CPF)4,Z5C5$*5-,*B)"8$`H(F!`*")@0#LW1$`I)E5%
+M*"-40#A&)5,Y-EE!.S8T2"DC8$D*32Y02"HH(F!`*")@0"@B8$0[5S54/%<Q
+M4B@C5$`O(U!",31=)C!$434T1"A"*")80#PF)4,Z4F!'/3(\3`I-*"(Q4STG
+M*%LB0BQ#*%(L0RA2+$,H4BQ#*%(L0RA2+$,H4BQ#*%(L0RA2+$,H4BQ#*%(L
+M0RA2+$,H4BQ#"DTH4BQ#*%(L0RA2+$,H4BQ#*%(L0RA2+$,H4BQ#*%(L0RA2
+M+$,H4BQ#*%(L0RA2+"HU)D%)/%(A23Q2(4$*32@F*4D[1B52/C(A1CHV444H
+M)S%(.#<P0#U6)5,H)R%!.%9-13DB(5<Z-S%(*"<Q2#DR8$<]-S50.#8M2PI-
+M/29=3SLB65`[(CQ`/59!23A60"HZ-RQ`.C990SLG-40Y-C!`.C980#TF044H
+M)2%%/$900#DF15,])RE)"DTX1S54.C9=3BM`2"HU)EQ`/3994#@V+4LH)S%(
+M.C<L0#E&14PY,B%5/%8T0#TF044H)CE/.R913SU614X*33E2(4,[5E5-.#99
+M1"Y`2"HH(F!`*")@1#LV-$`K-S1`*29=53TF.4D[)C1`*28Y23LF-"HB13%/
+M*"<I10I-.%<I13@W,44H)D54*"<U4SDR(50Z)C1`.49=3#LF75<Z-EE'*"8M
+M3SLV54$[1C!:(D!(0"@B8$`H(C%-"DTY,F!-/")@1#E&14PY,F!$.U<U5#E&
+M14PY,$@J,%<I13@W,44Y(B%!/2(A8#Y535,X5B5,.#<H0#LF74,*33@V450Z
+M-E5%-S=4*BA2+$,H4BQ#*%(L0RA2+$,H4BQ#*%(L0RA2+$,H4BQ#*%(L0RA2
+M+$,H4BQ#*%(L0PI-*%(L0RA2+$,H4BQ#*%(L0RA2+$,H4BQ#*%(L0RA2+$,H
+M4BQ#*%(L0RA2+$,H4BQ#*%!)/S=5-34W55PJ"DTQ-%TF,$11-31$*"HH(F!`
+M*"=4*B)"8$`H(F!#*%(L0#M7-50\)S54*"<Q2#DR(48Z-E%%(D)@0"@B(4D*
+M33E"0$`I)EU0/2<L32]'3$<\4CU=*")$0#Y02$`H(F!`*")@0"@G(5(Z-EE4
+M*"4M-#$D734U(F!$.U<U5`I-/%<Q4BY02$`H(F!`/S(A13LG+44H)TPJ*")@
+M0"@B8$`H(F!$.U<U5#E&14PY,F!=*"4Y+3132%HQ1D5,"DTY-RU0.38L6BY'
+M.4T\5D5&/C)`1#M7-50Y1D5,.3)$0#HV.$`I)5DO*"8U42@B/38S-2Q'+E!(
+M0"@B8$`*32@B8$`H)R%2.C995"@B*3<\1D54.C991R@B,48Z-E%%*"9%3CTF
+M7$`I)EU5/28Y23LF-3P[0BA`.C8X0`I-*29=4#TG+$TO1TQ'/4(]72Y02$`H
+M(F!`*")@0"@F75`Y-EA`.S=$0"DF754])CE(*R)@0B]"*$PH(C%/"DT]-S%&
+M.C9112)"8$`H(F!`*")@0"@B8$`H)EU2*"8Q3R@G3$`]5B52.T)@0C!6754[
+M)C!`.T9=5"@F75`*33DV6$`I)EU5/28Y23LF-$`Y1EU2*"<]4CHW,4D[1CQ:
+M*"(P02A#3$`Y-T%)/2)@4"@G5%LB0F!`*")@0`I-*")@0#A&14X[-EU$.3)@
+M1#M7-50Y1D!;(D)@0"@B8$`H(F!`*%(L0R@B,4\]-S%3/2<H0#LV14<Z)S!`
+M"DTX1C1`.3954#TG1$PH)D5&*"<Q2#DR(48Z-E%%*"<]03Q2(44[-R%4/C!(
+M0"@B8$`H(F!`*"<A4CHV650*32@B,4\]-S%&.B)@1#M7-50\5S%2*"9%1B@B
+M,4\]-S%3/2<H6R)"8$`H(F!`*")@0#A644\\5C1`*29=50I-/28Y2"Y02"HH
+M(F!`*")@0"@B(4,Z)E5/.2)@1#LV740Y,E!`*29=53TF.4D[)C1;(D)@0"@B
+M(5TB0$A`"DTH(F!`*%(L0R@F,44[)C54.3(A4SM7-5(X5C1`.49%3#DS7"HH
+M(F!`*"9%1BHB8$0[5R%4/%)47CY2/20*32E75$`X-EE$*"(Q1CHV444H)EE%
+M*"(Q3STW,48Z-E%%*")$0#Y02$`H(F!`*")@0"@C)$`]5D%).R8T0`I-/399
+M3#HV64LH(C%&.C9112Y02$`H(F!`/S!)72)`25,]-BA`.$<U3#I575`\1EU#
+M.3<M4R@G3"HH(F!`"DTH)E59*"(Q3SPG,5,H(U1`/%9!23E',%LB0F!`*"(A
+M33XR8$0S-B5..C8Y13Q7,$`O,F!$.U<A5#Q25%X*33Y2/4TI5U1;(D!(0"@B
+M8$`[5R%%.T(A33XR8$0Y1D!,*"(H7"A"4$`I)%5!.T9%1CDW+50H)EU2*"8Q
+M20I-.3)@0C!6754[)C!`.T9=5"@F75`Y-EA`*5(Q+3@V64DY1C53/2(\6BDB
+M)$(N4$@J*")@0"@G(5(Z-EE4"DTH(BDR.38E1#HV64<H(C$M.#9923E&-5,]
+M)5%.*$!(0"@B8$`H(F!`*")@0"@B(4DY0F!$.U<A5#Q25%X*33Y2/58I5U1;
+M(D!(0"@B8$`[-T1`*28M3STV650H(U1`+"-,*B@B8$`H)E59*"(Q3#HV644\
+M4F!=*"-@6PI-(D)@0"@B(5<Z)D5,.3)`0#LW1$`I)E%).T8T0"\R8%PI)CE(
+M+T)@22@G3"HH(F!`*")@0"@B(4,Z)EU-"DT\(F!$.R9%3CDS3"HH(F!`*")@
+M0"@B(4T^,F!(*28Y23LF-$DH(U1`/%<A3#HW,$`K55%3*E)<3"@B,4P*33HV
+M644N4$@J*")@0"@B8$`H(F!$.R9%3CDW+$LJ4TPJ(D)@0"@B8$`H(F!`.T8U
+M6#TB(54[1E%%/%<L0`I-*28Y23LF-$`O-UA`*U503CPF)4,Z5C5$*U-,*B)"
+M8$`H(F!`*")@0"DF+4\]-EE4*E),6R)`2$`H(F!`"DTH(F!`*"9562@B,4\]
+M-S!`+S)@1#E&14PY,TPJ*")@0"@B8$`H(F!$.U<U5"@C55XH)RQ/-R)94#@V
+M+4L*33DV,3P^0EQ/+E!(0"@B8$`H(F!`*"(Q3STW,$`O,B%6.S<M/SA6044X
+M5DT_.T8E33DR0$0[5S54*C(A20I-.4)@1#=$7$`Y-R1`*54Y+312/%LB0$A`
+M*")@0"@B8$`H(BQ#*%(A53M'(4$X5DPJ*")@0"@B8$`H(B%)"DTY0D!`*#(Q
+M3SPG,5,K,UE;*58L1S\R8$DH)TPJ*")@0"@B8$`H(F!`*")@0"HB8$0[5S54
+M*R)@1#E&14P*33DR8$DH(U1`*B)@1#E&14PY,E!`*29=53TB8$DH)D5&*"(Q
+M3SPG,5,K,UE;*5=@1S\S3"HH(F!`*")@0`I-*")@0"@B8$`Z-CA`*B)512@B
+M,4\]-S!)*"=,*B@B8$`H(F!`*")@0"@B8$`H(F!`*"9562@B,4,Z)B5."DTY
+M5C5$*"-40"LT5$`W4TPJ*")@0"@B8$`H(F!`*")@0"@B8$`H)D5&*")`1#A6
+M04$[1CU%.2)@7"@B,2P*33@W+50U-R%$.#<Q12@F)4XY(F!$.%9!03M&/44Y
+M(F!<*")5+2@B,48Z-E%%*C(A6R)"8$`H(F!`*")@0`I-*")@0"@B8$`H(F!`
+M*")@0#PG*4D[1S!`*$4M2SHW(5`Z-EE'*"(\1#E&14PY,CQ`.#<L0"E2,4\]
+M-S!'"DTH)D53*"<U4"LW,4\K-C%!/28T3C<F6$(B0F!`*")@0"@B8$`H(F!`
+M*")@0"@B8$`H(F!`*")@0"@F148*32@B,4\\)S%3*S-96RE7.$<_,TPJ*")@
+M0"@B8$`H(F!`*")@0"@B8$`H(F!`*"(A3CDW050N4$A`*")@0`I-*")@0"@B
+M8$`H(F!`*")@0#\P2$`H(F!`*")@0"@B8$`H(B%=(D)@0"@B8$`H(F!`*")@
+M0"@F04$[1C%,"DTY-5U&.C9112HB,4\\)S%3*R)@1#E&14PY,E!`*29=53TB
+M1%LB0F!`*")@0"@B8$`H(F!`*"<A4CHV650*32@B*2,[5EE6.3<I5#DV,$`I
+M4C%&.C9112E2(50[4F!'*29=53TB/3P[0B@J*")@0"@B8$`H(F!`*")@0`I-
+M*")@0"@F148H(C%//"<Q4RLS65LI5SA'/S-,*B)"8$`H(F!`*")@0"A2+$,H
+M)BU,.38E3B@G-5`B0F!`"DTH(F!`*")@0#\R(44[)RU%*"=,*B)"8$`H(F!`
+M*")@0"@B8$`H(BQ#*%(A1CHV444H)C58.C<M5#Q37"H*32@B8$`H(F!`*")@
+M0"@B8$`]-EE,.3<M4RHB8$TY,F!$.U<U5"@B1$`^4$A`*")@0"@B8$`H(F!`
+M*")@0`I-*")@0#PG*4D[1S!`*$0Y23LF-$`I4C%&.C9112E2(5<X-RQ`.T9=
+M5"@G-4X\)B5#.E8U1"@F14X])EQ`"DTI4C%//3<P1RM"(2,X-EA`.T9=5"@G
+M*44[-EU6.3)9/#M"*%LB0$A`*")@0"@B8$`H(F!`*")@0RA2+$`*33Q&-4T[
+M5SE%*"9%5")"8$`H(F!`*")@0"@B8$`H)U1`.3914SDR(5LB0F!`*")@0"@B
+M8$`H(F!`*")@0`I-*"(A4#Q&14X](F!"-$8U33M7.4D[1CQ`*5(Q3STW,$<W
+M)EA"+E!(0"@B8$`H(F!`*")@0"@B8$`H(F!`"DTL,B%7.B9%3#DR(54[1E%)
+M.T9,0"DF754](TPJ*")@0"@B8$`H(F!`*")@0#\P2$`H(F!`*")@0"@G5"H*
+M32@B8$`H)U0J*")@0"@G(5(Z-EE4*"(I)CM7-4XY(F!$.%9=53M',$`Y1D5,
+M.3<L0#TF7$`\)RE/.%8U4PI-/%(A3STW,$`[5CA`*29123M&-5,H)D5.*"(\
+M1#,V)4XZ-CE%/%<P1S<F6$(B0F!`*")@0"@B8$`H(F!`"DTH)D5&*"(Q3SPG
+M,5,K,UE;*5<X1S\S3"H_,$@J/%<U0B@G-5,X-CU%*"=,*B@B8$`H)RE%/2<U
+M4CM"(5$*33PU3"HU-RU!.58T6B@B,3XV(F!$+"(A.RLV,$`Y)D52-S(A.RLW
+M.3TH)4Q-.%540#92520W,F!-/"=030I-/3(A.SM7*4DY4B$[/"8E0SI6-40_
+M(E53-S(A7"@B54TH)4U-.#9923E&-5,])54](D!(0"@B8$`R)B5."DTY)E%%
+M*"8I23M&)5(^,B%&.C9113Q2(4D[0B%3.U<U4CA6-$`])RE%.3)80#!6)4XH
+M)BE%*"<U4SDV,$`*33TF7$`\)B5#.E(A3SQ`2$`H(F!`/3994#@V+4LH)CE)
+M.R8U4R@F14XY)D56.C8Q23TV)4P[)T1`.U<H0`I-.#<L0#Q7(44X5D5&.C8U
+M1"@F*5DH)B1`.S8E3CHV.44\5S!`.49%3#DR6"HB1%U0/29%3SM'+%HB0F!`
+M"DTH(F!-/3)@0#4V65`X-BU+*"8Y23LF-5,H(D%$.38Y03TV450\4B%4.U)@
+M33TR(54[1E%%/%<L0"LW8$`*33HW+$`\5R%%.%9%1CHV-40J,$A`*")@0"LW
+M8$`H)2%!.%9,0#E&14PY-RPJ*")@0"@B54,H(B$C.R8U00I-.T(A53PB(4$[
+M)E!`/3994#@V+4LY-C!`.49%3#DW+$XH)$5-/"9123DW+$`K-E0J(D)@0"@B
+M8$TQ(F!`"DTQ)C5,.3<Q12@G+4\]-RE#.3(A1CHV444H)B5&/28U4B@F-4XX
+M5EU$.C991RM6,44X5EU$.C991R)`2$`*32@B8$`K-RQ`*"1=53TG(54](B%4
+M.U(A,S4D,2\U-3!`/$8E5#HF-5(H)S%(.#980#-5-30T)34T-U0Y*0I-,R0T
+M*B@B8$`H(E5-*"(A-3Q6-$`[-B5..C8Y13Q7,$`Y1D5,.3)00#HV.$`[1EU.
+M.3(A23Q2(44^)R%,"DTZ-BU)/29162@G(5([5SE).28U1"@F,44Y1B55.R<Q
+M4R@G,4\H(CTM,#19*3%$-3,U(CPJ(D)@0"@B8$T*33DB8$`P5D%!.T8]12@F
+M,4D\1C5#/29=4CXR(50[4B%$.C<H0#A&-48[5RE%*"<A4CM6+44\5RU).T8\
+M*@I-(D)@0"@B8$T]0F!`-$<U3B@G.44\1BE//%8U3#XP2$`H(F!`*S9`0"@D
+M,4D\5R%,.#=$0#TF04D\4B%("DTY-E%0*"9513Q7+4$Y5C0J-S-,*C\P2"H\
+M5S5"*"<Y33Q574,Z)C5#.E5=3C@V544H)TPJ(D(L0#0F)4,*33I6-40H)CE)
+M.R8U4R@G,44[1C!`/29<0#HF)58Y,B%-/3915#HW(4PY,B%$.U<Q4RLB(5<Z
+M)D5#.B(A5`I-.B8T0#!5*30S(B%-.#=$0#M7*$`[-B59*"993STB(4@X-EE$
+M.R8T*BA2(5`\1EU0.3<I3#XR4$`\5EQ`"DTX5EU./48U4CTB(50[4B%..#<Q
+M23U&-$`Y1EU2.S8E5"M"8$`P-EE$*"8Q13PF-4XY)D5..5(A3SM"(4@*33M7
+M/$`])D%%*"8E4CA604D]1C1`/58E4R)"+$`]-EE0.#8M2SDV,$PH)CE/.U)9
+M0C@W*$XX1B5:*"9500I-/C(A0CDR(48[5ET_.$8E4BM&*4$^0B%//$(A1CM6
+M7$XX1B52-U8I03Y"6$`H)%A.,$)80#4F04D\4B%#"DTZ)C5#.E<L0#E&75(B
+M0BQ`.3=!23Q7,44[1BU%*R(A4SM2(4D\4B%..U<P0#Q7-4D])B5".R8T0#@W
+M+$T*33HW+$`])EQ`.58U3CDW*4$])C1`,U0Q,RLS*$T\5B5&.3(A3C@V544\
+M4B%).T(A4#Q&-5`X-RE!/29%3PI-.T!(0R@F.4\\0B%&.C9112@F+5(Y-B54
+M.C9=3BM`2"HH(F!`*"9562@B,48Z-E%%*"-40#Q604DY1S!;"DTB0$A`*")@
+M0"DF.4D[)C1`+S(A-C,U+%HN1#E).R8U4SPF-4,N0TE6.S<M23E'1$@I)CE)
+M.R8T22Y02$`*32@B8$`\1C54/3<I3B@B,48Z-E%%*"9%1B@B544H(C%&.C91
+M12Y02"HH(F!`*"9562@B0$0]1EU,*R(Q1`I-.C<I4RLB,4(X-RU%*C)@72@D
+M.4D[)C1:+D4M4#DV+$TO1RU0.R9%5#PF)50Z(D!$.49%3#DR1%LB0F!`"DTH
+M(B%-/C)@1#TF55`H(U1`*28I03Q6-%LB0F!`*")@42@G/4@Z-E%%*"(Q5#LW
+M8$`O-UA`/%)<2#9563P*32M%5$LJ-5!.*B)82S<B6$XJ4D1/*2,E/RDC*$\N
+M4$A`*")@0#LW1$`I)S%2/C)@72@D.4D[)C1:+D4M4`I-.38L32]&+4$])R%!
+M/29`2"DG.4\[(E!`*28Q23Q'+$PH(C%4.S=@22Y02$`H(F!`/$8U5#TW*4XH
+M(C%4"DT\1T1`.C8X0"LV-$`I)S%2/C-,*B)"8$`H(F!$/2954"@C5$`I)BE!
+M/%8T6R)"8$`H(F!1*"<]2#HV444*32@B,50[-V!`+S=80#Q27$@K0DT\*T)8
+M2RHU4$XJ)4T^-R)9/2I21$\I(R4_*2,H3RY02$`H(F!`*2<Q4@I-/C)@72@D
+M.4D[)C1:+D4M4#DV+$TO1BU!/2<A03TF0$@I)SE/.R)00"DF,4D\1RQ,*"(Q
+M5#LW8$DN4$A`"DTH(F!`/$8U5#TW*4XH(C%4/$=$0#HV.$`K-C1`*2<Q4CXS
+M3"HB0F!`*"(A4CDW,54\1EA`*28Y23LF-%L*32)'5"HB1E59*"(Q3SPG,5,H
+M(U1`/E=46R)$/44])%U0/29%3SM'+$@I)EU0/2<L3"E7-$<K(CU0*5)01PI-
+M.%(\3"@B/20I4E!`*5946CQ2/$PI5RQ'*R(]1"\W+$<K(CU6*5)01SHB/$DN
+M4$@J.29%12@B*2,X-EA'"DT](B%0.#8M2R@F)4XY(B%5.T<A03A63$`X-S!`
+M/29!12@G+4$[-C1`/29%33DR)3P[0BA,*"<U4S@V/44*32HB1"HH(F!`*"9%
+M1B@B,4\\)S%3*S-96RE7-$<_,F!&*4)@1#M7(50\4E1>/E(]4"E75%LB1C%)
+M.3(A50I-/%8E1SDR0$DH)D5&*"(Q3SPG,5,K,UE;*59`1S\S3"HB1D5&*")`
+M0"DF75`])RQ-+T=,1SDB/5TH(D1`"DT^4$A`*")@0#A6040Z-RA`*29=4#TG
+M+$TO1TQ'.2(]72)"8$`H(F!`*")@0#M7*$`Y)D5%*"(I)C@V14P*33DV,$`]
+M)EQ`.%9!1#HW*$`])EQ`*5(Q3SPG,5,K,UE;*58P1S\R/%HI(B1"+E!)72)"
+M,4\\)S%3*S-96PI-*5<T1S\R8%TH(R1`.C8X0"@R,4\\)S%3*S-96RE78$<_
+M,TPJ.$9%3CLV740Y,B$S-20Q+S4U,$`Z-CA`"DTI)EU0/2<L32]'3$<\4CU=
+M+E!)23E"8$@H)C58.C<M5#Q28$0[5R%4/%)47CY2/4TI5U1`.U<H0#DW04D*
+M33Q7,5,H(C%//"<Q4RLS65LI5BQ'/S)@22@G3"HH(F!`*"(Q3SPG,5,K,UE;
+M*5941S\R(5P_(U1`*$15(0I-,T1%)C$U+30H0TPJ*")@0"@F*54[)DT_/"<I
+M3SA6-5,\4D!$.U<A5#Q21%LB0F!`*"(A13XF150J(V!)"DTN4$E=*"8U3#Q6
+M-$`^4$A`*")@0#HV.$`J)"$A-$0]-BHR(5LB0F!`*")@0"@B8$`Z)B5..291
+M13=6.4D*33LF-$@I)EU0/2<L3"@D(2$T1#TV*C-,*B@B8$`H)U1`.3914SDR
+M(5LB0F!`*")@0"@B8$`Y)D5%*"(I+@I-.U(A1CHV444H)S%/*"<A4CM6+44\
+M5RQ`/%<A13A6148Z-C5$*#513BA"4$`]-RU!.58T2"HS3"HH(F!`"D$H)U0J
+I*")@0"@F-5@Z-S!(+")$6R)'5"HB0$E$.C8T0#TW+4$Y5C1(*C-,*@H`