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