| xf.li | 6c8fc1e | 2023-08-12 00:11:09 -0700 | [diff] [blame] | 1 | #*************************************************************************** | 
|  | 2 | #                                  _   _ ____  _ | 
|  | 3 | #  Project                     ___| | | |  _ \| | | 
|  | 4 | #                             / __| | | | |_) | | | 
|  | 5 | #                            | (__| |_| |  _ <| |___ | 
|  | 6 | #                             \___|\___/|_| \_\_____| | 
|  | 7 | # | 
|  | 8 | # Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al. | 
|  | 9 | # | 
|  | 10 | # This software is licensed as described in the file COPYING, which | 
|  | 11 | # you should have received as part of this distribution. The terms | 
|  | 12 | # are also available at https://curl.se/docs/copyright.html. | 
|  | 13 | # | 
|  | 14 | # You may opt to use, copy, modify, merge, publish, distribute and/or sell | 
|  | 15 | # copies of the Software, and permit persons to whom the Software is | 
|  | 16 | # furnished to do so, under the terms of the COPYING file. | 
|  | 17 | # | 
|  | 18 | # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | 
|  | 19 | # KIND, either express or implied. | 
|  | 20 | # | 
|  | 21 | # SPDX-License-Identifier: curl | 
|  | 22 | # | 
|  | 23 | ########################################################################### | 
|  | 24 |  | 
|  | 25 | #use strict; | 
|  | 26 |  | 
|  | 27 | my @xml; | 
|  | 28 | my $xmlfile; | 
|  | 29 |  | 
|  | 30 | my $warning=0; | 
|  | 31 | my $trace=0; | 
|  | 32 |  | 
|  | 33 | use MIME::Base64; | 
|  | 34 |  | 
|  | 35 | sub decode_hex { | 
|  | 36 | my $s = $_; | 
|  | 37 | # remove everything not hex | 
|  | 38 | $s =~ s/[^A-Fa-f0-9]//g; | 
|  | 39 | # encode everything | 
|  | 40 | $s =~ s/([a-fA-F0-9][a-fA-F0-9])/chr(hex($1))/eg; | 
|  | 41 | return $s; | 
|  | 42 | } | 
|  | 43 |  | 
|  | 44 | sub getpartattr { | 
|  | 45 | # if $part is undefined (ie only one argument) then | 
|  | 46 | # return the attributes of the section | 
|  | 47 |  | 
|  | 48 | my ($section, $part)=@_; | 
|  | 49 |  | 
|  | 50 | my %hash; | 
|  | 51 | my $inside=0; | 
|  | 52 |  | 
|  | 53 | #   print "Section: $section, part: $part\n"; | 
|  | 54 |  | 
|  | 55 | for(@xml) { | 
|  | 56 | #       print "$inside: $_"; | 
|  | 57 | if(!$inside && ($_ =~ /^ *\<$section/)) { | 
|  | 58 | $inside++; | 
|  | 59 | } | 
|  | 60 | if((1 ==$inside) && ( ($_ =~ /^ *\<$part ([^>]*)/) || | 
|  | 61 | !(defined($part)) ) | 
|  | 62 | ) { | 
|  | 63 | $inside++; | 
|  | 64 | my $attr=$1; | 
|  | 65 |  | 
|  | 66 | while($attr =~ s/ *([^=]*)= *(\"([^\"]*)\"|([^\> ]*))//) { | 
|  | 67 | my ($var, $cont)=($1, $2); | 
|  | 68 | $cont =~ s/^\"(.*)\"$/$1/; | 
|  | 69 | $hash{$var}=$cont; | 
|  | 70 | } | 
|  | 71 | last; | 
|  | 72 | } | 
|  | 73 | # detect end of section when part wasn't found | 
|  | 74 | elsif((1 ==$inside) && ($_ =~ /^ *\<\/$section\>/)) { | 
|  | 75 | last; | 
|  | 76 | } | 
|  | 77 | elsif((2 ==$inside) && ($_ =~ /^ *\<\/$part/)) { | 
|  | 78 | $inside--; | 
|  | 79 | } | 
|  | 80 | } | 
|  | 81 | return %hash; | 
|  | 82 | } | 
|  | 83 |  | 
|  | 84 | sub getpart { | 
|  | 85 | my ($section, $part)=@_; | 
|  | 86 |  | 
|  | 87 | my @this; | 
|  | 88 | my $inside=0; | 
|  | 89 | my $base64=0; | 
|  | 90 | my $hex=0; | 
|  | 91 | my $line; | 
|  | 92 |  | 
|  | 93 | for(@xml) { | 
|  | 94 | $line++; | 
|  | 95 | if(!$inside && ($_ =~ /^ *\<$section/)) { | 
|  | 96 | $inside++; | 
|  | 97 | } | 
|  | 98 | elsif(($inside >= 1) && ($_ =~ /^ *\<$part[ \>]/)) { | 
|  | 99 | if($inside > 1) { | 
|  | 100 | push @this, $_; | 
|  | 101 | } | 
|  | 102 | elsif($_ =~ /$part [^>]*base64=/) { | 
|  | 103 | # attempt to detect our base64 encoded part | 
|  | 104 | $base64=1; | 
|  | 105 | } | 
|  | 106 | elsif($_ =~ /$part [^>]*hex=/) { | 
|  | 107 | # attempt to detect a hex-encoded part | 
|  | 108 | $hex=1; | 
|  | 109 | } | 
|  | 110 | $inside++; | 
|  | 111 | } | 
|  | 112 | elsif(($inside >= 2) && ($_ =~ /^ *\<\/$part[ \>]/)) { | 
|  | 113 | if($inside > 2) { | 
|  | 114 | push @this, $_; | 
|  | 115 | } | 
|  | 116 | $inside--; | 
|  | 117 | } | 
|  | 118 | elsif(($inside >= 1) && ($_ =~ /^ *\<\/$section/)) { | 
|  | 119 | if($inside > 1) { | 
|  | 120 | print STDERR "$xmlfile:$line:1: error: missing </$part> tag before </$section>\n"; | 
|  | 121 | @this = ("format error in $xmlfile"); | 
|  | 122 | } | 
|  | 123 | if($trace && @this) { | 
|  | 124 | print STDERR "*** getpart.pm: $section/$part returned data!\n"; | 
|  | 125 | } | 
|  | 126 | if($warning && !@this) { | 
|  | 127 | print STDERR "*** getpart.pm: $section/$part returned empty!\n"; | 
|  | 128 | } | 
|  | 129 | if($base64) { | 
|  | 130 | # decode the whole array before returning it! | 
|  | 131 | for(@this) { | 
|  | 132 | my $decoded = decode_base64($_); | 
|  | 133 | $_ = $decoded; | 
|  | 134 | } | 
|  | 135 | } | 
|  | 136 | elsif($hex) { | 
|  | 137 | # decode the whole array before returning it! | 
|  | 138 | for(@this) { | 
|  | 139 | my $decoded = decode_hex($_); | 
|  | 140 | $_ = $decoded; | 
|  | 141 | } | 
|  | 142 | } | 
|  | 143 | return @this; | 
|  | 144 | } | 
|  | 145 | elsif($inside >= 2) { | 
|  | 146 | push @this, $_; | 
|  | 147 | } | 
|  | 148 | } | 
|  | 149 | if($trace && @this) { | 
|  | 150 | # section/part has data but end of section not detected, | 
|  | 151 | # end of file implies end of section. | 
|  | 152 | print STDERR "*** getpart.pm: $section/$part returned data!\n"; | 
|  | 153 | } | 
|  | 154 | if($warning && !@this) { | 
|  | 155 | # section/part does not exist or has no data without an end of | 
|  | 156 | # section; end of file implies end of section. | 
|  | 157 | print STDERR "*** getpart.pm: $section/$part returned empty!\n"; | 
|  | 158 | } | 
|  | 159 | return @this; | 
|  | 160 | } | 
|  | 161 |  | 
|  | 162 | sub partexists { | 
|  | 163 | my ($section, $part)=@_; | 
|  | 164 |  | 
|  | 165 | my $inside = 0; | 
|  | 166 |  | 
|  | 167 | for(@xml) { | 
|  | 168 | if(!$inside && ($_ =~ /^ *\<$section/)) { | 
|  | 169 | $inside++; | 
|  | 170 | } | 
|  | 171 | elsif((1 == $inside) && ($_ =~ /^ *\<$part[ \>]/)) { | 
|  | 172 | return 1; # exists | 
|  | 173 | } | 
|  | 174 | elsif((1 == $inside) && ($_ =~ /^ *\<\/$section/)) { | 
|  | 175 | return 0; # does not exist | 
|  | 176 | } | 
|  | 177 | } | 
|  | 178 | return 0; # does not exist | 
|  | 179 | } | 
|  | 180 |  | 
|  | 181 | # Return entire document as list of lines | 
|  | 182 | sub getall { | 
|  | 183 | return @xml; | 
|  | 184 | } | 
|  | 185 |  | 
|  | 186 | sub loadtest { | 
|  | 187 | my ($file)=@_; | 
|  | 188 |  | 
|  | 189 | undef @xml; | 
|  | 190 | $xmlfile = $file; | 
|  | 191 |  | 
|  | 192 | if(open(XML, "<$file")) { | 
|  | 193 | binmode XML; # for crapage systems, use binary | 
|  | 194 | while(<XML>) { | 
|  | 195 | push @xml, $_; | 
|  | 196 | } | 
|  | 197 | close(XML); | 
|  | 198 | } | 
|  | 199 | else { | 
|  | 200 | # failure | 
|  | 201 | if($warning) { | 
|  | 202 | print STDERR "file $file wouldn't open!\n"; | 
|  | 203 | } | 
|  | 204 | return 1; | 
|  | 205 | } | 
|  | 206 | return 0; | 
|  | 207 | } | 
|  | 208 |  | 
|  | 209 | sub fulltest { | 
|  | 210 | return @xml; | 
|  | 211 | } | 
|  | 212 |  | 
|  | 213 | # write the test to the given file | 
|  | 214 | sub savetest { | 
|  | 215 | my ($file)=@_; | 
|  | 216 |  | 
|  | 217 | if(open(XML, ">$file")) { | 
|  | 218 | binmode XML; # for crapage systems, use binary | 
|  | 219 | for(@xml) { | 
|  | 220 | print XML $_; | 
|  | 221 | } | 
|  | 222 | close(XML); | 
|  | 223 | } | 
|  | 224 | else { | 
|  | 225 | # failure | 
|  | 226 | if($warning) { | 
|  | 227 | print STDERR "file $file wouldn't open!\n"; | 
|  | 228 | } | 
|  | 229 | return 1; | 
|  | 230 | } | 
|  | 231 | return 0; | 
|  | 232 | } | 
|  | 233 |  | 
|  | 234 | # | 
|  | 235 | # Strip off all lines that match the specified pattern and return | 
|  | 236 | # the new array. | 
|  | 237 | # | 
|  | 238 |  | 
|  | 239 | sub striparray { | 
|  | 240 | my ($pattern, $arrayref) = @_; | 
|  | 241 |  | 
|  | 242 | my @array; | 
|  | 243 |  | 
|  | 244 | for(@$arrayref) { | 
|  | 245 | if($_ !~ /$pattern/) { | 
|  | 246 | push @array, $_; | 
|  | 247 | } | 
|  | 248 | } | 
|  | 249 | return @array; | 
|  | 250 | } | 
|  | 251 |  | 
|  | 252 | # | 
|  | 253 | # pass array *REFERENCES* ! | 
|  | 254 | # | 
|  | 255 | sub compareparts { | 
|  | 256 | my ($firstref, $secondref)=@_; | 
|  | 257 |  | 
|  | 258 | my $first = join("", @$firstref); | 
|  | 259 | my $second = join("", @$secondref); | 
|  | 260 |  | 
|  | 261 | # we cannot compare arrays index per index since with the base64 chunks, | 
|  | 262 | # they may not be "evenly" distributed | 
|  | 263 |  | 
|  | 264 | # NOTE: this no longer strips off carriage returns from the arrays. Is that | 
|  | 265 | # really necessary? It ruins the testing of newlines. I believe it was once | 
|  | 266 | # added to enable tests on win32. | 
|  | 267 |  | 
|  | 268 | if($first ne $second) { | 
|  | 269 | return 1; | 
|  | 270 | } | 
|  | 271 |  | 
|  | 272 | return 0; | 
|  | 273 | } | 
|  | 274 |  | 
|  | 275 | # | 
|  | 276 | # Write a given array to the specified file | 
|  | 277 | # | 
|  | 278 | sub writearray { | 
|  | 279 | my ($filename, $arrayref)=@_; | 
|  | 280 |  | 
|  | 281 | open(TEMP, ">$filename"); | 
|  | 282 | binmode(TEMP,":raw"); # cygwin fix by Kevin Roth | 
|  | 283 | for(@$arrayref) { | 
|  | 284 | print TEMP $_; | 
|  | 285 | } | 
|  | 286 | close(TEMP); | 
|  | 287 | } | 
|  | 288 |  | 
|  | 289 | # | 
|  | 290 | # Load a specified file and return it as an array | 
|  | 291 | # | 
|  | 292 | sub loadarray { | 
|  | 293 | my ($filename)=@_; | 
|  | 294 | my @array; | 
|  | 295 |  | 
|  | 296 | open(TEMP, "<$filename"); | 
|  | 297 | while(<TEMP>) { | 
|  | 298 | push @array, $_; | 
|  | 299 | } | 
|  | 300 | close(TEMP); | 
|  | 301 | return @array; | 
|  | 302 | } | 
|  | 303 |  | 
|  | 304 | # Given two array references, this function will store them in two temporary | 
|  | 305 | # files, run 'diff' on them, store the result and return the diff output! | 
|  | 306 |  | 
|  | 307 | sub showdiff { | 
|  | 308 | my ($logdir, $firstref, $secondref)=@_; | 
|  | 309 |  | 
|  | 310 | my $file1="$logdir/check-generated"; | 
|  | 311 | my $file2="$logdir/check-expected"; | 
|  | 312 |  | 
|  | 313 | open(TEMP, ">$file1"); | 
|  | 314 | for(@$firstref) { | 
|  | 315 | my $l = $_; | 
|  | 316 | $l =~ s/\r/[CR]/g; | 
|  | 317 | $l =~ s/\n/[LF]/g; | 
|  | 318 | $l =~ s/([^\x20-\x7f])/sprintf "%%%02x", ord $1/eg; | 
|  | 319 | print TEMP $l; | 
|  | 320 | print TEMP "\n"; | 
|  | 321 | } | 
|  | 322 | close(TEMP); | 
|  | 323 |  | 
|  | 324 | open(TEMP, ">$file2"); | 
|  | 325 | for(@$secondref) { | 
|  | 326 | my $l = $_; | 
|  | 327 | $l =~ s/\r/[CR]/g; | 
|  | 328 | $l =~ s/\n/[LF]/g; | 
|  | 329 | $l =~ s/([^\x20-\x7f])/sprintf "%%%02x", ord $1/eg; | 
|  | 330 | print TEMP $l; | 
|  | 331 | print TEMP "\n"; | 
|  | 332 | } | 
|  | 333 | close(TEMP); | 
|  | 334 | my @out = `diff -u $file2 $file1 2>/dev/null`; | 
|  | 335 |  | 
|  | 336 | if(!$out[0]) { | 
|  | 337 | @out = `diff -c $file2 $file1 2>/dev/null`; | 
|  | 338 | } | 
|  | 339 |  | 
|  | 340 | return @out; | 
|  | 341 | } | 
|  | 342 |  | 
|  | 343 |  | 
|  | 344 | 1; |