blob: f8cb6effc757a320ade294855d70631e4e92e255 [file] [log] [blame]
xf.li6c8fc1e2023-08-12 00:11:09 -07001#***************************************************************************
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
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 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
84sub 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
162sub 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
182sub getall {
183 return @xml;
184}
185
186sub 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
209sub fulltest {
210 return @xml;
211}
212
213# write the test to the given file
214sub 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
239sub 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#
255sub 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#
278sub 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#
292sub 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
307sub 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
3441;