int /* O - Exit status */ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { const char *name; /* Backend name */ cups_array_t *devices; /* Device array */ cups_device_t *device; /* Current device */ char uriName[1024]; /* Unquoted fullName for URI */ #ifdef HAVE_DNSSD int fd; /* Main file descriptor */ fd_set input; /* Input set for select() */ struct timeval timeout; /* Timeout for select() */ DNSServiceRef main_ref, /* Main service reference */ fax_ipp_ref, /* IPP fax service reference */ ipp_ref, /* IPP service reference */ ipp_tls_ref, /* IPP w/TLS service reference */ ipps_ref, /* IPP service reference */ local_fax_ipp_ref, /* Local IPP fax service reference */ local_ipp_ref, /* Local IPP service reference */ local_ipp_tls_ref, /* Local IPP w/TLS service reference */ local_ipps_ref, /* Local IPP service reference */ local_printer_ref, /* Local LPD service reference */ pdl_datastream_ref, /* AppSocket service reference */ printer_ref, /* LPD service reference */ riousbprint_ref; /* Remote IO service reference */ #endif /* HAVE_DNSSD */ #ifdef HAVE_AVAHI AvahiClient *client; /* Client information */ int error; /* Error code, if any */ #endif /* HAVE_AVAHI */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ /* * Don't buffer stderr, and catch SIGTERM... */ setbuf(stderr, NULL); #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ sigset(SIGTERM, sigterm_handler); #elif defined(HAVE_SIGACTION) memset(&action, 0, sizeof(action)); sigemptyset(&action.sa_mask); action.sa_handler = sigterm_handler; sigaction(SIGTERM, &action, NULL); #else signal(SIGTERM, sigterm_handler); #endif /* HAVE_SIGSET */ /* * Check command-line... */ if (argc >= 6) exec_backend(argv); else if (argc != 1) { _cupsLangPrintf(stderr, _("Usage: %s job-id user title copies options [file]"), argv[0]); return (1); } /* * Only do discovery when run as "dnssd"... */ if ((name = strrchr(argv[0], '/')) != NULL) name ++; else name = argv[0]; if (strcmp(name, "dnssd")) return (0); /* * Create an array to track devices... */ devices = cupsArrayNew((cups_array_func_t)compare_devices, NULL); /* * Browse for different kinds of printers... */ #ifdef HAVE_DNSSD if (DNSServiceCreateConnection(&main_ref) != kDNSServiceErr_NoError) { perror("ERROR: Unable to create service connection"); return (1); } fd = DNSServiceRefSockFD(main_ref); fax_ipp_ref = main_ref; DNSServiceBrowse(&fax_ipp_ref, kDNSServiceFlagsShareConnection, 0, "_fax-ipp._tcp", NULL, browse_callback, devices); ipp_ref = main_ref; DNSServiceBrowse(&ipp_ref, kDNSServiceFlagsShareConnection, 0, "_ipp._tcp", NULL, browse_callback, devices); ipp_tls_ref = main_ref; DNSServiceBrowse(&ipp_tls_ref, kDNSServiceFlagsShareConnection, 0, "_ipp-tls._tcp", NULL, browse_callback, devices); ipps_ref = main_ref; DNSServiceBrowse(&ipps_ref, kDNSServiceFlagsShareConnection, 0, "_ipps._tcp", NULL, browse_callback, devices); local_fax_ipp_ref = main_ref; DNSServiceBrowse(&local_fax_ipp_ref, kDNSServiceFlagsShareConnection, kDNSServiceInterfaceIndexLocalOnly, "_fax-ipp._tcp", NULL, browse_local_callback, devices); local_ipp_ref = main_ref; DNSServiceBrowse(&local_ipp_ref, kDNSServiceFlagsShareConnection, kDNSServiceInterfaceIndexLocalOnly, "_ipp._tcp", NULL, browse_local_callback, devices); local_ipp_tls_ref = main_ref; DNSServiceBrowse(&local_ipp_tls_ref, kDNSServiceFlagsShareConnection, kDNSServiceInterfaceIndexLocalOnly, "_ipp-tls._tcp", NULL, browse_local_callback, devices); local_ipps_ref = main_ref; DNSServiceBrowse(&local_ipps_ref, kDNSServiceFlagsShareConnection, kDNSServiceInterfaceIndexLocalOnly, "_ipps._tcp", NULL, browse_local_callback, devices); local_printer_ref = main_ref; DNSServiceBrowse(&local_printer_ref, kDNSServiceFlagsShareConnection, kDNSServiceInterfaceIndexLocalOnly, "_printer._tcp", NULL, browse_local_callback, devices); pdl_datastream_ref = main_ref; DNSServiceBrowse(&pdl_datastream_ref, kDNSServiceFlagsShareConnection, 0, "_pdl-datastream._tcp", NULL, browse_callback, devices); printer_ref = main_ref; DNSServiceBrowse(&printer_ref, kDNSServiceFlagsShareConnection, 0, "_printer._tcp", NULL, browse_callback, devices); riousbprint_ref = main_ref; DNSServiceBrowse(&riousbprint_ref, kDNSServiceFlagsShareConnection, 0, "_riousbprint._tcp", NULL, browse_callback, devices); #endif /* HAVE_DNSSD */ #ifdef HAVE_AVAHI if ((simple_poll = avahi_simple_poll_new()) == NULL) { fputs("DEBUG: Unable to create Avahi simple poll object.\n", stderr); return (0); } avahi_simple_poll_set_func(simple_poll, poll_callback, NULL); client = avahi_client_new(avahi_simple_poll_get(simple_poll), 0, client_callback, simple_poll, &error); if (!client) { fputs("DEBUG: Unable to create Avahi client.\n", stderr); return (0); } browsers = 6; avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_fax-ipp._tcp", NULL, 0, browse_callback, devices); avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_ipp._tcp", NULL, 0, browse_callback, devices); avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_ipp-tls._tcp", NULL, 0, browse_callback, devices); avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_ipps._tcp", NULL, 0, browse_callback, devices); avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_pdl-datastream._tcp", NULL, 0, browse_callback, devices); avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_printer._tcp", NULL, 0, browse_callback, devices); #endif /* HAVE_AVAHI */ /* * Loop until we are killed... */ while (!job_canceled) { int announce = 0; /* Announce printers? */ #ifdef HAVE_DNSSD FD_ZERO(&input); FD_SET(fd, &input); timeout.tv_sec = 0; timeout.tv_usec = 500000; if (select(fd + 1, &input, NULL, NULL, &timeout) < 0) continue; if (FD_ISSET(fd, &input)) { /* * Process results of our browsing... */ DNSServiceProcessResult(main_ref); } else announce = 1; #elif defined(HAVE_AVAHI) got_data = 0; if ((error = avahi_simple_poll_iterate(simple_poll, 500)) > 0) { /* * We've been told to exit the loop. Perhaps the connection to * Avahi failed. */ break; } if (!got_data) announce = 1; #endif /* HAVE_DNSSD */ /* fprintf(stderr, "DEBUG: announce=%d\n", announce);*/ if (announce) { /* * Announce any devices we've found... */ #ifdef HAVE_DNSSD DNSServiceErrorType status; /* DNS query status */ #endif /* HAVE_DNSSD */ cups_device_t *best; /* Best matching device */ char device_uri[1024]; /* Device URI */ int count; /* Number of queries */ int sent; /* Number of sent */ for (device = (cups_device_t *)cupsArrayFirst(devices), best = NULL, count = 0, sent = 0; device; device = (cups_device_t *)cupsArrayNext(devices)) { if (device->sent) sent ++; if (device->ref) count ++; if (!device->ref && !device->sent) { /* * Found the device, now get the TXT record(s) for it... */ if (count < 50) { fprintf(stderr, "DEBUG: Querying \"%s\"...\n", device->fullName); #ifdef HAVE_DNSSD device->ref = main_ref; status = DNSServiceQueryRecord(&(device->ref), kDNSServiceFlagsShareConnection, 0, device->fullName, kDNSServiceType_TXT, kDNSServiceClass_IN, query_callback, device); if (status != kDNSServiceErr_NoError) fprintf(stderr, "ERROR: Unable to query \"%s\" for TXT records: %d\n", device->fullName, status); /* Users never see this */ else count ++; #else if ((device->ref = avahi_record_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, device->fullName, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_TXT, 0, query_callback, device)) == NULL) fprintf(stderr, "ERROR: Unable to query \"%s\" for TXT records: %s\n", device->fullName, avahi_strerror(avahi_client_errno(client))); /* Users never see this */ else count ++; #endif /* HAVE_AVAHI */ } } else if (!device->sent) { #ifdef HAVE_DNSSD /* * Got the TXT records, now report the device... */ DNSServiceRefDeallocate(device->ref); #else avahi_record_browser_free(device->ref); #endif /* HAVE_DNSSD */ device->ref = NULL; if (!best) best = device; else if (_cups_strcasecmp(best->name, device->name) || _cups_strcasecmp(best->domain, device->domain)) { unquote(uriName, best->fullName, sizeof(uriName)); if (best->uuid) httpAssembleURIf(HTTP_URI_CODING_ALL, device_uri, sizeof(device_uri), "dnssd", NULL, uriName, 0, best->cups_shared ? "/cups?uuid=%s" : "/?uuid=%s", best->uuid); else httpAssembleURI(HTTP_URI_CODING_ALL, device_uri, sizeof(device_uri), "dnssd", NULL, uriName, 0, best->cups_shared ? "/cups" : "/"); cupsBackendReport("network", device_uri, best->make_and_model, best->name, best->device_id, NULL); best->sent = 1; best = device; sent ++; } else if (best->priority > device->priority || (best->priority == device->priority && best->type < device->type)) { best->sent = 1; best = device; sent ++; } else { device->sent = 1; sent ++; } } } if (best) { unquote(uriName, best->fullName, sizeof(uriName)); if (best->uuid) httpAssembleURIf(HTTP_URI_CODING_ALL, device_uri, sizeof(device_uri), "dnssd", NULL, uriName, 0, best->cups_shared ? "/cups?uuid=%s" : "/?uuid=%s", best->uuid); else httpAssembleURI(HTTP_URI_CODING_ALL, device_uri, sizeof(device_uri), "dnssd", NULL, uriName, 0, best->cups_shared ? "/cups" : "/"); cupsBackendReport("network", device_uri, best->make_and_model, best->name, best->device_id, NULL); best->sent = 1; sent ++; } fprintf(stderr, "DEBUG: sent=%d, count=%d\n", sent, count); #ifdef HAVE_AVAHI if (sent == cupsArrayCount(devices) && browsers == 0) #else if (sent == cupsArrayCount(devices)) #endif /* HAVE_AVAHI */ break; } } return (CUPS_BACKEND_OK); }
static void resolve_callback( DNSServiceRef sdRef, /* I - Service reference */ DNSServiceFlags flags, /* I - Data flags */ uint32_t interfaceIndex, /* I - Interface */ DNSServiceErrorType errorCode, /* I - Error, if any */ const char *fullName, /* I - Full service name */ const char *hostTarget, /* I - Hostname */ uint16_t port, /* I - Port number (network byte order) */ uint16_t txtLen, /* I - Length of TXT record data */ const unsigned char *txtRecord, /* I - TXT record data */ void *context) /* I - Device */ { char temp[257], /* TXT key value */ uri[1024]; /* Printer URI */ const void *value; /* Value from TXT record */ uint8_t valueLen; /* Length of value */ cups_device_t *device = (cups_device_t *)context; /* Device */ #ifdef DEBUG fprintf(stderr, "\rresolve_callback(sdRef=%p, flags=%x, " "interfaceIndex=%d, errorCode=%d, fullName=\"%s\", " "hostTarget=\"%s\", port=%d, txtLen=%u, txtRecord=%p, " "context=%p)\n", sdRef, flags, interfaceIndex, errorCode, fullName ? fullName : "(null)", hostTarget ? hostTarget : "(null)", ntohs(port), txtLen, txtRecord, context); #endif /* DEBUG */ /* * Only process "add" data... */ if (errorCode != kDNSServiceErr_NoError) return; device->got_resolve = 1; device->host = strdup(hostTarget); device->port = ntohs(port); /* * Extract the "remote printer" key from the TXT record and save the URI... */ if ((value = TXTRecordGetValuePtr(txtLen, txtRecord, "rp", &valueLen)) != NULL) { if (((char *)value)[0] == '/') { /* * "rp" value (incorrectly) has a leading slash already... */ memcpy(temp, value, valueLen); temp[valueLen] = '\0'; } else { /* * Convert to resource by concatenating with a leading "/"... */ temp[0] = '/'; memcpy(temp + 1, value, valueLen); temp[valueLen + 1] = '\0'; } } else { /* * Default "rp" value is blank, mapping to a path of "/"... */ temp[0] = '/'; temp[1] = '\0'; } if (!strncmp(temp, "/printers/", 10)) device->cups_shared = -1; httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, hostTarget, ntohs(port), temp); device->uri = strdup(uri); device->rp = strdup(temp); if ((value = TXTRecordGetValuePtr(txtLen, txtRecord, "ty", &valueLen)) != NULL) { memcpy(temp, value, valueLen); temp[valueLen] = '\0'; device->ty = strdup(temp); } if ((value = TXTRecordGetValuePtr(txtLen, txtRecord, "pdl", &valueLen)) != NULL) { memcpy(temp, value, valueLen); temp[valueLen] = '\0'; device->pdl = strdup(temp); } if ((value = TXTRecordGetValuePtr(txtLen, txtRecord, "printer-type", &valueLen)) != NULL) device->cups_shared = 1; if (device->cups_shared) fprintf(stderr, "\rIgnoring CUPS printer %s\n", uri); else fprintf(stderr, "\rFound IPP printer %s\n", uri); progress(); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int i; /* Looping var */ http_t *http; /* HTTP connection */ const char *server = NULL; /* Hostname from command-line */ int port = 0; /* Port number */ const char *cipherName = "UNKNOWN";/* Cipher suite name */ int dhBits = 0; /* Diffie-Hellman bits */ int tlsVersion = 0; /* TLS version number */ char uri[1024], /* Printer URI */ scheme[32], /* URI scheme */ host[256], /* Hostname */ userpass[256], /* Username/password */ resource[256]; /* Resource path */ int af = AF_UNSPEC, /* Address family */ tls_options = _HTTP_TLS_NONE, /* TLS options */ tls_min_version = _HTTP_TLS_1_0, tls_max_version = _HTTP_TLS_MAX, verbose = 0; /* Verbosity */ ipp_t *request, /* IPP Get-Printer-Attributes request */ *response; /* IPP Get-Printer-Attributes response */ ipp_attribute_t *attr; /* Current attribute */ const char *name; /* Attribute name */ char value[1024]; /* Attribute (string) value */ static const char * const pattrs[] = /* Requested attributes */ { "color-supported", "compression-supported", "document-format-supported", "pages-per-minute", "printer-location", "printer-make-and-model", "printer-state", "printer-state-reasons", "sides-supported", "uri-authentication-supported", "uri-security-supported" }; for (i = 1; i < argc; i ++) { if (!strcmp(argv[i], "--dh")) { tls_options |= _HTTP_TLS_ALLOW_DH; } else if (!strcmp(argv[i], "--no-cbc")) { tls_options |= _HTTP_TLS_DENY_CBC; } else if (!strcmp(argv[i], "--no-tls10")) { tls_min_version = _HTTP_TLS_1_1; } else if (!strcmp(argv[i], "--tls10")) { tls_min_version = _HTTP_TLS_1_0; tls_max_version = _HTTP_TLS_1_0; } else if (!strcmp(argv[i], "--rc4")) { tls_options |= _HTTP_TLS_ALLOW_RC4; } else if (!strcmp(argv[i], "--verbose") || !strcmp(argv[i], "-v")) { verbose = 1; } else if (!strcmp(argv[i], "-4")) { af = AF_INET; } else if (!strcmp(argv[i], "-6")) { af = AF_INET6; } else if (argv[i][0] == '-') { printf("tlscheck: Unknown option '%s'.\n", argv[i]); usage(); } else if (!server) { if (!strncmp(argv[i], "ipps://", 7)) { httpSeparateURI(HTTP_URI_CODING_ALL, argv[i], scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)); server = host; } else { server = argv[i]; strlcpy(resource, "/ipp/print", sizeof(resource)); } } else if (!port && (argv[i][0] == '=' || isdigit(argv[i][0] & 255))) { if (argv[i][0] == '=') port = atoi(argv[i] + 1); else port = atoi(argv[i]); } else { printf("tlscheck: Unexpected argument '%s'.\n", argv[i]); usage(); } } if (!server) usage(); if (!port) port = 631; _httpTLSSetOptions(tls_options, tls_min_version, tls_max_version); http = httpConnect2(server, port, NULL, af, HTTP_ENCRYPTION_ALWAYS, 1, 30000, NULL); if (!http) { printf("%s: ERROR (%s)\n", server, cupsLastErrorString()); return (1); } #ifdef __APPLE__ SSLProtocol protocol; SSLCipherSuite cipher; char unknownCipherName[256]; int paramsNeeded = 0; const void *params; size_t paramsLen; OSStatus err; if ((err = SSLGetNegotiatedProtocolVersion(http->tls, &protocol)) != noErr) { printf("%s: ERROR (No protocol version - %d)\n", server, (int)err); httpClose(http); return (1); } switch (protocol) { default : tlsVersion = 0; break; case kSSLProtocol3 : tlsVersion = 30; break; case kTLSProtocol1 : tlsVersion = 10; break; case kTLSProtocol11 : tlsVersion = 11; break; case kTLSProtocol12 : tlsVersion = 12; break; } if ((err = SSLGetNegotiatedCipher(http->tls, &cipher)) != noErr) { printf("%s: ERROR (No cipher suite - %d)\n", server, (int)err); httpClose(http); return (1); } switch (cipher) { case TLS_NULL_WITH_NULL_NULL: cipherName = "TLS_NULL_WITH_NULL_NULL"; break; case TLS_RSA_WITH_NULL_MD5: cipherName = "TLS_RSA_WITH_NULL_MD5"; break; case TLS_RSA_WITH_NULL_SHA: cipherName = "TLS_RSA_WITH_NULL_SHA"; break; case TLS_RSA_WITH_RC4_128_MD5: cipherName = "TLS_RSA_WITH_RC4_128_MD5"; break; case TLS_RSA_WITH_RC4_128_SHA: cipherName = "TLS_RSA_WITH_RC4_128_SHA"; break; case TLS_RSA_WITH_3DES_EDE_CBC_SHA: cipherName = "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; break; case TLS_RSA_WITH_NULL_SHA256: cipherName = "TLS_RSA_WITH_NULL_SHA256"; break; case TLS_RSA_WITH_AES_128_CBC_SHA256: cipherName = "TLS_RSA_WITH_AES_128_CBC_SHA256"; break; case TLS_RSA_WITH_AES_256_CBC_SHA256: cipherName = "TLS_RSA_WITH_AES_256_CBC_SHA256"; break; case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: cipherName = "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"; paramsNeeded = 1; break; case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: cipherName = "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"; paramsNeeded = 1; break; case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: cipherName = "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; paramsNeeded = 1; break; case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: cipherName = "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; paramsNeeded = 1; break; case TLS_DH_DSS_WITH_AES_128_CBC_SHA256: cipherName = "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"; paramsNeeded = 1; break; case TLS_DH_RSA_WITH_AES_128_CBC_SHA256: cipherName = "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"; paramsNeeded = 1; break; case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: cipherName = "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"; paramsNeeded = 1; break; case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: cipherName = "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"; paramsNeeded = 1; break; case TLS_DH_DSS_WITH_AES_256_CBC_SHA256: cipherName = "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"; paramsNeeded = 1; break; case TLS_DH_RSA_WITH_AES_256_CBC_SHA256: cipherName = "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"; paramsNeeded = 1; break; case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: cipherName = "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"; paramsNeeded = 1; break; case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: cipherName = "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"; paramsNeeded = 1; break; case TLS_DH_anon_WITH_RC4_128_MD5: cipherName = "TLS_DH_anon_WITH_RC4_128_MD5"; paramsNeeded = 1; break; case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA: cipherName = "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; paramsNeeded = 1; break; case TLS_DH_anon_WITH_AES_128_CBC_SHA256: cipherName = "TLS_DH_anon_WITH_AES_128_CBC_SHA256"; paramsNeeded = 1; break; case TLS_DH_anon_WITH_AES_256_CBC_SHA256: cipherName = "TLS_DH_anon_WITH_AES_256_CBC_SHA256"; paramsNeeded = 1; break; case TLS_PSK_WITH_RC4_128_SHA: cipherName = "TLS_PSK_WITH_RC4_128_SHA"; break; case TLS_PSK_WITH_3DES_EDE_CBC_SHA: cipherName = "TLS_PSK_WITH_3DES_EDE_CBC_SHA"; break; case TLS_PSK_WITH_AES_128_CBC_SHA: cipherName = "TLS_PSK_WITH_AES_128_CBC_SHA"; break; case TLS_PSK_WITH_AES_256_CBC_SHA: cipherName = "TLS_PSK_WITH_AES_256_CBC_SHA"; break; case TLS_DHE_PSK_WITH_RC4_128_SHA: cipherName = "TLS_DHE_PSK_WITH_RC4_128_SHA"; paramsNeeded = 1; break; case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: cipherName = "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA"; paramsNeeded = 1; break; case TLS_DHE_PSK_WITH_AES_128_CBC_SHA: cipherName = "TLS_DHE_PSK_WITH_AES_128_CBC_SHA"; paramsNeeded = 1; break; case TLS_DHE_PSK_WITH_AES_256_CBC_SHA: cipherName = "TLS_DHE_PSK_WITH_AES_256_CBC_SHA"; paramsNeeded = 1; break; case TLS_RSA_PSK_WITH_RC4_128_SHA: cipherName = "TLS_RSA_PSK_WITH_RC4_128_SHA"; break; case TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: cipherName = "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"; break; case TLS_RSA_PSK_WITH_AES_128_CBC_SHA: cipherName = "TLS_RSA_PSK_WITH_AES_128_CBC_SHA"; break; case TLS_RSA_PSK_WITH_AES_256_CBC_SHA: cipherName = "TLS_RSA_PSK_WITH_AES_256_CBC_SHA"; break; case TLS_PSK_WITH_NULL_SHA: cipherName = "TLS_PSK_WITH_NULL_SHA"; break; case TLS_DHE_PSK_WITH_NULL_SHA: cipherName = "TLS_DHE_PSK_WITH_NULL_SHA"; paramsNeeded = 1; break; case TLS_RSA_PSK_WITH_NULL_SHA: cipherName = "TLS_RSA_PSK_WITH_NULL_SHA"; break; case TLS_RSA_WITH_AES_128_GCM_SHA256: cipherName = "TLS_RSA_WITH_AES_128_GCM_SHA256"; break; case TLS_RSA_WITH_AES_256_GCM_SHA384: cipherName = "TLS_RSA_WITH_AES_256_GCM_SHA384"; break; case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: cipherName = "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"; paramsNeeded = 1; break; case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: cipherName = "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"; paramsNeeded = 1; break; case TLS_DH_RSA_WITH_AES_128_GCM_SHA256: cipherName = "TLS_DH_RSA_WITH_AES_128_GCM_SHA256"; paramsNeeded = 1; break; case TLS_DH_RSA_WITH_AES_256_GCM_SHA384: cipherName = "TLS_DH_RSA_WITH_AES_256_GCM_SHA384"; paramsNeeded = 1; break; case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: cipherName = "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"; paramsNeeded = 1; break; case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: cipherName = "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"; paramsNeeded = 1; break; case TLS_DH_DSS_WITH_AES_128_GCM_SHA256: cipherName = "TLS_DH_DSS_WITH_AES_128_GCM_SHA256"; paramsNeeded = 1; break; case TLS_DH_DSS_WITH_AES_256_GCM_SHA384: cipherName = "TLS_DH_DSS_WITH_AES_256_GCM_SHA384"; paramsNeeded = 1; break; case TLS_DH_anon_WITH_AES_128_GCM_SHA256: cipherName = "TLS_DH_anon_WITH_AES_128_GCM_SHA256"; paramsNeeded = 1; break; case TLS_DH_anon_WITH_AES_256_GCM_SHA384: cipherName = "TLS_DH_anon_WITH_AES_256_GCM_SHA384"; paramsNeeded = 1; break; case TLS_PSK_WITH_AES_128_GCM_SHA256: cipherName = "TLS_PSK_WITH_AES_128_GCM_SHA256"; break; case TLS_PSK_WITH_AES_256_GCM_SHA384: cipherName = "TLS_PSK_WITH_AES_256_GCM_SHA384"; break; case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: cipherName = "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"; paramsNeeded = 1; break; case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: cipherName = "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"; paramsNeeded = 1; break; case TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: cipherName = "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"; break; case TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: cipherName = "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384"; break; case TLS_PSK_WITH_AES_128_CBC_SHA256: cipherName = "TLS_PSK_WITH_AES_128_CBC_SHA256"; break; case TLS_PSK_WITH_AES_256_CBC_SHA384: cipherName = "TLS_PSK_WITH_AES_256_CBC_SHA384"; break; case TLS_PSK_WITH_NULL_SHA256: cipherName = "TLS_PSK_WITH_NULL_SHA256"; break; case TLS_PSK_WITH_NULL_SHA384: cipherName = "TLS_PSK_WITH_NULL_SHA384"; break; case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: cipherName = "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"; paramsNeeded = 1; break; case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: cipherName = "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"; paramsNeeded = 1; break; case TLS_DHE_PSK_WITH_NULL_SHA256: cipherName = "TLS_DHE_PSK_WITH_NULL_SHA256"; paramsNeeded = 1; break; case TLS_DHE_PSK_WITH_NULL_SHA384: cipherName = "TLS_DHE_PSK_WITH_NULL_SHA384"; paramsNeeded = 1; break; case TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: cipherName = "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"; break; case TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: cipherName = "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"; break; case TLS_RSA_PSK_WITH_NULL_SHA256: cipherName = "TLS_RSA_PSK_WITH_NULL_SHA256"; break; case TLS_RSA_PSK_WITH_NULL_SHA384: cipherName = "TLS_RSA_PSK_WITH_NULL_SHA384"; break; case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: cipherName = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"; paramsNeeded = 1; break; case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: cipherName = "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"; paramsNeeded = 1; break; case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: cipherName = "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"; paramsNeeded = 1; break; case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: cipherName = "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"; paramsNeeded = 1; break; case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: cipherName = "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"; paramsNeeded = 1; break; case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: cipherName = "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"; paramsNeeded = 1; break; case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: cipherName = "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"; paramsNeeded = 1; break; case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: cipherName = "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"; paramsNeeded = 1; break; case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: cipherName = "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"; paramsNeeded = 1; break; case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: cipherName = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"; paramsNeeded = 1; break; case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: cipherName = "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"; paramsNeeded = 1; break; case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: cipherName = "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"; paramsNeeded = 1; break; case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: cipherName = "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"; paramsNeeded = 1; break; case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: cipherName = "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"; paramsNeeded = 1; break; case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: cipherName = "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"; paramsNeeded = 1; break; case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: cipherName = "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"; paramsNeeded = 1; break; case TLS_RSA_WITH_AES_128_CBC_SHA: cipherName = "TLS_RSA_WITH_AES_128_CBC_SHA"; break; case TLS_DH_DSS_WITH_AES_128_CBC_SHA: cipherName = "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; paramsNeeded = 1; break; case TLS_DH_RSA_WITH_AES_128_CBC_SHA: cipherName = "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; paramsNeeded = 1; break; case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: cipherName = "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; paramsNeeded = 1; break; case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: cipherName = "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; paramsNeeded = 1; break; case TLS_DH_anon_WITH_AES_128_CBC_SHA: cipherName = "TLS_DH_anon_WITH_AES_128_CBC_SHA"; paramsNeeded = 1; break; case TLS_RSA_WITH_AES_256_CBC_SHA: cipherName = "TLS_RSA_WITH_AES_256_CBC_SHA"; break; case TLS_DH_DSS_WITH_AES_256_CBC_SHA: cipherName = "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; paramsNeeded = 1; break; case TLS_DH_RSA_WITH_AES_256_CBC_SHA: cipherName = "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; paramsNeeded = 1; break; case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: cipherName = "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; paramsNeeded = 1; break; case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: cipherName = "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; paramsNeeded = 1; break; case TLS_DH_anon_WITH_AES_256_CBC_SHA: cipherName = "TLS_DH_anon_WITH_AES_256_CBC_SHA"; paramsNeeded = 1; break; case TLS_ECDH_ECDSA_WITH_NULL_SHA: cipherName = "TLS_ECDH_ECDSA_WITH_NULL_SHA"; paramsNeeded = 1; break; case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: cipherName = "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"; paramsNeeded = 1; break; case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: cipherName = "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"; paramsNeeded = 1; break; case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: cipherName = "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"; paramsNeeded = 1; break; case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: cipherName = "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"; paramsNeeded = 1; break; case TLS_ECDHE_ECDSA_WITH_NULL_SHA: cipherName = "TLS_ECDHE_ECDSA_WITH_NULL_SHA"; paramsNeeded = 1; break; case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: cipherName = "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"; paramsNeeded = 1; break; case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: cipherName = "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"; paramsNeeded = 1; break; case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: cipherName = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"; paramsNeeded = 1; break; case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: cipherName = "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"; paramsNeeded = 1; break; case TLS_ECDH_RSA_WITH_NULL_SHA: cipherName = "TLS_ECDH_RSA_WITH_NULL_SHA"; paramsNeeded = 1; break; case TLS_ECDH_RSA_WITH_RC4_128_SHA: cipherName = "TLS_ECDH_RSA_WITH_RC4_128_SHA"; paramsNeeded = 1; break; case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: cipherName = "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"; paramsNeeded = 1; break; case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: cipherName = "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"; paramsNeeded = 1; break; case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: cipherName = "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"; paramsNeeded = 1; break; case TLS_ECDHE_RSA_WITH_NULL_SHA: cipherName = "TLS_ECDHE_RSA_WITH_NULL_SHA"; paramsNeeded = 1; break; case TLS_ECDHE_RSA_WITH_RC4_128_SHA: cipherName = "TLS_ECDHE_RSA_WITH_RC4_128_SHA"; paramsNeeded = 1; break; case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: cipherName = "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"; paramsNeeded = 1; break; case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: cipherName = "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"; paramsNeeded = 1; break; case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: cipherName = "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"; paramsNeeded = 1; break; case TLS_ECDH_anon_WITH_NULL_SHA: cipherName = "TLS_ECDH_anon_WITH_NULL_SHA"; paramsNeeded = 1; break; case TLS_ECDH_anon_WITH_RC4_128_SHA: cipherName = "TLS_ECDH_anon_WITH_RC4_128_SHA"; paramsNeeded = 1; break; case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA: cipherName = "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"; paramsNeeded = 1; break; case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: cipherName = "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"; paramsNeeded = 1; break; case TLS_ECDH_anon_WITH_AES_256_CBC_SHA: cipherName = "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"; paramsNeeded = 1; break; default : snprintf(unknownCipherName, sizeof(unknownCipherName), "UNKNOWN_%04X", cipher); cipherName = unknownCipherName; break; } if (cipher == TLS_RSA_WITH_RC4_128_MD5 || cipher == TLS_RSA_WITH_RC4_128_SHA) { printf("%s: ERROR (Printers MUST NOT negotiate RC4 cipher suites.)\n", server); httpClose(http); return (1); } if ((err = SSLGetDiffieHellmanParams(http->tls, ¶ms, ¶msLen)) != noErr && paramsNeeded) { printf("%s: ERROR (Unable to get Diffie-Hellman parameters - %d)\n", server, (int)err); httpClose(http); return (1); } if (paramsLen < 128 && paramsLen != 0) { printf("%s: ERROR (Diffie-Hellman parameters MUST be at least 2048 bits, but Printer uses only %d bits/%d bytes)\n", server, (int)paramsLen * 8, (int)paramsLen); httpClose(http); return (1); } dhBits = (int)paramsLen * 8; #endif /* __APPLE__ */ if (dhBits > 0) printf("%s: OK (TLS: %d.%d, %s, %d DH bits)\n", server, tlsVersion / 10, tlsVersion % 10, cipherName, dhBits); else printf("%s: OK (TLS: %d.%d, %s)\n", server, tlsVersion / 10, tlsVersion % 10, cipherName); if (verbose) { httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipps", NULL, host, port, resource); request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(pattrs) / sizeof(pattrs[0])), NULL, pattrs); response = cupsDoRequest(http, request, resource); for (attr = ippFirstAttribute(response); attr; attr = ippNextAttribute(response)) { if (ippGetGroupTag(attr) != IPP_TAG_PRINTER) continue; if ((name = ippGetName(attr)) == NULL) continue; ippAttributeString(attr, value, sizeof(value)); printf(" %s=%s\n", name, value); } ippDelete(response); } httpClose(http); return (0); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int i, j, k; /* Looping vars */ http_t *http; /* HTTP connection */ http_encryption_t encryption; /* Encryption type */ http_status_t status; /* Status of GET command */ int failures; /* Number of test failures */ char buffer[8192]; /* Input buffer */ long bytes; /* Number of bytes read */ FILE *out; /* Output file */ char encode[256], /* Base64-encoded string */ decode[256]; /* Base64-decoded string */ int decodelen; /* Length of decoded string */ char scheme[HTTP_MAX_URI], /* Scheme from URI */ hostname[HTTP_MAX_URI], /* Hostname from URI */ username[HTTP_MAX_URI], /* Username:password from URI */ resource[HTTP_MAX_URI]; /* Resource from URI */ int port; /* Port number from URI */ http_uri_status_t uri_status; /* Status of URI separation */ http_addrlist_t *addrlist, /* Address list */ *addr; /* Current address */ off_t length, total; /* Length and total bytes */ time_t start, current; /* Start and end time */ const char *encoding; /* Negotiated Content-Encoding */ static const char * const uri_status_strings[] = { "HTTP_URI_STATUS_OVERFLOW", "HTTP_URI_STATUS_BAD_ARGUMENTS", "HTTP_URI_STATUS_BAD_RESOURCE", "HTTP_URI_STATUS_BAD_PORT", "HTTP_URI_STATUS_BAD_HOSTNAME", "HTTP_URI_STATUS_BAD_USERNAME", "HTTP_URI_STATUS_BAD_SCHEME", "HTTP_URI_STATUS_BAD_URI", "HTTP_URI_STATUS_OK", "HTTP_URI_STATUS_MISSING_SCHEME", "HTTP_URI_STATUS_UNKNOWN_SCHEME", "HTTP_URI_STATUS_MISSING_RESOURCE" }; /* * Do API tests if we don't have a URL on the command-line... */ if (argc == 1) { failures = 0; /* * httpGetDateString()/httpGetDateTime() */ fputs("httpGetDateString()/httpGetDateTime(): ", stdout); start = time(NULL); strlcpy(buffer, httpGetDateString(start), sizeof(buffer)); current = httpGetDateTime(buffer); i = (int)(current - start); if (i < 0) i = -i; if (!i) puts("PASS"); else { failures ++; puts("FAIL"); printf(" Difference is %d seconds, %02d:%02d:%02d...\n", i, i / 3600, (i / 60) % 60, i % 60); printf(" httpGetDateString(%d) returned \"%s\"\n", (int)start, buffer); printf(" httpGetDateTime(\"%s\") returned %d\n", buffer, (int)current); printf(" httpGetDateString(%d) returned \"%s\"\n", (int)current, httpGetDateString(current)); } /* * httpDecode64_2()/httpEncode64_2() */ fputs("httpDecode64_2()/httpEncode64_2(): ", stdout); for (i = 0, j = 0; i < (int)(sizeof(base64_tests) / sizeof(base64_tests[0])); i ++) { httpEncode64_2(encode, sizeof(encode), base64_tests[i][0], (int)strlen(base64_tests[i][0])); decodelen = (int)sizeof(decode); httpDecode64_2(decode, &decodelen, base64_tests[i][1]); if (strcmp(decode, base64_tests[i][0])) { failures ++; if (j) { puts("FAIL"); j = 1; } printf(" httpDecode64_2() returned \"%s\", expected \"%s\"...\n", decode, base64_tests[i][0]); } if (strcmp(encode, base64_tests[i][1])) { failures ++; if (j) { puts("FAIL"); j = 1; } printf(" httpEncode64_2() returned \"%s\", expected \"%s\"...\n", encode, base64_tests[i][1]); } } if (!j) puts("PASS"); /* * httpGetHostname() */ fputs("httpGetHostname(): ", stdout); if (httpGetHostname(NULL, hostname, sizeof(hostname))) printf("PASS (%s)\n", hostname); else { failures ++; puts("FAIL"); } /* * httpAddrGetList() */ printf("httpAddrGetList(%s): ", hostname); addrlist = httpAddrGetList(hostname, AF_UNSPEC, NULL); if (addrlist) { for (i = 0, addr = addrlist; addr; i ++, addr = addr->next) { char numeric[1024]; /* Numeric IP address */ httpAddrString(&(addr->addr), numeric, sizeof(numeric)); if (!strcmp(numeric, "UNKNOWN")) break; } if (addr) printf("FAIL (bad address for %s)\n", hostname); else printf("PASS (%d address(es) for %s)\n", i, hostname); httpAddrFreeList(addrlist); } else if (isdigit(hostname[0] & 255)) { puts("FAIL (ignored because hostname is numeric)"); } else { failures ++; puts("FAIL"); } /* * Test httpSeparateURI()... */ fputs("httpSeparateURI(): ", stdout); for (i = 0, j = 0; i < (int)(sizeof(uri_tests) / sizeof(uri_tests[0])); i ++) { uri_status = httpSeparateURI(HTTP_URI_CODING_MOST, uri_tests[i].uri, scheme, sizeof(scheme), username, sizeof(username), hostname, sizeof(hostname), &port, resource, sizeof(resource)); if (uri_status != uri_tests[i].result || strcmp(scheme, uri_tests[i].scheme) || strcmp(username, uri_tests[i].username) || strcmp(hostname, uri_tests[i].hostname) || port != uri_tests[i].port || strcmp(resource, uri_tests[i].resource)) { failures ++; if (!j) { puts("FAIL"); j = 1; } printf(" \"%s\":\n", uri_tests[i].uri); if (uri_status != uri_tests[i].result) printf(" Returned %s instead of %s\n", uri_status_strings[uri_status + 8], uri_status_strings[uri_tests[i].result + 8]); if (strcmp(scheme, uri_tests[i].scheme)) printf(" Scheme \"%s\" instead of \"%s\"\n", scheme, uri_tests[i].scheme); if (strcmp(username, uri_tests[i].username)) printf(" Username \"%s\" instead of \"%s\"\n", username, uri_tests[i].username); if (strcmp(hostname, uri_tests[i].hostname)) printf(" Hostname \"%s\" instead of \"%s\"\n", hostname, uri_tests[i].hostname); if (port != uri_tests[i].port) printf(" Port %d instead of %d\n", port, uri_tests[i].port); if (strcmp(resource, uri_tests[i].resource)) printf(" Resource \"%s\" instead of \"%s\"\n", resource, uri_tests[i].resource); } } if (!j) printf("PASS (%d URIs tested)\n", (int)(sizeof(uri_tests) / sizeof(uri_tests[0]))); /* * Test httpAssembleURI()... */ fputs("httpAssembleURI(): ", stdout); for (i = 0, j = 0, k = 0; i < (int)(sizeof(uri_tests) / sizeof(uri_tests[0])); i ++) if (uri_tests[i].result == HTTP_URI_STATUS_OK && !strstr(uri_tests[i].uri, "%64") && strstr(uri_tests[i].uri, "//")) { k ++; uri_status = httpAssembleURI(uri_tests[i].assemble_coding, buffer, sizeof(buffer), uri_tests[i].scheme, uri_tests[i].username, uri_tests[i].hostname, uri_tests[i].assemble_port, uri_tests[i].resource); if (uri_status != HTTP_URI_STATUS_OK) { failures ++; if (!j) { puts("FAIL"); j = 1; } printf(" \"%s\": %s\n", uri_tests[i].uri, uri_status_strings[uri_status + 8]); } else if (strcmp(buffer, uri_tests[i].uri)) { failures ++; if (!j) { puts("FAIL"); j = 1; } printf(" \"%s\": assembled = \"%s\"\n", uri_tests[i].uri, buffer); } } if (!j) printf("PASS (%d URIs tested)\n", k); /* * httpAssembleUUID */ fputs("httpAssembleUUID: ", stdout); httpAssembleUUID("hostname.example.com", 631, "printer", 12345, buffer, sizeof(buffer)); if (strncmp(buffer, "urn:uuid:", 9)) { printf("FAIL (%s)\n", buffer); failures ++; } else printf("PASS (%s)\n", buffer); /* * Show a summary and return... */ if (failures) printf("\n%d TESTS FAILED!\n", failures); else puts("\nALL TESTS PASSED!"); return (failures); } else if (strstr(argv[1], "._tcp")) { /* * Test resolving an mDNS name. */ char resolved[1024]; /* Resolved URI */ printf("_httpResolveURI(%s, _HTTP_RESOLVE_DEFAULT): ", argv[1]); fflush(stdout); if (!_httpResolveURI(argv[1], resolved, sizeof(resolved), _HTTP_RESOLVE_DEFAULT, NULL, NULL)) { puts("FAIL"); return (1); } else printf("PASS (%s)\n", resolved); printf("_httpResolveURI(%s, _HTTP_RESOLVE_FQDN): ", argv[1]); fflush(stdout); if (!_httpResolveURI(argv[1], resolved, sizeof(resolved), _HTTP_RESOLVE_FQDN, NULL, NULL)) { puts("FAIL"); return (1); } else if (strstr(resolved, ".local:")) { printf("FAIL (%s)\n", resolved); return (1); } else { printf("PASS (%s)\n", resolved); return (0); } } else if (!strcmp(argv[1], "-u") && argc == 3) { /* * Test URI separation... */ uri_status = httpSeparateURI(HTTP_URI_CODING_ALL, argv[2], scheme, sizeof(scheme), username, sizeof(username), hostname, sizeof(hostname), &port, resource, sizeof(resource)); printf("uri_status = %s\n", uri_status_strings[uri_status + 8]); printf("scheme = \"%s\"\n", scheme); printf("username = \"%s\"\n", username); printf("hostname = \"%s\"\n", hostname); printf("port = %d\n", port); printf("resource = \"%s\"\n", resource); return (0); } /* * Test HTTP GET requests... */ http = NULL; out = stdout; for (i = 1; i < argc; i ++) { if (!strcmp(argv[i], "-o")) { i ++; if (i >= argc) break; out = fopen(argv[i], "wb"); continue; } httpSeparateURI(HTTP_URI_CODING_MOST, argv[i], scheme, sizeof(scheme), username, sizeof(username), hostname, sizeof(hostname), &port, resource, sizeof(resource)); if (!_cups_strcasecmp(scheme, "https") || !_cups_strcasecmp(scheme, "ipps") || port == 443) encryption = HTTP_ENCRYPTION_ALWAYS; else encryption = HTTP_ENCRYPTION_IF_REQUESTED; http = httpConnect2(hostname, port, NULL, AF_UNSPEC, encryption, 1, 30000, NULL); if (http == NULL) { perror(hostname); continue; } printf("Checking file \"%s\"...\n", resource); do { if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close")) { httpClearFields(http); if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } } httpClearFields(http); httpSetField(http, HTTP_FIELD_AUTHORIZATION, httpGetAuthString(http)); httpSetField(http, HTTP_FIELD_ACCEPT_LANGUAGE, "en"); if (httpHead(http, resource)) { if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } else { status = HTTP_STATUS_UNAUTHORIZED; continue; } } while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE); if (status == HTTP_STATUS_UNAUTHORIZED) { /* * Flush any error message... */ httpFlush(http); /* * See if we can do authentication... */ if (cupsDoAuthentication(http, "GET", resource)) { status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; break; } if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } continue; } #ifdef HAVE_SSL else if (status == HTTP_STATUS_UPGRADE_REQUIRED) { /* Flush any error message... */ httpFlush(http); /* Reconnect... */ if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } /* Upgrade with encryption... */ httpEncryption(http, HTTP_ENCRYPTION_REQUIRED); /* Try again, this time with encryption enabled... */ continue; } #endif /* HAVE_SSL */ } while (status == HTTP_STATUS_UNAUTHORIZED || status == HTTP_STATUS_UPGRADE_REQUIRED); if (status == HTTP_STATUS_OK) puts("HEAD OK:"); else printf("HEAD failed with status %d...\n", status); encoding = httpGetContentEncoding(http); printf("Requesting file \"%s\" (Accept-Encoding: %s)...\n", resource, encoding ? encoding : "identity"); do { if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close")) { httpClearFields(http); if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } } httpClearFields(http); httpSetField(http, HTTP_FIELD_AUTHORIZATION, httpGetAuthString(http)); httpSetField(http, HTTP_FIELD_ACCEPT_LANGUAGE, "en"); httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING, encoding); if (httpGet(http, resource)) { if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } else { status = HTTP_STATUS_UNAUTHORIZED; continue; } } while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE); if (status == HTTP_STATUS_UNAUTHORIZED) { /* * Flush any error message... */ httpFlush(http); /* * See if we can do authentication... */ if (cupsDoAuthentication(http, "GET", resource)) { status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; break; } if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } continue; } #ifdef HAVE_SSL else if (status == HTTP_STATUS_UPGRADE_REQUIRED) { /* Flush any error message... */ httpFlush(http); /* Reconnect... */ if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } /* Upgrade with encryption... */ httpEncryption(http, HTTP_ENCRYPTION_REQUIRED); /* Try again, this time with encryption enabled... */ continue; } #endif /* HAVE_SSL */ } while (status == HTTP_STATUS_UNAUTHORIZED || status == HTTP_STATUS_UPGRADE_REQUIRED); if (status == HTTP_STATUS_OK) puts("GET OK:"); else printf("GET failed with status %d...\n", status); start = time(NULL); length = httpGetLength2(http); total = 0; while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0) { total += bytes; fwrite(buffer, bytes, 1, out); if (out != stdout) { current = time(NULL); if (current == start) current ++; printf("\r" CUPS_LLFMT "/" CUPS_LLFMT " bytes (" CUPS_LLFMT " bytes/sec) ", CUPS_LLCAST total, CUPS_LLCAST length, CUPS_LLCAST (total / (current - start))); fflush(stdout); } } } puts("Closing connection to server..."); httpClose(http); if (out != stdout) fclose(out); return (0); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int i, j, k; /* Looping vars */ http_t *http; /* HTTP connection */ http_status_t status; /* Status of GET command */ int failures; /* Number of test failures */ char buffer[8192]; /* Input buffer */ long bytes; /* Number of bytes read */ FILE *out; /* Output file */ char encode[256], /* Base64-encoded string */ decode[256]; /* Base64-decoded string */ int decodelen; /* Length of decoded string */ char scheme[HTTP_MAX_URI], /* Scheme from URI */ hostname[HTTP_MAX_URI], /* Hostname from URI */ username[HTTP_MAX_URI], /* Username:password from URI */ resource[HTTP_MAX_URI]; /* Resource from URI */ int port; /* Port number from URI */ http_uri_status_t uri_status; /* Status of URI separation */ http_addrlist_t *addrlist, /* Address list */ *addr; /* Current address */ off_t length, total; /* Length and total bytes */ time_t start, current; /* Start and end time */ static const char * const uri_status_strings[] = { "HTTP_URI_OVERFLOW", "HTTP_URI_BAD_ARGUMENTS", "HTTP_URI_BAD_RESOURCE", "HTTP_URI_BAD_PORT", "HTTP_URI_BAD_HOSTNAME", "HTTP_URI_BAD_USERNAME", "HTTP_URI_BAD_SCHEME", "HTTP_URI_BAD_URI", "HTTP_URI_OK", "HTTP_URI_MISSING_SCHEME", "HTTP_URI_UNKNOWN_SCHEME", "HTTP_URI_MISSING_RESOURCE" }; /* * Do API tests if we don't have a URL on the command-line... */ if (argc == 1) { failures = 0; /* * httpGetDateString()/httpGetDateTime() */ fputs("httpGetDateString()/httpGetDateTime(): ", stdout); start = time(NULL); strcpy(buffer, httpGetDateString(start)); current = httpGetDateTime(buffer); i = (int)(current - start); if (i < 0) i = -i; if (!i) puts("PASS"); else { failures ++; puts("FAIL"); printf(" Difference is %d seconds, %02d:%02d:%02d...\n", i, i / 3600, (i / 60) % 60, i % 60); printf(" httpGetDateString(%d) returned \"%s\"\n", (int)start, buffer); printf(" httpGetDateTime(\"%s\") returned %d\n", buffer, (int)current); printf(" httpGetDateString(%d) returned \"%s\"\n", (int)current, httpGetDateString(current)); } /* * httpDecode64_2()/httpEncode64_2() */ fputs("httpDecode64_2()/httpEncode64_2(): ", stdout); for (i = 0, j = 0; i < (int)(sizeof(base64_tests) / sizeof(base64_tests[0])); i ++) { httpEncode64_2(encode, sizeof(encode), base64_tests[i][0], strlen(base64_tests[i][0])); decodelen = (int)sizeof(decode); httpDecode64_2(decode, &decodelen, base64_tests[i][1]); if (strcmp(decode, base64_tests[i][0])) { failures ++; if (j) { puts("FAIL"); j = 1; } printf(" httpDecode64_2() returned \"%s\", expected \"%s\"...\n", decode, base64_tests[i][0]); } if (strcmp(encode, base64_tests[i][1])) { failures ++; if (j) { puts("FAIL"); j = 1; } printf(" httpEncode64_2() returned \"%s\", expected \"%s\"...\n", encode, base64_tests[i][1]); } } if (!j) puts("PASS"); /* * httpGetHostname() */ fputs("httpGetHostname(): ", stdout); if (httpGetHostname(NULL, hostname, sizeof(hostname))) printf("PASS (%s)\n", hostname); else { failures ++; puts("FAIL"); } /* * httpAddrGetList() */ printf("httpAddrGetList(%s): ", hostname); addrlist = httpAddrGetList(hostname, AF_UNSPEC, NULL); if (addrlist) { for (i = 0, addr = addrlist; addr; i ++, addr = addr->next) { char numeric[1024]; /* Numeric IP address */ httpAddrString(&(addr->addr), numeric, sizeof(numeric)); if (!strcmp(numeric, "UNKNOWN")) break; } if (addr) printf("FAIL (bad address for %s)\n", hostname); else printf("PASS (%d address(es) for %s)\n", i, hostname); httpAddrFreeList(addrlist); } else { failures ++; puts("FAIL"); } /* * Test httpSeparateURI()... */ fputs("httpSeparateURI(): ", stdout); for (i = 0, j = 0; i < (int)(sizeof(uri_tests) / sizeof(uri_tests[0])); i ++) { uri_status = httpSeparateURI(HTTP_URI_CODING_MOST, uri_tests[i].uri, scheme, sizeof(scheme), username, sizeof(username), hostname, sizeof(hostname), &port, resource, sizeof(resource)); if (uri_status != uri_tests[i].result || strcmp(scheme, uri_tests[i].scheme) || strcmp(username, uri_tests[i].username) || strcmp(hostname, uri_tests[i].hostname) || port != uri_tests[i].port || strcmp(resource, uri_tests[i].resource)) { failures ++; if (!j) { puts("FAIL"); j = 1; } printf(" \"%s\":\n", uri_tests[i].uri); if (uri_status != uri_tests[i].result) printf(" Returned %s instead of %s\n", uri_status_strings[uri_status + 8], uri_status_strings[uri_tests[i].result + 8]); if (strcmp(scheme, uri_tests[i].scheme)) printf(" Scheme \"%s\" instead of \"%s\"\n", scheme, uri_tests[i].scheme); if (strcmp(username, uri_tests[i].username)) printf(" Username \"%s\" instead of \"%s\"\n", username, uri_tests[i].username); if (strcmp(hostname, uri_tests[i].hostname)) printf(" Hostname \"%s\" instead of \"%s\"\n", hostname, uri_tests[i].hostname); if (port != uri_tests[i].port) printf(" Port %d instead of %d\n", port, uri_tests[i].port); if (strcmp(resource, uri_tests[i].resource)) printf(" Resource \"%s\" instead of \"%s\"\n", resource, uri_tests[i].resource); } } if (!j) printf("PASS (%d URIs tested)\n", (int)(sizeof(uri_tests) / sizeof(uri_tests[0]))); /* * Test httpAssembleURI()... */ fputs("httpAssembleURI(): ", stdout); for (i = 0, j = 0, k = 0; i < (int)(sizeof(uri_tests) / sizeof(uri_tests[0])); i ++) if (uri_tests[i].result == HTTP_URI_OK && !strstr(uri_tests[i].uri, "%64") && strstr(uri_tests[i].uri, "//")) { k ++; uri_status = httpAssembleURI(HTTP_URI_CODING_MOST, buffer, sizeof(buffer), uri_tests[i].scheme, uri_tests[i].username, uri_tests[i].hostname, uri_tests[i].assemble_port, uri_tests[i].resource); if (uri_status != HTTP_URI_OK) { failures ++; if (!j) { puts("FAIL"); j = 1; } printf(" \"%s\": %s\n", uri_tests[i].uri, uri_status_strings[uri_status + 8]); } else if (strcmp(buffer, uri_tests[i].uri)) { failures ++; if (!j) { puts("FAIL"); j = 1; } printf(" \"%s\": assembled = \"%s\"\n", uri_tests[i].uri, buffer); } } if (!j) printf("PASS (%d URIs tested)\n", k); /* * Show a summary and return... */ if (failures) printf("\n%d TESTS FAILED!\n", failures); else puts("\nALL TESTS PASSED!"); return (failures); } /* * Test HTTP GET requests... */ http = NULL; out = stdout; for (i = 1; i < argc; i ++) { if (!strcmp(argv[i], "-o")) { i ++; if (i >= argc) break; out = fopen(argv[i], "wb"); continue; } httpSeparateURI(HTTP_URI_CODING_MOST, argv[i], scheme, sizeof(scheme), username, sizeof(username), hostname, sizeof(hostname), &port, resource, sizeof(resource)); http = httpConnectEncrypt(hostname, port, HTTP_ENCRYPT_IF_REQUESTED); if (http == NULL) { perror(hostname); continue; } printf("Requesting file \"%s\"...\n", resource); httpClearFields(http); httpSetField(http, HTTP_FIELD_ACCEPT_LANGUAGE, "en"); httpGet(http, resource); while ((status = httpUpdate(http)) == HTTP_CONTINUE); if (status == HTTP_OK) puts("GET OK:"); else printf("GET failed with status %d...\n", status); start = time(NULL); length = httpGetLength2(http); total = 0; while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0) { total += bytes; fwrite(buffer, bytes, 1, out); if (out != stdout) { current = time(NULL); if (current == start) current ++; printf("\r" CUPS_LLFMT "/" CUPS_LLFMT " bytes (" CUPS_LLFMT " bytes/sec) ", CUPS_LLCAST total, CUPS_LLCAST length, CUPS_LLCAST (total / (current - start))); fflush(stdout); } } } puts("Closing connection to server..."); httpClose(http); if (out != stdout) fclose(out); return (0); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int i; /* Looping var */ ipp_t *event; /* Event from scheduler */ ipp_state_t state; /* IPP event state */ char scheme[32], /* URI scheme ("rss") */ username[256], /* Username for remote RSS */ host[1024], /* Hostname for remote RSS */ resource[1024], /* RSS file */ *options; /* Options */ int port, /* Port number for remote RSS */ max_events; /* Maximum number of events */ http_t *http; /* Connection to remote server */ http_status_t status; /* HTTP GET/PUT status code */ char filename[1024], /* Local filename */ newname[1024]; /* filename.N */ cups_lang_t *language; /* Language information */ ipp_attribute_t *printer_up_time, /* Timestamp on event */ *notify_sequence_number,/* Sequence number */ *notify_printer_uri; /* Printer URI */ char *subject, /* Subject for notification message */ *text, /* Text for notification message */ link_url[1024], /* Link to printer */ link_scheme[32], /* Scheme for link */ link_username[256], /* Username for link */ link_host[1024], /* Host for link */ link_resource[1024]; /* Resource for link */ int link_port; /* Link port */ cups_array_t *rss; /* RSS message array */ _cups_rss_t *msg; /* RSS message */ char baseurl[1024]; /* Base URL */ fd_set input; /* Input set for select() */ struct timeval timeout; /* Timeout for select() */ int changed; /* Has the RSS data changed? */ int exit_status; /* Exit status */ fprintf(stderr, "DEBUG: argc=%d\n", argc); for (i = 0; i < argc; i ++) fprintf(stderr, "DEBUG: argv[%d]=\"%s\"\n", i, argv[i]); /* * See whether we are publishing this RSS feed locally or remotely... */ if (httpSeparateURI(HTTP_URI_CODING_ALL, argv[1], scheme, sizeof(scheme), username, sizeof(username), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_OK) { fprintf(stderr, "ERROR: Bad RSS URI \"%s\"!\n", argv[1]); return (1); } max_events = 20; if ((options = strchr(resource, '?')) != NULL) { *options++ = '\0'; if (!strncmp(options, "max_events=", 11)) { max_events = atoi(options + 11); if (max_events <= 0) max_events = 20; } } rss = cupsArrayNew((cups_array_func_t)compare_rss, NULL); if (host[0]) { /* * Remote feed, see if we can get the current file... */ int fd; /* Temporary file */ if ((rss_password = strchr(username, ':')) != NULL) *rss_password++ = '\0'; cupsSetPasswordCB(password_cb); cupsSetUser(username); if ((fd = cupsTempFd(filename, sizeof(filename))) < 0) { fprintf(stderr, "ERROR: Unable to create temporary file: %s\n", strerror(errno)); return (1); } if ((http = httpConnect(host, port)) == NULL) { fprintf(stderr, "ERROR: Unable to connect to %s on port %d: %s\n", host, port, strerror(errno)); close(fd); unlink(filename); return (1); } status = cupsGetFd(http, resource, fd); close(fd); if (status != HTTP_OK && status != HTTP_NOT_FOUND) { fprintf(stderr, "ERROR: Unable to GET %s from %s on port %d: %d %s\n", resource, host, port, status, httpStatus(status)); httpClose(http); unlink(filename); return (1); } strlcpy(newname, filename, sizeof(newname)); httpAssembleURI(HTTP_URI_CODING_ALL, baseurl, sizeof(baseurl), "http", NULL, host, port, resource); } else { const char *cachedir, /* CUPS_CACHEDIR */ *server_name, /* SERVER_NAME */ *server_port; /* SERVER_PORT */ http = NULL; if ((cachedir = getenv("CUPS_CACHEDIR")) == NULL) cachedir = CUPS_CACHEDIR; if ((server_name = getenv("SERVER_NAME")) == NULL) server_name = "localhost"; if ((server_port = getenv("SERVER_PORT")) == NULL) server_port = "631"; snprintf(filename, sizeof(filename), "%s/rss%s", cachedir, resource); snprintf(newname, sizeof(newname), "%s.N", filename); httpAssembleURIf(HTTP_URI_CODING_ALL, baseurl, sizeof(baseurl), "http", NULL, server_name, atoi(server_port), "/rss%s", resource); } /* * Load the previous RSS file, if any... */ load_rss(rss, filename); changed = cupsArrayCount(rss) == 0; /* * Localize for the user's chosen language... */ language = cupsLangDefault(); /* * Read events and update the RSS file until we are out of events. */ for (exit_status = 0, event = NULL;;) { if (changed) { /* * Save the messages to the file again, uploading as needed... */ if (save_rss(rss, newname, baseurl)) { if (http) { /* * Upload the RSS file... */ if ((status = cupsPutFile(http, resource, filename)) != HTTP_CREATED) fprintf(stderr, "ERROR: Unable to PUT %s from %s on port %d: %d %s\n", resource, host, port, status, httpStatus(status)); } else { /* * Move the new RSS file over top the old one... */ if (rename(newname, filename)) fprintf(stderr, "ERROR: Unable to rename %s to %s: %s\n", newname, filename, strerror(errno)); } changed = 0; } } /* * Wait up to 30 seconds for an event... */ timeout.tv_sec = 30; timeout.tv_usec = 0; FD_ZERO(&input); FD_SET(0, &input); if (select(1, &input, NULL, NULL, &timeout) < 0) continue; else if (!FD_ISSET(0, &input)) { fprintf(stderr, "DEBUG: %s is bored, exiting...\n", argv[1]); break; } /* * Read the next event... */ event = ippNew(); while ((state = ippReadFile(0, event)) != IPP_DATA) { if (state <= IPP_IDLE) break; } if (state == IPP_ERROR) fputs("DEBUG: ippReadFile() returned IPP_ERROR!\n", stderr); if (state <= IPP_IDLE) break; /* * Collect the info from the event... */ printer_up_time = ippFindAttribute(event, "printer-up-time", IPP_TAG_INTEGER); notify_sequence_number = ippFindAttribute(event, "notify-sequence-number", IPP_TAG_INTEGER); notify_printer_uri = ippFindAttribute(event, "notify-printer-uri", IPP_TAG_URI); subject = cupsNotifySubject(language, event); text = cupsNotifyText(language, event); if (printer_up_time && notify_sequence_number && subject && text) { /* * Create a new RSS message... */ if (notify_printer_uri) { httpSeparateURI(HTTP_URI_CODING_ALL, notify_printer_uri->values[0].string.text, link_scheme, sizeof(link_scheme), link_username, sizeof(link_username), link_host, sizeof(link_host), &link_port, link_resource, sizeof(link_resource)); httpAssembleURI(HTTP_URI_CODING_ALL, link_url, sizeof(link_url), "http", link_username, link_host, link_port, link_resource); } msg = new_message(notify_sequence_number->values[0].integer, xml_escape(subject), xml_escape(text), notify_printer_uri ? xml_escape(link_url) : NULL, printer_up_time->values[0].integer); if (!msg) { fprintf(stderr, "ERROR: Unable to create message: %s\n", strerror(errno)); exit_status = 1; break; } /* * Add it to the array... */ cupsArrayAdd(rss, msg); changed = 1; /* * Trim the array as needed... */ while (cupsArrayCount(rss) > max_events) { msg = cupsArrayFirst(rss); cupsArrayRemove(rss, msg); delete_message(msg); } } if (subject) free(subject); if (text) free(text); ippDelete(event); event = NULL; } /* * We only get here when idle or error... */ ippDelete(event); if (http) { unlink(filename); httpClose(http); } return (exit_status); }