]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/testhttp.c
License change: Apache License, Version 2.0.
[thirdparty/cups.git] / cups / testhttp.c
1 /*
2 * HTTP test program for CUPS.
3 *
4 * Copyright 2007-2014 by Apple Inc.
5 * Copyright 1997-2006 by Easy Software Products.
6 *
7 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
8 */
9
10 /*
11 * Include necessary headers...
12 */
13
14 #include "cups-private.h"
15
16
17 /*
18 * Types and structures...
19 */
20
21 typedef struct uri_test_s /**** URI test cases ****/
22 {
23 http_uri_status_t result; /* Expected return value */
24 const char *uri, /* URI */
25 *scheme, /* Scheme string */
26 *username, /* Username:password string */
27 *hostname, /* Hostname string */
28 *resource; /* Resource string */
29 int port, /* Port number */
30 assemble_port; /* Port number for httpAssembleURI() */
31 http_uri_coding_t assemble_coding;/* Coding for httpAssembleURI() */
32 } uri_test_t;
33
34
35 /*
36 * Local globals...
37 */
38
39 static uri_test_t uri_tests[] = /* URI test data */
40 {
41 /* Start with valid URIs */
42 { HTTP_URI_STATUS_OK, "file:/filename",
43 "file", "", "", "/filename", 0, 0,
44 HTTP_URI_CODING_MOST },
45 { HTTP_URI_STATUS_OK, "file:/filename%20with%20spaces",
46 "file", "", "", "/filename with spaces", 0, 0,
47 HTTP_URI_CODING_MOST },
48 { HTTP_URI_STATUS_OK, "file:///filename",
49 "file", "", "", "/filename", 0, 0,
50 HTTP_URI_CODING_MOST },
51 { HTTP_URI_STATUS_OK, "file:///filename%20with%20spaces",
52 "file", "", "", "/filename with spaces", 0, 0,
53 HTTP_URI_CODING_MOST },
54 { HTTP_URI_STATUS_OK, "file://localhost/filename",
55 "file", "", "localhost", "/filename", 0, 0,
56 HTTP_URI_CODING_MOST },
57 { HTTP_URI_STATUS_OK, "file://localhost/filename%20with%20spaces",
58 "file", "", "localhost", "/filename with spaces", 0, 0,
59 HTTP_URI_CODING_MOST },
60 { HTTP_URI_STATUS_OK, "http://server/",
61 "http", "", "server", "/", 80, 0,
62 HTTP_URI_CODING_MOST },
63 { HTTP_URI_STATUS_OK, "http://username@server/",
64 "http", "username", "server", "/", 80, 0,
65 HTTP_URI_CODING_MOST },
66 { HTTP_URI_STATUS_OK, "http://username:passwor%64@server/",
67 "http", "username:password", "server", "/", 80, 0,
68 HTTP_URI_CODING_MOST },
69 { HTTP_URI_STATUS_OK, "http://username:passwor%64@server:8080/",
70 "http", "username:password", "server", "/", 8080, 8080,
71 HTTP_URI_CODING_MOST },
72 { HTTP_URI_STATUS_OK, "http://username:passwor%64@server:8080/directory/filename",
73 "http", "username:password", "server", "/directory/filename", 8080, 8080,
74 HTTP_URI_CODING_MOST },
75 { HTTP_URI_STATUS_OK, "http://[2000::10:100]:631/ipp",
76 "http", "", "2000::10:100", "/ipp", 631, 631,
77 HTTP_URI_CODING_MOST },
78 { HTTP_URI_STATUS_OK, "https://username:passwor%64@server/directory/filename",
79 "https", "username:password", "server", "/directory/filename", 443, 0,
80 HTTP_URI_CODING_MOST },
81 { HTTP_URI_STATUS_OK, "ipp://username:passwor%64@[::1]/ipp",
82 "ipp", "username:password", "::1", "/ipp", 631, 0,
83 HTTP_URI_CODING_MOST },
84 { HTTP_URI_STATUS_OK, "lpd://server/queue?reserve=yes",
85 "lpd", "", "server", "/queue?reserve=yes", 515, 0,
86 HTTP_URI_CODING_MOST },
87 { HTTP_URI_STATUS_OK, "mailto:user@domain.com",
88 "mailto", "", "", "user@domain.com", 0, 0,
89 HTTP_URI_CODING_MOST },
90 { HTTP_URI_STATUS_OK, "socket://server/",
91 "socket", "", "server", "/", 9100, 0,
92 HTTP_URI_CODING_MOST },
93 { HTTP_URI_STATUS_OK, "socket://192.168.1.1:9101/",
94 "socket", "", "192.168.1.1", "/", 9101, 9101,
95 HTTP_URI_CODING_MOST },
96 { HTTP_URI_STATUS_OK, "tel:8005551212",
97 "tel", "", "", "8005551212", 0, 0,
98 HTTP_URI_CODING_MOST },
99 { HTTP_URI_STATUS_OK, "ipp://username:password@[v1.fe80::200:1234:5678:9abc+eth0]:999/ipp",
100 "ipp", "username:password", "fe80::200:1234:5678:9abc%eth0", "/ipp", 999, 999,
101 HTTP_URI_CODING_MOST },
102 { HTTP_URI_STATUS_OK, "ipp://username:password@[fe80::200:1234:5678:9abc%25eth0]:999/ipp",
103 "ipp", "username:password", "fe80::200:1234:5678:9abc%eth0", "/ipp", 999, 999,
104 (http_uri_coding_t)(HTTP_URI_CODING_MOST | HTTP_URI_CODING_RFC6874) },
105 { HTTP_URI_STATUS_OK, "http://server/admin?DEVICE_URI=usb://HP/Photosmart%25202600%2520series?serial=MY53OK70V10400",
106 "http", "", "server", "/admin?DEVICE_URI=usb://HP/Photosmart%25202600%2520series?serial=MY53OK70V10400", 80, 0,
107 HTTP_URI_CODING_MOST },
108 { HTTP_URI_STATUS_OK, "lpd://Acme%20Laser%20(01%3A23%3A45).local._tcp._printer/",
109 "lpd", "", "Acme Laser (01:23:45).local._tcp._printer", "/", 515, 0,
110 HTTP_URI_CODING_MOST },
111 { HTTP_URI_STATUS_OK, "ipp://HP%20Officejet%204500%20G510n-z%20%40%20Will's%20MacBook%20Pro%2015%22._ipp._tcp.local./",
112 "ipp", "", "HP Officejet 4500 G510n-z @ Will's MacBook Pro 15\"._ipp._tcp.local.", "/", 631, 0,
113 HTTP_URI_CODING_MOST },
114 { HTTP_URI_STATUS_OK, "ipp://%22%23%2F%3A%3C%3E%3F%40%5B%5C%5D%5E%60%7B%7C%7D/",
115 "ipp", "", "\"#/:<>?@[\\]^`{|}", "/", 631, 0,
116 HTTP_URI_CODING_MOST },
117
118 /* Missing scheme */
119 { HTTP_URI_STATUS_MISSING_SCHEME, "/path/to/file/index.html",
120 "file", "", "", "/path/to/file/index.html", 0, 0,
121 HTTP_URI_CODING_MOST },
122 { HTTP_URI_STATUS_MISSING_SCHEME, "//server/ipp",
123 "ipp", "", "server", "/ipp", 631, 0,
124 HTTP_URI_CODING_MOST },
125
126 /* Unknown scheme */
127 { HTTP_URI_STATUS_UNKNOWN_SCHEME, "vendor://server/resource",
128 "vendor", "", "server", "/resource", 0, 0,
129 HTTP_URI_CODING_MOST },
130
131 /* Missing resource */
132 { HTTP_URI_STATUS_MISSING_RESOURCE, "socket://[::192.168.2.1]",
133 "socket", "", "::192.168.2.1", "/", 9100, 0,
134 HTTP_URI_CODING_MOST },
135 { HTTP_URI_STATUS_MISSING_RESOURCE, "socket://192.168.1.1:9101",
136 "socket", "", "192.168.1.1", "/", 9101, 0,
137 HTTP_URI_CODING_MOST },
138
139 /* Bad URI */
140 { HTTP_URI_STATUS_BAD_URI, "",
141 "", "", "", "", 0, 0,
142 HTTP_URI_CODING_MOST },
143
144 /* Bad scheme */
145 { HTTP_URI_STATUS_BAD_SCHEME, "bad_scheme://server/resource",
146 "", "", "", "", 0, 0,
147 HTTP_URI_CODING_MOST },
148
149 /* Bad username */
150 { HTTP_URI_STATUS_BAD_USERNAME, "http://username:passwor%6@server/resource",
151 "http", "", "", "", 80, 0,
152 HTTP_URI_CODING_MOST },
153
154 /* Bad hostname */
155 { HTTP_URI_STATUS_BAD_HOSTNAME, "http://[/::1]/index.html",
156 "http", "", "", "", 80, 0,
157 HTTP_URI_CODING_MOST },
158 { HTTP_URI_STATUS_BAD_HOSTNAME, "http://[",
159 "http", "", "", "", 80, 0,
160 HTTP_URI_CODING_MOST },
161 { HTTP_URI_STATUS_BAD_HOSTNAME, "http://serve%7/index.html",
162 "http", "", "", "", 80, 0,
163 HTTP_URI_CODING_MOST },
164 { HTTP_URI_STATUS_BAD_HOSTNAME, "http://server with spaces/index.html",
165 "http", "", "", "", 80, 0,
166 HTTP_URI_CODING_MOST },
167 { HTTP_URI_STATUS_BAD_HOSTNAME, "ipp://\"#/:<>?@[\\]^`{|}/",
168 "ipp", "", "", "", 631, 0,
169 HTTP_URI_CODING_MOST },
170
171 /* Bad port number */
172 { HTTP_URI_STATUS_BAD_PORT, "http://127.0.0.1:9999a/index.html",
173 "http", "", "127.0.0.1", "", 0, 0,
174 HTTP_URI_CODING_MOST },
175
176 /* Bad resource */
177 { HTTP_URI_STATUS_BAD_RESOURCE, "http://server/index.html%",
178 "http", "", "server", "", 80, 0,
179 HTTP_URI_CODING_MOST },
180 { HTTP_URI_STATUS_BAD_RESOURCE, "http://server/index with spaces.html",
181 "http", "", "server", "", 80, 0,
182 HTTP_URI_CODING_MOST }
183 };
184 static const char * const base64_tests[][2] =
185 {
186 { "A", "QQ==" },
187 /* 010000 01 */
188 { "AB", "QUI=" },
189 /* 010000 010100 0010 */
190 { "ABC", "QUJD" },
191 /* 010000 010100 001001 000011 */
192 { "ABCD", "QUJDRA==" },
193 /* 010000 010100 001001 000011 010001 00 */
194 { "ABCDE", "QUJDREU=" },
195 /* 010000 010100 001001 000011 010001 000100 0101 */
196 { "ABCDEF", "QUJDREVG" },
197 /* 010000 010100 001001 000011 010001 000100 010101 000110 */
198 };
199
200
201 /*
202 * 'main()' - Main entry.
203 */
204
205 int /* O - Exit status */
206 main(int argc, /* I - Number of command-line arguments */
207 char *argv[]) /* I - Command-line arguments */
208 {
209 int i, j, k; /* Looping vars */
210 http_t *http; /* HTTP connection */
211 http_encryption_t encryption; /* Encryption type */
212 http_status_t status; /* Status of GET command */
213 int failures; /* Number of test failures */
214 char buffer[8192]; /* Input buffer */
215 long bytes; /* Number of bytes read */
216 FILE *out; /* Output file */
217 char encode[256], /* Base64-encoded string */
218 decode[256]; /* Base64-decoded string */
219 int decodelen; /* Length of decoded string */
220 char scheme[HTTP_MAX_URI], /* Scheme from URI */
221 hostname[HTTP_MAX_URI], /* Hostname from URI */
222 username[HTTP_MAX_URI], /* Username:password from URI */
223 resource[HTTP_MAX_URI]; /* Resource from URI */
224 int port; /* Port number from URI */
225 http_uri_status_t uri_status; /* Status of URI separation */
226 http_addrlist_t *addrlist, /* Address list */
227 *addr; /* Current address */
228 off_t length, total; /* Length and total bytes */
229 time_t start, current; /* Start and end time */
230 const char *encoding; /* Negotiated Content-Encoding */
231 static const char * const uri_status_strings[] =
232 {
233 "HTTP_URI_STATUS_OVERFLOW",
234 "HTTP_URI_STATUS_BAD_ARGUMENTS",
235 "HTTP_URI_STATUS_BAD_RESOURCE",
236 "HTTP_URI_STATUS_BAD_PORT",
237 "HTTP_URI_STATUS_BAD_HOSTNAME",
238 "HTTP_URI_STATUS_BAD_USERNAME",
239 "HTTP_URI_STATUS_BAD_SCHEME",
240 "HTTP_URI_STATUS_BAD_URI",
241 "HTTP_URI_STATUS_OK",
242 "HTTP_URI_STATUS_MISSING_SCHEME",
243 "HTTP_URI_STATUS_UNKNOWN_SCHEME",
244 "HTTP_URI_STATUS_MISSING_RESOURCE"
245 };
246
247
248 /*
249 * Do API tests if we don't have a URL on the command-line...
250 */
251
252 if (argc == 1)
253 {
254 failures = 0;
255
256 /*
257 * httpGetDateString()/httpGetDateTime()
258 */
259
260 fputs("httpGetDateString()/httpGetDateTime(): ", stdout);
261
262 start = time(NULL);
263 strlcpy(buffer, httpGetDateString(start), sizeof(buffer));
264 current = httpGetDateTime(buffer);
265
266 i = (int)(current - start);
267 if (i < 0)
268 i = -i;
269
270 if (!i)
271 puts("PASS");
272 else
273 {
274 failures ++;
275 puts("FAIL");
276 printf(" Difference is %d seconds, %02d:%02d:%02d...\n", i, i / 3600,
277 (i / 60) % 60, i % 60);
278 printf(" httpGetDateString(%d) returned \"%s\"\n", (int)start, buffer);
279 printf(" httpGetDateTime(\"%s\") returned %d\n", buffer, (int)current);
280 printf(" httpGetDateString(%d) returned \"%s\"\n", (int)current,
281 httpGetDateString(current));
282 }
283
284 /*
285 * httpDecode64_2()/httpEncode64_2()
286 */
287
288 fputs("httpDecode64_2()/httpEncode64_2(): ", stdout);
289
290 for (i = 0, j = 0; i < (int)(sizeof(base64_tests) / sizeof(base64_tests[0])); i ++)
291 {
292 httpEncode64_2(encode, sizeof(encode), base64_tests[i][0],
293 (int)strlen(base64_tests[i][0]));
294 decodelen = (int)sizeof(decode);
295 httpDecode64_2(decode, &decodelen, base64_tests[i][1]);
296
297 if (strcmp(decode, base64_tests[i][0]))
298 {
299 failures ++;
300
301 if (j)
302 {
303 puts("FAIL");
304 j = 1;
305 }
306
307 printf(" httpDecode64_2() returned \"%s\", expected \"%s\"...\n",
308 decode, base64_tests[i][0]);
309 }
310
311 if (strcmp(encode, base64_tests[i][1]))
312 {
313 failures ++;
314
315 if (j)
316 {
317 puts("FAIL");
318 j = 1;
319 }
320
321 printf(" httpEncode64_2() returned \"%s\", expected \"%s\"...\n",
322 encode, base64_tests[i][1]);
323 }
324 }
325
326 if (!j)
327 puts("PASS");
328
329 /*
330 * httpGetHostname()
331 */
332
333 fputs("httpGetHostname(): ", stdout);
334
335 if (httpGetHostname(NULL, hostname, sizeof(hostname)))
336 printf("PASS (%s)\n", hostname);
337 else
338 {
339 failures ++;
340 puts("FAIL");
341 }
342
343 /*
344 * httpAddrGetList()
345 */
346
347 printf("httpAddrGetList(%s): ", hostname);
348
349 addrlist = httpAddrGetList(hostname, AF_UNSPEC, NULL);
350 if (addrlist)
351 {
352 for (i = 0, addr = addrlist; addr; i ++, addr = addr->next)
353 {
354 char numeric[1024]; /* Numeric IP address */
355
356
357 httpAddrString(&(addr->addr), numeric, sizeof(numeric));
358 if (!strcmp(numeric, "UNKNOWN"))
359 break;
360 }
361
362 if (addr)
363 printf("FAIL (bad address for %s)\n", hostname);
364 else
365 printf("PASS (%d address(es) for %s)\n", i, hostname);
366
367 httpAddrFreeList(addrlist);
368 }
369 else if (isdigit(hostname[0] & 255))
370 {
371 puts("FAIL (ignored because hostname is numeric)");
372 }
373 else
374 {
375 failures ++;
376 puts("FAIL");
377 }
378
379 /*
380 * Test httpSeparateURI()...
381 */
382
383 fputs("httpSeparateURI(): ", stdout);
384 for (i = 0, j = 0; i < (int)(sizeof(uri_tests) / sizeof(uri_tests[0])); i ++)
385 {
386 uri_status = httpSeparateURI(HTTP_URI_CODING_MOST,
387 uri_tests[i].uri, scheme, sizeof(scheme),
388 username, sizeof(username),
389 hostname, sizeof(hostname), &port,
390 resource, sizeof(resource));
391 if (uri_status != uri_tests[i].result ||
392 strcmp(scheme, uri_tests[i].scheme) ||
393 strcmp(username, uri_tests[i].username) ||
394 strcmp(hostname, uri_tests[i].hostname) ||
395 port != uri_tests[i].port ||
396 strcmp(resource, uri_tests[i].resource))
397 {
398 failures ++;
399
400 if (!j)
401 {
402 puts("FAIL");
403 j = 1;
404 }
405
406 printf(" \"%s\":\n", uri_tests[i].uri);
407
408 if (uri_status != uri_tests[i].result)
409 printf(" Returned %s instead of %s\n",
410 uri_status_strings[uri_status + 8],
411 uri_status_strings[uri_tests[i].result + 8]);
412
413 if (strcmp(scheme, uri_tests[i].scheme))
414 printf(" Scheme \"%s\" instead of \"%s\"\n",
415 scheme, uri_tests[i].scheme);
416
417 if (strcmp(username, uri_tests[i].username))
418 printf(" Username \"%s\" instead of \"%s\"\n",
419 username, uri_tests[i].username);
420
421 if (strcmp(hostname, uri_tests[i].hostname))
422 printf(" Hostname \"%s\" instead of \"%s\"\n",
423 hostname, uri_tests[i].hostname);
424
425 if (port != uri_tests[i].port)
426 printf(" Port %d instead of %d\n",
427 port, uri_tests[i].port);
428
429 if (strcmp(resource, uri_tests[i].resource))
430 printf(" Resource \"%s\" instead of \"%s\"\n",
431 resource, uri_tests[i].resource);
432 }
433 }
434
435 if (!j)
436 printf("PASS (%d URIs tested)\n",
437 (int)(sizeof(uri_tests) / sizeof(uri_tests[0])));
438
439 /*
440 * Test httpAssembleURI()...
441 */
442
443 fputs("httpAssembleURI(): ", stdout);
444 for (i = 0, j = 0, k = 0;
445 i < (int)(sizeof(uri_tests) / sizeof(uri_tests[0]));
446 i ++)
447 if (uri_tests[i].result == HTTP_URI_STATUS_OK &&
448 !strstr(uri_tests[i].uri, "%64") &&
449 strstr(uri_tests[i].uri, "//"))
450 {
451 k ++;
452 uri_status = httpAssembleURI(uri_tests[i].assemble_coding,
453 buffer, sizeof(buffer),
454 uri_tests[i].scheme,
455 uri_tests[i].username,
456 uri_tests[i].hostname,
457 uri_tests[i].assemble_port,
458 uri_tests[i].resource);
459
460 if (uri_status != HTTP_URI_STATUS_OK)
461 {
462 failures ++;
463
464 if (!j)
465 {
466 puts("FAIL");
467 j = 1;
468 }
469
470 printf(" \"%s\": %s\n", uri_tests[i].uri,
471 uri_status_strings[uri_status + 8]);
472 }
473 else if (strcmp(buffer, uri_tests[i].uri))
474 {
475 failures ++;
476
477 if (!j)
478 {
479 puts("FAIL");
480 j = 1;
481 }
482
483 printf(" \"%s\": assembled = \"%s\"\n", uri_tests[i].uri,
484 buffer);
485 }
486 }
487
488 if (!j)
489 printf("PASS (%d URIs tested)\n", k);
490
491 /*
492 * httpAssembleUUID
493 */
494
495 fputs("httpAssembleUUID: ", stdout);
496 httpAssembleUUID("hostname.example.com", 631, "printer", 12345, buffer,
497 sizeof(buffer));
498 if (strncmp(buffer, "urn:uuid:", 9))
499 {
500 printf("FAIL (%s)\n", buffer);
501 failures ++;
502 }
503 else
504 printf("PASS (%s)\n", buffer);
505
506 /*
507 * Show a summary and return...
508 */
509
510 if (failures)
511 printf("\n%d TESTS FAILED!\n", failures);
512 else
513 puts("\nALL TESTS PASSED!");
514
515 return (failures);
516 }
517 else if (strstr(argv[1], "._tcp"))
518 {
519 /*
520 * Test resolving an mDNS name.
521 */
522
523 char resolved[1024]; /* Resolved URI */
524
525
526 printf("_httpResolveURI(%s, _HTTP_RESOLVE_DEFAULT): ", argv[1]);
527 fflush(stdout);
528
529 if (!_httpResolveURI(argv[1], resolved, sizeof(resolved),
530 _HTTP_RESOLVE_DEFAULT, NULL, NULL))
531 {
532 puts("FAIL");
533 return (1);
534 }
535 else
536 printf("PASS (%s)\n", resolved);
537
538 printf("_httpResolveURI(%s, _HTTP_RESOLVE_FQDN): ", argv[1]);
539 fflush(stdout);
540
541 if (!_httpResolveURI(argv[1], resolved, sizeof(resolved),
542 _HTTP_RESOLVE_FQDN, NULL, NULL))
543 {
544 puts("FAIL");
545 return (1);
546 }
547 else if (strstr(resolved, ".local:"))
548 {
549 printf("FAIL (%s)\n", resolved);
550 return (1);
551 }
552 else
553 {
554 printf("PASS (%s)\n", resolved);
555 return (0);
556 }
557 }
558 else if (!strcmp(argv[1], "-u") && argc == 3)
559 {
560 /*
561 * Test URI separation...
562 */
563
564 uri_status = httpSeparateURI(HTTP_URI_CODING_ALL, argv[2], scheme,
565 sizeof(scheme), username, sizeof(username),
566 hostname, sizeof(hostname), &port,
567 resource, sizeof(resource));
568 printf("uri_status = %s\n", uri_status_strings[uri_status + 8]);
569 printf("scheme = \"%s\"\n", scheme);
570 printf("username = \"%s\"\n", username);
571 printf("hostname = \"%s\"\n", hostname);
572 printf("port = %d\n", port);
573 printf("resource = \"%s\"\n", resource);
574
575 return (0);
576 }
577
578 /*
579 * Test HTTP GET requests...
580 */
581
582 http = NULL;
583 out = stdout;
584
585 for (i = 1; i < argc; i ++)
586 {
587 if (!strcmp(argv[i], "-o"))
588 {
589 i ++;
590 if (i >= argc)
591 break;
592
593 out = fopen(argv[i], "wb");
594 continue;
595 }
596
597 httpSeparateURI(HTTP_URI_CODING_MOST, argv[i], scheme, sizeof(scheme),
598 username, sizeof(username),
599 hostname, sizeof(hostname), &port,
600 resource, sizeof(resource));
601
602 if (!_cups_strcasecmp(scheme, "https") || !_cups_strcasecmp(scheme, "ipps") ||
603 port == 443)
604 encryption = HTTP_ENCRYPTION_ALWAYS;
605 else
606 encryption = HTTP_ENCRYPTION_IF_REQUESTED;
607
608 http = httpConnect2(hostname, port, NULL, AF_UNSPEC, encryption, 1, 30000, NULL);
609 if (http == NULL)
610 {
611 perror(hostname);
612 continue;
613 }
614
615 if (httpIsEncrypted(http))
616 {
617 cups_array_t *creds;
618 char info[1024];
619 static const char *trusts[] = { "OK", "Invalid", "Changed", "Expired", "Renewed", "Unknown" };
620 if (!httpCopyCredentials(http, &creds))
621 {
622 cups_array_t *lcreds;
623 http_trust_t trust = httpCredentialsGetTrust(creds, hostname);
624
625 httpCredentialsString(creds, info, sizeof(info));
626
627 printf("Count: %d\n", cupsArrayCount(creds));
628 printf("Trust: %s\n", trusts[trust]);
629 printf("Expiration: %s\n", httpGetDateString(httpCredentialsGetExpiration(creds)));
630 printf("IsValidName: %d\n", httpCredentialsAreValidForName(creds, hostname));
631 printf("String: \"%s\"\n", info);
632
633 printf("LoadCredentials: %d\n", httpLoadCredentials(NULL, &lcreds, hostname));
634 httpCredentialsString(lcreds, info, sizeof(info));
635 printf(" Count: %d\n", cupsArrayCount(lcreds));
636 printf(" String: \"%s\"\n", info);
637
638 if (lcreds && cupsArrayCount(creds) == cupsArrayCount(lcreds))
639 {
640 http_credential_t *cred, *lcred;
641
642 for (i = 1, cred = (http_credential_t *)cupsArrayFirst(creds), lcred = (http_credential_t *)cupsArrayFirst(lcreds);
643 cred && lcred;
644 i ++, cred = (http_credential_t *)cupsArrayNext(creds), lcred = (http_credential_t *)cupsArrayNext(lcreds))
645 {
646 if (cred->datalen != lcred->datalen)
647 printf(" Credential #%d: Different lengths (saved=%d, current=%d)\n", i, (int)cred->datalen, (int)lcred->datalen);
648 else if (memcmp(cred->data, lcred->data, cred->datalen))
649 printf(" Credential #%d: Different data\n", i);
650 else
651 printf(" Credential #%d: Matches\n", i);
652 }
653 }
654
655 if (trust != HTTP_TRUST_OK)
656 {
657 printf("SaveCredentials: %d\n", httpSaveCredentials(NULL, creds, hostname));
658 trust = httpCredentialsGetTrust(creds, hostname);
659 printf("New Trust: %s\n", trusts[trust]);
660 }
661
662 httpFreeCredentials(creds);
663 }
664 else
665 puts("No credentials!");
666 }
667
668 printf("Checking file \"%s\"...\n", resource);
669
670 do
671 {
672 if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close"))
673 {
674 httpClearFields(http);
675 if (httpReconnect2(http, 30000, NULL))
676 {
677 status = HTTP_STATUS_ERROR;
678 break;
679 }
680 }
681
682 httpClearFields(http);
683 httpSetField(http, HTTP_FIELD_AUTHORIZATION, httpGetAuthString(http));
684 httpSetField(http, HTTP_FIELD_ACCEPT_LANGUAGE, "en");
685 if (httpHead(http, resource))
686 {
687 if (httpReconnect2(http, 30000, NULL))
688 {
689 status = HTTP_STATUS_ERROR;
690 break;
691 }
692 else
693 {
694 status = HTTP_STATUS_UNAUTHORIZED;
695 continue;
696 }
697 }
698
699 while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE);
700
701 if (status == HTTP_STATUS_UNAUTHORIZED)
702 {
703 /*
704 * Flush any error message...
705 */
706
707 httpFlush(http);
708
709 /*
710 * See if we can do authentication...
711 */
712
713 if (cupsDoAuthentication(http, "GET", resource))
714 {
715 status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
716 break;
717 }
718
719 if (httpReconnect2(http, 30000, NULL))
720 {
721 status = HTTP_STATUS_ERROR;
722 break;
723 }
724
725 continue;
726 }
727 #ifdef HAVE_SSL
728 else if (status == HTTP_STATUS_UPGRADE_REQUIRED)
729 {
730 /* Flush any error message... */
731 httpFlush(http);
732
733 /* Reconnect... */
734 if (httpReconnect2(http, 30000, NULL))
735 {
736 status = HTTP_STATUS_ERROR;
737 break;
738 }
739
740 /* Upgrade with encryption... */
741 httpEncryption(http, HTTP_ENCRYPTION_REQUIRED);
742
743 /* Try again, this time with encryption enabled... */
744 continue;
745 }
746 #endif /* HAVE_SSL */
747 }
748 while (status == HTTP_STATUS_UNAUTHORIZED ||
749 status == HTTP_STATUS_UPGRADE_REQUIRED);
750
751 if (status == HTTP_STATUS_OK)
752 puts("HEAD OK:");
753 else
754 printf("HEAD failed with status %d...\n", status);
755
756 encoding = httpGetContentEncoding(http);
757
758 printf("Requesting file \"%s\" (Accept-Encoding: %s)...\n", resource,
759 encoding ? encoding : "identity");
760
761 do
762 {
763 if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close"))
764 {
765 httpClearFields(http);
766 if (httpReconnect2(http, 30000, NULL))
767 {
768 status = HTTP_STATUS_ERROR;
769 break;
770 }
771 }
772
773 httpClearFields(http);
774 httpSetField(http, HTTP_FIELD_AUTHORIZATION, httpGetAuthString(http));
775 httpSetField(http, HTTP_FIELD_ACCEPT_LANGUAGE, "en");
776 httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING, encoding);
777
778 if (httpGet(http, resource))
779 {
780 if (httpReconnect2(http, 30000, NULL))
781 {
782 status = HTTP_STATUS_ERROR;
783 break;
784 }
785 else
786 {
787 status = HTTP_STATUS_UNAUTHORIZED;
788 continue;
789 }
790 }
791
792 while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE);
793
794 if (status == HTTP_STATUS_UNAUTHORIZED)
795 {
796 /*
797 * Flush any error message...
798 */
799
800 httpFlush(http);
801
802 /*
803 * See if we can do authentication...
804 */
805
806 if (cupsDoAuthentication(http, "GET", resource))
807 {
808 status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
809 break;
810 }
811
812 if (httpReconnect2(http, 30000, NULL))
813 {
814 status = HTTP_STATUS_ERROR;
815 break;
816 }
817
818 continue;
819 }
820 #ifdef HAVE_SSL
821 else if (status == HTTP_STATUS_UPGRADE_REQUIRED)
822 {
823 /* Flush any error message... */
824 httpFlush(http);
825
826 /* Reconnect... */
827 if (httpReconnect2(http, 30000, NULL))
828 {
829 status = HTTP_STATUS_ERROR;
830 break;
831 }
832
833 /* Upgrade with encryption... */
834 httpEncryption(http, HTTP_ENCRYPTION_REQUIRED);
835
836 /* Try again, this time with encryption enabled... */
837 continue;
838 }
839 #endif /* HAVE_SSL */
840 }
841 while (status == HTTP_STATUS_UNAUTHORIZED || status == HTTP_STATUS_UPGRADE_REQUIRED);
842
843 if (status == HTTP_STATUS_OK)
844 puts("GET OK:");
845 else
846 printf("GET failed with status %d...\n", status);
847
848 start = time(NULL);
849 length = httpGetLength2(http);
850 total = 0;
851
852 while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0)
853 {
854 total += bytes;
855 fwrite(buffer, (size_t)bytes, 1, out);
856 if (out != stdout)
857 {
858 current = time(NULL);
859 if (current == start)
860 current ++;
861
862 printf("\r" CUPS_LLFMT "/" CUPS_LLFMT " bytes ("
863 CUPS_LLFMT " bytes/sec) ", CUPS_LLCAST total,
864 CUPS_LLCAST length, CUPS_LLCAST (total / (current - start)));
865 fflush(stdout);
866 }
867 }
868 }
869
870 if (out != stdout)
871 putchar('\n');
872
873 puts("Closing connection to server...");
874 httpClose(http);
875
876 if (out != stdout)
877 fclose(out);
878
879 return (0);
880 }