Index: doc/help/spec-ipp.html =================================================================== --- doc/help/spec-ipp.html (revision 6533) +++ doc/help/spec-ipp.html (working copy) @@ -1512,20 +1512,39 @@
"limit" (integer (1:MAX)): -
The client OPTIONALLY supplies this attribute limiting the number of - PPDs that are returned. +
The client OPTIONALLY supplies this attribute limiting the number of PPDs that are returned.
"ppd-make" (text(127)): -
The client OPTIONALLY supplies a printer manufacturer to select - which PPDs are returned. +
The client OPTIONALLY supplies a printer manufacturer to select which PPDs are returned. +
"ppd-make-and-model" (text(127)):CUPS 1.3 + +
The client OPTIONALLY supplies a make and model to select which PPDs are returned. + +
"ppd-model-number" (integer):CUPS 1.3 + +
The client OPTIONALLY supplies a model number to select which PPDs are returned. + +
"ppd-natural-language" (naturalLanguage):CUPS 1.3 + +
The client OPTIONALLY supplies a language to select which PPDs are returned. + +
"ppd-product" (text(127)):CUPS 1.3 + +
The client OPTIONALLY supplies a PostScript product string to select which PPDs are returned. + +
"ppd-psversion" (text(127)):CUPS 1.3 + +
The client OPTIONALLY supplies a PostScript version string to select which PPDs are returned. + +
"ppd-type" (type1 keyword):CUPS 1.3 + +
The client OPTIONALLY supplies a driver type to select which PPDs are returned. +
"requested-attributes" (1setOf keyword) : -
The client OPTIONALLY supplies a set of attribute names and/or - attribute group names in whose values the requester is interested. If - the client omits this attribute, the server responds as if this - attribute had been supplied with a value of 'all'. +
The client OPTIONALLY supplies a set of attribute names and/or attribute group names in whose values the requester is interested. If the client omits this attribute, the server responds as if this attribute had been supplied with a value of 'all'. Specify "ppd-make" to get a list of manufacturers. @@ -2135,11 +2154,13 @@ make and model is not specified in the PPD file then the ModelName or ShortNickName attributes are used instead. +

ppd-model-number (integer)CUPS 1.3

+ +

The ppd-model-number attribute provides the cupsModelNumber value from the PPD file. +

ppd-name (name(255))

-

The ppd-name attribute specifies the PPD filename on the server -relative to the model directory. The forward slash (/) is used to -delineate directories. +

The ppd-name attribute specifies either the PPD filename on the server relative to the model directory or a URI that maps to a specific driver interface in the driver directory. The forward slash (/) is used to delineate directories.

ppd-natural-language (1setOf naturalLanguage)

@@ -2155,7 +2176,25 @@

The ppd-product attribute specifies the PSVersion attribute values in the PPD file. +

ppd-type (type1 keyword)CUPS 1.3

+

The ppd-type attribute specifies the type of driver described by the PPD file:

+ + + +

Printer Attributes

auth-info-required (1setOf type2 keyword)CUPS 1.3

Index: scheduler/util.c =================================================================== --- scheduler/util.c (revision 6533) +++ scheduler/util.c (working copy) @@ -194,7 +194,6 @@ } -#if 0 /* Not currently used */ /* * 'cupsdSendIPPInteger()' - Send an integer attribute. */ @@ -210,7 +209,7 @@ /* * Send IPP integer value: value tag (1 byte), name length (2 bytes), - * name string (without nul), and value (4 bytes)... + * name string (without nul), value length (2 bytes), and value (4 bytes)... */ putchar(value_tag); @@ -221,12 +220,14 @@ fputs(name, stdout); + putchar(0); + putchar(4); + putchar(value >> 24); putchar(value >> 16); putchar(value >> 8); putchar(value); } -#endif /* 0 */ /* Index: scheduler/ipp.c =================================================================== --- scheduler/ipp.c (revision 6533) +++ scheduler/ipp.c (working copy) @@ -6001,7 +6001,7 @@ if (dtype & CUPS_PRINTER_REMOTE) { - send_ipp_status(con, CUPS_SEE_OTHER, NULL); + con->response->request.status.status_code = CUPS_SEE_OTHER; ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, dest->uri); return; @@ -6018,7 +6018,7 @@ dest = dest->printers[i]; else { - send_ipp_status(con, CUPS_SEE_OTHER, NULL); + con->response->request.status.status_code = CUPS_SEE_OTHER; ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, dest->printers[0]->uri); return; @@ -6044,7 +6044,7 @@ con->pipe_pid = 0; - send_ipp_status(con, IPP_OK, NULL); + con->response->request.status.status_code = IPP_OK; } else send_ipp_status(con, IPP_NOT_FOUND, @@ -6066,8 +6066,10 @@ *language, /* ppd-natural-language attribute */ *make, /* ppd-make attribute */ *model, /* ppd-make-and-model attribute */ + *model_number, /* ppd-model-number attribute */ *product, /* ppd-product attribute */ *psversion, /* ppd-psverion attribute */ + *type, /* ppd-type attribute */ *requested; /* requested-attributes attribute */ char command[1024], /* cups-driverd command */ options[1024], /* Options to pass to command */ @@ -6076,10 +6078,13 @@ /* Escaped ppd-natural-language string */ make_str[256], /* Escaped ppd-make string */ model_str[256], /* Escaped ppd-make-and-model string */ + model_number_str[256], + /* ppd-model-number string */ product_str[256], /* Escaped ppd-product string */ psversion_str[256], /* Escaped ppd-psversion string */ + type_str[256], /* Escaped ppd-type string */ requested_str[256]; /* String for requested attributes */ @@ -6100,17 +6105,20 @@ * Run cups-driverd command with the given options... */ - limit = ippFindAttribute(con->request, "limit", IPP_TAG_INTEGER); - device = ippFindAttribute(con->request, "ppd-device-id", IPP_TAG_TEXT); - language = ippFindAttribute(con->request, "ppd-natural-language", - IPP_TAG_LANGUAGE); - make = ippFindAttribute(con->request, "ppd-make", IPP_TAG_TEXT); - model = ippFindAttribute(con->request, "ppd-make-and-model", - IPP_TAG_TEXT); - product = ippFindAttribute(con->request, "ppd-product", IPP_TAG_TEXT); - psversion = ippFindAttribute(con->request, "ppd-psversion", IPP_TAG_TEXT); - requested = ippFindAttribute(con->request, "requested-attributes", - IPP_TAG_KEYWORD); + limit = ippFindAttribute(con->request, "limit", IPP_TAG_INTEGER); + device = ippFindAttribute(con->request, "ppd-device-id", IPP_TAG_TEXT); + language = ippFindAttribute(con->request, "ppd-natural-language", + IPP_TAG_LANGUAGE); + make = ippFindAttribute(con->request, "ppd-make", IPP_TAG_TEXT); + model = ippFindAttribute(con->request, "ppd-make-and-model", + IPP_TAG_TEXT); + model_number = ippFindAttribute(con->request, "ppd-model-number", + IPP_TAG_INTEGER); + product = ippFindAttribute(con->request, "ppd-product", IPP_TAG_TEXT); + psversion = ippFindAttribute(con->request, "ppd-psversion", IPP_TAG_TEXT); + type = ippFindAttribute(con->request, "ppd-type", IPP_TAG_KEYWORD); + requested = ippFindAttribute(con->request, "requested-attributes", + IPP_TAG_KEYWORD); if (requested) url_encode_attr(requested, requested_str, sizeof(requested_str)); @@ -6137,6 +6145,12 @@ else model_str[0] = '\0'; + if (model_number) + snprintf(model_number_str, sizeof(model_number_str), "ppd-model-number=%d", + model_number->values[0].integer); + else + model_number_str[0] = '\0'; + if (product) url_encode_attr(product, product_str, sizeof(product_str)); else @@ -6147,8 +6161,14 @@ else psversion_str[0] = '\0'; + if (type) + url_encode_attr(type, type_str, sizeof(type_str)); + else + type_str[0] = '\0'; + snprintf(command, sizeof(command), "%s/daemon/cups-driverd", ServerBin); - snprintf(options, sizeof(options), "list+%d+%d+%s%s%s%s%s%s%s%s%s%s%s%s%s", + snprintf(options, sizeof(options), + "list+%d+%d+%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", con->request->request.op.request_id, limit ? limit->values[0].integer : 0, requested_str, @@ -6156,8 +6176,10 @@ language ? "%20" : "", language_str, make ? "%20" : "", make_str, model ? "%20" : "", model_str, + model_number ? "%20" : "", model_number_str, product ? "%20" : "", product_str, - psversion ? "%20" : "", psversion_str); + psversion ? "%20" : "", psversion_str, + type ? "%20" : "", type_str); if (cupsdSendCommand(con, command, options, 0)) { @@ -8594,21 +8616,14 @@ char formatted[1024]; /* Formatted errror message */ - if (message) - { - va_start(ap, message); - vsnprintf(formatted, sizeof(formatted), - _cupsLangString(con->language, message), ap); - va_end(ap); + va_start(ap, message); + vsnprintf(formatted, sizeof(formatted), + _cupsLangString(con->language, message), ap); + va_end(ap); - cupsdLogMessage(CUPSD_LOG_DEBUG, "%s %s: %s", - ippOpString(con->request->request.op.operation_id), - ippErrorString(status), formatted); - } - else - cupsdLogMessage(CUPSD_LOG_DEBUG, "%s %s", - ippOpString(con->request->request.op.operation_id), - ippErrorString(status)); + cupsdLogMessage(CUPSD_LOG_DEBUG, "%s %s: %s", + ippOpString(con->request->request.op.operation_id), + ippErrorString(status), formatted); con->response->request.status.status_code = status; @@ -8622,9 +8637,8 @@ ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, DefaultLanguage); - if (message) - ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_TEXT, - "status-message", NULL, formatted); + ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_TEXT, + "status-message", NULL, formatted); } Index: scheduler/cups-driverd.c =================================================================== --- scheduler/cups-driverd.c (revision 6533) +++ scheduler/cups-driverd.c (working copy) @@ -58,12 +58,27 @@ * Constants... */ -#define PPD_SYNC 0x50504433 /* Sync word for ppds.dat (PPD3) */ +#define PPD_SYNC 0x50504434 /* Sync word for ppds.dat (PPD4) */ #define PPD_MAX_LANG 32 /* Maximum languages */ #define PPD_MAX_PROD 8 /* Maximum products */ #define PPD_MAX_VERS 8 /* Maximum versions */ +#define PPD_TYPE_POSTSCRIPT 0 /* PostScript PPD */ +#define PPD_TYPE_PDF 1 /* PDF PPD */ +#define PPD_TYPE_RASTER 2 /* CUPS raster PPD */ +#define PPD_TYPE_FAX 3 /* Facsimile/MFD PPD */ +#define PPD_TYPE_UNKNOWN 4 /* Other/hybrid PPD */ +static const char *ppd_types[] = +{ + "postscript", + "pdf", + "raster", + "fax", + "unknown" +}; + + /* * PPD information structures... */ @@ -72,6 +87,8 @@ { time_t mtime; /* Modification time */ size_t size; /* Size in bytes */ + int model_number; /* cupsModelNumber */ + int type; /* ppd-type */ char name[512], /* PPD name */ languages[PPD_MAX_LANG][6], /* LanguageVersion/cupsLanguages */ @@ -110,7 +127,7 @@ const char *make, const char *make_and_model, const char *device_id, const char *product, const char *psversion, time_t mtime, - size_t size); + size_t size, int model_number, int type); static int cat_ppd(const char *name, int request_id); static int compare_names(const ppd_info_t *p0, const ppd_info_t *p1); @@ -167,7 +184,9 @@ const char *product, /* I - Product */ const char *psversion, /* I - PSVersion */ time_t mtime, /* I - Modification time */ - size_t size) /* I - File size */ + size_t size, /* I - File size */ + int model_number, /* I - Model number */ + int type) /* I - Driver type */ { ppd_info_t *ppd; /* PPD */ char *recommended; /* Foomatic driver string */ @@ -210,9 +229,11 @@ memset(ppd, 0, sizeof(ppd_info_t)); - ppd->found = 1; - ppd->record.mtime = mtime; - ppd->record.size = size; + ppd->found = 1; + ppd->record.mtime = mtime; + ppd->record.size = size; + ppd->record.model_number = model_number; + ppd->record.type = type; strlcpy(ppd->record.name, name, sizeof(ppd->record.name)); strlcpy(ppd->record.languages[0], language, @@ -561,17 +582,23 @@ *language, /* ppd-natural-language option */ *make, /* ppd-make option */ *make_and_model, /* ppd-make-and-model option */ + *model_number_str, /* ppd-model-number option */ *product, /* ppd-product option */ - *psversion; /* ppd-psversion option */ - int mam_len, /* Length of ppd-make-and-model */ + *psversion, /* ppd-psversion option */ + *type_str; /* ppd-type option */ + int model_number, /* ppd-model-number value */ + type, /* ppd-type value */ + mam_len, /* Length of ppd-make-and-model */ device_id_len, /* Length of ppd-device-id */ - send_natural_language, /* Send ppd-natural-language? */ + send_device_id, /* Send ppd-device-id? */ send_make, /* Send ppd-make? */ send_make_and_model, /* Send ppd-make-and-model? */ + send_model_number, /* Send ppd-model-number? */ send_name, /* Send ppd-name? */ - send_device_id, /* Send ppd-device-id? */ + send_natural_language, /* Send ppd-natural-language? */ send_product, /* Send ppd-product? */ send_psversion, /* Send ppd-psversion? */ + send_type, /* Send ppd-type? */ sent_header; /* Sent the IPP header? */ @@ -734,7 +761,8 @@ * Add the raw driver... */ - add_ppd("raw", "en", "Raw", "Raw Queue", "", "", "", 0, 0); + add_ppd("raw", "en", "Raw", "Raw Queue", "", "", "", 0, 0, 0, + PPD_TYPE_UNKNOWN); /* * Sort the PPDs by make and model... @@ -748,14 +776,16 @@ * Send IPP attributes... */ - num_options = cupsParseOptions(opt, 0, &options); - requested = cupsGetOption("requested-attributes", num_options, options); - device_id = cupsGetOption("ppd-device-id", num_options, options); - language = cupsGetOption("ppd-natural-language", num_options, options); - make = cupsGetOption("ppd-make", num_options, options); - make_and_model = cupsGetOption("ppd-make-and-model", num_options, options); - product = cupsGetOption("ppd-product", num_options, options); - psversion = cupsGetOption("ppd-psversion", num_options, options); + num_options = cupsParseOptions(opt, 0, &options); + requested = cupsGetOption("requested-attributes", num_options, options); + device_id = cupsGetOption("ppd-device-id", num_options, options); + language = cupsGetOption("ppd-natural-language", num_options, options); + make = cupsGetOption("ppd-make", num_options, options); + make_and_model = cupsGetOption("ppd-make-and-model", num_options, options); + model_number_str = cupsGetOption("ppd-model-number", num_options, options); + product = cupsGetOption("ppd-product", num_options, options); + psversion = cupsGetOption("ppd-psversion", num_options, options); + type_str = cupsGetOption("ppd-type", num_options, options); if (make_and_model) mam_len = strlen(make_and_model); @@ -767,6 +797,27 @@ else device_id_len = 0; + if (model_number_str) + model_number = atoi(model_number_str); + else + model_number = 0; + + if (type_str) + { + for (type = 0; + type < (int)(sizeof(ppd_types) / sizeof(ppd_types[0])); + type ++) + if (!strcmp(type_str, ppd_types[type])) + break; + + if (type >= (int)(sizeof(ppd_types) / sizeof(ppd_types[0]))) + { + fprintf(stderr, "ERROR: [cups-driverd] Bad ppd-type=\"%s\" ignored!\n", + type_str); + type_str = NULL; + } + } + if (requested) fprintf(stderr, "DEBUG: [cups-driverd] requested-attributes=\"%s\"\n", requested); @@ -782,22 +833,29 @@ if (make_and_model) fprintf(stderr, "DEBUG: [cups-driverd] ppd-make-and-model=\"%s\"\n", make_and_model); + if (model_number_str) + fprintf(stderr, "DEBUG: [cups-driverd] ppd-model-number=\"%s\"\n", + model_number_str); if (product) fprintf(stderr, "DEBUG: [cups-driverd] ppd-product=\"%s\"\n", product); if (psversion) fprintf(stderr, "DEBUG: [cups-driverd] ppd-psversion=\"%s\"\n", psversion); + if (type_str) + fprintf(stderr, "DEBUG: [cups-driverd] ppd-type=\"%s\"\n", type_str); if (!requested || strstr(requested, "all")) { send_name = 1; send_make = 1; send_make_and_model = 1; + send_model_number = 1; send_natural_language = 1; send_device_id = 1; send_product = 1; send_psversion = 1; + send_type = 1; } else { @@ -806,10 +864,12 @@ strstr(requested, ",ppd-make") != NULL || !strcmp(requested, "ppd-make"); send_make_and_model = strstr(requested, "ppd-make-and-model") != NULL; + send_model_number = strstr(requested, "ppd-model-number") != NULL; send_natural_language = strstr(requested, "ppd-natural-language") != NULL; send_device_id = strstr(requested, "ppd-device-id") != NULL; send_product = strstr(requested, "ppd-product") != NULL; send_psversion = strstr(requested, "ppd-psversion") != NULL; + send_type = strstr(requested, "ppd-type") != NULL; } puts("Content-Type: application/ipp\n"); @@ -849,6 +909,9 @@ make_and_model, mam_len)) continue; + if (model_number_str && ppd->record.model_number != model_number) + continue; + if (product) { for (j = 0; j < PPD_MAX_PROD; j ++) @@ -871,6 +934,9 @@ continue; } + if (type_str && ppd->record.type != type) + continue; + /* * Send this PPD... */ @@ -933,6 +999,14 @@ cupsdSendIPPString(IPP_TAG_TEXT, "", ppd->record.psversions[j]); } + if (send_type) + cupsdSendIPPString(IPP_TAG_KEYWORD, "ppd-type", + ppd_types[ppd->record.type]); + + if (send_model_number) + cupsdSendIPPInteger(IPP_TAG_INTEGER, "ppd-model-number", + ppd->record.model_number); + /* * If we have only requested the ppd-make attribute, then skip * the remaining PPDs with this make... @@ -993,6 +1067,8 @@ device_id[256], /* 1284DeviceID */ product[256], /* Product */ psversion[256]; /* PSVersion */ + int model_number, /* cupsModelNumber */ + type; /* ppd-type */ cups_array_t *products, /* Product array */ *psversions, /* PSVersion array */ *cups_languages; /* cupsLanguages array */ @@ -1131,6 +1207,8 @@ device_id[0] = '\0'; lang_encoding[0] = '\0'; strcpy(lang_version, "en"); + model_number = 0; + type = PPD_TYPE_POSTSCRIPT; while (cupsFileGets(fp, line, sizeof(line)) != NULL) { @@ -1146,17 +1224,17 @@ sscanf(line, "%*[^\"]\"%255[^\"]", nick_name); else if (!strncasecmp(line, "*1284DeviceID:", 14)) sscanf(line, "%*[^\"]\"%255[^\"]", device_id); - else if (!strncasecmp(line, "*Product:", 9)) + else if (!strncmp(line, "*Product:", 9)) { sscanf(line, "%*[^\"]\"(%255[^)]", product); cupsArrayAdd(products, strdup(product)); } - else if (!strncasecmp(line, "*PSVersion:", 11)) + else if (!strncmp(line, "*PSVersion:", 11)) { sscanf(line, "%*[^\"]\"%255[^\"]", psversion); cupsArrayAdd(psversions, strdup(psversion)); } - else if (!strncasecmp(line, "*cupsLanguages:", 15)) + else if (!strncmp(line, "*cupsLanguages:", 15)) { char *start; /* Start of language */ @@ -1184,6 +1262,20 @@ } } } + else if (!strncmp(line, "*cupsFax:", 9) && strstr(line + 9, "true")) + type = PPD_TYPE_FAX; + else if (!strncmp(line, "*cupsFilter:", 12) && + (type == PPD_TYPE_POSTSCRIPT || type == PPD_TYPE_UNKNOWN)) + { + if (strstr(line + 12, "application/vnd.cups-raster")) + type = PPD_TYPE_RASTER; + else if (strstr(line + 12, "application/vnd.cups-pdf")) + type = PPD_TYPE_PDF; + else + type = PPD_TYPE_UNKNOWN; + } + else if (!strncmp(line, "*cupsModelNumber:", 17)) + sscanf(line, "*cupsModelNumber:%d", &model_number); else if (!strncmp(line, "*OpenUI", 7)) { /* @@ -1240,6 +1332,9 @@ continue; } + if (model_name[0]) + cupsArrayAdd(products, strdup(model_name)); + /* * See if we got a manufacturer... */ @@ -1366,7 +1461,8 @@ ppd = add_ppd(name, lang_version, manufacturer, make_model, device_id, (char *)cupsArrayFirst(products), (char *)cupsArrayFirst(psversions), - dent->fileinfo.st_mtime, dent->fileinfo.st_size); + dent->fileinfo.st_mtime, dent->fileinfo.st_size, + model_number, type); if (!ppd) { @@ -1384,9 +1480,11 @@ memset(ppd, 0, sizeof(ppd_info_t)); - ppd->found = 1; - ppd->record.mtime = dent->fileinfo.st_mtime; - ppd->record.size = dent->fileinfo.st_size; + ppd->found = 1; + ppd->record.mtime = dent->fileinfo.st_mtime; + ppd->record.size = dent->fileinfo.st_size; + ppd->record.model_number = model_number; + ppd->record.type = type; strlcpy(ppd->record.name, name, sizeof(ppd->record.name)); strlcpy(ppd->record.make, manufacturer, sizeof(ppd->record.make)); @@ -1463,7 +1561,9 @@ device_id[128], /* ppd-device-id */ languages[128], /* ppd-natural-language */ product[128], /* ppd-product */ - psversion[128]; /* ppd-psversion */ + psversion[128], /* ppd-psversion */ + type_str[128]; /* ppd-type */ + int type; /* PPD type */ ppd_info_t *ppd; /* Newly added PPD */ @@ -1516,12 +1616,14 @@ device_id[0] = '\0'; product[0] = '\0'; psversion[0] = '\0'; + strcpy(type_str, "postscript"); if (sscanf(line, "\"%511[^\"]\"%127s%*[ \t]\"%127[^\"]\"" "%*[ \t]\"%127[^\"]\"%*[ \t]\"%127[^\"]\"" - "%*[ \t]\"%127[^\"]\"%*[ \t]\"%127[^\"]\"", + "%*[ \t]\"%127[^\"]\"%*[ \t]\"%127[^\"]\"" + "%*[ \t]\"%127[^\"]\"", name, languages, make, make_and_model, - device_id, product, psversion) < 4) + device_id, product, psversion, type_str) < 4) { /* * Bad format; strip trailing newline and write an error message. @@ -1543,8 +1645,21 @@ if ((start = strchr(languages, ',')) != NULL) *start++ = '\0'; + for (type = 0; + type < (int)(sizeof(ppd_types) / sizeof(ppd_types[0])); + type ++) + if (!strcmp(type_str, ppd_types[type])) + break; + + if (type >= (int)(sizeof(ppd_types) / sizeof(ppd_types[0]))) + { + fprintf(stderr, "ERROR: [cups-driverd] Bad ppd-type \"%s\" ignored!\n", + type_str); + type = PPD_TYPE_UNKNOWN; + } + ppd = add_ppd(name, languages, make, make_and_model, device_id, - product, psversion, 0, 0); + product, psversion, 0, 0, 0, type); if (!ppd) {