/* * "$Id: ipp-support.c 9371 2010-11-17 06:21:32Z mike $" * * Internet Printing Protocol support functions for CUPS. * * Copyright 2007-2012 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright * law. Distribution and use rights are outlined in the file "LICENSE.txt" * which should have been included with this file. If this file is * file is missing or damaged, see the license at "http://www.cups.org/". * * This file is subject to the Apple OS-Developed Software exception. * * Contents: * * ippAttributeString() - Convert the attribute's value to a string. * ippEnumString() - Return a string corresponding to the enum value. * ippEnumValue() - Return the value associated with a given enum * string. * ippErrorString() - Return a name for the given status code. * ippErrorValue() - Return a status code for the given name. * ippOpString() - Return a name for the given operation id. * ippOpValue() - Return an operation id for the given name. * ippPort() - Return the default IPP port number. * ippSetPort() - Set the default port number. * ippTagString() - Return the tag name corresponding to a tag value. * ippTagValue() - Return the tag value corresponding to a tag name. * ipp_col_string() - Convert a collection to a string. */ /* * Include necessary headers... */ #include "cups-private.h" /* * Local globals... */ static const char * const ipp_status_oks[] = /* "OK" status codes */ { /* (name) = abandoned standard value */ "successful-ok", "successful-ok-ignored-or-substituted-attributes", "successful-ok-conflicting-attributes", "successful-ok-ignored-subscriptions", "(successful-ok-ignored-notifications)", "successful-ok-too-many-events", "(successful-ok-but-cancel-subscription)", "successful-ok-events-complete" }, * const ipp_status_400s[] = /* Client errors */ { /* (name) = abandoned standard value */ "client-error-bad-request", "client-error-forbidden", "client-error-not-authenticated", "client-error-not-authorized", "client-error-not-possible", "client-error-timeout", "client-error-not-found", "client-error-gone", "client-error-request-entity-too-large", "client-error-request-value-too-long", "client-error-document-format-not-supported", "client-error-attributes-or-values-not-supported", "client-error-uri-scheme-not-supported", "client-error-charset-not-supported", "client-error-conflicting-attributes", "client-error-compression-not-supported", "client-error-compression-error", "client-error-document-format-error", "client-error-document-access-error", "client-error-attributes-not-settable", "client-error-ignored-all-subscriptions", "client-error-too-many-subscriptions", "(client-error-ignored-all-notifications)", "(client-error-client-print-support-file-not-found)", "client-error-document-password-error", "client-error-document-permission-error", "client-error-document-security-error", "client-error-document-unprintable-error" }, * const ipp_status_500s[] = /* Server errors */ { "server-error-internal-error", "server-error-operation-not-supported", "server-error-service-unavailable", "server-error-version-not-supported", "server-error-device-error", "server-error-temporary-error", "server-error-not-accepting-jobs", "server-error-busy", "server-error-job-canceled", "server-error-multiple-document-jobs-not-supported", "server-error-printer-is-deactivated", "server-error-too-many-jobs", "server-error-too-many-documents" }, * const ipp_status_1000s[] = /* CUPS internal */ { "cups-authorization-canceled", "cups-pki-error", "cups-upgrade-required" }; static const char * const ipp_std_ops[] = { /* 0x0000 - 0x000f */ "0x00", "0x01", "Print-Job", "Print-URI", "Validate-Job", "Create-Job", "Send-Document", "Send-URI", "Cancel-Job", "Get-Job-Attributes", "Get-Jobs", "Get-Printer-Attributes", "Hold-Job", "Release-Job", "Restart-Job", "0x0f", /* 0x0010 - 0x001f */ "Pause-Printer", "Resume-Printer", "Purge-Jobs", "Set-Printer-Attributes", "Set-Job-Attributes", "Get-Printer-Supported-Values", "Create-Printer-Subscription", "Create-Job-Subscription", "Get-Subscription-Attributes", "Get-Subscriptions", "Renew-Subscription", "Cancel-Subscription", "Get-Notifications", "(Send-Notifications)", "(Get-Resource-Attributes)", "(Get-Resource-Data)", /* 0x0020 - 0x002f */ "(Get-Resources)", "(Get-Printer-Support-Files)", "Enable-Printer", "Disable-Printer", "Pause-Printer-After-Current-Job", "Hold-New-Jobs", "Release-Held-New-Jobs", "Deactivate-Printer", "Activate-Printer", "Restart-Printer", "Shutdown-Printer", "Startup-Printer", "Reprocess-Job", "Cancel-Current-Job", "Suspend-Current-Job", "Resume-Job", /* 0x0030 - 0x003d */ "Promote-Job", "Schedule-Job-After", "0x32", "Cancel-Document", "Get-Document-Attributes", "Get-Documents", "Delete-Document", "Set-Document-Attributes", "Cancel-Jobs", "Cancel-My-Jobs", "Resubmit-Job", "Close-Job", "Identify-Printer", "Validate-Document" }, * const ipp_cups_ops[] = { "CUPS-Get-Default", "CUPS-Get-Printers", "CUPS-Add-Modify-Printer", "CUPS-Delete-Printer", "CUPS-Get-Classes", "CUPS-Add-Modify-Class", "CUPS-Delete-Class", "CUPS-Accept-Jobs", "CUPS-Reject-Jobs", "CUPS-Set-Default", "CUPS-Get-Devices", "CUPS-Get-PPDs", "CUPS-Move-Job", "CUPS-Authenticate-Job", "CUPS-Get-PPD" }, * const ipp_cups_ops2[] = { "CUPS-Get-Document" }, * const ipp_tag_names[] = { /* Value/group tag names */ "zero", /* 0x00 */ "operation-attributes-tag", /* 0x01 */ "job-attributes-tag", /* 0x02 */ "end-of-attributes-tag", /* 0x03 */ "printer-attributes-tag", /* 0x04 */ "unsupported-attributes-tag", /* 0x05 */ "subscription-attributes-tag", /* 0x06 */ "event-notification-attributes-tag", /* 0x07 */ "(resource-attributes-tag)", /* 0x08 */ "document-attributes-tag", /* 0x09 */ "0x0a", /* 0x0a */ "0x0b", /* 0x0b */ "0x0c", /* 0x0c */ "0x0d", /* 0x0d */ "0x0e", /* 0x0e */ "0x0f", /* 0x0f */ "unsupported", /* 0x10 */ "default", /* 0x11 */ "unknown", /* 0x12 */ "no-value", /* 0x13 */ "0x14", /* 0x14 */ "not-settable", /* 0x15 */ "delete-attribute", /* 0x16 */ "admin-define", /* 0x17 */ "0x18", /* 0x18 */ "0x19", /* 0x19 */ "0x1a", /* 0x1a */ "0x1b", /* 0x1b */ "0x1c", /* 0x1c */ "0x1d", /* 0x1d */ "0x1e", /* 0x1e */ "0x1f", /* 0x1f */ "0x20", /* 0x20 */ "integer", /* 0x21 */ "boolean", /* 0x22 */ "enum", /* 0x23 */ "0x24", /* 0x24 */ "0x25", /* 0x25 */ "0x26", /* 0x26 */ "0x27", /* 0x27 */ "0x28", /* 0x28 */ "0x29", /* 0x29 */ "0x2a", /* 0x2a */ "0x2b", /* 0x2b */ "0x2c", /* 0x2c */ "0x2d", /* 0x2d */ "0x2e", /* 0x2e */ "0x2f", /* 0x2f */ "octetString", /* 0x30 */ "dateTime", /* 0x31 */ "resolution", /* 0x32 */ "rangeOfInteger", /* 0x33 */ "collection", /* 0x34 */ "textWithLanguage", /* 0x35 */ "nameWithLanguage", /* 0x36 */ "endCollection", /* 0x37 */ "0x38", /* 0x38 */ "0x39", /* 0x39 */ "0x3a", /* 0x3a */ "0x3b", /* 0x3b */ "0x3c", /* 0x3c */ "0x3d", /* 0x3d */ "0x3e", /* 0x3e */ "0x3f", /* 0x3f */ "0x40", /* 0x40 */ "textWithoutLanguage",/* 0x41 */ "nameWithoutLanguage",/* 0x42 */ "0x43", /* 0x43 */ "keyword", /* 0x44 */ "uri", /* 0x45 */ "uriScheme", /* 0x46 */ "charset", /* 0x47 */ "naturalLanguage", /* 0x48 */ "mimeMediaType", /* 0x49 */ "memberAttrName" /* 0x4a */ }; static const char * const ipp_document_states[] = { /* document-state-enums */ "pending", "4", "processing", "6", "canceled", "aborted", "completed" }, * const ipp_finishings[] = { /* finishings enums */ "none", "staple", "punch", "cover", "bind", "saddle-stitch", "edge-stitch", "fold", "trim", "bale", "booklet-maker", "jog-offset", "15", "16", "17", "18", "19", "staple-top-left", "staple-bottom-left", "staple-top-right", "staple-bottom-right", "edge-stitch-left", "edge-stitch-top", "edge-stitch-right", "edge-stitch-bottom", "staple-dual-left", "staple-dual-top", "staple-dual-right", "staple-dual-bottom", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "bind-left", "bind-top", "bind-right", "bind-bottom", "54", "55", "56", "57", "58", "59", "trim-after-pages", "trim-after-documents", "trim-after-copies", "trim-after-job" }, * const ipp_job_collation_types[] = { /* job-collation-type enums */ "uncollated-sheets", "collated-documents", "uncollated-documents" }, * const ipp_job_states[] = { /* job-state enums */ "pending", "pending-held", "processing", "processing-stopped", "canceled", "aborted", "completed" }, * const ipp_orientation_requesteds[] = { /* orientation-requested enums */ "portrait", "landscape", "reverse-landscape", "reverse-portrait" }, * const ipp_print_qualities[] = { /* print-quality enums */ "draft", "normal", "high" }, * const ipp_printer_states[] = { /* printer-state enums */ "idle", "processing", "stopped", }; /* * Local functions... */ static size_t ipp_col_string(ipp_t *col, char *buffer, size_t bufsize); /* * 'ippAttributeString()' - Convert the attribute's value to a string. * * Returns the number of bytes that would be written, not including the * trailing nul. The buffer pointer can be NULL to get the required length, * just like (v)snprintf. * * @since CUPS 1.6/OS X 10.8@ */ size_t /* O - Number of bytes less nul */ ippAttributeString( ipp_attribute_t *attr, /* I - Attribute */ char *buffer, /* I - String buffer or NULL */ size_t bufsize) /* I - Size of string buffer */ { int i; /* Looping var */ char *bufptr, /* Pointer into buffer */ *bufend, /* End of buffer */ temp[256]; /* Temporary string */ const char *ptr; /* Pointer into string */ _ipp_value_t *val; /* Current value */ if (!attr || !attr->name) { if (buffer) *buffer = '\0'; return (0); } bufptr = buffer; if (buffer) bufend = buffer + bufsize - 1; else bufend = NULL; for (i = attr->num_values, val = attr->values; i > 0; i --, val ++) { if (val > attr->values) { if (buffer && bufptr < bufend) *bufptr++ = ','; else bufptr ++; } switch (attr->value_tag & ~IPP_TAG_COPY) { case IPP_TAG_ENUM : ptr = ippEnumString(attr->name, val->integer); if (buffer && bufptr < bufend) strlcpy(bufptr, ptr, bufend - bufptr + 1); bufptr += strlen(ptr); break; case IPP_TAG_INTEGER : if (buffer && bufptr < bufend) bufptr += snprintf(bufptr, bufend - bufptr + 1, "%d", val->integer); else bufptr += snprintf(temp, sizeof(temp), "%d", val->integer); break; case IPP_TAG_BOOLEAN : if (buffer && bufptr < bufend) strlcpy(bufptr, val->boolean ? "true" : "false", bufend - bufptr + 1); bufptr += val->boolean ? 4 : 5; break; case IPP_TAG_RANGE : if (buffer && bufptr < bufend) bufptr += snprintf(bufptr, bufend - bufptr + 1, "%d-%d", val->range.lower, val->range.upper); else bufptr += snprintf(temp, sizeof(temp), "%d-%d", val->range.lower, val->range.upper); break; case IPP_TAG_RESOLUTION : if (buffer && bufptr < bufend) bufptr += snprintf(bufptr, bufend - bufptr + 1, "%dx%d%s", val->resolution.xres, val->resolution.yres, val->resolution.units == IPP_RES_PER_INCH ? "dpi" : "dpcm"); else bufptr += snprintf(temp, sizeof(temp), "%dx%d%s", val->resolution.xres, val->resolution.yres, val->resolution.units == IPP_RES_PER_INCH ? "dpi" : "dpcm"); break; case IPP_TAG_DATE : { unsigned year; /* Year */ year = (val->date[0] << 8) + val->date[1]; if (val->date[9] == 0 && val->date[10] == 0) snprintf(temp, sizeof(temp), "%04u-%02u-%02uT%02u:%02u:%02uZ", year, val->date[2], val->date[3], val->date[4], val->date[5], val->date[6]); else snprintf(temp, sizeof(temp), "%04u-%02u-%02uT%02u:%02u:%02u%c%02u%02u", year, val->date[2], val->date[3], val->date[4], val->date[5], val->date[6], val->date[8], val->date[9], val->date[10]); if (buffer && bufptr < bufend) strlcpy(bufptr, temp, bufend - bufptr + 1); bufptr += strlen(temp); } break; case IPP_TAG_TEXT : case IPP_TAG_NAME : case IPP_TAG_KEYWORD : case IPP_TAG_CHARSET : case IPP_TAG_URI : case IPP_TAG_URISCHEME : case IPP_TAG_MIMETYPE : case IPP_TAG_LANGUAGE : case IPP_TAG_TEXTLANG : case IPP_TAG_NAMELANG : if (!val->string.text) break; for (ptr = val->string.text; *ptr; ptr ++) { if (*ptr == '\\' || *ptr == '\"' || *ptr == '[') { if (buffer && bufptr < bufend) *bufptr = '\\'; bufptr ++; } if (buffer && bufptr < bufend) *bufptr = *ptr; bufptr ++; } if (val->string.language) { /* * Add "[language]" to end of string... */ if (buffer && bufptr < bufend) *bufptr = '['; bufptr ++; if (buffer && bufptr < bufend) strlcpy(bufptr, val->string.language, bufend - bufptr); bufptr += strlen(val->string.language); if (buffer && bufptr < bufend) *bufptr = ']'; bufptr ++; } break; case IPP_TAG_BEGIN_COLLECTION : if (buffer && bufptr < bufend) bufptr += ipp_col_string(val->collection, bufptr, bufend - bufptr + 1); else bufptr += ipp_col_string(val->collection, NULL, 0); break; case IPP_TAG_STRING : for (ptr = val->string.text; *ptr; ptr ++) { if (*ptr == '\\' || _cups_isspace(*ptr)) { if (buffer && bufptr < bufend) *bufptr = '\\'; bufptr ++; if (buffer && bufptr < bufend) *bufptr = *ptr; bufptr ++; } else if (!isprint(*ptr & 255)) { if (buffer && bufptr < bufend) bufptr += snprintf(bufptr, bufend - bufptr + 1, "\\%03o", *ptr & 255); else bufptr += snprintf(temp, sizeof(temp), "\\%03o", *ptr & 255); } else { if (buffer && bufptr < bufend) *bufptr = *ptr; bufptr ++; } } break; default : ptr = ippTagString(attr->value_tag); if (buffer && bufptr < bufend) strlcpy(bufptr, ptr, bufend - bufptr + 1); bufptr += strlen(ptr); break; } } if (buffer && bufptr < bufend) *bufptr = '\0'; else if (bufend) *bufend = '\0'; return (bufptr - buffer); } /* * 'ippEnumString()' - Return a string corresponding to the enum value. */ const char * /* O - Enum string */ ippEnumString(const char *attrname, /* I - Attribute name */ int enumvalue) /* I - Enum value */ { _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ /* * Check for standard enum values... */ if (!strcmp(attrname, "document-state") && enumvalue >= 3 && enumvalue < (3 + (int)(sizeof(ipp_document_states) / sizeof(ipp_document_states[0])))) return (ipp_document_states[enumvalue - 3]); else if ((!strcmp(attrname, "finishings") || !strcmp(attrname, "finishings-actual") || !strcmp(attrname, "finishings-default") || !strcmp(attrname, "finishings-ready") || !strcmp(attrname, "finishings-supported")) && enumvalue >= 3 && enumvalue < (3 + (int)(sizeof(ipp_finishings) / sizeof(ipp_finishings[0])))) return (ipp_finishings[enumvalue - 3]); else if ((!strcmp(attrname, "job-collation-type") || !strcmp(attrname, "job-collation-type-actual")) && enumvalue >= 3 && enumvalue < (3 + (int)(sizeof(ipp_job_collation_types) / sizeof(ipp_job_collation_types[0])))) return (ipp_job_collation_types[enumvalue - 3]); else if (!strcmp(attrname, "job-state") && enumvalue >= IPP_JOB_PENDING && enumvalue <= IPP_JOB_COMPLETED) return (ipp_job_states[enumvalue - IPP_JOB_PENDING]); else if (!strcmp(attrname, "operations-supported")) return (ippOpString((ipp_op_t)enumvalue)); else if ((!strcmp(attrname, "orientation-requested") || !strcmp(attrname, "orientation-requested-actual") || !strcmp(attrname, "orientation-requested-default") || !strcmp(attrname, "orientation-requested-supported")) && enumvalue >= 3 && enumvalue < (3 + (int)(sizeof(ipp_orientation_requesteds) / sizeof(ipp_orientation_requesteds[0])))) return (ipp_orientation_requesteds[enumvalue - 3]); else if ((!strcmp(attrname, "print-quality") || !strcmp(attrname, "print-quality-actual") || !strcmp(attrname, "print-quality-default") || !strcmp(attrname, "print-quality-supported")) && enumvalue >= 3 && enumvalue < (3 + (int)(sizeof(ipp_print_qualities) / sizeof(ipp_print_qualities[0])))) return (ipp_print_qualities[enumvalue - 3]); else if (!strcmp(attrname, "printer-state") && enumvalue >= IPP_PRINTER_IDLE && enumvalue <= IPP_PRINTER_STOPPED) return (ipp_printer_states[enumvalue - IPP_PRINTER_IDLE]); /* * Not a standard enum value, just return the decimal equivalent... */ snprintf(cg->ipp_unknown, sizeof(cg->ipp_unknown), "%d", enumvalue); return (cg->ipp_unknown); } /* * 'ippEnumValue()' - Return the value associated with a given enum string. */ int /* O - Enum value or -1 if unknown */ ippEnumValue(const char *attrname, /* I - Attribute name */ const char *enumstring) /* I - Enum string */ { int i, /* Looping var */ num_strings; /* Number of strings to compare */ const char * const *strings; /* Strings to compare */ /* * If the string is just a number, return it... */ if (isdigit(*enumstring & 255)) return (strtol(enumstring, NULL, 0)); /* * Otherwise look up the string... */ if (!strcmp(attrname, "document-state")) { num_strings = (int)(sizeof(ipp_document_states) / sizeof(ipp_document_states[0])); strings = ipp_document_states; } else if (!strcmp(attrname, "finishings") || !strcmp(attrname, "finishings-actual") || !strcmp(attrname, "finishings-default") || !strcmp(attrname, "finishings-ready") || !strcmp(attrname, "finishings-supported")) { num_strings = (int)(sizeof(ipp_finishings) / sizeof(ipp_finishings[0])); strings = ipp_finishings; } else if (!strcmp(attrname, "job-collation-type") || !strcmp(attrname, "job-collation-type-actual")) { num_strings = (int)(sizeof(ipp_job_collation_types) / sizeof(ipp_job_collation_types[0])); strings = ipp_job_collation_types; } else if (!strcmp(attrname, "job-state")) { num_strings = (int)(sizeof(ipp_job_states) / sizeof(ipp_job_states[0])); strings = ipp_job_states; } else if (!strcmp(attrname, "operations-supported")) return (ippOpValue(enumstring)); else if (!strcmp(attrname, "orientation-requested") || !strcmp(attrname, "orientation-requested-actual") || !strcmp(attrname, "orientation-requested-default") || !strcmp(attrname, "orientation-requested-supported")) { num_strings = (int)(sizeof(ipp_orientation_requesteds) / sizeof(ipp_orientation_requesteds[0])); strings = ipp_orientation_requesteds; } else if (!strcmp(attrname, "print-quality") || !strcmp(attrname, "print-quality-actual") || !strcmp(attrname, "print-quality-default") || !strcmp(attrname, "print-quality-supported")) { num_strings = (int)(sizeof(ipp_print_qualities) / sizeof(ipp_print_qualities[0])); strings = ipp_print_qualities; } else if (!strcmp(attrname, "printer-state")) { num_strings = (int)(sizeof(ipp_printer_states) / sizeof(ipp_printer_states[0])); strings = ipp_printer_states; } else return (-1); for (i = 0; i < num_strings; i ++) if (!strcmp(enumstring, strings[i])) return (i + 3); return (-1); } /* * 'ippErrorString()' - Return a name for the given status code. */ const char * /* O - Text string */ ippErrorString(ipp_status_t error) /* I - Error status */ { _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ /* * See if the error code is a known value... */ if (error >= IPP_OK && error <= IPP_OK_EVENTS_COMPLETE) return (ipp_status_oks[error]); else if (error == IPP_REDIRECTION_OTHER_SITE) return ("redirection-other-site"); else if (error == CUPS_SEE_OTHER) return ("cups-see-other"); else if (error >= IPP_BAD_REQUEST && error <= IPP_PRINT_SUPPORT_FILE_NOT_FOUND) return (ipp_status_400s[error - IPP_BAD_REQUEST]); else if (error >= IPP_INTERNAL_ERROR && error <= IPP_PRINTER_IS_DEACTIVATED) return (ipp_status_500s[error - IPP_INTERNAL_ERROR]); else if (error >= IPP_AUTHENTICATION_CANCELED && error <= IPP_UPGRADE_REQUIRED) return (ipp_status_1000s[error - IPP_AUTHENTICATION_CANCELED]); /* * No, build an "0xxxxx" error string... */ sprintf(cg->ipp_unknown, "0x%04x", error); return (cg->ipp_unknown); } /* * 'ippErrorValue()' - Return a status code for the given name. * * @since CUPS 1.2/OS X 10.5@ */ ipp_status_t /* O - IPP status code */ ippErrorValue(const char *name) /* I - Name */ { int i; for (i = 0; i < (sizeof(ipp_status_oks) / sizeof(ipp_status_oks[0])); i ++) if (!_cups_strcasecmp(name, ipp_status_oks[i])) return ((ipp_status_t)i); if (!_cups_strcasecmp(name, "redirection-other-site")) return (IPP_REDIRECTION_OTHER_SITE); if (!_cups_strcasecmp(name, "cups-see-other")) return (CUPS_SEE_OTHER); for (i = 0; i < (sizeof(ipp_status_400s) / sizeof(ipp_status_400s[0])); i ++) if (!_cups_strcasecmp(name, ipp_status_400s[i])) return ((ipp_status_t)(i + 0x400)); for (i = 0; i < (sizeof(ipp_status_500s) / sizeof(ipp_status_500s[0])); i ++) if (!_cups_strcasecmp(name, ipp_status_500s[i])) return ((ipp_status_t)(i + 0x500)); for (i = 0; i < (sizeof(ipp_status_1000s) / sizeof(ipp_status_1000s[0])); i ++) if (!_cups_strcasecmp(name, ipp_status_1000s[i])) return ((ipp_status_t)(i + 0x1000)); return ((ipp_status_t)-1); } /* * 'ippOpString()' - Return a name for the given operation id. * * @since CUPS 1.2/OS X 10.5@ */ const char * /* O - Name */ ippOpString(ipp_op_t op) /* I - Operation ID */ { _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ /* * See if the operation ID is a known value... */ if (op >= IPP_PRINT_JOB && op <= IPP_CLOSE_JOB) return (ipp_std_ops[op]); else if (op == IPP_PRIVATE) return ("windows-ext"); else if (op >= CUPS_GET_DEFAULT && op <= CUPS_GET_PPD) return (ipp_cups_ops[op - CUPS_GET_DEFAULT]); else if (op == CUPS_GET_DOCUMENT) return (ipp_cups_ops2[0]); /* * No, build an "0xxxxx" operation string... */ sprintf(cg->ipp_unknown, "0x%04x", op); return (cg->ipp_unknown); } /* * 'ippOpValue()' - Return an operation id for the given name. * * @since CUPS 1.2/OS X 10.5@ */ ipp_op_t /* O - Operation ID */ ippOpValue(const char *name) /* I - Textual name */ { int i; if (!strncmp(name, "0x", 2)) return ((ipp_op_t)strtol(name + 2, NULL, 16)); for (i = 0; i < (sizeof(ipp_std_ops) / sizeof(ipp_std_ops[0])); i ++) if (!_cups_strcasecmp(name, ipp_std_ops[i])) return ((ipp_op_t)i); if (!_cups_strcasecmp(name, "windows-ext")) return (IPP_PRIVATE); for (i = 0; i < (sizeof(ipp_cups_ops) / sizeof(ipp_cups_ops[0])); i ++) if (!_cups_strcasecmp(name, ipp_cups_ops[i])) return ((ipp_op_t)(i + 0x4001)); for (i = 0; i < (sizeof(ipp_cups_ops2) / sizeof(ipp_cups_ops2[0])); i ++) if (!_cups_strcasecmp(name, ipp_cups_ops2[i])) return ((ipp_op_t)(i + 0x4027)); if (!_cups_strcasecmp(name, "CUPS-Add-Class")) return (CUPS_ADD_MODIFY_CLASS); if (!_cups_strcasecmp(name, "CUPS-Add-Printer")) return (CUPS_ADD_MODIFY_PRINTER); return ((ipp_op_t)-1); } /* * 'ippPort()' - Return the default IPP port number. */ int /* O - Port number */ ippPort(void) { _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ DEBUG_puts("ippPort()"); if (!cg->ipp_port) _cupsSetDefaults(); DEBUG_printf(("1ippPort: Returning %d...", cg->ipp_port)); return (cg->ipp_port); } /* * 'ippSetPort()' - Set the default port number. */ void ippSetPort(int p) /* I - Port number to use */ { DEBUG_printf(("ippSetPort(p=%d)", p)); _cupsGlobals()->ipp_port = p; } /* * 'ippTagString()' - Return the tag name corresponding to a tag value. * * The returned names are defined in RFC 2911 and 3382. * * @since CUPS 1.4/OS X 10.6@ */ const char * /* O - Tag name */ ippTagString(ipp_tag_t tag) /* I - Tag value */ { tag &= IPP_TAG_MASK; if (tag < (ipp_tag_t)(sizeof(ipp_tag_names) / sizeof(ipp_tag_names[0]))) return (ipp_tag_names[tag]); else return ("UNKNOWN"); } /* * 'ippTagValue()' - Return the tag value corresponding to a tag name. * * The tag names are defined in RFC 2911 and 3382. * * @since CUPS 1.4/OS X 10.6@ */ ipp_tag_t /* O - Tag value */ ippTagValue(const char *name) /* I - Tag name */ { int i; /* Looping var */ for (i = 0; i < (sizeof(ipp_tag_names) / sizeof(ipp_tag_names[0])); i ++) if (!_cups_strcasecmp(name, ipp_tag_names[i])) return ((ipp_tag_t)i); if (!_cups_strcasecmp(name, "operation")) return (IPP_TAG_OPERATION); else if (!_cups_strcasecmp(name, "job")) return (IPP_TAG_JOB); else if (!_cups_strcasecmp(name, "printer")) return (IPP_TAG_PRINTER); else if (!_cups_strcasecmp(name, "unsupported")) return (IPP_TAG_UNSUPPORTED_GROUP); else if (!_cups_strcasecmp(name, "subscription")) return (IPP_TAG_SUBSCRIPTION); else if (!_cups_strcasecmp(name, "event")) return (IPP_TAG_EVENT_NOTIFICATION); else if (!_cups_strcasecmp(name, "language")) return (IPP_TAG_LANGUAGE); else if (!_cups_strcasecmp(name, "mimetype")) return (IPP_TAG_MIMETYPE); else if (!_cups_strcasecmp(name, "name")) return (IPP_TAG_NAME); else if (!_cups_strcasecmp(name, "text")) return (IPP_TAG_TEXT); else if (!_cups_strcasecmp(name, "begCollection")) return (IPP_TAG_BEGIN_COLLECTION); else return (IPP_TAG_ZERO); } /* * 'ipp_col_string()' - Convert a collection to a string. */ static size_t /* O - Number of bytes */ ipp_col_string(ipp_t *col, /* I - Collection attribute */ char *buffer, /* I - Buffer or NULL */ size_t bufsize) /* I - Size of buffer */ { char *bufptr, /* Position in buffer */ *bufend, /* End of buffer */ prefix = '{', /* Prefix character */ temp[256]; /* Temporary string */ ipp_attribute_t *attr; /* Current member attribute */ bufptr = buffer; bufend = buffer + bufsize - 1; for (attr = col->attrs; attr; attr = attr->next) { if (!attr->name) continue; if (buffer && bufptr < bufend) *bufptr = prefix; bufptr ++; prefix = ' '; if (buffer && bufptr < bufend) bufptr += snprintf(bufptr, bufend - bufptr + 1, "%s=", attr->name); else bufptr += strlen(attr->name) + 1; if (buffer && bufptr < bufend) bufptr += ippAttributeString(attr, bufptr, bufend - bufptr + 1); else bufptr += ippAttributeString(attr, temp, sizeof(temp)); } if (prefix == '{') { if (buffer && bufptr < bufend) *bufptr = prefix; bufptr ++; } if (buffer && bufptr < bufend) *bufptr = '}'; bufptr ++; return (bufptr - buffer); } /* * End of "$Id: ipp-support.c 9371 2010-11-17 06:21:32Z mike $". */