void cupsSetEncryption(http_encryption_t e) /* I - New encryption preference */ { _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ cg->encryption = e; if (cg->http) httpEncryption(cg->http, e); }
papi_status_t papiServiceSetEncryption(papi_service_t handle, papi_encryption_t encryption) { papi_status_t result = PAPI_OK; if (handle != NULL) { service_t *svc = handle; svc->encryption = encryption; httpEncryption(svc->connection, (http_encryption_t)svc->encryption); } else result = PAPI_BAD_ARGUMENT; return (result); }
static void _post_check (GtkCupsRequest *request) { http_status_t http_status; http_status = request->last_status; GTK_NOTE (PRINTING, g_print ("CUPS Backend: %s - status %i\n", G_STRFUNC, http_status)); request->poll_state = GTK_CUPS_HTTP_READ; if (http_status == HTTP_CONTINUE) { goto again; } else if (http_status == HTTP_UNAUTHORIZED) { int auth_result = -1; httpFlush (request->http); if (request->password_state == GTK_CUPS_PASSWORD_APPLIED) { request->poll_state = GTK_CUPS_HTTP_IDLE; request->password_state = GTK_CUPS_PASSWORD_NOT_VALID; request->state = GTK_CUPS_POST_AUTH; request->need_password = TRUE; return; } /* Negotiate */ if (strncmp (httpGetField (request->http, HTTP_FIELD_WWW_AUTHENTICATE), "Negotiate", 9) == 0) { auth_result = cupsDoAuthentication (request->http, "POST", request->resource); } /* Basic, BasicDigest, Digest and PeerCred */ else { if (request->password_state == GTK_CUPS_PASSWORD_NONE) { cups_username = request->username; cupsSetPasswordCB (passwordCB); /* This call success for PeerCred authentication */ auth_result = cupsDoAuthentication (request->http, "POST", request->resource); if (auth_result != 0) { /* move to AUTH state to let the backend * ask for a password */ request->poll_state = GTK_CUPS_HTTP_IDLE; request->state = GTK_CUPS_POST_AUTH; request->need_password = TRUE; return; } } else { cups_password = request->password; cups_username = request->username; auth_result = cupsDoAuthentication (request->http, "POST", request->resource); if (cups_password != NULL) return; if (request->password != NULL) { memset (request->password, 0, strlen (request->password)); g_free (request->password); request->password = NULL; } request->password_state = GTK_CUPS_PASSWORD_APPLIED; } } if (auth_result || httpReconnect (request->http)) { /* if the password has been used, reset password_state * so that we ask for a new one next time around */ if (cups_password == NULL) request->password_state = GTK_CUPS_PASSWORD_NONE; request->state = GTK_CUPS_POST_DONE; request->poll_state = GTK_CUPS_HTTP_IDLE; gtk_cups_result_set_error (request->result, GTK_CUPS_ERROR_AUTH, 0, 0, "Not authorized"); return; } if (request->data_io != NULL) g_io_channel_seek_position (request->data_io, 0, G_SEEK_SET, NULL); request->state = GTK_CUPS_POST_CONNECT; request->poll_state = GTK_CUPS_HTTP_WRITE; } else if (http_status == HTTP_ERROR) { int error = httpError (request->http); #ifdef G_OS_WIN32 if (error != WSAENETDOWN && error != WSAENETUNREACH) #else if (error != ENETDOWN && error != ENETUNREACH) #endif /* G_OS_WIN32 */ { request->attempts++; goto again; } else { request->state = GTK_CUPS_POST_DONE; request->poll_state = GTK_CUPS_HTTP_IDLE; gtk_cups_result_set_error (request->result, GTK_CUPS_ERROR_HTTP, http_status, error, "Unknown HTTP error"); return; } } else if (http_status == HTTP_UPGRADE_REQUIRED) { /* Flush any error message... */ httpFlush (request->http); cupsSetEncryption (HTTP_ENCRYPT_REQUIRED); request->state = GTK_CUPS_POST_CONNECT; /* Reconnect... */ httpReconnect (request->http); /* Upgrade with encryption... */ httpEncryption (request->http, HTTP_ENCRYPT_REQUIRED); request->attempts++; goto again; } else if (http_status != HTTP_OK) { int http_errno; http_errno = httpError (request->http); if (http_errno == EPIPE) request->state = GTK_CUPS_POST_CONNECT; else { request->state = GTK_CUPS_POST_DONE; gtk_cups_result_set_error (request->result, GTK_CUPS_ERROR_HTTP, http_status, http_errno, "HTTP Error in POST %s", g_strerror (http_errno)); request->poll_state = GTK_CUPS_HTTP_IDLE; httpFlush (request->http); return; } request->poll_state = GTK_CUPS_HTTP_IDLE; request->last_status = HTTP_CONTINUE; httpFlush (request->http); if (request->own_http) httpClose (request->http); request->http = NULL; return; } else { request->state = GTK_CUPS_POST_READ_RESPONSE; return; } again: http_status = HTTP_CONTINUE; if (httpCheck (request->http)) http_status = httpUpdate (request->http); request->last_status = http_status; }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { http_t *http; /* HTTP connection to server */ int i; /* Looping var */ int job_id; /* Job ID */ int num_dests; /* Number of destinations */ cups_dest_t *dests; /* Destinations */ char *dest, /* Destination printer */ *job, /* Job ID pointer */ *user; /* Cancel jobs for a user */ int purge; /* Purge or cancel jobs? */ char uri[1024]; /* Printer or job URI */ ipp_t *request; /* IPP request */ ipp_t *response; /* IPP response */ ipp_op_t op; /* Operation */ _cupsSetLocale(argv); /* * Setup to cancel individual print jobs... */ op = IPP_CANCEL_JOB; purge = 0; dest = NULL; user = NULL; http = NULL; num_dests = 0; dests = NULL; /* * Process command-line arguments... */ for (i = 1; i < argc; i ++) if (argv[i][0] == '-' && argv[i][1]) switch (argv[i][1]) { case 'E' : /* Encrypt */ #ifdef HAVE_SSL cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); if (http) httpEncryption(http, HTTP_ENCRYPT_REQUIRED); #else _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support compiled in!\n"), argv[0]); #endif /* HAVE_SSL */ break; case 'U' : /* Username */ if (argv[i][2] != '\0') cupsSetUser(argv[i] + 2); else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected username after " "\'-U\' option!\n"), argv[0]); return (1); } cupsSetUser(argv[i]); } break; case 'a' : /* Cancel all jobs */ purge = 1; op = IPP_PURGE_JOBS; break; case 'h' : /* Connect to host */ if (http != NULL) { httpClose(http); http = NULL; } if (argv[i][2] != '\0') cupsSetServer(argv[i] + 2); else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected hostname after " "\'-h\' option!\n"), argv[0]); return (1); } else cupsSetServer(argv[i]); } break; case 'u' : /* Username */ op = IPP_PURGE_JOBS; if (argv[i][2] != '\0') user = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected username after " "\'-u\' option!\n"), argv[0]); return (1); } else user = argv[i]; } break; default : _cupsLangPrintf(stderr, _("%s: Error - unknown option \'%c\'!\n"), argv[0], argv[i][1]); return (1); } else { /* * Cancel a job or printer... */ if (num_dests == 0) num_dests = cupsGetDests(&dests); if (!strcmp(argv[i], "-")) { /* * Delete the current job... */ dest = ""; job_id = 0; } else if (cupsGetDest(argv[i], NULL, num_dests, dests) != NULL) { /* * Delete the current job on the named destination... */ dest = argv[i]; job_id = 0; } else if ((job = strrchr(argv[i], '-')) != NULL && isdigit(job[1] & 255)) { /* * Delete the specified job ID. */ dest = NULL; op = IPP_CANCEL_JOB; job_id = atoi(job + 1); } else if (isdigit(argv[i][0] & 255)) { /* * Delete the specified job ID. */ dest = NULL; op = IPP_CANCEL_JOB; job_id = atoi(argv[i]); } else { /* * Bad printer name! */ _cupsLangPrintf(stderr, _("%s: Error - unknown destination \"%s\"!\n"), argv[0], argv[i]); return (1); } /* * For Solaris LP compatibility, ignore a destination name after * cancelling a specific job ID... */ if (job_id && (i + 1) < argc && cupsGetDest(argv[i + 1], NULL, num_dests, dests) != NULL) i ++; /* * Open a connection to the server... */ if (http == NULL) if ((http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption())) == NULL) { _cupsLangPrintf(stderr, _("%s: Unable to contact server!\n"), argv[0]); return (1); } /* * Build an IPP request, which requires the following * attributes: * * attributes-charset * attributes-natural-language * printer-uri + job-id *or* job-uri * [requesting-user-name] */ request = ippNewRequest(op); if (dest) { httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 0, "/printers/%s", dest); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id); } else { sprintf(uri, "ipp://localhost/jobs/%d", job_id); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri); } if (user) { ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, user); ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1); } else ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); if (op == IPP_PURGE_JOBS) ippAddBoolean(request, IPP_TAG_OPERATION, "purge-jobs", purge); /* * Do the request and get back a response... */ if (op == IPP_PURGE_JOBS && (!user || strcasecmp(user, cupsUser()))) response = cupsDoRequest(http, request, "/admin/"); else response = cupsDoRequest(http, request, "/jobs/"); if (response == NULL || response->request.status.status_code > IPP_OK_CONFLICT) { _cupsLangPrintf(stderr, _("%s: %s failed: %s\n"), argv[0], op == IPP_PURGE_JOBS ? "purge-jobs" : "cancel-job", cupsLastErrorString()); if (response) ippDelete(response); return (1); } ippDelete(response); } if (num_dests == 0 && op == IPP_PURGE_JOBS) { /* * Open a connection to the server... */ if (http == NULL) if ((http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption())) == NULL) { _cupsLangPrintf(stderr, _("%s: Unable to contact server!\n"), argv[0]); return (1); } /* * Build an IPP request, which requires the following * attributes: * * attributes-charset * attributes-natural-language * printer-uri + job-id *or* job-uri * [requesting-user-name] */ request = ippNewRequest(op); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, "ipp://localhost/printers/"); if (user) { ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, user); ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1); } else ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); ippAddBoolean(request, IPP_TAG_OPERATION, "purge-jobs", purge); /* * Do the request and get back a response... */ response = cupsDoRequest(http, request, "/admin/"); if (response == NULL || response->request.status.status_code > IPP_OK_CONFLICT) { _cupsLangPrintf(stderr, _("%s: %s failed: %s\n"), argv[0], op == IPP_PURGE_JOBS ? "purge-jobs" : "cancel-job", cupsLastErrorString()); if (response) ippDelete(response); return (1); } ippDelete(response); } return (0); }
http_status_t /* O - Initial HTTP status */ cupsSendRequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ ipp_t *request, /* I - IPP request */ const char *resource, /* I - Resource path */ size_t length) /* I - Length of data to follow or @code CUPS_LENGTH_VARIABLE@ */ { http_status_t status; /* Status of HTTP request */ int got_status; /* Did we get the status? */ ipp_state_t state; /* State of IPP processing */ http_status_t expect; /* Expect: header to use */ DEBUG_printf(("cupsSendRequest(http=%p, request=%p(%s), resource=\"%s\", " "length=" CUPS_LLFMT ")", http, request, request ? ippOpString(request->request.op.operation_id) : "?", resource, CUPS_LLCAST length)); /* * Range check input... */ if (!request || !resource) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); return (HTTP_STATUS_ERROR); } /* * Get the default connection as needed... */ if (!http) if ((http = _cupsConnect()) == NULL) return (HTTP_STATUS_SERVICE_UNAVAILABLE); /* * If the prior request was not flushed out, do so now... */ if (http->state == HTTP_STATE_GET_SEND || http->state == HTTP_STATE_POST_SEND) { DEBUG_puts("2cupsSendRequest: Flush prior response."); httpFlush(http); } else if (http->state != HTTP_STATE_WAITING) { DEBUG_printf(("1cupsSendRequest: Unknown HTTP state (%d), " "reconnecting.", http->state)); if (httpReconnect2(http, 30000, NULL)) return (HTTP_STATUS_ERROR); } #ifdef HAVE_SSL /* * See if we have an auth-info attribute and are communicating over * a non-local link. If so, encrypt the link so that we can pass * the authentication information securely... */ if (ippFindAttribute(request, "auth-info", IPP_TAG_TEXT) && !httpAddrLocalhost(http->hostaddr) && !http->tls && httpEncryption(http, HTTP_ENCRYPTION_REQUIRED)) { DEBUG_puts("1cupsSendRequest: Unable to encrypt connection."); return (HTTP_STATUS_SERVICE_UNAVAILABLE); } #endif /* HAVE_SSL */ /* * Reconnect if the last response had a "Connection: close"... */ if (!_cups_strcasecmp(http->fields[HTTP_FIELD_CONNECTION], "close")) { DEBUG_puts("2cupsSendRequest: Connection: close"); httpClearFields(http); if (httpReconnect2(http, 30000, NULL)) { DEBUG_puts("1cupsSendRequest: Unable to reconnect."); return (HTTP_STATUS_SERVICE_UNAVAILABLE); } } /* * Loop until we can send the request without authorization problems. */ expect = HTTP_STATUS_CONTINUE; for (;;) { DEBUG_puts("2cupsSendRequest: Setup..."); /* * Setup the HTTP variables needed... */ httpClearFields(http); httpSetExpect(http, expect); httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp"); httpSetLength(http, length); #ifdef HAVE_GSSAPI if (http->authstring && !strncmp(http->authstring, "Negotiate", 9)) { /* * Do not use cached Kerberos credentials since they will look like a * "replay" attack... */ _cupsSetNegotiateAuthString(http, "POST", resource); } #endif /* HAVE_GSSAPI */ httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring); DEBUG_printf(("2cupsSendRequest: authstring=\"%s\"", http->authstring)); /* * Try the request... */ DEBUG_puts("2cupsSendRequest: Sending HTTP POST..."); if (httpPost(http, resource)) { DEBUG_puts("2cupsSendRequest: POST failed, reconnecting."); if (httpReconnect2(http, 30000, NULL)) { DEBUG_puts("1cupsSendRequest: Unable to reconnect."); return (HTTP_STATUS_SERVICE_UNAVAILABLE); } else continue; } /* * Send the IPP data... */ DEBUG_puts("2cupsSendRequest: Writing IPP request..."); request->state = IPP_STATE_IDLE; status = HTTP_STATUS_CONTINUE; got_status = 0; while ((state = ippWrite(http, request)) != IPP_STATE_DATA) if (state == IPP_STATE_ERROR) break; else if (httpCheck(http)) { got_status = 1; _httpUpdate(http, &status); if (status >= HTTP_STATUS_MULTIPLE_CHOICES) break; } if (state == IPP_STATE_ERROR) { DEBUG_puts("1cupsSendRequest: Unable to send IPP request."); http->status = HTTP_STATUS_ERROR; http->state = HTTP_STATE_WAITING; return (HTTP_STATUS_ERROR); } /* * Wait up to 1 second to get the 100-continue response as needed... */ if (!got_status) { if (expect == HTTP_STATUS_CONTINUE) { DEBUG_puts("2cupsSendRequest: Waiting for 100-continue..."); if (httpWait(http, 1000)) _httpUpdate(http, &status); } else if (httpCheck(http)) _httpUpdate(http, &status); } DEBUG_printf(("2cupsSendRequest: status=%d", status)); /* * Process the current HTTP status... */ if (status >= HTTP_STATUS_MULTIPLE_CHOICES) { int temp_status; /* Temporary status */ _cupsSetHTTPError(status); do { temp_status = httpUpdate(http); } while (temp_status != HTTP_STATUS_ERROR && http->state == HTTP_STATE_POST_RECV); httpFlush(http); } switch (status) { case HTTP_STATUS_CONTINUE : case HTTP_STATUS_OK : case HTTP_STATUS_ERROR : DEBUG_printf(("1cupsSendRequest: Returning %d.", status)); return (status); case HTTP_STATUS_UNAUTHORIZED : if (cupsDoAuthentication(http, "POST", resource)) { DEBUG_puts("1cupsSendRequest: Returning HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED."); return (HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED); } DEBUG_puts("2cupsSendRequest: Reconnecting after HTTP_STATUS_UNAUTHORIZED."); if (httpReconnect2(http, 30000, NULL)) { DEBUG_puts("1cupsSendRequest: Unable to reconnect."); return (HTTP_STATUS_SERVICE_UNAVAILABLE); } break; #ifdef HAVE_SSL case HTTP_STATUS_UPGRADE_REQUIRED : /* * Flush any error message, reconnect, and then upgrade with * encryption... */ DEBUG_puts("2cupsSendRequest: Reconnecting after " "HTTP_STATUS_UPGRADE_REQUIRED."); if (httpReconnect2(http, 30000, NULL)) { DEBUG_puts("1cupsSendRequest: Unable to reconnect."); return (HTTP_STATUS_SERVICE_UNAVAILABLE); } DEBUG_puts("2cupsSendRequest: Upgrading to TLS."); if (httpEncryption(http, HTTP_ENCRYPTION_REQUIRED)) { DEBUG_puts("1cupsSendRequest: Unable to encrypt connection."); return (HTTP_STATUS_SERVICE_UNAVAILABLE); } break; #endif /* HAVE_SSL */ case HTTP_STATUS_EXPECTATION_FAILED : /* * Don't try using the Expect: header the next time around... */ expect = (http_status_t)0; DEBUG_puts("2cupsSendRequest: Reconnecting after " "HTTP_EXPECTATION_FAILED."); if (httpReconnect2(http, 30000, NULL)) { DEBUG_puts("1cupsSendRequest: Unable to reconnect."); return (HTTP_STATUS_SERVICE_UNAVAILABLE); } break; default : /* * Some other error... */ return (status); } } }
ipp_t * /* O - Response or @code NULL@ on HTTP error */ cupsGetResponse(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ const char *resource) /* I - HTTP resource for POST */ { http_status_t status; /* HTTP status */ ipp_state_t state; /* IPP read state */ ipp_t *response = NULL; /* IPP response */ DEBUG_printf(("cupsGetResponse(http=%p, resource=\"%s\")", http, resource)); /* * Connect to the default server as needed... */ if (!http) http = _cupsConnect(); if (!http || (http->state != HTTP_STATE_POST_RECV && http->state != HTTP_STATE_POST_SEND)) return (NULL); /* * Check for an unfinished chunked request... */ if (http->data_encoding == HTTP_ENCODING_CHUNKED) { /* * Send a 0-length chunk to finish off the request... */ DEBUG_puts("2cupsGetResponse: Finishing chunked POST..."); if (httpWrite2(http, "", 0) < 0) return (NULL); } /* * Wait for a response from the server... */ DEBUG_printf(("2cupsGetResponse: Update loop, http->status=%d...", http->status)); do { status = httpUpdate(http); } while (status == HTTP_STATUS_CONTINUE); DEBUG_printf(("2cupsGetResponse: status=%d", status)); if (status == HTTP_STATUS_OK) { /* * Get the IPP response... */ response = ippNew(); while ((state = ippRead(http, response)) != IPP_STATE_DATA) if (state == IPP_STATE_ERROR) break; if (state == IPP_STATE_ERROR) { /* * Flush remaining data and delete the response... */ DEBUG_puts("1cupsGetResponse: IPP read error!"); httpFlush(http); ippDelete(response); response = NULL; http->status = status = HTTP_STATUS_ERROR; http->error = EINVAL; } } else if (status != HTTP_STATUS_ERROR) { /* * Flush any error message... */ httpFlush(http); /* * Then handle encryption and authentication... */ if (status == HTTP_STATUS_UNAUTHORIZED) { /* * See if we can do authentication... */ DEBUG_puts("2cupsGetResponse: Need authorization..."); if (!cupsDoAuthentication(http, "POST", resource)) httpReconnect2(http, 30000, NULL); else http->status = status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; } #ifdef HAVE_SSL else if (status == HTTP_STATUS_UPGRADE_REQUIRED) { /* * Force a reconnect with encryption... */ DEBUG_puts("2cupsGetResponse: Need encryption..."); if (!httpReconnect2(http, 30000, NULL)) httpEncryption(http, HTTP_ENCRYPTION_REQUIRED); } #endif /* HAVE_SSL */ } if (response) { ipp_attribute_t *attr; /* status-message attribute */ attr = ippFindAttribute(response, "status-message", IPP_TAG_TEXT); DEBUG_printf(("1cupsGetResponse: status-code=%s, status-message=\"%s\"", ippErrorString(response->request.status.status_code), attr ? attr->values[0].string.text : "")); _cupsSetError(response->request.status.status_code, attr ? attr->values[0].string.text : ippErrorString(response->request.status.status_code), 0); } return (response); }
int main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int i; /* Looping var */ http_t *http; /* Connection to server */ const char *dest, /* Desired printer */ *user, /* Desired user */ *val; /* Environment variable name */ char *instance; /* Printer instance */ int id, /* Desired job ID */ all, /* All printers */ interval, /* Reporting interval */ longstatus; /* Show file details */ cups_dest_t *named_dest; /* Named destination */ _cupsSetLocale(argv); /* * Check for command-line options... */ http = NULL; dest = NULL; user = NULL; id = 0; interval = 0; longstatus = 0; all = 0; for (i = 1; i < argc; i ++) if (argv[i][0] == '+') interval = atoi(argv[i] + 1); else if (argv[i][0] == '-') { switch (argv[i][1]) { case 'E' : /* Encrypt */ #ifdef HAVE_SSL cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); if (http) httpEncryption(http, HTTP_ENCRYPT_REQUIRED); #else _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), argv[0]); #endif /* HAVE_SSL */ break; case 'U' : /* Username */ if (argv[i][2] != '\0') cupsSetUser(argv[i] + 2); else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected username after " "\"-U\" option."), argv[0]); return (1); } cupsSetUser(argv[i]); } break; case 'P' : /* Printer */ if (argv[i][2]) dest = argv[i] + 2; else { i ++; if (i >= argc) { httpClose(http); usage(); } dest = argv[i]; } if ((instance = strchr(dest, '/')) != NULL) *instance++ = '\0'; http = connect_server(argv[0], http); if ((named_dest = cupsGetNamedDest(http, dest, instance)) == NULL) { if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) _cupsLangPrintf(stderr, _("%s: Error - add '/version=1.1' to server " "name."), argv[0]); else if (instance) _cupsLangPrintf(stderr, _("%s: Error - unknown destination \"%s/%s\"."), argv[0], dest, instance); else _cupsLangPrintf(stderr, _("%s: Unknown destination \"%s\"."), argv[0], dest); return (1); } cupsFreeDests(1, named_dest); break; case 'a' : /* All printers */ all = 1; break; case 'h' : /* Connect to host */ if (http) { httpClose(http); http = NULL; } if (argv[i][2] != '\0') cupsSetServer(argv[i] + 2); else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected hostname after " "\"-h\" option."), argv[0]); return (1); } else cupsSetServer(argv[i]); } break; case 'l' : /* Long status */ longstatus = 1; break; default : httpClose(http); usage(); break; } } else if (isdigit(argv[i][0] & 255)) id = atoi(argv[i]); else user = argv[i]; http = connect_server(argv[0], http); if (dest == NULL && !all) { if ((named_dest = cupsGetNamedDest(http, NULL, NULL)) == NULL) { if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) { _cupsLangPrintf(stderr, _("%s: Error - add '/version=1.1' to server name."), argv[0]); return (1); } val = NULL; if ((dest = getenv("LPDEST")) == NULL) { if ((dest = getenv("PRINTER")) != NULL) { if (!strcmp(dest, "lp")) dest = NULL; else val = "PRINTER"; } } else val = "LPDEST"; if (dest && val) _cupsLangPrintf(stderr, _("%s: Error - %s environment variable names " "non-existent destination \"%s\"."), argv[0], val, dest); else _cupsLangPrintf(stderr, _("%s: Error - no default destination available."), argv[0]); httpClose(http); return (1); } dest = named_dest->name; } /* * Show the status in a loop... */ for (;;) { if (dest) show_printer(argv[0], http, dest); i = show_jobs(argv[0], http, dest, user, id, longstatus); if (i && interval) { fflush(stdout); sleep(interval); } else break; } /* * Close the connection to the server and return... */ httpClose(http); return (0); }
ipp_status_t /* O - Request status - @code IPP_OK@ on success. */ cupsGetDevices( http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ int timeout, /* I - Timeout in seconds or @code CUPS_TIMEOUT_DEFAULT@ */ const char *include_schemes, /* I - Comma-separated URI schemes to include or @code CUPS_INCLUDE_ALL@ */ const char *exclude_schemes, /* I - Comma-separated URI schemes to exclude or @code CUPS_EXCLUDE_NONE@ */ cups_device_cb_t callback, /* I - Callback function */ void *user_data) /* I - User data pointer */ { ipp_t *request, /* CUPS-Get-Devices request */ *response; /* CUPS-Get-Devices response */ ipp_attribute_t *attr; /* Current attribute */ const char *device_class, /* device-class value */ *device_id, /* device-id value */ *device_info, /* device-info value */ *device_location, /* device-location value */ *device_make_and_model, /* device-make-and-model value */ *device_uri; /* device-uri value */ int blocking; /* Current blocking-IO mode */ cups_option_t option; /* in/exclude-schemes option */ http_status_t status; /* HTTP status of request */ ipp_state_t state; /* IPP response state */ /* * Range check input... */ DEBUG_printf(("cupsGetDevices(http=%p, timeout=%d, include_schemes=\"%s\", exclude_schemes=\"%s\", callback=%p, user_data=%p)", (void *)http, timeout, include_schemes, exclude_schemes, (void *)callback, user_data)); if (!callback) return (IPP_STATUS_ERROR_INTERNAL); if (!http) http = _cupsConnect(); if (!http) return (IPP_STATUS_ERROR_SERVICE_UNAVAILABLE); /* * Create a CUPS-Get-Devices request... */ request = ippNewRequest(IPP_OP_CUPS_GET_DEVICES); if (timeout > 0) ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "timeout", timeout); if (include_schemes) { option.name = "include-schemes"; option.value = (char *)include_schemes; cupsEncodeOptions2(request, 1, &option, IPP_TAG_OPERATION); } if (exclude_schemes) { option.name = "exclude-schemes"; option.value = (char *)exclude_schemes; cupsEncodeOptions2(request, 1, &option, IPP_TAG_OPERATION); } /* * Send the request and do any necessary authentication... */ do { DEBUG_puts("2cupsGetDevices: Sending request..."); status = cupsSendRequest(http, request, "/", ippLength(request)); DEBUG_puts("2cupsGetDevices: Waiting for response status..."); while (status == HTTP_STATUS_CONTINUE) status = httpUpdate(http); if (status != HTTP_STATUS_OK) { httpFlush(http); if (status == HTTP_STATUS_UNAUTHORIZED) { /* * See if we can do authentication... */ DEBUG_puts("2cupsGetDevices: Need authorization..."); if (!cupsDoAuthentication(http, "POST", "/")) httpReconnect2(http, 30000, NULL); else { status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; break; } } #ifdef HAVE_SSL else if (status == HTTP_STATUS_UPGRADE_REQUIRED) { /* * Force a reconnect with encryption... */ DEBUG_puts("2cupsGetDevices: Need encryption..."); if (!httpReconnect2(http, 30000, NULL)) httpEncryption(http, HTTP_ENCRYPTION_REQUIRED); } #endif /* HAVE_SSL */ } } while (status == HTTP_STATUS_UNAUTHORIZED || status == HTTP_STATUS_UPGRADE_REQUIRED); DEBUG_printf(("2cupsGetDevices: status=%d", status)); ippDelete(request); if (status != HTTP_STATUS_OK) { _cupsSetHTTPError(status); return (cupsLastError()); } /* * Read the response in non-blocking mode... */ blocking = httpGetBlocking(http); httpBlocking(http, 0); response = ippNew(); device_class = NULL; device_id = NULL; device_info = NULL; device_location = ""; device_make_and_model = NULL; device_uri = NULL; attr = NULL; DEBUG_puts("2cupsGetDevices: Reading response..."); do { if ((state = ippRead(http, response)) == IPP_STATE_ERROR) break; DEBUG_printf(("2cupsGetDevices: state=%d, response->last=%p", state, (void *)response->last)); if (!response->attrs) continue; while (attr != response->last) { if (!attr) attr = response->attrs; else attr = attr->next; DEBUG_printf(("2cupsGetDevices: attr->name=\"%s\", attr->value_tag=%d", attr->name, attr->value_tag)); if (!attr->name) { if (device_class && device_id && device_info && device_make_and_model && device_uri) (*callback)(device_class, device_id, device_info, device_make_and_model, device_uri, device_location, user_data); device_class = NULL; device_id = NULL; device_info = NULL; device_location = ""; device_make_and_model = NULL; device_uri = NULL; } else if (!strcmp(attr->name, "device-class") && attr->value_tag == IPP_TAG_KEYWORD) device_class = attr->values[0].string.text; else if (!strcmp(attr->name, "device-id") && attr->value_tag == IPP_TAG_TEXT) device_id = attr->values[0].string.text; else if (!strcmp(attr->name, "device-info") && attr->value_tag == IPP_TAG_TEXT) device_info = attr->values[0].string.text; else if (!strcmp(attr->name, "device-location") && attr->value_tag == IPP_TAG_TEXT) device_location = attr->values[0].string.text; else if (!strcmp(attr->name, "device-make-and-model") && attr->value_tag == IPP_TAG_TEXT) device_make_and_model = attr->values[0].string.text; else if (!strcmp(attr->name, "device-uri") && attr->value_tag == IPP_TAG_URI) device_uri = attr->values[0].string.text; } } while (state != IPP_STATE_DATA); DEBUG_printf(("2cupsGetDevices: state=%d, response->last=%p", state, (void *)response->last)); if (device_class && device_id && device_info && device_make_and_model && device_uri) (*callback)(device_class, device_id, device_info, device_make_and_model, device_uri, device_location, user_data); /* * Set the IPP status and return... */ httpBlocking(http, blocking); httpFlush(http); if (status == HTTP_STATUS_ERROR) _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(http->error), 0); else { attr = ippFindAttribute(response, "status-message", IPP_TAG_TEXT); DEBUG_printf(("cupsGetDevices: status-code=%s, status-message=\"%s\"", ippErrorString(response->request.status.status_code), attr ? attr->values[0].string.text : "")); _cupsSetError(response->request.status.status_code, attr ? attr->values[0].string.text : ippErrorString(response->request.status.status_code), 0); } ippDelete(response); return (cupsLastError()); }
http_status_t /* O - HTTP status */ cupsGetFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ const char *resource, /* I - Resource name */ int fd) /* I - File descriptor */ { ssize_t bytes; /* Number of bytes read */ char buffer[8192]; /* Buffer for file */ http_status_t status; /* HTTP status from server */ char if_modified_since[HTTP_MAX_VALUE]; /* If-Modified-Since header */ int new_auth = 0; /* Using new auth information? */ int digest; /* Are we using Digest authentication? */ /* * Range check input... */ DEBUG_printf(("cupsGetFd(http=%p, resource=\"%s\", fd=%d)", (void *)http, resource, fd)); if (!resource || fd < 0) { if (http) http->error = EINVAL; return (HTTP_STATUS_ERROR); } if (!http) if ((http = _cupsConnect()) == NULL) return (HTTP_STATUS_SERVICE_UNAVAILABLE); /* * Then send GET requests to the HTTP server... */ strlcpy(if_modified_since, httpGetField(http, HTTP_FIELD_IF_MODIFIED_SINCE), sizeof(if_modified_since)); 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_IF_MODIFIED_SINCE, if_modified_since); digest = http->authstring && !strncmp(http->authstring, "Digest ", 7); if (digest && !new_auth) { /* * Update the Digest authentication string... */ _httpSetDigestAuthString(http, http->nextnonce, "GET", resource); } #ifdef HAVE_GSSAPI if (http->authstring && !strncmp(http->authstring, "Negotiate", 9) && !new_auth) { /* * Do not use cached Kerberos credentials since they will look like a * "replay" attack... */ _cupsSetNegotiateAuthString(http, "GET", resource); } #endif /* HAVE_GSSAPI */ httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring); if (httpGet(http, resource)) { if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } else { status = HTTP_STATUS_UNAUTHORIZED; continue; } } new_auth = 0; while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE); if (status == HTTP_STATUS_UNAUTHORIZED) { /* * Flush any error message... */ httpFlush(http); /* * See if we can do authentication... */ new_auth = 1; 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); /* * See if we actually got the file or an error... */ if (status == HTTP_STATUS_OK) { /* * Yes, copy the file... */ while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0) write(fd, buffer, (size_t)bytes); } else { _cupsSetHTTPError(status); httpFlush(http); } /* * Return the request status... */ DEBUG_printf(("1cupsGetFd: Returning %d...", status)); return (status); }
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); }
http_status_t /* O - HTTP status */ cupsPutFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ const char *resource, /* I - Resource name */ int fd) /* I - File descriptor */ { ssize_t bytes; /* Number of bytes read */ int retries; /* Number of retries */ char buffer[8192]; /* Buffer for file */ http_status_t status; /* HTTP status from server */ int new_auth = 0; /* Using new auth information? */ int digest; /* Are we using Digest authentication? */ /* * Range check input... */ DEBUG_printf(("cupsPutFd(http=%p, resource=\"%s\", fd=%d)", (void *)http, resource, fd)); if (!resource || fd < 0) { if (http) http->error = EINVAL; return (HTTP_STATUS_ERROR); } if (!http) if ((http = _cupsConnect()) == NULL) return (HTTP_STATUS_SERVICE_UNAVAILABLE); /* * Then send PUT requests to the HTTP server... */ retries = 0; do { if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close")) { httpClearFields(http); if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } } DEBUG_printf(("2cupsPutFd: starting attempt, authstring=\"%s\"...", http->authstring)); httpClearFields(http); httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked"); httpSetExpect(http, HTTP_STATUS_CONTINUE); digest = http->authstring && !strncmp(http->authstring, "Digest ", 7); if (digest && !new_auth) { /* * Update the Digest authentication string... */ _httpSetDigestAuthString(http, http->nextnonce, "PUT", resource); } #ifdef HAVE_GSSAPI if (http->authstring && !strncmp(http->authstring, "Negotiate", 9) && !new_auth) { /* * Do not use cached Kerberos credentials since they will look like a * "replay" attack... */ _cupsSetNegotiateAuthString(http, "PUT", resource); } #endif /* HAVE_GSSAPI */ httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring); if (httpPut(http, resource)) { if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } else { status = HTTP_STATUS_UNAUTHORIZED; continue; } } /* * Wait up to 1 second for a 100-continue response... */ if (httpWait(http, 1000)) status = httpUpdate(http); else status = HTTP_STATUS_CONTINUE; if (status == HTTP_STATUS_CONTINUE) { /* * Copy the file... */ lseek(fd, 0, SEEK_SET); while ((bytes = read(fd, buffer, sizeof(buffer))) > 0) if (httpCheck(http)) { if ((status = httpUpdate(http)) != HTTP_STATUS_CONTINUE) break; } else httpWrite2(http, buffer, (size_t)bytes); } if (status == HTTP_STATUS_CONTINUE) { httpWrite2(http, buffer, 0); while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE); } if (status == HTTP_STATUS_ERROR && !retries) { DEBUG_printf(("2cupsPutFd: retry on status %d", status)); retries ++; /* Flush any error message... */ httpFlush(http); /* Reconnect... */ if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } /* Try again... */ continue; } DEBUG_printf(("2cupsPutFd: status=%d", status)); new_auth = 0; if (status == HTTP_STATUS_UNAUTHORIZED) { /* * Flush any error message... */ httpFlush(http); /* * See if we can do authentication... */ new_auth = 1; if (cupsDoAuthentication(http, "PUT", 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 || (status == HTTP_STATUS_ERROR && retries < 2)); /* * See if we actually put the file or an error... */ if (status != HTTP_STATUS_CREATED) { _cupsSetHTTPError(status); httpFlush(http); } DEBUG_printf(("1cupsPutFd: Returning %d...", status)); return (status); }
int main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int i; /* Looping var */ http_t *http; /* Connection to server */ char *printer, /* Destination printer */ *pclass, /* Printer class name */ *val; /* Pointer to allow/deny value */ int num_options; /* Number of options */ cups_option_t *options; /* Options */ char *file; /* New PPD file/interface script */ _cupsSetLocale(argv); http = NULL; printer = NULL; num_options = 0; options = NULL; file = NULL; for (i = 1; i < argc; i ++) if (argv[i][0] == '-') switch (argv[i][1]) { case 'c' : /* Add printer to class */ if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno)); return (1); } } if (printer == NULL) { _cupsLangPuts(stderr, _("lpadmin: Unable to add a printer to the class:\n" " You must specify a printer name " "first.")); return (1); } if (argv[i][2]) pclass = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected class name after \"-c\" " "option.")); return (1); } pclass = argv[i]; } if (!validate_name(pclass)) { _cupsLangPuts(stderr, _("lpadmin: Class name can only contain printable " "characters.")); return (1); } if (add_printer_to_class(http, printer, pclass)) return (1); break; case 'd' : /* Set as default destination */ if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno)); return (1); } } if (argv[i][2]) printer = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected printer name after \"-d\" " "option.")); return (1); } printer = argv[i]; } if (!validate_name(printer)) { _cupsLangPuts(stderr, _("lpadmin: Printer name can only contain " "printable characters.")); return (1); } if (default_printer(http, printer)) return (1); i = argc; break; case 'h' : /* Connect to host */ if (http) { httpClose(http); http = NULL; } if (argv[i][2] != '\0') cupsSetServer(argv[i] + 2); else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected hostname after \"-h\" " "option.")); return (1); } cupsSetServer(argv[i]); } break; case 'i' : /* Use the specified interface script */ if (argv[i][2]) file = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected interface after \"-i\" " "option.")); return (1); } file = argv[i]; } break; case 'E' : /* Enable the printer */ if (printer == NULL) { #ifdef HAVE_SSL cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); if (http) httpEncryption(http, HTTP_ENCRYPT_REQUIRED); #else _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), argv[0]); #endif /* HAVE_SSL */ break; } if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno)); return (1); } } if (enable_printer(http, printer)) return (1); break; case 'm' : /* Use the specified standard script/PPD file */ if (argv[i][2]) num_options = cupsAddOption("ppd-name", argv[i] + 2, num_options, &options); else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected model after \"-m\" " "option.")); return (1); } num_options = cupsAddOption("ppd-name", argv[i], num_options, &options); } break; case 'o' : /* Set option */ if (argv[i][2]) num_options = cupsParseOptions(argv[i] + 2, num_options, &options); else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected name=value after \"-o\" " "option.")); return (1); } num_options = cupsParseOptions(argv[i], num_options, &options); } break; case 'p' : /* Add/modify a printer */ if (argv[i][2]) printer = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected printer after \"-p\" " "option.")); return (1); } printer = argv[i]; } if (!validate_name(printer)) { _cupsLangPuts(stderr, _("lpadmin: Printer name can only contain " "printable characters.")); return (1); } break; case 'r' : /* Remove printer from class */ if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno)); return (1); } } if (printer == NULL) { _cupsLangPuts(stderr, _("lpadmin: Unable to remove a printer from the " "class:\n" " You must specify a printer name " "first.")); return (1); } if (argv[i][2]) pclass = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected class after \"-r\" " "option.")); return (1); } pclass = argv[i]; } if (!validate_name(pclass)) { _cupsLangPuts(stderr, _("lpadmin: Class name can only contain printable " "characters.")); return (1); } if (delete_printer_from_class(http, printer, pclass)) return (1); break; case 'R' : /* Remove option */ if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno)); return (1); } } if (printer == NULL) { _cupsLangPuts(stderr, _("lpadmin: Unable to delete option:\n" " You must specify a printer name " "first.")); return (1); } if (argv[i][2]) val = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected name after \"-R\" " "option.")); return (1); } val = argv[i]; } if (delete_printer_option(http, printer, val)) return (1); break; case 'U' : /* Username */ if (argv[i][2] != '\0') cupsSetUser(argv[i] + 2); else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected username after " "\"-U\" option."), argv[0]); return (1); } cupsSetUser(argv[i]); } break; case 'u' : /* Allow/deny users */ if (argv[i][2]) val = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected allow/deny:userlist after " "\"-u\" option.")); return (1); } val = argv[i]; } if (!_cups_strncasecmp(val, "allow:", 6)) num_options = cupsAddOption("requesting-user-name-allowed", val + 6, num_options, &options); else if (!_cups_strncasecmp(val, "deny:", 5)) num_options = cupsAddOption("requesting-user-name-denied", val + 5, num_options, &options); else { _cupsLangPrintf(stderr, _("lpadmin: Unknown allow/deny option \"%s\"."), val); return (1); } break; case 'v' : /* Set the device-uri attribute */ if (argv[i][2]) num_options = cupsAddOption("device-uri", argv[i] + 2, num_options, &options); else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected device URI after \"-v\" " "option.")); return (1); } num_options = cupsAddOption("device-uri", argv[i], num_options, &options); } break; case 'x' : /* Delete a printer */ if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno)); return (1); } } if (argv[i][2]) printer = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected printer or class after " "\"-x\" option.")); return (1); } printer = argv[i]; } if (!validate_name(printer)) { _cupsLangPuts(stderr, _("lpadmin: Printer name can only contain " "printable characters.")); return (1); } if (delete_printer(http, printer)) return (1); i = argc; break; case 'D' : /* Set the printer-info attribute */ if (argv[i][2]) num_options = cupsAddOption("printer-info", argv[i] + 2, num_options, &options); else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected description after " "\"-D\" option.")); return (1); } num_options = cupsAddOption("printer-info", argv[i], num_options, &options); } break; case 'I' : /* Set the supported file types (ignored) */ i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected file type(s) after \"-I\" " "option.")); return (1); } _cupsLangPuts(stderr, _("lpadmin: Warning - content type list ignored.")); break; case 'L' : /* Set the printer-location attribute */ if (argv[i][2]) num_options = cupsAddOption("printer-location", argv[i] + 2, num_options, &options); else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected location after \"-L\" " "option.")); return (1); } num_options = cupsAddOption("printer-location", argv[i], num_options, &options); } break; case 'P' : /* Use the specified PPD file */ if (argv[i][2]) file = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected PPD after \"-P\" option.")); return (1); } file = argv[i]; } break; default : _cupsLangPrintf(stderr, _("lpadmin: Unknown option \"%c\"."), argv[i][1]); return (1); } else { _cupsLangPrintf(stderr, _("lpadmin: Unknown argument \"%s\"."), argv[i]); return (1); } /* * Set options as needed... */ if (num_options || file) { if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno)); return (1); } } if (printer == NULL) { _cupsLangPuts(stderr, _("lpadmin: Unable to set the printer options:\n" " You must specify a printer name first.")); return (1); } if (set_printer_options(http, printer, num_options, options, file)) return (1); } if (printer == NULL) { _cupsLangPuts(stdout, _("Usage:\n" "\n" " lpadmin [-h server] -d destination\n" " lpadmin [-h server] -x destination\n" " lpadmin [-h server] -p printer [-c add-class] " "[-i interface] [-m model]\n" " [-r remove-class] [-v device] " "[-D description]\n" " [-P ppd-file] [-o name=value]\n" " [-u allow:user,user] " "[-u deny:user,user]")); } if (http) httpClose(http); return (0); }
http_status_t /* O - HTTP status */ cupsGetFd(http_t *http, /* I - HTTP connection to server */ const char *resource, /* I - Resource name */ int fd) /* I - File descriptor */ { int bytes; /* Number of bytes read */ char buffer[8192]; /* Buffer for file */ http_status_t status; /* HTTP status from server */ char if_modified_since[HTTP_MAX_VALUE]; /* If-Modified-Since header */ /* * Range check input... */ DEBUG_printf(("cupsGetFd(http=%p, resource=\"%s\", fd=%d)\n", http, resource, fd)); if (!http || !resource || fd < 0) { if (http) http->error = EINVAL; return (HTTP_ERROR); } /* * Then send GET requests to the HTTP server... */ strlcpy(if_modified_since, httpGetField(http, HTTP_FIELD_IF_MODIFIED_SINCE), sizeof(if_modified_since)); do { httpClearFields(http); httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring); httpSetField(http, HTTP_FIELD_IF_MODIFIED_SINCE, if_modified_since); if (httpGet(http, resource)) { if (httpReconnect(http)) { status = HTTP_ERROR; break; } else { status = HTTP_UNAUTHORIZED; continue; } } while ((status = httpUpdate(http)) == HTTP_CONTINUE); if (status == HTTP_UNAUTHORIZED) { /* * Flush any error message... */ httpFlush(http); /* * See if we can do authentication... */ if (cupsDoAuthentication(http, "GET", resource)) break; if (httpReconnect(http)) { status = HTTP_ERROR; break; } continue; } #ifdef HAVE_SSL else if (status == HTTP_UPGRADE_REQUIRED) { /* Flush any error message... */ httpFlush(http); /* Reconnect... */ if (httpReconnect(http)) { status = HTTP_ERROR; break; } /* Upgrade with encryption... */ httpEncryption(http, HTTP_ENCRYPT_REQUIRED); /* Try again, this time with encryption enabled... */ continue; } #endif /* HAVE_SSL */ } while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED); /* * See if we actually got the file or an error... */ if (status == HTTP_OK) { /* * Yes, copy the file... */ while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0) write(fd, buffer, bytes); } else { _cupsSetHTTPError(status); httpFlush(http); } /* * Return the request status... */ return (status); }
http_status_t /* O - HTTP status */ cupsPutFd(http_t *http, /* I - HTTP connection to server */ const char *resource, /* I - Resource name */ int fd) /* I - File descriptor */ { int bytes, /* Number of bytes read */ retries; /* Number of retries */ char buffer[8192]; /* Buffer for file */ http_status_t status; /* HTTP status from server */ /* * Range check input... */ DEBUG_printf(("cupsPutFd(http=%p, resource=\"%s\", fd=%d)\n", http, resource, fd)); if (!http || !resource || fd < 0) { if (http) http->error = EINVAL; return (HTTP_ERROR); } /* * Then send PUT requests to the HTTP server... */ retries = 0; do { DEBUG_printf(("cupsPutFd: starting attempt, authstring=\"%s\"...\n", http->authstring)); httpClearFields(http); httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring); httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked"); httpSetExpect(http, HTTP_CONTINUE); if (httpPut(http, resource)) { if (httpReconnect(http)) { status = HTTP_ERROR; break; } else { status = HTTP_UNAUTHORIZED; continue; } } /* * Wait up to 1 second for a 100-continue response... */ if (httpWait(http, 1000)) status = httpUpdate(http); else status = HTTP_CONTINUE; if (status == HTTP_CONTINUE) { /* * Copy the file... */ lseek(fd, 0, SEEK_SET); while ((bytes = read(fd, buffer, sizeof(buffer))) > 0) if (httpCheck(http)) { if ((status = httpUpdate(http)) != HTTP_CONTINUE) break; } else httpWrite2(http, buffer, bytes); } if (status == HTTP_CONTINUE) { httpWrite2(http, buffer, 0); while ((status = httpUpdate(http)) == HTTP_CONTINUE); } if (status == HTTP_ERROR && !retries) { DEBUG_printf(("cupsPutFd: retry on status %d\n", status)); retries ++; /* Flush any error message... */ httpFlush(http); /* Reconnect... */ if (httpReconnect(http)) { status = HTTP_ERROR; break; } /* Try again... */ continue; } DEBUG_printf(("cupsPutFd: status=%d\n", status)); if (status == HTTP_UNAUTHORIZED) { /* * Flush any error message... */ httpFlush(http); /* * See if we can do authentication... */ if (cupsDoAuthentication(http, "PUT", resource)) break; if (httpReconnect(http)) { status = HTTP_ERROR; break; } continue; } #ifdef HAVE_SSL else if (status == HTTP_UPGRADE_REQUIRED) { /* Flush any error message... */ httpFlush(http); /* Reconnect... */ if (httpReconnect(http)) { status = HTTP_ERROR; break; } /* Upgrade with encryption... */ httpEncryption(http, HTTP_ENCRYPT_REQUIRED); /* Try again, this time with encryption enabled... */ continue; } #endif /* HAVE_SSL */ } while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED || (status == HTTP_ERROR && retries < 2)); /* * See if we actually put the file or an error... */ if (status != HTTP_CREATED) { _cupsSetHTTPError(status); httpFlush(http); } return (status); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { http_t *http; /* HTTP connection to server */ int i; /* Looping var */ int job_id; /* Job ID */ const char *dest; /* Destination printer */ char *instance; /* Pointer to instance name */ char uri[1024]; /* Printer or job URI */ ipp_t *request; /* IPP request */ ipp_t *response; /* IPP response */ ipp_op_t op; /* Operation */ int num_dests; /* Number of destinations */ cups_dest_t *dests, /* Destinations */ *defdest; /* Default destination */ http_encryption_t encryption; /* Encryption? */ _cupsSetLocale(argv); /* * Setup to cancel individual print jobs... */ op = IPP_CANCEL_JOB; job_id = 0; dest = NULL; response = NULL; http = NULL; encryption = cupsEncryption(); /* * Open a connection to the server... */ if ((http = httpConnectEncrypt(cupsServer(), ippPort(), encryption)) == NULL) { _cupsLangPuts(stderr, _("lprm: Unable to contact server!\n")); return (1); } num_dests = cupsGetDests2(http, &dests); defdest = cupsGetDest(NULL, NULL, num_dests, dests); dest = defdest ? defdest->name : NULL; /* * Process command-line arguments... */ for (i = 1; i < argc; i ++) if (argv[i][0] == '-' && argv[i][1] != '\0') switch (argv[i][1]) { case 'E' : /* Encrypt */ #ifdef HAVE_SSL encryption = HTTP_ENCRYPT_REQUIRED; httpEncryption(http, encryption); cupsSetEncryption(encryption); #else _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support compiled in!\n"), argv[0]); #endif /* HAVE_SSL */ break; case 'P' : /* Cancel jobs on a printer */ if (argv[i][2]) dest = argv[i] + 2; else { i ++; dest = argv[i]; } if ((instance = strchr(dest, '/')) != NULL) *instance = '\0'; if (cupsGetDest(dest, NULL, num_dests, dests) == NULL) { _cupsLangPrintf(stderr, _("%s: Error - unknown destination \"%s\"!\n"), argv[0], dest); cupsFreeDests(num_dests, dests); httpClose(http); return(1); } break; case 'U' : /* Username */ if (argv[i][2] != '\0') cupsSetUser(argv[i] + 2); else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected username after " "\'-U\' option!\n"), argv[0]); return (1); } cupsSetUser(argv[i]); } break; case 'h' : /* Connect to host */ if (argv[i][2] != '\0') cupsSetServer(argv[i] + 2); else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected hostname after " "\'-h\' option!\n"), argv[0]); return (1); } else cupsSetServer(argv[i]); } httpClose(http); cupsFreeDests(num_dests, dests); if ((http = httpConnectEncrypt(cupsServer(), ippPort(), encryption)) == NULL) { _cupsLangPuts(stderr, _("lprm: Unable to contact server!\n")); return (1); } num_dests = cupsGetDests2(http, &dests); defdest = cupsGetDest(NULL, NULL, num_dests, dests); dest = defdest ? defdest->name : NULL; break; default : _cupsLangPrintf(stderr, _("%s: Error - unknown option \'%c\'!\n"), argv[0], argv[i][1]); cupsFreeDests(num_dests, dests); httpClose(http); return (1); } else { /* * Cancel a job or printer... */ if (isdigit(argv[i][0] & 255) && cupsGetDest(argv[i], NULL, num_dests, dests) == NULL) { dest = NULL; op = IPP_CANCEL_JOB; job_id = atoi(argv[i]); } else if (!strcmp(argv[i], "-")) { /* * Cancel all jobs */ op = IPP_PURGE_JOBS; } else { dest = argv[i]; job_id = 0; } /* * Build an IPP request, which requires the following * attributes: * * attributes-charset * attributes-natural-language * printer-uri + job-id *or* job-uri * [requesting-user-name] */ request = ippNewRequest(op); if (dest) { httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 0, "/printers/%s", dest); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id); } else { sprintf(uri, "ipp://localhost/jobs/%d", job_id); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri); } ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); /* * Do the request and get back a response... */ if (op == IPP_PURGE_JOBS) response = cupsDoRequest(http, request, "/admin/"); else response = cupsDoRequest(http, request, "/jobs/"); ippDelete(response); if (cupsLastError() > IPP_OK_CONFLICT) { _cupsLangPrintf(stderr, "%s: %s\n", argv[0], cupsLastErrorString()); cupsFreeDests(num_dests, dests); httpClose(http); return (1); } } /* * If nothing has been canceled yet, cancel the current job on the specified * (or default) printer... */ if (response == NULL) if (!cupsCancelJob(dest, 0)) { _cupsLangPrintf(stderr, "%s: %s\n", argv[0], cupsLastErrorString()); cupsFreeDests(num_dests, dests); httpClose(http); return (1); } cupsFreeDests(num_dests, dests); httpClose(http); return (0); }