* do_set_sharing() - Set printer-is-shared value.
* get_option_value() - Return the value of an option.
* get_points() - Get a value in points.
- * match_string() - Return the number of matching characters.
*/
/*
static char *get_option_value(ppd_file_t *ppd, const char *name,
char *buffer, size_t bufsize);
static double get_points(double number, const char *uval);
-static int match_string(const char *a, const char *b);
/*
if ((var = cgiGetVariable("CURRENT_MAKE")) == NULL)
var = cgiGetVariable("PPD_MAKE");
if (var)
+ {
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT,
"ppd-make", NULL, var);
+
+ if ((var = cgiGetVariable("CURRENT_MAKE_AND_MODEL")) != NULL)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT,
+ "ppd-make-and-model", NULL, var);
+ }
else
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
"requested-attributes", NULL, "ppd-make");
* Let the user choose a model...
*/
- const char *make_model; /* Current make/model string */
-
-
- if ((make_model = cgiGetVariable("CURRENT_MAKE_AND_MODEL")) != NULL)
- {
- /*
- * Scan for "close" matches...
- */
-
- int match, /* Current match */
- best_match, /* Best match so far */
- count; /* Number of drivers */
- const char *best, /* Best matching string */
- *current; /* Current string */
-
-
- count = cgiGetSize("PPD_MAKE_AND_MODEL");
-
- for (i = 0, best_match = 0, best = NULL; i < count; i ++)
- {
- current = cgiGetArray("PPD_MAKE_AND_MODEL", i);
- match = match_string(make_model, current);
-
- if (match > best_match)
- {
- best_match = match;
- best = current;
- }
- }
-
- if (best_match > strlen(var))
- {
- /*
- * Found a match longer than the make...
- */
-
- cgiSetVariable("CURRENT_MAKE_AND_MODEL", best);
- }
- }
-
cgiStartHTML(title);
+ cgiSetVariable("CURRENT_MAKE_AND_MODEL",
+ cgiGetArray("PPD_MAKE_AND_MODEL", 0));
cgiCopyTemplateLang("choose-model.tmpl");
cgiEndHTML();
}
}
-/*
- * 'match_string()' - Return the number of matching characters.
- */
-
-static int /* O - Number of matching characters */
-match_string(const char *a, /* I - First string */
- const char *b) /* I - Second string */
-{
- int count; /* Number of matching characters */
-
-
- /*
- * Loop through both strings until we hit the end of either or we find
- * a non-matching character. For the purposes of comparison, we ignore
- * whitespace and do a case-insensitive comparison so that we have a
- * better chance of finding a match...
- */
-
- for (count = 0; *a && *b; a++, b++, count ++)
- {
- /*
- * Skip leading whitespace characters...
- */
-
- while (isspace(*a & 255))
- a ++;
-
- while (isspace(*b & 255))
- b ++;
-
- /*
- * Break out if we run out of characters...
- */
-
- if (!*a || !*b)
- break;
-
- /*
- * Do a case-insensitive comparison of the next two chars...
- */
-
- if (tolower(*a & 255) != tolower(*b & 255))
- break;
- }
-
- return (count);
-}
-
-
/*
* End of "$Id$".
*/
*
* Contents:
*
- * main() - Scan for drivers and return an IPP response.
- * add_ppd() - Add a PPD file.
- * cat_drv() - Generate a PPD from a driver info file.
- * cat_ppd() - Copy a PPD file to stdout.
- * copy_static() - Copy a static PPD file to stdout.
- * compare_names() - Compare PPD filenames for sorting.
- * compare_ppds() - Compare PPD file make and model names for sorting.
- * free_array() - Free an array of strings.
- * list_ppds() - List PPD files.
- * load_ppds() - Load PPD files recursively.
- * load_drv() - Load the PPDs from a driver information file.
- * load_drivers() - Load driver-generated PPD files.
+ * main() - Scan for drivers and return an IPP response.
+ * add_ppd() - Add a PPD file.
+ * cat_drv() - Generate a PPD from a driver info file.
+ * cat_ppd() - Copy a PPD file to stdout.
+ * copy_static() - Copy a static PPD file to stdout.
+ * compare_matches() - Compare PPD match scores for sorting.
+ * compare_names() - Compare PPD filenames for sorting.
+ * compare_ppds() - Compare PPD file make and model names for sorting.
+ * free_array() - Free an array of strings.
+ * list_ppds() - List PPD files.
+ * load_ppds() - Load PPD files recursively.
+ * load_drv() - Load the PPDs from a driver information file.
+ * load_drivers() - Load driver-generated PPD files.
+ * regex_device_id() - Compile a regular expression based on the 1284 device
+ * ID.
+ * regex_string() - Construct a regular expression to compare a simple
+ * string.
*/
/*
#include <cups/transcode.h>
#include <cups/ppd-private.h>
#include <ppdc/ppdc.h>
+#include <regex.h>
/*
typedef struct /**** In-memory record ****/
{
int found; /* 1 if PPD is found */
+ int matches; /* Match count */
ppd_rec_t record; /* PPDs.dat record */
} ppd_info_t;
static int cat_drv(const char *name, int request_id);
static int cat_ppd(const char *name, int request_id);
static int cat_static(const char *name, int request_id);
+static int compare_matches(const ppd_info_t *p0,
+ const ppd_info_t *p1);
static int compare_names(const ppd_info_t *p0,
const ppd_info_t *p1);
static int compare_ppds(const ppd_info_t *p0,
static int load_drv(const char *filename, const char *name,
cups_file_t *fp, time_t mtime, off_t size);
static int load_ppds(const char *d, const char *p, int descend);
+static regex_t *regex_device_id(const char *device_id);
+static regex_t *regex_string(const char *s);
/*
ppdcCatalog *catalog; // Message catalog in .drv file
- fprintf(stderr, "DEBUG: %d locales defined in \"%s\"...\n",
+ fprintf(stderr, "DEBUG: [cups-driverd] %d locales defined in \"%s\"...\n",
src->po_files->count, filename);
locales = new ppdcArray();
catalog;
catalog = (ppdcCatalog *)src->po_files->next())
{
- fprintf(stderr, "DEBUG: Adding locale \"%s\"...\n",
+ fprintf(stderr, "DEBUG: [cups-driverd] Adding locale \"%s\"...\n",
catalog->locale->value);
locales->add(catalog->locale);
}
}
+/*
+ * 'compare_matches()' - Compare PPD match scores for sorting.
+ */
+
+static int
+compare_matches(const ppd_info_t *p0, /* I - First PPD */
+ const ppd_info_t *p1) /* I - Second PPD */
+{
+ if (p1->matches != p0->matches)
+ return (p1->matches - p0->matches);
+ else
+ return (cupsdCompareNames(p1->record.make_and_model,
+ p0->record.make_and_model));
+}
+
+
/*
* 'compare_names()' - Compare PPD filenames for sorting.
*/
*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 */
+ make_and_model_len, /* Length of ppd-make-and-model */
+ product_len, /* Length of ppd-product */
send_device_id, /* Send ppd-device-id? */
send_make, /* Send ppd-make? */
send_make_and_model, /* Send ppd-make-and-model? */
send_psversion, /* Send ppd-psversion? */
send_type, /* Send ppd-type? */
sent_header; /* Sent the IPP header? */
+ regex_t *device_id_re, /* Regular expression for matching device ID */
+ *make_and_model_re; /* Regular expression for matching make and model */
+ regmatch_t re_matches[6]; /* Regular expression matches */
+ cups_array_t *matches; /* Matching PPDs */
fprintf(stderr,
type_str = cupsGetOption("ppd-type", num_options, options);
if (make_and_model)
- mam_len = strlen(make_and_model);
+ make_and_model_len = strlen(make_and_model);
else
- mam_len = 0;
+ make_and_model_len = 0;
- if (device_id)
- device_id_len = strlen(device_id);
+ if (product)
+ product_len = strlen(product);
else
- device_id_len = 0;
+ product_len = 0;
if (model_number_str)
model_number = atoi(model_number_str);
else
count = limit;
- for (ppd = (ppd_info_t *)cupsArrayFirst(PPDsByMakeModel);
- count > 0 && ppd;
- ppd = (ppd_info_t *)cupsArrayNext(PPDsByMakeModel))
+ if (device_id || language || make || make_and_model || model_number_str ||
+ product)
{
- /*
- * Filter PPDs based on make, model, or device ID...
- */
+ matches = cupsArrayNew((cups_array_func_t)compare_matches, NULL);
- if (ppd->record.type < PPD_TYPE_POSTSCRIPT ||
- ppd->record.type >= PPD_TYPE_DRV)
- continue;
+ if (device_id)
+ device_id_re = regex_device_id(device_id);
+ else
+ device_id_re = NULL;
- if (device_id && strncasecmp(ppd->record.device_id, device_id,
- device_id_len))
- continue; /* TODO: implement smart compare */
+ if (make_and_model)
+ make_and_model_re = regex_string(make_and_model);
+ else
+ make_and_model_re = NULL;
- if (language)
+ for (ppd = (ppd_info_t *)cupsArrayFirst(PPDsByMakeModel);
+ ppd;
+ ppd = (ppd_info_t *)cupsArrayNext(PPDsByMakeModel))
{
- for (i = 0; i < PPD_MAX_LANG; i ++)
- if (!ppd->record.languages[i][0] ||
- !strcasecmp(ppd->record.languages[i], language))
- break;
+ /*
+ * Filter PPDs based on make, model, product, language, model number,
+ * and/or device ID using the "matches" score value. An exact match
+ * for product, make-and-model, or device-id adds 3 to the score.
+ * Partial matches for make-and-model yield 1 or 2 points, and matches
+ * for the make and language add a single point. Results are then sorted
+ * by score, highest score first.
+ */
- if (i >= PPD_MAX_LANG || !ppd->record.languages[i][0])
+ if (ppd->record.type < PPD_TYPE_POSTSCRIPT ||
+ ppd->record.type >= PPD_TYPE_DRV)
continue;
- }
- if (make && strcasecmp(ppd->record.make, make))
- continue;
+ ppd->matches = 0;
- if (make_and_model && strncasecmp(ppd->record.make_and_model,
- make_and_model, mam_len))
- continue;
+ if (device_id_re &&
+ !regexec(device_id_re, ppd->record.device_id,
+ (int)(sizeof(re_matches) / sizeof(re_matches[0])),
+ re_matches, 0))
+ {
+ /*
+ * Add the number of matching values from the device ID - it will be
+ * at least 2 (manufacturer and model), and as much as 3 (command set).
+ */
- if (model_number_str && ppd->record.model_number != model_number)
- continue;
+ for (i = 1; i < (int)(sizeof(re_matches) / sizeof(re_matches[0])); i ++)
+ if (re_matches[i].rm_so >= 0)
+ ppd->matches ++;
+ }
- if (product)
- {
- for (i = 0; i < PPD_MAX_PROD; i ++)
- if (!ppd->record.products[i][0] ||
- !strcasecmp(ppd->record.products[i], product))
- break;
+ if (language)
+ {
+ for (i = 0; i < PPD_MAX_LANG; i ++)
+ if (!ppd->record.languages[i][0] ||
+ !strcasecmp(ppd->record.languages[i], language))
+ {
+ ppd->matches ++;
+ break;
+ }
+ }
- if (i >= PPD_MAX_PROD || !ppd->record.products[i][0])
- continue;
- }
+ if (make && !strcasecmp(ppd->record.make, make))
+ ppd->matches ++;
- if (psversion)
- {
- for (i = 0; i < PPD_MAX_VERS; i ++)
- if (!ppd->record.psversions[i][0] ||
- !strcasecmp(ppd->record.psversions[i], psversion))
- break;
+ if (make_and_model_re &&
+ !regexec(make_and_model_re, ppd->record.make_and_model,
+ (int)(sizeof(re_matches) / sizeof(re_matches[0])),
+ re_matches, 0))
+ {
+ // See how much of the make-and-model string we matched...
+ if (re_matches[0].rm_so == 0)
+ {
+ if (re_matches[0].rm_eo == make_and_model_len)
+ ppd->matches += 3; // Exact match
+ else
+ ppd->matches += 2; // Prefix match
+ }
+ else
+ ppd->matches ++; // Infix match
+ }
- if (i >= PPD_MAX_VERS || !ppd->record.psversions[i][0])
- continue;
+ if (model_number_str && ppd->record.model_number == model_number)
+ ppd->matches ++;
+
+ if (product)
+ {
+ for (i = 0; i < PPD_MAX_PROD; i ++)
+ if (!ppd->record.products[i][0] ||
+ !strcasecmp(ppd->record.products[i], product))
+ {
+ ppd->matches += 3;
+ break;
+ }
+ }
+
+ if (psversion)
+ {
+ for (i = 0; i < PPD_MAX_VERS; i ++)
+ if (!ppd->record.psversions[i][0] ||
+ !strcasecmp(ppd->record.psversions[i], psversion))
+ {
+ ppd->matches ++;
+ break;
+ }
+ }
+
+ if (type_str && ppd->record.type == type)
+ ppd->matches ++;
+
+ if (ppd->matches)
+ {
+ fprintf(stderr, "DEBUG: [cups-driverd] %s matches with score %d!\n",
+ ppd->record.name, ppd->matches);
+ cupsArrayAdd(matches, ppd);
+ }
}
+ }
+ else
+ matches = PPDsByMakeModel;
- if (type_str && ppd->record.type != type)
+ for (ppd = (ppd_info_t *)cupsArrayFirst(matches);
+ count > 0 && ppd;
+ ppd = (ppd_info_t *)cupsArrayNext(matches))
+ {
+ /*
+ * Skip invalid PPDs...
+ */
+
+ if (ppd->record.type < PPD_TYPE_POSTSCRIPT ||
+ ppd->record.type >= PPD_TYPE_DRV)
continue;
/*
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");
+ cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language",
+ "en-US");
}
fprintf(stderr, "DEBUG: [cups-driverd] Sending %s (%s)...\n",
for (this_make = ppd->record.make,
- ppd = (ppd_info_t *)cupsArrayNext(PPDsByMakeModel);
+ ppd = (ppd_info_t *)cupsArrayNext(matches);
ppd;
- ppd = (ppd_info_t *)cupsArrayNext(PPDsByMakeModel))
+ ppd = (ppd_info_t *)cupsArrayNext(matches))
if (strcasecmp(this_make, ppd->record.make))
break;
- cupsArrayPrev(PPDsByMakeModel);
+ cupsArrayPrev(matches);
}
}
else if (!strncmp(line, "*NickName:", 10))
sscanf(line, "%*[^\"]\"%255[^\"]", nick_name);
else if (!strncasecmp(line, "*1284DeviceID:", 14))
+ {
sscanf(line, "%*[^\"]\"%255[^\"]", device_id);
+
+ // Make sure device ID ends with a semicolon...
+ if (device_id[0] && device_id[strlen(device_id) - 1] != ';')
+ strlcat(device_id, ";", sizeof(device_id));
+ }
else if (!strncmp(line, "*Product:", 9))
{
if (sscanf(line, "%*[^\"]\"(%255[^)]", product) == 1)
}
+/*
+ * 'regex_device_id()' - Compile a regular expression based on the 1284 device
+ * ID.
+ */
+
+static regex_t * /* O - Regular expression */
+regex_device_id(const char *device_id) /* I - IEEE-1284 device ID */
+{
+ char res[2048], /* Regular expression string */
+ *ptr; /* Pointer into string */
+ regex_t *re; /* Regular expression */
+ int cmd; /* Command set string? */
+
+
+ fprintf(stderr, "DEBUG: [cups-driverd] regex_device_id(\"%s\")\n", device_id);
+
+ /*
+ * Scan the device ID string and insert class, command set, manufacturer, and
+ * model attributes to match. We assume that the device ID in the PPD and the
+ * device ID reported by the device itself use the same attribute names and
+ * order of attributes.
+ */
+
+ ptr = res;
+
+ while (*device_id && ptr < (res + sizeof(res) - 6))
+ {
+ cmd = !strncasecmp(device_id, "COMMAND SET:", 12) ||
+ !strncasecmp(device_id, "CMD:", 4);
+
+ if (cmd || !strncasecmp(device_id, "MANUFACTURER:", 13) ||
+ !strncasecmp(device_id, "MFG:", 4) ||
+ !strncasecmp(device_id, "MFR:", 4) ||
+ !strncasecmp(device_id, "MODEL:", 6) ||
+ !strncasecmp(device_id, "MDL:", 4))
+ {
+ if (ptr > res)
+ {
+ *ptr++ = '.';
+ *ptr++ = '*';
+ }
+
+ *ptr++ = '(';
+
+ while (*device_id && *device_id != ';' && ptr < (res + sizeof(res) - 4))
+ {
+ if (strchr("[]{}().*\\|", *device_id))
+ *ptr++ = '\\';
+ *ptr++ = *device_id++;
+ }
+
+ if (*device_id == ';' || !*device_id)
+ *ptr++ = ';';
+ *ptr++ = ')';
+ if (cmd)
+ *ptr++ = '?';
+ }
+ else if ((device_id = strchr(device_id, ';')) == NULL)
+ break;
+ else
+ device_id ++;
+ }
+
+ *ptr = '\0';
+
+ fprintf(stderr, "DEBUG: [cups-driverd] regex_device_id: \"%s\"\n", res);
+
+ /*
+ * Compile the regular expression and return...
+ */
+
+ if (res[0] && (re = (regex_t *)calloc(1, sizeof(regex_t))) != NULL)
+ {
+ if (!regcomp(re, res, REG_EXTENDED | REG_ICASE))
+ {
+ fputs("DEBUG: [cups-driverd] regex_device_id: OK\n", stderr);
+ return (re);
+ }
+
+ free(re);
+ }
+
+ return (NULL);
+}
+
+
+/*
+ * 'regex_string()' - Construct a regular expression to compare a simple string.
+ */
+
+static regex_t * /* O - Regular expression */
+regex_string(const char *s) /* I - String to compare */
+{
+ char res[2048], /* Regular expression string */
+ *ptr; /* Pointer into string */
+ regex_t *re; /* Regular expression */
+
+
+ fprintf(stderr, "DEBUG: [cups-driverd] regex_string(\"%s\")\n", s);
+
+ /*
+ * Convert the string to a regular expression, escaping special characters
+ * as needed.
+ */
+
+ ptr = res;
+
+ while (*s && ptr < (res + sizeof(res) - 2))
+ {
+ if (strchr("[]{}().*\\", *s))
+ *ptr++ = '\\';
+
+ *ptr++ = *s++;
+ }
+
+ *ptr = '\0';
+
+ fprintf(stderr, "DEBUG: [cups-driverd] regex_string: \"%s\"\n", res);
+
+ /*
+ * Create a case-insensitive regular expression...
+ */
+
+ if (res[0] && (re = (regex_t *)calloc(1, sizeof(regex_t))) != NULL)
+ {
+ if (!regcomp(re, res, REG_ICASE))
+ {
+ fputs("DEBUG: [cups-driverd] regex_string: OK\n", stderr);
+ return (re);
+ }
+
+ free(re);
+ }
+
+ return (NULL);
+}
+
+
/*
* End of "$Id$".
*/
const char *device_make_and_model,
const char *device_uri, const char *device_location,
void *user_data);
-static int show_devices(http_t *, int);
-static int show_models(http_t *, int);
+static int show_devices(http_t *http, int long_status, int timeout);
+static int show_models(http_t *http, int long_status,
+ const char *device_id, const char *language,
+ const char *make_model, const char *product);
/*
int i; /* Looping var */
http_t *http; /* Connection to server */
int long_status; /* Long listing? */
+ const char *device_id, /* 1284 device ID */
+ *language, /* Language */
+ *make_model, /* Make and model */
+ *product; /* Product */
+ int timeout; /* Device timeout */
_cupsSetLocale(argv);
http = NULL;
long_status = 0;
+ device_id = NULL;
+ language = NULL;
+ make_model = NULL;
+ product = NULL;
+ timeout = CUPS_TIMEOUT_DEFAULT;
for (i = 1; i < argc; i ++)
if (argv[i][0] == '-')
#endif /* HAVE_SSL */
break;
+ case 'h' : /* Connect to host */
+ if (http)
+ {
+ httpClose(http);
+ http = NULL;
+ }
+
+ if (argv[i][2] != '\0')
+ cupsSetServer(argv[i] + 2);
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ _cupsLangPuts(stderr,
+ _("Error: need hostname after \'-h\' option!\n"));
+ return (1);
+ }
+
+ cupsSetServer(argv[i]);
+ }
+ break;
+
case 'l' : /* Show long listing */
long_status = 1;
break;
}
}
- if (show_models(http, long_status))
+ if (show_models(http, long_status, device_id, language, make_model,
+ product))
return (1);
break;
}
}
- if (show_devices(http, long_status))
+ if (show_devices(http, long_status, timeout))
return (1);
break;
- case 'h' : /* Connect to host */
- if (http)
+ case '-' : /* --something */
+ if (!strcmp(argv[i], "--device-id"))
{
- httpClose(http);
- http = NULL;
- }
+ i ++;
- if (argv[i][2] != '\0')
- cupsSetServer(argv[i] + 2);
- else
+ if (i < argc)
+ device_id = argv[i];
+ else
+ {
+ _cupsLangPuts(stderr,
+ _("lpinfo: Expected 1284 device ID string "
+ "after --device-id!\n"));
+ return (1);
+ }
+ }
+ else if (!strncmp(argv[i], "--device-id=", 12) && argv[i][12])
+ {
+ device_id = argv[i] + 12;
+ }
+ else if (!strcmp(argv[i], "--language"))
{
i ++;
-
- if (i >= argc)
+ if (i < argc)
+ language = argv[i];
+ else
{
- _cupsLangPuts(stderr,
- _("Error: need hostname after \'-h\' option!\n"));
+ _cupsLangPuts(stderr,
+ _("lpinfo: Expected language after "
+ "--language!\n"));
return (1);
- }
-
- cupsSetServer(argv[i]);
+ }
+ }
+ else if (!strncmp(argv[i], "--language=", 11) && argv[i][11])
+ {
+ language = argv[i] + 11;
+ }
+ else if (!strcmp(argv[i], "--make-and-model"))
+ {
+ i ++;
+ if (i < argc)
+ make_model= argv[i];
+ else
+ {
+ _cupsLangPuts(stderr,
+ _("lpinfo: Expected make and model after "
+ "--make-and-model!\n"));
+ return (1);
+ }
+ }
+ else if (!strncmp(argv[i], "--make-and-model=", 17) && argv[i][17])
+ {
+ make_model = argv[i] + 17;
+ }
+ else if (!strcmp(argv[i], "--product"))
+ {
+ i ++;
+ if (i < argc)
+ product = argv[i];
+ else
+ {
+ _cupsLangPuts(stderr,
+ _("lpinfo: Expected product string after "
+ "--product!\n"));
+ return (1);
+ }
+ }
+ else if (!strncmp(argv[i], "--product=", 10) && argv[i][10])
+ {
+ product = argv[i] + 10;
+ }
+ else if (!strcmp(argv[i], "--timeout"))
+ {
+ i ++;
+ if (i < argc)
+ timeout = atoi(argv[i]);
+ else
+ {
+ _cupsLangPuts(stderr,
+ _("lpinfo: Expected timeout after --timeout!\n"));
+ return (1);
+ }
+ }
+ else if (!strncmp(argv[i], "--timeout=", 10) && argv[i][10])
+ {
+ timeout = atoi(argv[i] + 10);
+ }
+ else
+ {
+ _cupsLangPrintf(stderr, _("lpinfo: Unknown option \'%s\'!\n"),
+ argv[i]);
+ return (1);
}
break;
static int /* O - 0 on success, 1 on failure */
show_devices(http_t *http, /* I - HTTP connection to server */
- int long_status) /* I - Long status report? */
+ int long_status, /* I - Long status report? */
+ int timeout) /* I - Timeout */
{
- if (cupsGetDevices(http, CUPS_TIMEOUT_DEFAULT, CUPS_EXCLUDE_NONE, device_cb,
+ if (cupsGetDevices(http, timeout, CUPS_EXCLUDE_NONE, device_cb,
&long_status) != IPP_OK)
{
_cupsLangPrintf(stderr, "lpinfo: %s\n", cupsLastErrorString());
*/
static int /* O - 0 on success, 1 on failure */
-show_models(http_t *http, /* I - HTTP connection to server */
- int long_status) /* I - Long status report? */
+show_models(http_t *http, /* I - HTTP connection to server */
+ int long_status, /* I - Long status report? */
+ const char *device_id, /* I - 1284 device ID */
+ const char *language, /* I - Language */
+ const char *make_model, /* I - Make and model */
+ const char *product) /* I - Product */
{
ipp_t *request, /* IPP Request */
*response; /* IPP Response */
ipp_attribute_t *attr; /* Current attribute */
const char *ppd_device_id, /* Pointer to ppd-device-id */
*ppd_language, /* Pointer to ppd-natural-language */
- *ppd_make, /* Pointer to ppd-make-and-model */
+ *ppd_make_model, /* Pointer to ppd-make-and-model */
*ppd_name; /* Pointer to ppd-name */
return (1);
/*
- * Build a CUPS_GET_PPDS request, which requires the following
- * attributes:
- *
- * attributes-charset
- * attributes-natural-language
+ * Build a CUPS_GET_PPDS request...
*/
request = ippNewRequest(CUPS_GET_PPDS);
+ if (device_id)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-device-id",
+ NULL, device_id);
+ if (language)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "ppd-language",
+ NULL, language);
+ if (make_model)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-make-and-model",
+ NULL, make_model);
+ if (product)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-product",
+ NULL, product);
+
/*
* Do the request and get back a response...
*/
* Pull the needed attributes from this PPD...
*/
- ppd_device_id = "NONE";
- ppd_language = NULL;
- ppd_make = NULL;
- ppd_name = NULL;
+ ppd_device_id = "NONE";
+ ppd_language = NULL;
+ ppd_make_model = NULL;
+ ppd_name = NULL;
while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
{
ppd_language = attr->values[0].string.text;
else if (!strcmp(attr->name, "ppd-make-and-model") &&
attr->value_tag == IPP_TAG_TEXT)
- ppd_make = attr->values[0].string.text;
+ ppd_make_model = attr->values[0].string.text;
else if (!strcmp(attr->name, "ppd-name") &&
attr->value_tag == IPP_TAG_NAME)
ppd_name = attr->values[0].string.text;
* See if we have everything needed...
*/
- if (ppd_language == NULL || ppd_make == NULL || ppd_name == NULL)
+ if (ppd_language == NULL || ppd_make_model == NULL || ppd_name == NULL)
{
if (attr == NULL)
break;
" natural_language = %s\n"
" make-and-model = %s\n"
" device-id = %s\n"),
- ppd_name, ppd_language, ppd_make, ppd_device_id);
+ ppd_name, ppd_language, ppd_make_model, ppd_device_id);
}
else
- _cupsLangPrintf(stdout, "%s %s\n", ppd_name, ppd_make);
+ _cupsLangPrintf(stdout, "%s %s\n", ppd_name, ppd_make_model);
if (attr == NULL)
break;