char * /* O - Message text or @code NULL@ */ cupsNotifyText(cups_lang_t *lang, /* I - Language data */ ipp_t *event) /* I - Event data */ { ipp_attribute_t *notify_text; /* notify-text */ /* * Range check input... */ if (!event || !lang) return (NULL); /* * Get the notify-text attribute from the server... */ if ((notify_text = ippFindAttribute(event, "notify-text", IPP_TAG_TEXT)) == NULL) return (NULL); /* * Return a copy... */ return (strdup(notify_text->values[0].string.text)); }
/////////////////////////////////////////////////////////////////////////////////////////// // // CS : PUBLIC gint getPrinterStatus(gchar *pDestName, gchar *pStatus, gint bufSize) // IN : gchar *pDestName : Printer name. // gint bufSize : Size of output buffer. // OUT : gchar *pStatus : Printer status string. // RETURN : ID_ERR_NO_ERROR : No error. // ID_ERR_CUPS_API_FAILED : Error occured in CUPS API. // PUBLIC gint getPrinterStatus(gchar *pDestName, gchar *pStatus, gint bufSize) { /*** Parameters start ***/ http_t *pHTTP; // Pointer to HTTP connection. ipp_t *pRequest, // Pointer to CUPS IPP request. *pResponse; // Pointer to CUPS IPP response. ipp_attribute_t *pAttribute; // Pointer to CUPS attributes. cups_lang_t *pLanguage; // Pointer to language. gchar printerURI[HTTP_MAX_URI]; // Printer URI. gchar serverName[HTTP_MAX_URI]; // CUPS server name. gint retVal = ID_ERR_NO_ERROR; // Return value. /*** Parameters end ***/ // Initialize buffer. memset(printerURI, 0, sizeof(printerURI)); memset(serverName, 0, sizeof(serverName)); // Get printer URI and CUPS server name. retVal = getPrinterURI(pDestName, printerURI, serverName, HTTP_MAX_URI); if (retVal == ID_ERR_NO_ERROR) { // CUPS http connect. if ((pHTTP = httpConnectEncrypt(serverName, ippPort(), cupsEncryption())) == NULL) { retVal = ID_ERR_CUPS_API_FAILED; } else { pRequest = ippNew(); ippSetOperation(pRequest, IPP_GET_PRINTER_ATTRIBUTES); ippSetRequestId(pRequest, 1); pLanguage = bjcupsLangDefault(); // cupsLangDefault() -> bjcupsLangDefault() for cups-1.1.19 ippAddString(pRequest, IPP_TAG_OPERATION, IPP_TAG_CHARSET, "attributes-charset", NULL, cupsLangEncoding(pLanguage)); ippAddString(pRequest, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, pLanguage->language); ippAddString(pRequest, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printerURI); if ((pResponse = cupsDoRequest(pHTTP, pRequest, "/")) != NULL) { if (ippGetStatusCode(pResponse) > IPP_OK_CONFLICT) { retVal = ID_ERR_CUPS_API_FAILED; } else { pAttribute = ippFindAttribute(pResponse, "printer-state-message", IPP_TAG_TEXT); if (pAttribute != NULL) { strncpy(pStatus, ippGetString(pAttribute, 0, NULL), bufSize); } } ippDelete(pResponse); } else { retVal = ID_ERR_CUPS_API_FAILED; } cupsLangFree(pLanguage); httpClose(pHTTP); } } return(retVal); }// End getPrinterStatus
void serverCreateJobFilename( server_printer_t *printer, /* I - Printer */ server_job_t *job, /* I - Job */ const char *format, /* I - Format or NULL */ char *fname, /* I - Filename buffer */ size_t fnamesize) /* I - Size of filename buffer */ { char name[256], /* "Safe" filename */ *nameptr; /* Pointer into filename */ const char *ext, /* Filename extension */ *job_name; /* job-name value */ ipp_attribute_t *job_name_attr; /* job-name attribute */ /* * Make a name from the job-name attribute... */ if ((job_name_attr = ippFindAttribute(job->attrs, "job-name", IPP_TAG_NAME)) != NULL) job_name = ippGetString(job_name_attr, 0, NULL); else job_name = "untitled"; for (nameptr = name; *job_name && nameptr < (name + sizeof(name) - 1); job_name ++) if (isalnum(*job_name & 255) || *job_name == '-') *nameptr++ = (char)tolower(*job_name & 255); else *nameptr++ = '_'; *nameptr = '\0'; /* * Figure out the extension... */ if (!format) format = job->format; if (!strcasecmp(format, "image/jpeg")) ext = "jpg"; else if (!strcasecmp(format, "image/png")) ext = "png"; else if (!strcasecmp(format, "image/pwg-raster")) ext = "ras"; else if (!strcasecmp(format, "image/urf")) ext = "urf"; else if (!strcasecmp(format, "application/pdf")) ext = "pdf"; else if (!strcasecmp(format, "application/postscript")) ext = "ps"; else ext = "prn"; /* * Create a filename with the job-id, job-name, and document-format (extension)... */ snprintf(fname, fnamesize, "%s/%s/%d-%s.%s", SpoolDirectory, printer->name, job->id, name, ext); }
const char * /* O - Default printer or NULL */ cupsGetDefault2(http_t *http) /* I - HTTP connection */ { ipp_t *request, /* IPP Request */ *response; /* IPP Response */ ipp_attribute_t *attr; /* Current attribute */ const char *var; /* Environment variable */ _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ /* * First see if the LPDEST or PRINTER environment variables are * set... However, if PRINTER is set to "lp", ignore it to work * around a "feature" in most Linux distributions - the default * user login scripts set PRINTER to "lp"... */ if ((var = getenv("LPDEST")) != NULL) return (var); else if ((var = getenv("PRINTER")) != NULL && strcmp(var, "lp") != 0) return (var); /* * Range check input... */ if (!http) return (NULL); /* * Build a CUPS_GET_DEFAULT request, which requires the following * attributes: * * attributes-charset * attributes-natural-language */ request = ippNewRequest(CUPS_GET_DEFAULT); /* * Do the request and get back a response... */ if ((response = cupsDoRequest(http, request, "/")) != NULL) { if ((attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME)) != NULL) { strlcpy(cg->def_printer, attr->values[0].string.text, sizeof(cg->def_printer)); ippDelete(response); return (cg->def_printer); } ippDelete(response); } return (NULL); }
static cups_ptype_t /* O - printer-type value */ get_printer_type(http_t *http, /* I - Server connection */ char *printer, /* I - Printer name */ char *uri, /* I - URI buffer */ size_t urisize) /* I - Size of URI buffer */ { ipp_t *request, /* IPP request */ *response; /* IPP response */ ipp_attribute_t *attr; /* printer-type attribute */ cups_ptype_t type; /* printer-type value */ /* * Build a GET_PRINTER_ATTRIBUTES request, which requires the following * attributes: * * attributes-charset * attributes-natural-language * printer-uri * requested-attributes * requesting-user-name */ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, urisize, "ipp", NULL, "localhost", ippPort(), "/printers/%s", printer); request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", NULL, "printer-type"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); /* * Do the request... */ response = cupsDoRequest(http, request, "/"); if ((attr = ippFindAttribute(response, "printer-type", IPP_TAG_ENUM)) != NULL) { type = (cups_ptype_t)attr->values[0].integer; if (type & CUPS_PRINTER_CLASS) httpAssembleURIf(HTTP_URI_CODING_ALL, uri, urisize, "ipp", NULL, "localhost", ippPort(), "/classes/%s", printer); } else type = CUPS_PRINTER_LOCAL; ippDelete(response); return (type); }
server_job_t * /* O - Job or NULL */ serverFindJob( server_client_t *client, /* I - Client */ int job_id) /* I - Job ID to find or 0 to lookup */ { ipp_attribute_t *attr; /* job-id or job-uri attribute */ server_job_t key, /* Job search key */ *job; /* Matching job, if any */ if (job_id > 0) { key.id = job_id; } else if ((attr = ippFindAttribute(client->request, "job-uri", IPP_TAG_URI)) != NULL) { const char *uri = ippGetString(attr, 0, NULL); /* job-uri value */ char scheme[32], /* URI scheme */ userpass[256], /* username:password */ host[256], /* Hostname/IP */ resource[1024]; /* Resource path */ int port; /* Port number */ if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) >= HTTP_URI_STATUS_OK && !strncmp(resource, client->printer->resource, client->printer->resourcelen) && resource[client->printer->resourcelen] == '/') key.id = atoi(resource + client->printer->resourcelen + 1); else return (NULL); } else if ((attr = ippFindAttribute(client->request, "job-id", IPP_TAG_INTEGER)) != NULL) { key.id = ippGetInteger(attr, 0); } _cupsRWLockRead(&(client->printer->rwlock)); job = (server_job_t *)cupsArrayFind(client->printer->jobs, &key); _cupsRWUnlock(&(client->printer->rwlock)); return (job); }
/////////////////////////////////////////////////////////////////////////////////////////// // // CS : PRIVATE gint checkPrinterState(gchar *pDestName, gchar *pURI, gchar *pServerName) // IN : gchar *pDestName : Printer name. // gchar *pURI : Printer URI. // gchar *pServerName : CUPS server name. // OUT : None. // RETURN : ID_ERR_NO_ERROR : No error. // ID_ERR_UNKNOWN_PRINTER : No printer registerd in CUPS. // ID_ERR_CUPS_API_FAILED : Error occured in CUPS API. // PRIVATE gint checkPrinterState(gchar *pDestName, gchar *pURI, gchar *pServerName) { /*** Parameters start ***/ http_t *pHTTP; // Pointer to HTTP connection. ipp_t *pRequest, // Pointer to CUPS IPP request. *pResponse; // Pointer to CUPS IPP response. ipp_attribute_t *pAttribute; // Pointer to CUPS attributes. cups_lang_t *pLanguage; // Pointer to language. ipp_pstate_t printerState = IPP_PRINTER_STOPPED; // Pointer to printer state. gint retVal = ID_ERR_UNKNOWN_PRINTER; // Return value. /*** Parameters end ***/ // CUPS http connect. if ((pHTTP = httpConnectEncrypt(pServerName, ippPort(), cupsEncryption())) == NULL) { retVal = ID_ERR_CUPS_API_FAILED; } else { pRequest = ippNew(); ippSetOperation(pRequest, IPP_GET_PRINTER_ATTRIBUTES); ippSetRequestId(pRequest, 1); pLanguage = bjcupsLangDefault(); // cupsLangDefault() -> bjcupsLangDefault() for cups-1.1.19 ippAddString(pRequest, IPP_TAG_OPERATION, IPP_TAG_CHARSET, "attributes-charset", NULL, cupsLangEncoding(pLanguage)); ippAddString(pRequest, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, pLanguage->language); ippAddString(pRequest, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, pURI); if ((pResponse = cupsDoRequest(pHTTP, pRequest, "/")) != NULL) { if (ippGetStatusCode(pResponse) > IPP_OK_CONFLICT) { retVal = ID_ERR_CUPS_API_FAILED; } else { if ((pAttribute = ippFindAttribute(pResponse, "printer-state", IPP_TAG_ENUM)) != NULL) { printerState = (ipp_state_t) ippGetInteger(pAttribute, 0); } } ippDelete(pResponse); } else { retVal = ID_ERR_CUPS_API_FAILED; } cupsLangFree(pLanguage); httpClose(pHTTP); } if (printerState == IPP_PRINTER_IDLE || printerState == IPP_PRINTER_PROCESSING) { retVal = ID_ERR_NO_ERROR; } return(retVal); }// End checkPrinterState
const char * /* O - Default printer or @code NULL@ */ cupsGetDefault2(http_t *http) /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ { ipp_t *request, /* IPP Request */ *response; /* IPP Response */ ipp_attribute_t *attr; /* Current attribute */ _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ /* * See if we have a user default printer set... */ if (_cupsUserDefault(cg->def_printer, sizeof(cg->def_printer))) return (cg->def_printer); /* * Connect to the server as needed... */ if (!http) if ((http = _cupsConnect()) == NULL) return (NULL); /* * Build a CUPS_GET_DEFAULT request, which requires the following * attributes: * * attributes-charset * attributes-natural-language */ request = ippNewRequest(CUPS_GET_DEFAULT); /* * Do the request and get back a response... */ if ((response = cupsDoRequest(http, request, "/")) != NULL) { if ((attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME)) != NULL) { strlcpy(cg->def_printer, attr->values[0].string.text, sizeof(cg->def_printer)); ippDelete(response); return (cg->def_printer); } ippDelete(response); } return (NULL); }
const char * gtk_cups_request_ipp_get_string (GtkCupsRequest *request, ipp_tag_t tag, const char *name) { ipp_attribute_t *attribute = NULL; if (request != NULL && request->ipp_request != NULL) attribute = ippFindAttribute (request->ipp_request, name, tag); if (attribute != NULL && ippGetCount (attribute) > 0) return ippGetString (attribute, 0, NULL); else return NULL; }
const char * gtk_cups_request_ipp_get_string (GtkCupsRequest *request, ipp_tag_t tag, const char *name) { ipp_attribute_t *attribute = NULL; if (request != NULL && request->ipp_request != NULL) attribute = ippFindAttribute (request->ipp_request, name, tag); if (attribute != NULL && attribute->values != NULL) return attribute->values[0].string.text; else return NULL; }
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); }
static int iprint_queue_get(const char *sharename, enum printing_types printing_type, char *lpq_command, print_queue_struct **q, print_status_struct *status) { fstring printername; http_t *http = NULL; /* HTTP connection to server */ ipp_t *request = NULL, /* IPP Request */ *response = NULL; /* IPP Response */ ipp_attribute_t *attr = NULL; /* Current attribute */ cups_lang_t *language = NULL; /* Default language */ char uri[HTTP_MAX_URI]; /* printer-uri attribute */ char serviceUri[HTTP_MAX_URI]; /* service-uri attribute */ char httpPath[HTTP_MAX_URI]; /* path portion of the uri */ int jobUseUnixTime = 0; /* Whether job times should * be assumed to be Unix time */ int qcount = 0, /* Number of active queue entries */ qalloc = 0; /* Number of queue entries allocated */ print_queue_struct *queue = NULL, /* Queue entries */ *temp; /* Temporary pointer for queue */ const char *user_name, /* job-originating-user-name attribute */ *job_name; /* job-name attribute */ int job_id; /* job-id attribute */ int job_k_octets; /* job-k-octets attribute */ time_t job_time; /* time-at-creation attribute */ time_t printer_up_time = 0; /* printer's uptime */ ipp_jstate_t job_status; /* job-status attribute */ int job_priority; /* job-priority attribute */ static const char *jattrs[] = /* Requested job attributes */ { "job-id", "job-k-octets", "job-name", "job-originating-user-name", "job-priority", "job-state", "time-at-creation", }; static const char *pattrs[] = /* Requested printer attributes */ { "printer-state", "printer-state-message", "printer-current-time", "printer-up-time" }; *q = NULL; /* HACK ALERT!!! The porblem with support the 'printer name' option is that we key the tdb off the sharename. So we will overload the lpq_command string to pass in the printername (which is basically what we do for non-cups printers ... using the lpq_command to get the queue listing). */ fstrcpy( printername, lpq_command ); DEBUG(5,("iprint_queue_get(%s, %p, %p)\n", printername, q, status)); /* * Make sure we don't ask for passwords... */ cupsSetPasswordCB(iprint_passwd_cb); /* * Try to connect to the server... */ if ((http = httpConnect(iprint_server(), ippPort())) == NULL) { DEBUG(0,("Unable to connect to iPrint server %s - %s\n", iprint_server(), strerror(errno))); goto out; } /* * Generate the printer URI and the service URI that goes with it... */ slprintf(uri, sizeof(uri) - 1, "ipp://%s/ipp/%s", iprint_server(), printername); slprintf(serviceUri, sizeof(serviceUri) - 1, "ipp://%s/ipp/", iprint_server()); /* * For Linux iPrint servers from OES SP1 on, the iPrint server * uses Unix time for job start times unless it detects the iPrint * client in an http User-Agent header. (This was done to accomodate * CUPS broken behavior. According to RFC 2911, section 4.3.14, job * start times are supposed to be relative to how long the printer has * been up.) Since libcups doesn't allow us to set that header before * the request is sent, this ugly hack allows us to detect the server * version and decide how to interpret the job time. */ if (iprint_get_server_version(http, serviceUri) >= NOVELL_SERVER_VERSION_OES_SP1) jobUseUnixTime = 1; request = ippNew(); ippSetOperation(request, IPP_GET_PRINTER_ATTRIBUTES); ippSetRequestId(request, 2); language = cupsLangDefault(); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, "attributes-charset", NULL, "utf-8"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, language->language); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (sizeof(pattrs) / sizeof(pattrs[0])), NULL, pattrs); /* * Do the request and get back a response... */ slprintf(httpPath, sizeof(httpPath) - 1, "/ipp/%s", printername); if ((response = cupsDoRequest(http, request, httpPath)) == NULL) { DEBUG(0,("Unable to get printer status for %s - %s\n", printername, ippErrorString(cupsLastError()))); *q = queue; goto out; } if (ippGetStatusCode(response) >= IPP_OK_CONFLICT) { DEBUG(0,("Unable to get printer status for %s - %s\n", printername, ippErrorString(ippGetStatusCode(response)))); *q = queue; goto out; } /* * Get the current printer status and convert it to the SAMBA values. */ if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL) { if (ippGetInteger(attr, 0) == IPP_PRINTER_STOPPED) status->status = LPSTAT_STOPPED; else status->status = LPSTAT_OK; } if ((attr = ippFindAttribute(response, "printer-state-message", IPP_TAG_TEXT)) != NULL) fstrcpy(status->message, ippGetString(attr, 0, NULL)); if ((attr = ippFindAttribute(response, "printer-up-time", IPP_TAG_INTEGER)) != NULL) printer_up_time = ippGetInteger(attr, 0); ippDelete(response); response = NULL; /* * Build an IPP_GET_JOBS request, which requires the following * attributes: * * attributes-charset * attributes-natural-language * requested-attributes * printer-uri */ request = ippNew(); ippSetOperation(request, IPP_GET_JOBS); ippSetRequestId(request, 3); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, "attributes-charset", NULL, "utf-8"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, language->language); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (sizeof(jattrs) / sizeof(jattrs[0])), NULL, jattrs); /* * Do the request and get back a response... */ slprintf(httpPath, sizeof(httpPath) - 1, "/ipp/%s", printername); if ((response = cupsDoRequest(http, request, httpPath)) == NULL) { DEBUG(0,("Unable to get jobs for %s - %s\n", uri, ippErrorString(cupsLastError()))); goto out; } if (ippGetStatusCode(response) >= IPP_OK_CONFLICT) { DEBUG(0,("Unable to get jobs for %s - %s\n", uri, ippErrorString(ippGetStatusCode(response)))); goto out; } /* * Process the jobs... */ qcount = 0; qalloc = 0; queue = NULL; for (attr = ippFirstAttribute(response); attr != NULL; attr = ippNextAttribute(response)) { /* * Skip leading attributes until we hit a job... */ while (attr != NULL && ippGetGroupTag(attr) != IPP_TAG_JOB) attr = ippNextAttribute(response); if (attr == NULL) break; /* * Allocate memory as needed... */ if (qcount >= qalloc) { qalloc += 16; queue = SMB_REALLOC_ARRAY(queue, print_queue_struct, qalloc); if (queue == NULL) { DEBUG(0,("iprint_queue_get: Not enough memory!")); qcount = 0; goto out; } } temp = queue + qcount; memset(temp, 0, sizeof(print_queue_struct)); /* * Pull the needed attributes from this job... */ job_id = 0; job_priority = 50; job_status = IPP_JOB_PENDING; job_time = 0; job_k_octets = 0; user_name = NULL; job_name = NULL; while (attr != NULL && ippGetGroupTag(attr) == IPP_TAG_JOB) { if (ippGetName(attr) == NULL) { attr = ippNextAttribute(response); break; } if (strcmp(ippGetName(attr), "job-id") == 0 && ippGetValueTag(attr) == IPP_TAG_INTEGER) job_id = ippGetInteger(attr, 0); if (strcmp(ippGetName(attr), "job-k-octets") == 0 && ippGetValueTag(attr) == IPP_TAG_INTEGER) job_k_octets = ippGetInteger(attr, 0); if (strcmp(ippGetName(attr), "job-priority") == 0 && ippGetValueTag(attr) == IPP_TAG_INTEGER) job_priority = ippGetInteger(attr, 0); if (strcmp(ippGetName(attr), "job-state") == 0 && ippGetValueTag(attr) == IPP_TAG_ENUM) job_status = (ipp_jstate_t)ippGetInteger(attr, 0); if (strcmp(ippGetName(attr), "time-at-creation") == 0 && ippGetValueTag(attr) == IPP_TAG_INTEGER) { /* * If jobs times are in Unix time, the accuracy of the job * start time depends upon the iPrint server's time being * set correctly. Otherwise, the accuracy depends upon * the Samba server's time being set correctly */ if (jobUseUnixTime) job_time = ippGetInteger(attr, 0); else job_time = time(NULL) - printer_up_time + ippGetInteger(attr, 0); } if (strcmp(ippGetName(attr), "job-name") == 0 && (ippGetValueTag(attr) == IPP_TAG_NAMELANG || ippGetValueTag(attr) == IPP_TAG_NAME)) job_name = ippGetString(attr, 0, NULL); if (strcmp(ippGetName(attr), "job-originating-user-name") == 0 && (ippGetValueTag(attr) == IPP_TAG_NAMELANG || ippGetValueTag(attr) == IPP_TAG_NAME)) user_name = ippGetString(attr, 0, NULL); attr = ippNextAttribute(response); } /* * See if we have everything needed... */ if (user_name == NULL || job_name == NULL || job_id == 0) { if (attr == NULL) break; else continue; } temp->sysjob = job_id; temp->size = job_k_octets * 1024; temp->status = job_status == IPP_JOB_PENDING ? LPQ_QUEUED : job_status == IPP_JOB_STOPPED ? LPQ_PAUSED : job_status == IPP_JOB_HELD ? LPQ_PAUSED : LPQ_PRINTING; temp->priority = job_priority; temp->time = job_time; strncpy(temp->fs_user, user_name, sizeof(temp->fs_user) - 1); strncpy(temp->fs_file, job_name, sizeof(temp->fs_file) - 1); qcount ++; if (attr == NULL) break; } /* * Return the job queue... */ *q = queue; out: if (response) ippDelete(response); if (language) cupsLangFree(language); if (http) httpClose(http); return qcount; }
static int /* O - 1 on success, 0 on failure */ cups_get_printer_uri( http_t *http, /* I - HTTP connection */ const char *name, /* I - Name of printer or class */ char *host, /* I - Hostname buffer */ int hostsize, /* I - Size of hostname buffer */ int *port, /* O - Port number */ char *resource, /* I - Resource buffer */ int resourcesize, /* I - Size of resource buffer */ int depth) /* I - Depth of query */ { int i; /* Looping var */ int http_port; /* Port number */ http_t *http2; /* Alternate HTTP connection */ ipp_t *request, /* IPP request */ *response; /* IPP response */ ipp_attribute_t *attr; /* Current attribute */ char uri[HTTP_MAX_URI], /* printer-uri attribute */ scheme[HTTP_MAX_URI], /* Scheme name */ username[HTTP_MAX_URI], /* Username:password */ classname[255], /* Temporary class name */ http_hostname[HTTP_MAX_HOST]; /* Hostname associated with connection */ static const char * const requested_attrs[] = { /* Requested attributes */ "printer-uri-supported", "printer-type", "member-uris" }; DEBUG_printf(("cups_get_printer_uri(http=%p, name=\"%s\", host=%p, " "hostsize=%d, resource=%p, resourcesize=%d, depth=%d)\n", http, name ? name : "(null)", host, hostsize, resource, resourcesize, depth)); /* * Setup the printer URI... */ if (httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 0, "/printers/%s", name) != HTTP_URI_OK) { _cupsSetError(IPP_INTERNAL_ERROR, "Unable to create printer-uri!"); *host = '\0'; *resource = '\0'; return (0); } DEBUG_printf(("cups_get_printer_uri: printer-uri=\"%s\"\n", uri)); /* * Get the hostname and port number we are connected to... */ httpGetHostname(http, http_hostname, sizeof(http_hostname)); #ifdef AF_INET6 if (http->hostaddr->addr.sa_family == AF_INET6) http_port = ntohs(http->hostaddr->ipv6.sin6_port); else #endif /* AF_INET6 */ if (http->hostaddr->addr.sa_family == AF_INET) http_port = ntohs(http->hostaddr->ipv4.sin_port); else http_port = ippPort(); /* * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following * attributes: * * attributes-charset * attributes-natural-language * printer-uri * requested-attributes */ request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requested-attributes", sizeof(requested_attrs) / sizeof(requested_attrs[0]), NULL, requested_attrs); /* * Do the request and get back a response... */ if ((response = cupsDoRequest(http, request, "/")) != NULL) { if ((attr = ippFindAttribute(response, "member-uris", IPP_TAG_URI)) != NULL) { /* * Get the first actual printer name in the class... */ for (i = 0; i < attr->num_values; i ++) { httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[i].string.text, scheme, sizeof(scheme), username, sizeof(username), host, hostsize, port, resource, resourcesize); if (!strncmp(resource, "/printers/", 10)) { /* * Found a printer! */ ippDelete(response); return (1); } } /* * No printers in this class - try recursively looking for a printer, * but not more than 3 levels deep... */ if (depth < 3) { for (i = 0; i < attr->num_values; i ++) { httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[i].string.text, scheme, sizeof(scheme), username, sizeof(username), host, hostsize, port, resource, resourcesize); if (!strncmp(resource, "/classes/", 9)) { /* * Found a class! Connect to the right server... */ if (!strcasecmp(http_hostname, host) && *port == http_port) http2 = http; else if ((http2 = httpConnectEncrypt(host, *port, cupsEncryption())) == NULL) { DEBUG_puts("Unable to connect to server!"); continue; } /* * Look up printers on that server... */ strlcpy(classname, resource + 9, sizeof(classname)); cups_get_printer_uri(http2, classname, host, hostsize, port, resource, resourcesize, depth + 1); /* * Close the connection as needed... */ if (http2 != http) httpClose(http2); if (*host) return (1); } } } } else if ((attr = ippFindAttribute(response, "printer-uri-supported", IPP_TAG_URI)) != NULL) { httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[0].string.text, scheme, sizeof(scheme), username, sizeof(username), host, hostsize, port, resource, resourcesize); ippDelete(response); if (!strncmp(resource, "/classes/", 9)) { _cupsSetError(IPP_INTERNAL_ERROR, _("No printer-uri found for class!")); *host = '\0'; *resource = '\0'; return (0); } return (1); } ippDelete(response); } if (cupsLastError() != IPP_NOT_FOUND) _cupsSetError(IPP_INTERNAL_ERROR, _("No printer-uri found!")); *host = '\0'; *resource = '\0'; return (0); }
cupsd_quota_t * /* O - Quota data */ cupsdUpdateQuota( cupsd_printer_t *p, /* I - Printer */ const char *username, /* I - User */ int pages, /* I - Number of pages */ int k) /* I - Number of kilobytes */ { cupsd_quota_t *q; /* Quota data */ cupsd_job_t *job; /* Current job */ time_t curtime; /* Current time */ ipp_attribute_t *attr; /* Job attribute */ if (!p || !username) return (NULL); if (!p->k_limit && !p->page_limit) return (NULL); if ((q = cupsdFindQuota(p, username)) == NULL) return (NULL); cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdUpdateQuota: p=%s username=%s pages=%d k=%d", p->name, username, pages, k); #if defined(__APPLE__) && defined(HAVE_DLFCN_H) /* * Use Apple PrintService quota enforcement if installed (X Server only) */ if (AppleQuotas && PSQUpdateQuotaProc) { q->page_count = (*PSQUpdateQuotaProc)(p->name, p->info, username, pages, 0); return (q); } #endif /* __APPLE__ && HAVE_DLFCN_H */ curtime = time(NULL); if (curtime < q->next_update) { q->page_count += pages; q->k_count += k; return (q); } if (p->quota_period) curtime -= p->quota_period; else curtime = 0; q->next_update = 0; q->page_count = 0; q->k_count = 0; for (job = (cupsd_job_t *)cupsArrayFirst(Jobs); job; job = (cupsd_job_t *)cupsArrayNext(Jobs)) { /* * We only care about the current printer/class and user... */ if (strcasecmp(job->dest, p->name) != 0 || strcasecmp(job->username, q->username) != 0) continue; /* * Make sure attributes are loaded; we always call cupsdLoadJob() to ensure * the access_time member is updated so the job isn't unloaded right away... */ if (!cupsdLoadJob(job)) continue; if ((attr = ippFindAttribute(job->attrs, "time-at-completion", IPP_TAG_INTEGER)) == NULL) if ((attr = ippFindAttribute(job->attrs, "time-at-processing", IPP_TAG_INTEGER)) == NULL) attr = ippFindAttribute(job->attrs, "time-at-creation", IPP_TAG_INTEGER); if (attr->values[0].integer < curtime) { /* * This job is too old to count towards the quota, ignore it... */ if (JobAutoPurge && !job->printer && job->state_value > IPP_JOB_STOPPED) cupsdDeleteJob(job, CUPSD_JOB_PURGE); continue; } if (q->next_update == 0) q->next_update = attr->values[0].integer + p->quota_period; if ((attr = ippFindAttribute(job->attrs, "job-media-sheets-completed", IPP_TAG_INTEGER)) != NULL) q->page_count += attr->values[0].integer; if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL) q->k_count += attr->values[0].integer; } return (q); }
ipp_status_t /* O - IPP status code */ cupsCreateDestJob( http_t *http, /* I - Connection to destination */ cups_dest_t *dest, /* I - Destination */ cups_dinfo_t *info, /* I - Destination information */ int *job_id, /* O - Job ID or 0 on error */ const char *title, /* I - Job name */ int num_options, /* I - Number of job options */ cups_option_t *options) /* I - Job options */ { ipp_t *request, /* Create-Job request */ *response; /* Create-Job response */ ipp_attribute_t *attr; /* job-id attribute */ DEBUG_printf(("cupsCreateDestJob(http=%p, dest=%p(%s/%s), info=%p, " "job_id=%p, title=\"%s\", num_options=%d, options=%p)", http, dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, info, job_id, title, num_options, options)); /* * Range check input... */ if (job_id) *job_id = 0; if (!http || !dest || !info || !job_id) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); DEBUG_puts("1cupsCreateDestJob: Bad arguments."); return (IPP_STATUS_ERROR_INTERNAL); } /* * Build a Create-Job request... */ if ((request = ippNewRequest(IPP_OP_CREATE_JOB)) == NULL) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0); DEBUG_puts("1cupsCreateDestJob: Unable to create Create-Job request."); return (IPP_STATUS_ERROR_INTERNAL); } ippSetVersion(request, info->version / 10, info->version % 10); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, info->uri); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); if (title) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, title); cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION); cupsEncodeOptions2(request, num_options, options, IPP_TAG_JOB); cupsEncodeOptions2(request, num_options, options, IPP_TAG_SUBSCRIPTION); /* * Send the request and get the job-id... */ response = cupsDoRequest(http, request, info->resource); if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) != NULL) { *job_id = attr->values[0].integer; DEBUG_printf(("1cupsCreateDestJob: job-id=%d", *job_id)); } ippDelete(response); /* * Return the status code from the Create-Job request... */ DEBUG_printf(("1cupsCreateDestJob: %s (%s)", ippErrorString(cupsLastError()), cupsLastErrorString())); return (cupsLastError()); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { ipp_t *msg; /* Event message from scheduler */ ipp_state_t state; /* IPP event state */ struct sigaction action; /* POSIX sigaction data */ DBusConnection *con = NULL; /* Connection to DBUS server */ DBusError error; /* Error, if any */ DBusMessage *message; /* Message to send */ DBusMessageIter iter; /* Iterator for message data */ int lock_fd = -1; /* Lock file descriptor */ /* * Don't buffer stderr... */ setbuf(stderr, NULL); /* * Ignore SIGPIPE signals... */ memset(&action, 0, sizeof(action)); action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &action, NULL); /* * Validate command-line options... */ if (argc != 3) { fputs("Usage: dbus dbus:/// notify-user-data\n", stderr); return (1); } if (strncmp(argv[1], "dbus:", 5)) { fprintf(stderr, "ERROR: Bad URI \"%s\"!\n", argv[1]); return (1); } /* * Loop forever until we run out of events... */ for (;;) { ipp_attribute_t *attr; /* Current attribute */ const char *event; /* Event name */ const char *signame = NULL;/* DBUS signal name */ char *printer_reasons = NULL; /* Printer reasons string */ char *job_reasons = NULL; /* Job reasons string */ const char *nul = ""; /* Empty string value */ int no = 0; /* Boolean "no" value */ int params = PARAMS_NONE; /* What parameters to include? */ /* * Get the next event... */ msg = ippNew(); while ((state = ippReadFile(0, msg)) != IPP_DATA) { if (state <= IPP_IDLE) break; } fprintf(stderr, "DEBUG: state=%d\n", state); if (state == IPP_ERROR) fputs("DEBUG: ippReadFile() returned IPP_ERROR!\n", stderr); if (state <= IPP_IDLE) { /* * Out of messages, free memory and then exit... */ ippDelete(msg); break; } /* * Verify connection to DBUS server... */ if (con && !dbus_connection_get_is_connected(con)) { dbus_connection_unref(con); con = NULL; } if (!con) { dbus_error_init(&error); con = dbus_bus_get(DBUS_BUS_SYSTEM, &error); if (!con) dbus_error_free(&error); else fputs("DEBUG: Connected to D-BUS\n", stderr); } if (!con) continue; if (lock_fd == -1 && acquire_lock(&lock_fd, lock_filename, sizeof(lock_filename))) continue; attr = ippFindAttribute(msg, "notify-subscribed-event", IPP_TAG_KEYWORD); if (!attr) continue; event = ippGetString(attr, 0, NULL); if (!strncmp(event, "server-", 7)) { const char *word2 = event + 7; /* Second word */ if (!strcmp(word2, "restarted")) signame = "ServerRestarted"; else if (!strcmp(word2, "started")) signame = "ServerStarted"; else if (!strcmp(word2, "stopped")) signame = "ServerStopped"; else if (!strcmp(word2, "audit")) signame = "ServerAudit"; else continue; } else if (!strncmp(event, "printer-", 8)) { const char *word2 = event + 8; /* Second word */ params = PARAMS_PRINTER; if (!strcmp(word2, "restarted")) signame = "PrinterRestarted"; else if (!strcmp(word2, "shutdown")) signame = "PrinterShutdown"; else if (!strcmp(word2, "stopped")) signame = "PrinterStopped"; else if (!strcmp(word2, "state-changed")) signame = "PrinterStateChanged"; else if (!strcmp(word2, "finishings-changed")) signame = "PrinterFinishingsChanged"; else if (!strcmp(word2, "media-changed")) signame = "PrinterMediaChanged"; else if (!strcmp(word2, "added")) signame = "PrinterAdded"; else if (!strcmp(word2, "deleted")) signame = "PrinterDeleted"; else if (!strcmp(word2, "modified")) signame = "PrinterModified"; else continue; } else if (!strncmp(event, "job-", 4)) { const char *word2 = event + 4; /* Second word */ params = PARAMS_JOB; if (!strcmp(word2, "state-changed")) signame = "JobState"; else if (!strcmp(word2, "created")) signame = "JobCreated"; else if (!strcmp(word2, "completed")) signame = "JobCompleted"; else if (!strcmp(word2, "stopped")) signame = "JobStopped"; else if (!strcmp(word2, "config-changed")) signame = "JobConfigChanged"; else if (!strcmp(word2, "progress")) signame = "JobProgress"; else continue; } else continue; /* * Create and send the new message... */ fprintf(stderr, "DEBUG: %s\n", signame); message = dbus_message_new_signal("/org/cups/cupsd/Notifier", "org.cups.cupsd.Notifier", signame); dbus_message_append_iter_init(message, &iter); attr = ippFindAttribute(msg, "notify-text", IPP_TAG_TEXT); if (attr) { const char *val = ippGetString(attr, 0, NULL); if (!dbus_message_iter_append_string(&iter, &val)) goto bail; } else goto bail; if (params >= PARAMS_PRINTER) { char *p; /* Pointer into printer_reasons */ size_t reasons_length; /* Required size of printer_reasons */ int i; /* Looping var */ int have_printer_params = 1;/* Do we have printer URI? */ /* STRING printer-uri or "" */ attr = ippFindAttribute(msg, "notify-printer-uri", IPP_TAG_URI); if (attr) { const char *val = ippGetString(attr, 0, NULL); if (!dbus_message_iter_append_string(&iter, &val)) goto bail; } else { have_printer_params = 0; dbus_message_iter_append_string(&iter, &nul); } /* STRING printer-name */ if (have_printer_params) { attr = ippFindAttribute(msg, "printer-name", IPP_TAG_NAME); if (attr) { const char *val = ippGetString(attr, 0, NULL); if (!dbus_message_iter_append_string(&iter, &val)) goto bail; } else goto bail; } else dbus_message_iter_append_string(&iter, &nul); /* UINT32 printer-state */ if (have_printer_params) { attr = ippFindAttribute(msg, "printer-state", IPP_TAG_ENUM); if (attr) { dbus_uint32_t val = ippGetInteger(attr, 0); dbus_message_iter_append_uint32(&iter, &val); } else goto bail; } else dbus_message_iter_append_uint32(&iter, &no); /* STRING printer-state-reasons */ if (have_printer_params) { attr = ippFindAttribute(msg, "printer-state-reasons", IPP_TAG_KEYWORD); if (attr) { int num_values = ippGetCount(attr); for (reasons_length = 0, i = 0; i < num_values; i++) /* All need commas except the last, which needs a nul byte. */ reasons_length += 1 + strlen(ippGetString(attr, i, NULL)); printer_reasons = malloc(reasons_length); if (!printer_reasons) goto bail; p = printer_reasons; for (i = 0; i < num_values; i++) { if (i) *p++ = ','; strlcpy(p, ippGetString(attr, i, NULL), reasons_length - (p - printer_reasons)); p += strlen(p); } if (!dbus_message_iter_append_string(&iter, &printer_reasons)) goto bail; } else goto bail; } else dbus_message_iter_append_string(&iter, &nul); /* BOOL printer-is-accepting-jobs */ if (have_printer_params) { attr = ippFindAttribute(msg, "printer-is-accepting-jobs", IPP_TAG_BOOLEAN); if (attr) { dbus_bool_t val = ippGetBoolean(attr, 0); dbus_message_iter_append_boolean(&iter, &val); } else goto bail; } else dbus_message_iter_append_boolean(&iter, &no); } if (params >= PARAMS_JOB) { char *p; /* Pointer into job_reasons */ size_t reasons_length; /* Required size of job_reasons */ int i; /* Looping var */ /* UINT32 job-id */ attr = ippFindAttribute(msg, "notify-job-id", IPP_TAG_INTEGER); if (attr) { dbus_uint32_t val = ippGetInteger(attr, 0); dbus_message_iter_append_uint32(&iter, &val); } else goto bail; /* UINT32 job-state */ attr = ippFindAttribute(msg, "job-state", IPP_TAG_ENUM); if (attr) { dbus_uint32_t val = ippGetInteger(attr, 0); dbus_message_iter_append_uint32(&iter, &val); } else goto bail; /* STRING job-state-reasons */ attr = ippFindAttribute(msg, "job-state-reasons", IPP_TAG_KEYWORD); if (attr) { int num_values = ippGetCount(attr); for (reasons_length = 0, i = 0; i < num_values; i++) /* All need commas except the last, which needs a nul byte. */ reasons_length += 1 + strlen(ippGetString(attr, i, NULL)); job_reasons = malloc(reasons_length); if (!job_reasons) goto bail; p = job_reasons; for (i = 0; i < num_values; i++) { if (i) *p++ = ','; strlcpy(p, ippGetString(attr, i, NULL), reasons_length - (p - job_reasons)); p += strlen(p); } if (!dbus_message_iter_append_string(&iter, &job_reasons)) goto bail; } else goto bail; /* STRING job-name or "" */ attr = ippFindAttribute(msg, "job-name", IPP_TAG_NAME); if (attr) { const char *val = ippGetString(attr, 0, NULL); if (!dbus_message_iter_append_string(&iter, &val)) goto bail; } else dbus_message_iter_append_string(&iter, &nul); /* UINT32 job-impressions-completed */ attr = ippFindAttribute(msg, "job-impressions-completed", IPP_TAG_INTEGER); if (attr) { dbus_uint32_t val = ippGetInteger(attr, 0); dbus_message_iter_append_uint32(&iter, &val); } else goto bail; } dbus_connection_send(con, message, NULL); dbus_connection_flush(con); /* * Cleanup... */ bail: dbus_message_unref(message); if (printer_reasons) free(printer_reasons); if (job_reasons) free(job_reasons); ippDelete(msg); } /* * Remove lock file... */ if (lock_fd >= 0) { close(lock_fd); release_lock(); } return (0); }
void cupsdAddEvent( cupsd_eventmask_t event, /* I - Event */ cupsd_printer_t *dest, /* I - Printer associated with event */ cupsd_job_t *job, /* I - Job associated with event */ const char *text, /* I - Notification text */ ...) /* I - Additional arguments as needed */ { va_list ap; /* Pointer to additional arguments */ char ftext[1024]; /* Formatted text buffer */ ipp_attribute_t *attr; /* Printer/job attribute */ cupsd_event_t *temp; /* New event pointer */ cupsd_subscription_t *sub; /* Current subscription */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddEvent(event=%s, dest=%p(%s), job=%p(%d), text=\"%s\", ...)", cupsdEventName(event), dest, dest ? dest->name : "", job, job ? job->id : 0, text); /* * Keep track of events with any OS-supplied notification mechanisms... */ LastEvent |= event; #ifdef HAVE_DBUS cupsd_send_dbus(event, dest, job); #endif /* HAVE_DBUS */ /* * Return if we aren't keeping events... */ if (MaxEvents <= 0) { cupsdLogMessage(CUPSD_LOG_WARN, "cupsdAddEvent: Discarding %s event since MaxEvents is %d!", cupsdEventName(event), MaxEvents); return; } /* * Then loop through the subscriptions and add the event to the corresponding * caches... */ for (temp = NULL, sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions); sub; sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions)) { /* * Check if this subscription requires this event... */ if ((sub->mask & event) != 0 && (sub->dest == dest || !sub->dest) && (sub->job == job || !sub->job)) { /* * Need this event, so create a new event record... */ if ((temp = (cupsd_event_t *)calloc(1, sizeof(cupsd_event_t))) == NULL) { cupsdLogMessage(CUPSD_LOG_CRIT, "Unable to allocate memory for event - %s", strerror(errno)); return; } temp->event = event; temp->time = time(NULL); temp->attrs = ippNew(); temp->job = job; if (dest) temp->dest = dest; else if (job) temp->dest = dest = cupsdFindPrinter(job->dest); /* * Add common event notification attributes... */ ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_CHARSET, "notify-charset", NULL, "utf-8"); ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_LANGUAGE, "notify-natural-language", NULL, "en-US"); ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER, "notify-subscription-id", sub->id); ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER, "notify-sequence-number", sub->next_event_id); ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "notify-subscribed-event", NULL, cupsdEventName(event)); if (sub->user_data_len > 0) ippAddOctetString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, "notify-user-data", sub->user_data, sub->user_data_len); ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER, "printer-up-time", time(NULL)); va_start(ap, text); vsnprintf(ftext, sizeof(ftext), text, ap); va_end(ap); ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_TEXT, "notify-text", NULL, ftext); if (dest) { /* * Add printer attributes... */ ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_URI, "notify-printer-uri", NULL, dest->uri); ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_NAME, "printer-name", NULL, dest->name); ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_ENUM, "printer-state", dest->state); if (dest->num_reasons == 0) ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "printer-state-reasons", NULL, dest->state == IPP_PRINTER_STOPPED ? "paused" : "none"); else ippAddStrings(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "printer-state-reasons", dest->num_reasons, NULL, (const char * const *)dest->reasons); ippAddBoolean(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, "printer-is-accepting-jobs", (char)dest->accepting); } if (job) { /* * Add job attributes... */ ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER, "notify-job-id", job->id); ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_ENUM, "job-state", job->state_value); if ((attr = ippFindAttribute(job->attrs, "job-name", IPP_TAG_NAME)) != NULL) ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_NAME, "job-name", NULL, attr->values[0].string.text); switch (job->state_value) { case IPP_JOB_PENDING : if (dest && dest->state == IPP_PRINTER_STOPPED) ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "printer-stopped"); else ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "none"); break; case IPP_JOB_HELD : if (ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_KEYWORD) != NULL || ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME) != NULL) ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-hold-until-specified"); else ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-incoming"); break; case IPP_JOB_PROCESSING : ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-printing"); break; case IPP_JOB_STOPPED : ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-stopped"); break; case IPP_JOB_CANCELED : ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-canceled-by-user"); break; case IPP_JOB_ABORTED : ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "aborted-by-system"); break; case IPP_JOB_COMPLETED : ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-completed-successfully"); break; } ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER, "job-impressions-completed", job->sheets ? job->sheets->values[0].integer : 0); } /* * Send the notification for this subscription... */ cupsd_send_notification(sub, temp); } } if (temp) cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS); else cupsdLogMessage(CUPSD_LOG_DEBUG, "Discarding unused %s event...", cupsdEventName(event)); }
char * /* O - Subject string or @code NULL@ */ cupsNotifySubject(cups_lang_t *lang, /* I - Language data */ ipp_t *event) /* I - Event data */ { char buffer[1024]; /* Subject buffer */ const char *prefix, /* Prefix on subject */ *state; /* Printer/job state string */ ipp_attribute_t *job_id, /* notify-job-id */ *job_name, /* job-name */ *job_state, /* job-state */ *printer_name, /* printer-name */ *printer_state, /* printer-state */ *printer_uri, /* notify-printer-uri */ *subscribed; /* notify-subscribed-event */ /* * Range check input... */ if (!event || !lang) return (NULL); /* * Get the required attributes... */ job_id = ippFindAttribute(event, "notify-job-id", IPP_TAG_INTEGER); job_name = ippFindAttribute(event, "job-name", IPP_TAG_NAME); job_state = ippFindAttribute(event, "job-state", IPP_TAG_ENUM); printer_name = ippFindAttribute(event, "printer-name", IPP_TAG_NAME); printer_state = ippFindAttribute(event, "printer-state", IPP_TAG_ENUM); printer_uri = ippFindAttribute(event, "notify-printer-uri", IPP_TAG_URI); subscribed = ippFindAttribute(event, "notify-subscribed-event", IPP_TAG_KEYWORD); if (job_id && printer_name && printer_uri && job_state) { /* * Job event... */ prefix = _cupsLangString(lang, _("Print Job:")); switch (job_state->values[0].integer) { case IPP_JOB_PENDING : state = _cupsLangString(lang, _("pending")); break; case IPP_JOB_HELD : state = _cupsLangString(lang, _("held")); break; case IPP_JOB_PROCESSING : state = _cupsLangString(lang, _("processing")); break; case IPP_JOB_STOPPED : state = _cupsLangString(lang, _("stopped")); break; case IPP_JOB_CANCELED : state = _cupsLangString(lang, _("canceled")); break; case IPP_JOB_ABORTED : state = _cupsLangString(lang, _("aborted")); break; case IPP_JOB_COMPLETED : state = _cupsLangString(lang, _("completed")); break; default : state = _cupsLangString(lang, _("unknown")); break; } snprintf(buffer, sizeof(buffer), "%s %s-%d (%s) %s", prefix, printer_name->values[0].string.text, job_id->values[0].integer, job_name ? job_name->values[0].string.text : _cupsLangString(lang, _("untitled")), state); } else if (printer_uri && printer_name && printer_state) { /* * Printer event... */ prefix = _cupsLangString(lang, _("Printer:")); switch (printer_state->values[0].integer) { case IPP_PRINTER_IDLE : state = _cupsLangString(lang, _("idle")); break; case IPP_PRINTER_PROCESSING : state = _cupsLangString(lang, _("processing")); break; case IPP_PRINTER_STOPPED : state = _cupsLangString(lang, _("stopped")); break; default : state = _cupsLangString(lang, _("unknown")); break; } snprintf(buffer, sizeof(buffer), "%s %s %s", prefix, printer_name->values[0].string.text, state); } else if (subscribed) strlcpy(buffer, subscribed->values[0].string.text, sizeof(buffer)); else return (NULL); /* * Duplicate and return the subject string... */ return (strdup(buffer)); }
static int /* O - Number of options or -1 on error */ get_printer(http_t *http, /* I - HTTP connection */ const char *name, /* I - Printer name from request */ char *dest, /* I - Destination buffer */ size_t destsize, /* I - Size of destination buffer */ cups_option_t **options, /* O - Printer options */ int *accepting, /* O - printer-is-accepting-jobs value */ int *shared, /* O - printer-is-shared value */ ipp_pstate_t *state) /* O - printer-state value */ { int num_options; /* Number of options */ cups_file_t *fp; /* lpoptions file */ char line[1024], /* Line from lpoptions file */ *value, /* Pointer to value on line */ *optptr; /* Pointer to options on line */ int linenum; /* Line number in file */ const char *cups_serverroot; /* CUPS_SERVERROOT env var */ ipp_t *request; /* IPP request */ ipp_t *response; /* IPP response */ ipp_attribute_t *attr; /* IPP attribute */ char uri[HTTP_MAX_URI]; /* Printer URI */ static const char * const requested[] = { /* Requested attributes */ "printer-info", "printer-is-accepting-jobs", "printer-is-shared", "printer-name", "printer-state" }; /* * Initialize everything... */ if (accepting) *accepting = 0; if (shared) *shared = 0; if (state) *state = IPP_PRINTER_STOPPED; if (options) *options = NULL; /* * See if the name is a queue name optionally with an instance name. */ strlcpy(dest, name, destsize); if ((value = strchr(dest, '/')) != NULL) *value = '\0'; /* * Setup the Get-Printer-Attributes request... */ request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES); 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); ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(requested) / sizeof(requested[0])), NULL, requested); /* * Do the request... */ response = cupsDoRequest(http, request, "/"); if (!response || cupsLastError() > IPP_OK_CONFLICT) { /* * If we can't find the printer by name, look up the printer-name * using the printer-info values... */ ipp_attribute_t *accepting_attr,/* printer-is-accepting-jobs */ *info_attr, /* printer-info */ *name_attr, /* printer-name */ *shared_attr, /* printer-is-shared */ *state_attr; /* printer-state */ ippDelete(response); /* * Setup the CUPS-Get-Printers request... */ request = ippNewRequest(CUPS_GET_PRINTERS); ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(requested) / sizeof(requested[0])), NULL, requested); /* * Do the request... */ response = cupsDoRequest(http, request, "/"); if (!response || cupsLastError() > IPP_OK_CONFLICT) { syslog(LOG_ERR, "Unable to get list of printers - %s", cupsLastErrorString()); ippDelete(response); return (-1); } /* * Scan the response for printers... */ *dest = '\0'; attr = response->attrs; while (attr) { /* * Skip to the next printer... */ while (attr && attr->group_tag != IPP_TAG_PRINTER) attr = attr->next; if (!attr) break; /* * Get all of the attributes for the current printer... */ accepting_attr = NULL; info_attr = NULL; name_attr = NULL; shared_attr = NULL; state_attr = NULL; while (attr && attr->group_tag == IPP_TAG_PRINTER) { if (!strcmp(attr->name, "printer-is-accepting-jobs") && attr->value_tag == IPP_TAG_BOOLEAN) accepting_attr = attr; else if (!strcmp(attr->name, "printer-info") && attr->value_tag == IPP_TAG_TEXT) info_attr = attr; else if (!strcmp(attr->name, "printer-name") && attr->value_tag == IPP_TAG_NAME) name_attr = attr; else if (!strcmp(attr->name, "printer-is-shared") && attr->value_tag == IPP_TAG_BOOLEAN) shared_attr = attr; else if (!strcmp(attr->name, "printer-state") && attr->value_tag == IPP_TAG_ENUM) state_attr = attr; attr = attr->next; } if (info_attr && name_attr && !_cups_strcasecmp(name, info_attr->values[0].string.text)) { /* * Found a match, use this one! */ strlcpy(dest, name_attr->values[0].string.text, destsize); if (accepting && accepting_attr) *accepting = accepting_attr->values[0].boolean; if (shared && shared_attr) *shared = shared_attr->values[0].boolean; if (state && state_attr) *state = (ipp_pstate_t)state_attr->values[0].integer; break; } } ippDelete(response); if (!*dest) { syslog(LOG_ERR, "Unable to find \"%s\" in list of printers!", name); return (-1); } name = dest; } else { /* * Get values from the response... */ if (accepting) { if ((attr = ippFindAttribute(response, "printer-is-accepting-jobs", IPP_TAG_BOOLEAN)) == NULL) syslog(LOG_ERR, "No printer-is-accepting-jobs attribute found in " "response from server!"); else *accepting = attr->values[0].boolean; } if (shared) { if ((attr = ippFindAttribute(response, "printer-is-shared", IPP_TAG_BOOLEAN)) == NULL) { syslog(LOG_ERR, "No printer-is-shared attribute found in " "response from server!"); *shared = 1; } else *shared = attr->values[0].boolean; } if (state) { if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) == NULL) syslog(LOG_ERR, "No printer-state attribute found in " "response from server!"); else *state = (ipp_pstate_t)attr->values[0].integer; } ippDelete(response); } /* * Next look for the printer in the lpoptions file... */ num_options = 0; if (options && shared && accepting) { if ((cups_serverroot = getenv("CUPS_SERVERROOT")) == NULL) cups_serverroot = CUPS_SERVERROOT; snprintf(line, sizeof(line), "%s/lpoptions", cups_serverroot); if ((fp = cupsFileOpen(line, "r")) != NULL) { linenum = 0; while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) { /* * Make sure we have "Dest name options" or "Default name options"... */ if ((_cups_strcasecmp(line, "Dest") && _cups_strcasecmp(line, "Default")) || !value) continue; /* * Separate destination name from options... */ for (optptr = value; *optptr && !isspace(*optptr & 255); optptr ++); while (*optptr == ' ') *optptr++ = '\0'; /* * If this is our destination, parse the options and break out of * the loop - we're done! */ if (!_cups_strcasecmp(value, name)) { num_options = cupsParseOptions(optptr, num_options, options); break; } } cupsFileClose(fp); } } else if (options) *options = NULL; /* * Return the number of options for this destination... */ return (num_options); }
static int /* O - Job ID or -1 on error */ create_job(http_t *http, /* I - HTTP connection */ const char *dest, /* I - Destination name */ const char *title, /* I - job-name */ const char *docname, /* I - Name of job file */ const char *user, /* I - requesting-user-name */ int num_options, /* I - Number of options for job */ cups_option_t *options) /* I - Options for job */ { ipp_t *request; /* IPP request */ ipp_t *response; /* IPP response */ ipp_attribute_t *attr; /* IPP attribute */ char uri[HTTP_MAX_URI]; /* Printer URI */ int id; /* Job ID */ /* * Setup the Create-Job request... */ request = ippNewRequest(IPP_CREATE_JOB); 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); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, user); if (title[0]) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, title); if (docname[0]) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name", NULL, docname); cupsEncodeOptions(request, num_options, options); /* * Do the request... */ snprintf(uri, sizeof(uri), "/printers/%s", dest); response = cupsDoRequest(http, request, uri); if (!response || cupsLastError() > IPP_OK_CONFLICT) { syslog(LOG_ERR, "Unable to create job - %s", cupsLastErrorString()); ippDelete(response); return (-1); } /* * Get the job-id value from the response and return it... */ if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) == NULL) { id = -1; syslog(LOG_ERR, "No job-id attribute found in response from server!"); } else { id = attr->values[0].integer; syslog(LOG_INFO, "Print file - job ID = %d", id); } ippDelete(response); return (id); }
static void _pp_maintenance_command_execute_thread (GSimpleAsyncResult *res, GObject *object, GCancellable *cancellable) { PpMaintenanceCommand *command = (PpMaintenanceCommand *) object; PpMaintenanceCommandPrivate *priv = command->priv; static const char *attrs[] = {"printer-commands"}; ipp_attribute_t *attr = NULL; gboolean success = FALSE; GError *error = NULL; ipp_t *request; ipp_t *response = NULL; gchar *printer_uri; gchar *printer_commands = NULL; gchar *printer_commands_lowercase = NULL; gchar *command_lowercase; gchar *file_name = NULL; int fd = -1; printer_uri = g_strdup_printf ("ipp://localhost/printers/%s", priv->printer_name); request = ippNewRequest (IPP_GET_PRINTER_ATTRIBUTES); ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printer_uri); ippAddStrings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", 1, NULL, attrs); response = cupsDoRequest (CUPS_HTTP_DEFAULT, request, "/"); if (response) { if (ippGetStatusCode (response) <= IPP_OK_CONFLICT) { attr = ippFindAttribute (response, "printer-commands", IPP_TAG_ZERO); if (attr && ippGetCount (attr) > 0 && ippGetValueTag (attr) != IPP_TAG_NOVALUE) { if (ippGetValueTag (attr) == IPP_TAG_KEYWORD) { printer_commands = g_strdup (ippGetString (attr, 0, NULL)); } } else { success = TRUE; } } ippDelete (response); } if (printer_commands) { command_lowercase = g_ascii_strdown (priv->command, -1); printer_commands_lowercase = g_ascii_strdown (printer_commands, -1); if (g_strrstr (printer_commands_lowercase, command_lowercase)) { request = ippNewRequest (IPP_PRINT_JOB); ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printer_uri); ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, priv->title); ippAddString (request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format", NULL, "application/vnd.cups-command"); fd = g_file_open_tmp ("ccXXXXXX", &file_name, &error); if (fd != -1) { FILE *file; file = fdopen (fd, "w"); fprintf (file, "#CUPS-COMMAND\n"); fprintf (file, "%s\n", priv->command); fclose (file); response = cupsDoFileRequest (CUPS_HTTP_DEFAULT, request, "/", file_name); g_unlink (file_name); if (response) { if (ippGetStatusCode (response) <= IPP_OK_CONFLICT) { success = TRUE; } ippDelete (response); } } g_free (file_name); } else { success = TRUE; } g_free (command_lowercase); g_free (printer_commands_lowercase); g_free (printer_commands); } g_free (printer_uri); if (!success) { g_simple_async_result_set_error (res, G_IO_ERROR, G_IO_ERROR_FAILED, "Execution of maintenance command failed."); } g_simple_async_result_set_op_res_gboolean (res, success); }
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); } } }
int /* O - Exit status */ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { int status; /* Status of tests (0 = success, 1 = fail) */ const char *ppdfile; /* PPD filename */ ppd_file_t *ppd; /* PPD file */ _ppd_cache_t *pc; /* PPD cache and PWG mapping data */ const pwg_media_t *pwgmedia; /* PWG media size */ size_t i, /* Looping var */ num_media; /* Number of media sizes */ const pwg_media_t *mediatable; /* Media size table */ int dupmedia = 0; /* Duplicate media sizes? */ status = 0; if (argc < 2 || argc > 3) { puts("Usage: ./testpwg filename.ppd [jobfile]"); return (1); } ppdfile = argv[1]; printf("ppdOpenFile(%s): ", ppdfile); if ((ppd = ppdOpenFile(ppdfile)) == NULL) { ppd_status_t err; /* Last error in file */ int line; /* Line number in file */ err = ppdLastError(&line); printf("FAIL (%s on line %d)\n", ppdErrorString(err), line); return (1); } else puts("PASS"); fputs("_ppdCacheCreateWithPPD(ppd): ", stdout); if ((pc = _ppdCacheCreateWithPPD(ppd)) == NULL) { puts("FAIL"); status ++; } else { puts("PASS"); status += test_ppd_cache(pc, ppd); if (argc == 3) { /* * Test PageSize mapping code. */ int fd; /* Job file descriptor */ const char *pagesize; /* PageSize value */ ipp_t *job; /* Job attributes */ ipp_attribute_t *media; /* Media attribute */ if ((fd = open(argv[2], O_RDONLY)) >= 0) { job = ippNew(); ippReadFile(fd, job); close(fd); if ((media = ippFindAttribute(job, "media", IPP_TAG_ZERO)) != NULL && media->value_tag != IPP_TAG_NAME && media->value_tag != IPP_TAG_KEYWORD) media = NULL; if (media) printf("_ppdCacheGetPageSize(media=%s): ", media->values[0].string.text); else fputs("_ppdCacheGetPageSize(media-col): ", stdout); fflush(stdout); if ((pagesize = _ppdCacheGetPageSize(pc, job, NULL, NULL)) == NULL) { puts("FAIL (Not Found)"); status = 1; } else if (media && _cups_strcasecmp(pagesize, media->values[0].string.text)) { printf("FAIL (Got \"%s\", Expected \"%s\")\n", pagesize, media->values[0].string.text); status = 1; } else printf("PASS (%s)\n", pagesize); ippDelete(job); } else { perror(argv[2]); status = 1; } } /* * _ppdCacheDestroy should never fail... */ fputs("_ppdCacheDestroy(pc): ", stdout); _ppdCacheDestroy(pc); puts("PASS"); } fputs("pwgMediaForPWG(\"iso_a4_210x297mm\"): ", stdout); if ((pwgmedia = pwgMediaForPWG("iso_a4_210x297mm")) == NULL) { puts("FAIL (not found)"); status ++; } else if (strcmp(pwgmedia->pwg, "iso_a4_210x297mm")) { printf("FAIL (%s)\n", pwgmedia->pwg); status ++; } else if (pwgmedia->width != 21000 || pwgmedia->length != 29700) { printf("FAIL (%dx%d)\n", pwgmedia->width, pwgmedia->length); status ++; } else puts("PASS"); fputs("pwgMediaForPWG(\"roll_max_36.1025x3622.0472in\"): ", stdout); if ((pwgmedia = pwgMediaForPWG("roll_max_36.1025x3622.0472in")) == NULL) { puts("FAIL (not found)"); status ++; } else if (pwgmedia->width != 91700 || pwgmedia->length != 9199999) { printf("FAIL (%dx%d)\n", pwgmedia->width, pwgmedia->length); status ++; } else printf("PASS (%dx%d)\n", pwgmedia->width, pwgmedia->length); fputs("pwgMediaForLegacy(\"na-letter\"): ", stdout); if ((pwgmedia = pwgMediaForLegacy("na-letter")) == NULL) { puts("FAIL (not found)"); status ++; } else if (strcmp(pwgmedia->pwg, "na_letter_8.5x11in")) { printf("FAIL (%s)\n", pwgmedia->pwg); status ++; } else if (pwgmedia->width != 21590 || pwgmedia->length != 27940) { printf("FAIL (%dx%d)\n", pwgmedia->width, pwgmedia->length); status ++; } else puts("PASS"); fputs("pwgMediaForPPD(\"4x6\"): ", stdout); if ((pwgmedia = pwgMediaForPPD("4x6")) == NULL) { puts("FAIL (not found)"); status ++; } else if (strcmp(pwgmedia->pwg, "na_index-4x6_4x6in")) { printf("FAIL (%s)\n", pwgmedia->pwg); status ++; } else if (pwgmedia->width != 10160 || pwgmedia->length != 15240) { printf("FAIL (%dx%d)\n", pwgmedia->width, pwgmedia->length); status ++; } else puts("PASS"); fputs("pwgMediaForPPD(\"10x15cm\"): ", stdout); if ((pwgmedia = pwgMediaForPPD("10x15cm")) == NULL) { puts("FAIL (not found)"); status ++; } else if (strcmp(pwgmedia->pwg, "om_100x150mm_100x150mm")) { printf("FAIL (%s)\n", pwgmedia->pwg); status ++; } else if (pwgmedia->width != 10000 || pwgmedia->length != 15000) { printf("FAIL (%dx%d)\n", pwgmedia->width, pwgmedia->length); status ++; } else puts("PASS"); fputs("pwgMediaForPPD(\"Custom.10x15cm\"): ", stdout); if ((pwgmedia = pwgMediaForPPD("Custom.10x15cm")) == NULL) { puts("FAIL (not found)"); status ++; } else if (strcmp(pwgmedia->pwg, "custom_10x15cm_100x150mm")) { printf("FAIL (%s)\n", pwgmedia->pwg); status ++; } else if (pwgmedia->width != 10000 || pwgmedia->length != 15000) { printf("FAIL (%dx%d)\n", pwgmedia->width, pwgmedia->length); status ++; } else puts("PASS"); fputs("pwgMediaForSize(29700, 42000): ", stdout); if ((pwgmedia = pwgMediaForSize(29700, 42000)) == NULL) { puts("FAIL (not found)"); status ++; } else if (strcmp(pwgmedia->pwg, "iso_a3_297x420mm")) { printf("FAIL (%s)\n", pwgmedia->pwg); status ++; } else puts("PASS"); fputs("pwgMediaForSize(9842, 19050): ", stdout); if ((pwgmedia = pwgMediaForSize(9842, 19050)) == NULL) { puts("FAIL (not found)"); status ++; } else if (strcmp(pwgmedia->pwg, "na_monarch_3.875x7.5in")) { printf("FAIL (%s)\n", pwgmedia->pwg); status ++; } else printf("PASS (%s)\n", pwgmedia->pwg); fputs("pwgMediaForSize(9800, 19000): ", stdout); if ((pwgmedia = pwgMediaForSize(9800, 19000)) == NULL) { puts("FAIL (not found)"); status ++; } else if (strcmp(pwgmedia->pwg, "jpn_you6_98x190mm")) { printf("FAIL (%s)\n", pwgmedia->pwg); status ++; } else printf("PASS (%s)\n", pwgmedia->pwg); fputs("Duplicate size test: ", stdout); for (mediatable = _pwgMediaTable(&num_media); num_media > 1; num_media --, mediatable ++) { for (i = num_media - 1, pwgmedia = mediatable + 1; i > 0; i --, pwgmedia ++) { if (pwgmedia->width == mediatable->width && pwgmedia->length == mediatable->length) { if (!dupmedia) { dupmedia = 1; status ++; puts("FAIL"); } printf(" %s and %s have the same dimensions (%dx%d)\n", pwgmedia->pwg, mediatable->pwg, pwgmedia->width, pwgmedia->length); } } } if (!dupmedia) puts("PASS"); return (status); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { _ippdata_t data; /* IPP buffer */ ipp_uchar_t buffer[8192]; /* Write buffer data */ ipp_t *cols[2], /* Collections */ *size; /* media-size collection */ ipp_t *request; /* Request */ ipp_attribute_t *media_col, /* media-col attribute */ *media_size, /* media-size attribute */ *attr; /* Other attribute */ ipp_state_t state; /* State */ size_t length; /* Length of data */ cups_file_t *fp; /* File pointer */ size_t i; /* Looping var */ int status; /* Status of tests (0 = success, 1 = fail) */ #ifdef DEBUG const char *name; /* Option name */ #endif /* DEBUG */ status = 0; if (argc == 1) { /* * Test request generation code... */ printf("Create Sample Request: "); request = ippNew(); request->request.op.version[0] = 0x01; request->request.op.version[1] = 0x01; request->request.op.operation_id = IPP_OP_PRINT_JOB; request->request.op.request_id = 1; ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, "attributes-charset", NULL, "utf-8"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, "en"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, "ipp://localhost/printers/foo"); cols[0] = ippNew(); size = ippNew(); ippAddInteger(size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "x-dimension", 21590); ippAddInteger(size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "y-dimension", 27940); ippAddCollection(cols[0], IPP_TAG_JOB, "media-size", size); ippDelete(size); ippAddString(cols[0], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-color", NULL, "blue"); ippAddString(cols[0], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-type", NULL, "plain"); cols[1] = ippNew(); size = ippNew(); ippAddInteger(size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "x-dimension", 21000); ippAddInteger(size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "y-dimension", 29700); ippAddCollection(cols[1], IPP_TAG_JOB, "media-size", size); ippDelete(size); ippAddString(cols[1], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-color", NULL, "plaid"); ippAddString(cols[1], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-type", NULL, "glossy"); ippAddCollections(request, IPP_TAG_JOB, "media-col", 2, (const ipp_t **)cols); ippDelete(cols[0]); ippDelete(cols[1]); length = ippLength(request); if (length != sizeof(collection)) { printf("FAIL - wrong ippLength(), %d instead of %d bytes!\n", (int)length, (int)sizeof(collection)); status = 1; } else puts("PASS"); /* * Write test #1... */ printf("Write Sample to Memory: "); data.wused = 0; data.wsize = sizeof(buffer); data.wbuffer = buffer; while ((state = ippWriteIO(&data, (ipp_iocb_t)write_cb, 1, NULL, request)) != IPP_STATE_DATA) if (state == IPP_STATE_ERROR) break; if (state != IPP_STATE_DATA) { printf("FAIL - %d bytes written.\n", (int)data.wused); status = 1; } else if (data.wused != sizeof(collection)) { printf("FAIL - wrote %d bytes, expected %d bytes!\n", (int)data.wused, (int)sizeof(collection)); hex_dump("Bytes Written", data.wbuffer, data.wused); hex_dump("Baseline", collection, sizeof(collection)); status = 1; } else if (memcmp(data.wbuffer, collection, data.wused)) { for (i = 0; i < data.wused; i ++) if (data.wbuffer[i] != collection[i]) break; printf("FAIL - output does not match baseline at 0x%04x!\n", (unsigned)i); hex_dump("Bytes Written", data.wbuffer, data.wused); hex_dump("Baseline", collection, sizeof(collection)); status = 1; } else puts("PASS"); ippDelete(request); /* * Read the data back in and confirm... */ printf("Read Sample from Memory: "); request = ippNew(); data.rpos = 0; while ((state = ippReadIO(&data, (ipp_iocb_t)read_cb, 1, NULL, request)) != IPP_STATE_DATA) if (state == IPP_STATE_ERROR) break; length = ippLength(request); if (state != IPP_STATE_DATA) { printf("FAIL - %d bytes read.\n", (int)data.rpos); status = 1; } else if (data.rpos != data.wused) { printf("FAIL - read %d bytes, expected %d bytes!\n", (int)data.rpos, (int)data.wused); print_attributes(request, 8); status = 1; } else if (length != sizeof(collection)) { printf("FAIL - wrong ippLength(), %d instead of %d bytes!\n", (int)length, (int)sizeof(collection)); print_attributes(request, 8); status = 1; } else puts("PASS"); fputs("ippFindAttribute(media-col): ", stdout); if ((media_col = ippFindAttribute(request, "media-col", IPP_TAG_BEGIN_COLLECTION)) == NULL) { if ((media_col = ippFindAttribute(request, "media-col", IPP_TAG_ZERO)) == NULL) puts("FAIL (not found)"); else printf("FAIL (wrong type - %s)\n", ippTagString(media_col->value_tag)); status = 1; } else if (media_col->num_values != 2) { printf("FAIL (wrong count - %d)\n", media_col->num_values); status = 1; } else puts("PASS"); if (media_col) { fputs("ippFindAttribute(media-size 1): ", stdout); if ((media_size = ippFindAttribute(media_col->values[0].collection, "media-size", IPP_TAG_BEGIN_COLLECTION)) == NULL) { if ((media_size = ippFindAttribute(media_col->values[0].collection, "media-col", IPP_TAG_ZERO)) == NULL) puts("FAIL (not found)"); else printf("FAIL (wrong type - %s)\n", ippTagString(media_size->value_tag)); status = 1; } else { if ((attr = ippFindAttribute(media_size->values[0].collection, "x-dimension", IPP_TAG_INTEGER)) == NULL) { if ((attr = ippFindAttribute(media_size->values[0].collection, "x-dimension", IPP_TAG_ZERO)) == NULL) puts("FAIL (missing x-dimension)"); else printf("FAIL (wrong type for x-dimension - %s)\n", ippTagString(attr->value_tag)); status = 1; } else if (attr->values[0].integer != 21590) { printf("FAIL (wrong value for x-dimension - %d)\n", attr->values[0].integer); status = 1; } else if ((attr = ippFindAttribute(media_size->values[0].collection, "y-dimension", IPP_TAG_INTEGER)) == NULL) { if ((attr = ippFindAttribute(media_size->values[0].collection, "y-dimension", IPP_TAG_ZERO)) == NULL) puts("FAIL (missing y-dimension)"); else printf("FAIL (wrong type for y-dimension - %s)\n", ippTagString(attr->value_tag)); status = 1; } else if (attr->values[0].integer != 27940) { printf("FAIL (wrong value for y-dimension - %d)\n", attr->values[0].integer); status = 1; } else puts("PASS"); } fputs("ippFindAttribute(media-size 2): ", stdout); if ((media_size = ippFindAttribute(media_col->values[1].collection, "media-size", IPP_TAG_BEGIN_COLLECTION)) == NULL) { if ((media_size = ippFindAttribute(media_col->values[1].collection, "media-col", IPP_TAG_ZERO)) == NULL) puts("FAIL (not found)"); else printf("FAIL (wrong type - %s)\n", ippTagString(media_size->value_tag)); status = 1; } else { if ((attr = ippFindAttribute(media_size->values[0].collection, "x-dimension", IPP_TAG_INTEGER)) == NULL) { if ((attr = ippFindAttribute(media_size->values[0].collection, "x-dimension", IPP_TAG_ZERO)) == NULL) puts("FAIL (missing x-dimension)"); else printf("FAIL (wrong type for x-dimension - %s)\n", ippTagString(attr->value_tag)); status = 1; } else if (attr->values[0].integer != 21000) { printf("FAIL (wrong value for x-dimension - %d)\n", attr->values[0].integer); status = 1; } else if ((attr = ippFindAttribute(media_size->values[0].collection, "y-dimension", IPP_TAG_INTEGER)) == NULL) { if ((attr = ippFindAttribute(media_size->values[0].collection, "y-dimension", IPP_TAG_ZERO)) == NULL) puts("FAIL (missing y-dimension)"); else printf("FAIL (wrong type for y-dimension - %s)\n", ippTagString(attr->value_tag)); status = 1; } else if (attr->values[0].integer != 29700) { printf("FAIL (wrong value for y-dimension - %d)\n", attr->values[0].integer); status = 1; } else puts("PASS"); } } /* * Test hierarchical find... */ fputs("ippFindAttribute(media-col/media-size/x-dimension): ", stdout); if ((attr = ippFindAttribute(request, "media-col/media-size/x-dimension", IPP_TAG_INTEGER)) != NULL) { if (ippGetInteger(attr, 0) != 21590) { printf("FAIL (wrong value for x-dimension - %d)\n", ippGetInteger(attr, 0)); status = 1; } else puts("PASS"); } else { puts("FAIL (not found)"); status = 1; } fputs("ippFindNextAttribute(media-col/media-size/x-dimension): ", stdout); if ((attr = ippFindNextAttribute(request, "media-col/media-size/x-dimension", IPP_TAG_INTEGER)) != NULL) { if (ippGetInteger(attr, 0) != 21000) { printf("FAIL (wrong value for x-dimension - %d)\n", ippGetInteger(attr, 0)); status = 1; } else puts("PASS"); } else { puts("FAIL (not found)"); status = 1; } fputs("ippFindNextAttribute(media-col/media-size/x-dimension) again: ", stdout); if ((attr = ippFindNextAttribute(request, "media-col/media-size/x-dimension", IPP_TAG_INTEGER)) != NULL) { printf("FAIL (got %d, expected nothing)\n", ippGetInteger(attr, 0)); status = 1; } else puts("PASS"); ippDelete(request); /* * Read the mixed data and confirm we converted everything to rangeOfInteger * values... */ printf("Read Mixed integer/rangeOfInteger from Memory: "); request = ippNew(); data.rpos = 0; data.wused = sizeof(mixed); data.wsize = sizeof(mixed); data.wbuffer = mixed; while ((state = ippReadIO(&data, (ipp_iocb_t)read_cb, 1, NULL, request)) != IPP_STATE_DATA) if (state == IPP_STATE_ERROR) break; length = ippLength(request); if (state != IPP_STATE_DATA) { printf("FAIL - %d bytes read.\n", (int)data.rpos); status = 1; } else if (data.rpos != sizeof(mixed)) { printf("FAIL - read %d bytes, expected %d bytes!\n", (int)data.rpos, (int)sizeof(mixed)); print_attributes(request, 8); status = 1; } else if (length != (sizeof(mixed) + 4)) { printf("FAIL - wrong ippLength(), %d instead of %d bytes!\n", (int)length, (int)sizeof(mixed) + 4); print_attributes(request, 8); status = 1; } else puts("PASS"); fputs("ippFindAttribute(notify-lease-duration-supported): ", stdout); if ((attr = ippFindAttribute(request, "notify-lease-duration-supported", IPP_TAG_ZERO)) == NULL) { puts("FAIL (not found)"); status = 1; } else if (attr->value_tag != IPP_TAG_RANGE) { printf("FAIL (wrong type - %s)\n", ippTagString(attr->value_tag)); status = 1; } else if (attr->num_values != 2) { printf("FAIL (wrong count - %d)\n", attr->num_values); status = 1; } else if (attr->values[0].range.lower != 1 || attr->values[0].range.upper != 1 || attr->values[1].range.lower != 16 || attr->values[1].range.upper != 32) { printf("FAIL (wrong values - %d,%d and %d,%d)\n", attr->values[0].range.lower, attr->values[0].range.upper, attr->values[1].range.lower, attr->values[1].range.upper); status = 1; } else puts("PASS"); ippDelete(request); #ifdef DEBUG /* * Test that private option array is sorted... */ fputs("_ippCheckOptions: ", stdout); if ((name = _ippCheckOptions()) == NULL) puts("PASS"); else { printf("FAIL (\"%s\" out of order)\n", name); status = 1; } #endif /* DEBUG */ /* * Test _ippFindOption() private API... */ fputs("_ippFindOption(\"printer-type\"): ", stdout); if (_ippFindOption("printer-type")) puts("PASS"); else { puts("FAIL"); status = 1; } /* * Summarize... */ putchar('\n'); if (status) puts("Core IPP tests failed."); else puts("Core IPP tests passed."); } else { /* * Read IPP files... */ for (i = 1; i < (size_t)argc; i ++) { if ((fp = cupsFileOpen(argv[i], "r")) == NULL) { printf("Unable to open \"%s\" - %s\n", argv[i], strerror(errno)); status = 1; continue; } request = ippNew(); while ((state = ippReadIO(fp, (ipp_iocb_t)cupsFileRead, 1, NULL, request)) == IPP_STATE_ATTRIBUTE); if (state != IPP_STATE_DATA) { printf("Error reading IPP message from \"%s\"!\n", argv[i]); status = 1; } else { printf("\n%s:\n", argv[i]); print_attributes(request, 4); } ippDelete(request); cupsFileClose(fp); } } return (status); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { int i; /* Looping var */ const char *opt, /* Current option character */ *name = NULL, /* Service name */ *type = "_ipp._tcp", /* Service type */ *domain = "local."; /* Service domain */ #ifdef HAVE_DNSSD DNSServiceRef ref; /* Browsing service reference */ #endif /* HAVE_DNSSD */ #ifdef HAVE_AVAHI AvahiClient *client; /* Client information */ int error; /* Error code, if any */ #endif /* HAVE_AVAHI */ for (i = 1; i < argc; i ++) if (!strcmp(argv[i], "snmp")) snmponly = 1; else if (!strcmp(argv[i], "ipp")) ipponly = 1; else { puts("Usage: ./ipp-printers [{ipp | snmp}]"); return (1); } /* * Create an array to track devices... */ devices = cupsArrayNew((cups_array_func_t)compare_devices, NULL); /* * Browse for different kinds of printers... */ if (DNSServiceCreateConnection(&main_ref) != kDNSServiceErr_NoError) { perror("ERROR: Unable to create service connection"); return (1); } fd = DNSServiceRefSockFD(main_ref); ipp_ref = main_ref; DNSServiceBrowse(&ipp_ref, kDNSServiceFlagsShareConnection, 0, "_ipp._tcp", NULL, browse_callback, devices); /* * Loop until we are killed... */ progress(); for (;;) { FD_ZERO(&input); FD_SET(fd, &input); timeout.tv_sec = 2; timeout.tv_usec = 500000; if (select(fd + 1, &input, NULL, NULL, &timeout) <= 0) { time_t curtime = time(NULL); for (device = (cups_device_t *)cupsArrayFirst(devices); device; device = (cups_device_t *)cupsArrayNext(devices)) if (!device->got_resolve) { if (!device->ref) break; if ((curtime - device->resolve_time) > 10) { device->got_resolve = -1; fprintf(stderr, "\rUnable to resolve \"%s\": timeout\n", device->name); progress(); } else break; } if (!device) break; } if (FD_ISSET(fd, &input)) { /* * Process results of our browsing... */ progress(); DNSServiceProcessResult(main_ref); } else { /* * Query any devices we've found... */ DNSServiceErrorType status; /* DNS query status */ int count; /* Number of queries */ for (device = (cups_device_t *)cupsArrayFirst(devices), count = 0; device; device = (cups_device_t *)cupsArrayNext(devices)) { if (!device->ref && !device->sent) { /* * Found the device, now get the TXT record(s) for it... */ if (count < 50) { device->resolve_time = time(NULL); device->ref = main_ref; status = DNSServiceResolve(&(device->ref), kDNSServiceFlagsShareConnection, 0, device->name, device->regtype, device->domain, resolve_callback, device); if (status != kDNSServiceErr_NoError) { fprintf(stderr, "\rUnable to resolve \"%s\": %d\n", device->name, status); progress(); } else count ++; } } else if (!device->sent && device->got_resolve) { /* * Got the TXT records, now report the device... */ DNSServiceRefDeallocate(device->ref); device->ref = 0; device->sent = 1; } } } } #ifndef DEBUG fprintf(stderr, "\rFound %d printers. Now querying for capabilities...\n", cupsArrayCount(devices)); #endif /* !DEBUG */ puts("#!/bin/sh -x"); puts("test -d results && rm -rf results"); puts("mkdir results"); puts("CUPS_DEBUG_LEVEL=6; export CUPS_DEBUG_LEVEL"); puts("CUPS_DEBUG_FILTER='^(ipp|http|_ipp|_http|cupsGetResponse|cupsSend|" "cupsWrite|cupsDo).*'; export CUPS_DEBUG_FILTER"); for (device = (cups_device_t *)cupsArrayFirst(devices); device; device = (cups_device_t *)cupsArrayNext(devices)) { if (device->got_resolve <= 0 || device->cups_shared) continue; #ifdef DEBUG fprintf(stderr, "Checking \"%s\" (got_resolve=%d, cups_shared=%d, uri=%s)\n", device->name, device->got_resolve, device->cups_shared, device->uri); #else fprintf(stderr, "Checking \"%s\"...\n", device->name); #endif /* DEBUG */ if ((http = httpConnect(device->host, device->port)) == NULL) { fprintf(stderr, "Failed to connect to \"%s\": %s\n", device->name, cupsLastErrorString()); continue; } request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, device->uri); response = cupsDoRequest(http, request, device->rp); if (cupsLastError() > IPP_OK_SUBST) fprintf(stderr, "Failed to query \"%s\": %s\n", device->name, cupsLastErrorString()); else { if ((attr = ippFindAttribute(response, "ipp-versions-supported", IPP_TAG_KEYWORD)) != NULL) { version = attr->values[0].string.text; for (i = 1; i < attr->num_values; i ++) if (strcmp(attr->values[i].string.text, version) > 0) version = attr->values[i].string.text; } else version = "1.0"; testfile = NULL; if ((attr = ippFindAttribute(response, "document-format-supported", IPP_TAG_MIMETYPE)) != NULL) { /* * Figure out the test file for printing, preferring PDF and PostScript * over JPEG and plain text... */ for (i = 0; i < attr->num_values; i ++) { if (!strcasecmp(attr->values[i].string.text, "application/pdf")) { testfile = "testfile.pdf"; break; } else if (!strcasecmp(attr->values[i].string.text, "application/postscript")) testfile = "testfile.ps"; else if (!strcasecmp(attr->values[i].string.text, "image/jpeg") && !testfile) testfile = "testfile.jpg"; else if (!strcasecmp(attr->values[i].string.text, "text/plain") && !testfile) testfile = "testfile.txt"; else if (!strcasecmp(attr->values[i].string.text, "application/vnd.hp-PCL") && !testfile) testfile = "testfile.pcl"; } if (!testfile) { fprintf(stderr, "Printer \"%s\" reports the following IPP file formats:\n", device->name); for (i = 0; i < attr->num_values; i ++) fprintf(stderr, " \"%s\"\n", attr->values[i].string.text); } } if (!testfile && device->pdl) { char *pdl, /* Copy of pdl string */ *start, *end; /* Pointers into pdl string */ pdl = strdup(device->pdl); for (start = device->pdl; start && *start; start = end) { if ((end = strchr(start, ',')) != NULL) *end++ = '\0'; if (!strcasecmp(start, "application/pdf")) { testfile = "testfile.pdf"; break; } else if (!strcasecmp(start, "application/postscript")) testfile = "testfile.ps"; else if (!strcasecmp(start, "image/jpeg") && !testfile) testfile = "testfile.jpg"; else if (!strcasecmp(start, "text/plain") && !testfile) testfile = "testfile.txt"; else if (!strcasecmp(start, "application/vnd.hp-PCL") && !testfile) testfile = "testfile.pcl"; } free(pdl); if (testfile) { fprintf(stderr, "Using \"%s\" for printer \"%s\" based on TXT record pdl " "info.\n", testfile, device->name); } else { fprintf(stderr, "Printer \"%s\" reports the following TXT file formats:\n", device->name); fprintf(stderr, " \"%s\"\n", device->pdl); } } if (!device->ty && (attr = ippFindAttribute(response, "printer-make-and-model", IPP_TAG_TEXT)) != NULL) device->ty = strdup(attr->values[0].string.text); if (strcmp(version, "1.0") && testfile && device->ty) { char filename[1024], /* Filename */ *fileptr; /* Pointer into filename */ const char *typtr; /* Pointer into ty */ if (!strncasecmp(device->ty, "DeskJet", 7) || !strncasecmp(device->ty, "DesignJet", 9) || !strncasecmp(device->ty, "OfficeJet", 9) || !strncasecmp(device->ty, "Photosmart", 10)) strlcpy(filename, "HP_", sizeof(filename)); else filename[0] = '\0'; fileptr = filename + strlen(filename); if (!strncasecmp(device->ty, "Lexmark International Lexmark", 29)) typtr = device->ty + 22; else typtr = device->ty; while (*typtr && fileptr < (filename + sizeof(filename) - 1)) { if (isalnum(*typtr & 255) || *typtr == '-') *fileptr++ = *typtr++; else { *fileptr++ = '_'; typtr++; } } *fileptr = '\0'; printf("# %s\n", device->name); printf("echo \"Testing %s...\"\n", device->name); if (!ipponly) { printf("echo \"snmpwalk -c public -v 1 -Cc %s 1.3.6.1.2.1.25 " "1.3.6.1.2.1.43 1.3.6.1.4.1.2699.1\" > results/%s.snmpwalk\n", device->host, filename); printf("snmpwalk -c public -v 1 -Cc %s 1.3.6.1.2.1.25 " "1.3.6.1.2.1.43 1.3.6.1.4.1.2699.1 | " "tee -a results/%s.snmpwalk\n", device->host, filename); } if (!snmponly) { printf("echo \"./ipptool-static -tIf %s -T 30 -d NOPRINT=1 -V %s %s " "ipp-%s.test\" > results/%s.log\n", testfile, version, device->uri, version, filename); printf("CUPS_DEBUG_LOG=results/%s.debug_log " "./ipptool-static -tIf %s -T 30 -d NOPRINT=1 -V %s %s " "ipp-%s.test | tee -a results/%s.log\n", filename, testfile, version, device->uri, version, filename); } puts(""); } else if (!device->ty) fprintf(stderr, "Ignoring \"%s\" since it doesn't provide a make and model.\n", device->name); else if (!testfile) fprintf(stderr, "Ignoring \"%s\" since it does not support a common format.\n", device->name); else fprintf(stderr, "Ignoring \"%s\" since it only supports IPP/1.0.\n", device->name); } 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 */ { const char *printer; /* Printer name */ const char *user; /* Username */ http_t *http; /* Connection to the server */ ipp_t *request, /* IPP request */ *response; /* IPP response */ ipp_attribute_t *attr; /* IPP attribute */ const char *op; /* Operation to perform, if any */ static const char *def_attrs[] = /* Attributes for default printer */ { "printer-name", "printer-uri-supported" }; /* * Get any form variables... */ cgiInitialize(); op = cgiGetVariable("OP"); /* * Set the web interface section... */ cgiSetVariable("SECTION", "printers"); cgiSetVariable("REFRESH_PAGE", ""); /* * See if we are displaying a printer or all printers... */ if ((printer = getenv("PATH_INFO")) != NULL) { printer ++; if (!*printer) printer = NULL; if (printer) cgiSetVariable("PRINTER_NAME", printer); } /* * See who is logged in... */ user = getenv("REMOTE_USER"); /* * Connect to the HTTP server... */ http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); /* * Get the default printer... */ if (!op || !cgiIsPOST()) { /* * Get the default destination... */ request = ippNewRequest(CUPS_GET_DEFAULT); ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", sizeof(def_attrs) / sizeof(def_attrs[0]), NULL, def_attrs); if ((response = cupsDoRequest(http, request, "/")) != NULL) { if ((attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME)) != NULL) cgiSetVariable("DEFAULT_NAME", attr->values[0].string.text); if ((attr = ippFindAttribute(response, "printer-uri-supported", IPP_TAG_URI)) != NULL) { char url[HTTP_MAX_URI]; /* New URL */ cgiSetVariable("DEFAULT_URI", cgiRewriteURL(attr->values[0].string.text, url, sizeof(url), NULL)); } ippDelete(response); } /* * See if we need to show a list of printers or the status of a * single printer... */ if (!printer) show_all_printers(http, user); else show_printer(http, printer); } else if (printer) { if (!*op) { const char *server_port = getenv("SERVER_PORT"); /* Port number string */ int port = atoi(server_port ? server_port : "0"); /* Port number */ char uri[1024]; /* URL */ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), getenv("HTTPS") ? "https" : "http", NULL, getenv("SERVER_NAME"), port, "/printers/%s", printer); printf("Location: %s\n\n", uri); } else if (!strcmp(op, "start-printer")) do_printer_op(http, printer, IPP_RESUME_PRINTER, cgiText(_("Resume Printer"))); else if (!strcmp(op, "stop-printer")) do_printer_op(http, printer, IPP_PAUSE_PRINTER, cgiText(_("Pause Printer"))); else if (!strcmp(op, "accept-jobs")) do_printer_op(http, printer, CUPS_ACCEPT_JOBS, cgiText(_("Accept Jobs"))); else if (!strcmp(op, "reject-jobs")) do_printer_op(http, printer, CUPS_REJECT_JOBS, cgiText(_("Reject Jobs"))); else if (!strcmp(op, "purge-jobs")) do_printer_op(http, printer, IPP_PURGE_JOBS, cgiText(_("Purge Jobs"))); else if (!_cups_strcasecmp(op, "print-self-test-page")) cgiPrintCommand(http, printer, "PrintSelfTestPage", cgiText(_("Print Self-Test Page"))); else if (!_cups_strcasecmp(op, "clean-print-heads")) cgiPrintCommand(http, printer, "Clean all", cgiText(_("Clean Print Heads"))); else if (!_cups_strcasecmp(op, "print-test-page")) cgiPrintTestPage(http, printer); else if (!_cups_strcasecmp(op, "move-jobs")) cgiMoveJobs(http, printer, 0); else { /* * Unknown/bad operation... */ cgiStartHTML(printer); cgiCopyTemplateLang("error-op.tmpl"); cgiEndHTML(); } } else { /* * Unknown/bad operation... */ cgiStartHTML(cgiText(_("Printers"))); cgiCopyTemplateLang("error-op.tmpl"); cgiEndHTML(); } /* * Close the HTTP server connection... */ httpClose(http); /* * Return with no errors... */ return (0); }
static void process_children(void) { int status; /* Exit status of child */ int pid, /* Process ID of child */ job_id; /* Job ID of child */ cupsd_job_t *job; /* Current job */ int i; /* Looping var */ char name[1024]; /* Process name */ const char *type; /* Type of program */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "process_children()"); /* * Reset the dead_children flag... */ dead_children = 0; /* * Collect the exit status of some children... */ #ifdef HAVE_WAITPID while ((pid = waitpid(-1, &status, WNOHANG)) > 0) #elif defined(HAVE_WAIT3) while ((pid = wait3(&status, WNOHANG, NULL)) > 0) #else if ((pid = wait(&status)) > 0) #endif /* HAVE_WAITPID */ { /* * Collect the name of the process that finished... */ cupsdFinishProcess(pid, name, sizeof(name), &job_id); /* * Delete certificates for CGI processes... */ if (pid) cupsdDeleteCert(pid); /* * Handle completed job filters... */ if (job_id > 0) job = cupsdFindJob(job_id); else job = NULL; if (job) { for (i = 0; job->filters[i]; i ++) if (job->filters[i] == pid) break; if (job->filters[i] || job->backend == pid) { /* * OK, this process has gone away; what's left? */ if (job->filters[i]) { job->filters[i] = -pid; type = "Filter"; } else { job->backend = -pid; type = "Backend"; } if (status && status != SIGTERM && status != SIGKILL && status != SIGPIPE) { /* * An error occurred; save the exit status so we know to stop * the printer or cancel the job when all of the filters finish... * * A negative status indicates that the backend failed and the * printer needs to be stopped. * * In order to preserve the most serious status, we always log * when a process dies due to a signal (e.g. SIGABRT, SIGSEGV, * and SIGBUS) and prefer to log the backend exit status over a * filter's. */ int old_status = abs(job->status); if (WIFSIGNALED(status) || /* This process crashed, or */ !job->status || /* No process had a status, or */ (!job->filters[i] && WIFEXITED(old_status))) { /* Backend and filter didn't crash */ if (job->filters[i]) job->status = status; /* Filter failed */ else job->status = -status; /* Backend failed */ } if (job->state_value == IPP_JOB_PROCESSING && job->status_level > CUPSD_LOG_ERROR && (job->filters[i] || !WIFEXITED(status))) { char message[1024]; /* New printer-state-message */ job->status_level = CUPSD_LOG_ERROR; snprintf(message, sizeof(message), "%s failed", type); if (job->printer) { strlcpy(job->printer->state_message, message, sizeof(job->printer->state_message)); } if (!job->attrs) cupsdLoadJob(job); if (!job->printer_message && job->attrs) { if ((job->printer_message = ippFindAttribute(job->attrs, "job-printer-state-message", IPP_TAG_TEXT)) == NULL) job->printer_message = ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_TEXT, "job-printer-state-message", NULL, NULL); } if (job->printer_message) cupsdSetString(&(job->printer_message->values[0].string.text), message); } } /* * If this is not the last file in a job, see if all of the * filters are done, and if so move to the next file. */ if (job->current_file < job->num_files && job->printer) { for (i = 0; job->filters[i] < 0; i ++); if (!job->filters[i] && (!job->printer->pc || !job->printer->pc->single_file || job->backend <= 0)) { /* * Process the next file... */ cupsdContinueJob(job); } } else if (job->state_value >= IPP_JOB_CANCELED) { /* * Remove the job from the active list if there are no processes still * running for it... */ for (i = 0; job->filters[i] < 0; i++); if (!job->filters[i] && job->backend <= 0) cupsArrayRemove(ActiveJobs, job); } } } /* * Show the exit status as needed, ignoring SIGTERM and SIGKILL errors * since they come when we kill/end a process... */ if (status == SIGTERM || status == SIGKILL) { cupsdLogJob(job, CUPSD_LOG_DEBUG, "PID %d (%s) was terminated normally with signal %d.", pid, name, status); } else if (status == SIGPIPE) { cupsdLogJob(job, CUPSD_LOG_DEBUG, "PID %d (%s) did not catch or ignore signal %d.", pid, name, status); } else if (status) { if (WIFEXITED(status)) { int code = WEXITSTATUS(status); /* Exit code */ if (code > 100) cupsdLogJob(job, CUPSD_LOG_DEBUG, "PID %d (%s) stopped with status %d (%s)", pid, name, code, strerror(code - 100)); else cupsdLogJob(job, CUPSD_LOG_DEBUG, "PID %d (%s) stopped with status %d.", pid, name, code); } else cupsdLogJob(job, CUPSD_LOG_DEBUG, "PID %d (%s) crashed on signal %d.", pid, name, WTERMSIG(status)); if (LogLevel < CUPSD_LOG_DEBUG) cupsdLogJob(job, CUPSD_LOG_INFO, "Hint: Try setting the LogLevel to \"debug\" to find out " "more."); } else cupsdLogJob(job, CUPSD_LOG_DEBUG, "PID %d (%s) exited with no errors.", pid, name); } /* * If wait*() is interrupted by a signal, tell main() to call us again... */ if (pid < 0 && errno == EINTR) dead_children = 1; }
static void show_printer(http_t *http, /* I - Connection to server */ const char *printer) /* I - Name of printer */ { ipp_t *request, /* IPP request */ *response; /* IPP response */ ipp_attribute_t *attr; /* IPP attribute */ char uri[HTTP_MAX_URI]; /* Printer URI */ char refresh[1024]; /* Refresh URL */ fprintf(stderr, "DEBUG: show_printer(http=%p, printer=\"%s\")\n", http, printer ? printer : "(null)"); /* * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following * attributes: * * attributes-charset * attributes-natural-language * printer-uri */ request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES); httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 0, "/printers/%s", printer); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); cgiGetAttributes(request, "printer.tmpl"); /* * Do the request and get back a response... */ if ((response = cupsDoRequest(http, request, "/")) != NULL) { /* * Got the result; set the CGI variables and check the status of a * single-queue request... */ cgiSetIPPVars(response, NULL, NULL, NULL, 0); if (printer && (attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL && attr->values[0].integer == IPP_PRINTER_PROCESSING) { /* * Printer is processing - automatically refresh the page until we * are done printing... */ cgiFormEncode(uri, printer, sizeof(uri)); snprintf(refresh, sizeof(refresh), "10;URL=/printers/%s", uri); cgiSetVariable("refresh_page", refresh); } /* * Delete the response... */ ippDelete(response); /* * Show the standard header... */ cgiStartHTML(printer); /* * Show the printer status... */ cgiCopyTemplateLang("printer.tmpl"); /* * Show jobs for the specified printer... */ cgiCopyTemplateLang("printer-jobs-header.tmpl"); cgiShowJobs(http, printer); } else { /* * Show the IPP error... */ cgiStartHTML(printer); cgiShowIPPError(_("Unable to get printer status")); } cgiEndHTML(); }
ipp_status_t /* O - IPP status code */ cupsCloseDestJob( http_t *http, /* I - Connection to destination */ cups_dest_t *dest, /* I - Destination */ cups_dinfo_t *info, /* I - Destination information */ int job_id) /* I - Job ID */ { int i; /* Looping var */ ipp_t *request = NULL;/* Close-Job/Send-Document request */ ipp_attribute_t *attr; /* operations-supported attribute */ DEBUG_printf(("cupsCloseDestJob(http=%p, dest=%p(%s/%s), info=%p, job_id=%d)", http, dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, info, job_id)); /* * Range check input... */ if (!http || !dest || !info || job_id <= 0) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); DEBUG_puts("1cupsCloseDestJob: Bad arguments."); return (IPP_STATUS_ERROR_INTERNAL); } /* * Build a Close-Job or empty Send-Document request... */ if ((attr = ippFindAttribute(info->attrs, "operations-supported", IPP_TAG_ENUM)) != NULL) { for (i = 0; i < attr->num_values; i ++) if (attr->values[i].integer == IPP_OP_CLOSE_JOB) { request = ippNewRequest(IPP_OP_CLOSE_JOB); break; } } if (!request) request = ippNewRequest(IPP_OP_SEND_DOCUMENT); if (!request) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0); DEBUG_puts("1cupsCloseDestJob: Unable to create Close-Job/Send-Document " "request."); return (IPP_STATUS_ERROR_INTERNAL); } ippSetVersion(request, info->version / 10, info->version % 10); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, info->uri); ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); if (ippGetOperation(request) == IPP_OP_SEND_DOCUMENT) ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1); /* * Send the request and return the status... */ ippDelete(cupsDoRequest(http, request, info->resource)); DEBUG_printf(("1cupsCloseDestJob: %s (%s)", ippErrorString(cupsLastError()), cupsLastErrorString())); return (cupsLastError()); }
int /* O - Job ID */ cupsPrintFiles2(http_t *http, /* I - HTTP connection */ const char *name, /* I - Printer or class name */ int num_files,/* I - Number of files */ const char **files, /* I - File(s) to print */ const char *title, /* I - Title of job */ int num_options, /* I - Number of options */ cups_option_t *options) /* I - Options */ { int i; /* Looping var */ const char *val; /* Pointer to option value */ ipp_t *request; /* IPP request */ ipp_t *response; /* IPP response */ ipp_attribute_t *attr; /* IPP job-id attribute */ char uri[HTTP_MAX_URI]; /* Printer URI */ int jobid; /* New job ID */ const char *base; /* Basename of current filename */ DEBUG_printf(("cupsPrintFiles(http=%p, name=\"%s\", num_files=%d, " "files=%p, title=\"%s\", num_options=%d, options=%p)\n", http, name, num_files, files, title, num_options, options)); /* * Range check input... */ if (!http || !name || num_files < 1 || files == NULL) { _cupsSetError(IPP_INTERNAL_ERROR, NULL); return (0); } /* * Setup the printer URI... */ if (httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 0, "/printers/%s", name) != HTTP_URI_OK) { _cupsSetError(IPP_INTERNAL_ERROR, NULL); return (0); } /* * Build a standard CUPS URI for the printer and fill the standard IPP * attributes... */ if ((request = ippNewRequest(num_files == 1 ? IPP_PRINT_JOB : IPP_CREATE_JOB)) == NULL) { _cupsSetError(IPP_INTERNAL_ERROR, NULL); return (0); } 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()); if (title) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, title); /* * Then add all options... */ cupsEncodeOptions(request, num_options, options); /* * Do the request... */ snprintf(uri, sizeof(uri), "/printers/%s", name); if (num_files == 1) response = cupsDoFileRequest(http, request, uri, *files); else response = cupsDoRequest(http, request, uri); if (response == NULL) jobid = 0; else if (response->request.status.status_code > IPP_OK_CONFLICT) { DEBUG_printf(("IPP response code was 0x%x!\n", response->request.status.status_code)); jobid = 0; } else if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) == NULL) { DEBUG_puts("No job ID!"); _cupsSetError(IPP_INTERNAL_ERROR, NULL); jobid = 0; } else jobid = attr->values[0].integer; if (response != NULL) ippDelete(response); /* * Handle multiple file jobs if the create-job operation worked... */ if (jobid > 0 && num_files > 1) for (i = 0; i < num_files; i ++) { /* * Build a standard CUPS URI for the job and fill the standard IPP * attributes... */ if ((request = ippNewRequest(IPP_SEND_DOCUMENT)) == NULL) return (0); snprintf(uri, sizeof(uri), "ipp://localhost/jobs/%d", jobid); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri); /* * Handle raw print files... */ if (cupsGetOption("raw", num_options, options)) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", NULL, "application/vnd.cups-raw"); else if ((val = cupsGetOption("document-format", num_options, options)) != NULL) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", NULL, val); else ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", NULL, "application/octet-stream"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); /* * Add the original document filename... */ if ((base = strrchr(files[i], '/')) != NULL) base ++; else base = files[i]; ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name", NULL, base); /* * Is this the last document? */ if (i == (num_files - 1)) ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1); /* * Send the file... */ snprintf(uri, sizeof(uri), "/printers/%s", name); if ((response = cupsDoFileRequest(http, request, uri, files[i])) != NULL) ippDelete(response); } return (jobid); }