#include "cups.h"
#include <stdlib.h>
#include <ctype.h>
#include "string.h"
#include "debug.h"
int
cupsAddOption(const char *name,
const char *value,
int num_options,
cups_option_t **options)
{
int i;
cups_option_t *temp;
if (name == NULL || !name[0] || value == NULL ||
options == NULL || num_options < 0)
return (num_options);
for (i = 0, temp = *options; i < num_options; i ++, temp ++)
if (strcasecmp(temp->name, name) == 0)
break;
if (i >= num_options)
{
if (num_options == 0)
temp = (cups_option_t *)malloc(sizeof(cups_option_t));
else
temp = (cups_option_t *)realloc(*options, sizeof(cups_option_t) *
(num_options + 1));
if (temp == NULL)
return (0);
*options = temp;
temp += num_options;
temp->name = strdup(name);
num_options ++;
}
else
{
free(temp->value);
}
temp->value = strdup(value);
return (num_options);
}
void
cupsFreeOptions(int num_options,
cups_option_t *options)
{
int i;
if (num_options <= 0 || options == NULL)
return;
for (i = 0; i < num_options; i ++)
{
free(options[i].name);
free(options[i].value);
}
free(options);
}
const char *
cupsGetOption(const char *name,
int num_options,
cups_option_t *options)
{
int i;
if (name == NULL || num_options <= 0 || options == NULL)
return (NULL);
for (i = 0; i < num_options; i ++)
if (strcasecmp(options[i].name, name) == 0)
return (options[i].value);
return (NULL);
}
int
cupsParseOptions(const char *arg,
int num_options,
cups_option_t **options)
{
char *copyarg,
*ptr,
*name,
*value;
if (arg == NULL || options == NULL || num_options < 0)
return (0);
copyarg = strdup(arg);
ptr = copyarg;
while (isspace(*ptr & 255))
ptr ++;
while (*ptr != '\0')
{
name = ptr;
while (!isspace(*ptr & 255) && *ptr != '=' && *ptr != '\0')
ptr ++;
if (ptr == name)
break;
while (isspace(*ptr & 255))
*ptr++ = '\0';
if (*ptr != '=')
{
if (strncasecmp(name, "no", 2) == 0)
num_options = cupsAddOption(name + 2, "false", num_options,
options);
else
num_options = cupsAddOption(name, "true", num_options, options);
continue;
}
*ptr++ = '\0';
if (*ptr == '\'')
{
ptr ++;
value = ptr;
while (*ptr != '\'' && *ptr != '\0')
{
if (*ptr == '\\')
cups_strcpy(ptr, ptr + 1);
ptr ++;
}
if (*ptr != '\0')
*ptr++ = '\0';
}
else if (*ptr == '\"')
{
ptr ++;
value = ptr;
while (*ptr != '\"' && *ptr != '\0')
{
if (*ptr == '\\')
cups_strcpy(ptr, ptr + 1);
ptr ++;
}
if (*ptr != '\0')
*ptr++ = '\0';
}
else if (*ptr == '{')
{
int depth;
value = ptr;
for (depth = 1; *ptr; ptr ++)
if (*ptr == '{')
depth ++;
else if (*ptr == '}')
{
depth --;
if (!depth)
{
ptr ++;
if (*ptr != ',')
break;
}
}
else if (*ptr == '\\')
cups_strcpy(ptr, ptr + 1);
if (*ptr != '\0')
*ptr++ = '\0';
}
else
{
value = ptr;
while (!isspace(*ptr & 255) && *ptr != '\0')
{
if (*ptr == '\\')
cups_strcpy(ptr, ptr + 1);
ptr ++;
}
}
while (isspace(*ptr & 255))
*ptr++ = '\0';
num_options = cupsAddOption(name, value, num_options, options);
}
free(copyarg);
return (num_options);
}
int
cupsMarkOptions(ppd_file_t *ppd,
int num_options,
cups_option_t *options)
{
int i;
int conflict;
char *val,
*ptr,
s[255];
cups_option_t *optptr;
if (ppd == NULL || num_options <= 0 || options == NULL)
return (0);
conflict = 0;
for (i = num_options, optptr = options; i > 0; i --, optptr ++)
if (strcasecmp(optptr->name, "media") == 0)
{
for (val = optptr->value; *val;)
{
const char *pgSizeOptionStr;
for (ptr = s; *val && *val != ',' && (ptr - s) < (sizeof(s) - 1);)
*ptr++ = *val++;
*ptr++ = '\0';
if (*val == ',')
val ++;
if ( (pgSizeOptionStr = cupsGetOption("PageSize", num_options, options)) == NULL || pgSizeOptionStr[0] == '\0')
if (ppdMarkOption(ppd, "PageSize", s))
conflict = 1;
if (cupsGetOption("InputSlot", num_options, options) == NULL)
if (ppdMarkOption(ppd, "InputSlot", s))
conflict = 1;
if (cupsGetOption("MediaType", num_options, options) == NULL)
if (ppdMarkOption(ppd, "MediaType", s))
conflict = 1;
if (cupsGetOption("EFMediaQualityMode", num_options, options) == NULL)
if (ppdMarkOption(ppd, "EFMediaQualityMode", s))
conflict = 1;
if (strcasecmp(s, "manual") == 0 &&
cupsGetOption("ManualFeed", num_options, options) == NULL)
if (ppdMarkOption(ppd, "ManualFeed", "True"))
conflict = 1;
}
}
else if (strcasecmp(optptr->name, "sides") == 0)
{
if (cupsGetOption("Duplex", num_options, options) != NULL ||
cupsGetOption("JCLDuplex", num_options, options) != NULL ||
cupsGetOption("EFDuplex", num_options, options) != NULL ||
cupsGetOption("KD03Duplex", num_options, options) != NULL)
{
continue;
}
else if (strcasecmp(optptr->value, "one-sided") == 0)
{
if (ppdMarkOption(ppd, "Duplex", "None"))
conflict = 1;
if (ppdMarkOption(ppd, "JCLDuplex", "None"))
conflict = 1;
if (ppdMarkOption(ppd, "EFDuplex", "None"))
conflict = 1;
if (ppdMarkOption(ppd, "KD03Duplex", "None"))
conflict = 1;
}
else if (strcasecmp(optptr->value, "two-sided-long-edge") == 0)
{
if (ppdMarkOption(ppd, "Duplex", "DuplexNoTumble"))
conflict = 1;
if (ppdMarkOption(ppd, "JCLDuplex", "DuplexNoTumble"))
conflict = 1;
if (ppdMarkOption(ppd, "EFDuplex", "DuplexNoTumble"))
conflict = 1;
if (ppdMarkOption(ppd, "KD03Duplex", "DuplexNoTumble"))
conflict = 1;
}
else if (strcasecmp(optptr->value, "two-sided-short-edge") == 0)
{
if (ppdMarkOption(ppd, "Duplex", "DuplexTumble"))
conflict = 1;
if (ppdMarkOption(ppd, "JCLDuplex", "DuplexTumble"))
conflict = 1;
if (ppdMarkOption(ppd, "EFDuplex", "DuplexTumble"))
conflict = 1;
if (ppdMarkOption(ppd, "KD03Duplex", "DuplexTumble"))
conflict = 1;
}
}
else if (strcasecmp(optptr->name, "resolution") == 0 ||
strcasecmp(optptr->name, "printer-resolution") == 0)
{
if (ppdMarkOption(ppd, "Resolution", optptr->value))
conflict = 1;
if (ppdMarkOption(ppd, "SetResolution", optptr->value))
conflict = 1;
if (ppdMarkOption(ppd, "JCLResolution", optptr->value))
conflict = 1;
if (ppdMarkOption(ppd, "CNRes_PGP", optptr->value))
conflict = 1;
}
else if (strcasecmp(optptr->name, "output-bin") == 0)
{
if (cupsGetOption("OutputBin", num_options, options) == NULL)
if (ppdMarkOption(ppd, "OutputBin", optptr->value))
conflict = 1;
}
else if (ppdMarkOption(ppd, optptr->name, optptr->value))
conflict = 1;
return (conflict);
}