int num_options; /* Number of options */
cups_option_t *options; /* Options */
const char *requested, /* requested-attributes option */
- *make; /* ppd-make option */
- int send_natural_language, /* Send ppd-natural-language? */
+ *device_id, /* ppd-device-id option */
+ *language, /* ppd-natural-language option */
+ *make, /* ppd-make option */
+ *make_and_model, /* ppd-make-and-model option */
+ *product, /* ppd-product option */
+ *psversion; /* ppd-psversion option */
+ int mam_len, /* Length of ppd-make-and-model */
+ device_id_len, /* Length of ppd-device-id */
+ send_natural_language, /* Send ppd-natural-language? */
send_make, /* Send ppd-make? */
send_make_and_model, /* Send ppd-make-and-model? */
send_name, /* Send ppd-name? */
send_device_id, /* Send ppd-device-id? */
send_product, /* Send ppd-product? */
- send_psversion; /* Send ppd-psversion? */
+ send_psversion, /* Send ppd-psversion? */
+ sent_header; /* Sent the IPP header? */
fprintf(stderr,
== sizeof(ppdsync) &&
ppdsync == PPD_SYNC &&
!stat(filename, &fileinfo) &&
- (fileinfo.st_size - sizeof(ppdsync) % sizeof(ppd_rec_t)) == 0 &&
+ ((fileinfo.st_size - sizeof(ppdsync)) % sizeof(ppd_rec_t)) == 0 &&
(NumPPDs = (fileinfo.st_size - sizeof(ppdsync)) /
sizeof(ppd_rec_t)) > 0)
{
* Send IPP attributes...
*/
- num_options = cupsParseOptions(opt, 0, &options);
- requested = cupsGetOption("requested-attributes", num_options, options);
- make = cupsGetOption("ppd-make", 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);
+ product = cupsGetOption("ppd-product", num_options, options);
+ psversion = cupsGetOption("ppd-psversion", num_options, options);
+
+ if (make_and_model)
+ mam_len = strlen(make_and_model);
+ else
+ mam_len = 0;
- fprintf(stderr, "DEBUG: [cups-driverd] requested=\"%s\"\n",
- requested ? requested : "(nil)");
+ if (device_id)
+ device_id_len = strlen(device_id);
+ else
+ device_id_len = 0;
+
+ if (requested)
+ fprintf(stderr, "DEBUG: [cups-driverd] requested-attributes=\"%s\"\n",
+ requested);
+ if (device_id)
+ fprintf(stderr, "DEBUG: [cups-driverd] ppd-device-id=\"%s\"\n",
+ device_id);
+ if (language)
+ fprintf(stderr, "DEBUG: [cups-driverd] ppd-natural-language=\"%s\"\n",
+ language);
+ if (make)
+ fprintf(stderr, "DEBUG: [cups-driverd] ppd-make=\"%s\"\n",
+ make);
+ if (make_and_model)
+ fprintf(stderr, "DEBUG: [cups-driverd] ppd-make-and-model=\"%s\"\n",
+ make_and_model);
+ 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 (!requested || strstr(requested, "all"))
{
puts("Content-Type: application/ipp\n");
- cupsdSendIPPHeader(IPP_OK, request_id);
- cupsdSendIPPGroup(IPP_TAG_OPERATION);
- cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8");
- cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", "en-US");
+ sent_header = 0;
if (limit <= 0 || limit > NumPPDs)
count = NumPPDs;
count = limit;
for (i = NumPPDs, ppd = PPDs; count > 0 && i > 0; i --, ppd ++)
- if (!make || !strcasecmp(ppd->record.make, make))
+ {
+ /*
+ * Filter PPDs based on make, model, or device ID...
+ */
+
+ if (device_id && strncasecmp(ppd->record.device_id, device_id,
+ device_id_len))
+ continue; /* TODO: implement smart compare */
+
+ if (language)
{
- /*
- * Send this PPD...
- */
+ for (j = 0; j < PPD_MAX_LANG; j ++)
+ if (!ppd->record.languages[j][0] ||
+ !strcasecmp(ppd->record.languages[j], language))
+ break;
- fprintf(stderr, "DEBUG: [cups-driverd] Sending %s (%s)...\n",
- ppd->record.name, ppd->record.make_and_model);
+ if (j >= PPD_MAX_LANG || !ppd->record.languages[j][0])
+ continue;
+ }
- count --;
+ if (make && strcasecmp(ppd->record.make, make))
+ continue;
- cupsdSendIPPGroup(IPP_TAG_PRINTER);
+ if (make_and_model && strncasecmp(ppd->record.make_and_model,
+ make_and_model, mam_len))
+ continue;
- if (send_name)
- cupsdSendIPPString(IPP_TAG_NAME, "ppd-name", ppd->record.name);
+ if (product)
+ {
+ for (j = 0; j < PPD_MAX_PROD; j ++)
+ if (!ppd->record.products[j][0] ||
+ !strcasecmp(ppd->record.products[j], product))
+ break;
- if (send_natural_language)
- {
- cupsdSendIPPString(IPP_TAG_LANGUAGE, "ppd-natural-language",
- ppd->record.languages[0]);
+ if (j >= PPD_MAX_PROD || !ppd->record.products[j][0])
+ continue;
+ }
- for (j = 1; j < PPD_MAX_LANG && ppd->record.languages[j][0]; j ++)
- cupsdSendIPPString(IPP_TAG_LANGUAGE, "", ppd->record.languages[j]);
- }
+ if (psversion)
+ {
+ for (j = 0; j < PPD_MAX_VERS; j ++)
+ if (!ppd->record.psversions[j][0] ||
+ !strcasecmp(ppd->record.psversions[j], psversion))
+ break;
- if (send_make)
- cupsdSendIPPString(IPP_TAG_TEXT, "ppd-make", ppd->record.make);
+ if (j >= PPD_MAX_VERS || !ppd->record.psversions[j][0])
+ continue;
+ }
- if (send_make_and_model)
- cupsdSendIPPString(IPP_TAG_TEXT, "ppd-make-and-model",
- ppd->record.make_and_model);
+ /*
+ * Send this PPD...
+ */
- if (send_device_id)
- cupsdSendIPPString(IPP_TAG_TEXT, "ppd-device-id",
- ppd->record.device_id);
+ if (!sent_header)
+ {
+ sent_header = 1;
- if (send_product)
- {
- cupsdSendIPPString(IPP_TAG_TEXT, "ppd-product",
- ppd->record.products[0]);
+ cupsdSendIPPHeader(IPP_OK, request_id);
+ cupsdSendIPPGroup(IPP_TAG_OPERATION);
+ cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8");
+ cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", "en-US");
+ }
- for (j = 1; j < PPD_MAX_PROD && ppd->record.products[j][0]; j ++)
- cupsdSendIPPString(IPP_TAG_TEXT, "", ppd->record.products[j]);
- }
+ fprintf(stderr, "DEBUG: [cups-driverd] Sending %s (%s)...\n",
+ ppd->record.name, ppd->record.make_and_model);
- if (send_psversion)
- {
- cupsdSendIPPString(IPP_TAG_TEXT, "ppd-psversion",
- ppd->record.psversions[0]);
+ count --;
- for (j = 1; j < PPD_MAX_VERS && ppd->record.psversions[j][0]; j ++)
- cupsdSendIPPString(IPP_TAG_TEXT, "", ppd->record.psversions[j]);
- }
+ cupsdSendIPPGroup(IPP_TAG_PRINTER);
- /*
- * If we have only requested the ppd-make attribute, then skip
- * the remaining PPDs with this make...
- */
+ if (send_name)
+ cupsdSendIPPString(IPP_TAG_NAME, "ppd-name", ppd->record.name);
- if (requested && !strcmp(requested, "ppd-make"))
- {
- const char *this_make; /* This ppd-make */
+ if (send_natural_language)
+ {
+ cupsdSendIPPString(IPP_TAG_LANGUAGE, "ppd-natural-language",
+ ppd->record.languages[0]);
+
+ for (j = 1; j < PPD_MAX_LANG && ppd->record.languages[j][0]; j ++)
+ cupsdSendIPPString(IPP_TAG_LANGUAGE, "", ppd->record.languages[j]);
+ }
+ if (send_make)
+ cupsdSendIPPString(IPP_TAG_TEXT, "ppd-make", ppd->record.make);
- for (this_make = ppd->record.make, i --, ppd ++; i > 0; i --, ppd ++)
- if (strcasecmp(this_make, ppd->record.make))
- break;
+ if (send_make_and_model)
+ cupsdSendIPPString(IPP_TAG_TEXT, "ppd-make-and-model",
+ ppd->record.make_and_model);
- i ++;
- ppd --;
- }
+ if (send_device_id)
+ cupsdSendIPPString(IPP_TAG_TEXT, "ppd-device-id",
+ ppd->record.device_id);
+
+ if (send_product)
+ {
+ cupsdSendIPPString(IPP_TAG_TEXT, "ppd-product",
+ ppd->record.products[0]);
+
+ for (j = 1; j < PPD_MAX_PROD && ppd->record.products[j][0]; j ++)
+ cupsdSendIPPString(IPP_TAG_TEXT, "", ppd->record.products[j]);
+ }
+
+ if (send_psversion)
+ {
+ cupsdSendIPPString(IPP_TAG_TEXT, "ppd-psversion",
+ ppd->record.psversions[0]);
+
+ for (j = 1; j < PPD_MAX_VERS && ppd->record.psversions[j][0]; j ++)
+ cupsdSendIPPString(IPP_TAG_TEXT, "", ppd->record.psversions[j]);
}
+ /*
+ * If we have only requested the ppd-make attribute, then skip
+ * the remaining PPDs with this make...
+ */
+
+ if (requested && !strcmp(requested, "ppd-make"))
+ {
+ const char *this_make; /* This ppd-make */
+
+
+ for (this_make = ppd->record.make, i --, ppd ++; i > 0; i --, ppd ++)
+ if (strcasecmp(this_make, ppd->record.make))
+ break;
+
+ i ++;
+ ppd --;
+ }
+ }
+
+ if (!sent_header)
+ {
+ cupsdSendIPPHeader(IPP_NOT_FOUND, request_id);
+ cupsdSendIPPGroup(IPP_TAG_OPERATION);
+ cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8");
+ cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", "en-US");
+ }
+
cupsdSendIPPTrailer();
return (0);
}
else if (!strncasecmp(line, "*PSVersion:", 11))
{
- sscanf(line, "%*[^\"]\"(%255[^)]", psversion);
+ sscanf(line, "%*[^\"]\"%255[^\"]", psversion);
cupsArrayAdd(psversions, strdup(psversion));
}
else if (!strncasecmp(line, "*cupsLanguages:", 15))
{
http_status_t status; /* Policy status */
ipp_attribute_t *limit, /* Limit attribute */
+ *device, /* ppd-device-id attribute */
+ *language, /* ppd-natural-language attribute */
*make, /* ppd-make attribute */
+ *model, /* ppd-make-and-model attribute */
+ *product, /* ppd-product attribute */
+ *psversion, /* ppd-psverion attribute */
*requested; /* requested-attributes attribute */
char command[1024], /* cups-driverd command */
options[1024], /* Options to pass to command */
- requested_str[256],
+ device_str[256],/* Escaped ppd-device-id string */
+ language_str[256],
+ /* Escaped ppd-natural-language string */
+ make_str[256], /* Escaped ppd-make string */
+ model_str[256], /* Escaped ppd-make-and-model string */
+ product_str[256],
+ /* Escaped ppd-product string */
+ psversion_str[256],
+ /* Escaped ppd-psversion string */
+ requested_str[256];
/* String for requested attributes */
- make_str[256]; /* Escaped ppd-make string */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_ppds(%p[%d])", con, con->http.fd);
*/
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);
else
strlcpy(requested_str, "requested-attributes=all", sizeof(requested_str));
+ if (device)
+ url_encode_attr(device, device_str, sizeof(device_str));
+ else
+ device_str[0] = '\0';
+
+ if (language)
+ url_encode_attr(language, language_str, sizeof(language_str));
+ else
+ language_str[0] = '\0';
+
if (make)
url_encode_attr(make, make_str, sizeof(make_str));
else
make_str[0] = '\0';
+ if (model)
+ url_encode_attr(model, model_str, sizeof(model_str));
+ else
+ model_str[0] = '\0';
+
+ if (product)
+ url_encode_attr(product, product_str, sizeof(product_str));
+ else
+ product_str[0] = '\0';
+
+ if (psversion)
+ url_encode_attr(psversion, psversion_str, sizeof(psversion_str));
+ else
+ psversion_str[0] = '\0';
+
snprintf(command, sizeof(command), "%s/daemon/cups-driverd", ServerBin);
- snprintf(options, sizeof(options), "list+%d+%d+%s%s%s",
+ snprintf(options, sizeof(options), "list+%d+%d+%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, make ? "%20" : "", make_str);
+ requested_str,
+ device ? "%20" : "", device_str,
+ language ? "%20" : "", language_str,
+ make ? "%20" : "", make_str,
+ model ? "%20" : "", model_str,
+ product ? "%20" : "", product_str,
+ psversion ? "%20" : "", psversion_str);
if (cupsdSendCommand(con, command, options, 0))
{