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